]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-icmp6.c
When checking for pcap_if_t, add $V_INCLS to CFLAGS, so we look at the
[tcpdump] / print-icmp6.c
index b3711b6c6c34896f3d7009bbeb996962f31659b5..2eab0ac706896e2bcfd84106310478ff1a4c5b89 100644 (file)
@@ -20,8 +20,8 @@
  */
 
 #ifndef lint
-static const char rcsid[] =
-    "@(#) $Header: /tcpdump/master/tcpdump/print-icmp6.c,v 1.65 2002-09-05 00:52:30 guy Exp $";
+static const char rcsid[] _U_ =
+    "@(#) $Header: /tcpdump/master/tcpdump/print-icmp6.c,v 1.77 2004-06-16 00:06:28 guy Exp $";
 #endif
 
 #ifdef HAVE_CONFIG_H
@@ -37,9 +37,11 @@ static const char rcsid[] =
 
 #include "ip6.h"
 #include "icmp6.h"
+#include "ipproto.h"
 
 #include "interface.h"
 #include "addrtoname.h"
+#include "extract.h"
 
 #include "udp.h"
 #include "ah.h"
@@ -47,17 +49,30 @@ static const char rcsid[] =
 static const char *get_rtpref(u_int);
 static const char *get_lifetime(u_int32_t);
 static void print_lladdr(const u_char *, size_t);
-void icmp6_opt_print(const u_char *, int);
-void mld6_print(const u_char *);
-static struct udphdr *get_upperlayer(u_char *, int *);
+static void icmp6_opt_print(const u_char *, int);
+static void mld6_print(const u_char *);
+static void mldv2_report_print(const u_char *, u_int);
+static void mldv2_query_print(const u_char *, u_int);
+static struct udphdr *get_upperlayer(u_char *, u_int *);
 static void dnsname_print(const u_char *, const u_char *);
-void icmp6_nodeinfo_print(int, const u_char *, const u_char *);
-void icmp6_rrenum_print(int, const u_char *, const u_char *);
+static void icmp6_nodeinfo_print(u_int, const u_char *, const u_char *);
+static void icmp6_rrenum_print(const u_char *, const u_char *);
 
 #ifndef abs
 #define abs(a) ((0 < (a)) ? (a) : -(a))
 #endif
 
+/* mldv2 report types */
+static struct tok mldv2report2str[] = {
+       { 1,    "is_in" },
+       { 2,    "is_ex" },
+       { 3,    "to_in" },
+       { 4,    "to_ex" },
+       { 5,    "allow" },
+       { 6,    "block" },
+       { 0,    NULL }
+};
+
 static const char *
 get_rtpref(u_int v)
 {
@@ -99,8 +114,51 @@ print_lladdr(const u_int8_t *p, size_t l)
        }
 }
 
+static int icmp6_cksum(const struct ip6_hdr *ip6, const struct icmp6_hdr *icp,
+       u_int len)
+{
+       size_t i;
+       register const u_int16_t *sp;
+       u_int32_t sum;
+       union {
+               struct {
+                       struct in6_addr ph_src;
+                       struct in6_addr ph_dst;
+                       u_int32_t       ph_len;
+                       u_int8_t        ph_zero[3];
+                       u_int8_t        ph_nxt;
+               } ph;
+               u_int16_t pa[20];
+       } phu;
+
+       /* pseudo-header */
+       memset(&phu, 0, sizeof(phu));
+       phu.ph.ph_src = ip6->ip6_src;
+       phu.ph.ph_dst = ip6->ip6_dst;
+       phu.ph.ph_len = htonl(len);
+       phu.ph.ph_nxt = IPPROTO_ICMPV6;
+
+       sum = 0;
+       for (i = 0; i < sizeof(phu.pa) / sizeof(phu.pa[0]); i++)
+               sum += phu.pa[i];
+
+       sp = (const u_int16_t *)icp;
+
+       for (i = 0; i < (len & ~1); i += 2)
+               sum += *sp++;
+
+       if (len & 1)
+               sum += htons((*(const u_int8_t *)sp) << 8);
+
+       while (sum > 0xffff)
+               sum = (sum & 0xffff) + (sum >> 16);
+       sum = ~sum & 0xffff;
+
+       return (sum);
+}
+
 void
-icmp6_print(const u_char *bp, const u_char *bp2)
+icmp6_print(const u_char *bp, u_int length, const u_char *bp2, int fragmented)
 {
        const struct icmp6_hdr *dp;
        const struct ip6_hdr *ip;
@@ -110,7 +168,7 @@ icmp6_print(const u_char *bp, const u_char *bp2)
        int dport;
        const u_char *ep;
        char buf[256];
-       int icmp6len, prot;
+       u_int prot;
 
        dp = (struct icmp6_hdr *)bp;
        ip = (struct ip6_hdr *)bp2;
@@ -118,13 +176,21 @@ icmp6_print(const u_char *bp, const u_char *bp2)
        str = buf;
        /* 'ep' points to the end of available data. */
        ep = snapend;
-       if (ip->ip6_plen)
-               icmp6len = (ntohs(ip->ip6_plen) + sizeof(struct ip6_hdr) -
-                           (bp - bp2));
-       else                    /* XXX: jumbo payload case... */
-               icmp6len = snapend - bp;
 
-       TCHECK(dp->icmp6_code);
+       TCHECK(dp->icmp6_cksum);
+
+       if (vflag && !fragmented) {
+               int sum = dp->icmp6_cksum;
+
+               if (TTEST2(bp[0], length)) {
+                       sum = icmp6_cksum(ip, dp, length);
+                       if (sum != 0)
+                               (void)printf("[bad icmp6 cksum %x!] ", sum);
+                       else
+                               (void)printf("[icmp6 sum ok] ");
+               }
+       }
+
        switch (dp->icmp6_type) {
        case ICMP6_DST_UNREACH:
                TCHECK(oip->ip6_dst);
@@ -151,7 +217,7 @@ icmp6_print(const u_char *bp, const u_char *bp2)
                            == NULL)
                                goto trunc;
 
-                       dport = ntohs(ouh->uh_dport);
+                       dport = EXTRACT_16BITS(&ouh->uh_dport);
                        switch (prot) {
                        case IPPROTO_TCP:
                                printf("icmp6: %s tcp port %s unreachable",
@@ -179,7 +245,7 @@ icmp6_print(const u_char *bp, const u_char *bp2)
                break;
        case ICMP6_PACKET_TOO_BIG:
                TCHECK(dp->icmp6_mtu);
-               printf("icmp6: too big %u", (u_int32_t)ntohl(dp->icmp6_mtu));
+               printf("icmp6: too big %u", EXTRACT_32BITS(&dp->icmp6_mtu));
                break;
        case ICMP6_TIME_EXCEEDED:
                TCHECK(oip->ip6_dst);
@@ -202,15 +268,15 @@ icmp6_print(const u_char *bp, const u_char *bp2)
                switch (dp->icmp6_code) {
                case ICMP6_PARAMPROB_HEADER:
                        printf("icmp6: parameter problem errorneous - octet %u",
-                               (u_int32_t)ntohl(dp->icmp6_pptr));
+                               EXTRACT_32BITS(&dp->icmp6_pptr));
                        break;
                case ICMP6_PARAMPROB_NEXTHEADER:
                        printf("icmp6: parameter problem next header - octet %u",
-                               (u_int32_t)ntohl(dp->icmp6_pptr));
+                               EXTRACT_32BITS(&dp->icmp6_pptr));
                        break;
                case ICMP6_PARAMPROB_OPTION:
                        printf("icmp6: parameter problem option - octet %u",
-                               (u_int32_t)ntohl(dp->icmp6_pptr));
+                               EXTRACT_32BITS(&dp->icmp6_pptr));
                        break;
                default:
                        printf("icmp6: parameter problem code-#%d",
@@ -219,14 +285,23 @@ icmp6_print(const u_char *bp, const u_char *bp2)
                }
                break;
        case ICMP6_ECHO_REQUEST:
-               printf("icmp6: echo request");
-               break;
        case ICMP6_ECHO_REPLY:
-               printf("icmp6: echo reply");
+               TCHECK(dp->icmp6_seq);
+               printf("icmp6: echo %s seq %u",
+                       dp->icmp6_type == ICMP6_ECHO_REQUEST ?
+                       "request" : "reply",
+                       EXTRACT_16BITS(&dp->icmp6_seq));
                break;
        case ICMP6_MEMBERSHIP_QUERY:
                printf("icmp6: multicast listener query ");
-               mld6_print((const u_char *)dp);
+               if (length == MLD_MINLEN) {
+                       mld6_print((const u_char *)dp);
+               } else if (length >= MLDV2_MINLEN) {
+                       printf("v2 ");
+                       mldv2_query_print((const u_char *)dp, length);
+               } else {
+                       printf(" unknown-version(len=%d) ", length);
+               }
                break;
        case ICMP6_MEMBERSHIP_REPORT:
                printf("icmp6: multicast listener report ");
@@ -241,7 +316,7 @@ icmp6_print(const u_char *bp, const u_char *bp2)
                if (vflag) {
 #define RTSOLLEN 8
                        icmp6_opt_print((const u_char *)dp + RTSOLLEN,
-                                       icmp6len - RTSOLLEN);
+                                       length - RTSOLLEN);
                }
                break;
        case ND_ROUTER_ADVERT:
@@ -266,14 +341,14 @@ icmp6_print(const u_char *bp, const u_char *bp2)
                        printf("pref=%s, ",
                            get_rtpref(p->nd_ra_flags_reserved));
 
-                       printf("router_ltime=%d, ", ntohs(p->nd_ra_router_lifetime));
+                       printf("router_ltime=%d, ", EXTRACT_16BITS(&p->nd_ra_router_lifetime));
                        printf("reachable_time=%u, ",
-                               (u_int32_t)ntohl(p->nd_ra_reachable));
+                               EXTRACT_32BITS(&p->nd_ra_reachable));
                        printf("retrans_time=%u)",
-                               (u_int32_t)ntohl(p->nd_ra_retransmit));
+                               EXTRACT_32BITS(&p->nd_ra_retransmit));
 #define RTADVLEN 16
                        icmp6_opt_print((const u_char *)dp + RTADVLEN,
-                                       icmp6len - RTADVLEN);
+                                       length - RTADVLEN);
                }
                break;
        case ND_NEIGHBOR_SOLICIT:
@@ -286,7 +361,7 @@ icmp6_print(const u_char *bp, const u_char *bp2)
                if (vflag) {
 #define NDSOLLEN 24
                        icmp6_opt_print((const u_char *)dp + NDSOLLEN,
-                                       icmp6len - NDSOLLEN);
+                                       length - NDSOLLEN);
                }
            }
                break;
@@ -318,7 +393,7 @@ icmp6_print(const u_char *bp, const u_char *bp2)
                        }
 #define NDADVLEN 24
                        icmp6_opt_print((const u_char *)dp + NDADVLEN,
-                                       icmp6len - NDADVLEN);
+                                       length - NDADVLEN);
 #undef NDADVLEN
                }
            }
@@ -328,42 +403,51 @@ icmp6_print(const u_char *bp, const u_char *bp2)
                TCHECK(RDR(dp)->nd_rd_dst);
                printf("icmp6: redirect %s",
                    getname6((const u_char *)&RDR(dp)->nd_rd_dst));
+               TCHECK(RDR(dp)->nd_rd_target);
                printf(" to %s",
                    getname6((const u_char*)&RDR(dp)->nd_rd_target));
 #define REDIRECTLEN 40
                if (vflag) {
                        icmp6_opt_print((const u_char *)dp + REDIRECTLEN,
-                                       icmp6len - REDIRECTLEN);
+                                       length - REDIRECTLEN);
                }
                break;
 #undef REDIRECTLEN
 #undef RDR
        case ICMP6_ROUTER_RENUMBERING:
-               icmp6_rrenum_print(icmp6len, bp, ep);
+               icmp6_rrenum_print(bp, ep);
                break;
        case ICMP6_NI_QUERY:
        case ICMP6_NI_REPLY:
-               icmp6_nodeinfo_print(icmp6len, bp, ep);
+               icmp6_nodeinfo_print(length, bp, ep);
+               break;
+       case IND_SOLICIT:
+               printf("icmp6: inverse neighbor solicitation");
+               break;
+       case IND_ADVERT:
+               printf("icmp6: inverse neighbor advertisement");
+               break;
+       case ICMP6_V2_MEMBERSHIP_REPORT:
+               printf("icmp6: multicast listener report v2 ");
+               mldv2_report_print((const u_char *) dp, length);
                break;
        case ICMP6_HADISCOV_REQUEST:
                printf("icmp6: ha discovery request");
                if (vflag) {
                        TCHECK(dp->icmp6_data16[0]);
-                       printf("(id=%d)", ntohs(dp->icmp6_data16[0]));
+                       printf("(id=%d)", EXTRACT_16BITS(&dp->icmp6_data16[0]));
                }
                break;
        case ICMP6_HADISCOV_REPLY:
                printf("icmp6: ha discovery reply");
                if (vflag) {
                        struct in6_addr *in6;
-                       u_int32_t *res;
                        u_char *cp;
 
                        TCHECK(dp->icmp6_data16[0]);
-                       printf("(id=%d", ntohs(dp->icmp6_data16[0]));
-                       cp = (u_char *)dp + icmp6len;
-                       res = (u_int32_t *)(dp + 1);
-                       in6 = (struct in6_addr *)(res + 2);
+                       printf("(id=%d", EXTRACT_16BITS(&dp->icmp6_data16[0]));
+                       cp = (u_char *)dp + length;
+                       in6 = (struct in6_addr *)(dp + 1);
                        for (; (u_char *)in6 < cp; in6++) {
                                TCHECK(*in6);
                                printf(", %s", ip6addr_string(in6));
@@ -375,17 +459,24 @@ icmp6_print(const u_char *bp, const u_char *bp2)
                printf("icmp6: mobile router solicitation");
                if (vflag) {
                        TCHECK(dp->icmp6_data16[0]);
-                       printf("(id=%d)", ntohs(dp->icmp6_data16[0]));
+                       printf("(id=%d)", EXTRACT_16BITS(&dp->icmp6_data16[0]));
                }
                break;
        case ICMP6_MOBILEPREFIX_ADVERT:
                printf("icmp6: mobile router advertisement");
                if (vflag) {
                        TCHECK(dp->icmp6_data16[0]);
-                       printf("(id=%d)", ntohs(dp->icmp6_data16[0]));
-#define MPADVLEN 6
+                       printf("(id=%d", EXTRACT_16BITS(&dp->icmp6_data16[0]));
+                       if (dp->icmp6_data16[1] & 0xc0)
+                               printf(" ");
+                       if (dp->icmp6_data16[1] & 0x80)
+                               printf("M");
+                       if (dp->icmp6_data16[1] & 0x40)
+                               printf("O");
+                       printf(")");
+#define MPADVLEN 8
                        icmp6_opt_print((const u_char *)dp + MPADVLEN,
-                                       icmp6len - MPADVLEN);
+                                       length - MPADVLEN);
                }
                break;
        default:
@@ -398,7 +489,7 @@ trunc:
 }
 
 static struct udphdr *
-get_upperlayer(u_char *bp, int *prot)
+get_upperlayer(u_char *bp, u_int *prot)
 {
        const u_char *ep;
        struct ip6_hdr *ip6 = (struct ip6_hdr *)bp;
@@ -406,12 +497,13 @@ get_upperlayer(u_char *bp, int *prot)
        struct ip6_hbh *hbh;
        struct ip6_frag *fragh;
        struct ah *ah;
-       int nh, hlen;
+       u_int nh;
+       int hlen;
 
        /* 'ep' points to the end of available data. */
        ep = snapend;
 
-       if (TTEST(ip6->ip6_nxt) == 0)
+       if (!TTEST(ip6->ip6_nxt))
                return NULL;
 
        nh = ip6->ip6_nxt;
@@ -436,7 +528,7 @@ get_upperlayer(u_char *bp, int *prot)
                case IPPROTO_DSTOPTS:
                case IPPROTO_ROUTING:
                        hbh = (struct ip6_hbh *)bp;
-                       if (TTEST(hbh->ip6h_len) == 0)
+                       if (!TTEST(hbh->ip6h_len))
                                return(NULL);
                        nh = hbh->ip6h_nxt;
                        hlen = (hbh->ip6h_len + 1) << 3;
@@ -444,10 +536,10 @@ get_upperlayer(u_char *bp, int *prot)
 
                case IPPROTO_FRAGMENT: /* this should be odd, but try anyway */
                        fragh = (struct ip6_frag *)bp;
-                       if (TTEST(fragh->ip6f_offlg) == 0)
+                       if (!TTEST(fragh->ip6f_offlg))
                                return(NULL);
                        /* fragments with non-zero offset are meaningless */
-                       if ((fragh->ip6f_offlg & IP6F_OFF_MASK) != 0)
+                       if ((EXTRACT_16BITS(&fragh->ip6f_offlg) & IP6F_OFF_MASK) != 0)
                                return(NULL);
                        nh = fragh->ip6f_nxt;
                        hlen = sizeof(struct ip6_frag);
@@ -455,7 +547,7 @@ get_upperlayer(u_char *bp, int *prot)
 
                case IPPROTO_AH:
                        ah = (struct ah *)bp;
-                       if (TTEST(ah->ah_len) == 0)
+                       if (!TTEST(ah->ah_len))
                                return(NULL);
                        nh = ah->ah_nxt;
                        hlen = (ah->ah_len + 2) << 2;
@@ -470,7 +562,7 @@ get_upperlayer(u_char *bp, int *prot)
        return(NULL);           /* should be notreached, though */
 }
 
-void
+static void
 icmp6_opt_print(const u_char *bp, int resid)
 {
        const struct nd_opt_hdr *op;
@@ -538,9 +630,9 @@ icmp6_opt_print(const u_char *bp, int resid)
                        if (opp->nd_opt_pi_flags_reserved)
                                printf(" ");
                        printf("valid_ltime=%s,",
-                           get_lifetime((u_int32_t)ntohl(opp->nd_opt_pi_valid_time)));
+                           get_lifetime(EXTRACT_32BITS(&opp->nd_opt_pi_valid_time)));
                        printf("preferred_ltime=%s,",
-                           get_lifetime((u_int32_t)ntohl(opp->nd_opt_pi_preferred_time)));
+                           get_lifetime(EXTRACT_32BITS(&opp->nd_opt_pi_preferred_time)));
                        printf("prefix=%s/%d",
                            ip6addr_string(&opp->nd_opt_pi_prefix),
                            opp->nd_opt_pi_prefix_len);
@@ -564,7 +656,7 @@ icmp6_opt_print(const u_char *bp, int resid)
                                printf(")");
                                break;
                        }
-                       printf(" mtu=%u", (u_int32_t)ntohl(opm->nd_opt_mtu_mtu));
+                       printf(" mtu=%u", EXTRACT_32BITS(&opm->nd_opt_mtu_mtu));
                        if (opm->nd_opt_mtu_len != 1)
                                printf("!");
                        printf(")");
@@ -574,7 +666,7 @@ icmp6_opt_print(const u_char *bp, int resid)
                        TCHECK(opa->nd_opt_adv_interval);
                        printf("(advint:");     /*)*/
                        printf(" advint=%u",
-                           (u_int32_t)ntohl(opa->nd_opt_adv_interval));
+                           EXTRACT_32BITS(&opa->nd_opt_adv_interval));
                        /*(*/
                        printf(")");
                        break;
@@ -582,8 +674,8 @@ icmp6_opt_print(const u_char *bp, int resid)
                        oph = (struct nd_opt_homeagent_info *)op;
                        TCHECK(oph->nd_opt_hai_lifetime);
                        printf("(ha info:");    /*)*/
-                       printf(" pref=%d", ntohs(oph->nd_opt_hai_preference));
-                       printf(", lifetime=%u", ntohs(oph->nd_opt_hai_lifetime));
+                       printf(" pref=%d", EXTRACT_16BITS(&oph->nd_opt_hai_preference));
+                       printf(", lifetime=%u", EXTRACT_16BITS(&oph->nd_opt_hai_lifetime));
                        printf(")");
                        break;
                case ND_OPT_ROUTE_INFO:
@@ -610,7 +702,7 @@ icmp6_opt_print(const u_char *bp, int resid)
                            opri->nd_opt_rti_prefixlen);
                        printf(", pref=%s", get_rtpref(opri->nd_opt_rti_flags));
                        printf(", lifetime=%s",
-                           get_lifetime((u_int32_t)ntohl(opri->nd_opt_rti_lifetime)));
+                           get_lifetime(EXTRACT_32BITS(&opri->nd_opt_rti_lifetime)));
                        /*(*/
                        printf(")");
                        break;
@@ -631,7 +723,7 @@ icmp6_opt_print(const u_char *bp, int resid)
 #undef ECHECK
 }
 
-void
+static void
 mld6_print(const u_char *bp)
 {
        struct mld6_hdr *mp = (struct mld6_hdr *)bp;
@@ -643,11 +735,131 @@ mld6_print(const u_char *bp)
        if ((u_char *)mp + sizeof(*mp) > ep)
                return;
 
-       printf("max resp delay: %d ", ntohs(mp->mld6_maxdelay));
+       printf("max resp delay: %d ", EXTRACT_16BITS(&mp->mld6_maxdelay));
        printf("addr: %s", ip6addr_string(&mp->mld6_addr));
 }
 
 static void
+mldv2_report_print(const u_char *bp, u_int len)
+{
+    struct icmp6_hdr *icp = (struct icmp6_hdr *) bp;
+    u_int group, nsrcs, ngroups;
+    u_int i, j;
+
+    /* Minimum len is 8 */
+    if (len < 8) {
+       printf(" [invalid len %d]", len);
+       return;
+    }
+
+    TCHECK(icp->icmp6_data16[1]);
+    ngroups = ntohs(icp->icmp6_data16[1]);
+    printf(", %d group record(s)", ngroups);
+    if (vflag > 0) {
+       /* Print the group records */
+       group = 8;
+        for (i = 0; i < ngroups; i++) {
+           /* type(1) + auxlen(1) + numsrc(2) + grp(16) */
+           if (len < group + 20) {
+               printf(" [invalid number of groups]");
+               return;
+           }
+            TCHECK(bp[group + 4]);
+            printf(" [gaddr %s", ip6addr_string(&bp[group + 4]));
+           printf(" %s", tok2str(mldv2report2str, " [v2-report-#%d]",
+                                                               bp[group]));
+            nsrcs = (bp[group + 2] << 8) + bp[group + 3];
+           /* Check the number of sources and print them */
+           if (len < group + 20 + (nsrcs * 16)) {
+               printf(" [invalid number of sources %d]", nsrcs);
+               return;
+           }
+            if (vflag == 1)
+                printf(", %d source(s)", nsrcs);
+            else {
+               /* Print the sources */
+                (void)printf(" {");
+                for (j = 0; j < nsrcs; j++) {
+                    TCHECK2(bp[group + 20 + j * 16], 16);
+                   printf(" %s", ip6addr_string(&bp[group + 20 + j * 16]));
+               }
+                (void)printf(" }");
+            }
+           /* Next group record */
+            group += 20 + nsrcs * 16;
+           printf("]");
+        }
+    }
+    return;
+trunc:
+    (void)printf("[|icmp6]");
+    return;
+}
+
+static void
+mldv2_query_print(const u_char *bp, u_int len)
+{
+    struct icmp6_hdr *icp = (struct icmp6_hdr *) bp;
+    u_int mrc;
+    int mrt, qqi;
+    u_int nsrcs;
+    register u_int i;
+
+    /* Minimum len is 28 */
+    if (len < 28) {
+       printf(" [invalid len %d]", len);
+       return;
+    }
+    TCHECK(icp->icmp6_data16[0]);
+    mrc = ntohs(icp->icmp6_data16[0]);
+    if (mrc < 32768) {
+       mrt = mrc;
+    } else {
+        mrt = ((mrc & 0x0fff) | 0x1000) << (((mrc & 0x7000) >> 12) + 3);
+    }
+    if (vflag) {
+       (void)printf(" [max resp delay=%d]", mrt);
+    }
+    printf(" [gaddr %s", ip6addr_string(&bp[8]));
+
+    if (vflag) {
+        TCHECK(bp[25]);
+       if (bp[24] & 0x08) {
+               printf(" sflag");
+       }
+       if (bp[24] & 0x07) {
+               printf(" robustness=%d", bp[24] & 0x07);
+       }
+       if (bp[25] < 128) {
+               qqi = bp[25];
+       } else {
+               qqi = ((bp[25] & 0x0f) | 0x10) << (((bp[25] & 0x70) >> 4) + 3);
+       }
+       printf(" qqi=%d", qqi);
+    }
+
+    nsrcs = ntohs(*(u_short *)&bp[26]);
+    if (nsrcs > 0) {
+       if (len < 28 + nsrcs * 16)
+           printf(" [invalid number of sources]");
+       else if (vflag > 1) {
+           printf(" {");
+           for (i = 0; i < nsrcs; i++) {
+               TCHECK2(bp[28 + i * 16], 16);
+               printf(" %s", ip6addr_string(&bp[28 + i * 16]));
+           }
+           printf(" }");
+       } else
+           printf(", %d source(s)", nsrcs);
+    }
+    printf("]");
+    return;
+trunc:
+    (void)printf("[|icmp6]");
+    return;
+}
+
+void
 dnsname_print(const u_char *cp, const u_char *ep)
 {
        int i;
@@ -683,15 +895,17 @@ dnsname_print(const u_char *cp, const u_char *ep)
        printf("\"");
 }
 
-void
-icmp6_nodeinfo_print(int icmp6len, const u_char *bp, const u_char *ep)
+static void
+icmp6_nodeinfo_print(u_int icmp6len, const u_char *bp, const u_char *ep)
 {
        struct icmp6_nodeinfo *ni6;
        struct icmp6_hdr *dp;
        const u_char *cp;
-       int siz, i;
+       size_t siz, i;
        int needcomma;
 
+       if (ep < bp)
+               return;
        dp = (struct icmp6_hdr *)bp;
        ni6 = (struct icmp6_nodeinfo *)bp;
        siz = ep - bp;
@@ -708,13 +922,13 @@ icmp6_nodeinfo_print(int icmp6len, const u_char *bp, const u_char *ep)
                TCHECK2(*dp, sizeof(*ni6));
                ni6 = (struct icmp6_nodeinfo *)dp;
                printf(" (");   /*)*/
-               switch (ntohs(ni6->ni_qtype)) {
+               switch (EXTRACT_16BITS(&ni6->ni_qtype)) {
                case NI_QTYPE_NOOP:
                        printf("noop");
                        break;
                case NI_QTYPE_SUPTYPES:
                        printf("supported qtypes");
-                       i = ntohs(ni6->ni_flags);
+                       i = EXTRACT_16BITS(&ni6->ni_flags);
                        if (i)
                                printf(" [%s]", (i & 0x01) ? "C" : "");
                        break;
@@ -850,7 +1064,7 @@ icmp6_nodeinfo_print(int icmp6len, const u_char *bp, const u_char *ep)
                        break;
                }
 
-               switch (ntohs(ni6->ni_qtype)) {
+               switch (EXTRACT_16BITS(&ni6->ni_qtype)) {
                case NI_QTYPE_NOOP:
                        if (needcomma)
                                printf(", ");
@@ -863,7 +1077,7 @@ icmp6_nodeinfo_print(int icmp6len, const u_char *bp, const u_char *ep)
                        if (needcomma)
                                printf(", ");
                        printf("supported qtypes");
-                       i = ntohs(ni6->ni_flags);
+                       i = EXTRACT_16BITS(&ni6->ni_flags);
                        if (i)
                                printf(" [%s]", (i & 0x01) ? "C" : "");
                        break;
@@ -885,7 +1099,7 @@ icmp6_nodeinfo_print(int icmp6len, const u_char *bp, const u_char *ep)
                                printf("\"");
                        } else
                                dnsname_print(cp, ep);
-                       if ((ntohs(ni6->ni_flags) & 0x01) != 0)
+                       if ((EXTRACT_16BITS(&ni6->ni_flags) & 0x01) != 0)
                                printf(" [TTL=%u]", *(u_int32_t *)(ni6 + 1));
                        break;
                case NI_QTYPE_NODEADDR:
@@ -898,7 +1112,7 @@ icmp6_nodeinfo_print(int icmp6len, const u_char *bp, const u_char *ep)
                                        break;
                                printf(" %s", getname6(bp + i));
                                i += sizeof(struct in6_addr);
-                               printf("(%d)", (int32_t)ntohl(*(int32_t *)(bp + i)));
+                               printf("(%d)", (int32_t)EXTRACT_32BITS(bp + i));
                                i += sizeof(int32_t);
                        }
                        i = ni6->ni_flags;
@@ -930,8 +1144,8 @@ trunc:
        fputs("[|icmp6]", stdout);
 }
 
-void
-icmp6_rrenum_print(int icmp6len, const u_char *bp, const u_char *ep)
+static void
+icmp6_rrenum_print(const u_char *bp, const u_char *ep)
 {
        struct icmp6_router_renum *rr6;
        struct icmp6_hdr *dp;
@@ -942,6 +1156,8 @@ icmp6_rrenum_print(int icmp6len, const u_char *bp, const u_char *ep)
        char hbuf[NI_MAXHOST];
        int n;
 
+       if (ep < bp)
+               return;
        dp = (struct icmp6_hdr *)bp;
        rr6 = (struct icmp6_router_renum *)bp;
        siz = ep - bp;
@@ -963,7 +1179,7 @@ icmp6_rrenum_print(int icmp6len, const u_char *bp, const u_char *ep)
                break;
        }
 
-       printf(", seq=%u", (u_int32_t)ntohl(rr6->rr_seqnum));
+       printf(", seq=%u", EXTRACT_32BITS(&rr6->rr_seqnum));
 
        if (vflag) {
 #define F(x, y)        ((rr6->rr_flags) & (x) ? (y) : "")
@@ -978,7 +1194,7 @@ icmp6_rrenum_print(int icmp6len, const u_char *bp, const u_char *ep)
                printf("seg=%u,", rr6->rr_segnum);
                printf("maxdelay=%u", rr6->rr_maxdelay);
                if (rr6->rr_reserved)
-                       printf("rsvd=0x%x", (u_int16_t)ntohs(rr6->rr_reserved));
+                       printf("rsvd=0x%x", EXTRACT_16BITS(&rr6->rr_reserved));
                /*[*/
                printf("]");
 #undef F
@@ -1043,12 +1259,12 @@ icmp6_rrenum_print(int icmp6len, const u_char *bp, const u_char *ep)
                                        printf("vltime=infty,");
                                else
                                        printf("vltime=%u,",
-                                           (u_int32_t)ntohl(use->rpu_vltime));
+                                           EXTRACT_32BITS(&use->rpu_vltime));
                                if (~use->rpu_pltime == 0)
                                        printf("pltime=infty,");
                                else
                                        printf("pltime=%u,",
-                                           (u_int32_t)ntohl(use->rpu_pltime));
+                                           EXTRACT_32BITS(&use->rpu_pltime));
                        }
                        if (inet_ntop(AF_INET6, &use->rpu_prefix, hbuf,
                            sizeof(hbuf)))