]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-icmp6.c
Fix the pointer tests in the non-ndoified TTEST2() macro as well.
[tcpdump] / print-icmp6.c
index 2ec05d43115e6a5c6d325587a080675c0838bb6e..24765381b654c5a611fb1f69834f102547e8ca41 100644 (file)
@@ -21,7 +21,7 @@
 
 #ifndef lint
 static const char rcsid[] _U_ =
-    "@(#) $Header: /tcpdump/master/tcpdump/print-icmp6.c,v 1.85 2005-09-05 09:29:01 guy Exp $";
+    "@(#) $Header: /tcpdump/master/tcpdump/print-icmp6.c,v 1.86 2008-02-05 19:36:13 guy Exp $";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -62,6 +62,9 @@ static void icmp6_rrenum_print(const u_char *, const u_char *);
 #define abs(a) ((0 < (a)) ? (a) : -(a))
 #endif
 
+/* inline the various RPL definitions */
+#define ND_RPL_MESSAGE 0x9B
+
 static struct tok icmp6_type_values[] = {
     { ICMP6_DST_UNREACH, "destination unreachable"},
     { ICMP6_PACKET_TOO_BIG, "packet too big"},
@@ -91,6 +94,7 @@ static struct tok icmp6_type_values[] = {
     { ICMP6_NI_REPLY, "node information reply"},
     { MLD6_MTRACE, "mtrace message"},
     { MLD6_MTRACE_RESP, "mtrace response"},
+    { ND_RPL_MESSAGE,   "RPL"},
     { 0,       NULL }
 };
 
@@ -131,6 +135,7 @@ static struct tok icmp6_opt_values[] = {
    { ND_OPT_PREFIX_INFORMATION, "prefix info"},
    { ND_OPT_REDIRECTED_HEADER, "redirected header"},
    { ND_OPT_MTU, "mtu"},
+   { ND_OPT_RDNSS, "rdnss"},
    { ND_OPT_ADVINTERVAL, "advertisement interval"},
    { ND_OPT_HOMEAGENT_INFO, "homeagent information"},
    { ND_OPT_ROUTE_INFO, "route info"},
@@ -232,8 +237,87 @@ static int icmp6_cksum(const struct ip6_hdr *ip6, const struct icmp6_hdr *icp,
        return (sum);
 }
 
+enum ND_RPL_CODE {
+        ND_RPL_DAG_IS=0x01,
+        ND_RPL_DAG_IO=0x02,
+        ND_RPL_DAO   =0x04
+};
+
+enum ND_RPL_DIO_FLAGS {
+        ND_RPL_DIO_GROUNDED = 0x80,
+        ND_RPL_DIO_DATRIG   = 0x40,
+        ND_RPL_DIO_DASUPPORT= 0x20,
+        ND_RPL_DIO_RES4     = 0x10,
+        ND_RPL_DIO_RES3     = 0x08,
+        ND_RPL_DIO_PRF_MASK = 0x07,  /* 3-bit preference */
+};
+
+struct nd_rpl_dio {
+        u_int8_t rpl_flags;
+        u_int8_t rpl_seq;
+        u_int8_t rpl_instanceid;
+        u_int8_t rpl_dagrank;
+        u_int8_t rpl_dagid[16];
+};
+
+static void
+rpl_print(netdissect_options *ndo,
+          const struct icmp6_hdr *hdr,
+          const u_char *bp, u_int length _U_)
+{
+        struct nd_rpl_dio *dio = (struct nd_rpl_dio *)bp;
+
+        ND_TCHECK(dio->rpl_dagid);
+
+        switch(hdr->icmp6_code) {
+        case ND_RPL_DAG_IS:
+                ND_PRINT((ndo, ", DAG Information Solicitation"));
+                if(ndo->ndo_vflag) {
+                }
+                break;
+        case ND_RPL_DAG_IO:
+                ND_PRINT((ndo, ", DAG Information Object"));
+                if(ndo->ndo_vflag) {
+                        char dagid[65];
+                        char *d = dagid;
+                        int  i;
+                        for(i=0;i<16;i++) {
+                                if(isprint(dio->rpl_dagid[i])) {
+                                        *d++ = dio->rpl_dagid[i];
+                                } else {
+                                        int cnt=snprintf(d,4,"0x%02x",
+                                                         dio->rpl_dagid[i]);
+                                        d += cnt;
+                                }
+                        }
+                        *d++ = '\0';
+                        ND_PRINT((ndo, " [seq:%u,instance:%u,rank:%u,dagid:%s]",
+                                  dio->rpl_seq,
+                                  dio->rpl_instanceid,
+                                  dio->rpl_dagrank,
+                                  dagid));
+                }
+                break;
+        case ND_RPL_DAO:
+                ND_PRINT((ndo, ", Destination Advertisement Object"));
+                if(ndo->ndo_vflag) {
+                }
+                break;
+        default:
+                ND_PRINT((ndo, ", RPL message, unknown code %u",hdr->icmp6_code));
+                break;
+        }
+       return;
+trunc:
+       ND_PRINT((ndo," [|truncated]"));
+       return;
+        
+}
+
+
 void
-icmp6_print(const u_char *bp, u_int length, const u_char *bp2, int fragmented)
+icmp6_print(netdissect_options *ndo,
+            const u_char *bp, u_int length, const u_char *bp2, int fragmented)
 {
        const struct icmp6_hdr *dp;
        const struct ip6_hdr *ip;
@@ -266,14 +350,13 @@ icmp6_print(const u_char *bp, u_int length, const u_char *bp2, int fragmented)
         printf("ICMP6, %s", tok2str(icmp6_type_values,"unknown icmp6 type (%u)",dp->icmp6_type));
 
         /* display cosmetics: print the packet length for printer that use the vflag now */
-        if (vflag && (dp->icmp6_type ==
-                      ND_ROUTER_SOLICIT ||
-                      ND_ROUTER_ADVERT ||
-                      ND_NEIGHBOR_ADVERT ||
-                      ND_NEIGHBOR_SOLICIT ||
-                      ND_REDIRECT ||
-                      ICMP6_HADISCOV_REPLY ||
-                      ICMP6_MOBILEPREFIX_ADVERT ))
+        if (vflag && (dp->icmp6_type == ND_ROUTER_SOLICIT ||
+                      dp->icmp6_type == ND_ROUTER_ADVERT ||
+                      dp->icmp6_type == ND_NEIGHBOR_ADVERT ||
+                      dp->icmp6_type == ND_NEIGHBOR_SOLICIT ||
+                      dp->icmp6_type == ND_REDIRECT ||
+                      dp->icmp6_type == ICMP6_HADISCOV_REPLY ||
+                      dp->icmp6_type == ICMP6_MOBILEPREFIX_ADVERT ))
             printf(", length %u", length);
                       
        switch (dp->icmp6_type) {
@@ -505,6 +588,9 @@ icmp6_print(const u_char *bp, u_int length, const u_char *bp2, int fragmented)
                                        length - MPADVLEN);
                }
                break;
+        case ND_RPL_MESSAGE:
+                rpl_print(ndo, dp, &dp->icmp6_data8[0], length);
+                break;
        default:
                 printf(", length %u", length);
                 if (vflag <= 1)
@@ -600,12 +686,14 @@ icmp6_opt_print(const u_char *bp, int resid)
        const struct nd_opt_prefix_info *opp;
        const struct icmp6_opts_redirect *opr;
        const struct nd_opt_mtu *opm;
+       const struct nd_opt_rdnss *oprd;
        const struct nd_opt_advinterval *opa;
        const struct nd_opt_homeagent_info *oph;
        const struct nd_opt_route_info *opri;
        const u_char *cp, *ep;
        struct in6_addr in6, *in6p;
        size_t l;
+       u_int i;
 
 #define ECHECK(var) if ((u_char *)&(var) > ep - sizeof(var)) return
 
@@ -664,6 +752,17 @@ icmp6_opt_print(const u_char *bp, int resid)
                                EXTRACT_32BITS(&opm->nd_opt_mtu_mtu),
                                (op->nd_opt_len != 1) ? "bad option length" : "" );
                         break;
+               case ND_OPT_RDNSS:
+                       oprd = (struct nd_opt_rdnss *)op;
+                       l = (op->nd_opt_len - 1) / 2;
+                       printf(" lifetime %us,", 
+                               EXTRACT_32BITS(&oprd->nd_opt_rdnss_lifetime)); 
+                       for (i = 0; i < l; i++) {
+                               TCHECK(oprd->nd_opt_rdnss_addr[i]);
+                               printf(" addr: %s", 
+                                   ip6addr_string(&oprd->nd_opt_rdnss_addr[i]));
+                       }
+                       break;
                case ND_OPT_ADVINTERVAL:
                        opa = (struct nd_opt_advinterval *)op;
                        TCHECK(opa->nd_opt_adv_interval);
@@ -753,7 +852,7 @@ mldv2_report_print(const u_char *bp, u_int len)
     }
 
     TCHECK(icp->icmp6_data16[1]);
-    ngroups = ntohs(icp->icmp6_data16[1]);
+    ngroups = EXTRACT_16BITS(&icp->icmp6_data16[1]);
     printf(", %d group record(s)", ngroups);
     if (vflag > 0) {
        /* Print the group records */
@@ -812,7 +911,7 @@ mldv2_query_print(const u_char *bp, u_int len)
        return;
     }
     TCHECK(icp->icmp6_data16[0]);
-    mrc = ntohs(icp->icmp6_data16[0]);
+    mrc = EXTRACT_16BITS(&icp->icmp6_data16[0]);
     if (mrc < 32768) {
        mrt = mrc;
     } else {
@@ -841,7 +940,7 @@ mldv2_query_print(const u_char *bp, u_int len)
     }
 
     TCHECK2(bp[26], 2);
-    nsrcs = ntohs(*(u_short *)&bp[26]);
+    nsrcs = EXTRACT_16BITS(&bp[26]);
     if (nsrcs > 0) {
        if (len < 28 + nsrcs * sizeof(struct in6_addr))
            printf(" [invalid number of sources]");
@@ -863,7 +962,7 @@ trunc:
     return;
 }
 
-void
+static void
 dnsname_print(const u_char *cp, const u_char *ep)
 {
        int i;
@@ -1192,9 +1291,9 @@ icmp6_rrenum_print(const u_char *bp, const u_char *ep)
                            F(ICMP6_RR_FLAGS_PREVDONE, "P"));
                }
                printf("seg=%u,", rr6->rr_segnum);
-               printf("maxdelay=%u", rr6->rr_maxdelay);
+               printf("maxdelay=%u", EXTRACT_16BITS(&rr6->rr_maxdelay));
                if (rr6->rr_reserved)
-                       printf("rsvd=0x%x", EXTRACT_16BITS(&rr6->rr_reserved));
+                       printf("rsvd=0x%x", EXTRACT_32BITS(&rr6->rr_reserved));
                /*[*/
                printf("]");
 #undef F