]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-icmp6.c
Update .gitignore for other configurations
[tcpdump] / print-icmp6.c
index b447562ea13dbbc493b71faba6c6bab61ced4a53..6e7143aa434e2c939a65f3e721e39fecc71b6ee3 100644 (file)
@@ -22,7 +22,7 @@
 /* \summary: IPv6 Internet Control Message Protocol (ICMPv6) printer */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
 #endif
 
 #include "netdissect-stdinc.h"
@@ -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 */
 
@@ -175,7 +175,7 @@ struct icmp6_hdr {
  */
 struct mld6_hdr {
        struct icmp6_hdr        mld6_hdr;
-       struct in6_addr         mld6_addr; /* multicast address */
+       nd_ipv6                 mld6_addr; /* multicast address */
 };
 
 #define mld6_type      mld6_hdr.icmp6_type
@@ -232,7 +232,7 @@ struct nd_router_advert {   /* router advertisement */
 
 struct nd_neighbor_solicit {   /* neighbor solicitation */
        struct icmp6_hdr        nd_ns_hdr;
-       struct in6_addr         nd_ns_target;   /*target address */
+       nd_ipv6                 nd_ns_target;   /*target address */
        /* could be followed by options */
 };
 
@@ -243,7 +243,7 @@ struct nd_neighbor_solicit {        /* neighbor solicitation */
 
 struct nd_neighbor_advert {    /* neighbor advertisement */
        struct icmp6_hdr        nd_na_hdr;
-       struct in6_addr         nd_na_target;   /* target address */
+       nd_ipv6                 nd_na_target;   /* target address */
        /* could be followed by options */
 };
 
@@ -258,8 +258,8 @@ struct nd_neighbor_advert { /* neighbor advertisement */
 
 struct nd_redirect {           /* redirect */
        struct icmp6_hdr        nd_rd_hdr;
-       struct in6_addr         nd_rd_target;   /* target address */
-       struct in6_addr         nd_rd_dst;      /* destination address */
+       nd_ipv6                 nd_rd_target;   /* target address */
+       nd_ipv6                 nd_rd_dst;      /* destination address */
        /* could be followed by options */
 };
 
@@ -286,14 +286,14 @@ struct nd_opt_hdr {               /* Neighbor discovery option header */
 #define ND_OPT_DNSSL                   31
 
 struct nd_opt_prefix_info {    /* prefix information */
-       nd_uint8_t              nd_opt_pi_type;
-       nd_uint8_t              nd_opt_pi_len;
-       nd_uint8_t              nd_opt_pi_prefix_len;
-       nd_uint8_t              nd_opt_pi_flags_reserved;
-       nd_uint32_t             nd_opt_pi_valid_time;
-       nd_uint32_t             nd_opt_pi_preferred_time;
-       nd_uint32_t             nd_opt_pi_reserved2;
-       struct in6_addr nd_opt_pi_prefix;
+       nd_uint8_t      nd_opt_pi_type;
+       nd_uint8_t      nd_opt_pi_len;
+       nd_uint8_t      nd_opt_pi_prefix_len;
+       nd_uint8_t      nd_opt_pi_flags_reserved;
+       nd_uint32_t     nd_opt_pi_valid_time;
+       nd_uint32_t     nd_opt_pi_preferred_time;
+       nd_uint32_t     nd_opt_pi_reserved2;
+       nd_ipv6         nd_opt_pi_prefix;
 };
 
 #define ND_OPT_PI_FLAG_ONLINK          0x80
@@ -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;
-       struct in6_addr 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 */
@@ -440,7 +440,7 @@ struct rr_pco_match {               /* match prefix part */
        nd_uint8_t              rpm_minlen;
        nd_uint8_t              rpm_maxlen;
        nd_uint16_t             rpm_reserved;
-       struct  in6_addr        rpm_prefix;
+       nd_ipv6                 rpm_prefix;
 };
 
 #define RPM_PCO_ADD            1
@@ -456,7 +456,7 @@ struct rr_pco_use {         /* use prefix part */
        nd_uint32_t     rpu_vltime;
        nd_uint32_t     rpu_pltime;
        nd_uint32_t     rpu_flags;
-       struct  in6_addr rpu_prefix;
+       nd_ipv6         rpu_prefix;
 };
 #define ICMP6_RR_PCOUSE_RAFLAGS_ONLINK 0x80
 #define ICMP6_RR_PCOUSE_RAFLAGS_AUTO   0x40
@@ -470,7 +470,7 @@ struct rr_result {          /* router renumbering result message */
        nd_uint8_t      rrr_ordinal;
        nd_uint8_t      rrr_matchedlen;
        nd_uint32_t     rrr_ifid;
-       struct  in6_addr rrr_prefix;
+       nd_ipv6         rrr_prefix;
 };
 /* network endian */
 #define ICMP6_RR_RESULT_FLAGS_OOB              ((uint16_t)htons(0x0002))
@@ -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);
@@ -755,7 +755,7 @@ get_lifetime(uint32_t v)
        if (v == (uint32_t)~0UL)
                return "infinity";
        else {
-               snprintf(buf, sizeof(buf), "%us", v);
+               nd_snprintf(buf, sizeof(buf), "%us", v);
                return buf;
        }
 }
@@ -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,17 +1033,23 @@ 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;
 
                if (ND_TTEST_LEN(bp, length)) {
-                       ND_TCHECK(dp->icmp6_cksum);
+                       ND_TCHECK_2(dp->icmp6_cksum);
                        udp_sum = EXTRACT_BE_U_2(dp->icmp6_cksum);
                        sum = icmp6_cksum(ndo, ip, dp, length);
                        if (sum != 0)
@@ -1074,19 +1080,19 @@ icmp6_print(netdissect_options *ndo,
 
        switch (icmp6_type) {
        case ICMP6_DST_UNREACH:
-               ND_TCHECK(oip->ip6_dst);
+               ND_TCHECK_16(oip->ip6_dst);
                 ND_PRINT(", %s", tok2str(icmp6_dst_unreach_code_values,"unknown unreach code (%u)",icmp6_code));
                switch (icmp6_code) {
 
                case ICMP6_DST_UNREACH_NOROUTE: /* fall through */
                case ICMP6_DST_UNREACH_ADMIN:
                case ICMP6_DST_UNREACH_ADDR:
-                        ND_PRINT(" %s",ip6addr_string(ndo, &oip->ip6_dst));
+                        ND_PRINT(" %s",ip6addr_string(ndo, oip->ip6_dst));
                         break;
                case ICMP6_DST_UNREACH_BEYONDSCOPE:
                        ND_PRINT(" %s, source address %s",
-                              ip6addr_string(ndo, &oip->ip6_dst),
-                                  ip6addr_string(ndo, &oip->ip6_src));
+                              ip6addr_string(ndo, oip->ip6_dst),
+                                  ip6addr_string(ndo, oip->ip6_src));
                        break;
                case ICMP6_DST_UNREACH_NOPORT:
                        if ((ouh = get_upperlayer(ndo, (const u_char *)oip, &prot))
@@ -1097,17 +1103,17 @@ icmp6_print(netdissect_options *ndo,
                        switch (prot) {
                        case IPPROTO_TCP:
                                ND_PRINT(", %s tcp port %s",
-                                       ip6addr_string(ndo, &oip->ip6_dst),
+                                       ip6addr_string(ndo, oip->ip6_dst),
                                           tcpport_string(ndo, dport));
                                break;
                        case IPPROTO_UDP:
                                ND_PRINT(", %s udp port %s",
-                                       ip6addr_string(ndo, &oip->ip6_dst),
+                                       ip6addr_string(ndo, oip->ip6_dst),
                                           udpport_string(ndo, dport));
                                break;
                        default:
                                ND_PRINT(", %s protocol %u port %u unreachable",
-                                       ip6addr_string(ndo, &oip->ip6_dst),
+                                       ip6addr_string(ndo, oip->ip6_dst),
                                           prot, dport);
                                break;
                        }
@@ -1125,11 +1131,11 @@ icmp6_print(netdissect_options *ndo,
                ND_PRINT(", mtu %u", EXTRACT_BE_U_4(dp->icmp6_mtu));
                break;
        case ICMP6_TIME_EXCEEDED:
-               ND_TCHECK(oip->ip6_dst);
+               ND_TCHECK_16(oip->ip6_dst);
                switch (icmp6_code) {
                case ICMP6_TIME_EXCEED_TRANSIT:
                        ND_PRINT(" for %s",
-                                  ip6addr_string(ndo, &oip->ip6_dst));
+                                  ip6addr_string(ndo, oip->ip6_dst));
                        break;
                case ICMP6_TIME_EXCEED_REASSEMBLY:
                        ND_PRINT(" (reassembly)");
@@ -1140,7 +1146,7 @@ icmp6_print(netdissect_options *ndo,
                }
                break;
        case ICMP6_PARAM_PROB:
-               ND_TCHECK(oip->ip6_dst);
+               ND_TCHECK_16(oip->ip6_dst);
                switch (icmp6_code) {
                case ICMP6_PARAMPROB_HEADER:
                         ND_PRINT(", erroneous - octet %u", EXTRACT_BE_U_4(dp->icmp6_pptr));
@@ -1181,8 +1187,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:
@@ -1191,9 +1198,9 @@ icmp6_print(netdissect_options *ndo,
                        const struct nd_router_advert *p;
 
                        p = (const struct nd_router_advert *)dp;
-                       ND_TCHECK(p->nd_ra_retransmit);
+                       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,20 +1208,22 @@ 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:
            {
                const struct nd_neighbor_solicit *p;
                p = (const struct nd_neighbor_solicit *)dp;
-               ND_TCHECK(p->nd_ns_target);
-               ND_PRINT(", who has %s", ip6addr_string(ndo, &p->nd_ns_target));
+               ND_TCHECK_16(p->nd_ns_target);
+               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;
@@ -1223,36 +1232,40 @@ icmp6_print(netdissect_options *ndo,
                const struct nd_neighbor_advert *p;
 
                p = (const struct nd_neighbor_advert *)dp;
-               ND_TCHECK(p->nd_na_target);
+               ND_TCHECK_16(p->nd_na_target);
                ND_PRINT(", tgt is %s",
-                          ip6addr_string(ndo, &p->nd_na_target));
+                          ip6addr_string(ndo, p->nd_na_target));
                if (ndo->ndo_vflag) {
                         ND_PRINT(", Flags [%s]",
                                   bittok2str(icmp6_nd_na_flag_values,
                                              "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
                }
            }
                break;
        case ND_REDIRECT:
-#define RDR(i) ((const struct nd_redirect *)(i))
-                         ND_TCHECK(RDR(dp)->nd_rd_dst);
-                         ND_PRINT(", %s", ip6addr_string(ndo, &RDR(dp)->nd_rd_dst));
-               ND_TCHECK(RDR(dp)->nd_rd_target);
-               ND_PRINT(" to %s",
-                          ip6addr_string(ndo, &RDR(dp)->nd_rd_target));
+           {
+               const struct nd_redirect *p;
+
+               p = (const struct nd_redirect *)dp;
+               ND_TCHECK_16(p->nd_rd_dst);
+               ND_PRINT(", %s", ip6addr_string(ndo, p->nd_rd_dst));
+               ND_TCHECK_16(p->nd_rd_target);
+               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
                }
+           }
                break;
-#undef REDIRECTLEN
-#undef RDR
        case ICMP6_ROUTER_RENUMBERING:
                icmp6_rrenum_print(ndo, bp, ep);
                break;
@@ -1268,21 +1281,22 @@ icmp6_print(netdissect_options *ndo,
                break;
        case ICMP6_MOBILEPREFIX_SOLICIT: /* fall through */
        case ICMP6_HADISCOV_REQUEST:
-                ND_TCHECK(dp->icmp6_data16[0]);
-                ND_PRINT(", id 0x%04x", EXTRACT_BE_U_2(&dp->icmp6_data16[0]));
+                ND_TCHECK_2(dp->icmp6_data16[0]);
+                ND_PRINT(", id 0x%04x", EXTRACT_BE_U_2(dp->icmp6_data16[0]));
                 break;
        case ICMP6_HADISCOV_REPLY:
                if (ndo->ndo_vflag) {
-                       const struct in6_addr *in6;
                        const u_char *cp;
+                       const u_char *p;
 
-                       ND_TCHECK(dp->icmp6_data16[0]);
-                       ND_PRINT(", id 0x%04x", EXTRACT_BE_U_2(&dp->icmp6_data16[0]));
+                       ND_TCHECK_2(dp->icmp6_data16[0]);
+                       ND_PRINT(", id 0x%04x", EXTRACT_BE_U_2(dp->icmp6_data16[0]));
                        cp = (const u_char *)dp + length;
-                       in6 = (const struct in6_addr *)(dp + 1);
-                       for (; (const u_char *)in6 < cp; in6++) {
-                               ND_TCHECK_SIZE(in6);
-                               ND_PRINT(", %s", ip6addr_string(ndo, in6));
+                       p = (const u_char *)(dp + 1);
+                       while (p < cp) {
+                               ND_TCHECK_16(p);
+                               ND_PRINT(", %s", ip6addr_string(ndo, p));
+                               p += 16;
                        }
                }
                break;
@@ -1301,8 +1315,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:
@@ -1319,7 +1334,7 @@ icmp6_print(netdissect_options *ndo,
                 ND_PRINT(", length %u", length);
        return;
 trunc:
-       ND_PRINT("[|icmp6]");
+       nd_print_trunc(ndo);
 }
 
 static const struct udphdr *
@@ -1337,7 +1352,7 @@ get_upperlayer(netdissect_options *ndo, const u_char *bp, u_int *prot)
        /* 'ep' points to the end of available data. */
        ep = ndo->ndo_snapend;
 
-       if (!ND_TTEST(ip6->ip6_nxt))
+       if (!ND_TTEST_1(ip6->ip6_nxt))
                return NULL;
 
        nh = EXTRACT_U_1(ip6->ip6_nxt);
@@ -1350,7 +1365,7 @@ get_upperlayer(netdissect_options *ndo, const u_char *bp, u_int *prot)
                case IPPROTO_UDP:
                case IPPROTO_TCP:
                        uh = (const struct udphdr *)bp;
-                       if (ND_TTEST(uh->uh_dport)) {
+                       if (ND_TTEST_2(uh->uh_dport)) {
                                *prot = nh;
                                return(uh);
                        }
@@ -1362,7 +1377,7 @@ get_upperlayer(netdissect_options *ndo, const u_char *bp, u_int *prot)
                case IPPROTO_DSTOPTS:
                case IPPROTO_ROUTING:
                        hbh = (const struct ip6_hbh *)bp;
-                       if (!ND_TTEST(hbh->ip6h_len))
+                       if (!ND_TTEST_1(hbh->ip6h_len))
                                return(NULL);
                        nh = EXTRACT_U_1(hbh->ip6h_nxt);
                        hlen = (EXTRACT_U_1(hbh->ip6h_len) + 1) << 3;
@@ -1370,7 +1385,7 @@ get_upperlayer(netdissect_options *ndo, const u_char *bp, u_int *prot)
 
                case IPPROTO_FRAGMENT: /* this should be odd, but try anyway */
                        fragh = (const struct ip6_frag *)bp;
-                       if (!ND_TTEST(fragh->ip6f_offlg))
+                       if (!ND_TTEST_2(fragh->ip6f_offlg))
                                return(NULL);
                        /* fragments with non-zero offset are meaningless */
                        if ((EXTRACT_BE_U_2(fragh->ip6f_offlg) & IP6F_OFF_MASK) != 0)
@@ -1381,7 +1396,7 @@ get_upperlayer(netdissect_options *ndo, const u_char *bp, u_int *prot)
 
                case IPPROTO_AH:
                        ah = (const struct ah *)bp;
-                       if (!ND_TTEST(ah->ah_len))
+                       if (!ND_TTEST_1(ah->ah_len))
                                return(NULL);
                        nh = EXTRACT_U_1(ah->ah_nxt);
                        hlen = (EXTRACT_U_1(ah->ah_len) + 2) << 2;
@@ -1396,7 +1411,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;
@@ -1410,12 +1425,9 @@ icmp6_opt_print(netdissect_options *ndo, const u_char *bp, int resid)
        const struct nd_opt_route_info *opri;
        const u_char *cp, *ep, *domp;
        struct in6_addr in6;
-       const struct in6_addr *in6p;
        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;
@@ -1423,9 +1435,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)
@@ -1450,9 +1462,9 @@ icmp6_opt_print(netdissect_options *ndo, const u_char *bp, int resid)
                        break;
                case ND_OPT_PREFIX_INFORMATION:
                        opp = (const struct nd_opt_prefix_info *)op;
-                       ND_TCHECK(opp->nd_opt_pi_prefix);
+                       ND_TCHECK_16(opp->nd_opt_pi_prefix);
                         ND_PRINT("%s/%u%s, Flags [%s], valid time %s",
-                                  ip6addr_string(ndo, &opp->nd_opt_pi_prefix),
+                                  ip6addr_string(ndo, opp->nd_opt_pi_prefix),
                                   EXTRACT_U_1(opp->nd_opt_pi_prefix_len),
                                   (opt_len != 4) ? "badlen" : "",
                                   bittok2str(icmp6_opt_pi_flag_values, "none", EXTRACT_U_1(opp->nd_opt_pi_flags_reserved)),
@@ -1465,7 +1477,7 @@ icmp6_opt_print(netdissect_options *ndo, const u_char *bp, int resid)
                        break;
                case ND_OPT_MTU:
                        opm = (const struct nd_opt_mtu *)op;
-                       ND_TCHECK(opm->nd_opt_mtu_mtu);
+                       ND_TCHECK_4(opm->nd_opt_mtu_mtu);
                        ND_PRINT(" %u%s",
                                EXTRACT_BE_U_4(opm->nd_opt_mtu_mtu),
                                (opt_len != 1) ? "bad option length" : "" );
@@ -1476,9 +1488,9 @@ icmp6_opt_print(netdissect_options *ndo, const u_char *bp, int resid)
                        ND_PRINT(" lifetime %us,",
                                   EXTRACT_BE_U_4(oprd->nd_opt_rdnss_lifetime));
                        for (i = 0; i < l; i++) {
-                               ND_TCHECK(oprd->nd_opt_rdnss_addr[i]);
+                               ND_TCHECK_16(oprd->nd_opt_rdnss_addr[i]);
                                ND_PRINT(" addr: %s",
-                                          ip6addr_string(ndo, &oprd->nd_opt_rdnss_addr[i]));
+                                          ip6addr_string(ndo, oprd->nd_opt_rdnss_addr[i]));
                        }
                        break;
                case ND_OPT_DNSSL:
@@ -1489,42 +1501,41 @@ 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;
                case ND_OPT_ADVINTERVAL:
                        opa = (const struct nd_opt_advinterval *)op;
-                       ND_TCHECK(opa->nd_opt_adv_interval);
+                       ND_TCHECK_4(opa->nd_opt_adv_interval);
                        ND_PRINT(" %ums", EXTRACT_BE_U_4(opa->nd_opt_adv_interval));
                        break;
                 case ND_OPT_HOMEAGENT_INFO:
                        oph = (const struct nd_opt_homeagent_info *)op;
-                       ND_TCHECK(oph->nd_opt_hai_lifetime);
+                       ND_TCHECK_2(oph->nd_opt_hai_lifetime);
                        ND_PRINT(" preference %u, lifetime %u",
                                   EXTRACT_BE_U_2(oph->nd_opt_hai_preference),
                                   EXTRACT_BE_U_2(oph->nd_opt_hai_lifetime));
                        break;
                case ND_OPT_ROUTE_INFO:
                        opri = (const struct nd_opt_route_info *)op;
-                       ND_TCHECK(opri->nd_opt_rti_lifetime);
+                       ND_TCHECK_4(opri->nd_opt_rti_lifetime);
                        memset(&in6, 0, sizeof(in6));
-                       in6p = (const struct in6_addr *)(opri + 1);
                        switch (opt_len) {
                        case 1:
                                break;
                        case 2:
-                               ND_TCHECK_8(in6p);
+                               ND_TCHECK_8(opri + 1);
                                memcpy(&in6, opri + 1, 8);
                                break;
                        case 3:
-                               ND_TCHECK_SIZE(in6p);
-                               memcpy(&in6, opri + 1, sizeof(in6));
+                               ND_TCHECK_16(opri + 1);
+                               memcpy(&in6, opri + 1, 16);
                                break;
                        default:
                                goto trunc;
                        }
-                       ND_PRINT(" %s/%u", ip6addr_string(ndo, &in6),
+                       ND_PRINT(" %s/%u", ip6addr_string(ndo, (const u_char *)&in6),
                                   EXTRACT_U_1(opri->nd_opt_rti_prefixlen));
                        ND_PRINT(", pref=%s", get_rtpref(EXTRACT_U_1(opri->nd_opt_rti_flags)));
                        ND_PRINT(", lifetime=%s",
@@ -1533,7 +1544,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;
                }
@@ -1544,12 +1555,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
@@ -1565,7 +1574,7 @@ mld6_print(netdissect_options *ndo, const u_char *bp)
                return;
 
        ND_PRINT("max resp delay: %u ", EXTRACT_BE_U_2(mp->mld6_maxdelay));
-       ND_PRINT("addr: %s", ip6addr_string(ndo, &mp->mld6_addr));
+       ND_PRINT("addr: %s", ip6addr_string(ndo, mp->mld6_addr));
 }
 
 static void
@@ -1581,8 +1590,8 @@ mldv2_report_print(netdissect_options *ndo, const u_char *bp, u_int len)
             return;
     }
 
-    ND_TCHECK(icp->icmp6_data16[1]);
-    ngroups = EXTRACT_BE_U_2(&icp->icmp6_data16[1]);
+    ND_TCHECK_2(icp->icmp6_data16[1]);
+    ngroups = EXTRACT_BE_U_2(icp->icmp6_data16[1]);
     ND_PRINT(", %u group record(s)", ngroups);
     if (ndo->ndo_vflag > 0) {
        /* Print the group records */
@@ -1593,13 +1602,13 @@ mldv2_report_print(netdissect_options *ndo, const u_char *bp, u_int len)
                     ND_PRINT(" [invalid number of groups]");
                     return;
            }
-            ND_TCHECK_LEN(bp + 4 + group, sizeof(struct in6_addr));
+            ND_TCHECK_LEN(bp + 4 + group, sizeof(nd_ipv6));
             ND_PRINT(" [gaddr %s", ip6addr_string(ndo, bp + group + 4));
            ND_PRINT(" %s", tok2str(mldv2report2str, " [v2-report-#%u]",
                                          EXTRACT_U_1(bp + group)));
             nsrcs = EXTRACT_BE_U_2(bp + group + 2);
            /* Check the number of sources and print them */
-           if (len < group + 20 + (nsrcs * sizeof(struct in6_addr))) {
+           if (len < group + 20 + (nsrcs * sizeof(nd_ipv6))) {
                     ND_PRINT(" [invalid number of sources %u]", nsrcs);
                     return;
            }
@@ -1609,20 +1618,20 @@ mldv2_report_print(netdissect_options *ndo, const u_char *bp, u_int len)
                /* Print the sources */
                     ND_PRINT(" {");
                 for (j = 0; j < nsrcs; j++) {
-                    ND_TCHECK_LEN(bp + group + 20 + (j * sizeof(struct in6_addr)),
-                                  sizeof(struct in6_addr));
-                   ND_PRINT(" %s", ip6addr_string(ndo, bp + group + 20 + (j * sizeof(struct in6_addr))));
+                    ND_TCHECK_LEN(bp + group + 20 + (j * sizeof(nd_ipv6)),
+                                  sizeof(nd_ipv6));
+                   ND_PRINT(" %s", ip6addr_string(ndo, bp + group + 20 + (j * sizeof(nd_ipv6))));
                }
                 ND_PRINT(" }");
             }
            /* Next group record */
-            group += 20 + nsrcs * sizeof(struct in6_addr);
+            group += 20 + nsrcs * sizeof(nd_ipv6);
            ND_PRINT("]");
         }
     }
     return;
 trunc:
-    ND_PRINT("[|icmp6]");
+    nd_print_trunc(ndo);
     return;
 }
 
@@ -1640,8 +1649,8 @@ mldv2_query_print(netdissect_options *ndo, const u_char *bp, u_int len)
         ND_PRINT(" [invalid len %u]", len);
        return;
     }
-    ND_TCHECK(icp->icmp6_data16[0]);
-    mrc = EXTRACT_BE_U_2(&icp->icmp6_data16[0]);
+    ND_TCHECK_2(icp->icmp6_data16[0]);
+    mrc = EXTRACT_BE_U_2(icp->icmp6_data16[0]);
     if (mrc < 32768) {
        mrt = mrc;
     } else {
@@ -1650,7 +1659,7 @@ mldv2_query_print(netdissect_options *ndo, const u_char *bp, u_int len)
     if (ndo->ndo_vflag) {
             ND_PRINT(" [max resp delay=%u]", mrt);
     }
-    ND_TCHECK_LEN(bp + 8, sizeof(struct in6_addr));
+    ND_TCHECK_LEN(bp + 8, sizeof(nd_ipv6));
     ND_PRINT(" [gaddr %s", ip6addr_string(ndo, bp + 8));
 
     if (ndo->ndo_vflag) {
@@ -1673,14 +1682,14 @@ mldv2_query_print(netdissect_options *ndo, const u_char *bp, u_int len)
     ND_TCHECK_2(bp + 26);
     nsrcs = EXTRACT_BE_U_2(bp + 26);
     if (nsrcs > 0) {
-       if (len < 28 + nsrcs * sizeof(struct in6_addr))
+       if (len < 28 + nsrcs * sizeof(nd_ipv6))
            ND_PRINT(" [invalid number of sources]");
        else if (ndo->ndo_vflag > 1) {
            ND_PRINT(" {");
            for (i = 0; i < nsrcs; i++) {
-               ND_TCHECK_LEN(bp + 28 + (i * sizeof(struct in6_addr)),
-                              sizeof(struct in6_addr));
-               ND_PRINT(" %s", ip6addr_string(ndo, bp + 28 + (i * sizeof(struct in6_addr))));
+               ND_TCHECK_LEN(bp + 28 + (i * sizeof(nd_ipv6)),
+                              sizeof(nd_ipv6));
+               ND_PRINT(" %s", ip6addr_string(ndo, bp + 28 + (i * sizeof(nd_ipv6))));
            }
            ND_PRINT(" }");
        } else
@@ -1689,7 +1698,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;
 }
 
@@ -1709,7 +1718,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))
@@ -1808,21 +1817,21 @@ icmp6_nodeinfo_print(netdissect_options *ndo, u_int icmp6len, const u_char *bp,
                        break;
                }
 
+               cp = (const u_char *)(ni6 + 1);
                switch (EXTRACT_U_1(ni6->ni_code)) {
                case ICMP6_NI_SUBJ_IPV6:
-                       if (!ND_TTEST_LEN(dp, sizeof(*ni6) + sizeof(struct in6_addr)))
+                       if (!ND_TTEST_LEN(dp, sizeof(*ni6) + sizeof(nd_ipv6)))
                                break;
-                       if (siz != sizeof(*ni6) + sizeof(struct in6_addr)) {
+                       if (siz != sizeof(*ni6) + sizeof(nd_ipv6)) {
                                if (ndo->ndo_vflag)
                                        ND_PRINT(", invalid subject len");
                                break;
                        }
                        ND_PRINT(", subject=%s",
-                                  ip6addr_string(ndo, ni6 + 1));
+                                  ip6addr_string(ndo, cp));
                        break;
                case ICMP6_NI_SUBJ_FQDN:
                        ND_PRINT(", subject=DNS name");
-                       cp = (const u_char *)(ni6 + 1);
                        if (EXTRACT_U_1(cp) == ep - cp - 1) {
                                /* icmp-name-lookup-03, pascal string */
                                if (ndo->ndo_vflag)
@@ -1830,7 +1839,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("\"");
@@ -1838,15 +1847,15 @@ icmp6_nodeinfo_print(netdissect_options *ndo, u_int icmp6len, const u_char *bp,
                                dnsname_print(ndo, cp, ep);
                        break;
                case ICMP6_NI_SUBJ_IPV4:
-                       if (!ND_TTEST_LEN(dp, sizeof(*ni6) + sizeof(struct in_addr)))
+                       if (!ND_TTEST_LEN(dp, sizeof(*ni6) + sizeof(nd_ipv4)))
                                break;
-                       if (siz != sizeof(*ni6) + sizeof(struct in_addr)) {
+                       if (siz != sizeof(*ni6) + sizeof(nd_ipv4)) {
                                if (ndo->ndo_vflag)
                                        ND_PRINT(", invalid subject len");
                                break;
                        }
                        ND_PRINT(", subject=%s",
-                                  ipaddr_string(ndo, ni6 + 1));
+                                  ipaddr_string(ndo, cp));
                        break;
                default:
                        ND_PRINT(", unknown subject");
@@ -1858,10 +1867,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;
 
@@ -1928,7 +1935,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("\"");
@@ -1943,12 +1950,12 @@ icmp6_nodeinfo_print(netdissect_options *ndo, u_int icmp6len, const u_char *bp,
                        ND_PRINT("node addresses");
                        i = sizeof(*ni6);
                        while (i < siz) {
-                               if (i + sizeof(uint32_t) + sizeof(struct in6_addr) > siz)
+                               if (i + sizeof(uint32_t) + sizeof(nd_ipv6) > siz)
                                        break;
                                ND_PRINT(" %s(%u)",
                                    ip6addr_string(ndo, bp + i + sizeof(uint32_t)),
                                    EXTRACT_BE_U_4(bp + i));
-                               i += sizeof(uint32_t) + sizeof(struct in6_addr);
+                               i += sizeof(uint32_t) + sizeof(nd_ipv6);
                        }
                        i = EXTRACT_BE_U_2(ni6->ni_flags);
                        if (!i)
@@ -1976,7 +1983,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
@@ -1994,7 +2001,7 @@ icmp6_rrenum_print(netdissect_options *ndo, const u_char *bp, const u_char *ep)
        rr6 = (const struct icmp6_router_renum *)bp;
        cp = (const char *)(rr6 + 1);
 
-       ND_TCHECK(rr6->rr_reserved);
+       ND_TCHECK_4(rr6->rr_reserved);
        switch (EXTRACT_U_1(rr6->rr_code)) {
        case ICMP6_ROUTER_RENUMBERING_COMMAND:
                ND_PRINT("router renum: command");
@@ -2036,7 +2043,7 @@ icmp6_rrenum_print(netdissect_options *ndo, const u_char *bp, const u_char *ep)
                match = (const struct rr_pco_match *)cp;
                cp = (const char *)(match + 1);
 
-               ND_TCHECK(match->rpm_prefix);
+               ND_TCHECK_16(match->rpm_prefix);
 
                if (ndo->ndo_vflag > 1)
                        ND_PRINT("\n\t");
@@ -2055,7 +2062,7 @@ icmp6_rrenum_print(netdissect_options *ndo, const u_char *bp, const u_char *ep)
                        ND_PRINT(",min=%u", EXTRACT_U_1(match->rpm_minlen));
                        ND_PRINT(",max=%u", EXTRACT_U_1(match->rpm_maxlen));
                }
-               if (addrtostr6(&match->rpm_prefix, hbuf, sizeof(hbuf)))
+               if (addrtostr6(match->rpm_prefix, hbuf, sizeof(hbuf)))
                        ND_PRINT(",%s/%u", hbuf, EXTRACT_U_1(match->rpm_matchlen));
                else
                        ND_PRINT(",?/%u", EXTRACT_U_1(match->rpm_matchlen));
@@ -2070,7 +2077,7 @@ icmp6_rrenum_print(netdissect_options *ndo, const u_char *bp, const u_char *ep)
                        use = (const struct rr_pco_use *)cp;
                        cp = (const char *)(use + 1);
 
-                       ND_TCHECK(use->rpu_prefix);
+                       ND_TCHECK_16(use->rpu_prefix);
 
                        if (ndo->ndo_vflag > 1)
                                ND_PRINT("\n\t");
@@ -2098,7 +2105,7 @@ icmp6_rrenum_print(netdissect_options *ndo, const u_char *bp, const u_char *ep)
                                        ND_PRINT("pltime=%u,",
                                                   EXTRACT_BE_U_4(use->rpu_pltime));
                        }
-                       if (addrtostr6(&use->rpu_prefix, hbuf, sizeof(hbuf)))
+                       if (addrtostr6(use->rpu_prefix, hbuf, sizeof(hbuf)))
                                ND_PRINT("%s/%u/%u", hbuf, EXTRACT_U_1(use->rpu_uselen),
                                           EXTRACT_U_1(use->rpu_keeplen));
                        else
@@ -2112,12 +2119,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:
- */