1b0453382SBill Fenner /* 2b0453382SBill Fenner * Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994 3b0453382SBill Fenner * The Regents of the University of California. All rights reserved. 4b0453382SBill Fenner * 5b0453382SBill Fenner * Redistribution and use in source and binary forms, with or without 6b0453382SBill Fenner * modification, are permitted provided that: (1) source code distributions 7b0453382SBill Fenner * retain the above copyright notice and this paragraph in its entirety, (2) 8b0453382SBill Fenner * distributions including binary code include the above copyright notice and 9b0453382SBill Fenner * this paragraph in its entirety in the documentation or other materials 10b0453382SBill Fenner * provided with the distribution, and (3) all advertising materials mentioning 11b0453382SBill Fenner * features or use of this software display the following acknowledgement: 12b0453382SBill Fenner * ``This product includes software developed by the University of California, 13b0453382SBill Fenner * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14b0453382SBill Fenner * the University nor the names of its contributors may be used to endorse 15b0453382SBill Fenner * or promote products derived from this software without specific prior 16b0453382SBill Fenner * written permission. 17b0453382SBill Fenner * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18b0453382SBill Fenner * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19b0453382SBill Fenner * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20b0453382SBill Fenner */ 21b0453382SBill Fenner 223340d773SGleb Smirnoff /* \summary: IPv6 Internet Control Message Protocol (ICMPv6) printer */ 233340d773SGleb Smirnoff 24b0453382SBill Fenner #ifdef HAVE_CONFIG_H 25*ee67461eSJoseph Mingrone #include <config.h> 26b0453382SBill Fenner #endif 27b0453382SBill Fenner 28*ee67461eSJoseph Mingrone #include "netdissect-stdinc.h" 29b0453382SBill Fenner 30b0453382SBill Fenner #include <stdio.h> 31a90e161bSBill Fenner #include <string.h> 32b0453382SBill Fenner 333340d773SGleb Smirnoff #include "netdissect.h" 34b0453382SBill Fenner #include "addrtoname.h" 353340d773SGleb Smirnoff #include "addrtostr.h" 365b0fe478SBruce M Simpson #include "extract.h" 37b0453382SBill Fenner 38f4d0c64aSSam Leffler #include "ip6.h" 39f4d0c64aSSam Leffler #include "ipproto.h" 40f4d0c64aSSam Leffler 41685295f4SBill Fenner #include "udp.h" 42685295f4SBill Fenner #include "ah.h" 43685295f4SBill Fenner 443c602fabSXin LI /* NetBSD: icmp6.h,v 1.13 2000/08/03 16:30:37 itojun Exp */ 453c602fabSXin LI /* $KAME: icmp6.h,v 1.22 2000/08/03 15:25:16 jinmei Exp $ */ 463c602fabSXin LI 473c602fabSXin LI /* 483c602fabSXin LI * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 493c602fabSXin LI * All rights reserved. 503c602fabSXin LI * 513c602fabSXin LI * Redistribution and use in source and binary forms, with or without 523c602fabSXin LI * modification, are permitted provided that the following conditions 533c602fabSXin LI * are met: 543c602fabSXin LI * 1. Redistributions of source code must retain the above copyright 553c602fabSXin LI * notice, this list of conditions and the following disclaimer. 563c602fabSXin LI * 2. Redistributions in binary form must reproduce the above copyright 573c602fabSXin LI * notice, this list of conditions and the following disclaimer in the 583c602fabSXin LI * documentation and/or other materials provided with the distribution. 593c602fabSXin LI * 3. Neither the name of the project nor the names of its contributors 603c602fabSXin LI * may be used to endorse or promote products derived from this software 613c602fabSXin LI * without specific prior written permission. 623c602fabSXin LI * 633c602fabSXin LI * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 643c602fabSXin LI * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 653c602fabSXin LI * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 663c602fabSXin LI * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 673c602fabSXin LI * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 683c602fabSXin LI * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 693c602fabSXin LI * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 703c602fabSXin LI * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 713c602fabSXin LI * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 723c602fabSXin LI * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 733c602fabSXin LI * SUCH DAMAGE. 743c602fabSXin LI */ 753c602fabSXin LI 763c602fabSXin LI struct icmp6_hdr { 77*ee67461eSJoseph Mingrone nd_uint8_t icmp6_type; /* type field */ 78*ee67461eSJoseph Mingrone nd_uint8_t icmp6_code; /* code field */ 79*ee67461eSJoseph Mingrone nd_uint16_t icmp6_cksum; /* checksum field */ 803c602fabSXin LI union { 81*ee67461eSJoseph Mingrone nd_uint32_t icmp6_un_data32[1]; /* type-specific field */ 82*ee67461eSJoseph Mingrone nd_uint16_t icmp6_un_data16[2]; /* type-specific field */ 83*ee67461eSJoseph Mingrone nd_uint8_t icmp6_un_data8[4]; /* type-specific field */ 84*ee67461eSJoseph Mingrone nd_byte icmp6_un_data[1]; /* type-specific field */ 853c602fabSXin LI } icmp6_dataun; 863c602fabSXin LI }; 873c602fabSXin LI 883c602fabSXin LI #define icmp6_data32 icmp6_dataun.icmp6_un_data32 893c602fabSXin LI #define icmp6_data16 icmp6_dataun.icmp6_un_data16 903c602fabSXin LI #define icmp6_data8 icmp6_dataun.icmp6_un_data8 91*ee67461eSJoseph Mingrone #define icmp6_data icmp6_dataun.icmp6_un_data 923c602fabSXin LI #define icmp6_pptr icmp6_data32[0] /* parameter prob */ 933c602fabSXin LI #define icmp6_mtu icmp6_data32[0] /* packet too big */ 943c602fabSXin LI #define icmp6_id icmp6_data16[0] /* echo request/reply */ 953c602fabSXin LI #define icmp6_seq icmp6_data16[1] /* echo request/reply */ 963c602fabSXin LI #define icmp6_maxdelay icmp6_data16[0] /* mcast group membership */ 973c602fabSXin LI 983c602fabSXin LI #define ICMP6_DST_UNREACH 1 /* dest unreachable, codes: */ 993c602fabSXin LI #define ICMP6_PACKET_TOO_BIG 2 /* packet too big */ 1003c602fabSXin LI #define ICMP6_TIME_EXCEEDED 3 /* time exceeded, code: */ 1013c602fabSXin LI #define ICMP6_PARAM_PROB 4 /* ip6 header bad */ 1023c602fabSXin LI 1033c602fabSXin LI #define ICMP6_ECHO_REQUEST 128 /* echo service */ 1043c602fabSXin LI #define ICMP6_ECHO_REPLY 129 /* echo reply */ 1053c602fabSXin LI #define ICMP6_MEMBERSHIP_QUERY 130 /* group membership query */ 1063c602fabSXin LI #define MLD6_LISTENER_QUERY 130 /* multicast listener query */ 1073c602fabSXin LI #define ICMP6_MEMBERSHIP_REPORT 131 /* group membership report */ 1083c602fabSXin LI #define MLD6_LISTENER_REPORT 131 /* multicast listener report */ 1093c602fabSXin LI #define ICMP6_MEMBERSHIP_REDUCTION 132 /* group membership termination */ 1103c602fabSXin LI #define MLD6_LISTENER_DONE 132 /* multicast listener done */ 1113c602fabSXin LI 1123c602fabSXin LI #define ND_ROUTER_SOLICIT 133 /* router solicitation */ 1133c602fabSXin LI #define ND_ROUTER_ADVERT 134 /* router advertisement */ 1143c602fabSXin LI #define ND_NEIGHBOR_SOLICIT 135 /* neighbor solicitation */ 1153c602fabSXin LI #define ND_NEIGHBOR_ADVERT 136 /* neighbor advertisement */ 1163c602fabSXin LI #define ND_REDIRECT 137 /* redirect */ 1173c602fabSXin LI 1183c602fabSXin LI #define ICMP6_ROUTER_RENUMBERING 138 /* router renumbering */ 1193c602fabSXin LI 1203c602fabSXin LI #define ICMP6_WRUREQUEST 139 /* who are you request */ 1213c602fabSXin LI #define ICMP6_WRUREPLY 140 /* who are you reply */ 1223c602fabSXin LI #define ICMP6_FQDN_QUERY 139 /* FQDN query */ 1233c602fabSXin LI #define ICMP6_FQDN_REPLY 140 /* FQDN reply */ 124*ee67461eSJoseph Mingrone #define ICMP6_NI_QUERY 139 /* node information request - RFC 4620 */ 125*ee67461eSJoseph Mingrone #define ICMP6_NI_REPLY 140 /* node information reply - RFC 4620 */ 1263c602fabSXin LI #define IND_SOLICIT 141 /* inverse neighbor solicitation */ 1273c602fabSXin LI #define IND_ADVERT 142 /* inverse neighbor advertisement */ 1283c602fabSXin LI 1293c602fabSXin LI #define ICMP6_V2_MEMBERSHIP_REPORT 143 /* v2 membership report */ 1303c602fabSXin LI #define MLDV2_LISTENER_REPORT 143 /* v2 multicast listener report */ 1313c602fabSXin LI #define ICMP6_HADISCOV_REQUEST 144 1323c602fabSXin LI #define ICMP6_HADISCOV_REPLY 145 1333c602fabSXin LI #define ICMP6_MOBILEPREFIX_SOLICIT 146 1343c602fabSXin LI #define ICMP6_MOBILEPREFIX_ADVERT 147 1353c602fabSXin LI 1363c602fabSXin LI #define MLD6_MTRACE_RESP 200 /* mtrace response(to sender) */ 1373c602fabSXin LI #define MLD6_MTRACE 201 /* mtrace messages */ 1383c602fabSXin LI 1393c602fabSXin LI #define ICMP6_MAXTYPE 201 1403c602fabSXin LI 1413c602fabSXin LI #define ICMP6_DST_UNREACH_NOROUTE 0 /* no route to destination */ 1423c602fabSXin LI #define ICMP6_DST_UNREACH_ADMIN 1 /* administratively prohibited */ 1433c602fabSXin LI #define ICMP6_DST_UNREACH_NOTNEIGHBOR 2 /* not a neighbor(obsolete) */ 1443c602fabSXin LI #define ICMP6_DST_UNREACH_BEYONDSCOPE 2 /* beyond scope of source address */ 1453c602fabSXin LI #define ICMP6_DST_UNREACH_ADDR 3 /* address unreachable */ 1463c602fabSXin LI #define ICMP6_DST_UNREACH_NOPORT 4 /* port unreachable */ 1473c602fabSXin LI 1483c602fabSXin LI #define ICMP6_TIME_EXCEED_TRANSIT 0 /* ttl==0 in transit */ 1493c602fabSXin LI #define ICMP6_TIME_EXCEED_REASSEMBLY 1 /* ttl==0 in reass */ 1503c602fabSXin LI 1513c602fabSXin LI #define ICMP6_PARAMPROB_HEADER 0 /* erroneous header field */ 1523c602fabSXin LI #define ICMP6_PARAMPROB_NEXTHEADER 1 /* unrecognized next header */ 1533c602fabSXin LI #define ICMP6_PARAMPROB_OPTION 2 /* unrecognized option */ 154*ee67461eSJoseph Mingrone #define ICMP6_PARAMPROB_FRAGHDRCHAIN 3 /* incomplete header chain */ 1553c602fabSXin LI 1563c602fabSXin LI #define ICMP6_INFOMSG_MASK 0x80 /* all informational messages */ 1573c602fabSXin LI 1583c602fabSXin LI #define ICMP6_NI_SUBJ_IPV6 0 /* Query Subject is an IPv6 address */ 1593c602fabSXin LI #define ICMP6_NI_SUBJ_FQDN 1 /* Query Subject is a Domain name */ 1603c602fabSXin LI #define ICMP6_NI_SUBJ_IPV4 2 /* Query Subject is an IPv4 address */ 1613c602fabSXin LI 1623c602fabSXin LI #define ICMP6_NI_SUCCESS 0 /* node information successful reply */ 1633c602fabSXin LI #define ICMP6_NI_REFUSED 1 /* node information request is refused */ 1643c602fabSXin LI #define ICMP6_NI_UNKNOWN 2 /* unknown Qtype */ 1653c602fabSXin LI 1663c602fabSXin LI #define ICMP6_ROUTER_RENUMBERING_COMMAND 0 /* rr command */ 1673c602fabSXin LI #define ICMP6_ROUTER_RENUMBERING_RESULT 1 /* rr result */ 1683c602fabSXin LI #define ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET 255 /* rr seq num reset */ 1693c602fabSXin LI 1703c602fabSXin LI /* Used in kernel only */ 1713c602fabSXin LI #define ND_REDIRECT_ONLINK 0 /* redirect to an on-link node */ 1723c602fabSXin LI #define ND_REDIRECT_ROUTER 1 /* redirect to a better router */ 1733c602fabSXin LI 1743c602fabSXin LI /* 1753c602fabSXin LI * Multicast Listener Discovery 1763c602fabSXin LI */ 1773c602fabSXin LI struct mld6_hdr { 1783c602fabSXin LI struct icmp6_hdr mld6_hdr; 179*ee67461eSJoseph Mingrone nd_ipv6 mld6_addr; /* multicast address */ 1803c602fabSXin LI }; 1813c602fabSXin LI 1823c602fabSXin LI #define mld6_type mld6_hdr.icmp6_type 1833c602fabSXin LI #define mld6_code mld6_hdr.icmp6_code 1843c602fabSXin LI #define mld6_cksum mld6_hdr.icmp6_cksum 1853c602fabSXin LI #define mld6_maxdelay mld6_hdr.icmp6_data16[0] 1863c602fabSXin LI #define mld6_reserved mld6_hdr.icmp6_data16[1] 1873c602fabSXin LI 1883c602fabSXin LI #define MLD_MINLEN 24 1893c602fabSXin LI #define MLDV2_MINLEN 28 1903c602fabSXin LI 1913c602fabSXin LI /* 1923c602fabSXin LI * Neighbor Discovery 1933c602fabSXin LI */ 1943c602fabSXin LI 1953c602fabSXin LI struct nd_router_solicit { /* router solicitation */ 1963c602fabSXin LI struct icmp6_hdr nd_rs_hdr; 1973c602fabSXin LI /* could be followed by options */ 1983c602fabSXin LI }; 1993c602fabSXin LI 2003c602fabSXin LI #define nd_rs_type nd_rs_hdr.icmp6_type 2013c602fabSXin LI #define nd_rs_code nd_rs_hdr.icmp6_code 2023c602fabSXin LI #define nd_rs_cksum nd_rs_hdr.icmp6_cksum 2033c602fabSXin LI #define nd_rs_reserved nd_rs_hdr.icmp6_data32[0] 2043c602fabSXin LI 2053c602fabSXin LI struct nd_router_advert { /* router advertisement */ 2063c602fabSXin LI struct icmp6_hdr nd_ra_hdr; 207*ee67461eSJoseph Mingrone nd_uint32_t nd_ra_reachable; /* reachable time */ 208*ee67461eSJoseph Mingrone nd_uint32_t nd_ra_retransmit; /* retransmit timer */ 2093c602fabSXin LI /* could be followed by options */ 2103c602fabSXin LI }; 2113c602fabSXin LI 2123c602fabSXin LI #define nd_ra_type nd_ra_hdr.icmp6_type 2133c602fabSXin LI #define nd_ra_code nd_ra_hdr.icmp6_code 2143c602fabSXin LI #define nd_ra_cksum nd_ra_hdr.icmp6_cksum 2153c602fabSXin LI #define nd_ra_curhoplimit nd_ra_hdr.icmp6_data8[0] 2163c602fabSXin LI #define nd_ra_flags_reserved nd_ra_hdr.icmp6_data8[1] 2173c602fabSXin LI #define ND_RA_FLAG_MANAGED 0x80 2183c602fabSXin LI #define ND_RA_FLAG_OTHER 0x40 2193c602fabSXin LI #define ND_RA_FLAG_HOME_AGENT 0x20 220*ee67461eSJoseph Mingrone #define ND_RA_FLAG_IPV6ONLY 0x02 2213c602fabSXin LI 2223c602fabSXin LI /* 2233c602fabSXin LI * Router preference values based on draft-draves-ipngwg-router-selection-01. 2243c602fabSXin LI * These are non-standard definitions. 2253c602fabSXin LI */ 2263c602fabSXin LI #define ND_RA_FLAG_RTPREF_MASK 0x18 /* 00011000 */ 2273c602fabSXin LI 2283c602fabSXin LI #define ND_RA_FLAG_RTPREF_HIGH 0x08 /* 00001000 */ 2293c602fabSXin LI #define ND_RA_FLAG_RTPREF_MEDIUM 0x00 /* 00000000 */ 2303c602fabSXin LI #define ND_RA_FLAG_RTPREF_LOW 0x18 /* 00011000 */ 2313c602fabSXin LI #define ND_RA_FLAG_RTPREF_RSV 0x10 /* 00010000 */ 2323c602fabSXin LI 2333c602fabSXin LI #define nd_ra_router_lifetime nd_ra_hdr.icmp6_data16[1] 2343c602fabSXin LI 2353c602fabSXin LI struct nd_neighbor_solicit { /* neighbor solicitation */ 2363c602fabSXin LI struct icmp6_hdr nd_ns_hdr; 237*ee67461eSJoseph Mingrone nd_ipv6 nd_ns_target; /*target address */ 2383c602fabSXin LI /* could be followed by options */ 2393c602fabSXin LI }; 2403c602fabSXin LI 2413c602fabSXin LI #define nd_ns_type nd_ns_hdr.icmp6_type 2423c602fabSXin LI #define nd_ns_code nd_ns_hdr.icmp6_code 2433c602fabSXin LI #define nd_ns_cksum nd_ns_hdr.icmp6_cksum 2443c602fabSXin LI #define nd_ns_reserved nd_ns_hdr.icmp6_data32[0] 2453c602fabSXin LI 2463c602fabSXin LI struct nd_neighbor_advert { /* neighbor advertisement */ 2473c602fabSXin LI struct icmp6_hdr nd_na_hdr; 248*ee67461eSJoseph Mingrone nd_ipv6 nd_na_target; /* target address */ 2493c602fabSXin LI /* could be followed by options */ 2503c602fabSXin LI }; 2513c602fabSXin LI 2523c602fabSXin LI #define nd_na_type nd_na_hdr.icmp6_type 2533c602fabSXin LI #define nd_na_code nd_na_hdr.icmp6_code 2543c602fabSXin LI #define nd_na_cksum nd_na_hdr.icmp6_cksum 2553c602fabSXin LI #define nd_na_flags_reserved nd_na_hdr.icmp6_data32[0] 2563c602fabSXin LI 2573c602fabSXin LI #define ND_NA_FLAG_ROUTER 0x80000000 2583c602fabSXin LI #define ND_NA_FLAG_SOLICITED 0x40000000 2593c602fabSXin LI #define ND_NA_FLAG_OVERRIDE 0x20000000 2603c602fabSXin LI 2613c602fabSXin LI struct nd_redirect { /* redirect */ 2623c602fabSXin LI struct icmp6_hdr nd_rd_hdr; 263*ee67461eSJoseph Mingrone nd_ipv6 nd_rd_target; /* target address */ 264*ee67461eSJoseph Mingrone nd_ipv6 nd_rd_dst; /* destination address */ 2653c602fabSXin LI /* could be followed by options */ 2663c602fabSXin LI }; 2673c602fabSXin LI 2683c602fabSXin LI #define nd_rd_type nd_rd_hdr.icmp6_type 2693c602fabSXin LI #define nd_rd_code nd_rd_hdr.icmp6_code 2703c602fabSXin LI #define nd_rd_cksum nd_rd_hdr.icmp6_cksum 2713c602fabSXin LI #define nd_rd_reserved nd_rd_hdr.icmp6_data32[0] 2723c602fabSXin LI 2733c602fabSXin LI struct nd_opt_hdr { /* Neighbor discovery option header */ 274*ee67461eSJoseph Mingrone nd_uint8_t nd_opt_type; 275*ee67461eSJoseph Mingrone nd_uint8_t nd_opt_len; 2763c602fabSXin LI /* followed by option specific data*/ 2773c602fabSXin LI }; 2783c602fabSXin LI 2793c602fabSXin LI #define ND_OPT_SOURCE_LINKADDR 1 2803c602fabSXin LI #define ND_OPT_TARGET_LINKADDR 2 2813c602fabSXin LI #define ND_OPT_PREFIX_INFORMATION 3 2823c602fabSXin LI #define ND_OPT_REDIRECTED_HEADER 4 2833c602fabSXin LI #define ND_OPT_MTU 5 2843c602fabSXin LI #define ND_OPT_ADVINTERVAL 7 2853c602fabSXin LI #define ND_OPT_HOMEAGENT_INFO 8 2863c602fabSXin LI #define ND_OPT_ROUTE_INFO 24 /* RFC4191 */ 2873c602fabSXin LI #define ND_OPT_RDNSS 25 2883c602fabSXin LI #define ND_OPT_DNSSL 31 2893c602fabSXin LI 2903c602fabSXin LI struct nd_opt_prefix_info { /* prefix information */ 2913340d773SGleb Smirnoff nd_uint8_t nd_opt_pi_type; 2923340d773SGleb Smirnoff nd_uint8_t nd_opt_pi_len; 2933340d773SGleb Smirnoff nd_uint8_t nd_opt_pi_prefix_len; 2943340d773SGleb Smirnoff nd_uint8_t nd_opt_pi_flags_reserved; 2953340d773SGleb Smirnoff nd_uint32_t nd_opt_pi_valid_time; 2963340d773SGleb Smirnoff nd_uint32_t nd_opt_pi_preferred_time; 2973340d773SGleb Smirnoff nd_uint32_t nd_opt_pi_reserved2; 298*ee67461eSJoseph Mingrone nd_ipv6 nd_opt_pi_prefix; 2993c602fabSXin LI }; 3003c602fabSXin LI 3013c602fabSXin LI #define ND_OPT_PI_FLAG_ONLINK 0x80 3023c602fabSXin LI #define ND_OPT_PI_FLAG_AUTO 0x40 3033c602fabSXin LI #define ND_OPT_PI_FLAG_ROUTER 0x20 /*2292bis*/ 3043c602fabSXin LI 3053c602fabSXin LI struct nd_opt_rd_hdr { /* redirected header */ 306*ee67461eSJoseph Mingrone nd_uint8_t nd_opt_rh_type; 307*ee67461eSJoseph Mingrone nd_uint8_t nd_opt_rh_len; 308*ee67461eSJoseph Mingrone nd_uint16_t nd_opt_rh_reserved1; 309*ee67461eSJoseph Mingrone nd_uint32_t nd_opt_rh_reserved2; 3103c602fabSXin LI /* followed by IP header and data */ 3113c602fabSXin LI }; 3123c602fabSXin LI 3133c602fabSXin LI struct nd_opt_mtu { /* MTU option */ 314*ee67461eSJoseph Mingrone nd_uint8_t nd_opt_mtu_type; 315*ee67461eSJoseph Mingrone nd_uint8_t nd_opt_mtu_len; 316*ee67461eSJoseph Mingrone nd_uint16_t nd_opt_mtu_reserved; 317*ee67461eSJoseph Mingrone nd_uint32_t nd_opt_mtu_mtu; 3183c602fabSXin LI }; 3193c602fabSXin LI 3203c602fabSXin LI struct nd_opt_rdnss { /* RDNSS RFC 6106 5.1 */ 321*ee67461eSJoseph Mingrone nd_uint8_t nd_opt_rdnss_type; 322*ee67461eSJoseph Mingrone nd_uint8_t nd_opt_rdnss_len; 323*ee67461eSJoseph Mingrone nd_uint16_t nd_opt_rdnss_reserved; 324*ee67461eSJoseph Mingrone nd_uint32_t nd_opt_rdnss_lifetime; 325*ee67461eSJoseph Mingrone nd_ipv6 nd_opt_rdnss_addr[1]; /* variable-length */ 3263c602fabSXin LI }; 3273c602fabSXin LI 3283c602fabSXin LI struct nd_opt_dnssl { /* DNSSL RFC 6106 5.2 */ 329*ee67461eSJoseph Mingrone nd_uint8_t nd_opt_dnssl_type; 330*ee67461eSJoseph Mingrone nd_uint8_t nd_opt_dnssl_len; 331*ee67461eSJoseph Mingrone nd_uint16_t nd_opt_dnssl_reserved; 332*ee67461eSJoseph Mingrone nd_uint32_t nd_opt_dnssl_lifetime; 3333c602fabSXin LI /* followed by list of DNS search domains, variable-length */ 3343c602fabSXin LI }; 3353c602fabSXin LI 3363c602fabSXin LI struct nd_opt_advinterval { /* Advertisement interval option */ 337*ee67461eSJoseph Mingrone nd_uint8_t nd_opt_adv_type; 338*ee67461eSJoseph Mingrone nd_uint8_t nd_opt_adv_len; 339*ee67461eSJoseph Mingrone nd_uint16_t nd_opt_adv_reserved; 340*ee67461eSJoseph Mingrone nd_uint32_t nd_opt_adv_interval; 3413c602fabSXin LI }; 3423c602fabSXin LI 3433c602fabSXin LI struct nd_opt_homeagent_info { /* Home Agent info */ 344*ee67461eSJoseph Mingrone nd_uint8_t nd_opt_hai_type; 345*ee67461eSJoseph Mingrone nd_uint8_t nd_opt_hai_len; 346*ee67461eSJoseph Mingrone nd_uint16_t nd_opt_hai_reserved; 347*ee67461eSJoseph Mingrone nd_uint16_t nd_opt_hai_preference; 348*ee67461eSJoseph Mingrone nd_uint16_t nd_opt_hai_lifetime; 3493c602fabSXin LI }; 3503c602fabSXin LI 3513c602fabSXin LI struct nd_opt_route_info { /* route info */ 352*ee67461eSJoseph Mingrone nd_uint8_t nd_opt_rti_type; 353*ee67461eSJoseph Mingrone nd_uint8_t nd_opt_rti_len; 354*ee67461eSJoseph Mingrone nd_uint8_t nd_opt_rti_prefixlen; 355*ee67461eSJoseph Mingrone nd_uint8_t nd_opt_rti_flags; 356*ee67461eSJoseph Mingrone nd_uint32_t nd_opt_rti_lifetime; 3573c602fabSXin LI /* prefix follows */ 3583c602fabSXin LI }; 3593c602fabSXin LI 3603c602fabSXin LI /* 3613c602fabSXin LI * icmp6 namelookup 3623c602fabSXin LI */ 3633c602fabSXin LI 3643c602fabSXin LI struct icmp6_namelookup { 3653c602fabSXin LI struct icmp6_hdr icmp6_nl_hdr; 366*ee67461eSJoseph Mingrone nd_byte icmp6_nl_nonce[8]; 367*ee67461eSJoseph Mingrone nd_int32_t icmp6_nl_ttl; 3683c602fabSXin LI #if 0 369*ee67461eSJoseph Mingrone nd_uint8_t icmp6_nl_len; 370*ee67461eSJoseph Mingrone nd_byte icmp6_nl_name[3]; 3713c602fabSXin LI #endif 3723c602fabSXin LI /* could be followed by options */ 3733c602fabSXin LI }; 3743c602fabSXin LI 3753c602fabSXin LI /* 3763c602fabSXin LI * icmp6 node information 3773c602fabSXin LI */ 3783c602fabSXin LI struct icmp6_nodeinfo { 3793c602fabSXin LI struct icmp6_hdr icmp6_ni_hdr; 380*ee67461eSJoseph Mingrone nd_byte icmp6_ni_nonce[8]; 3813c602fabSXin LI /* could be followed by reply data */ 3823c602fabSXin LI }; 3833c602fabSXin LI 3843c602fabSXin LI #define ni_type icmp6_ni_hdr.icmp6_type 3853c602fabSXin LI #define ni_code icmp6_ni_hdr.icmp6_code 3863c602fabSXin LI #define ni_cksum icmp6_ni_hdr.icmp6_cksum 3873c602fabSXin LI #define ni_qtype icmp6_ni_hdr.icmp6_data16[0] 3883c602fabSXin LI #define ni_flags icmp6_ni_hdr.icmp6_data16[1] 3893c602fabSXin LI 3903c602fabSXin LI #define NI_QTYPE_NOOP 0 /* NOOP */ 391*ee67461eSJoseph Mingrone #define NI_QTYPE_SUPTYPES 1 /* Supported Qtypes (drafts up to 09) */ 3923c602fabSXin LI #define NI_QTYPE_FQDN 2 /* FQDN (draft 04) */ 3933c602fabSXin LI #define NI_QTYPE_DNSNAME 2 /* DNS Name */ 3943c602fabSXin LI #define NI_QTYPE_NODEADDR 3 /* Node Addresses */ 3953c602fabSXin LI #define NI_QTYPE_IPV4ADDR 4 /* IPv4 Addresses */ 3963c602fabSXin LI 397*ee67461eSJoseph Mingrone #define NI_NODEADDR_FLAG_TRUNCATE 0x0001 398*ee67461eSJoseph Mingrone #define NI_NODEADDR_FLAG_ALL 0x0002 399*ee67461eSJoseph Mingrone #define NI_NODEADDR_FLAG_COMPAT 0x0004 400*ee67461eSJoseph Mingrone #define NI_NODEADDR_FLAG_LINKLOCAL 0x0008 401*ee67461eSJoseph Mingrone #define NI_NODEADDR_FLAG_SITELOCAL 0x0010 402*ee67461eSJoseph Mingrone #define NI_NODEADDR_FLAG_GLOBAL 0x0020 403*ee67461eSJoseph Mingrone #define NI_NODEADDR_FLAG_ANYCAST 0x0040 /* just experimental. not in spec */ 4043c602fabSXin LI 4053c602fabSXin LI struct ni_reply_fqdn { 406*ee67461eSJoseph Mingrone nd_uint32_t ni_fqdn_ttl; /* TTL */ 407*ee67461eSJoseph Mingrone nd_uint8_t ni_fqdn_namelen; /* length in octets of the FQDN */ 408*ee67461eSJoseph Mingrone nd_byte ni_fqdn_name[3]; /* XXX: alignment */ 4093c602fabSXin LI }; 4103c602fabSXin LI 4113c602fabSXin LI /* 4123c602fabSXin LI * Router Renumbering. as router-renum-08.txt 4133c602fabSXin LI */ 4143c602fabSXin LI struct icmp6_router_renum { /* router renumbering header */ 4153c602fabSXin LI struct icmp6_hdr rr_hdr; 416*ee67461eSJoseph Mingrone nd_uint8_t rr_segnum; 417*ee67461eSJoseph Mingrone nd_uint8_t rr_flags; 418*ee67461eSJoseph Mingrone nd_uint16_t rr_maxdelay; 419*ee67461eSJoseph Mingrone nd_uint32_t rr_reserved; 4203c602fabSXin LI }; 4213c602fabSXin LI #define ICMP6_RR_FLAGS_TEST 0x80 4223c602fabSXin LI #define ICMP6_RR_FLAGS_REQRESULT 0x40 4233c602fabSXin LI #define ICMP6_RR_FLAGS_FORCEAPPLY 0x20 4243c602fabSXin LI #define ICMP6_RR_FLAGS_SPECSITE 0x10 4253c602fabSXin LI #define ICMP6_RR_FLAGS_PREVDONE 0x08 4263c602fabSXin LI 4273c602fabSXin LI #define rr_type rr_hdr.icmp6_type 4283c602fabSXin LI #define rr_code rr_hdr.icmp6_code 4293c602fabSXin LI #define rr_cksum rr_hdr.icmp6_cksum 4303c602fabSXin LI #define rr_seqnum rr_hdr.icmp6_data32[0] 4313c602fabSXin LI 4323c602fabSXin LI struct rr_pco_match { /* match prefix part */ 433*ee67461eSJoseph Mingrone nd_uint8_t rpm_code; 434*ee67461eSJoseph Mingrone nd_uint8_t rpm_len; 435*ee67461eSJoseph Mingrone nd_uint8_t rpm_ordinal; 436*ee67461eSJoseph Mingrone nd_uint8_t rpm_matchlen; 437*ee67461eSJoseph Mingrone nd_uint8_t rpm_minlen; 438*ee67461eSJoseph Mingrone nd_uint8_t rpm_maxlen; 439*ee67461eSJoseph Mingrone nd_uint16_t rpm_reserved; 440*ee67461eSJoseph Mingrone nd_ipv6 rpm_prefix; 4413c602fabSXin LI }; 4423c602fabSXin LI 4433c602fabSXin LI #define RPM_PCO_ADD 1 4443c602fabSXin LI #define RPM_PCO_CHANGE 2 4453c602fabSXin LI #define RPM_PCO_SETGLOBAL 3 4463c602fabSXin LI #define RPM_PCO_MAX 4 4473c602fabSXin LI 4483c602fabSXin LI struct rr_pco_use { /* use prefix part */ 449*ee67461eSJoseph Mingrone nd_uint8_t rpu_uselen; 450*ee67461eSJoseph Mingrone nd_uint8_t rpu_keeplen; 451*ee67461eSJoseph Mingrone nd_uint8_t rpu_ramask; 452*ee67461eSJoseph Mingrone nd_uint8_t rpu_raflags; 453*ee67461eSJoseph Mingrone nd_uint32_t rpu_vltime; 454*ee67461eSJoseph Mingrone nd_uint32_t rpu_pltime; 455*ee67461eSJoseph Mingrone nd_uint32_t rpu_flags; 456*ee67461eSJoseph Mingrone nd_ipv6 rpu_prefix; 4573c602fabSXin LI }; 4583c602fabSXin LI #define ICMP6_RR_PCOUSE_RAFLAGS_ONLINK 0x80 4593c602fabSXin LI #define ICMP6_RR_PCOUSE_RAFLAGS_AUTO 0x40 4603c602fabSXin LI 4613c602fabSXin LI /* network endian */ 4623c602fabSXin LI #define ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME ((uint32_t)htonl(0x80000000)) 4633c602fabSXin LI #define ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME ((uint32_t)htonl(0x40000000)) 4643c602fabSXin LI 4653c602fabSXin LI struct rr_result { /* router renumbering result message */ 466*ee67461eSJoseph Mingrone nd_uint16_t rrr_flags; 467*ee67461eSJoseph Mingrone nd_uint8_t rrr_ordinal; 468*ee67461eSJoseph Mingrone nd_uint8_t rrr_matchedlen; 469*ee67461eSJoseph Mingrone nd_uint32_t rrr_ifid; 470*ee67461eSJoseph Mingrone nd_ipv6 rrr_prefix; 4713c602fabSXin LI }; 4723c602fabSXin LI /* network endian */ 4733c602fabSXin LI #define ICMP6_RR_RESULT_FLAGS_OOB ((uint16_t)htons(0x0002)) 4743c602fabSXin LI #define ICMP6_RR_RESULT_FLAGS_FORBIDDEN ((uint16_t)htons(0x0001)) 4753c602fabSXin LI 476a90e161bSBill Fenner static const char *get_rtpref(u_int); 4773c602fabSXin LI static const char *get_lifetime(uint32_t); 4783c602fabSXin LI static void print_lladdr(netdissect_options *ndo, const u_char *, size_t); 479*ee67461eSJoseph Mingrone static int icmp6_opt_print(netdissect_options *ndo, const u_char *, int); 4803c602fabSXin LI static void mld6_print(netdissect_options *ndo, const u_char *); 4813c602fabSXin LI static void mldv2_report_print(netdissect_options *ndo, const u_char *, u_int); 4823c602fabSXin LI static void mldv2_query_print(netdissect_options *ndo, const u_char *, u_int); 4833c602fabSXin LI static const struct udphdr *get_upperlayer(netdissect_options *ndo, const u_char *, u_int *); 4843c602fabSXin LI static void dnsname_print(netdissect_options *ndo, const u_char *, const u_char *); 4853c602fabSXin LI static void icmp6_nodeinfo_print(netdissect_options *ndo, u_int, const u_char *, const u_char *); 4863c602fabSXin LI static void icmp6_rrenum_print(netdissect_options *ndo, const u_char *, const u_char *); 487685295f4SBill Fenner 488*ee67461eSJoseph Mingrone /* 489*ee67461eSJoseph Mingrone * DIO: Updated to RFC6550, as published in 2012: section 6. (page 30) 490*ee67461eSJoseph Mingrone */ 491b0453382SBill Fenner 492*ee67461eSJoseph Mingrone #define ND_RPL_MESSAGE 155 /* 0x9B */ 493*ee67461eSJoseph Mingrone 494*ee67461eSJoseph Mingrone enum ND_RPL_CODE { 495*ee67461eSJoseph Mingrone ND_RPL_DAG_IS=0x00, 496*ee67461eSJoseph Mingrone ND_RPL_DAG_IO=0x01, 497*ee67461eSJoseph Mingrone ND_RPL_DAO =0x02, 498*ee67461eSJoseph Mingrone ND_RPL_DAO_ACK=0x03, 499*ee67461eSJoseph Mingrone ND_RPL_SEC_DAG_IS = 0x80, 500*ee67461eSJoseph Mingrone ND_RPL_SEC_DAG_IO = 0x81, 501*ee67461eSJoseph Mingrone ND_RPL_SEC_DAG = 0x82, 502*ee67461eSJoseph Mingrone ND_RPL_SEC_DAG_ACK= 0x83, 503*ee67461eSJoseph Mingrone ND_RPL_SEC_CONSIST= 0x8A 504*ee67461eSJoseph Mingrone }; 505*ee67461eSJoseph Mingrone 506*ee67461eSJoseph Mingrone enum ND_RPL_DIO_FLAGS { 507*ee67461eSJoseph Mingrone ND_RPL_DIO_GROUNDED = 0x80, 508*ee67461eSJoseph Mingrone ND_RPL_DIO_DATRIG = 0x40, 509*ee67461eSJoseph Mingrone ND_RPL_DIO_DASUPPORT= 0x20, 510*ee67461eSJoseph Mingrone ND_RPL_DIO_RES4 = 0x10, 511*ee67461eSJoseph Mingrone ND_RPL_DIO_RES3 = 0x08, 512*ee67461eSJoseph Mingrone ND_RPL_DIO_PRF_MASK = 0x07 /* 3-bit preference */ 513*ee67461eSJoseph Mingrone }; 514*ee67461eSJoseph Mingrone 515*ee67461eSJoseph Mingrone #define DAGID_LEN 16 516*ee67461eSJoseph Mingrone 517*ee67461eSJoseph Mingrone /* section 6 of draft-ietf-roll-rpl-19 */ 518*ee67461eSJoseph Mingrone struct nd_rpl_security { 519*ee67461eSJoseph Mingrone nd_uint8_t rpl_sec_t_reserved; /* bit 7 is T-bit */ 520*ee67461eSJoseph Mingrone nd_uint8_t rpl_sec_algo; 521*ee67461eSJoseph Mingrone nd_uint16_t rpl_sec_kim_lvl_flags; /* bit 15/14, KIM */ 522*ee67461eSJoseph Mingrone /* bit 10-8, LVL, bit 7-0 flags */ 523*ee67461eSJoseph Mingrone nd_uint32_t rpl_sec_counter; 524*ee67461eSJoseph Mingrone #if 0 525*ee67461eSJoseph Mingrone nd_byte rpl_sec_ki[0]; /* depends upon kim */ 526*ee67461eSJoseph Mingrone #endif 527*ee67461eSJoseph Mingrone }; 528*ee67461eSJoseph Mingrone 529*ee67461eSJoseph Mingrone /* section 6.2.1, DODAG Information Solication (DIS_IS) */ 530*ee67461eSJoseph Mingrone struct nd_rpl_dis_is { 531*ee67461eSJoseph Mingrone nd_uint8_t rpl_dis_flags; 532*ee67461eSJoseph Mingrone nd_uint8_t rpl_dis_reserved; 533*ee67461eSJoseph Mingrone #if 0 534*ee67461eSJoseph Mingrone nd_byte rpl_dis_options[0]; 535*ee67461eSJoseph Mingrone #endif 536*ee67461eSJoseph Mingrone }; 537*ee67461eSJoseph Mingrone 538*ee67461eSJoseph Mingrone /* section 6.3.1, DODAG Information Object (DIO) */ 539*ee67461eSJoseph Mingrone struct nd_rpl_dio { 540*ee67461eSJoseph Mingrone nd_uint8_t rpl_instanceid; 541*ee67461eSJoseph Mingrone nd_uint8_t rpl_version; 542*ee67461eSJoseph Mingrone nd_uint16_t rpl_dagrank; 543*ee67461eSJoseph Mingrone nd_uint8_t rpl_mopprf; /* bit 7=G, 5-3=MOP, 2-0=PRF */ 544*ee67461eSJoseph Mingrone nd_uint8_t rpl_dtsn; /* Dest. Advertisement Trigger Sequence Number */ 545*ee67461eSJoseph Mingrone nd_uint8_t rpl_flags; /* no flags defined yet */ 546*ee67461eSJoseph Mingrone nd_uint8_t rpl_resv1; 547*ee67461eSJoseph Mingrone nd_byte rpl_dagid[DAGID_LEN]; 548*ee67461eSJoseph Mingrone }; 549*ee67461eSJoseph Mingrone #define RPL_DIO_GROUND_FLAG 0x80 550*ee67461eSJoseph Mingrone #define RPL_DIO_MOP_SHIFT 3 551*ee67461eSJoseph Mingrone #define RPL_DIO_MOP_MASK (7 << RPL_DIO_MOP_SHIFT) 552*ee67461eSJoseph Mingrone #define RPL_DIO_PRF_SHIFT 0 553*ee67461eSJoseph Mingrone #define RPL_DIO_PRF_MASK (7 << RPL_DIO_PRF_SHIFT) 554*ee67461eSJoseph Mingrone #define RPL_DIO_GROUNDED(X) ((X)&RPL_DIO_GROUND_FLAG) 555*ee67461eSJoseph Mingrone #define RPL_DIO_MOP(X) (enum RPL_DIO_MOP)(((X)&RPL_DIO_MOP_MASK) >> RPL_DIO_MOP_SHIFT) 556*ee67461eSJoseph Mingrone #define RPL_DIO_PRF(X) (((X)&RPL_DIO_PRF_MASK) >> RPL_DIO_PRF_SHIFT) 557*ee67461eSJoseph Mingrone 558*ee67461eSJoseph Mingrone enum RPL_DIO_MOP { 559*ee67461eSJoseph Mingrone RPL_DIO_NONSTORING= 0x0, 560*ee67461eSJoseph Mingrone RPL_DIO_STORING = 0x1, 561*ee67461eSJoseph Mingrone RPL_DIO_NONSTORING_MULTICAST = 0x2, 562*ee67461eSJoseph Mingrone RPL_DIO_STORING_MULTICAST = 0x3 563*ee67461eSJoseph Mingrone }; 564*ee67461eSJoseph Mingrone 565*ee67461eSJoseph Mingrone enum RPL_SUBOPT { 566*ee67461eSJoseph Mingrone RPL_OPT_PAD1 = 0, 567*ee67461eSJoseph Mingrone RPL_OPT_PADN = 1, 568*ee67461eSJoseph Mingrone RPL_DIO_METRICS = 2, 569*ee67461eSJoseph Mingrone RPL_DIO_ROUTINGINFO = 3, 570*ee67461eSJoseph Mingrone RPL_DIO_CONFIG = 4, 571*ee67461eSJoseph Mingrone RPL_DAO_RPLTARGET = 5, 572*ee67461eSJoseph Mingrone RPL_DAO_TRANSITINFO = 6, 573*ee67461eSJoseph Mingrone RPL_DIO_DESTPREFIX = 8, 574*ee67461eSJoseph Mingrone RPL_DAO_RPLTARGET_DESC=9 575*ee67461eSJoseph Mingrone }; 576*ee67461eSJoseph Mingrone 577*ee67461eSJoseph Mingrone struct rpl_genoption { 578*ee67461eSJoseph Mingrone nd_uint8_t rpl_dio_type; 579*ee67461eSJoseph Mingrone nd_uint8_t rpl_dio_len; /* suboption length, not including type/len */ 580*ee67461eSJoseph Mingrone }; 581*ee67461eSJoseph Mingrone #define RPL_GENOPTION_LEN 2 582*ee67461eSJoseph Mingrone 583*ee67461eSJoseph Mingrone #define RPL_DIO_LIFETIME_INFINITE 0xffffffff 584*ee67461eSJoseph Mingrone #define RPL_DIO_LIFETIME_DISCONNECT 0 585*ee67461eSJoseph Mingrone 586*ee67461eSJoseph Mingrone struct rpl_dio_destprefix { 587*ee67461eSJoseph Mingrone nd_uint8_t rpl_dio_type; 588*ee67461eSJoseph Mingrone nd_uint8_t rpl_dio_len; 589*ee67461eSJoseph Mingrone nd_uint8_t rpl_dio_prefixlen; /* in bits */ 590*ee67461eSJoseph Mingrone nd_uint8_t rpl_dio_prf; /* flags, including Route Preference */ 591*ee67461eSJoseph Mingrone nd_uint32_t rpl_dio_prefixlifetime; /* in seconds */ 592*ee67461eSJoseph Mingrone #if 0 593*ee67461eSJoseph Mingrone nd_byte rpl_dio_prefix[0]; /* variable number of bytes */ 594*ee67461eSJoseph Mingrone #endif 595*ee67461eSJoseph Mingrone }; 596*ee67461eSJoseph Mingrone 597*ee67461eSJoseph Mingrone /* section 6.4.1, DODAG Information Object (DIO) */ 598*ee67461eSJoseph Mingrone struct nd_rpl_dao { 599*ee67461eSJoseph Mingrone nd_uint8_t rpl_instanceid; 600*ee67461eSJoseph Mingrone nd_uint8_t rpl_flags; /* bit 7=K, 6=D */ 601*ee67461eSJoseph Mingrone nd_uint8_t rpl_resv; 602*ee67461eSJoseph Mingrone nd_uint8_t rpl_daoseq; 603*ee67461eSJoseph Mingrone nd_byte rpl_dagid[DAGID_LEN]; /* present when D set. */ 604*ee67461eSJoseph Mingrone }; 605*ee67461eSJoseph Mingrone #define ND_RPL_DAO_MIN_LEN 4 /* length without DAGID */ 606*ee67461eSJoseph Mingrone 607*ee67461eSJoseph Mingrone /* indicates if this DAO is to be acK'ed */ 608*ee67461eSJoseph Mingrone #define RPL_DAO_K_SHIFT 7 609*ee67461eSJoseph Mingrone #define RPL_DAO_K_MASK (1 << RPL_DAO_K_SHIFT) 610*ee67461eSJoseph Mingrone #define RPL_DAO_K(X) (((X)&RPL_DAO_K_MASK) >> RPL_DAO_K_SHIFT) 611*ee67461eSJoseph Mingrone 612*ee67461eSJoseph Mingrone /* indicates if the DAGID is present */ 613*ee67461eSJoseph Mingrone #define RPL_DAO_D_SHIFT 6 614*ee67461eSJoseph Mingrone #define RPL_DAO_D_MASK (1 << RPL_DAO_D_SHIFT) 615*ee67461eSJoseph Mingrone #define RPL_DAO_D(X) (((X)&RPL_DAO_D_MASK) >> RPL_DAO_D_SHIFT) 616*ee67461eSJoseph Mingrone 617*ee67461eSJoseph Mingrone struct rpl_dao_target { 618*ee67461eSJoseph Mingrone nd_uint8_t rpl_dao_type; 619*ee67461eSJoseph Mingrone nd_uint8_t rpl_dao_len; 620*ee67461eSJoseph Mingrone nd_uint8_t rpl_dao_flags; /* unused */ 621*ee67461eSJoseph Mingrone nd_uint8_t rpl_dao_prefixlen; /* in bits */ 622*ee67461eSJoseph Mingrone #if 0 623*ee67461eSJoseph Mingrone nd_byte rpl_dao_prefix[0]; /* variable number of bytes */ 624*ee67461eSJoseph Mingrone #endif 625*ee67461eSJoseph Mingrone }; 626*ee67461eSJoseph Mingrone 627*ee67461eSJoseph Mingrone /* section 6.5.1, Destination Advertisement Object Acknowledgement (DAO-ACK) */ 628*ee67461eSJoseph Mingrone struct nd_rpl_daoack { 629*ee67461eSJoseph Mingrone nd_uint8_t rpl_instanceid; 630*ee67461eSJoseph Mingrone nd_uint8_t rpl_flags; /* bit 7=D */ 631*ee67461eSJoseph Mingrone nd_uint8_t rpl_daoseq; 632*ee67461eSJoseph Mingrone nd_uint8_t rpl_status; 633*ee67461eSJoseph Mingrone nd_byte rpl_dagid[DAGID_LEN]; /* present when D set. */ 634*ee67461eSJoseph Mingrone }; 635*ee67461eSJoseph Mingrone #define ND_RPL_DAOACK_MIN_LEN 4 /* length without DAGID */ 636*ee67461eSJoseph Mingrone /* indicates if the DAGID is present */ 637*ee67461eSJoseph Mingrone #define RPL_DAOACK_D_SHIFT 7 638*ee67461eSJoseph Mingrone #define RPL_DAOACK_D_MASK (1 << RPL_DAOACK_D_SHIFT) 639*ee67461eSJoseph Mingrone #define RPL_DAOACK_D(X) (((X)&RPL_DAOACK_D_MASK) >> RPL_DAOACK_D_SHIFT) 64027df3f5dSRui Paulo 6413c602fabSXin LI static const struct tok icmp6_type_values[] = { 6421de50e9fSSam Leffler { ICMP6_DST_UNREACH, "destination unreachable"}, 6431de50e9fSSam Leffler { ICMP6_PACKET_TOO_BIG, "packet too big"}, 6441de50e9fSSam Leffler { ICMP6_TIME_EXCEEDED, "time exceeded in-transit"}, 6451de50e9fSSam Leffler { ICMP6_PARAM_PROB, "parameter problem"}, 6461de50e9fSSam Leffler { ICMP6_ECHO_REQUEST, "echo request"}, 6471de50e9fSSam Leffler { ICMP6_ECHO_REPLY, "echo reply"}, 6481de50e9fSSam Leffler { MLD6_LISTENER_QUERY, "multicast listener query"}, 6491de50e9fSSam Leffler { MLD6_LISTENER_REPORT, "multicast listener report"}, 6501de50e9fSSam Leffler { MLD6_LISTENER_DONE, "multicast listener done"}, 6511de50e9fSSam Leffler { ND_ROUTER_SOLICIT, "router solicitation"}, 6521de50e9fSSam Leffler { ND_ROUTER_ADVERT, "router advertisement"}, 6531de50e9fSSam Leffler { ND_NEIGHBOR_SOLICIT, "neighbor solicitation"}, 6542ebc47dbSSam Leffler { ND_NEIGHBOR_ADVERT, "neighbor advertisement"}, 6551de50e9fSSam Leffler { ND_REDIRECT, "redirect"}, 6561de50e9fSSam Leffler { ICMP6_ROUTER_RENUMBERING, "router renumbering"}, 6571de50e9fSSam Leffler { IND_SOLICIT, "inverse neighbor solicitation"}, 6581de50e9fSSam Leffler { IND_ADVERT, "inverse neighbor advertisement"}, 6591de50e9fSSam Leffler { MLDV2_LISTENER_REPORT, "multicast listener report v2"}, 6601de50e9fSSam Leffler { ICMP6_HADISCOV_REQUEST, "ha discovery request"}, 6611de50e9fSSam Leffler { ICMP6_HADISCOV_REPLY, "ha discovery reply"}, 6621de50e9fSSam Leffler { ICMP6_MOBILEPREFIX_SOLICIT, "mobile router solicitation"}, 6631de50e9fSSam Leffler { ICMP6_MOBILEPREFIX_ADVERT, "mobile router advertisement"}, 6641de50e9fSSam Leffler { ICMP6_WRUREQUEST, "who-are-you request"}, 6651de50e9fSSam Leffler { ICMP6_WRUREPLY, "who-are-you reply"}, 6661de50e9fSSam Leffler { ICMP6_NI_QUERY, "node information query"}, 6671de50e9fSSam Leffler { ICMP6_NI_REPLY, "node information reply"}, 6681de50e9fSSam Leffler { MLD6_MTRACE, "mtrace message"}, 6691de50e9fSSam Leffler { MLD6_MTRACE_RESP, "mtrace response"}, 67027df3f5dSRui Paulo { ND_RPL_MESSAGE, "RPL"}, 6711de50e9fSSam Leffler { 0, NULL } 6721de50e9fSSam Leffler }; 6731de50e9fSSam Leffler 6743c602fabSXin LI static const struct tok icmp6_dst_unreach_code_values[] = { 6751de50e9fSSam Leffler { ICMP6_DST_UNREACH_NOROUTE, "unreachable route" }, 6761de50e9fSSam Leffler { ICMP6_DST_UNREACH_ADMIN, " unreachable prohibited"}, 6771de50e9fSSam Leffler { ICMP6_DST_UNREACH_BEYONDSCOPE, "beyond scope"}, 6781de50e9fSSam Leffler { ICMP6_DST_UNREACH_ADDR, "unreachable address"}, 6791de50e9fSSam Leffler { ICMP6_DST_UNREACH_NOPORT, "unreachable port"}, 6801de50e9fSSam Leffler { 0, NULL } 6811de50e9fSSam Leffler }; 6821de50e9fSSam Leffler 6833c602fabSXin LI static const struct tok icmp6_opt_pi_flag_values[] = { 6841de50e9fSSam Leffler { ND_OPT_PI_FLAG_ONLINK, "onlink" }, 6851de50e9fSSam Leffler { ND_OPT_PI_FLAG_AUTO, "auto" }, 6861de50e9fSSam Leffler { ND_OPT_PI_FLAG_ROUTER, "router" }, 6871de50e9fSSam Leffler { 0, NULL } 6881de50e9fSSam Leffler }; 6891de50e9fSSam Leffler 6903c602fabSXin LI static const struct tok icmp6_opt_ra_flag_values[] = { 6911de50e9fSSam Leffler { ND_RA_FLAG_MANAGED, "managed" }, 6921de50e9fSSam Leffler { ND_RA_FLAG_OTHER, "other stateful"}, 6931de50e9fSSam Leffler { ND_RA_FLAG_HOME_AGENT, "home agent"}, 694*ee67461eSJoseph Mingrone { ND_RA_FLAG_IPV6ONLY, "ipv6 only"}, 6951de50e9fSSam Leffler { 0, NULL } 6961de50e9fSSam Leffler }; 6971de50e9fSSam Leffler 6983c602fabSXin LI static const struct tok icmp6_nd_na_flag_values[] = { 6991de50e9fSSam Leffler { ND_NA_FLAG_ROUTER, "router" }, 7001de50e9fSSam Leffler { ND_NA_FLAG_SOLICITED, "solicited" }, 7011de50e9fSSam Leffler { ND_NA_FLAG_OVERRIDE, "override" }, 7021de50e9fSSam Leffler { 0, NULL } 7031de50e9fSSam Leffler }; 7041de50e9fSSam Leffler 7053c602fabSXin LI static const struct tok icmp6_opt_values[] = { 7061de50e9fSSam Leffler { ND_OPT_SOURCE_LINKADDR, "source link-address"}, 7071de50e9fSSam Leffler { ND_OPT_TARGET_LINKADDR, "destination link-address"}, 7081de50e9fSSam Leffler { ND_OPT_PREFIX_INFORMATION, "prefix info"}, 7091de50e9fSSam Leffler { ND_OPT_REDIRECTED_HEADER, "redirected header"}, 7101de50e9fSSam Leffler { ND_OPT_MTU, "mtu"}, 71127df3f5dSRui Paulo { ND_OPT_RDNSS, "rdnss"}, 712d03c0883SXin LI { ND_OPT_DNSSL, "dnssl"}, 7132ebc47dbSSam Leffler { ND_OPT_ADVINTERVAL, "advertisement interval"}, 7141de50e9fSSam Leffler { ND_OPT_HOMEAGENT_INFO, "homeagent information"}, 7151de50e9fSSam Leffler { ND_OPT_ROUTE_INFO, "route info"}, 7161de50e9fSSam Leffler { 0, NULL } 7171de50e9fSSam Leffler }; 7181de50e9fSSam Leffler 7191de50e9fSSam Leffler /* mldv2 report types */ 7203c602fabSXin LI static const struct tok mldv2report2str[] = { 7211de50e9fSSam Leffler { 1, "is_in" }, 7221de50e9fSSam Leffler { 2, "is_ex" }, 7231de50e9fSSam Leffler { 3, "to_in" }, 7241de50e9fSSam Leffler { 4, "to_ex" }, 7251de50e9fSSam Leffler { 5, "allow" }, 7261de50e9fSSam Leffler { 6, "block" }, 7271de50e9fSSam Leffler { 0, NULL } 7281de50e9fSSam Leffler }; 7291de50e9fSSam Leffler 730a90e161bSBill Fenner static const char * 731a90e161bSBill Fenner get_rtpref(u_int v) 732a90e161bSBill Fenner { 733a90e161bSBill Fenner static const char *rtpref_str[] = { 734a90e161bSBill Fenner "medium", /* 00 */ 735a90e161bSBill Fenner "high", /* 01 */ 736a90e161bSBill Fenner "rsv", /* 10 */ 737a90e161bSBill Fenner "low" /* 11 */ 738a90e161bSBill Fenner }; 739a90e161bSBill Fenner 740a90e161bSBill Fenner return rtpref_str[((v & ND_RA_FLAG_RTPREF_MASK) >> 3) & 0xff]; 741a90e161bSBill Fenner } 742a90e161bSBill Fenner 743a90e161bSBill Fenner static const char * 7443c602fabSXin LI get_lifetime(uint32_t v) 745a90e161bSBill Fenner { 746a90e161bSBill Fenner static char buf[20]; 747a90e161bSBill Fenner 7483c602fabSXin LI if (v == (uint32_t)~0UL) 749a90e161bSBill Fenner return "infinity"; 750a90e161bSBill Fenner else { 751d03c0883SXin LI snprintf(buf, sizeof(buf), "%us", v); 752a90e161bSBill Fenner return buf; 753a90e161bSBill Fenner } 754a90e161bSBill Fenner } 755a90e161bSBill Fenner 756a90e161bSBill Fenner static void 7573c602fabSXin LI print_lladdr(netdissect_options *ndo, const uint8_t *p, size_t l) 758a90e161bSBill Fenner { 7593c602fabSXin LI const uint8_t *ep, *q; 760a90e161bSBill Fenner 761a90e161bSBill Fenner q = p; 762a90e161bSBill Fenner ep = p + l; 763a90e161bSBill Fenner while (l > 0 && q < ep) { 764a90e161bSBill Fenner if (q > p) 765*ee67461eSJoseph Mingrone ND_PRINT(":"); 766*ee67461eSJoseph Mingrone ND_PRINT("%02x", GET_U_1(q)); 767*ee67461eSJoseph Mingrone q++; 768a90e161bSBill Fenner l--; 769a90e161bSBill Fenner } 770a90e161bSBill Fenner } 771a90e161bSBill Fenner 772*ee67461eSJoseph Mingrone static uint16_t icmp6_cksum(netdissect_options *ndo, const struct ip6_hdr *ip6, 7733340d773SGleb Smirnoff const struct icmp6_hdr *icp, u_int len) 7745b0fe478SBruce M Simpson { 7753340d773SGleb Smirnoff return nextproto6_cksum(ndo, ip6, (const uint8_t *)(const void *)icp, len, len, 7763c602fabSXin LI IPPROTO_ICMPV6); 7775b0fe478SBruce M Simpson } 7785b0fe478SBruce M Simpson 7793340d773SGleb Smirnoff static const struct tok rpl_mop_values[] = { 7803c602fabSXin LI { RPL_DIO_NONSTORING, "nonstoring"}, 7813c602fabSXin LI { RPL_DIO_STORING, "storing"}, 7823c602fabSXin LI { RPL_DIO_NONSTORING_MULTICAST, "nonstoring-multicast"}, 7833c602fabSXin LI { RPL_DIO_STORING_MULTICAST, "storing-multicast"}, 7843c602fabSXin LI { 0, NULL}, 78527df3f5dSRui Paulo }; 78627df3f5dSRui Paulo 7873340d773SGleb Smirnoff static const struct tok rpl_subopt_values[] = { 788*ee67461eSJoseph Mingrone { RPL_OPT_PAD1, "pad1"}, 7893c602fabSXin LI { RPL_OPT_PADN, "padN"}, 7903c602fabSXin LI { RPL_DIO_METRICS, "metrics"}, 7913c602fabSXin LI { RPL_DIO_ROUTINGINFO, "routinginfo"}, 7923c602fabSXin LI { RPL_DIO_CONFIG, "config"}, 7933c602fabSXin LI { RPL_DAO_RPLTARGET, "rpltarget"}, 7943c602fabSXin LI { RPL_DAO_TRANSITINFO, "transitinfo"}, 7953c602fabSXin LI { RPL_DIO_DESTPREFIX, "destprefix"}, 7963c602fabSXin LI { RPL_DAO_RPLTARGET_DESC, "rpltargetdesc"}, 7973c602fabSXin LI { 0, NULL}, 79827df3f5dSRui Paulo }; 79927df3f5dSRui Paulo 8003c602fabSXin LI static void 801*ee67461eSJoseph Mingrone rpl_printopts(netdissect_options *ndo, const uint8_t *opts, u_int length) 8023c602fabSXin LI { 803*ee67461eSJoseph Mingrone const struct rpl_genoption *opt; 804*ee67461eSJoseph Mingrone uint8_t dio_type; 805*ee67461eSJoseph Mingrone u_int optlen; 8063c602fabSXin LI 807*ee67461eSJoseph Mingrone while (length != 0) { 808*ee67461eSJoseph Mingrone opt = (const struct rpl_genoption *)opts; 809*ee67461eSJoseph Mingrone dio_type = GET_U_1(opt->rpl_dio_type); 810*ee67461eSJoseph Mingrone if (dio_type == RPL_OPT_PAD1) { 8113c602fabSXin LI optlen = 1; 812*ee67461eSJoseph Mingrone ND_PRINT(" opt:pad1"); 8133c602fabSXin LI } else { 814*ee67461eSJoseph Mingrone if (length < RPL_GENOPTION_LEN) 815*ee67461eSJoseph Mingrone goto trunc; 816*ee67461eSJoseph Mingrone optlen = GET_U_1(opt->rpl_dio_len)+RPL_GENOPTION_LEN; 817*ee67461eSJoseph Mingrone ND_PRINT(" opt:%s len:%u ", 818*ee67461eSJoseph Mingrone tok2str(rpl_subopt_values, "subopt:%u", dio_type), 819*ee67461eSJoseph Mingrone optlen); 820*ee67461eSJoseph Mingrone ND_TCHECK_LEN(opt, optlen); 821*ee67461eSJoseph Mingrone if (length < optlen) 822*ee67461eSJoseph Mingrone goto trunc; 8233c602fabSXin LI if (ndo->ndo_vflag > 2) { 8243c602fabSXin LI hex_print(ndo, 8253c602fabSXin LI " ", 826*ee67461eSJoseph Mingrone opts + RPL_GENOPTION_LEN, /* content of DIO option */ 827*ee67461eSJoseph Mingrone optlen - RPL_GENOPTION_LEN); 8283c602fabSXin LI } 8293c602fabSXin LI } 830*ee67461eSJoseph Mingrone opts += optlen; 8313c602fabSXin LI length -= optlen; 8323c602fabSXin LI } 8333c602fabSXin LI return; 8343c602fabSXin LI trunc: 835*ee67461eSJoseph Mingrone nd_print_trunc(ndo); 8363c602fabSXin LI } 8373c602fabSXin LI 8383c602fabSXin LI static void 8393c602fabSXin LI rpl_dio_print(netdissect_options *ndo, 8403c602fabSXin LI const u_char *bp, u_int length) 8413c602fabSXin LI { 8423340d773SGleb Smirnoff const struct nd_rpl_dio *dio = (const struct nd_rpl_dio *)bp; 8433c602fabSXin LI 844*ee67461eSJoseph Mingrone ND_LCHECK_ZU(length, sizeof(struct nd_rpl_dio)); 845*ee67461eSJoseph Mingrone ND_PRINT(" [dagid:%s,seq:%u,instance:%u,rank:%u,%smop:%s,prf:%u]", 846*ee67461eSJoseph Mingrone GET_IP6ADDR_STRING(dio->rpl_dagid), 847*ee67461eSJoseph Mingrone GET_U_1(dio->rpl_dtsn), 848*ee67461eSJoseph Mingrone GET_U_1(dio->rpl_instanceid), 849*ee67461eSJoseph Mingrone GET_BE_U_2(dio->rpl_dagrank), 850*ee67461eSJoseph Mingrone RPL_DIO_GROUNDED(GET_U_1(dio->rpl_mopprf)) ? "grounded,":"", 851*ee67461eSJoseph Mingrone tok2str(rpl_mop_values, "mop%u", 852*ee67461eSJoseph Mingrone RPL_DIO_MOP(GET_U_1(dio->rpl_mopprf))), 853*ee67461eSJoseph Mingrone RPL_DIO_PRF(GET_U_1(dio->rpl_mopprf))); 8543c602fabSXin LI 8553c602fabSXin LI if(ndo->ndo_vflag > 1) { 856*ee67461eSJoseph Mingrone rpl_printopts(ndo, bp + sizeof(struct nd_rpl_dio), 857*ee67461eSJoseph Mingrone length - sizeof(struct nd_rpl_dio)); 8583c602fabSXin LI } 8593c602fabSXin LI return; 860*ee67461eSJoseph Mingrone invalid: 861*ee67461eSJoseph Mingrone nd_print_invalid(ndo); 8623c602fabSXin LI } 8633c602fabSXin LI 8643c602fabSXin LI static void 8653c602fabSXin LI rpl_dao_print(netdissect_options *ndo, 8663c602fabSXin LI const u_char *bp, u_int length) 8673c602fabSXin LI { 8683340d773SGleb Smirnoff const struct nd_rpl_dao *dao = (const struct nd_rpl_dao *)bp; 8693340d773SGleb Smirnoff const char *dagid_str = "<elided>"; 870*ee67461eSJoseph Mingrone uint8_t rpl_flags; 8713c602fabSXin LI 872*ee67461eSJoseph Mingrone ND_TCHECK_SIZE(dao); 8733c602fabSXin LI if (length < ND_RPL_DAO_MIN_LEN) 8743c602fabSXin LI goto tooshort; 8753c602fabSXin LI 8763c602fabSXin LI bp += ND_RPL_DAO_MIN_LEN; 8773c602fabSXin LI length -= ND_RPL_DAO_MIN_LEN; 878*ee67461eSJoseph Mingrone rpl_flags = GET_U_1(dao->rpl_flags); 879*ee67461eSJoseph Mingrone if(RPL_DAO_D(rpl_flags)) { 880*ee67461eSJoseph Mingrone ND_TCHECK_LEN(dao->rpl_dagid, DAGID_LEN); 8813c602fabSXin LI if (length < DAGID_LEN) 8823c602fabSXin LI goto tooshort; 8833340d773SGleb Smirnoff dagid_str = ip6addr_string (ndo, dao->rpl_dagid); 8843c602fabSXin LI bp += DAGID_LEN; 8853c602fabSXin LI length -= DAGID_LEN; 8863c602fabSXin LI } 8873c602fabSXin LI 888*ee67461eSJoseph Mingrone ND_PRINT(" [dagid:%s,seq:%u,instance:%u%s%s,flags:%02x]", 8893c602fabSXin LI dagid_str, 890*ee67461eSJoseph Mingrone GET_U_1(dao->rpl_daoseq), 891*ee67461eSJoseph Mingrone GET_U_1(dao->rpl_instanceid), 892*ee67461eSJoseph Mingrone RPL_DAO_K(rpl_flags) ? ",acK":"", 893*ee67461eSJoseph Mingrone RPL_DAO_D(rpl_flags) ? ",Dagid":"", 894*ee67461eSJoseph Mingrone rpl_flags); 8953c602fabSXin LI 8963c602fabSXin LI if(ndo->ndo_vflag > 1) { 897*ee67461eSJoseph Mingrone rpl_printopts(ndo, bp, length); 8983c602fabSXin LI } 8993c602fabSXin LI return; 9003c602fabSXin LI 9013c602fabSXin LI trunc: 902*ee67461eSJoseph Mingrone nd_print_trunc(ndo); 9033c602fabSXin LI return; 9043c602fabSXin LI 9053c602fabSXin LI tooshort: 906*ee67461eSJoseph Mingrone ND_PRINT(" [|length too short]"); 9073c602fabSXin LI } 9083c602fabSXin LI 9093c602fabSXin LI static void 9103c602fabSXin LI rpl_daoack_print(netdissect_options *ndo, 9113c602fabSXin LI const u_char *bp, u_int length) 9123c602fabSXin LI { 9133340d773SGleb Smirnoff const struct nd_rpl_daoack *daoack = (const struct nd_rpl_daoack *)bp; 9143340d773SGleb Smirnoff const char *dagid_str = "<elided>"; 9153c602fabSXin LI 916*ee67461eSJoseph Mingrone ND_TCHECK_LEN(daoack, ND_RPL_DAOACK_MIN_LEN); 9173c602fabSXin LI if (length < ND_RPL_DAOACK_MIN_LEN) 9183c602fabSXin LI goto tooshort; 9193c602fabSXin LI 9203c602fabSXin LI bp += ND_RPL_DAOACK_MIN_LEN; 9213c602fabSXin LI length -= ND_RPL_DAOACK_MIN_LEN; 922*ee67461eSJoseph Mingrone if(RPL_DAOACK_D(GET_U_1(daoack->rpl_flags))) { 923*ee67461eSJoseph Mingrone ND_TCHECK_LEN(daoack->rpl_dagid, DAGID_LEN); 9243c602fabSXin LI if (length < DAGID_LEN) 9253c602fabSXin LI goto tooshort; 9263340d773SGleb Smirnoff dagid_str = ip6addr_string (ndo, daoack->rpl_dagid); 9273c602fabSXin LI bp += DAGID_LEN; 9283c602fabSXin LI length -= DAGID_LEN; 9293c602fabSXin LI } 9303c602fabSXin LI 931*ee67461eSJoseph Mingrone ND_PRINT(" [dagid:%s,seq:%u,instance:%u,status:%u]", 9323c602fabSXin LI dagid_str, 933*ee67461eSJoseph Mingrone GET_U_1(daoack->rpl_daoseq), 934*ee67461eSJoseph Mingrone GET_U_1(daoack->rpl_instanceid), 935*ee67461eSJoseph Mingrone GET_U_1(daoack->rpl_status)); 9363c602fabSXin LI 9373c602fabSXin LI /* no officially defined options for DAOACK, but print any we find */ 9383c602fabSXin LI if(ndo->ndo_vflag > 1) { 939*ee67461eSJoseph Mingrone rpl_printopts(ndo, bp, length); 9403c602fabSXin LI } 9413c602fabSXin LI return; 9423c602fabSXin LI 9433c602fabSXin LI trunc: 944*ee67461eSJoseph Mingrone nd_print_trunc(ndo); 9453c602fabSXin LI return; 9463c602fabSXin LI 9473c602fabSXin LI tooshort: 948*ee67461eSJoseph Mingrone ND_PRINT(" [|dao-length too short]"); 9493c602fabSXin LI } 95027df3f5dSRui Paulo 95127df3f5dSRui Paulo static void 95227df3f5dSRui Paulo rpl_print(netdissect_options *ndo, 953*ee67461eSJoseph Mingrone uint8_t icmp6_code, 9543c602fabSXin LI const u_char *bp, u_int length) 95527df3f5dSRui Paulo { 956*ee67461eSJoseph Mingrone int secured = icmp6_code & 0x80; 957*ee67461eSJoseph Mingrone int basecode= icmp6_code & 0x7f; 95827df3f5dSRui Paulo 959cac3dcd5SXin LI if(secured) { 960*ee67461eSJoseph Mingrone ND_PRINT(", (SEC) [worktodo]"); 9613c602fabSXin LI /* XXX 9623c602fabSXin LI * the next header pointer needs to move forward to 9633c602fabSXin LI * skip the secure part. 9643c602fabSXin LI */ 9653c602fabSXin LI return; 966cac3dcd5SXin LI } else { 967*ee67461eSJoseph Mingrone ND_PRINT(", (CLR)"); 968cac3dcd5SXin LI } 969cac3dcd5SXin LI 970cac3dcd5SXin LI switch(basecode) { 9713c602fabSXin LI case ND_RPL_DAG_IS: 972*ee67461eSJoseph Mingrone ND_PRINT("DODAG Information Solicitation"); 97327df3f5dSRui Paulo if(ndo->ndo_vflag) { 97427df3f5dSRui Paulo } 97527df3f5dSRui Paulo break; 9763c602fabSXin LI case ND_RPL_DAG_IO: 977*ee67461eSJoseph Mingrone ND_PRINT("DODAG Information Object"); 97827df3f5dSRui Paulo if(ndo->ndo_vflag) { 9793c602fabSXin LI rpl_dio_print(ndo, bp, length); 98027df3f5dSRui Paulo } 98127df3f5dSRui Paulo break; 98227df3f5dSRui Paulo case ND_RPL_DAO: 983*ee67461eSJoseph Mingrone ND_PRINT("Destination Advertisement Object"); 984cac3dcd5SXin LI if(ndo->ndo_vflag) { 9853c602fabSXin LI rpl_dao_print(ndo, bp, length); 986cac3dcd5SXin LI } 987cac3dcd5SXin LI break; 988cac3dcd5SXin LI case ND_RPL_DAO_ACK: 989*ee67461eSJoseph Mingrone ND_PRINT("Destination Advertisement Object Ack"); 99027df3f5dSRui Paulo if(ndo->ndo_vflag) { 9913c602fabSXin LI rpl_daoack_print(ndo, bp, length); 99227df3f5dSRui Paulo } 99327df3f5dSRui Paulo break; 99427df3f5dSRui Paulo default: 995*ee67461eSJoseph Mingrone ND_PRINT("RPL message, unknown code %u",icmp6_code); 99627df3f5dSRui Paulo break; 99727df3f5dSRui Paulo } 99827df3f5dSRui Paulo return; 9993c602fabSXin LI 10003c602fabSXin LI #if 0 100127df3f5dSRui Paulo trunc: 1002*ee67461eSJoseph Mingrone nd_print_trunc(ndo); 100327df3f5dSRui Paulo return; 10043c602fabSXin LI #endif 100527df3f5dSRui Paulo 100627df3f5dSRui Paulo } 100727df3f5dSRui Paulo 1008b0453382SBill Fenner void 100927df3f5dSRui Paulo icmp6_print(netdissect_options *ndo, 101027df3f5dSRui Paulo const u_char *bp, u_int length, const u_char *bp2, int fragmented) 1011b0453382SBill Fenner { 1012685295f4SBill Fenner const struct icmp6_hdr *dp; 1013*ee67461eSJoseph Mingrone uint8_t icmp6_type, icmp6_code; 1014a90e161bSBill Fenner const struct ip6_hdr *ip; 1015a90e161bSBill Fenner const struct ip6_hdr *oip; 1016a90e161bSBill Fenner const struct udphdr *ouh; 1017*ee67461eSJoseph Mingrone uint16_t dport; 1018a90e161bSBill Fenner const u_char *ep; 10195b0fe478SBruce M Simpson u_int prot; 1020b0453382SBill Fenner 1021*ee67461eSJoseph Mingrone ndo->ndo_protocol = "icmp6"; 10223340d773SGleb Smirnoff dp = (const struct icmp6_hdr *)bp; 10233340d773SGleb Smirnoff ip = (const struct ip6_hdr *)bp2; 10243340d773SGleb Smirnoff oip = (const struct ip6_hdr *)(dp + 1); 1025685295f4SBill Fenner /* 'ep' points to the end of available data. */ 10263c602fabSXin LI ep = ndo->ndo_snapend; 1027*ee67461eSJoseph Mingrone if (length == 0) { 1028*ee67461eSJoseph Mingrone ND_PRINT("ICMP6, length 0"); 1029*ee67461eSJoseph Mingrone nd_print_invalid(ndo); 1030*ee67461eSJoseph Mingrone return; 1031*ee67461eSJoseph Mingrone } 10325b0fe478SBruce M Simpson 10333c602fabSXin LI if (ndo->ndo_vflag && !fragmented) { 10343c602fabSXin LI uint16_t sum, udp_sum; 10355b0fe478SBruce M Simpson 1036*ee67461eSJoseph Mingrone if (ND_TTEST_LEN(bp, length)) { 1037*ee67461eSJoseph Mingrone udp_sum = GET_BE_U_2(dp->icmp6_cksum); 10383340d773SGleb Smirnoff sum = icmp6_cksum(ndo, ip, dp, length); 10395b0fe478SBruce M Simpson if (sum != 0) 1040*ee67461eSJoseph Mingrone ND_PRINT("[bad icmp6 cksum 0x%04x -> 0x%04x!] ", 1041cac3dcd5SXin LI udp_sum, 1042*ee67461eSJoseph Mingrone in_cksum_shouldbe(udp_sum, sum)); 10435b0fe478SBruce M Simpson else 1044*ee67461eSJoseph Mingrone ND_PRINT("[icmp6 sum ok] "); 10455b0fe478SBruce M Simpson } 10465b0fe478SBruce M Simpson } 10475b0fe478SBruce M Simpson 1048*ee67461eSJoseph Mingrone icmp6_type = GET_U_1(dp->icmp6_type); 1049*ee67461eSJoseph Mingrone ND_PRINT("ICMP6, %s", tok2str(icmp6_type_values,"unknown icmp6 type (%u)",icmp6_type)); 10501de50e9fSSam Leffler 10511de50e9fSSam Leffler /* display cosmetics: print the packet length for printer that use the vflag now */ 1052*ee67461eSJoseph Mingrone if (ndo->ndo_vflag && (icmp6_type == ND_ROUTER_SOLICIT || 1053*ee67461eSJoseph Mingrone icmp6_type == ND_ROUTER_ADVERT || 1054*ee67461eSJoseph Mingrone icmp6_type == ND_NEIGHBOR_ADVERT || 1055*ee67461eSJoseph Mingrone icmp6_type == ND_NEIGHBOR_SOLICIT || 1056*ee67461eSJoseph Mingrone icmp6_type == ND_REDIRECT || 1057*ee67461eSJoseph Mingrone icmp6_type == ICMP6_HADISCOV_REPLY || 1058*ee67461eSJoseph Mingrone icmp6_type == ICMP6_MOBILEPREFIX_ADVERT )) 1059*ee67461eSJoseph Mingrone ND_PRINT(", length %u", length); 10601de50e9fSSam Leffler 1061*ee67461eSJoseph Mingrone icmp6_code = GET_U_1(dp->icmp6_code); 1062*ee67461eSJoseph Mingrone 1063*ee67461eSJoseph Mingrone switch (icmp6_type) { 1064b0453382SBill Fenner case ICMP6_DST_UNREACH: 1065*ee67461eSJoseph Mingrone ND_PRINT(", %s", tok2str(icmp6_dst_unreach_code_values,"unknown unreach code (%u)",icmp6_code)); 1066*ee67461eSJoseph Mingrone switch (icmp6_code) { 10671de50e9fSSam Leffler 10681de50e9fSSam Leffler case ICMP6_DST_UNREACH_NOROUTE: /* fall through */ 1069b0453382SBill Fenner case ICMP6_DST_UNREACH_ADMIN: 10701de50e9fSSam Leffler case ICMP6_DST_UNREACH_ADDR: 1071*ee67461eSJoseph Mingrone ND_PRINT(" %s",GET_IP6ADDR_STRING(oip->ip6_dst)); 1072b0453382SBill Fenner break; 1073b0453382SBill Fenner case ICMP6_DST_UNREACH_BEYONDSCOPE: 1074*ee67461eSJoseph Mingrone ND_PRINT(" %s, source address %s", 1075*ee67461eSJoseph Mingrone GET_IP6ADDR_STRING(oip->ip6_dst), 1076*ee67461eSJoseph Mingrone GET_IP6ADDR_STRING(oip->ip6_src)); 1077b0453382SBill Fenner break; 1078b0453382SBill Fenner case ICMP6_DST_UNREACH_NOPORT: 10793340d773SGleb Smirnoff if ((ouh = get_upperlayer(ndo, (const u_char *)oip, &prot)) 1080685295f4SBill Fenner == NULL) 1081685295f4SBill Fenner goto trunc; 1082685295f4SBill Fenner 1083*ee67461eSJoseph Mingrone dport = GET_BE_U_2(ouh->uh_dport); 1084685295f4SBill Fenner switch (prot) { 1085b0453382SBill Fenner case IPPROTO_TCP: 1086*ee67461eSJoseph Mingrone ND_PRINT(", %s tcp port %s", 1087*ee67461eSJoseph Mingrone GET_IP6ADDR_STRING(oip->ip6_dst), 1088*ee67461eSJoseph Mingrone tcpport_string(ndo, dport)); 1089b0453382SBill Fenner break; 1090b0453382SBill Fenner case IPPROTO_UDP: 1091*ee67461eSJoseph Mingrone ND_PRINT(", %s udp port %s", 1092*ee67461eSJoseph Mingrone GET_IP6ADDR_STRING(oip->ip6_dst), 1093*ee67461eSJoseph Mingrone udpport_string(ndo, dport)); 1094b0453382SBill Fenner break; 1095b0453382SBill Fenner default: 1096*ee67461eSJoseph Mingrone ND_PRINT(", %s protocol %u port %u unreachable", 1097*ee67461eSJoseph Mingrone GET_IP6ADDR_STRING(oip->ip6_dst), 1098*ee67461eSJoseph Mingrone prot, dport); 1099b0453382SBill Fenner break; 1100b0453382SBill Fenner } 1101b0453382SBill Fenner break; 1102b0453382SBill Fenner default: 11033c602fabSXin LI if (ndo->ndo_vflag <= 1) { 11043c602fabSXin LI print_unknown_data(ndo, bp,"\n\t",length); 11051de50e9fSSam Leffler return; 11061de50e9fSSam Leffler } 1107b0453382SBill Fenner break; 1108b0453382SBill Fenner } 1109b0453382SBill Fenner break; 1110b0453382SBill Fenner case ICMP6_PACKET_TOO_BIG: 1111*ee67461eSJoseph Mingrone ND_PRINT(", mtu %u", GET_BE_U_4(dp->icmp6_mtu)); 1112b0453382SBill Fenner break; 1113b0453382SBill Fenner case ICMP6_TIME_EXCEEDED: 1114*ee67461eSJoseph Mingrone switch (icmp6_code) { 1115b0453382SBill Fenner case ICMP6_TIME_EXCEED_TRANSIT: 1116*ee67461eSJoseph Mingrone ND_PRINT(" for %s", 1117*ee67461eSJoseph Mingrone GET_IP6ADDR_STRING(oip->ip6_dst)); 1118b0453382SBill Fenner break; 1119b0453382SBill Fenner case ICMP6_TIME_EXCEED_REASSEMBLY: 1120*ee67461eSJoseph Mingrone ND_PRINT(" (reassembly)"); 1121b0453382SBill Fenner break; 1122b0453382SBill Fenner default: 1123*ee67461eSJoseph Mingrone ND_PRINT(", unknown code (%u)", icmp6_code); 1124b0453382SBill Fenner break; 1125b0453382SBill Fenner } 1126b0453382SBill Fenner break; 1127b0453382SBill Fenner case ICMP6_PARAM_PROB: 1128*ee67461eSJoseph Mingrone ND_TCHECK_16(oip->ip6_dst); 1129*ee67461eSJoseph Mingrone switch (icmp6_code) { 1130b0453382SBill Fenner case ICMP6_PARAMPROB_HEADER: 1131*ee67461eSJoseph Mingrone ND_PRINT(", erroneous - octet %u", 1132*ee67461eSJoseph Mingrone GET_BE_U_4(dp->icmp6_pptr)); 1133b0453382SBill Fenner break; 1134b0453382SBill Fenner case ICMP6_PARAMPROB_NEXTHEADER: 1135*ee67461eSJoseph Mingrone ND_PRINT(", next header - octet %u", 1136*ee67461eSJoseph Mingrone GET_BE_U_4(dp->icmp6_pptr)); 1137b0453382SBill Fenner break; 1138b0453382SBill Fenner case ICMP6_PARAMPROB_OPTION: 1139*ee67461eSJoseph Mingrone ND_PRINT(", option - octet %u", 1140*ee67461eSJoseph Mingrone GET_BE_U_4(dp->icmp6_pptr)); 1141*ee67461eSJoseph Mingrone break; 1142*ee67461eSJoseph Mingrone case ICMP6_PARAMPROB_FRAGHDRCHAIN: 1143*ee67461eSJoseph Mingrone ND_PRINT(", incomplete header chain - octet %u", 1144*ee67461eSJoseph Mingrone GET_BE_U_4(dp->icmp6_pptr)); 1145b0453382SBill Fenner break; 1146b0453382SBill Fenner default: 1147*ee67461eSJoseph Mingrone ND_PRINT(", code-#%u", 1148*ee67461eSJoseph Mingrone icmp6_code); 1149b0453382SBill Fenner break; 1150b0453382SBill Fenner } 1151b0453382SBill Fenner break; 1152b0453382SBill Fenner case ICMP6_ECHO_REQUEST: 1153b0453382SBill Fenner case ICMP6_ECHO_REPLY: 1154*ee67461eSJoseph Mingrone ND_PRINT(", id %u, seq %u", GET_BE_U_2(dp->icmp6_id), 1155*ee67461eSJoseph Mingrone GET_BE_U_2(dp->icmp6_seq)); 1156b0453382SBill Fenner break; 1157b0453382SBill Fenner case ICMP6_MEMBERSHIP_QUERY: 11581de50e9fSSam Leffler if (length == MLD_MINLEN) { 11593c602fabSXin LI mld6_print(ndo, (const u_char *)dp); 11601de50e9fSSam Leffler } else if (length >= MLDV2_MINLEN) { 1161*ee67461eSJoseph Mingrone ND_PRINT(" v2"); 11623c602fabSXin LI mldv2_query_print(ndo, (const u_char *)dp, length); 11631de50e9fSSam Leffler } else { 1164*ee67461eSJoseph Mingrone ND_PRINT(" unknown-version (len %u) ", length); 11651de50e9fSSam Leffler } 1166b0453382SBill Fenner break; 1167b0453382SBill Fenner case ICMP6_MEMBERSHIP_REPORT: 11683c602fabSXin LI mld6_print(ndo, (const u_char *)dp); 1169b0453382SBill Fenner break; 1170b0453382SBill Fenner case ICMP6_MEMBERSHIP_REDUCTION: 11713c602fabSXin LI mld6_print(ndo, (const u_char *)dp); 1172b0453382SBill Fenner break; 1173b0453382SBill Fenner case ND_ROUTER_SOLICIT: 1174b0453382SBill Fenner #define RTSOLLEN 8 11753c602fabSXin LI if (ndo->ndo_vflag) { 1176*ee67461eSJoseph Mingrone if (icmp6_opt_print(ndo, (const u_char *)dp + RTSOLLEN, 1177*ee67461eSJoseph Mingrone length - RTSOLLEN) == -1) 1178*ee67461eSJoseph Mingrone goto trunc; 1179b0453382SBill Fenner } 1180b0453382SBill Fenner break; 1181b0453382SBill Fenner case ND_ROUTER_ADVERT: 11821de50e9fSSam Leffler #define RTADVLEN 16 11833c602fabSXin LI if (ndo->ndo_vflag) { 11843340d773SGleb Smirnoff const struct nd_router_advert *p; 1185b0453382SBill Fenner 11863340d773SGleb Smirnoff p = (const struct nd_router_advert *)dp; 1187*ee67461eSJoseph Mingrone ND_PRINT("\n\thop limit %u, Flags [%s]" 118839e421e8SCy Schubert ", pref %s, router lifetime %us, reachable time %ums, retrans timer %ums", 1189*ee67461eSJoseph Mingrone GET_U_1(p->nd_ra_curhoplimit), 1190*ee67461eSJoseph Mingrone bittok2str(icmp6_opt_ra_flag_values,"none",GET_U_1(p->nd_ra_flags_reserved)), 1191*ee67461eSJoseph Mingrone get_rtpref(GET_U_1(p->nd_ra_flags_reserved)), 1192*ee67461eSJoseph Mingrone GET_BE_U_2(p->nd_ra_router_lifetime), 1193*ee67461eSJoseph Mingrone GET_BE_U_4(p->nd_ra_reachable), 1194*ee67461eSJoseph Mingrone GET_BE_U_4(p->nd_ra_retransmit)); 11951de50e9fSSam Leffler 1196*ee67461eSJoseph Mingrone if (icmp6_opt_print(ndo, (const u_char *)dp + RTADVLEN, 1197*ee67461eSJoseph Mingrone length - RTADVLEN) == -1) 1198*ee67461eSJoseph Mingrone goto trunc; 1199b0453382SBill Fenner } 1200b0453382SBill Fenner break; 1201b0453382SBill Fenner case ND_NEIGHBOR_SOLICIT: 1202b0453382SBill Fenner { 12033340d773SGleb Smirnoff const struct nd_neighbor_solicit *p; 12043340d773SGleb Smirnoff p = (const struct nd_neighbor_solicit *)dp; 1205*ee67461eSJoseph Mingrone ND_PRINT(", who has %s", GET_IP6ADDR_STRING(p->nd_ns_target)); 12063c602fabSXin LI if (ndo->ndo_vflag) { 1207b0453382SBill Fenner #define NDSOLLEN 24 1208*ee67461eSJoseph Mingrone if (icmp6_opt_print(ndo, (const u_char *)dp + NDSOLLEN, 1209*ee67461eSJoseph Mingrone length - NDSOLLEN) == -1) 1210*ee67461eSJoseph Mingrone goto trunc; 1211b0453382SBill Fenner } 1212b0453382SBill Fenner } 1213b0453382SBill Fenner break; 1214b0453382SBill Fenner case ND_NEIGHBOR_ADVERT: 1215b0453382SBill Fenner { 12163340d773SGleb Smirnoff const struct nd_neighbor_advert *p; 1217b0453382SBill Fenner 12183340d773SGleb Smirnoff p = (const struct nd_neighbor_advert *)dp; 1219*ee67461eSJoseph Mingrone ND_PRINT(", tgt is %s", 1220*ee67461eSJoseph Mingrone GET_IP6ADDR_STRING(p->nd_na_target)); 12213c602fabSXin LI if (ndo->ndo_vflag) { 1222*ee67461eSJoseph Mingrone ND_PRINT(", Flags [%s]", 12231de50e9fSSam Leffler bittok2str(icmp6_nd_na_flag_values, 12241de50e9fSSam Leffler "none", 1225*ee67461eSJoseph Mingrone GET_BE_U_4(p->nd_na_flags_reserved))); 1226b0453382SBill Fenner #define NDADVLEN 24 1227*ee67461eSJoseph Mingrone if (icmp6_opt_print(ndo, (const u_char *)dp + NDADVLEN, 1228*ee67461eSJoseph Mingrone length - NDADVLEN) == -1) 1229*ee67461eSJoseph Mingrone goto trunc; 1230685295f4SBill Fenner #undef NDADVLEN 1231b0453382SBill Fenner } 1232b0453382SBill Fenner } 1233b0453382SBill Fenner break; 1234b0453382SBill Fenner case ND_REDIRECT: 1235*ee67461eSJoseph Mingrone { 1236*ee67461eSJoseph Mingrone const struct nd_redirect *p; 1237*ee67461eSJoseph Mingrone 1238*ee67461eSJoseph Mingrone p = (const struct nd_redirect *)dp; 1239*ee67461eSJoseph Mingrone ND_PRINT(", %s", GET_IP6ADDR_STRING(p->nd_rd_dst)); 1240*ee67461eSJoseph Mingrone ND_PRINT(" to %s", GET_IP6ADDR_STRING(p->nd_rd_target)); 1241b0453382SBill Fenner #define REDIRECTLEN 40 12423c602fabSXin LI if (ndo->ndo_vflag) { 1243*ee67461eSJoseph Mingrone if (icmp6_opt_print(ndo, (const u_char *)dp + REDIRECTLEN, 1244*ee67461eSJoseph Mingrone length - REDIRECTLEN) == -1) 1245*ee67461eSJoseph Mingrone goto trunc; 1246*ee67461eSJoseph Mingrone #undef REDIRECTLEN 1247*ee67461eSJoseph Mingrone } 1248b0453382SBill Fenner } 1249b0453382SBill Fenner break; 1250b0453382SBill Fenner case ICMP6_ROUTER_RENUMBERING: 12513c602fabSXin LI icmp6_rrenum_print(ndo, bp, ep); 1252b0453382SBill Fenner break; 1253685295f4SBill Fenner case ICMP6_NI_QUERY: 1254685295f4SBill Fenner case ICMP6_NI_REPLY: 12553c602fabSXin LI icmp6_nodeinfo_print(ndo, length, bp, ep); 12565b0fe478SBruce M Simpson break; 12571de50e9fSSam Leffler case IND_SOLICIT: 12581de50e9fSSam Leffler case IND_ADVERT: 12591de50e9fSSam Leffler break; 12601de50e9fSSam Leffler case ICMP6_V2_MEMBERSHIP_REPORT: 12613c602fabSXin LI mldv2_report_print(ndo, (const u_char *) dp, length); 12621de50e9fSSam Leffler break; 12631de50e9fSSam Leffler case ICMP6_MOBILEPREFIX_SOLICIT: /* fall through */ 12645b0fe478SBruce M Simpson case ICMP6_HADISCOV_REQUEST: 1265*ee67461eSJoseph Mingrone ND_PRINT(", id 0x%04x", GET_BE_U_2(dp->icmp6_data16[0])); 12665b0fe478SBruce M Simpson break; 12675b0fe478SBruce M Simpson case ICMP6_HADISCOV_REPLY: 12683c602fabSXin LI if (ndo->ndo_vflag) { 12693340d773SGleb Smirnoff const u_char *cp; 1270*ee67461eSJoseph Mingrone const u_char *p; 12715b0fe478SBruce M Simpson 1272*ee67461eSJoseph Mingrone ND_PRINT(", id 0x%04x", 1273*ee67461eSJoseph Mingrone GET_BE_U_2(dp->icmp6_data16[0])); 12743340d773SGleb Smirnoff cp = (const u_char *)dp + length; 1275*ee67461eSJoseph Mingrone p = (const u_char *)(dp + 1); 1276*ee67461eSJoseph Mingrone while (p < cp) { 1277*ee67461eSJoseph Mingrone ND_PRINT(", %s", GET_IP6ADDR_STRING(p)); 1278*ee67461eSJoseph Mingrone p += 16; 12795b0fe478SBruce M Simpson } 12805b0fe478SBruce M Simpson } 12815b0fe478SBruce M Simpson break; 12825b0fe478SBruce M Simpson case ICMP6_MOBILEPREFIX_ADVERT: 12833c602fabSXin LI if (ndo->ndo_vflag) { 1284*ee67461eSJoseph Mingrone uint16_t flags; 1285*ee67461eSJoseph Mingrone 1286*ee67461eSJoseph Mingrone ND_PRINT(", id 0x%04x", 1287*ee67461eSJoseph Mingrone GET_BE_U_2(dp->icmp6_data16[0])); 1288*ee67461eSJoseph Mingrone flags = GET_BE_U_2(dp->icmp6_data16[1]); 1289*ee67461eSJoseph Mingrone if (flags & 0xc000) 1290*ee67461eSJoseph Mingrone ND_PRINT(" "); 1291*ee67461eSJoseph Mingrone if (flags & 0x8000) 1292*ee67461eSJoseph Mingrone ND_PRINT("M"); 1293*ee67461eSJoseph Mingrone if (flags & 0x4000) 1294*ee67461eSJoseph Mingrone ND_PRINT("O"); 12955b0fe478SBruce M Simpson #define MPADVLEN 8 1296*ee67461eSJoseph Mingrone if (icmp6_opt_print(ndo, (const u_char *)dp + MPADVLEN, 1297*ee67461eSJoseph Mingrone length - MPADVLEN) == -1) 1298*ee67461eSJoseph Mingrone goto trunc; 12995b0fe478SBruce M Simpson } 1300b0453382SBill Fenner break; 130127df3f5dSRui Paulo case ND_RPL_MESSAGE: 13023c602fabSXin LI /* plus 4, because struct icmp6_hdr contains 4 bytes of icmp payload */ 1303*ee67461eSJoseph Mingrone rpl_print(ndo, icmp6_code, dp->icmp6_data, length-sizeof(struct icmp6_hdr)+4); 130427df3f5dSRui Paulo break; 1305b0453382SBill Fenner default: 1306*ee67461eSJoseph Mingrone ND_PRINT(", length %u", length); 13073c602fabSXin LI if (ndo->ndo_vflag <= 1) 13083c602fabSXin LI print_unknown_data(ndo, bp,"\n\t", length); 13091de50e9fSSam Leffler return; 1310b0453382SBill Fenner } 13113c602fabSXin LI if (!ndo->ndo_vflag) 1312*ee67461eSJoseph Mingrone ND_PRINT(", length %u", length); 1313b0453382SBill Fenner return; 1314b0453382SBill Fenner trunc: 1315*ee67461eSJoseph Mingrone nd_print_trunc(ndo); 1316b0453382SBill Fenner } 1317b0453382SBill Fenner 13183c602fabSXin LI static const struct udphdr * 13193c602fabSXin LI get_upperlayer(netdissect_options *ndo, const u_char *bp, u_int *prot) 1320685295f4SBill Fenner { 1321a90e161bSBill Fenner const u_char *ep; 13223340d773SGleb Smirnoff const struct ip6_hdr *ip6 = (const struct ip6_hdr *)bp; 13233c602fabSXin LI const struct udphdr *uh; 13243c602fabSXin LI const struct ip6_hbh *hbh; 13253c602fabSXin LI const struct ip6_frag *fragh; 13263c602fabSXin LI const struct ah *ah; 13275b0fe478SBruce M Simpson u_int nh; 13285b0fe478SBruce M Simpson int hlen; 1329685295f4SBill Fenner 1330685295f4SBill Fenner /* 'ep' points to the end of available data. */ 13313c602fabSXin LI ep = ndo->ndo_snapend; 1332685295f4SBill Fenner 1333*ee67461eSJoseph Mingrone if (!ND_TTEST_1(ip6->ip6_nxt)) 1334685295f4SBill Fenner return NULL; 1335685295f4SBill Fenner 1336*ee67461eSJoseph Mingrone nh = GET_U_1(ip6->ip6_nxt); 1337685295f4SBill Fenner hlen = sizeof(struct ip6_hdr); 1338685295f4SBill Fenner 1339f4d0c64aSSam Leffler while (bp < ep) { 1340685295f4SBill Fenner bp += hlen; 1341685295f4SBill Fenner 1342685295f4SBill Fenner switch(nh) { 1343685295f4SBill Fenner case IPPROTO_UDP: 1344685295f4SBill Fenner case IPPROTO_TCP: 13453340d773SGleb Smirnoff uh = (const struct udphdr *)bp; 1346*ee67461eSJoseph Mingrone if (ND_TTEST_2(uh->uh_dport)) { 1347685295f4SBill Fenner *prot = nh; 1348685295f4SBill Fenner return(uh); 1349685295f4SBill Fenner } 1350685295f4SBill Fenner else 1351685295f4SBill Fenner return(NULL); 1352685295f4SBill Fenner /* NOTREACHED */ 1353685295f4SBill Fenner 1354685295f4SBill Fenner case IPPROTO_HOPOPTS: 1355685295f4SBill Fenner case IPPROTO_DSTOPTS: 1356685295f4SBill Fenner case IPPROTO_ROUTING: 13573340d773SGleb Smirnoff hbh = (const struct ip6_hbh *)bp; 1358*ee67461eSJoseph Mingrone if (!ND_TTEST_1(hbh->ip6h_len)) 1359685295f4SBill Fenner return(NULL); 1360*ee67461eSJoseph Mingrone nh = GET_U_1(hbh->ip6h_nxt); 1361*ee67461eSJoseph Mingrone hlen = (GET_U_1(hbh->ip6h_len) + 1) << 3; 1362685295f4SBill Fenner break; 1363685295f4SBill Fenner 1364685295f4SBill Fenner case IPPROTO_FRAGMENT: /* this should be odd, but try anyway */ 13653340d773SGleb Smirnoff fragh = (const struct ip6_frag *)bp; 1366*ee67461eSJoseph Mingrone if (!ND_TTEST_2(fragh->ip6f_offlg)) 1367685295f4SBill Fenner return(NULL); 1368685295f4SBill Fenner /* fragments with non-zero offset are meaningless */ 1369*ee67461eSJoseph Mingrone if ((GET_BE_U_2(fragh->ip6f_offlg) & IP6F_OFF_MASK) != 0) 1370685295f4SBill Fenner return(NULL); 1371*ee67461eSJoseph Mingrone nh = GET_U_1(fragh->ip6f_nxt); 1372685295f4SBill Fenner hlen = sizeof(struct ip6_frag); 1373685295f4SBill Fenner break; 1374685295f4SBill Fenner 1375685295f4SBill Fenner case IPPROTO_AH: 13763340d773SGleb Smirnoff ah = (const struct ah *)bp; 1377*ee67461eSJoseph Mingrone if (!ND_TTEST_1(ah->ah_len)) 1378685295f4SBill Fenner return(NULL); 1379*ee67461eSJoseph Mingrone nh = GET_U_1(ah->ah_nxt); 1380*ee67461eSJoseph Mingrone hlen = (GET_U_1(ah->ah_len) + 2) << 2; 1381685295f4SBill Fenner break; 1382685295f4SBill Fenner 1383685295f4SBill Fenner default: /* unknown or undecodable header */ 1384685295f4SBill Fenner *prot = nh; /* meaningless, but set here anyway */ 1385685295f4SBill Fenner return(NULL); 1386685295f4SBill Fenner } 1387685295f4SBill Fenner } 1388685295f4SBill Fenner 1389685295f4SBill Fenner return(NULL); /* should be notreached, though */ 1390685295f4SBill Fenner } 1391685295f4SBill Fenner 1392*ee67461eSJoseph Mingrone static int 13933c602fabSXin LI icmp6_opt_print(netdissect_options *ndo, const u_char *bp, int resid) 1394b0453382SBill Fenner { 1395a90e161bSBill Fenner const struct nd_opt_hdr *op; 1396*ee67461eSJoseph Mingrone uint8_t opt_type; 1397*ee67461eSJoseph Mingrone u_int opt_len; 1398a90e161bSBill Fenner const struct nd_opt_prefix_info *opp; 1399a90e161bSBill Fenner const struct nd_opt_mtu *opm; 140027df3f5dSRui Paulo const struct nd_opt_rdnss *oprd; 1401d03c0883SXin LI const struct nd_opt_dnssl *opds; 1402a90e161bSBill Fenner const struct nd_opt_advinterval *opa; 14035b0fe478SBruce M Simpson const struct nd_opt_homeagent_info *oph; 1404a90e161bSBill Fenner const struct nd_opt_route_info *opri; 1405d03c0883SXin LI const u_char *cp, *ep, *domp; 1406*ee67461eSJoseph Mingrone nd_ipv6 in6; 1407a90e161bSBill Fenner size_t l; 140827df3f5dSRui Paulo u_int i; 1409b0453382SBill Fenner 1410a90e161bSBill Fenner cp = bp; 1411685295f4SBill Fenner /* 'ep' points to the end of available data. */ 14123c602fabSXin LI ep = ndo->ndo_snapend; 1413b0453382SBill Fenner 1414a90e161bSBill Fenner while (cp < ep) { 14153340d773SGleb Smirnoff op = (const struct nd_opt_hdr *)cp; 1416a90e161bSBill Fenner 1417*ee67461eSJoseph Mingrone ND_TCHECK_1(op->nd_opt_len); 1418b0453382SBill Fenner if (resid <= 0) 1419*ee67461eSJoseph Mingrone return 0; 1420*ee67461eSJoseph Mingrone opt_type = GET_U_1(op->nd_opt_type); 1421*ee67461eSJoseph Mingrone opt_len = GET_U_1(op->nd_opt_len); 1422*ee67461eSJoseph Mingrone if (opt_len == 0) 1423a90e161bSBill Fenner goto trunc; 1424*ee67461eSJoseph Mingrone if (cp + (opt_len << 3) > ep) 1425a90e161bSBill Fenner goto trunc; 1426a90e161bSBill Fenner 1427*ee67461eSJoseph Mingrone ND_PRINT("\n\t %s option (%u), length %u (%u): ", 1428*ee67461eSJoseph Mingrone tok2str(icmp6_opt_values, "unknown", opt_type), 1429*ee67461eSJoseph Mingrone opt_type, 1430*ee67461eSJoseph Mingrone opt_len << 3, 1431*ee67461eSJoseph Mingrone opt_len); 14321de50e9fSSam Leffler 1433*ee67461eSJoseph Mingrone switch (opt_type) { 1434b0453382SBill Fenner case ND_OPT_SOURCE_LINKADDR: 1435*ee67461eSJoseph Mingrone l = (opt_len << 3) - 2; 14363c602fabSXin LI print_lladdr(ndo, cp + 2, l); 1437b0453382SBill Fenner break; 1438b0453382SBill Fenner case ND_OPT_TARGET_LINKADDR: 1439*ee67461eSJoseph Mingrone l = (opt_len << 3) - 2; 14403c602fabSXin LI print_lladdr(ndo, cp + 2, l); 1441b0453382SBill Fenner break; 1442b0453382SBill Fenner case ND_OPT_PREFIX_INFORMATION: 14433340d773SGleb Smirnoff opp = (const struct nd_opt_prefix_info *)op; 1444*ee67461eSJoseph Mingrone ND_PRINT("%s/%u%s, Flags [%s], valid time %s", 1445*ee67461eSJoseph Mingrone GET_IP6ADDR_STRING(opp->nd_opt_pi_prefix), 1446*ee67461eSJoseph Mingrone GET_U_1(opp->nd_opt_pi_prefix_len), 1447*ee67461eSJoseph Mingrone (opt_len != 4) ? "badlen" : "", 1448*ee67461eSJoseph Mingrone bittok2str(icmp6_opt_pi_flag_values, "none", GET_U_1(opp->nd_opt_pi_flags_reserved)), 1449*ee67461eSJoseph Mingrone get_lifetime(GET_BE_U_4(opp->nd_opt_pi_valid_time))); 1450*ee67461eSJoseph Mingrone ND_PRINT(", pref. time %s", 1451*ee67461eSJoseph Mingrone get_lifetime(GET_BE_U_4(opp->nd_opt_pi_preferred_time))); 1452b0453382SBill Fenner break; 1453b0453382SBill Fenner case ND_OPT_REDIRECTED_HEADER: 1454*ee67461eSJoseph Mingrone print_unknown_data(ndo, bp,"\n\t ",opt_len<<3); 1455b0453382SBill Fenner /* xxx */ 1456b0453382SBill Fenner break; 1457b0453382SBill Fenner case ND_OPT_MTU: 14583340d773SGleb Smirnoff opm = (const struct nd_opt_mtu *)op; 1459*ee67461eSJoseph Mingrone ND_PRINT(" %u%s", 1460*ee67461eSJoseph Mingrone GET_BE_U_4(opm->nd_opt_mtu_mtu), 1461*ee67461eSJoseph Mingrone (opt_len != 1) ? "bad option length" : "" ); 1462b0453382SBill Fenner break; 146327df3f5dSRui Paulo case ND_OPT_RDNSS: 14643340d773SGleb Smirnoff oprd = (const struct nd_opt_rdnss *)op; 1465*ee67461eSJoseph Mingrone l = (opt_len - 1) / 2; 1466*ee67461eSJoseph Mingrone ND_PRINT(" lifetime %us,", 1467*ee67461eSJoseph Mingrone GET_BE_U_4(oprd->nd_opt_rdnss_lifetime)); 146827df3f5dSRui Paulo for (i = 0; i < l; i++) { 1469*ee67461eSJoseph Mingrone ND_PRINT(" addr: %s", 1470*ee67461eSJoseph Mingrone GET_IP6ADDR_STRING(oprd->nd_opt_rdnss_addr[i])); 147127df3f5dSRui Paulo } 147227df3f5dSRui Paulo break; 1473d03c0883SXin LI case ND_OPT_DNSSL: 14743340d773SGleb Smirnoff opds = (const struct nd_opt_dnssl *)op; 1475*ee67461eSJoseph Mingrone ND_PRINT(" lifetime %us, domain(s):", 1476*ee67461eSJoseph Mingrone GET_BE_U_4(opds->nd_opt_dnssl_lifetime)); 1477d03c0883SXin LI domp = cp + 8; /* domain names, variable-sized, RFC1035-encoded */ 1478*ee67461eSJoseph Mingrone while (domp < cp + (opt_len << 3) && GET_U_1(domp) != '\0') 1479d03c0883SXin LI { 1480*ee67461eSJoseph Mingrone ND_PRINT(" "); 1481*ee67461eSJoseph Mingrone if ((domp = fqdn_print(ndo, domp, bp)) == NULL) 1482d03c0883SXin LI goto trunc; 1483d03c0883SXin LI } 1484d03c0883SXin LI break; 1485a90e161bSBill Fenner case ND_OPT_ADVINTERVAL: 14863340d773SGleb Smirnoff opa = (const struct nd_opt_advinterval *)op; 1487*ee67461eSJoseph Mingrone ND_PRINT(" %ums", 1488*ee67461eSJoseph Mingrone GET_BE_U_4(opa->nd_opt_adv_interval)); 1489a90e161bSBill Fenner break; 14905b0fe478SBruce M Simpson case ND_OPT_HOMEAGENT_INFO: 14913340d773SGleb Smirnoff oph = (const struct nd_opt_homeagent_info *)op; 1492*ee67461eSJoseph Mingrone ND_PRINT(" preference %u, lifetime %u", 1493*ee67461eSJoseph Mingrone GET_BE_U_2(oph->nd_opt_hai_preference), 1494*ee67461eSJoseph Mingrone GET_BE_U_2(oph->nd_opt_hai_lifetime)); 14955b0fe478SBruce M Simpson break; 1496a90e161bSBill Fenner case ND_OPT_ROUTE_INFO: 14973340d773SGleb Smirnoff opri = (const struct nd_opt_route_info *)op; 1498*ee67461eSJoseph Mingrone ND_TCHECK_4(opri->nd_opt_rti_lifetime); 1499a90e161bSBill Fenner memset(&in6, 0, sizeof(in6)); 1500*ee67461eSJoseph Mingrone switch (opt_len) { 1501a90e161bSBill Fenner case 1: 1502a90e161bSBill Fenner break; 1503a90e161bSBill Fenner case 2: 1504*ee67461eSJoseph Mingrone GET_CPY_BYTES(&in6, opri + 1, 8); 1505a90e161bSBill Fenner break; 1506a90e161bSBill Fenner case 3: 1507*ee67461eSJoseph Mingrone GET_CPY_BYTES(&in6, opri + 1, 16); 1508685295f4SBill Fenner break; 1509b0453382SBill Fenner default: 1510a90e161bSBill Fenner goto trunc; 1511a90e161bSBill Fenner } 1512*ee67461eSJoseph Mingrone ND_PRINT(" %s/%u", ip6addr_string(ndo, (const u_char *)&in6), /* local buffer, not packet data; don't use GET_IP6ADDR_STRING() */ 1513*ee67461eSJoseph Mingrone GET_U_1(opri->nd_opt_rti_prefixlen)); 1514*ee67461eSJoseph Mingrone ND_PRINT(", pref=%s", 1515*ee67461eSJoseph Mingrone get_rtpref(GET_U_1(opri->nd_opt_rti_flags))); 1516*ee67461eSJoseph Mingrone ND_PRINT(", lifetime=%s", 1517*ee67461eSJoseph Mingrone get_lifetime(GET_BE_U_4(opri->nd_opt_rti_lifetime))); 1518a90e161bSBill Fenner break; 1519a90e161bSBill Fenner default: 15203c602fabSXin LI if (ndo->ndo_vflag <= 1) { 1521*ee67461eSJoseph Mingrone print_unknown_data(ndo,cp+2,"\n\t ", (opt_len << 3) - 2); /* skip option header */ 1522*ee67461eSJoseph Mingrone return 0; 15231de50e9fSSam Leffler } 1524b0453382SBill Fenner break; 1525b0453382SBill Fenner } 15261de50e9fSSam Leffler /* do we want to see an additional hexdump ? */ 15273c602fabSXin LI if (ndo->ndo_vflag> 1) 1528*ee67461eSJoseph Mingrone print_unknown_data(ndo, cp+2,"\n\t ", (opt_len << 3) - 2); /* skip option header */ 1529a90e161bSBill Fenner 1530*ee67461eSJoseph Mingrone cp += opt_len << 3; 1531*ee67461eSJoseph Mingrone resid -= opt_len << 3; 1532a90e161bSBill Fenner } 1533*ee67461eSJoseph Mingrone return 0; 1534a90e161bSBill Fenner 1535b0453382SBill Fenner trunc: 1536*ee67461eSJoseph Mingrone return -1; 1537b0453382SBill Fenner } 1538b0453382SBill Fenner 15395b0fe478SBruce M Simpson static void 15403c602fabSXin LI mld6_print(netdissect_options *ndo, const u_char *bp) 1541b0453382SBill Fenner { 15423340d773SGleb Smirnoff const struct mld6_hdr *mp = (const struct mld6_hdr *)bp; 1543a90e161bSBill Fenner const u_char *ep; 1544b0453382SBill Fenner 1545685295f4SBill Fenner /* 'ep' points to the end of available data. */ 15463c602fabSXin LI ep = ndo->ndo_snapend; 1547b0453382SBill Fenner 15483340d773SGleb Smirnoff if ((const u_char *)mp + sizeof(*mp) > ep) 1549b0453382SBill Fenner return; 1550b0453382SBill Fenner 1551*ee67461eSJoseph Mingrone ND_PRINT("max resp delay: %u ", GET_BE_U_2(mp->mld6_maxdelay)); 1552*ee67461eSJoseph Mingrone ND_PRINT("addr: %s", GET_IP6ADDR_STRING(mp->mld6_addr)); 1553685295f4SBill Fenner } 1554685295f4SBill Fenner 1555685295f4SBill Fenner static void 15563c602fabSXin LI mldv2_report_print(netdissect_options *ndo, const u_char *bp, u_int len) 15571de50e9fSSam Leffler { 15583340d773SGleb Smirnoff const struct icmp6_hdr *icp = (const struct icmp6_hdr *) bp; 15591de50e9fSSam Leffler u_int group, nsrcs, ngroups; 15601de50e9fSSam Leffler u_int i, j; 15611de50e9fSSam Leffler 15621de50e9fSSam Leffler /* Minimum len is 8 */ 15631de50e9fSSam Leffler if (len < 8) { 1564*ee67461eSJoseph Mingrone ND_PRINT(" [invalid len %u]", len); 15651de50e9fSSam Leffler return; 15661de50e9fSSam Leffler } 15671de50e9fSSam Leffler 1568*ee67461eSJoseph Mingrone ngroups = GET_BE_U_2(icp->icmp6_data16[1]); 1569*ee67461eSJoseph Mingrone ND_PRINT(", %u group record(s)", ngroups); 15703c602fabSXin LI if (ndo->ndo_vflag > 0) { 15711de50e9fSSam Leffler /* Print the group records */ 15721de50e9fSSam Leffler group = 8; 15731de50e9fSSam Leffler for (i = 0; i < ngroups; i++) { 15741de50e9fSSam Leffler /* type(1) + auxlen(1) + numsrc(2) + grp(16) */ 15751de50e9fSSam Leffler if (len < group + 20) { 1576*ee67461eSJoseph Mingrone ND_PRINT(" [invalid number of groups]"); 15771de50e9fSSam Leffler return; 15781de50e9fSSam Leffler } 1579*ee67461eSJoseph Mingrone ND_PRINT(" [gaddr %s", GET_IP6ADDR_STRING(bp + group + 4)); 1580*ee67461eSJoseph Mingrone ND_PRINT(" %s", tok2str(mldv2report2str, " [v2-report-#%u]", 1581*ee67461eSJoseph Mingrone GET_U_1(bp + group))); 1582*ee67461eSJoseph Mingrone nsrcs = GET_BE_U_2(bp + group + 2); 15831de50e9fSSam Leffler /* Check the number of sources and print them */ 1584*ee67461eSJoseph Mingrone if (len < group + 20 + (nsrcs * sizeof(nd_ipv6))) { 1585*ee67461eSJoseph Mingrone ND_PRINT(" [invalid number of sources %u]", nsrcs); 15861de50e9fSSam Leffler return; 15871de50e9fSSam Leffler } 15883c602fabSXin LI if (ndo->ndo_vflag == 1) 1589*ee67461eSJoseph Mingrone ND_PRINT(", %u source(s)", nsrcs); 15901de50e9fSSam Leffler else { 15911de50e9fSSam Leffler /* Print the sources */ 1592*ee67461eSJoseph Mingrone ND_PRINT(" {"); 15931de50e9fSSam Leffler for (j = 0; j < nsrcs; j++) { 1594*ee67461eSJoseph Mingrone ND_PRINT(" %s", GET_IP6ADDR_STRING(bp + group + 20 + (j * sizeof(nd_ipv6)))); 15951de50e9fSSam Leffler } 1596*ee67461eSJoseph Mingrone ND_PRINT(" }"); 15971de50e9fSSam Leffler } 15981de50e9fSSam Leffler /* Next group record */ 1599*ee67461eSJoseph Mingrone group += 20 + nsrcs * sizeof(nd_ipv6); 1600*ee67461eSJoseph Mingrone ND_PRINT("]"); 16011de50e9fSSam Leffler } 16021de50e9fSSam Leffler } 16031de50e9fSSam Leffler } 16041de50e9fSSam Leffler 16051de50e9fSSam Leffler static void 16063c602fabSXin LI mldv2_query_print(netdissect_options *ndo, const u_char *bp, u_int len) 16071de50e9fSSam Leffler { 16083340d773SGleb Smirnoff const struct icmp6_hdr *icp = (const struct icmp6_hdr *) bp; 16091de50e9fSSam Leffler u_int mrc; 1610*ee67461eSJoseph Mingrone u_int mrt, qqi; 16111de50e9fSSam Leffler u_int nsrcs; 1612*ee67461eSJoseph Mingrone u_int i; 16131de50e9fSSam Leffler 16141de50e9fSSam Leffler /* Minimum len is 28 */ 16151de50e9fSSam Leffler if (len < 28) { 1616*ee67461eSJoseph Mingrone ND_PRINT(" [invalid len %u]", len); 16171de50e9fSSam Leffler return; 16181de50e9fSSam Leffler } 1619*ee67461eSJoseph Mingrone mrc = GET_BE_U_2(icp->icmp6_data16[0]); 16201de50e9fSSam Leffler if (mrc < 32768) { 16211de50e9fSSam Leffler mrt = mrc; 16221de50e9fSSam Leffler } else { 16231de50e9fSSam Leffler mrt = ((mrc & 0x0fff) | 0x1000) << (((mrc & 0x7000) >> 12) + 3); 16241de50e9fSSam Leffler } 16253c602fabSXin LI if (ndo->ndo_vflag) { 1626*ee67461eSJoseph Mingrone ND_PRINT(" [max resp delay=%u]", mrt); 16271de50e9fSSam Leffler } 1628*ee67461eSJoseph Mingrone ND_PRINT(" [gaddr %s", GET_IP6ADDR_STRING(bp + 8)); 16291de50e9fSSam Leffler 16303c602fabSXin LI if (ndo->ndo_vflag) { 1631*ee67461eSJoseph Mingrone if (GET_U_1(bp + 24) & 0x08) { 1632*ee67461eSJoseph Mingrone ND_PRINT(" sflag"); 16331de50e9fSSam Leffler } 1634*ee67461eSJoseph Mingrone if (GET_U_1(bp + 24) & 0x07) { 1635*ee67461eSJoseph Mingrone ND_PRINT(" robustness=%u", GET_U_1(bp + 24) & 0x07); 16361de50e9fSSam Leffler } 1637*ee67461eSJoseph Mingrone if (GET_U_1(bp + 25) < 128) { 1638*ee67461eSJoseph Mingrone qqi = GET_U_1(bp + 25); 16391de50e9fSSam Leffler } else { 1640*ee67461eSJoseph Mingrone qqi = ((GET_U_1(bp + 25) & 0x0f) | 0x10) << 1641*ee67461eSJoseph Mingrone (((GET_U_1(bp + 25) & 0x70) >> 4) + 3); 16421de50e9fSSam Leffler } 1643*ee67461eSJoseph Mingrone ND_PRINT(" qqi=%u", qqi); 16441de50e9fSSam Leffler } 16451de50e9fSSam Leffler 1646*ee67461eSJoseph Mingrone nsrcs = GET_BE_U_2(bp + 26); 16471de50e9fSSam Leffler if (nsrcs > 0) { 1648*ee67461eSJoseph Mingrone if (len < 28 + nsrcs * sizeof(nd_ipv6)) 1649*ee67461eSJoseph Mingrone ND_PRINT(" [invalid number of sources]"); 16503c602fabSXin LI else if (ndo->ndo_vflag > 1) { 1651*ee67461eSJoseph Mingrone ND_PRINT(" {"); 16521de50e9fSSam Leffler for (i = 0; i < nsrcs; i++) { 1653*ee67461eSJoseph Mingrone ND_PRINT(" %s", GET_IP6ADDR_STRING(bp + 28 + (i * sizeof(nd_ipv6)))); 16541de50e9fSSam Leffler } 1655*ee67461eSJoseph Mingrone ND_PRINT(" }"); 16561de50e9fSSam Leffler } else 1657*ee67461eSJoseph Mingrone ND_PRINT(", %u source(s)", nsrcs); 16581de50e9fSSam Leffler } 1659*ee67461eSJoseph Mingrone ND_PRINT("]"); 16601de50e9fSSam Leffler } 16611de50e9fSSam Leffler 166227df3f5dSRui Paulo static void 16633c602fabSXin LI dnsname_print(netdissect_options *ndo, const u_char *cp, const u_char *ep) 1664685295f4SBill Fenner { 1665685295f4SBill Fenner int i; 1666685295f4SBill Fenner 1667685295f4SBill Fenner /* DNS name decoding - no decompression */ 1668*ee67461eSJoseph Mingrone ND_PRINT(", \""); 1669685295f4SBill Fenner while (cp < ep) { 1670*ee67461eSJoseph Mingrone i = GET_U_1(cp); 1671*ee67461eSJoseph Mingrone cp++; 1672685295f4SBill Fenner if (i) { 1673685295f4SBill Fenner if (i > ep - cp) { 1674*ee67461eSJoseph Mingrone ND_PRINT("???"); 1675685295f4SBill Fenner break; 1676685295f4SBill Fenner } 1677685295f4SBill Fenner while (i-- && cp < ep) { 1678*ee67461eSJoseph Mingrone fn_print_char(ndo, GET_U_1(cp)); 1679685295f4SBill Fenner cp++; 1680685295f4SBill Fenner } 1681*ee67461eSJoseph Mingrone if (cp + 1 < ep && GET_U_1(cp)) 1682*ee67461eSJoseph Mingrone ND_PRINT("."); 1683685295f4SBill Fenner } else { 1684685295f4SBill Fenner if (cp == ep) { 1685685295f4SBill Fenner /* FQDN */ 1686*ee67461eSJoseph Mingrone ND_PRINT("."); 1687*ee67461eSJoseph Mingrone } else if (cp + 1 == ep && GET_U_1(cp) == '\0') { 1688685295f4SBill Fenner /* truncated */ 1689685295f4SBill Fenner } else { 1690685295f4SBill Fenner /* invalid */ 1691*ee67461eSJoseph Mingrone ND_PRINT("???"); 1692685295f4SBill Fenner } 1693685295f4SBill Fenner break; 1694685295f4SBill Fenner } 1695685295f4SBill Fenner } 1696*ee67461eSJoseph Mingrone ND_PRINT("\""); 1697685295f4SBill Fenner } 1698685295f4SBill Fenner 16995b0fe478SBruce M Simpson static void 17003c602fabSXin LI icmp6_nodeinfo_print(netdissect_options *ndo, u_int icmp6len, const u_char *bp, const u_char *ep) 1701685295f4SBill Fenner { 17023c602fabSXin LI const struct icmp6_nodeinfo *ni6; 17033c602fabSXin LI const struct icmp6_hdr *dp; 1704685295f4SBill Fenner const u_char *cp; 17055b0fe478SBruce M Simpson size_t siz, i; 1706685295f4SBill Fenner int needcomma; 1707685295f4SBill Fenner 17085b0fe478SBruce M Simpson if (ep < bp) 17095b0fe478SBruce M Simpson return; 17103340d773SGleb Smirnoff dp = (const struct icmp6_hdr *)bp; 17113340d773SGleb Smirnoff ni6 = (const struct icmp6_nodeinfo *)bp; 1712685295f4SBill Fenner siz = ep - bp; 1713685295f4SBill Fenner 1714*ee67461eSJoseph Mingrone switch (GET_U_1(ni6->ni_type)) { 1715685295f4SBill Fenner case ICMP6_NI_QUERY: 1716685295f4SBill Fenner if (siz == sizeof(*dp) + 4) { 1717685295f4SBill Fenner /* KAME who-are-you */ 1718*ee67461eSJoseph Mingrone ND_PRINT(" who-are-you request"); 1719685295f4SBill Fenner break; 1720685295f4SBill Fenner } 1721*ee67461eSJoseph Mingrone ND_PRINT(" node information query"); 1722685295f4SBill Fenner 1723*ee67461eSJoseph Mingrone ND_TCHECK_LEN(dp, sizeof(*ni6)); 17243340d773SGleb Smirnoff ni6 = (const struct icmp6_nodeinfo *)dp; 1725*ee67461eSJoseph Mingrone ND_PRINT(" ("); /*)*/ 1726*ee67461eSJoseph Mingrone switch (GET_BE_U_2(ni6->ni_qtype)) { 1727685295f4SBill Fenner case NI_QTYPE_NOOP: 1728*ee67461eSJoseph Mingrone ND_PRINT("noop"); 1729685295f4SBill Fenner break; 1730685295f4SBill Fenner case NI_QTYPE_SUPTYPES: 1731*ee67461eSJoseph Mingrone ND_PRINT("supported qtypes"); 1732*ee67461eSJoseph Mingrone i = GET_BE_U_2(ni6->ni_flags); 1733685295f4SBill Fenner if (i) 1734*ee67461eSJoseph Mingrone ND_PRINT(" [%s]", (i & 0x01) ? "C" : ""); 1735685295f4SBill Fenner break; 1736685295f4SBill Fenner case NI_QTYPE_FQDN: 1737*ee67461eSJoseph Mingrone ND_PRINT("DNS name"); 1738685295f4SBill Fenner break; 1739685295f4SBill Fenner case NI_QTYPE_NODEADDR: 1740*ee67461eSJoseph Mingrone ND_PRINT("node addresses"); 1741*ee67461eSJoseph Mingrone i = GET_BE_U_2(ni6->ni_flags); 1742685295f4SBill Fenner if (!i) 1743685295f4SBill Fenner break; 1744685295f4SBill Fenner /* NI_NODEADDR_FLAG_TRUNCATE undefined for query */ 1745*ee67461eSJoseph Mingrone ND_PRINT(" [%s%s%s%s%s%s]", 1746685295f4SBill Fenner (i & NI_NODEADDR_FLAG_ANYCAST) ? "a" : "", 1747685295f4SBill Fenner (i & NI_NODEADDR_FLAG_GLOBAL) ? "G" : "", 1748685295f4SBill Fenner (i & NI_NODEADDR_FLAG_SITELOCAL) ? "S" : "", 1749685295f4SBill Fenner (i & NI_NODEADDR_FLAG_LINKLOCAL) ? "L" : "", 1750685295f4SBill Fenner (i & NI_NODEADDR_FLAG_COMPAT) ? "C" : "", 1751*ee67461eSJoseph Mingrone (i & NI_NODEADDR_FLAG_ALL) ? "A" : ""); 1752685295f4SBill Fenner break; 1753685295f4SBill Fenner default: 1754*ee67461eSJoseph Mingrone ND_PRINT("unknown"); 1755685295f4SBill Fenner break; 1756685295f4SBill Fenner } 1757685295f4SBill Fenner 1758*ee67461eSJoseph Mingrone if (GET_BE_U_2(ni6->ni_qtype) == NI_QTYPE_NOOP || 1759*ee67461eSJoseph Mingrone GET_BE_U_2(ni6->ni_qtype) == NI_QTYPE_SUPTYPES) { 1760685295f4SBill Fenner if (siz != sizeof(*ni6)) 17613c602fabSXin LI if (ndo->ndo_vflag) 1762*ee67461eSJoseph Mingrone ND_PRINT(", invalid len"); 1763685295f4SBill Fenner /*(*/ 1764*ee67461eSJoseph Mingrone ND_PRINT(")"); 1765685295f4SBill Fenner break; 1766685295f4SBill Fenner } 1767685295f4SBill Fenner 1768685295f4SBill Fenner /* XXX backward compat, icmp-name-lookup-03 */ 1769685295f4SBill Fenner if (siz == sizeof(*ni6)) { 1770*ee67461eSJoseph Mingrone ND_PRINT(", 03 draft"); 1771685295f4SBill Fenner /*(*/ 1772*ee67461eSJoseph Mingrone ND_PRINT(")"); 1773685295f4SBill Fenner break; 1774685295f4SBill Fenner } 1775685295f4SBill Fenner 1776*ee67461eSJoseph Mingrone cp = (const u_char *)(ni6 + 1); 1777*ee67461eSJoseph Mingrone switch (GET_U_1(ni6->ni_code)) { 1778685295f4SBill Fenner case ICMP6_NI_SUBJ_IPV6: 1779*ee67461eSJoseph Mingrone if (!ND_TTEST_LEN(dp, sizeof(*ni6) + sizeof(nd_ipv6))) 1780685295f4SBill Fenner break; 1781*ee67461eSJoseph Mingrone if (siz != sizeof(*ni6) + sizeof(nd_ipv6)) { 17823c602fabSXin LI if (ndo->ndo_vflag) 1783*ee67461eSJoseph Mingrone ND_PRINT(", invalid subject len"); 1784685295f4SBill Fenner break; 1785685295f4SBill Fenner } 1786*ee67461eSJoseph Mingrone ND_PRINT(", subject=%s", 1787*ee67461eSJoseph Mingrone GET_IP6ADDR_STRING(cp)); 1788685295f4SBill Fenner break; 1789685295f4SBill Fenner case ICMP6_NI_SUBJ_FQDN: 1790*ee67461eSJoseph Mingrone ND_PRINT(", subject=DNS name"); 1791*ee67461eSJoseph Mingrone if (GET_U_1(cp) == ep - cp - 1) { 1792685295f4SBill Fenner /* icmp-name-lookup-03, pascal string */ 17933c602fabSXin LI if (ndo->ndo_vflag) 1794*ee67461eSJoseph Mingrone ND_PRINT(", 03 draft"); 1795685295f4SBill Fenner cp++; 1796*ee67461eSJoseph Mingrone ND_PRINT(", \""); 1797685295f4SBill Fenner while (cp < ep) { 1798*ee67461eSJoseph Mingrone fn_print_char(ndo, GET_U_1(cp)); 1799685295f4SBill Fenner cp++; 1800685295f4SBill Fenner } 1801*ee67461eSJoseph Mingrone ND_PRINT("\""); 1802685295f4SBill Fenner } else 18033c602fabSXin LI dnsname_print(ndo, cp, ep); 1804685295f4SBill Fenner break; 1805685295f4SBill Fenner case ICMP6_NI_SUBJ_IPV4: 1806*ee67461eSJoseph Mingrone if (!ND_TTEST_LEN(dp, sizeof(*ni6) + sizeof(nd_ipv4))) 1807685295f4SBill Fenner break; 1808*ee67461eSJoseph Mingrone if (siz != sizeof(*ni6) + sizeof(nd_ipv4)) { 18093c602fabSXin LI if (ndo->ndo_vflag) 1810*ee67461eSJoseph Mingrone ND_PRINT(", invalid subject len"); 1811685295f4SBill Fenner break; 1812685295f4SBill Fenner } 1813*ee67461eSJoseph Mingrone ND_PRINT(", subject=%s", 1814*ee67461eSJoseph Mingrone GET_IPADDR_STRING(cp)); 1815685295f4SBill Fenner break; 1816685295f4SBill Fenner default: 1817*ee67461eSJoseph Mingrone ND_PRINT(", unknown subject"); 1818685295f4SBill Fenner break; 1819685295f4SBill Fenner } 1820685295f4SBill Fenner 1821685295f4SBill Fenner /*(*/ 1822*ee67461eSJoseph Mingrone ND_PRINT(")"); 1823685295f4SBill Fenner break; 1824685295f4SBill Fenner 1825685295f4SBill Fenner case ICMP6_NI_REPLY: 1826*ee67461eSJoseph Mingrone if (icmp6len > siz) 1827*ee67461eSJoseph Mingrone goto trunc; 1828685295f4SBill Fenner 1829685295f4SBill Fenner needcomma = 0; 1830685295f4SBill Fenner 1831*ee67461eSJoseph Mingrone ND_TCHECK_LEN(dp, sizeof(*ni6)); 18323340d773SGleb Smirnoff ni6 = (const struct icmp6_nodeinfo *)dp; 1833*ee67461eSJoseph Mingrone ND_PRINT(" node information reply"); 1834*ee67461eSJoseph Mingrone ND_PRINT(" ("); /*)*/ 1835*ee67461eSJoseph Mingrone switch (GET_U_1(ni6->ni_code)) { 1836685295f4SBill Fenner case ICMP6_NI_SUCCESS: 18373c602fabSXin LI if (ndo->ndo_vflag) { 1838*ee67461eSJoseph Mingrone ND_PRINT("success"); 1839685295f4SBill Fenner needcomma++; 1840685295f4SBill Fenner } 1841685295f4SBill Fenner break; 1842685295f4SBill Fenner case ICMP6_NI_REFUSED: 1843*ee67461eSJoseph Mingrone ND_PRINT("refused"); 1844685295f4SBill Fenner needcomma++; 1845685295f4SBill Fenner if (siz != sizeof(*ni6)) 18463c602fabSXin LI if (ndo->ndo_vflag) 1847*ee67461eSJoseph Mingrone ND_PRINT(", invalid length"); 1848685295f4SBill Fenner break; 1849685295f4SBill Fenner case ICMP6_NI_UNKNOWN: 1850*ee67461eSJoseph Mingrone ND_PRINT("unknown"); 1851685295f4SBill Fenner needcomma++; 1852685295f4SBill Fenner if (siz != sizeof(*ni6)) 18533c602fabSXin LI if (ndo->ndo_vflag) 1854*ee67461eSJoseph Mingrone ND_PRINT(", invalid length"); 1855685295f4SBill Fenner break; 1856685295f4SBill Fenner } 1857685295f4SBill Fenner 1858*ee67461eSJoseph Mingrone if (GET_U_1(ni6->ni_code) != ICMP6_NI_SUCCESS) { 1859685295f4SBill Fenner /*(*/ 1860*ee67461eSJoseph Mingrone ND_PRINT(")"); 1861685295f4SBill Fenner break; 1862685295f4SBill Fenner } 1863685295f4SBill Fenner 1864*ee67461eSJoseph Mingrone switch (GET_BE_U_2(ni6->ni_qtype)) { 1865685295f4SBill Fenner case NI_QTYPE_NOOP: 1866685295f4SBill Fenner if (needcomma) 1867*ee67461eSJoseph Mingrone ND_PRINT(", "); 1868*ee67461eSJoseph Mingrone ND_PRINT("noop"); 1869685295f4SBill Fenner if (siz != sizeof(*ni6)) 18703c602fabSXin LI if (ndo->ndo_vflag) 1871*ee67461eSJoseph Mingrone ND_PRINT(", invalid length"); 1872685295f4SBill Fenner break; 1873685295f4SBill Fenner case NI_QTYPE_SUPTYPES: 1874685295f4SBill Fenner if (needcomma) 1875*ee67461eSJoseph Mingrone ND_PRINT(", "); 1876*ee67461eSJoseph Mingrone ND_PRINT("supported qtypes"); 1877*ee67461eSJoseph Mingrone i = GET_BE_U_2(ni6->ni_flags); 1878685295f4SBill Fenner if (i) 1879*ee67461eSJoseph Mingrone ND_PRINT(" [%s]", (i & 0x01) ? "C" : ""); 1880685295f4SBill Fenner break; 1881685295f4SBill Fenner case NI_QTYPE_FQDN: 1882685295f4SBill Fenner if (needcomma) 1883*ee67461eSJoseph Mingrone ND_PRINT(", "); 1884*ee67461eSJoseph Mingrone ND_PRINT("DNS name"); 1885685295f4SBill Fenner cp = (const u_char *)(ni6 + 1) + 4; 1886*ee67461eSJoseph Mingrone if (GET_U_1(cp) == ep - cp - 1) { 1887685295f4SBill Fenner /* icmp-name-lookup-03, pascal string */ 18883c602fabSXin LI if (ndo->ndo_vflag) 1889*ee67461eSJoseph Mingrone ND_PRINT(", 03 draft"); 1890685295f4SBill Fenner cp++; 1891*ee67461eSJoseph Mingrone ND_PRINT(", \""); 1892685295f4SBill Fenner while (cp < ep) { 1893*ee67461eSJoseph Mingrone fn_print_char(ndo, GET_U_1(cp)); 1894685295f4SBill Fenner cp++; 1895685295f4SBill Fenner } 1896*ee67461eSJoseph Mingrone ND_PRINT("\""); 1897685295f4SBill Fenner } else 18983c602fabSXin LI dnsname_print(ndo, cp, ep); 1899*ee67461eSJoseph Mingrone if ((GET_BE_U_2(ni6->ni_flags) & 0x01) != 0) 1900*ee67461eSJoseph Mingrone ND_PRINT(" [TTL=%u]", GET_BE_U_4(ni6 + 1)); 1901685295f4SBill Fenner break; 1902685295f4SBill Fenner case NI_QTYPE_NODEADDR: 1903685295f4SBill Fenner if (needcomma) 1904*ee67461eSJoseph Mingrone ND_PRINT(", "); 1905*ee67461eSJoseph Mingrone ND_PRINT("node addresses"); 1906685295f4SBill Fenner i = sizeof(*ni6); 1907685295f4SBill Fenner while (i < siz) { 1908*ee67461eSJoseph Mingrone if (i + sizeof(uint32_t) + sizeof(nd_ipv6) > siz) 1909685295f4SBill Fenner break; 1910*ee67461eSJoseph Mingrone ND_PRINT(" %s(%u)", 1911*ee67461eSJoseph Mingrone GET_IP6ADDR_STRING(bp + i + sizeof(uint32_t)), 1912*ee67461eSJoseph Mingrone GET_BE_U_4(bp + i)); 1913*ee67461eSJoseph Mingrone i += sizeof(uint32_t) + sizeof(nd_ipv6); 1914685295f4SBill Fenner } 1915*ee67461eSJoseph Mingrone i = GET_BE_U_2(ni6->ni_flags); 1916685295f4SBill Fenner if (!i) 1917685295f4SBill Fenner break; 1918*ee67461eSJoseph Mingrone ND_PRINT(" [%s%s%s%s%s%s%s]", 1919685295f4SBill Fenner (i & NI_NODEADDR_FLAG_ANYCAST) ? "a" : "", 1920685295f4SBill Fenner (i & NI_NODEADDR_FLAG_GLOBAL) ? "G" : "", 1921685295f4SBill Fenner (i & NI_NODEADDR_FLAG_SITELOCAL) ? "S" : "", 1922685295f4SBill Fenner (i & NI_NODEADDR_FLAG_LINKLOCAL) ? "L" : "", 1923685295f4SBill Fenner (i & NI_NODEADDR_FLAG_COMPAT) ? "C" : "", 1924685295f4SBill Fenner (i & NI_NODEADDR_FLAG_ALL) ? "A" : "", 1925*ee67461eSJoseph Mingrone (i & NI_NODEADDR_FLAG_TRUNCATE) ? "T" : ""); 1926685295f4SBill Fenner break; 1927685295f4SBill Fenner default: 1928685295f4SBill Fenner if (needcomma) 1929*ee67461eSJoseph Mingrone ND_PRINT(", "); 1930*ee67461eSJoseph Mingrone ND_PRINT("unknown"); 1931685295f4SBill Fenner break; 1932685295f4SBill Fenner } 1933685295f4SBill Fenner 1934685295f4SBill Fenner /*(*/ 1935*ee67461eSJoseph Mingrone ND_PRINT(")"); 1936685295f4SBill Fenner break; 1937685295f4SBill Fenner } 1938685295f4SBill Fenner return; 1939685295f4SBill Fenner 1940685295f4SBill Fenner trunc: 1941*ee67461eSJoseph Mingrone nd_print_trunc(ndo); 1942685295f4SBill Fenner } 1943685295f4SBill Fenner 19445b0fe478SBruce M Simpson static void 19453c602fabSXin LI icmp6_rrenum_print(netdissect_options *ndo, const u_char *bp, const u_char *ep) 1946685295f4SBill Fenner { 19473c602fabSXin LI const struct icmp6_router_renum *rr6; 1948685295f4SBill Fenner const char *cp; 19493340d773SGleb Smirnoff const struct rr_pco_match *match; 19503340d773SGleb Smirnoff const struct rr_pco_use *use; 1951685295f4SBill Fenner char hbuf[NI_MAXHOST]; 1952685295f4SBill Fenner int n; 1953685295f4SBill Fenner 19545b0fe478SBruce M Simpson if (ep < bp) 19555b0fe478SBruce M Simpson return; 19563340d773SGleb Smirnoff rr6 = (const struct icmp6_router_renum *)bp; 1957685295f4SBill Fenner cp = (const char *)(rr6 + 1); 1958685295f4SBill Fenner 1959*ee67461eSJoseph Mingrone ND_TCHECK_4(rr6->rr_reserved); 1960*ee67461eSJoseph Mingrone switch (GET_U_1(rr6->rr_code)) { 1961685295f4SBill Fenner case ICMP6_ROUTER_RENUMBERING_COMMAND: 1962*ee67461eSJoseph Mingrone ND_PRINT(", command"); 1963685295f4SBill Fenner break; 1964685295f4SBill Fenner case ICMP6_ROUTER_RENUMBERING_RESULT: 1965*ee67461eSJoseph Mingrone ND_PRINT(", result"); 1966685295f4SBill Fenner break; 1967685295f4SBill Fenner case ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET: 1968*ee67461eSJoseph Mingrone ND_PRINT(", sequence number reset"); 1969685295f4SBill Fenner break; 1970685295f4SBill Fenner default: 1971*ee67461eSJoseph Mingrone ND_PRINT(", code-#%u", GET_U_1(rr6->rr_code)); 1972685295f4SBill Fenner break; 1973685295f4SBill Fenner } 1974685295f4SBill Fenner 1975*ee67461eSJoseph Mingrone ND_PRINT(", seq=%u", GET_BE_U_4(rr6->rr_seqnum)); 1976685295f4SBill Fenner 19773c602fabSXin LI if (ndo->ndo_vflag) { 1978*ee67461eSJoseph Mingrone uint8_t rr_flags = GET_U_1(rr6->rr_flags); 1979*ee67461eSJoseph Mingrone #define F(x, y) (rr_flags & (x) ? (y) : "") 1980*ee67461eSJoseph Mingrone ND_PRINT("["); /*]*/ 1981*ee67461eSJoseph Mingrone if (rr_flags) { 1982*ee67461eSJoseph Mingrone ND_PRINT("%s%s%s%s%s,", F(ICMP6_RR_FLAGS_TEST, "T"), 1983685295f4SBill Fenner F(ICMP6_RR_FLAGS_REQRESULT, "R"), 1984a90e161bSBill Fenner F(ICMP6_RR_FLAGS_FORCEAPPLY, "A"), 1985685295f4SBill Fenner F(ICMP6_RR_FLAGS_SPECSITE, "S"), 1986*ee67461eSJoseph Mingrone F(ICMP6_RR_FLAGS_PREVDONE, "P")); 1987685295f4SBill Fenner } 1988*ee67461eSJoseph Mingrone ND_PRINT("seg=%u,", GET_U_1(rr6->rr_segnum)); 1989*ee67461eSJoseph Mingrone ND_PRINT("maxdelay=%u", GET_BE_U_2(rr6->rr_maxdelay)); 1990*ee67461eSJoseph Mingrone if (GET_BE_U_4(rr6->rr_reserved)) 1991*ee67461eSJoseph Mingrone ND_PRINT("rsvd=0x%x", GET_BE_U_4(rr6->rr_reserved)); 1992685295f4SBill Fenner /*[*/ 1993*ee67461eSJoseph Mingrone ND_PRINT("]"); 1994685295f4SBill Fenner #undef F 1995685295f4SBill Fenner } 1996685295f4SBill Fenner 1997*ee67461eSJoseph Mingrone if (GET_U_1(rr6->rr_code) == ICMP6_ROUTER_RENUMBERING_COMMAND) { 19983340d773SGleb Smirnoff match = (const struct rr_pco_match *)cp; 1999685295f4SBill Fenner cp = (const char *)(match + 1); 2000685295f4SBill Fenner 2001*ee67461eSJoseph Mingrone ND_TCHECK_16(match->rpm_prefix); 2002685295f4SBill Fenner 20033c602fabSXin LI if (ndo->ndo_vflag > 1) 2004*ee67461eSJoseph Mingrone ND_PRINT("\n\t"); 2005685295f4SBill Fenner else 2006*ee67461eSJoseph Mingrone ND_PRINT(" "); 2007*ee67461eSJoseph Mingrone ND_PRINT("match("); /*)*/ 2008*ee67461eSJoseph Mingrone switch (GET_U_1(match->rpm_code)) { 2009*ee67461eSJoseph Mingrone case RPM_PCO_ADD: ND_PRINT("add"); break; 2010*ee67461eSJoseph Mingrone case RPM_PCO_CHANGE: ND_PRINT("change"); break; 2011*ee67461eSJoseph Mingrone case RPM_PCO_SETGLOBAL: ND_PRINT("setglobal"); break; 2012*ee67461eSJoseph Mingrone default: ND_PRINT("#%u", 2013*ee67461eSJoseph Mingrone GET_U_1(match->rpm_code)); break; 2014685295f4SBill Fenner } 2015685295f4SBill Fenner 20163c602fabSXin LI if (ndo->ndo_vflag) { 2017*ee67461eSJoseph Mingrone ND_PRINT(",ord=%u", GET_U_1(match->rpm_ordinal)); 2018*ee67461eSJoseph Mingrone ND_PRINT(",min=%u", GET_U_1(match->rpm_minlen)); 2019*ee67461eSJoseph Mingrone ND_PRINT(",max=%u", GET_U_1(match->rpm_maxlen)); 2020685295f4SBill Fenner } 2021*ee67461eSJoseph Mingrone if (addrtostr6(match->rpm_prefix, hbuf, sizeof(hbuf))) 2022*ee67461eSJoseph Mingrone ND_PRINT(",%s/%u", hbuf, GET_U_1(match->rpm_matchlen)); 2023685295f4SBill Fenner else 2024*ee67461eSJoseph Mingrone ND_PRINT(",?/%u", GET_U_1(match->rpm_matchlen)); 2025685295f4SBill Fenner /*(*/ 2026*ee67461eSJoseph Mingrone ND_PRINT(")"); 2027685295f4SBill Fenner 2028*ee67461eSJoseph Mingrone n = GET_U_1(match->rpm_len) - 3; 2029685295f4SBill Fenner if (n % 4) 2030685295f4SBill Fenner goto trunc; 2031685295f4SBill Fenner n /= 4; 2032685295f4SBill Fenner while (n-- > 0) { 20333340d773SGleb Smirnoff use = (const struct rr_pco_use *)cp; 2034685295f4SBill Fenner cp = (const char *)(use + 1); 2035685295f4SBill Fenner 2036*ee67461eSJoseph Mingrone ND_TCHECK_16(use->rpu_prefix); 2037685295f4SBill Fenner 20383c602fabSXin LI if (ndo->ndo_vflag > 1) 2039*ee67461eSJoseph Mingrone ND_PRINT("\n\t"); 2040685295f4SBill Fenner else 2041*ee67461eSJoseph Mingrone ND_PRINT(" "); 2042*ee67461eSJoseph Mingrone ND_PRINT("use("); /*)*/ 2043*ee67461eSJoseph Mingrone if (GET_U_1(use->rpu_flags)) { 2044*ee67461eSJoseph Mingrone #define F(x, y) (GET_U_1(use->rpu_flags) & (x) ? (y) : "") 2045*ee67461eSJoseph Mingrone ND_PRINT("%s%s,", 2046685295f4SBill Fenner F(ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME, "V"), 2047*ee67461eSJoseph Mingrone F(ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME, "P")); 2048685295f4SBill Fenner #undef F 2049685295f4SBill Fenner } 20503c602fabSXin LI if (ndo->ndo_vflag) { 2051*ee67461eSJoseph Mingrone ND_PRINT("mask=0x%x,", 2052*ee67461eSJoseph Mingrone GET_U_1(use->rpu_ramask)); 2053*ee67461eSJoseph Mingrone ND_PRINT("raflags=0x%x,", 2054*ee67461eSJoseph Mingrone GET_U_1(use->rpu_raflags)); 2055*ee67461eSJoseph Mingrone if (GET_BE_U_4(use->rpu_vltime) == 0xffffffff) 2056*ee67461eSJoseph Mingrone ND_PRINT("vltime=infty,"); 2057685295f4SBill Fenner else 2058*ee67461eSJoseph Mingrone ND_PRINT("vltime=%u,", 2059*ee67461eSJoseph Mingrone GET_BE_U_4(use->rpu_vltime)); 2060*ee67461eSJoseph Mingrone if (GET_BE_U_4(use->rpu_pltime) == 0xffffffff) 2061*ee67461eSJoseph Mingrone ND_PRINT("pltime=infty,"); 2062685295f4SBill Fenner else 2063*ee67461eSJoseph Mingrone ND_PRINT("pltime=%u,", 2064*ee67461eSJoseph Mingrone GET_BE_U_4(use->rpu_pltime)); 2065685295f4SBill Fenner } 2066*ee67461eSJoseph Mingrone if (addrtostr6(use->rpu_prefix, hbuf, sizeof(hbuf))) 2067*ee67461eSJoseph Mingrone ND_PRINT("%s/%u/%u", hbuf, 2068*ee67461eSJoseph Mingrone GET_U_1(use->rpu_uselen), 2069*ee67461eSJoseph Mingrone GET_U_1(use->rpu_keeplen)); 2070685295f4SBill Fenner else 2071*ee67461eSJoseph Mingrone ND_PRINT("?/%u/%u", GET_U_1(use->rpu_uselen), 2072*ee67461eSJoseph Mingrone GET_U_1(use->rpu_keeplen)); 2073685295f4SBill Fenner /*(*/ 2074*ee67461eSJoseph Mingrone ND_PRINT(")"); 2075685295f4SBill Fenner } 2076685295f4SBill Fenner } 2077b0453382SBill Fenner 2078b0453382SBill Fenner return; 2079685295f4SBill Fenner 2080685295f4SBill Fenner trunc: 2081*ee67461eSJoseph Mingrone nd_print_trunc(ndo); 2082b0453382SBill Fenner } 2083