]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-icmp6.c
Merge pull request #703 from nmap/update-gitignore
[tcpdump] / print-icmp6.c
index 9bbd5c81f5d38a812db6b96f719eed06edf96d95..042e50726b988953abc719e26c28bd26584945c7 100644 (file)
@@ -139,7 +139,7 @@ struct icmp6_hdr {
 #define ICMP6_MAXTYPE                  201
 
 #define ICMP6_DST_UNREACH_NOROUTE      0       /* no route to destination */
-#define ICMP6_DST_UNREACH_ADMIN                1       /* administratively prohibited */
+#define ICMP6_DST_UNREACH_ADMIN                1       /* administratively prohibited */
 #define ICMP6_DST_UNREACH_NOTNEIGHBOR  2       /* not a neighbor(obsolete) */
 #define ICMP6_DST_UNREACH_BEYONDSCOPE  2       /* beyond scope of source address */
 #define ICMP6_DST_UNREACH_ADDR         3       /* address unreachable */
@@ -148,7 +148,7 @@ struct icmp6_hdr {
 #define ICMP6_TIME_EXCEED_TRANSIT      0       /* ttl==0 in transit */
 #define ICMP6_TIME_EXCEED_REASSEMBLY   1       /* ttl==0 in reass */
 
-#define ICMP6_PARAMPROB_HEADER                 0       /* erroneous header field */
+#define ICMP6_PARAMPROB_HEADER                 0       /* erroneous header field */
 #define ICMP6_PARAMPROB_NEXTHEADER     1       /* unrecognized next header */
 #define ICMP6_PARAMPROB_OPTION         2       /* unrecognized option */
 
@@ -320,7 +320,7 @@ struct nd_opt_rdnss {               /* RDNSS RFC 6106 5.1 */
        nd_uint8_t      nd_opt_rdnss_len;
        nd_uint16_t     nd_opt_rdnss_reserved;
        nd_uint32_t     nd_opt_rdnss_lifetime;
-       nd_ipv6         nd_opt_rdnss_addr[1];   /* variable-length */
+       nd_ipv6         nd_opt_rdnss_addr[1];   /* variable-length */
 };
 
 struct nd_opt_dnssl {          /* DNSSL RFC 6106 5.2 */
@@ -479,7 +479,7 @@ struct rr_result {          /* router renumbering result message */
 static const char *get_rtpref(u_int);
 static const char *get_lifetime(uint32_t);
 static void print_lladdr(netdissect_options *ndo, const u_char *, size_t);
-static void icmp6_opt_print(netdissect_options *ndo, const u_char *, int);
+static int icmp6_opt_print(netdissect_options *ndo, const u_char *, int);
 static void mld6_print(netdissect_options *ndo, const u_char *);
 static void mldv2_report_print(netdissect_options *ndo, const u_char *, u_int);
 static void mldv2_query_print(netdissect_options *ndo, const u_char *, u_int);
@@ -776,7 +776,7 @@ print_lladdr(netdissect_options *ndo, const uint8_t *p, size_t l)
        }
 }
 
-static int icmp6_cksum(netdissect_options *ndo, const struct ip6_hdr *ip6,
+static uint16_t icmp6_cksum(netdissect_options *ndo, const struct ip6_hdr *ip6,
        const struct icmp6_hdr *icp, u_int len)
 {
        return nextproto6_cksum(ndo, ip6, (const uint8_t *)(const void *)icp, len, len,
@@ -840,7 +840,7 @@ rpl_printopts(netdissect_options *ndo, const uint8_t *opts, u_int length)
         }
         return;
 trunc:
-       ND_PRINT(" [|truncated]");
+       nd_print_trunc(ndo);
        return;
 }
 
@@ -869,7 +869,7 @@ rpl_dio_print(netdissect_options *ndo,
         }
        return;
 trunc:
-       ND_PRINT(" [|truncated]");
+       nd_print_trunc(ndo);
        return;
 }
 
@@ -883,7 +883,7 @@ rpl_dao_print(netdissect_options *ndo,
 
         ND_TCHECK_SIZE(dao);
         if (length < ND_RPL_DAO_MIN_LEN)
-               goto tooshort;
+               goto tooshort;
 
         bp += ND_RPL_DAO_MIN_LEN;
         length -= ND_RPL_DAO_MIN_LEN;
@@ -911,7 +911,7 @@ rpl_dao_print(netdissect_options *ndo,
        return;
 
 trunc:
-       ND_PRINT(" [|truncated]");
+       nd_print_trunc(ndo);
        return;
 
 tooshort:
@@ -928,7 +928,7 @@ rpl_daoack_print(netdissect_options *ndo,
 
         ND_TCHECK_LEN(daoack, ND_RPL_DAOACK_MIN_LEN);
         if (length < ND_RPL_DAOACK_MIN_LEN)
-               goto tooshort;
+               goto tooshort;
 
         bp += ND_RPL_DAOACK_MIN_LEN;
         length -= ND_RPL_DAOACK_MIN_LEN;
@@ -954,7 +954,7 @@ rpl_daoack_print(netdissect_options *ndo,
        return;
 
 trunc:
-       ND_PRINT(" [|dao-truncated]");
+       nd_print_trunc(ndo);
        return;
 
 tooshort:
@@ -1013,7 +1013,7 @@ rpl_print(netdissect_options *ndo,
 
 #if 0
 trunc:
-       ND_PRINT(" [|truncated]");
+       nd_print_trunc(ndo);
        return;
 #endif
 
@@ -1033,11 +1033,17 @@ icmp6_print(netdissect_options *ndo,
        const u_char *ep;
        u_int prot;
 
+       ndo->ndo_protocol = "icmp6";
        dp = (const struct icmp6_hdr *)bp;
        ip = (const struct ip6_hdr *)bp2;
        oip = (const struct ip6_hdr *)(dp + 1);
        /* 'ep' points to the end of available data. */
        ep = ndo->ndo_snapend;
+       if (length == 0) {
+               ND_PRINT("ICMP6, length 0");
+               nd_print_invalid(ndo);
+               return;
+       }
 
        if (ndo->ndo_vflag && !fragmented) {
                uint16_t sum, udp_sum;
@@ -1159,8 +1165,9 @@ icmp6_print(netdissect_options *ndo,
                break;
        case ICMP6_ECHO_REQUEST:
        case ICMP6_ECHO_REPLY:
+                /* The check below covers both icmp6_id and icmp6_seq. */
                 ND_TCHECK_2(dp->icmp6_seq);
-                ND_PRINT(", seq %u", EXTRACT_BE_U_2(dp->icmp6_seq));
+                ND_PRINT(", id %u, seq %u", EXTRACT_BE_U_2(dp->icmp6_id), EXTRACT_BE_U_2(dp->icmp6_seq));
                break;
        case ICMP6_MEMBERSHIP_QUERY:
                if (length == MLD_MINLEN) {
@@ -1181,8 +1188,9 @@ icmp6_print(netdissect_options *ndo,
        case ND_ROUTER_SOLICIT:
 #define RTSOLLEN 8
                if (ndo->ndo_vflag) {
-                       icmp6_opt_print(ndo, (const u_char *)dp + RTSOLLEN,
-                                       length - RTSOLLEN);
+                       if (icmp6_opt_print(ndo, (const u_char *)dp + RTSOLLEN,
+                                           length - RTSOLLEN) == -1)
+                               goto trunc;
                }
                break;
        case ND_ROUTER_ADVERT:
@@ -1193,7 +1201,7 @@ icmp6_print(netdissect_options *ndo,
                        p = (const struct nd_router_advert *)dp;
                        ND_TCHECK_4(p->nd_ra_retransmit);
                        ND_PRINT("\n\thop limit %u, Flags [%s]"
-                                  ", pref %s, router lifetime %us, reachable time %us, retrans time %us",
+                                  ", pref %s, router lifetime %us, reachable time %ums, retrans timer %ums",
                                   EXTRACT_U_1(p->nd_ra_curhoplimit),
                                   bittok2str(icmp6_opt_ra_flag_values,"none",EXTRACT_U_1(p->nd_ra_flags_reserved)),
                                   get_rtpref(EXTRACT_U_1(p->nd_ra_flags_reserved)),
@@ -1201,8 +1209,9 @@ icmp6_print(netdissect_options *ndo,
                                   EXTRACT_BE_U_4(p->nd_ra_reachable),
                                   EXTRACT_BE_U_4(p->nd_ra_retransmit));
 
-                       icmp6_opt_print(ndo, (const u_char *)dp + RTADVLEN,
-                                       length - RTADVLEN);
+                       if (icmp6_opt_print(ndo, (const u_char *)dp + RTADVLEN,
+                                           length - RTADVLEN) == -1)
+                               goto trunc;
                }
                break;
        case ND_NEIGHBOR_SOLICIT:
@@ -1213,8 +1222,9 @@ icmp6_print(netdissect_options *ndo,
                ND_PRINT(", who has %s", ip6addr_string(ndo, p->nd_ns_target));
                if (ndo->ndo_vflag) {
 #define NDSOLLEN 24
-                       icmp6_opt_print(ndo, (const u_char *)dp + NDSOLLEN,
-                                       length - NDSOLLEN);
+                       if (icmp6_opt_print(ndo, (const u_char *)dp + NDSOLLEN,
+                                           length - NDSOLLEN) == -1)
+                               goto trunc;
                }
            }
                break;
@@ -1232,8 +1242,9 @@ icmp6_print(netdissect_options *ndo,
                                              "none",
                                              EXTRACT_BE_U_4(p->nd_na_flags_reserved)));
 #define NDADVLEN 24
-                       icmp6_opt_print(ndo, (const u_char *)dp + NDADVLEN,
-                                       length - NDADVLEN);
+                       if (icmp6_opt_print(ndo, (const u_char *)dp + NDADVLEN,
+                                           length - NDADVLEN) == -1)
+                               goto trunc;
 #undef NDADVLEN
                }
            }
@@ -1249,8 +1260,9 @@ icmp6_print(netdissect_options *ndo,
                ND_PRINT(" to %s", ip6addr_string(ndo, p->nd_rd_target));
 #define REDIRECTLEN 40
                if (ndo->ndo_vflag) {
-                       icmp6_opt_print(ndo, (const u_char *)dp + REDIRECTLEN,
-                                       length - REDIRECTLEN);
+                       if (icmp6_opt_print(ndo, (const u_char *)dp + REDIRECTLEN,
+                                           length - REDIRECTLEN) == -1)
+                               goto trunc;
 #undef REDIRECTLEN
                }
            }
@@ -1304,8 +1316,9 @@ icmp6_print(netdissect_options *ndo,
                        if (flags & 0x4000)
                                ND_PRINT("O");
 #define MPADVLEN 8
-                       icmp6_opt_print(ndo, (const u_char *)dp + MPADVLEN,
-                                       length - MPADVLEN);
+                       if (icmp6_opt_print(ndo, (const u_char *)dp + MPADVLEN,
+                                           length - MPADVLEN) == -1)
+                               goto trunc;
                }
                break;
         case ND_RPL_MESSAGE:
@@ -1322,7 +1335,7 @@ icmp6_print(netdissect_options *ndo,
                 ND_PRINT(", length %u", length);
        return;
 trunc:
-       ND_PRINT("[|icmp6]");
+       nd_print_trunc(ndo);
 }
 
 static const struct udphdr *
@@ -1399,7 +1412,7 @@ get_upperlayer(netdissect_options *ndo, const u_char *bp, u_int *prot)
        return(NULL);           /* should be notreached, though */
 }
 
-static void
+static int
 icmp6_opt_print(netdissect_options *ndo, const u_char *bp, int resid)
 {
        const struct nd_opt_hdr *op;
@@ -1416,8 +1429,6 @@ icmp6_opt_print(netdissect_options *ndo, const u_char *bp, int resid)
        size_t l;
        u_int i;
 
-#define ECHECK(var) if ((const u_char *)&(var) > ep - sizeof(var)) return
-
        cp = bp;
        /* 'ep' points to the end of available data. */
        ep = ndo->ndo_snapend;
@@ -1425,9 +1436,9 @@ icmp6_opt_print(netdissect_options *ndo, const u_char *bp, int resid)
        while (cp < ep) {
                op = (const struct nd_opt_hdr *)cp;
 
-               ECHECK(op->nd_opt_len);
+               ND_TCHECK_1(op->nd_opt_len);
                if (resid <= 0)
-                       return;
+                       return 0;
                opt_type = EXTRACT_U_1(op->nd_opt_type);
                opt_len = EXTRACT_U_1(op->nd_opt_len);
                if (opt_len == 0)
@@ -1491,7 +1502,7 @@ icmp6_opt_print(netdissect_options *ndo, const u_char *bp, int resid)
                        while (domp < cp + (opt_len << 3) && EXTRACT_U_1(domp) != '\0')
                        {
                                ND_PRINT(" ");
-                               if ((domp = ns_nprint (ndo, domp, bp)) == NULL)
+                               if ((domp = ns_nprint(ndo, domp, bp)) == NULL)
                                        goto trunc;
                        }
                        break;
@@ -1534,7 +1545,7 @@ icmp6_opt_print(netdissect_options *ndo, const u_char *bp, int resid)
                default:
                         if (ndo->ndo_vflag <= 1) {
                                 print_unknown_data(ndo,cp+2,"\n\t  ", (opt_len << 3) - 2); /* skip option header */
-                            return;
+                            return 0;
                         }
                         break;
                }
@@ -1545,12 +1556,10 @@ icmp6_opt_print(netdissect_options *ndo, const u_char *bp, int resid)
                cp += opt_len << 3;
                resid -= opt_len << 3;
        }
-       return;
+       return 0;
 
- trunc:
-       ND_PRINT("[ndp opt]");
-       return;
-#undef ECHECK
+trunc:
+       return -1;
 }
 
 static void
@@ -1623,7 +1632,7 @@ mldv2_report_print(netdissect_options *ndo, const u_char *bp, u_int len)
     }
     return;
 trunc:
-    ND_PRINT("[|icmp6]");
+    nd_print_trunc(ndo);
     return;
 }
 
@@ -1690,7 +1699,7 @@ mldv2_query_print(netdissect_options *ndo, const u_char *bp, u_int len)
     ND_PRINT("]");
     return;
 trunc:
-    ND_PRINT("[|icmp6]");
+    nd_print_trunc(ndo);
     return;
 }
 
@@ -1710,7 +1719,7 @@ dnsname_print(netdissect_options *ndo, const u_char *cp, const u_char *ep)
                                break;
                        }
                        while (i-- && cp < ep) {
-                               safeputchar(ndo, EXTRACT_U_1(cp));
+                               fn_print_char(ndo, EXTRACT_U_1(cp));
                                cp++;
                        }
                        if (cp + 1 < ep && EXTRACT_U_1(cp))
@@ -1831,7 +1840,7 @@ icmp6_nodeinfo_print(netdissect_options *ndo, u_int icmp6len, const u_char *bp,
                                cp++;
                                ND_PRINT(", \"");
                                while (cp < ep) {
-                                       safeputchar(ndo, EXTRACT_U_1(cp));
+                                       fn_print_char(ndo, EXTRACT_U_1(cp));
                                        cp++;
                                }
                                ND_PRINT("\"");
@@ -1859,10 +1868,8 @@ icmp6_nodeinfo_print(netdissect_options *ndo, u_int icmp6len, const u_char *bp,
                break;
 
        case ICMP6_NI_REPLY:
-               if (icmp6len > siz) {
-                       ND_PRINT("[|icmp6: node information reply]");
-                       break;
-               }
+               if (icmp6len > siz)
+                       goto trunc;
 
                needcomma = 0;
 
@@ -1929,7 +1936,7 @@ icmp6_nodeinfo_print(netdissect_options *ndo, u_int icmp6len, const u_char *bp,
                                cp++;
                                ND_PRINT(", \"");
                                while (cp < ep) {
-                                       safeputchar(ndo, EXTRACT_U_1(cp));
+                                       fn_print_char(ndo, EXTRACT_U_1(cp));
                                        cp++;
                                }
                                ND_PRINT("\"");
@@ -1977,7 +1984,7 @@ icmp6_nodeinfo_print(netdissect_options *ndo, u_int icmp6len, const u_char *bp,
        return;
 
 trunc:
-       ND_PRINT("[|icmp6]");
+       nd_print_trunc(ndo);
 }
 
 static void
@@ -2113,12 +2120,5 @@ icmp6_rrenum_print(netdissect_options *ndo, const u_char *bp, const u_char *ep)
        return;
 
 trunc:
-       ND_PRINT("[|icmp6]");
+       nd_print_trunc(ndo);
 }
-
-/*
- * Local Variables:
- * c-style: whitesmith
- * c-basic-offset: 8
- * End:
- */