"Fossies" - the Fresh Open Source Software Archive

Member "tcpdump-4.99.1/./print-icmp6.c" (7 Jun 2021, 63904 Bytes) of package /linux/misc/tcpdump-4.99.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "print-icmp6.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 4.99.0_vs_4.99.1.

    1 /*
    2  * Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994
    3  *  The Regents of the University of California.  All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that: (1) source code distributions
    7  * retain the above copyright notice and this paragraph in its entirety, (2)
    8  * distributions including binary code include the above copyright notice and
    9  * this paragraph in its entirety in the documentation or other materials
   10  * provided with the distribution, and (3) all advertising materials mentioning
   11  * features or use of this software display the following acknowledgement:
   12  * ``This product includes software developed by the University of California,
   13  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
   14  * the University nor the names of its contributors may be used to endorse
   15  * or promote products derived from this software without specific prior
   16  * written permission.
   17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
   18  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
   19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
   20  */
   21 
   22 /* \summary: IPv6 Internet Control Message Protocol (ICMPv6) printer */
   23 
   24 #ifdef HAVE_CONFIG_H
   25 #include <config.h>
   26 #endif
   27 
   28 #include "netdissect-stdinc.h"
   29 
   30 #include <stdio.h>
   31 #include <string.h>
   32 
   33 #include "netdissect.h"
   34 #include "addrtoname.h"
   35 #include "addrtostr.h"
   36 #include "extract.h"
   37 
   38 #include "ip6.h"
   39 #include "ipproto.h"
   40 
   41 #include "udp.h"
   42 #include "ah.h"
   43 
   44 /*  NetBSD: icmp6.h,v 1.13 2000/08/03 16:30:37 itojun Exp   */
   45 /*  $KAME: icmp6.h,v 1.22 2000/08/03 15:25:16 jinmei Exp $  */
   46 
   47 /*
   48  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
   49  * All rights reserved.
   50  *
   51  * Redistribution and use in source and binary forms, with or without
   52  * modification, are permitted provided that the following conditions
   53  * are met:
   54  * 1. Redistributions of source code must retain the above copyright
   55  *    notice, this list of conditions and the following disclaimer.
   56  * 2. Redistributions in binary form must reproduce the above copyright
   57  *    notice, this list of conditions and the following disclaimer in the
   58  *    documentation and/or other materials provided with the distribution.
   59  * 3. Neither the name of the project nor the names of its contributors
   60  *    may be used to endorse or promote products derived from this software
   61  *    without specific prior written permission.
   62  *
   63  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
   64  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   65  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   66  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
   67  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   68  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   69  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   70  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   71  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   72  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   73  * SUCH DAMAGE.
   74  */
   75 
   76 struct icmp6_hdr {
   77     nd_uint8_t  icmp6_type; /* type field */
   78     nd_uint8_t  icmp6_code; /* code field */
   79     nd_uint16_t icmp6_cksum;    /* checksum field */
   80     union {
   81         nd_uint32_t icmp6_un_data32[1]; /* type-specific field */
   82         nd_uint16_t icmp6_un_data16[2]; /* type-specific field */
   83         nd_uint8_t  icmp6_un_data8[4];  /* type-specific field */
   84         nd_byte     icmp6_un_data[1];   /* type-specific field */
   85     } icmp6_dataun;
   86 };
   87 
   88 #define icmp6_data32    icmp6_dataun.icmp6_un_data32
   89 #define icmp6_data16    icmp6_dataun.icmp6_un_data16
   90 #define icmp6_data8 icmp6_dataun.icmp6_un_data8
   91 #define icmp6_data  icmp6_dataun.icmp6_un_data
   92 #define icmp6_pptr  icmp6_data32[0]     /* parameter prob */
   93 #define icmp6_mtu   icmp6_data32[0]     /* packet too big */
   94 #define icmp6_id    icmp6_data16[0]     /* echo request/reply */
   95 #define icmp6_seq   icmp6_data16[1]     /* echo request/reply */
   96 #define icmp6_maxdelay  icmp6_data16[0]     /* mcast group membership */
   97 
   98 #define ICMP6_DST_UNREACH       1   /* dest unreachable, codes: */
   99 #define ICMP6_PACKET_TOO_BIG        2   /* packet too big */
  100 #define ICMP6_TIME_EXCEEDED     3   /* time exceeded, code: */
  101 #define ICMP6_PARAM_PROB        4   /* ip6 header bad */
  102 
  103 #define ICMP6_ECHO_REQUEST      128 /* echo service */
  104 #define ICMP6_ECHO_REPLY        129 /* echo reply */
  105 #define ICMP6_MEMBERSHIP_QUERY      130 /* group membership query */
  106 #define MLD6_LISTENER_QUERY     130     /* multicast listener query */
  107 #define ICMP6_MEMBERSHIP_REPORT     131 /* group membership report */
  108 #define MLD6_LISTENER_REPORT        131 /* multicast listener report */
  109 #define ICMP6_MEMBERSHIP_REDUCTION  132 /* group membership termination */
  110 #define MLD6_LISTENER_DONE      132 /* multicast listener done */
  111 
  112 #define ND_ROUTER_SOLICIT       133 /* router solicitation */
  113 #define ND_ROUTER_ADVERT        134 /* router advertisement */
  114 #define ND_NEIGHBOR_SOLICIT     135 /* neighbor solicitation */
  115 #define ND_NEIGHBOR_ADVERT      136 /* neighbor advertisement */
  116 #define ND_REDIRECT         137 /* redirect */
  117 
  118 #define ICMP6_ROUTER_RENUMBERING    138 /* router renumbering */
  119 
  120 #define ICMP6_WRUREQUEST        139 /* who are you request */
  121 #define ICMP6_WRUREPLY          140 /* who are you reply */
  122 #define ICMP6_FQDN_QUERY        139 /* FQDN query */
  123 #define ICMP6_FQDN_REPLY        140 /* FQDN reply */
  124 #define ICMP6_NI_QUERY          139 /* node information request - RFC 4620 */
  125 #define ICMP6_NI_REPLY          140 /* node information reply - RFC 4620 */
  126 #define IND_SOLICIT         141 /* inverse neighbor solicitation */
  127 #define IND_ADVERT          142 /* inverse neighbor advertisement */
  128 
  129 #define ICMP6_V2_MEMBERSHIP_REPORT  143 /* v2 membership report */
  130 #define MLDV2_LISTENER_REPORT       143 /* v2 multicast listener report */
  131 #define ICMP6_HADISCOV_REQUEST      144
  132 #define ICMP6_HADISCOV_REPLY        145
  133 #define ICMP6_MOBILEPREFIX_SOLICIT  146
  134 #define ICMP6_MOBILEPREFIX_ADVERT   147
  135 
  136 #define MLD6_MTRACE_RESP        200 /* mtrace response(to sender) */
  137 #define MLD6_MTRACE         201 /* mtrace messages */
  138 
  139 #define ICMP6_MAXTYPE           201
  140 
  141 #define ICMP6_DST_UNREACH_NOROUTE   0   /* no route to destination */
  142 #define ICMP6_DST_UNREACH_ADMIN     1   /* administratively prohibited */
  143 #define ICMP6_DST_UNREACH_NOTNEIGHBOR   2   /* not a neighbor(obsolete) */
  144 #define ICMP6_DST_UNREACH_BEYONDSCOPE   2   /* beyond scope of source address */
  145 #define ICMP6_DST_UNREACH_ADDR      3   /* address unreachable */
  146 #define ICMP6_DST_UNREACH_NOPORT    4   /* port unreachable */
  147 
  148 #define ICMP6_TIME_EXCEED_TRANSIT   0   /* ttl==0 in transit */
  149 #define ICMP6_TIME_EXCEED_REASSEMBLY    1   /* ttl==0 in reass */
  150 
  151 #define ICMP6_PARAMPROB_HEADER      0   /* erroneous header field */
  152 #define ICMP6_PARAMPROB_NEXTHEADER  1   /* unrecognized next header */
  153 #define ICMP6_PARAMPROB_OPTION      2   /* unrecognized option */
  154 #define ICMP6_PARAMPROB_FRAGHDRCHAIN    3   /* incomplete header chain */
  155 
  156 #define ICMP6_INFOMSG_MASK      0x80    /* all informational messages */
  157 
  158 #define ICMP6_NI_SUBJ_IPV6  0   /* Query Subject is an IPv6 address */
  159 #define ICMP6_NI_SUBJ_FQDN  1   /* Query Subject is a Domain name */
  160 #define ICMP6_NI_SUBJ_IPV4  2   /* Query Subject is an IPv4 address */
  161 
  162 #define ICMP6_NI_SUCCESS    0   /* node information successful reply */
  163 #define ICMP6_NI_REFUSED    1   /* node information request is refused */
  164 #define ICMP6_NI_UNKNOWN    2   /* unknown Qtype */
  165 
  166 #define ICMP6_ROUTER_RENUMBERING_COMMAND  0 /* rr command */
  167 #define ICMP6_ROUTER_RENUMBERING_RESULT   1 /* rr result */
  168 #define ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET   255 /* rr seq num reset */
  169 
  170 /* Used in kernel only */
  171 #define ND_REDIRECT_ONLINK  0   /* redirect to an on-link node */
  172 #define ND_REDIRECT_ROUTER  1   /* redirect to a better router */
  173 
  174 /*
  175  * Multicast Listener Discovery
  176  */
  177 struct mld6_hdr {
  178     struct icmp6_hdr    mld6_hdr;
  179     nd_ipv6         mld6_addr; /* multicast address */
  180 };
  181 
  182 #define mld6_type   mld6_hdr.icmp6_type
  183 #define mld6_code   mld6_hdr.icmp6_code
  184 #define mld6_cksum  mld6_hdr.icmp6_cksum
  185 #define mld6_maxdelay   mld6_hdr.icmp6_data16[0]
  186 #define mld6_reserved   mld6_hdr.icmp6_data16[1]
  187 
  188 #define MLD_MINLEN  24
  189 #define MLDV2_MINLEN    28
  190 
  191 /*
  192  * Neighbor Discovery
  193  */
  194 
  195 struct nd_router_solicit {  /* router solicitation */
  196     struct icmp6_hdr    nd_rs_hdr;
  197     /* could be followed by options */
  198 };
  199 
  200 #define nd_rs_type  nd_rs_hdr.icmp6_type
  201 #define nd_rs_code  nd_rs_hdr.icmp6_code
  202 #define nd_rs_cksum nd_rs_hdr.icmp6_cksum
  203 #define nd_rs_reserved  nd_rs_hdr.icmp6_data32[0]
  204 
  205 struct nd_router_advert {   /* router advertisement */
  206     struct icmp6_hdr    nd_ra_hdr;
  207     nd_uint32_t     nd_ra_reachable;    /* reachable time */
  208     nd_uint32_t     nd_ra_retransmit;   /* retransmit timer */
  209     /* could be followed by options */
  210 };
  211 
  212 #define nd_ra_type      nd_ra_hdr.icmp6_type
  213 #define nd_ra_code      nd_ra_hdr.icmp6_code
  214 #define nd_ra_cksum     nd_ra_hdr.icmp6_cksum
  215 #define nd_ra_curhoplimit   nd_ra_hdr.icmp6_data8[0]
  216 #define nd_ra_flags_reserved    nd_ra_hdr.icmp6_data8[1]
  217 #define ND_RA_FLAG_MANAGED  0x80
  218 #define ND_RA_FLAG_OTHER    0x40
  219 #define ND_RA_FLAG_HOME_AGENT   0x20
  220 #define ND_RA_FLAG_IPV6ONLY 0x02
  221 
  222 /*
  223  * Router preference values based on draft-draves-ipngwg-router-selection-01.
  224  * These are non-standard definitions.
  225  */
  226 #define ND_RA_FLAG_RTPREF_MASK  0x18 /* 00011000 */
  227 
  228 #define ND_RA_FLAG_RTPREF_HIGH  0x08 /* 00001000 */
  229 #define ND_RA_FLAG_RTPREF_MEDIUM    0x00 /* 00000000 */
  230 #define ND_RA_FLAG_RTPREF_LOW   0x18 /* 00011000 */
  231 #define ND_RA_FLAG_RTPREF_RSV   0x10 /* 00010000 */
  232 
  233 #define nd_ra_router_lifetime   nd_ra_hdr.icmp6_data16[1]
  234 
  235 struct nd_neighbor_solicit {    /* neighbor solicitation */
  236     struct icmp6_hdr    nd_ns_hdr;
  237     nd_ipv6         nd_ns_target;   /*target address */
  238     /* could be followed by options */
  239 };
  240 
  241 #define nd_ns_type      nd_ns_hdr.icmp6_type
  242 #define nd_ns_code      nd_ns_hdr.icmp6_code
  243 #define nd_ns_cksum     nd_ns_hdr.icmp6_cksum
  244 #define nd_ns_reserved      nd_ns_hdr.icmp6_data32[0]
  245 
  246 struct nd_neighbor_advert { /* neighbor advertisement */
  247     struct icmp6_hdr    nd_na_hdr;
  248     nd_ipv6         nd_na_target;   /* target address */
  249     /* could be followed by options */
  250 };
  251 
  252 #define nd_na_type      nd_na_hdr.icmp6_type
  253 #define nd_na_code      nd_na_hdr.icmp6_code
  254 #define nd_na_cksum     nd_na_hdr.icmp6_cksum
  255 #define nd_na_flags_reserved    nd_na_hdr.icmp6_data32[0]
  256 
  257 #define ND_NA_FLAG_ROUTER       0x80000000
  258 #define ND_NA_FLAG_SOLICITED        0x40000000
  259 #define ND_NA_FLAG_OVERRIDE     0x20000000
  260 
  261 struct nd_redirect {        /* redirect */
  262     struct icmp6_hdr    nd_rd_hdr;
  263     nd_ipv6         nd_rd_target;   /* target address */
  264     nd_ipv6         nd_rd_dst;  /* destination address */
  265     /* could be followed by options */
  266 };
  267 
  268 #define nd_rd_type      nd_rd_hdr.icmp6_type
  269 #define nd_rd_code      nd_rd_hdr.icmp6_code
  270 #define nd_rd_cksum     nd_rd_hdr.icmp6_cksum
  271 #define nd_rd_reserved      nd_rd_hdr.icmp6_data32[0]
  272 
  273 struct nd_opt_hdr {     /* Neighbor discovery option header */
  274     nd_uint8_t  nd_opt_type;
  275     nd_uint8_t  nd_opt_len;
  276     /* followed by option specific data*/
  277 };
  278 
  279 #define ND_OPT_SOURCE_LINKADDR      1
  280 #define ND_OPT_TARGET_LINKADDR      2
  281 #define ND_OPT_PREFIX_INFORMATION   3
  282 #define ND_OPT_REDIRECTED_HEADER    4
  283 #define ND_OPT_MTU          5
  284 #define ND_OPT_ADVINTERVAL      7
  285 #define ND_OPT_HOMEAGENT_INFO       8
  286 #define ND_OPT_ROUTE_INFO       24  /* RFC4191 */
  287 #define ND_OPT_RDNSS            25
  288 #define ND_OPT_DNSSL            31
  289 
  290 struct nd_opt_prefix_info { /* prefix information */
  291     nd_uint8_t  nd_opt_pi_type;
  292     nd_uint8_t  nd_opt_pi_len;
  293     nd_uint8_t  nd_opt_pi_prefix_len;
  294     nd_uint8_t  nd_opt_pi_flags_reserved;
  295     nd_uint32_t nd_opt_pi_valid_time;
  296     nd_uint32_t nd_opt_pi_preferred_time;
  297     nd_uint32_t nd_opt_pi_reserved2;
  298     nd_ipv6     nd_opt_pi_prefix;
  299 };
  300 
  301 #define ND_OPT_PI_FLAG_ONLINK       0x80
  302 #define ND_OPT_PI_FLAG_AUTO     0x40
  303 #define ND_OPT_PI_FLAG_ROUTER       0x20    /*2292bis*/
  304 
  305 struct nd_opt_rd_hdr {         /* redirected header */
  306     nd_uint8_t  nd_opt_rh_type;
  307     nd_uint8_t  nd_opt_rh_len;
  308     nd_uint16_t nd_opt_rh_reserved1;
  309     nd_uint32_t nd_opt_rh_reserved2;
  310     /* followed by IP header and data */
  311 };
  312 
  313 struct nd_opt_mtu {     /* MTU option */
  314     nd_uint8_t  nd_opt_mtu_type;
  315     nd_uint8_t  nd_opt_mtu_len;
  316     nd_uint16_t nd_opt_mtu_reserved;
  317     nd_uint32_t nd_opt_mtu_mtu;
  318 };
  319 
  320 struct nd_opt_rdnss {       /* RDNSS RFC 6106 5.1 */
  321     nd_uint8_t  nd_opt_rdnss_type;
  322     nd_uint8_t  nd_opt_rdnss_len;
  323     nd_uint16_t nd_opt_rdnss_reserved;
  324     nd_uint32_t nd_opt_rdnss_lifetime;
  325     nd_ipv6     nd_opt_rdnss_addr[1];   /* variable-length */
  326 };
  327 
  328 struct nd_opt_dnssl {       /* DNSSL RFC 6106 5.2 */
  329     nd_uint8_t  nd_opt_dnssl_type;
  330     nd_uint8_t  nd_opt_dnssl_len;
  331     nd_uint16_t nd_opt_dnssl_reserved;
  332     nd_uint32_t nd_opt_dnssl_lifetime;
  333     /* followed by list of DNS search domains, variable-length */
  334 };
  335 
  336 struct nd_opt_advinterval { /* Advertisement interval option */
  337     nd_uint8_t  nd_opt_adv_type;
  338     nd_uint8_t  nd_opt_adv_len;
  339     nd_uint16_t nd_opt_adv_reserved;
  340     nd_uint32_t nd_opt_adv_interval;
  341 };
  342 
  343 struct nd_opt_homeagent_info {  /* Home Agent info */
  344     nd_uint8_t  nd_opt_hai_type;
  345     nd_uint8_t  nd_opt_hai_len;
  346     nd_uint16_t nd_opt_hai_reserved;
  347     nd_uint16_t nd_opt_hai_preference;
  348     nd_uint16_t nd_opt_hai_lifetime;
  349 };
  350 
  351 struct nd_opt_route_info {  /* route info */
  352     nd_uint8_t  nd_opt_rti_type;
  353     nd_uint8_t  nd_opt_rti_len;
  354     nd_uint8_t  nd_opt_rti_prefixlen;
  355     nd_uint8_t  nd_opt_rti_flags;
  356     nd_uint32_t nd_opt_rti_lifetime;
  357     /* prefix follows */
  358 };
  359 
  360 /*
  361  * icmp6 namelookup
  362  */
  363 
  364 struct icmp6_namelookup {
  365     struct icmp6_hdr    icmp6_nl_hdr;
  366     nd_byte         icmp6_nl_nonce[8];
  367     nd_int32_t      icmp6_nl_ttl;
  368 #if 0
  369     nd_uint8_t      icmp6_nl_len;
  370     nd_byte         icmp6_nl_name[3];
  371 #endif
  372     /* could be followed by options */
  373 };
  374 
  375 /*
  376  * icmp6 node information
  377  */
  378 struct icmp6_nodeinfo {
  379     struct icmp6_hdr icmp6_ni_hdr;
  380     nd_byte icmp6_ni_nonce[8];
  381     /* could be followed by reply data */
  382 };
  383 
  384 #define ni_type     icmp6_ni_hdr.icmp6_type
  385 #define ni_code     icmp6_ni_hdr.icmp6_code
  386 #define ni_cksum    icmp6_ni_hdr.icmp6_cksum
  387 #define ni_qtype    icmp6_ni_hdr.icmp6_data16[0]
  388 #define ni_flags    icmp6_ni_hdr.icmp6_data16[1]
  389 
  390 #define NI_QTYPE_NOOP       0 /* NOOP  */
  391 #define NI_QTYPE_SUPTYPES   1 /* Supported Qtypes (drafts up to 09) */
  392 #define NI_QTYPE_FQDN       2 /* FQDN (draft 04) */
  393 #define NI_QTYPE_DNSNAME    2 /* DNS Name */
  394 #define NI_QTYPE_NODEADDR   3 /* Node Addresses */
  395 #define NI_QTYPE_IPV4ADDR   4 /* IPv4 Addresses */
  396 
  397 /* network endian */
  398 #define NI_SUPTYPE_FLAG_COMPRESS    ((uint16_t)htons(0x1))
  399 #define NI_FQDN_FLAG_VALIDTTL       ((uint16_t)htons(0x1))
  400 
  401 /* network endian */
  402 #define NI_NODEADDR_FLAG_TRUNCATE   ((uint16_t)htons(0x1))
  403 #define NI_NODEADDR_FLAG_ALL        ((uint16_t)htons(0x2))
  404 #define NI_NODEADDR_FLAG_COMPAT     ((uint16_t)htons(0x4))
  405 #define NI_NODEADDR_FLAG_LINKLOCAL  ((uint16_t)htons(0x8))
  406 #define NI_NODEADDR_FLAG_SITELOCAL  ((uint16_t)htons(0x10))
  407 #define NI_NODEADDR_FLAG_GLOBAL     ((uint16_t)htons(0x20))
  408 #define NI_NODEADDR_FLAG_ANYCAST    ((uint16_t)htons(0x40)) /* just experimental. not in spec */
  409 
  410 struct ni_reply_fqdn {
  411     nd_uint32_t ni_fqdn_ttl;    /* TTL */
  412     nd_uint8_t ni_fqdn_namelen; /* length in octets of the FQDN */
  413     nd_byte ni_fqdn_name[3]; /* XXX: alignment */
  414 };
  415 
  416 /*
  417  * Router Renumbering. as router-renum-08.txt
  418  */
  419 struct icmp6_router_renum { /* router renumbering header */
  420     struct icmp6_hdr    rr_hdr;
  421     nd_uint8_t      rr_segnum;
  422     nd_uint8_t      rr_flags;
  423     nd_uint16_t     rr_maxdelay;
  424     nd_uint32_t     rr_reserved;
  425 };
  426 #define ICMP6_RR_FLAGS_TEST     0x80
  427 #define ICMP6_RR_FLAGS_REQRESULT    0x40
  428 #define ICMP6_RR_FLAGS_FORCEAPPLY   0x20
  429 #define ICMP6_RR_FLAGS_SPECSITE     0x10
  430 #define ICMP6_RR_FLAGS_PREVDONE     0x08
  431 
  432 #define rr_type     rr_hdr.icmp6_type
  433 #define rr_code     rr_hdr.icmp6_code
  434 #define rr_cksum    rr_hdr.icmp6_cksum
  435 #define rr_seqnum   rr_hdr.icmp6_data32[0]
  436 
  437 struct rr_pco_match {       /* match prefix part */
  438     nd_uint8_t      rpm_code;
  439     nd_uint8_t      rpm_len;
  440     nd_uint8_t      rpm_ordinal;
  441     nd_uint8_t      rpm_matchlen;
  442     nd_uint8_t      rpm_minlen;
  443     nd_uint8_t      rpm_maxlen;
  444     nd_uint16_t     rpm_reserved;
  445     nd_ipv6         rpm_prefix;
  446 };
  447 
  448 #define RPM_PCO_ADD     1
  449 #define RPM_PCO_CHANGE      2
  450 #define RPM_PCO_SETGLOBAL   3
  451 #define RPM_PCO_MAX     4
  452 
  453 struct rr_pco_use {     /* use prefix part */
  454     nd_uint8_t  rpu_uselen;
  455     nd_uint8_t  rpu_keeplen;
  456     nd_uint8_t  rpu_ramask;
  457     nd_uint8_t  rpu_raflags;
  458     nd_uint32_t rpu_vltime;
  459     nd_uint32_t rpu_pltime;
  460     nd_uint32_t rpu_flags;
  461     nd_ipv6     rpu_prefix;
  462 };
  463 #define ICMP6_RR_PCOUSE_RAFLAGS_ONLINK  0x80
  464 #define ICMP6_RR_PCOUSE_RAFLAGS_AUTO    0x40
  465 
  466 /* network endian */
  467 #define ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME     ((uint32_t)htonl(0x80000000))
  468 #define ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME     ((uint32_t)htonl(0x40000000))
  469 
  470 struct rr_result {      /* router renumbering result message */
  471     nd_uint16_t rrr_flags;
  472     nd_uint8_t  rrr_ordinal;
  473     nd_uint8_t  rrr_matchedlen;
  474     nd_uint32_t rrr_ifid;
  475     nd_ipv6     rrr_prefix;
  476 };
  477 /* network endian */
  478 #define ICMP6_RR_RESULT_FLAGS_OOB       ((uint16_t)htons(0x0002))
  479 #define ICMP6_RR_RESULT_FLAGS_FORBIDDEN     ((uint16_t)htons(0x0001))
  480 
  481 static const char *get_rtpref(u_int);
  482 static const char *get_lifetime(uint32_t);
  483 static void print_lladdr(netdissect_options *ndo, const u_char *, size_t);
  484 static int icmp6_opt_print(netdissect_options *ndo, const u_char *, int);
  485 static void mld6_print(netdissect_options *ndo, const u_char *);
  486 static void mldv2_report_print(netdissect_options *ndo, const u_char *, u_int);
  487 static void mldv2_query_print(netdissect_options *ndo, const u_char *, u_int);
  488 static const struct udphdr *get_upperlayer(netdissect_options *ndo, const u_char *, u_int *);
  489 static void dnsname_print(netdissect_options *ndo, const u_char *, const u_char *);
  490 static void icmp6_nodeinfo_print(netdissect_options *ndo, u_int, const u_char *, const u_char *);
  491 static void icmp6_rrenum_print(netdissect_options *ndo, const u_char *, const u_char *);
  492 
  493 #ifndef abs
  494 #define abs(a)  ((0 < (a)) ? (a) : -(a))
  495 #endif
  496 
  497 /*
  498  * DIO: Updated to RFC6550, as published in 2012: section 6. (page 30)
  499  */
  500 
  501 #define ND_RPL_MESSAGE 155  /* 0x9B */
  502 
  503 enum ND_RPL_CODE {
  504     ND_RPL_DAG_IS=0x00,
  505     ND_RPL_DAG_IO=0x01,
  506     ND_RPL_DAO   =0x02,
  507     ND_RPL_DAO_ACK=0x03,
  508     ND_RPL_SEC_DAG_IS = 0x80,
  509     ND_RPL_SEC_DAG_IO = 0x81,
  510     ND_RPL_SEC_DAG    = 0x82,
  511     ND_RPL_SEC_DAG_ACK= 0x83,
  512     ND_RPL_SEC_CONSIST= 0x8A
  513 };
  514 
  515 enum ND_RPL_DIO_FLAGS {
  516         ND_RPL_DIO_GROUNDED = 0x80,
  517         ND_RPL_DIO_DATRIG   = 0x40,
  518         ND_RPL_DIO_DASUPPORT= 0x20,
  519         ND_RPL_DIO_RES4     = 0x10,
  520         ND_RPL_DIO_RES3     = 0x08,
  521         ND_RPL_DIO_PRF_MASK = 0x07  /* 3-bit preference */
  522 };
  523 
  524 #define DAGID_LEN 16
  525 
  526 /* section 6 of draft-ietf-roll-rpl-19 */
  527 struct nd_rpl_security {
  528     nd_uint8_t  rpl_sec_t_reserved;     /* bit 7 is T-bit */
  529     nd_uint8_t  rpl_sec_algo;
  530     nd_uint16_t rpl_sec_kim_lvl_flags;  /* bit 15/14, KIM */
  531                                       /* bit 10-8, LVL, bit 7-0 flags */
  532     nd_uint32_t rpl_sec_counter;
  533 #if 0
  534     nd_byte     rpl_sec_ki[0];          /* depends upon kim */
  535 #endif
  536 };
  537 
  538 /* section 6.2.1, DODAG Information Solication (DIS_IS) */
  539 struct nd_rpl_dis_is {
  540     nd_uint8_t rpl_dis_flags;
  541     nd_uint8_t rpl_dis_reserved;
  542 #if 0
  543     nd_byte    rpl_dis_options[0];
  544 #endif
  545 };
  546 
  547 /* section 6.3.1, DODAG Information Object (DIO) */
  548 struct nd_rpl_dio {
  549     nd_uint8_t  rpl_instanceid;
  550     nd_uint8_t  rpl_version;
  551     nd_uint16_t rpl_dagrank;
  552     nd_uint8_t  rpl_mopprf;   /* bit 7=G, 5-3=MOP, 2-0=PRF */
  553     nd_uint8_t  rpl_dtsn;     /* Dest. Advertisement Trigger Sequence Number */
  554     nd_uint8_t  rpl_flags;    /* no flags defined yet */
  555     nd_uint8_t  rpl_resv1;
  556     nd_byte     rpl_dagid[DAGID_LEN];
  557 };
  558 #define RPL_DIO_GROUND_FLAG 0x80
  559 #define RPL_DIO_MOP_SHIFT   3
  560 #define RPL_DIO_MOP_MASK    (7 << RPL_DIO_MOP_SHIFT)
  561 #define RPL_DIO_PRF_SHIFT   0
  562 #define RPL_DIO_PRF_MASK    (7 << RPL_DIO_PRF_SHIFT)
  563 #define RPL_DIO_GROUNDED(X) ((X)&RPL_DIO_GROUND_FLAG)
  564 #define RPL_DIO_MOP(X)      (enum RPL_DIO_MOP)(((X)&RPL_DIO_MOP_MASK) >> RPL_DIO_MOP_SHIFT)
  565 #define RPL_DIO_PRF(X)      (((X)&RPL_DIO_PRF_MASK) >> RPL_DIO_PRF_SHIFT)
  566 
  567 enum RPL_DIO_MOP {
  568     RPL_DIO_NONSTORING= 0x0,
  569     RPL_DIO_STORING   = 0x1,
  570     RPL_DIO_NONSTORING_MULTICAST = 0x2,
  571     RPL_DIO_STORING_MULTICAST    = 0x3
  572 };
  573 
  574 enum RPL_SUBOPT {
  575         RPL_OPT_PAD1        = 0,
  576         RPL_OPT_PADN        = 1,
  577         RPL_DIO_METRICS     = 2,
  578         RPL_DIO_ROUTINGINFO = 3,
  579         RPL_DIO_CONFIG      = 4,
  580         RPL_DAO_RPLTARGET   = 5,
  581         RPL_DAO_TRANSITINFO = 6,
  582         RPL_DIO_DESTPREFIX  = 8,
  583         RPL_DAO_RPLTARGET_DESC=9
  584 };
  585 
  586 struct rpl_genoption {
  587     nd_uint8_t rpl_dio_type;
  588     nd_uint8_t rpl_dio_len;        /* suboption length, not including type/len */
  589 };
  590 #define RPL_GENOPTION_LEN   2
  591 
  592 #define RPL_DIO_LIFETIME_INFINITE   0xffffffff
  593 #define RPL_DIO_LIFETIME_DISCONNECT 0
  594 
  595 struct rpl_dio_destprefix {
  596     nd_uint8_t rpl_dio_type;
  597     nd_uint8_t rpl_dio_len;
  598     nd_uint8_t rpl_dio_prefixlen;        /* in bits */
  599     nd_uint8_t rpl_dio_prf;              /* flags, including Route Preference */
  600     nd_uint32_t rpl_dio_prefixlifetime;  /* in seconds */
  601 #if 0
  602     nd_byte     rpl_dio_prefix[0];       /* variable number of bytes */
  603 #endif
  604 };
  605 
  606 /* section 6.4.1, DODAG Information Object (DIO) */
  607 struct nd_rpl_dao {
  608     nd_uint8_t  rpl_instanceid;
  609     nd_uint8_t  rpl_flags;      /* bit 7=K, 6=D */
  610     nd_uint8_t  rpl_resv;
  611     nd_uint8_t  rpl_daoseq;
  612     nd_byte     rpl_dagid[DAGID_LEN];   /* present when D set. */
  613 };
  614 #define ND_RPL_DAO_MIN_LEN  4   /* length without DAGID */
  615 
  616 /* indicates if this DAO is to be acK'ed */
  617 #define RPL_DAO_K_SHIFT   7
  618 #define RPL_DAO_K_MASK    (1 << RPL_DAO_K_SHIFT)
  619 #define RPL_DAO_K(X)      (((X)&RPL_DAO_K_MASK) >> RPL_DAO_K_SHIFT)
  620 
  621 /* indicates if the DAGID is present */
  622 #define RPL_DAO_D_SHIFT   6
  623 #define RPL_DAO_D_MASK    (1 << RPL_DAO_D_SHIFT)
  624 #define RPL_DAO_D(X)      (((X)&RPL_DAO_D_MASK) >> RPL_DAO_D_SHIFT)
  625 
  626 struct rpl_dao_target {
  627     nd_uint8_t rpl_dao_type;
  628     nd_uint8_t rpl_dao_len;
  629     nd_uint8_t rpl_dao_flags;            /* unused */
  630     nd_uint8_t rpl_dao_prefixlen;        /* in bits */
  631 #if 0
  632     nd_byte    rpl_dao_prefix[0];        /* variable number of bytes */
  633 #endif
  634 };
  635 
  636 /* section 6.5.1, Destination Advertisement Object Acknowledgement (DAO-ACK) */
  637 struct nd_rpl_daoack {
  638     nd_uint8_t  rpl_instanceid;
  639     nd_uint8_t  rpl_flags;      /* bit 7=D */
  640     nd_uint8_t  rpl_daoseq;
  641     nd_uint8_t  rpl_status;
  642     nd_byte     rpl_dagid[DAGID_LEN];   /* present when D set. */
  643 };
  644 #define ND_RPL_DAOACK_MIN_LEN   4   /* length without DAGID */
  645 /* indicates if the DAGID is present */
  646 #define RPL_DAOACK_D_SHIFT   7
  647 #define RPL_DAOACK_D_MASK    (1 << RPL_DAOACK_D_SHIFT)
  648 #define RPL_DAOACK_D(X)      (((X)&RPL_DAOACK_D_MASK) >> RPL_DAOACK_D_SHIFT)
  649 
  650 static const struct tok icmp6_type_values[] = {
  651     { ICMP6_DST_UNREACH, "destination unreachable"},
  652     { ICMP6_PACKET_TOO_BIG, "packet too big"},
  653     { ICMP6_TIME_EXCEEDED, "time exceeded in-transit"},
  654     { ICMP6_PARAM_PROB, "parameter problem"},
  655     { ICMP6_ECHO_REQUEST, "echo request"},
  656     { ICMP6_ECHO_REPLY, "echo reply"},
  657     { MLD6_LISTENER_QUERY, "multicast listener query"},
  658     { MLD6_LISTENER_REPORT, "multicast listener report"},
  659     { MLD6_LISTENER_DONE, "multicast listener done"},
  660     { ND_ROUTER_SOLICIT, "router solicitation"},
  661     { ND_ROUTER_ADVERT, "router advertisement"},
  662     { ND_NEIGHBOR_SOLICIT, "neighbor solicitation"},
  663     { ND_NEIGHBOR_ADVERT, "neighbor advertisement"},
  664     { ND_REDIRECT, "redirect"},
  665     { ICMP6_ROUTER_RENUMBERING, "router renumbering"},
  666     { IND_SOLICIT, "inverse neighbor solicitation"},
  667     { IND_ADVERT, "inverse neighbor advertisement"},
  668     { MLDV2_LISTENER_REPORT, "multicast listener report v2"},
  669     { ICMP6_HADISCOV_REQUEST, "ha discovery request"},
  670     { ICMP6_HADISCOV_REPLY, "ha discovery reply"},
  671     { ICMP6_MOBILEPREFIX_SOLICIT, "mobile router solicitation"},
  672     { ICMP6_MOBILEPREFIX_ADVERT, "mobile router advertisement"},
  673     { ICMP6_WRUREQUEST, "who-are-you request"},
  674     { ICMP6_WRUREPLY, "who-are-you reply"},
  675     { ICMP6_NI_QUERY, "node information query"},
  676     { ICMP6_NI_REPLY, "node information reply"},
  677     { MLD6_MTRACE, "mtrace message"},
  678     { MLD6_MTRACE_RESP, "mtrace response"},
  679     { ND_RPL_MESSAGE,   "RPL"},
  680     { 0,    NULL }
  681 };
  682 
  683 static const struct tok icmp6_dst_unreach_code_values[] = {
  684     { ICMP6_DST_UNREACH_NOROUTE, "unreachable route" },
  685     { ICMP6_DST_UNREACH_ADMIN, " unreachable prohibited"},
  686     { ICMP6_DST_UNREACH_BEYONDSCOPE, "beyond scope"},
  687     { ICMP6_DST_UNREACH_ADDR, "unreachable address"},
  688     { ICMP6_DST_UNREACH_NOPORT, "unreachable port"},
  689     { 0,    NULL }
  690 };
  691 
  692 static const struct tok icmp6_opt_pi_flag_values[] = {
  693     { ND_OPT_PI_FLAG_ONLINK, "onlink" },
  694     { ND_OPT_PI_FLAG_AUTO, "auto" },
  695     { ND_OPT_PI_FLAG_ROUTER, "router" },
  696     { 0,    NULL }
  697 };
  698 
  699 static const struct tok icmp6_opt_ra_flag_values[] = {
  700     { ND_RA_FLAG_MANAGED, "managed" },
  701     { ND_RA_FLAG_OTHER, "other stateful"},
  702     { ND_RA_FLAG_HOME_AGENT, "home agent"},
  703     { ND_RA_FLAG_IPV6ONLY, "ipv6 only"},
  704     { 0,    NULL }
  705 };
  706 
  707 static const struct tok icmp6_nd_na_flag_values[] = {
  708     { ND_NA_FLAG_ROUTER, "router" },
  709     { ND_NA_FLAG_SOLICITED, "solicited" },
  710     { ND_NA_FLAG_OVERRIDE, "override" },
  711     { 0,    NULL }
  712 };
  713 
  714 
  715 static const struct tok icmp6_opt_values[] = {
  716    { ND_OPT_SOURCE_LINKADDR, "source link-address"},
  717    { ND_OPT_TARGET_LINKADDR, "destination link-address"},
  718    { ND_OPT_PREFIX_INFORMATION, "prefix info"},
  719    { ND_OPT_REDIRECTED_HEADER, "redirected header"},
  720    { ND_OPT_MTU, "mtu"},
  721    { ND_OPT_RDNSS, "rdnss"},
  722    { ND_OPT_DNSSL, "dnssl"},
  723    { ND_OPT_ADVINTERVAL, "advertisement interval"},
  724    { ND_OPT_HOMEAGENT_INFO, "homeagent information"},
  725    { ND_OPT_ROUTE_INFO, "route info"},
  726    { 0, NULL }
  727 };
  728 
  729 /* mldv2 report types */
  730 static const struct tok mldv2report2str[] = {
  731     { 1,    "is_in" },
  732     { 2,    "is_ex" },
  733     { 3,    "to_in" },
  734     { 4,    "to_ex" },
  735     { 5,    "allow" },
  736     { 6,    "block" },
  737     { 0,    NULL }
  738 };
  739 
  740 static const char *
  741 get_rtpref(u_int v)
  742 {
  743     static const char *rtpref_str[] = {
  744         "medium",       /* 00 */
  745         "high",         /* 01 */
  746         "rsv",          /* 10 */
  747         "low"           /* 11 */
  748     };
  749 
  750     return rtpref_str[((v & ND_RA_FLAG_RTPREF_MASK) >> 3) & 0xff];
  751 }
  752 
  753 static const char *
  754 get_lifetime(uint32_t v)
  755 {
  756     static char buf[20];
  757 
  758     if (v == (uint32_t)~0UL)
  759         return "infinity";
  760     else {
  761         snprintf(buf, sizeof(buf), "%us", v);
  762         return buf;
  763     }
  764 }
  765 
  766 static void
  767 print_lladdr(netdissect_options *ndo, const uint8_t *p, size_t l)
  768 {
  769     const uint8_t *ep, *q;
  770 
  771     q = p;
  772     ep = p + l;
  773     while (l > 0 && q < ep) {
  774         if (q > p)
  775                         ND_PRINT(":");
  776         ND_PRINT("%02x", GET_U_1(q));
  777         q++;
  778         l--;
  779     }
  780 }
  781 
  782 static uint16_t icmp6_cksum(netdissect_options *ndo, const struct ip6_hdr *ip6,
  783     const struct icmp6_hdr *icp, u_int len)
  784 {
  785     return nextproto6_cksum(ndo, ip6, (const uint8_t *)(const void *)icp, len, len,
  786                 IPPROTO_ICMPV6);
  787 }
  788 
  789 static const struct tok rpl_mop_values[] = {
  790         { RPL_DIO_NONSTORING,         "nonstoring"},
  791         { RPL_DIO_STORING,            "storing"},
  792         { RPL_DIO_NONSTORING_MULTICAST, "nonstoring-multicast"},
  793         { RPL_DIO_STORING_MULTICAST,  "storing-multicast"},
  794         { 0, NULL},
  795 };
  796 
  797 static const struct tok rpl_subopt_values[] = {
  798         { RPL_OPT_PAD1, "pad1"},
  799         { RPL_OPT_PADN, "padN"},
  800         { RPL_DIO_METRICS, "metrics"},
  801         { RPL_DIO_ROUTINGINFO, "routinginfo"},
  802         { RPL_DIO_CONFIG,    "config"},
  803         { RPL_DAO_RPLTARGET, "rpltarget"},
  804         { RPL_DAO_TRANSITINFO, "transitinfo"},
  805         { RPL_DIO_DESTPREFIX, "destprefix"},
  806         { RPL_DAO_RPLTARGET_DESC, "rpltargetdesc"},
  807         { 0, NULL},
  808 };
  809 
  810 static void
  811 rpl_printopts(netdissect_options *ndo, const uint8_t *opts, u_int length)
  812 {
  813     const struct rpl_genoption *opt;
  814     uint8_t dio_type;
  815     u_int optlen;
  816 
  817     while (length != 0) {
  818         opt = (const struct rpl_genoption *)opts;
  819         dio_type = GET_U_1(opt->rpl_dio_type);
  820         if (dio_type == RPL_OPT_PAD1) {
  821                         optlen = 1;
  822                         ND_PRINT(" opt:pad1");
  823                 } else {
  824                     if (length < RPL_GENOPTION_LEN)
  825                         goto trunc;
  826                     optlen = GET_U_1(opt->rpl_dio_len)+RPL_GENOPTION_LEN;
  827                         ND_PRINT(" opt:%s len:%u ",
  828                                   tok2str(rpl_subopt_values, "subopt:%u", dio_type),
  829                                   optlen);
  830                         ND_TCHECK_LEN(opt, optlen);
  831                         if (length < optlen)
  832                             goto trunc;
  833                         if (ndo->ndo_vflag > 2) {
  834                                 hex_print(ndo,
  835                                           " ",
  836                                           opts + RPL_GENOPTION_LEN,  /* content of DIO option */
  837                                           optlen - RPL_GENOPTION_LEN);
  838                         }
  839                 }
  840                 opts += optlen;
  841                 length -= optlen;
  842         }
  843         return;
  844 trunc:
  845     nd_print_trunc(ndo);
  846 }
  847 
  848 static void
  849 rpl_dio_print(netdissect_options *ndo,
  850               const u_char *bp, u_int length)
  851 {
  852         const struct nd_rpl_dio *dio = (const struct nd_rpl_dio *)bp;
  853         const char *dagid_str;
  854 
  855         ND_TCHECK_SIZE(dio);
  856         dagid_str = ip6addr_string (ndo, dio->rpl_dagid);
  857 
  858         ND_PRINT(" [dagid:%s,seq:%u,instance:%u,rank:%u,%smop:%s,prf:%u]",
  859                   dagid_str,
  860                   GET_U_1(dio->rpl_dtsn),
  861                   GET_U_1(dio->rpl_instanceid),
  862                   GET_BE_U_2(dio->rpl_dagrank),
  863                   RPL_DIO_GROUNDED(GET_U_1(dio->rpl_mopprf)) ? "grounded,":"",
  864                   tok2str(rpl_mop_values, "mop%u", RPL_DIO_MOP(GET_U_1(dio->rpl_mopprf))),
  865                   RPL_DIO_PRF(GET_U_1(dio->rpl_mopprf)));
  866 
  867         if(ndo->ndo_vflag > 1) {
  868                 rpl_printopts(ndo, bp + sizeof(struct nd_rpl_dio),
  869                               length - sizeof(struct nd_rpl_dio));
  870         }
  871     return;
  872 trunc:
  873     nd_print_trunc(ndo);
  874 }
  875 
  876 static void
  877 rpl_dao_print(netdissect_options *ndo,
  878               const u_char *bp, u_int length)
  879 {
  880         const struct nd_rpl_dao *dao = (const struct nd_rpl_dao *)bp;
  881         const char *dagid_str = "<elided>";
  882         uint8_t rpl_flags;
  883 
  884         ND_TCHECK_SIZE(dao);
  885         if (length < ND_RPL_DAO_MIN_LEN)
  886         goto tooshort;
  887 
  888         bp += ND_RPL_DAO_MIN_LEN;
  889         length -= ND_RPL_DAO_MIN_LEN;
  890         rpl_flags = GET_U_1(dao->rpl_flags);
  891         if(RPL_DAO_D(rpl_flags)) {
  892                 ND_TCHECK_LEN(dao->rpl_dagid, DAGID_LEN);
  893                 if (length < DAGID_LEN)
  894                     goto tooshort;
  895                 dagid_str = ip6addr_string (ndo, dao->rpl_dagid);
  896                 bp += DAGID_LEN;
  897                 length -= DAGID_LEN;
  898         }
  899 
  900         ND_PRINT(" [dagid:%s,seq:%u,instance:%u%s%s,%02x]",
  901                   dagid_str,
  902                   GET_U_1(dao->rpl_daoseq),
  903                   GET_U_1(dao->rpl_instanceid),
  904                   RPL_DAO_K(rpl_flags) ? ",acK":"",
  905                   RPL_DAO_D(rpl_flags) ? ",Dagid":"",
  906                   rpl_flags);
  907 
  908         if(ndo->ndo_vflag > 1) {
  909                 rpl_printopts(ndo, bp, length);
  910         }
  911     return;
  912 
  913 trunc:
  914     nd_print_trunc(ndo);
  915     return;
  916 
  917 tooshort:
  918     ND_PRINT(" [|length too short]");
  919 }
  920 
  921 static void
  922 rpl_daoack_print(netdissect_options *ndo,
  923                  const u_char *bp, u_int length)
  924 {
  925         const struct nd_rpl_daoack *daoack = (const struct nd_rpl_daoack *)bp;
  926         const char *dagid_str = "<elided>";
  927 
  928         ND_TCHECK_LEN(daoack, ND_RPL_DAOACK_MIN_LEN);
  929         if (length < ND_RPL_DAOACK_MIN_LEN)
  930         goto tooshort;
  931 
  932         bp += ND_RPL_DAOACK_MIN_LEN;
  933         length -= ND_RPL_DAOACK_MIN_LEN;
  934         if(RPL_DAOACK_D(GET_U_1(daoack->rpl_flags))) {
  935                 ND_TCHECK_LEN(daoack->rpl_dagid, DAGID_LEN);
  936                 if (length < DAGID_LEN)
  937                     goto tooshort;
  938                 dagid_str = ip6addr_string (ndo, daoack->rpl_dagid);
  939                 bp += DAGID_LEN;
  940                 length -= DAGID_LEN;
  941         }
  942 
  943         ND_PRINT(" [dagid:%s,seq:%u,instance:%u,status:%u]",
  944                   dagid_str,
  945                   GET_U_1(daoack->rpl_daoseq),
  946                   GET_U_1(daoack->rpl_instanceid),
  947                   GET_U_1(daoack->rpl_status));
  948 
  949         /* no officially defined options for DAOACK, but print any we find */
  950         if(ndo->ndo_vflag > 1) {
  951                 rpl_printopts(ndo, bp, length);
  952         }
  953     return;
  954 
  955 trunc:
  956     nd_print_trunc(ndo);
  957     return;
  958 
  959 tooshort:
  960     ND_PRINT(" [|dao-length too short]");
  961 }
  962 
  963 static void
  964 rpl_print(netdissect_options *ndo,
  965           uint8_t icmp6_code,
  966           const u_char *bp, u_int length)
  967 {
  968         int secured = icmp6_code & 0x80;
  969         int basecode= icmp6_code & 0x7f;
  970 
  971         if(secured) {
  972                 ND_PRINT(", (SEC) [worktodo]");
  973                 /* XXX
  974                  * the next header pointer needs to move forward to
  975                  * skip the secure part.
  976                  */
  977                 return;
  978         } else {
  979                 ND_PRINT(", (CLR)");
  980         }
  981 
  982         switch(basecode) {
  983         case ND_RPL_DAG_IS:
  984                 ND_PRINT("DODAG Information Solicitation");
  985                 if(ndo->ndo_vflag) {
  986                 }
  987                 break;
  988         case ND_RPL_DAG_IO:
  989                 ND_PRINT("DODAG Information Object");
  990                 if(ndo->ndo_vflag) {
  991                         rpl_dio_print(ndo, bp, length);
  992                 }
  993                 break;
  994         case ND_RPL_DAO:
  995                 ND_PRINT("Destination Advertisement Object");
  996                 if(ndo->ndo_vflag) {
  997                         rpl_dao_print(ndo, bp, length);
  998                 }
  999                 break;
 1000         case ND_RPL_DAO_ACK:
 1001                 ND_PRINT("Destination Advertisement Object Ack");
 1002                 if(ndo->ndo_vflag) {
 1003                         rpl_daoack_print(ndo, bp, length);
 1004                 }
 1005                 break;
 1006         default:
 1007                 ND_PRINT("RPL message, unknown code %u",icmp6_code);
 1008                 break;
 1009         }
 1010     return;
 1011 
 1012 #if 0
 1013 trunc:
 1014     nd_print_trunc(ndo);
 1015     return;
 1016 #endif
 1017 
 1018 }
 1019 
 1020 
 1021 void
 1022 icmp6_print(netdissect_options *ndo,
 1023             const u_char *bp, u_int length, const u_char *bp2, int fragmented)
 1024 {
 1025     const struct icmp6_hdr *dp;
 1026     uint8_t icmp6_type, icmp6_code;
 1027     const struct ip6_hdr *ip;
 1028     const struct ip6_hdr *oip;
 1029     const struct udphdr *ouh;
 1030     uint16_t dport;
 1031     const u_char *ep;
 1032     u_int prot;
 1033 
 1034     ndo->ndo_protocol = "icmp6";
 1035     dp = (const struct icmp6_hdr *)bp;
 1036     ip = (const struct ip6_hdr *)bp2;
 1037     oip = (const struct ip6_hdr *)(dp + 1);
 1038     /* 'ep' points to the end of available data. */
 1039     ep = ndo->ndo_snapend;
 1040     if (length == 0) {
 1041         ND_PRINT("ICMP6, length 0");
 1042         nd_print_invalid(ndo);
 1043         return;
 1044     }
 1045 
 1046     if (ndo->ndo_vflag && !fragmented) {
 1047         uint16_t sum, udp_sum;
 1048 
 1049         if (ND_TTEST_LEN(bp, length)) {
 1050             udp_sum = GET_BE_U_2(dp->icmp6_cksum);
 1051             sum = icmp6_cksum(ndo, ip, dp, length);
 1052             if (sum != 0)
 1053                 ND_PRINT("[bad icmp6 cksum 0x%04x -> 0x%04x!] ",
 1054                                                 udp_sum,
 1055                                                 in_cksum_shouldbe(udp_sum, sum));
 1056             else
 1057                 ND_PRINT("[icmp6 sum ok] ");
 1058         }
 1059     }
 1060 
 1061     icmp6_type = GET_U_1(dp->icmp6_type);
 1062     ND_PRINT("ICMP6, %s", tok2str(icmp6_type_values,"unknown icmp6 type (%u)",icmp6_type));
 1063 
 1064         /* display cosmetics: print the packet length for printer that use the vflag now */
 1065         if (ndo->ndo_vflag && (icmp6_type == ND_ROUTER_SOLICIT ||
 1066                       icmp6_type == ND_ROUTER_ADVERT ||
 1067                       icmp6_type == ND_NEIGHBOR_ADVERT ||
 1068                       icmp6_type == ND_NEIGHBOR_SOLICIT ||
 1069                       icmp6_type == ND_REDIRECT ||
 1070                       icmp6_type == ICMP6_HADISCOV_REPLY ||
 1071                       icmp6_type == ICMP6_MOBILEPREFIX_ADVERT ))
 1072                 ND_PRINT(", length %u", length);
 1073 
 1074     icmp6_code = GET_U_1(dp->icmp6_code);
 1075 
 1076     switch (icmp6_type) {
 1077     case ICMP6_DST_UNREACH:
 1078                 ND_PRINT(", %s", tok2str(icmp6_dst_unreach_code_values,"unknown unreach code (%u)",icmp6_code));
 1079         switch (icmp6_code) {
 1080 
 1081         case ICMP6_DST_UNREACH_NOROUTE: /* fall through */
 1082         case ICMP6_DST_UNREACH_ADMIN:
 1083         case ICMP6_DST_UNREACH_ADDR:
 1084                         ND_PRINT(" %s",GET_IP6ADDR_STRING(oip->ip6_dst));
 1085                         break;
 1086         case ICMP6_DST_UNREACH_BEYONDSCOPE:
 1087             ND_PRINT(" %s, source address %s",
 1088                    GET_IP6ADDR_STRING(oip->ip6_dst),
 1089                                   GET_IP6ADDR_STRING(oip->ip6_src));
 1090             break;
 1091         case ICMP6_DST_UNREACH_NOPORT:
 1092             if ((ouh = get_upperlayer(ndo, (const u_char *)oip, &prot))
 1093                 == NULL)
 1094                 goto trunc;
 1095 
 1096             dport = GET_BE_U_2(ouh->uh_dport);
 1097             switch (prot) {
 1098             case IPPROTO_TCP:
 1099                 ND_PRINT(", %s tcp port %s",
 1100                     GET_IP6ADDR_STRING(oip->ip6_dst),
 1101                                           tcpport_string(ndo, dport));
 1102                 break;
 1103             case IPPROTO_UDP:
 1104                 ND_PRINT(", %s udp port %s",
 1105                     GET_IP6ADDR_STRING(oip->ip6_dst),
 1106                                           udpport_string(ndo, dport));
 1107                 break;
 1108             default:
 1109                 ND_PRINT(", %s protocol %u port %u unreachable",
 1110                     GET_IP6ADDR_STRING(oip->ip6_dst),
 1111                                           prot, dport);
 1112                 break;
 1113             }
 1114             break;
 1115         default:
 1116                   if (ndo->ndo_vflag <= 1) {
 1117                     print_unknown_data(ndo, bp,"\n\t",length);
 1118                     return;
 1119                   }
 1120                     break;
 1121         }
 1122         break;
 1123     case ICMP6_PACKET_TOO_BIG:
 1124         ND_PRINT(", mtu %u", GET_BE_U_4(dp->icmp6_mtu));
 1125         break;
 1126     case ICMP6_TIME_EXCEEDED:
 1127         switch (icmp6_code) {
 1128         case ICMP6_TIME_EXCEED_TRANSIT:
 1129             ND_PRINT(" for %s",
 1130                                   GET_IP6ADDR_STRING(oip->ip6_dst));
 1131             break;
 1132         case ICMP6_TIME_EXCEED_REASSEMBLY:
 1133             ND_PRINT(" (reassembly)");
 1134             break;
 1135         default:
 1136                         ND_PRINT(", unknown code (%u)", icmp6_code);
 1137             break;
 1138         }
 1139         break;
 1140     case ICMP6_PARAM_PROB:
 1141         ND_TCHECK_16(oip->ip6_dst);
 1142         switch (icmp6_code) {
 1143         case ICMP6_PARAMPROB_HEADER:
 1144                         ND_PRINT(", erroneous - octet %u",
 1145                  GET_BE_U_4(dp->icmp6_pptr));
 1146                         break;
 1147         case ICMP6_PARAMPROB_NEXTHEADER:
 1148                         ND_PRINT(", next header - octet %u",
 1149                  GET_BE_U_4(dp->icmp6_pptr));
 1150                         break;
 1151         case ICMP6_PARAMPROB_OPTION:
 1152                         ND_PRINT(", option - octet %u",
 1153                  GET_BE_U_4(dp->icmp6_pptr));
 1154                         break;
 1155         case ICMP6_PARAMPROB_FRAGHDRCHAIN:
 1156                         ND_PRINT(", incomplete header chain - octet %u",
 1157                  GET_BE_U_4(dp->icmp6_pptr));
 1158                         break;
 1159         default:
 1160                         ND_PRINT(", code-#%u",
 1161                                   icmp6_code);
 1162                         break;
 1163         }
 1164         break;
 1165     case ICMP6_ECHO_REQUEST:
 1166     case ICMP6_ECHO_REPLY:
 1167                 ND_PRINT(", id %u, seq %u", GET_BE_U_2(dp->icmp6_id),
 1168              GET_BE_U_2(dp->icmp6_seq));
 1169         break;
 1170     case ICMP6_MEMBERSHIP_QUERY:
 1171         if (length == MLD_MINLEN) {
 1172             mld6_print(ndo, (const u_char *)dp);
 1173         } else if (length >= MLDV2_MINLEN) {
 1174             ND_PRINT(" v2");
 1175             mldv2_query_print(ndo, (const u_char *)dp, length);
 1176         } else {
 1177                         ND_PRINT(" unknown-version (len %u) ", length);
 1178         }
 1179         break;
 1180     case ICMP6_MEMBERSHIP_REPORT:
 1181         mld6_print(ndo, (const u_char *)dp);
 1182         break;
 1183     case ICMP6_MEMBERSHIP_REDUCTION:
 1184         mld6_print(ndo, (const u_char *)dp);
 1185         break;
 1186     case ND_ROUTER_SOLICIT:
 1187 #define RTSOLLEN 8
 1188         if (ndo->ndo_vflag) {
 1189             if (icmp6_opt_print(ndo, (const u_char *)dp + RTSOLLEN,
 1190                         length - RTSOLLEN) == -1)
 1191                 goto trunc;
 1192         }
 1193         break;
 1194     case ND_ROUTER_ADVERT:
 1195 #define RTADVLEN 16
 1196         if (ndo->ndo_vflag) {
 1197             const struct nd_router_advert *p;
 1198 
 1199             p = (const struct nd_router_advert *)dp;
 1200             ND_PRINT("\n\thop limit %u, Flags [%s]"
 1201                                   ", pref %s, router lifetime %us, reachable time %ums, retrans timer %ums",
 1202                                   GET_U_1(p->nd_ra_curhoplimit),
 1203                                   bittok2str(icmp6_opt_ra_flag_values,"none",GET_U_1(p->nd_ra_flags_reserved)),
 1204                                   get_rtpref(GET_U_1(p->nd_ra_flags_reserved)),
 1205                                   GET_BE_U_2(p->nd_ra_router_lifetime),
 1206                                   GET_BE_U_4(p->nd_ra_reachable),
 1207                                   GET_BE_U_4(p->nd_ra_retransmit));
 1208 
 1209             if (icmp6_opt_print(ndo, (const u_char *)dp + RTADVLEN,
 1210                         length - RTADVLEN) == -1)
 1211                 goto trunc;
 1212         }
 1213         break;
 1214     case ND_NEIGHBOR_SOLICIT:
 1215         {
 1216         const struct nd_neighbor_solicit *p;
 1217         p = (const struct nd_neighbor_solicit *)dp;
 1218         ND_PRINT(", who has %s", GET_IP6ADDR_STRING(p->nd_ns_target));
 1219         if (ndo->ndo_vflag) {
 1220 #define NDSOLLEN 24
 1221             if (icmp6_opt_print(ndo, (const u_char *)dp + NDSOLLEN,
 1222                         length - NDSOLLEN) == -1)
 1223                 goto trunc;
 1224         }
 1225         }
 1226         break;
 1227     case ND_NEIGHBOR_ADVERT:
 1228         {
 1229         const struct nd_neighbor_advert *p;
 1230 
 1231         p = (const struct nd_neighbor_advert *)dp;
 1232         ND_PRINT(", tgt is %s",
 1233                           GET_IP6ADDR_STRING(p->nd_na_target));
 1234         if (ndo->ndo_vflag) {
 1235                         ND_PRINT(", Flags [%s]",
 1236                                   bittok2str(icmp6_nd_na_flag_values,
 1237                                              "none",
 1238                                              GET_BE_U_4(p->nd_na_flags_reserved)));
 1239 #define NDADVLEN 24
 1240             if (icmp6_opt_print(ndo, (const u_char *)dp + NDADVLEN,
 1241                         length - NDADVLEN) == -1)
 1242                 goto trunc;
 1243 #undef NDADVLEN
 1244         }
 1245         }
 1246         break;
 1247     case ND_REDIRECT:
 1248         {
 1249         const struct nd_redirect *p;
 1250 
 1251         p = (const struct nd_redirect *)dp;
 1252         ND_PRINT(", %s", GET_IP6ADDR_STRING(p->nd_rd_dst));
 1253         ND_PRINT(" to %s", GET_IP6ADDR_STRING(p->nd_rd_target));
 1254 #define REDIRECTLEN 40
 1255         if (ndo->ndo_vflag) {
 1256             if (icmp6_opt_print(ndo, (const u_char *)dp + REDIRECTLEN,
 1257                         length - REDIRECTLEN) == -1)
 1258                 goto trunc;
 1259 #undef REDIRECTLEN
 1260         }
 1261         }
 1262         break;
 1263     case ICMP6_ROUTER_RENUMBERING:
 1264         icmp6_rrenum_print(ndo, bp, ep);
 1265         break;
 1266     case ICMP6_NI_QUERY:
 1267     case ICMP6_NI_REPLY:
 1268         icmp6_nodeinfo_print(ndo, length, bp, ep);
 1269         break;
 1270     case IND_SOLICIT:
 1271     case IND_ADVERT:
 1272         break;
 1273     case ICMP6_V2_MEMBERSHIP_REPORT:
 1274         mldv2_report_print(ndo, (const u_char *) dp, length);
 1275         break;
 1276     case ICMP6_MOBILEPREFIX_SOLICIT: /* fall through */
 1277     case ICMP6_HADISCOV_REQUEST:
 1278                 ND_PRINT(", id 0x%04x", GET_BE_U_2(dp->icmp6_data16[0]));
 1279                 break;
 1280     case ICMP6_HADISCOV_REPLY:
 1281         if (ndo->ndo_vflag) {
 1282             const u_char *cp;
 1283             const u_char *p;
 1284 
 1285             ND_PRINT(", id 0x%04x",
 1286                  GET_BE_U_2(dp->icmp6_data16[0]));
 1287             cp = (const u_char *)dp + length;
 1288             p = (const u_char *)(dp + 1);
 1289             while (p < cp) {
 1290                 ND_PRINT(", %s", GET_IP6ADDR_STRING(p));
 1291                 p += 16;
 1292             }
 1293         }
 1294         break;
 1295     case ICMP6_MOBILEPREFIX_ADVERT:
 1296         if (ndo->ndo_vflag) {
 1297             uint16_t flags;
 1298 
 1299             ND_PRINT(", id 0x%04x",
 1300                  GET_BE_U_2(dp->icmp6_data16[0]));
 1301             flags = GET_BE_U_2(dp->icmp6_data16[1]);
 1302             if (flags & 0xc000)
 1303                 ND_PRINT(" ");
 1304             if (flags & 0x8000)
 1305                 ND_PRINT("M");
 1306             if (flags & 0x4000)
 1307                 ND_PRINT("O");
 1308 #define MPADVLEN 8
 1309             if (icmp6_opt_print(ndo, (const u_char *)dp + MPADVLEN,
 1310                         length - MPADVLEN) == -1)
 1311                 goto trunc;
 1312         }
 1313         break;
 1314         case ND_RPL_MESSAGE:
 1315                 /* plus 4, because struct icmp6_hdr contains 4 bytes of icmp payload */
 1316                 rpl_print(ndo, icmp6_code, dp->icmp6_data, length-sizeof(struct icmp6_hdr)+4);
 1317                 break;
 1318     default:
 1319                 ND_PRINT(", length %u", length);
 1320                 if (ndo->ndo_vflag <= 1)
 1321                         print_unknown_data(ndo, bp,"\n\t", length);
 1322                 return;
 1323         }
 1324         if (!ndo->ndo_vflag)
 1325                 ND_PRINT(", length %u", length);
 1326     return;
 1327 trunc:
 1328     nd_print_trunc(ndo);
 1329 }
 1330 
 1331 static const struct udphdr *
 1332 get_upperlayer(netdissect_options *ndo, const u_char *bp, u_int *prot)
 1333 {
 1334     const u_char *ep;
 1335     const struct ip6_hdr *ip6 = (const struct ip6_hdr *)bp;
 1336     const struct udphdr *uh;
 1337     const struct ip6_hbh *hbh;
 1338     const struct ip6_frag *fragh;
 1339     const struct ah *ah;
 1340     u_int nh;
 1341     int hlen;
 1342 
 1343     /* 'ep' points to the end of available data. */
 1344     ep = ndo->ndo_snapend;
 1345 
 1346     if (!ND_TTEST_1(ip6->ip6_nxt))
 1347         return NULL;
 1348 
 1349     nh = GET_U_1(ip6->ip6_nxt);
 1350     hlen = sizeof(struct ip6_hdr);
 1351 
 1352     while (bp < ep) {
 1353         bp += hlen;
 1354 
 1355         switch(nh) {
 1356         case IPPROTO_UDP:
 1357         case IPPROTO_TCP:
 1358             uh = (const struct udphdr *)bp;
 1359             if (ND_TTEST_2(uh->uh_dport)) {
 1360                 *prot = nh;
 1361                 return(uh);
 1362             }
 1363             else
 1364                 return(NULL);
 1365             /* NOTREACHED */
 1366 
 1367         case IPPROTO_HOPOPTS:
 1368         case IPPROTO_DSTOPTS:
 1369         case IPPROTO_ROUTING:
 1370             hbh = (const struct ip6_hbh *)bp;
 1371             if (!ND_TTEST_1(hbh->ip6h_len))
 1372                 return(NULL);
 1373             nh = GET_U_1(hbh->ip6h_nxt);
 1374             hlen = (GET_U_1(hbh->ip6h_len) + 1) << 3;
 1375             break;
 1376 
 1377         case IPPROTO_FRAGMENT: /* this should be odd, but try anyway */
 1378             fragh = (const struct ip6_frag *)bp;
 1379             if (!ND_TTEST_2(fragh->ip6f_offlg))
 1380                 return(NULL);
 1381             /* fragments with non-zero offset are meaningless */
 1382             if ((GET_BE_U_2(fragh->ip6f_offlg) & IP6F_OFF_MASK) != 0)
 1383                 return(NULL);
 1384             nh = GET_U_1(fragh->ip6f_nxt);
 1385             hlen = sizeof(struct ip6_frag);
 1386             break;
 1387 
 1388         case IPPROTO_AH:
 1389             ah = (const struct ah *)bp;
 1390             if (!ND_TTEST_1(ah->ah_len))
 1391                 return(NULL);
 1392             nh = GET_U_1(ah->ah_nxt);
 1393             hlen = (GET_U_1(ah->ah_len) + 2) << 2;
 1394             break;
 1395 
 1396         default:    /* unknown or undecodable header */
 1397             *prot = nh; /* meaningless, but set here anyway */
 1398             return(NULL);
 1399         }
 1400     }
 1401 
 1402     return(NULL);       /* should be notreached, though */
 1403 }
 1404 
 1405 static int
 1406 icmp6_opt_print(netdissect_options *ndo, const u_char *bp, int resid)
 1407 {
 1408     const struct nd_opt_hdr *op;
 1409     uint8_t opt_type;
 1410     u_int opt_len;
 1411     const struct nd_opt_prefix_info *opp;
 1412     const struct nd_opt_mtu *opm;
 1413     const struct nd_opt_rdnss *oprd;
 1414     const struct nd_opt_dnssl *opds;
 1415     const struct nd_opt_advinterval *opa;
 1416     const struct nd_opt_homeagent_info *oph;
 1417     const struct nd_opt_route_info *opri;
 1418     const u_char *cp, *ep, *domp;
 1419     nd_ipv6 in6;
 1420     size_t l;
 1421     u_int i;
 1422 
 1423     cp = bp;
 1424     /* 'ep' points to the end of available data. */
 1425     ep = ndo->ndo_snapend;
 1426 
 1427     while (cp < ep) {
 1428         op = (const struct nd_opt_hdr *)cp;
 1429 
 1430         ND_TCHECK_1(op->nd_opt_len);
 1431         if (resid <= 0)
 1432             return 0;
 1433         opt_type = GET_U_1(op->nd_opt_type);
 1434         opt_len = GET_U_1(op->nd_opt_len);
 1435         if (opt_len == 0)
 1436             goto trunc;
 1437         if (cp + (opt_len << 3) > ep)
 1438             goto trunc;
 1439 
 1440                 ND_PRINT("\n\t  %s option (%u), length %u (%u): ",
 1441                           tok2str(icmp6_opt_values, "unknown", opt_type),
 1442                           opt_type,
 1443                           opt_len << 3,
 1444                           opt_len);
 1445 
 1446         switch (opt_type) {
 1447         case ND_OPT_SOURCE_LINKADDR:
 1448             l = (opt_len << 3) - 2;
 1449             print_lladdr(ndo, cp + 2, l);
 1450             break;
 1451         case ND_OPT_TARGET_LINKADDR:
 1452             l = (opt_len << 3) - 2;
 1453             print_lladdr(ndo, cp + 2, l);
 1454             break;
 1455         case ND_OPT_PREFIX_INFORMATION:
 1456             opp = (const struct nd_opt_prefix_info *)op;
 1457                         ND_PRINT("%s/%u%s, Flags [%s], valid time %s",
 1458                                   GET_IP6ADDR_STRING(opp->nd_opt_pi_prefix),
 1459                                   GET_U_1(opp->nd_opt_pi_prefix_len),
 1460                                   (opt_len != 4) ? "badlen" : "",
 1461                                   bittok2str(icmp6_opt_pi_flag_values, "none", GET_U_1(opp->nd_opt_pi_flags_reserved)),
 1462                                   get_lifetime(GET_BE_U_4(opp->nd_opt_pi_valid_time)));
 1463                         ND_PRINT(", pref. time %s",
 1464                  get_lifetime(GET_BE_U_4(opp->nd_opt_pi_preferred_time)));
 1465             break;
 1466         case ND_OPT_REDIRECTED_HEADER:
 1467                         print_unknown_data(ndo, bp,"\n\t    ",opt_len<<3);
 1468             /* xxx */
 1469             break;
 1470         case ND_OPT_MTU:
 1471             opm = (const struct nd_opt_mtu *)op;
 1472             ND_PRINT(" %u%s",
 1473                                GET_BE_U_4(opm->nd_opt_mtu_mtu),
 1474                                (opt_len != 1) ? "bad option length" : "" );
 1475                         break;
 1476         case ND_OPT_RDNSS:
 1477             oprd = (const struct nd_opt_rdnss *)op;
 1478             l = (opt_len - 1) / 2;
 1479             ND_PRINT(" lifetime %us,",
 1480                                   GET_BE_U_4(oprd->nd_opt_rdnss_lifetime));
 1481             for (i = 0; i < l; i++) {
 1482                 ND_PRINT(" addr: %s",
 1483                                           GET_IP6ADDR_STRING(oprd->nd_opt_rdnss_addr[i]));
 1484             }
 1485             break;
 1486         case ND_OPT_DNSSL:
 1487             opds = (const struct nd_opt_dnssl *)op;
 1488             ND_PRINT(" lifetime %us, domain(s):",
 1489                                   GET_BE_U_4(opds->nd_opt_dnssl_lifetime));
 1490             domp = cp + 8; /* domain names, variable-sized, RFC1035-encoded */
 1491             while (domp < cp + (opt_len << 3) && GET_U_1(domp) != '\0')
 1492             {
 1493                 ND_PRINT(" ");
 1494                 if ((domp = fqdn_print(ndo, domp, bp)) == NULL)
 1495                     goto trunc;
 1496             }
 1497             break;
 1498         case ND_OPT_ADVINTERVAL:
 1499             opa = (const struct nd_opt_advinterval *)op;
 1500             ND_PRINT(" %ums",
 1501                  GET_BE_U_4(opa->nd_opt_adv_interval));
 1502             break;
 1503                 case ND_OPT_HOMEAGENT_INFO:
 1504             oph = (const struct nd_opt_homeagent_info *)op;
 1505             ND_PRINT(" preference %u, lifetime %u",
 1506                                   GET_BE_U_2(oph->nd_opt_hai_preference),
 1507                                   GET_BE_U_2(oph->nd_opt_hai_lifetime));
 1508             break;
 1509         case ND_OPT_ROUTE_INFO:
 1510             opri = (const struct nd_opt_route_info *)op;
 1511             ND_TCHECK_4(opri->nd_opt_rti_lifetime);
 1512             memset(&in6, 0, sizeof(in6));
 1513             switch (opt_len) {
 1514             case 1:
 1515                 break;
 1516             case 2:
 1517                 GET_CPY_BYTES(&in6, opri + 1, 8);
 1518                 break;
 1519             case 3:
 1520                 GET_CPY_BYTES(&in6, opri + 1, 16);
 1521                 break;
 1522             default:
 1523                 goto trunc;
 1524             }
 1525             ND_PRINT(" %s/%u", ip6addr_string(ndo, (const u_char *)&in6),
 1526                                   GET_U_1(opri->nd_opt_rti_prefixlen));
 1527             ND_PRINT(", pref=%s",
 1528                  get_rtpref(GET_U_1(opri->nd_opt_rti_flags)));
 1529             ND_PRINT(", lifetime=%s",
 1530                                   get_lifetime(GET_BE_U_4(opri->nd_opt_rti_lifetime)));
 1531             break;
 1532         default:
 1533                         if (ndo->ndo_vflag <= 1) {
 1534                                 print_unknown_data(ndo,cp+2,"\n\t  ", (opt_len << 3) - 2); /* skip option header */
 1535                             return 0;
 1536                         }
 1537                         break;
 1538         }
 1539                 /* do we want to see an additional hexdump ? */
 1540                 if (ndo->ndo_vflag> 1)
 1541                         print_unknown_data(ndo, cp+2,"\n\t    ", (opt_len << 3) - 2); /* skip option header */
 1542 
 1543         cp += opt_len << 3;
 1544         resid -= opt_len << 3;
 1545     }
 1546     return 0;
 1547 
 1548 trunc:
 1549     return -1;
 1550 }
 1551 
 1552 static void
 1553 mld6_print(netdissect_options *ndo, const u_char *bp)
 1554 {
 1555     const struct mld6_hdr *mp = (const struct mld6_hdr *)bp;
 1556     const u_char *ep;
 1557 
 1558     /* 'ep' points to the end of available data. */
 1559     ep = ndo->ndo_snapend;
 1560 
 1561     if ((const u_char *)mp + sizeof(*mp) > ep)
 1562         return;
 1563 
 1564     ND_PRINT("max resp delay: %u ", GET_BE_U_2(mp->mld6_maxdelay));
 1565     ND_PRINT("addr: %s", GET_IP6ADDR_STRING(mp->mld6_addr));
 1566 }
 1567 
 1568 static void
 1569 mldv2_report_print(netdissect_options *ndo, const u_char *bp, u_int len)
 1570 {
 1571     const struct icmp6_hdr *icp = (const struct icmp6_hdr *) bp;
 1572     u_int group, nsrcs, ngroups;
 1573     u_int i, j;
 1574 
 1575     /* Minimum len is 8 */
 1576     if (len < 8) {
 1577             ND_PRINT(" [invalid len %u]", len);
 1578             return;
 1579     }
 1580 
 1581     ngroups = GET_BE_U_2(icp->icmp6_data16[1]);
 1582     ND_PRINT(", %u group record(s)", ngroups);
 1583     if (ndo->ndo_vflag > 0) {
 1584     /* Print the group records */
 1585     group = 8;
 1586         for (i = 0; i < ngroups; i++) {
 1587         /* type(1) + auxlen(1) + numsrc(2) + grp(16) */
 1588         if (len < group + 20) {
 1589                     ND_PRINT(" [invalid number of groups]");
 1590                     return;
 1591         }
 1592             ND_PRINT(" [gaddr %s", GET_IP6ADDR_STRING(bp + group + 4));
 1593         ND_PRINT(" %s", tok2str(mldv2report2str, " [v2-report-#%u]",
 1594                                          GET_U_1(bp + group)));
 1595             nsrcs = GET_BE_U_2(bp + group + 2);
 1596         /* Check the number of sources and print them */
 1597         if (len < group + 20 + (nsrcs * sizeof(nd_ipv6))) {
 1598                     ND_PRINT(" [invalid number of sources %u]", nsrcs);
 1599                     return;
 1600         }
 1601             if (ndo->ndo_vflag == 1)
 1602                     ND_PRINT(", %u source(s)", nsrcs);
 1603             else {
 1604         /* Print the sources */
 1605                     ND_PRINT(" {");
 1606                 for (j = 0; j < nsrcs; j++) {
 1607             ND_PRINT(" %s", GET_IP6ADDR_STRING(bp + group + 20 + (j * sizeof(nd_ipv6))));
 1608         }
 1609                 ND_PRINT(" }");
 1610             }
 1611         /* Next group record */
 1612             group += 20 + nsrcs * sizeof(nd_ipv6);
 1613         ND_PRINT("]");
 1614         }
 1615     }
 1616 }
 1617 
 1618 static void
 1619 mldv2_query_print(netdissect_options *ndo, const u_char *bp, u_int len)
 1620 {
 1621     const struct icmp6_hdr *icp = (const struct icmp6_hdr *) bp;
 1622     u_int mrc;
 1623     u_int mrt, qqi;
 1624     u_int nsrcs;
 1625     u_int i;
 1626 
 1627     /* Minimum len is 28 */
 1628     if (len < 28) {
 1629         ND_PRINT(" [invalid len %u]", len);
 1630     return;
 1631     }
 1632     mrc = GET_BE_U_2(icp->icmp6_data16[0]);
 1633     if (mrc < 32768) {
 1634     mrt = mrc;
 1635     } else {
 1636         mrt = ((mrc & 0x0fff) | 0x1000) << (((mrc & 0x7000) >> 12) + 3);
 1637     }
 1638     if (ndo->ndo_vflag) {
 1639             ND_PRINT(" [max resp delay=%u]", mrt);
 1640     }
 1641     ND_PRINT(" [gaddr %s", GET_IP6ADDR_STRING(bp + 8));
 1642 
 1643     if (ndo->ndo_vflag) {
 1644     if (GET_U_1(bp + 24) & 0x08) {
 1645         ND_PRINT(" sflag");
 1646     }
 1647     if (GET_U_1(bp + 24) & 0x07) {
 1648         ND_PRINT(" robustness=%u", GET_U_1(bp + 24) & 0x07);
 1649     }
 1650     if (GET_U_1(bp + 25) < 128) {
 1651         qqi = GET_U_1(bp + 25);
 1652     } else {
 1653         qqi = ((GET_U_1(bp + 25) & 0x0f) | 0x10) <<
 1654                (((GET_U_1(bp + 25) & 0x70) >> 4) + 3);
 1655     }
 1656     ND_PRINT(" qqi=%u", qqi);
 1657     }
 1658 
 1659     nsrcs = GET_BE_U_2(bp + 26);
 1660     if (nsrcs > 0) {
 1661     if (len < 28 + nsrcs * sizeof(nd_ipv6))
 1662         ND_PRINT(" [invalid number of sources]");
 1663     else if (ndo->ndo_vflag > 1) {
 1664         ND_PRINT(" {");
 1665         for (i = 0; i < nsrcs; i++) {
 1666         ND_PRINT(" %s", GET_IP6ADDR_STRING(bp + 28 + (i * sizeof(nd_ipv6))));
 1667         }
 1668         ND_PRINT(" }");
 1669     } else
 1670                 ND_PRINT(", %u source(s)", nsrcs);
 1671     }
 1672     ND_PRINT("]");
 1673 }
 1674 
 1675 static void
 1676 dnsname_print(netdissect_options *ndo, const u_char *cp, const u_char *ep)
 1677 {
 1678     int i;
 1679 
 1680     /* DNS name decoding - no decompression */
 1681     ND_PRINT(", \"");
 1682     while (cp < ep) {
 1683         i = GET_U_1(cp);
 1684         cp++;
 1685         if (i) {
 1686             if (i > ep - cp) {
 1687                 ND_PRINT("???");
 1688                 break;
 1689             }
 1690             while (i-- && cp < ep) {
 1691                 fn_print_char(ndo, GET_U_1(cp));
 1692                 cp++;
 1693             }
 1694             if (cp + 1 < ep && GET_U_1(cp))
 1695                 ND_PRINT(".");
 1696         } else {
 1697             if (cp == ep) {
 1698                 /* FQDN */
 1699                 ND_PRINT(".");
 1700             } else if (cp + 1 == ep && GET_U_1(cp) == '\0') {
 1701                 /* truncated */
 1702             } else {
 1703                 /* invalid */
 1704                 ND_PRINT("???");
 1705             }
 1706             break;
 1707         }
 1708     }
 1709     ND_PRINT("\"");
 1710 }
 1711 
 1712 static void
 1713 icmp6_nodeinfo_print(netdissect_options *ndo, u_int icmp6len, const u_char *bp, const u_char *ep)
 1714 {
 1715     const struct icmp6_nodeinfo *ni6;
 1716     const struct icmp6_hdr *dp;
 1717     const u_char *cp;
 1718     size_t siz, i;
 1719     int needcomma;
 1720 
 1721     if (ep < bp)
 1722         return;
 1723     dp = (const struct icmp6_hdr *)bp;
 1724     ni6 = (const struct icmp6_nodeinfo *)bp;
 1725     siz = ep - bp;
 1726 
 1727     switch (GET_U_1(ni6->ni_type)) {
 1728     case ICMP6_NI_QUERY:
 1729         if (siz == sizeof(*dp) + 4) {
 1730             /* KAME who-are-you */
 1731             ND_PRINT(" who-are-you request");
 1732             break;
 1733         }
 1734         ND_PRINT(" node information query");
 1735 
 1736         ND_TCHECK_LEN(dp, sizeof(*ni6));
 1737         ni6 = (const struct icmp6_nodeinfo *)dp;
 1738         ND_PRINT(" ("); /*)*/
 1739         switch (GET_BE_U_2(ni6->ni_qtype)) {
 1740         case NI_QTYPE_NOOP:
 1741             ND_PRINT("noop");
 1742             break;
 1743         case NI_QTYPE_SUPTYPES:
 1744             ND_PRINT("supported qtypes");
 1745             i = GET_BE_U_2(ni6->ni_flags);
 1746             if (i)
 1747                 ND_PRINT(" [%s]", (i & 0x01) ? "C" : "");
 1748             break;
 1749         case NI_QTYPE_FQDN:
 1750             ND_PRINT("DNS name");
 1751             break;
 1752         case NI_QTYPE_NODEADDR:
 1753             ND_PRINT("node addresses");
 1754             i = GET_BE_U_2(ni6->ni_flags);
 1755             if (!i)
 1756                 break;
 1757             /* NI_NODEADDR_FLAG_TRUNCATE undefined for query */
 1758             ND_PRINT(" [%s%s%s%s%s%s]",
 1759                 (i & NI_NODEADDR_FLAG_ANYCAST) ? "a" : "",
 1760                 (i & NI_NODEADDR_FLAG_GLOBAL) ? "G" : "",
 1761                 (i & NI_NODEADDR_FLAG_SITELOCAL) ? "S" : "",
 1762                 (i & NI_NODEADDR_FLAG_LINKLOCAL) ? "L" : "",
 1763                 (i & NI_NODEADDR_FLAG_COMPAT) ? "C" : "",
 1764                 (i & NI_NODEADDR_FLAG_ALL) ? "A" : "");
 1765             break;
 1766         default:
 1767             ND_PRINT("unknown");
 1768             break;
 1769         }
 1770 
 1771         if (GET_BE_U_2(ni6->ni_qtype) == NI_QTYPE_NOOP ||
 1772             GET_BE_U_2(ni6->ni_qtype) == NI_QTYPE_SUPTYPES) {
 1773             if (siz != sizeof(*ni6))
 1774                 if (ndo->ndo_vflag)
 1775                     ND_PRINT(", invalid len");
 1776             /*(*/
 1777             ND_PRINT(")");
 1778             break;
 1779         }
 1780 
 1781 
 1782         /* XXX backward compat, icmp-name-lookup-03 */
 1783         if (siz == sizeof(*ni6)) {
 1784             ND_PRINT(", 03 draft");
 1785             /*(*/
 1786             ND_PRINT(")");
 1787             break;
 1788         }
 1789 
 1790         cp = (const u_char *)(ni6 + 1);
 1791         switch (GET_U_1(ni6->ni_code)) {
 1792         case ICMP6_NI_SUBJ_IPV6:
 1793             if (!ND_TTEST_LEN(dp, sizeof(*ni6) + sizeof(nd_ipv6)))
 1794                 break;
 1795             if (siz != sizeof(*ni6) + sizeof(nd_ipv6)) {
 1796                 if (ndo->ndo_vflag)
 1797                     ND_PRINT(", invalid subject len");
 1798                 break;
 1799             }
 1800             ND_PRINT(", subject=%s",
 1801                                   GET_IP6ADDR_STRING(cp));
 1802             break;
 1803         case ICMP6_NI_SUBJ_FQDN:
 1804             ND_PRINT(", subject=DNS name");
 1805             if (GET_U_1(cp) == ep - cp - 1) {
 1806                 /* icmp-name-lookup-03, pascal string */
 1807                 if (ndo->ndo_vflag)
 1808                     ND_PRINT(", 03 draft");
 1809                 cp++;
 1810                 ND_PRINT(", \"");
 1811                 while (cp < ep) {
 1812                     fn_print_char(ndo, GET_U_1(cp));
 1813                     cp++;
 1814                 }
 1815                 ND_PRINT("\"");
 1816             } else
 1817                 dnsname_print(ndo, cp, ep);
 1818             break;
 1819         case ICMP6_NI_SUBJ_IPV4:
 1820             if (!ND_TTEST_LEN(dp, sizeof(*ni6) + sizeof(nd_ipv4)))
 1821                 break;
 1822             if (siz != sizeof(*ni6) + sizeof(nd_ipv4)) {
 1823                 if (ndo->ndo_vflag)
 1824                     ND_PRINT(", invalid subject len");
 1825                 break;
 1826             }
 1827             ND_PRINT(", subject=%s",
 1828                                   GET_IPADDR_STRING(cp));
 1829             break;
 1830         default:
 1831             ND_PRINT(", unknown subject");
 1832             break;
 1833         }
 1834 
 1835         /*(*/
 1836         ND_PRINT(")");
 1837         break;
 1838 
 1839     case ICMP6_NI_REPLY:
 1840         if (icmp6len > siz)
 1841             goto trunc;
 1842 
 1843         needcomma = 0;
 1844 
 1845         ND_TCHECK_LEN(dp, sizeof(*ni6));
 1846         ni6 = (const struct icmp6_nodeinfo *)dp;
 1847         ND_PRINT(" node information reply");
 1848         ND_PRINT(" ("); /*)*/
 1849         switch (GET_U_1(ni6->ni_code)) {
 1850         case ICMP6_NI_SUCCESS:
 1851             if (ndo->ndo_vflag) {
 1852                 ND_PRINT("success");
 1853                 needcomma++;
 1854             }
 1855             break;
 1856         case ICMP6_NI_REFUSED:
 1857             ND_PRINT("refused");
 1858             needcomma++;
 1859             if (siz != sizeof(*ni6))
 1860                 if (ndo->ndo_vflag)
 1861                     ND_PRINT(", invalid length");
 1862             break;
 1863         case ICMP6_NI_UNKNOWN:
 1864             ND_PRINT("unknown");
 1865             needcomma++;
 1866             if (siz != sizeof(*ni6))
 1867                 if (ndo->ndo_vflag)
 1868                     ND_PRINT(", invalid length");
 1869             break;
 1870         }
 1871 
 1872         if (GET_U_1(ni6->ni_code) != ICMP6_NI_SUCCESS) {
 1873             /*(*/
 1874             ND_PRINT(")");
 1875             break;
 1876         }
 1877 
 1878         switch (GET_BE_U_2(ni6->ni_qtype)) {
 1879         case NI_QTYPE_NOOP:
 1880             if (needcomma)
 1881                 ND_PRINT(", ");
 1882             ND_PRINT("noop");
 1883             if (siz != sizeof(*ni6))
 1884                 if (ndo->ndo_vflag)
 1885                     ND_PRINT(", invalid length");
 1886             break;
 1887         case NI_QTYPE_SUPTYPES:
 1888             if (needcomma)
 1889                 ND_PRINT(", ");
 1890             ND_PRINT("supported qtypes");
 1891             i = GET_BE_U_2(ni6->ni_flags);
 1892             if (i)
 1893                 ND_PRINT(" [%s]", (i & 0x01) ? "C" : "");
 1894             break;
 1895         case NI_QTYPE_FQDN:
 1896             if (needcomma)
 1897                 ND_PRINT(", ");
 1898             ND_PRINT("DNS name");
 1899             cp = (const u_char *)(ni6 + 1) + 4;
 1900             if (GET_U_1(cp) == ep - cp - 1) {
 1901                 /* icmp-name-lookup-03, pascal string */
 1902                 if (ndo->ndo_vflag)
 1903                     ND_PRINT(", 03 draft");
 1904                 cp++;
 1905                 ND_PRINT(", \"");
 1906                 while (cp < ep) {
 1907                     fn_print_char(ndo, GET_U_1(cp));
 1908                     cp++;
 1909                 }
 1910                 ND_PRINT("\"");
 1911             } else
 1912                 dnsname_print(ndo, cp, ep);
 1913             if ((GET_BE_U_2(ni6->ni_flags) & 0x01) != 0)
 1914                 ND_PRINT(" [TTL=%u]", GET_BE_U_4(ni6 + 1));
 1915             break;
 1916         case NI_QTYPE_NODEADDR:
 1917             if (needcomma)
 1918                 ND_PRINT(", ");
 1919             ND_PRINT("node addresses");
 1920             i = sizeof(*ni6);
 1921             while (i < siz) {
 1922                 if (i + sizeof(uint32_t) + sizeof(nd_ipv6) > siz)
 1923                     break;
 1924                 ND_PRINT(" %s(%u)",
 1925                     GET_IP6ADDR_STRING(bp + i + sizeof(uint32_t)),
 1926                     GET_BE_U_4(bp + i));
 1927                 i += sizeof(uint32_t) + sizeof(nd_ipv6);
 1928             }
 1929             i = GET_BE_U_2(ni6->ni_flags);
 1930             if (!i)
 1931                 break;
 1932             ND_PRINT(" [%s%s%s%s%s%s%s]",
 1933                                   (i & NI_NODEADDR_FLAG_ANYCAST) ? "a" : "",
 1934                                   (i & NI_NODEADDR_FLAG_GLOBAL) ? "G" : "",
 1935                                   (i & NI_NODEADDR_FLAG_SITELOCAL) ? "S" : "",
 1936                                   (i & NI_NODEADDR_FLAG_LINKLOCAL) ? "L" : "",
 1937                                   (i & NI_NODEADDR_FLAG_COMPAT) ? "C" : "",
 1938                                   (i & NI_NODEADDR_FLAG_ALL) ? "A" : "",
 1939                                   (i & NI_NODEADDR_FLAG_TRUNCATE) ? "T" : "");
 1940             break;
 1941         default:
 1942             if (needcomma)
 1943                 ND_PRINT(", ");
 1944             ND_PRINT("unknown");
 1945             break;
 1946         }
 1947 
 1948         /*(*/
 1949         ND_PRINT(")");
 1950         break;
 1951     }
 1952     return;
 1953 
 1954 trunc:
 1955     nd_print_trunc(ndo);
 1956 }
 1957 
 1958 static void
 1959 icmp6_rrenum_print(netdissect_options *ndo, const u_char *bp, const u_char *ep)
 1960 {
 1961     const struct icmp6_router_renum *rr6;
 1962     const char *cp;
 1963     const struct rr_pco_match *match;
 1964     const struct rr_pco_use *use;
 1965     char hbuf[NI_MAXHOST];
 1966     int n;
 1967 
 1968     if (ep < bp)
 1969         return;
 1970     rr6 = (const struct icmp6_router_renum *)bp;
 1971     cp = (const char *)(rr6 + 1);
 1972 
 1973     ND_TCHECK_4(rr6->rr_reserved);
 1974     switch (GET_U_1(rr6->rr_code)) {
 1975     case ICMP6_ROUTER_RENUMBERING_COMMAND:
 1976         ND_PRINT("router renum: command");
 1977         break;
 1978     case ICMP6_ROUTER_RENUMBERING_RESULT:
 1979         ND_PRINT("router renum: result");
 1980         break;
 1981     case ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET:
 1982         ND_PRINT("router renum: sequence number reset");
 1983         break;
 1984     default:
 1985         ND_PRINT("router renum: code-#%u", GET_U_1(rr6->rr_code));
 1986         break;
 1987     }
 1988 
 1989         ND_PRINT(", seq=%u", GET_BE_U_4(rr6->rr_seqnum));
 1990 
 1991     if (ndo->ndo_vflag) {
 1992         uint8_t rr_flags = GET_U_1(rr6->rr_flags);
 1993 #define F(x, y) (rr_flags & (x) ? (y) : "")
 1994         ND_PRINT("[");  /*]*/
 1995         if (rr_flags) {
 1996             ND_PRINT("%s%s%s%s%s,", F(ICMP6_RR_FLAGS_TEST, "T"),
 1997                                   F(ICMP6_RR_FLAGS_REQRESULT, "R"),
 1998                                   F(ICMP6_RR_FLAGS_FORCEAPPLY, "A"),
 1999                                   F(ICMP6_RR_FLAGS_SPECSITE, "S"),
 2000                                   F(ICMP6_RR_FLAGS_PREVDONE, "P"));
 2001         }
 2002                 ND_PRINT("seg=%u,", GET_U_1(rr6->rr_segnum));
 2003                 ND_PRINT("maxdelay=%u", GET_BE_U_2(rr6->rr_maxdelay));
 2004         if (GET_BE_U_4(rr6->rr_reserved))
 2005             ND_PRINT("rsvd=0x%x", GET_BE_U_4(rr6->rr_reserved));
 2006         /*[*/
 2007         ND_PRINT("]");
 2008 #undef F
 2009     }
 2010 
 2011     if (GET_U_1(rr6->rr_code) == ICMP6_ROUTER_RENUMBERING_COMMAND) {
 2012         match = (const struct rr_pco_match *)cp;
 2013         cp = (const char *)(match + 1);
 2014 
 2015         ND_TCHECK_16(match->rpm_prefix);
 2016 
 2017         if (ndo->ndo_vflag > 1)
 2018             ND_PRINT("\n\t");
 2019         else
 2020             ND_PRINT(" ");
 2021         ND_PRINT("match("); /*)*/
 2022         switch (GET_U_1(match->rpm_code)) {
 2023         case RPM_PCO_ADD:   ND_PRINT("add"); break;
 2024         case RPM_PCO_CHANGE:    ND_PRINT("change"); break;
 2025         case RPM_PCO_SETGLOBAL: ND_PRINT("setglobal"); break;
 2026         default:        ND_PRINT("#%u",
 2027                          GET_U_1(match->rpm_code)); break;
 2028         }
 2029 
 2030         if (ndo->ndo_vflag) {
 2031             ND_PRINT(",ord=%u", GET_U_1(match->rpm_ordinal));
 2032             ND_PRINT(",min=%u", GET_U_1(match->rpm_minlen));
 2033             ND_PRINT(",max=%u", GET_U_1(match->rpm_maxlen));
 2034         }
 2035         if (addrtostr6(match->rpm_prefix, hbuf, sizeof(hbuf)))
 2036             ND_PRINT(",%s/%u", hbuf, GET_U_1(match->rpm_matchlen));
 2037         else
 2038             ND_PRINT(",?/%u", GET_U_1(match->rpm_matchlen));
 2039         /*(*/
 2040         ND_PRINT(")");
 2041 
 2042         n = GET_U_1(match->rpm_len) - 3;
 2043         if (n % 4)
 2044             goto trunc;
 2045         n /= 4;
 2046         while (n-- > 0) {
 2047             use = (const struct rr_pco_use *)cp;
 2048             cp = (const char *)(use + 1);
 2049 
 2050             ND_TCHECK_16(use->rpu_prefix);
 2051 
 2052             if (ndo->ndo_vflag > 1)
 2053                 ND_PRINT("\n\t");
 2054             else
 2055                 ND_PRINT(" ");
 2056             ND_PRINT("use(");   /*)*/
 2057             if (GET_U_1(use->rpu_flags)) {
 2058 #define F(x, y) (GET_U_1(use->rpu_flags) & (x) ? (y) : "")
 2059                 ND_PRINT("%s%s,",
 2060                                           F(ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME, "V"),
 2061                                           F(ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME, "P"));
 2062 #undef F
 2063             }
 2064             if (ndo->ndo_vflag) {
 2065                 ND_PRINT("mask=0x%x,",
 2066                      GET_U_1(use->rpu_ramask));
 2067                 ND_PRINT("raflags=0x%x,",
 2068                      GET_U_1(use->rpu_raflags));
 2069                 if (GET_BE_U_4(use->rpu_vltime) == 0xffffffff)
 2070                     ND_PRINT("vltime=infty,");
 2071                 else
 2072                     ND_PRINT("vltime=%u,",
 2073                                                   GET_BE_U_4(use->rpu_vltime));
 2074                 if (GET_BE_U_4(use->rpu_pltime) == 0xffffffff)
 2075                     ND_PRINT("pltime=infty,");
 2076                 else
 2077                     ND_PRINT("pltime=%u,",
 2078                                                   GET_BE_U_4(use->rpu_pltime));
 2079             }
 2080             if (addrtostr6(use->rpu_prefix, hbuf, sizeof(hbuf)))
 2081                 ND_PRINT("%s/%u/%u", hbuf,
 2082                                           GET_U_1(use->rpu_uselen),
 2083                                           GET_U_1(use->rpu_keeplen));
 2084             else
 2085                 ND_PRINT("?/%u/%u", GET_U_1(use->rpu_uselen),
 2086                                           GET_U_1(use->rpu_keeplen));
 2087             /*(*/
 2088                         ND_PRINT(")");
 2089         }
 2090     }
 2091 
 2092     return;
 2093 
 2094 trunc:
 2095     nd_print_trunc(ndo);
 2096 }