xref: /dflybsd-src/contrib/tcpdump/print-icmp6.c (revision 59c07fbdf8168fa08c76c515186d561b5a92690c)
141c99275SPeter Avalos /*
241c99275SPeter Avalos  * Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994
341c99275SPeter Avalos  *	The Regents of the University of California.  All rights reserved.
441c99275SPeter Avalos  *
541c99275SPeter Avalos  * Redistribution and use in source and binary forms, with or without
641c99275SPeter Avalos  * modification, are permitted provided that: (1) source code distributions
741c99275SPeter Avalos  * retain the above copyright notice and this paragraph in its entirety, (2)
841c99275SPeter Avalos  * distributions including binary code include the above copyright notice and
941c99275SPeter Avalos  * this paragraph in its entirety in the documentation or other materials
1041c99275SPeter Avalos  * provided with the distribution, and (3) all advertising materials mentioning
1141c99275SPeter Avalos  * features or use of this software display the following acknowledgement:
1241c99275SPeter Avalos  * ``This product includes software developed by the University of California,
1341c99275SPeter Avalos  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1441c99275SPeter Avalos  * the University nor the names of its contributors may be used to endorse
1541c99275SPeter Avalos  * or promote products derived from this software without specific prior
1641c99275SPeter Avalos  * written permission.
1741c99275SPeter Avalos  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1841c99275SPeter Avalos  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1941c99275SPeter Avalos  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2041c99275SPeter Avalos  */
2141c99275SPeter Avalos 
22411677aeSAaron LI /* \summary: IPv6 Internet Control Message Protocol (ICMPv6) printer */
2341c99275SPeter Avalos 
2441c99275SPeter Avalos #ifdef HAVE_CONFIG_H
25*ed775ee7SAntonio Huete Jimenez #include <config.h>
2641c99275SPeter Avalos #endif
2741c99275SPeter Avalos 
28*ed775ee7SAntonio Huete Jimenez #include "netdissect-stdinc.h"
2941c99275SPeter Avalos 
3041c99275SPeter Avalos #include <stdio.h>
3141c99275SPeter Avalos #include <string.h>
3241c99275SPeter Avalos 
33411677aeSAaron LI #include "netdissect.h"
3441c99275SPeter Avalos #include "addrtoname.h"
35411677aeSAaron LI #include "addrtostr.h"
3641c99275SPeter Avalos #include "extract.h"
3741c99275SPeter Avalos 
3841c99275SPeter Avalos #include "ip6.h"
3941c99275SPeter Avalos #include "ipproto.h"
4041c99275SPeter Avalos 
4141c99275SPeter Avalos #include "udp.h"
4241c99275SPeter Avalos #include "ah.h"
4341c99275SPeter Avalos 
44411677aeSAaron LI /*	NetBSD: icmp6.h,v 1.13 2000/08/03 16:30:37 itojun Exp 	*/
45411677aeSAaron LI /*	$KAME: icmp6.h,v 1.22 2000/08/03 15:25:16 jinmei Exp $	*/
46411677aeSAaron LI 
47411677aeSAaron LI /*
48411677aeSAaron LI  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
49411677aeSAaron LI  * All rights reserved.
50411677aeSAaron LI  *
51411677aeSAaron LI  * Redistribution and use in source and binary forms, with or without
52411677aeSAaron LI  * modification, are permitted provided that the following conditions
53411677aeSAaron LI  * are met:
54411677aeSAaron LI  * 1. Redistributions of source code must retain the above copyright
55411677aeSAaron LI  *    notice, this list of conditions and the following disclaimer.
56411677aeSAaron LI  * 2. Redistributions in binary form must reproduce the above copyright
57411677aeSAaron LI  *    notice, this list of conditions and the following disclaimer in the
58411677aeSAaron LI  *    documentation and/or other materials provided with the distribution.
59411677aeSAaron LI  * 3. Neither the name of the project nor the names of its contributors
60411677aeSAaron LI  *    may be used to endorse or promote products derived from this software
61411677aeSAaron LI  *    without specific prior written permission.
62411677aeSAaron LI  *
63411677aeSAaron LI  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
64411677aeSAaron LI  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
65411677aeSAaron LI  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
66411677aeSAaron LI  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
67411677aeSAaron LI  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
68411677aeSAaron LI  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
69411677aeSAaron LI  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
70411677aeSAaron LI  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
71411677aeSAaron LI  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
72411677aeSAaron LI  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
73411677aeSAaron LI  * SUCH DAMAGE.
74411677aeSAaron LI  */
75411677aeSAaron LI 
76411677aeSAaron LI struct icmp6_hdr {
77*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t	icmp6_type;	/* type field */
78*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t	icmp6_code;	/* code field */
79*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	icmp6_cksum;	/* checksum field */
80411677aeSAaron LI 	union {
81*ed775ee7SAntonio Huete Jimenez 		nd_uint32_t	icmp6_un_data32[1]; /* type-specific field */
82*ed775ee7SAntonio Huete Jimenez 		nd_uint16_t	icmp6_un_data16[2]; /* type-specific field */
83*ed775ee7SAntonio Huete Jimenez 		nd_uint8_t	icmp6_un_data8[4];  /* type-specific field */
84*ed775ee7SAntonio Huete Jimenez 		nd_byte		icmp6_un_data[1];   /* type-specific field */
85411677aeSAaron LI 	} icmp6_dataun;
86411677aeSAaron LI };
87411677aeSAaron LI 
88411677aeSAaron LI #define icmp6_data32	icmp6_dataun.icmp6_un_data32
89411677aeSAaron LI #define icmp6_data16	icmp6_dataun.icmp6_un_data16
90411677aeSAaron LI #define icmp6_data8	icmp6_dataun.icmp6_un_data8
91*ed775ee7SAntonio Huete Jimenez #define icmp6_data	icmp6_dataun.icmp6_un_data
92411677aeSAaron LI #define icmp6_pptr	icmp6_data32[0]		/* parameter prob */
93411677aeSAaron LI #define icmp6_mtu	icmp6_data32[0]		/* packet too big */
94411677aeSAaron LI #define icmp6_id	icmp6_data16[0]		/* echo request/reply */
95411677aeSAaron LI #define icmp6_seq	icmp6_data16[1]		/* echo request/reply */
96411677aeSAaron LI #define icmp6_maxdelay	icmp6_data16[0]		/* mcast group membership */
97411677aeSAaron LI 
98411677aeSAaron LI #define ICMP6_DST_UNREACH		1	/* dest unreachable, codes: */
99411677aeSAaron LI #define ICMP6_PACKET_TOO_BIG		2	/* packet too big */
100411677aeSAaron LI #define ICMP6_TIME_EXCEEDED		3	/* time exceeded, code: */
101411677aeSAaron LI #define ICMP6_PARAM_PROB		4	/* ip6 header bad */
102411677aeSAaron LI 
103411677aeSAaron LI #define ICMP6_ECHO_REQUEST		128	/* echo service */
104411677aeSAaron LI #define ICMP6_ECHO_REPLY		129	/* echo reply */
105411677aeSAaron LI #define ICMP6_MEMBERSHIP_QUERY		130	/* group membership query */
106411677aeSAaron LI #define MLD6_LISTENER_QUERY		130 	/* multicast listener query */
107411677aeSAaron LI #define ICMP6_MEMBERSHIP_REPORT		131	/* group membership report */
108411677aeSAaron LI #define MLD6_LISTENER_REPORT		131	/* multicast listener report */
109411677aeSAaron LI #define ICMP6_MEMBERSHIP_REDUCTION	132	/* group membership termination */
110411677aeSAaron LI #define MLD6_LISTENER_DONE		132	/* multicast listener done */
111411677aeSAaron LI 
112411677aeSAaron LI #define ND_ROUTER_SOLICIT		133	/* router solicitation */
113411677aeSAaron LI #define ND_ROUTER_ADVERT		134	/* router advertisement */
114411677aeSAaron LI #define ND_NEIGHBOR_SOLICIT		135	/* neighbor solicitation */
115411677aeSAaron LI #define ND_NEIGHBOR_ADVERT		136	/* neighbor advertisement */
116411677aeSAaron LI #define ND_REDIRECT			137	/* redirect */
117411677aeSAaron LI 
118411677aeSAaron LI #define ICMP6_ROUTER_RENUMBERING	138	/* router renumbering */
119411677aeSAaron LI 
120411677aeSAaron LI #define ICMP6_WRUREQUEST		139	/* who are you request */
121411677aeSAaron LI #define ICMP6_WRUREPLY			140	/* who are you reply */
122411677aeSAaron LI #define ICMP6_FQDN_QUERY		139	/* FQDN query */
123411677aeSAaron LI #define ICMP6_FQDN_REPLY		140	/* FQDN reply */
124*ed775ee7SAntonio Huete Jimenez #define ICMP6_NI_QUERY			139	/* node information request - RFC 4620 */
125*ed775ee7SAntonio Huete Jimenez #define ICMP6_NI_REPLY			140	/* node information reply - RFC 4620 */
126411677aeSAaron LI #define IND_SOLICIT			141	/* inverse neighbor solicitation */
127411677aeSAaron LI #define IND_ADVERT			142	/* inverse neighbor advertisement */
128411677aeSAaron LI 
129411677aeSAaron LI #define ICMP6_V2_MEMBERSHIP_REPORT	143	/* v2 membership report */
130411677aeSAaron LI #define MLDV2_LISTENER_REPORT		143	/* v2 multicast listener report */
131411677aeSAaron LI #define ICMP6_HADISCOV_REQUEST		144
132411677aeSAaron LI #define ICMP6_HADISCOV_REPLY		145
133411677aeSAaron LI #define ICMP6_MOBILEPREFIX_SOLICIT	146
134411677aeSAaron LI #define ICMP6_MOBILEPREFIX_ADVERT	147
135411677aeSAaron LI 
136411677aeSAaron LI #define MLD6_MTRACE_RESP		200	/* mtrace response(to sender) */
137411677aeSAaron LI #define MLD6_MTRACE			201	/* mtrace messages */
138411677aeSAaron LI 
139411677aeSAaron LI #define ICMP6_MAXTYPE			201
140411677aeSAaron LI 
141411677aeSAaron LI #define ICMP6_DST_UNREACH_NOROUTE	0	/* no route to destination */
142411677aeSAaron LI #define ICMP6_DST_UNREACH_ADMIN		1	/* administratively prohibited */
143411677aeSAaron LI #define ICMP6_DST_UNREACH_NOTNEIGHBOR	2	/* not a neighbor(obsolete) */
144411677aeSAaron LI #define ICMP6_DST_UNREACH_BEYONDSCOPE	2	/* beyond scope of source address */
145411677aeSAaron LI #define ICMP6_DST_UNREACH_ADDR		3	/* address unreachable */
146411677aeSAaron LI #define ICMP6_DST_UNREACH_NOPORT	4	/* port unreachable */
147411677aeSAaron LI 
148411677aeSAaron LI #define ICMP6_TIME_EXCEED_TRANSIT 	0	/* ttl==0 in transit */
149411677aeSAaron LI #define ICMP6_TIME_EXCEED_REASSEMBLY	1	/* ttl==0 in reass */
150411677aeSAaron LI 
151411677aeSAaron LI #define ICMP6_PARAMPROB_HEADER 		0	/* erroneous header field */
152411677aeSAaron LI #define ICMP6_PARAMPROB_NEXTHEADER	1	/* unrecognized next header */
153411677aeSAaron LI #define ICMP6_PARAMPROB_OPTION		2	/* unrecognized option */
154*ed775ee7SAntonio Huete Jimenez #define ICMP6_PARAMPROB_FRAGHDRCHAIN	3	/* incomplete header chain */
155411677aeSAaron LI 
156411677aeSAaron LI #define ICMP6_INFOMSG_MASK		0x80	/* all informational messages */
157411677aeSAaron LI 
158411677aeSAaron LI #define ICMP6_NI_SUBJ_IPV6	0	/* Query Subject is an IPv6 address */
159411677aeSAaron LI #define ICMP6_NI_SUBJ_FQDN	1	/* Query Subject is a Domain name */
160411677aeSAaron LI #define ICMP6_NI_SUBJ_IPV4	2	/* Query Subject is an IPv4 address */
161411677aeSAaron LI 
162411677aeSAaron LI #define ICMP6_NI_SUCCESS	0	/* node information successful reply */
163411677aeSAaron LI #define ICMP6_NI_REFUSED	1	/* node information request is refused */
164411677aeSAaron LI #define ICMP6_NI_UNKNOWN	2	/* unknown Qtype */
165411677aeSAaron LI 
166411677aeSAaron LI #define ICMP6_ROUTER_RENUMBERING_COMMAND  0	/* rr command */
167411677aeSAaron LI #define ICMP6_ROUTER_RENUMBERING_RESULT   1	/* rr result */
168411677aeSAaron LI #define ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET   255	/* rr seq num reset */
169411677aeSAaron LI 
170411677aeSAaron LI /* Used in kernel only */
171411677aeSAaron LI #define ND_REDIRECT_ONLINK	0	/* redirect to an on-link node */
172411677aeSAaron LI #define ND_REDIRECT_ROUTER	1	/* redirect to a better router */
173411677aeSAaron LI 
174411677aeSAaron LI /*
175411677aeSAaron LI  * Multicast Listener Discovery
176411677aeSAaron LI  */
177411677aeSAaron LI struct mld6_hdr {
178411677aeSAaron LI 	struct icmp6_hdr	mld6_hdr;
179*ed775ee7SAntonio Huete Jimenez 	nd_ipv6			mld6_addr; /* multicast address */
180411677aeSAaron LI };
181411677aeSAaron LI 
182411677aeSAaron LI #define mld6_type	mld6_hdr.icmp6_type
183411677aeSAaron LI #define mld6_code	mld6_hdr.icmp6_code
184411677aeSAaron LI #define mld6_cksum	mld6_hdr.icmp6_cksum
185411677aeSAaron LI #define mld6_maxdelay	mld6_hdr.icmp6_data16[0]
186411677aeSAaron LI #define mld6_reserved	mld6_hdr.icmp6_data16[1]
187411677aeSAaron LI 
188411677aeSAaron LI #define MLD_MINLEN	24
189411677aeSAaron LI #define MLDV2_MINLEN	28
190411677aeSAaron LI 
191411677aeSAaron LI /*
192411677aeSAaron LI  * Neighbor Discovery
193411677aeSAaron LI  */
194411677aeSAaron LI 
195411677aeSAaron LI struct nd_router_solicit {	/* router solicitation */
196411677aeSAaron LI 	struct icmp6_hdr 	nd_rs_hdr;
197411677aeSAaron LI 	/* could be followed by options */
198411677aeSAaron LI };
199411677aeSAaron LI 
200411677aeSAaron LI #define nd_rs_type	nd_rs_hdr.icmp6_type
201411677aeSAaron LI #define nd_rs_code	nd_rs_hdr.icmp6_code
202411677aeSAaron LI #define nd_rs_cksum	nd_rs_hdr.icmp6_cksum
203411677aeSAaron LI #define nd_rs_reserved	nd_rs_hdr.icmp6_data32[0]
204411677aeSAaron LI 
205411677aeSAaron LI struct nd_router_advert {	/* router advertisement */
206411677aeSAaron LI 	struct icmp6_hdr	nd_ra_hdr;
207*ed775ee7SAntonio Huete Jimenez 	nd_uint32_t		nd_ra_reachable;	/* reachable time */
208*ed775ee7SAntonio Huete Jimenez 	nd_uint32_t		nd_ra_retransmit;	/* retransmit timer */
209411677aeSAaron LI 	/* could be followed by options */
210411677aeSAaron LI };
211411677aeSAaron LI 
212411677aeSAaron LI #define nd_ra_type		nd_ra_hdr.icmp6_type
213411677aeSAaron LI #define nd_ra_code		nd_ra_hdr.icmp6_code
214411677aeSAaron LI #define nd_ra_cksum		nd_ra_hdr.icmp6_cksum
215411677aeSAaron LI #define nd_ra_curhoplimit	nd_ra_hdr.icmp6_data8[0]
216411677aeSAaron LI #define nd_ra_flags_reserved	nd_ra_hdr.icmp6_data8[1]
217411677aeSAaron LI #define ND_RA_FLAG_MANAGED	0x80
218411677aeSAaron LI #define ND_RA_FLAG_OTHER	0x40
219411677aeSAaron LI #define ND_RA_FLAG_HOME_AGENT	0x20
220*ed775ee7SAntonio Huete Jimenez #define ND_RA_FLAG_IPV6ONLY	0x02
221411677aeSAaron LI 
222411677aeSAaron LI /*
223411677aeSAaron LI  * Router preference values based on draft-draves-ipngwg-router-selection-01.
224411677aeSAaron LI  * These are non-standard definitions.
225411677aeSAaron LI  */
226411677aeSAaron LI #define ND_RA_FLAG_RTPREF_MASK	0x18 /* 00011000 */
227411677aeSAaron LI 
228411677aeSAaron LI #define ND_RA_FLAG_RTPREF_HIGH	0x08 /* 00001000 */
229411677aeSAaron LI #define ND_RA_FLAG_RTPREF_MEDIUM	0x00 /* 00000000 */
230411677aeSAaron LI #define ND_RA_FLAG_RTPREF_LOW	0x18 /* 00011000 */
231411677aeSAaron LI #define ND_RA_FLAG_RTPREF_RSV	0x10 /* 00010000 */
232411677aeSAaron LI 
233411677aeSAaron LI #define nd_ra_router_lifetime	nd_ra_hdr.icmp6_data16[1]
234411677aeSAaron LI 
235411677aeSAaron LI struct nd_neighbor_solicit {	/* neighbor solicitation */
236411677aeSAaron LI 	struct icmp6_hdr	nd_ns_hdr;
237*ed775ee7SAntonio Huete Jimenez 	nd_ipv6			nd_ns_target;	/*target address */
238411677aeSAaron LI 	/* could be followed by options */
239411677aeSAaron LI };
240411677aeSAaron LI 
241411677aeSAaron LI #define nd_ns_type		nd_ns_hdr.icmp6_type
242411677aeSAaron LI #define nd_ns_code		nd_ns_hdr.icmp6_code
243411677aeSAaron LI #define nd_ns_cksum		nd_ns_hdr.icmp6_cksum
244411677aeSAaron LI #define nd_ns_reserved		nd_ns_hdr.icmp6_data32[0]
245411677aeSAaron LI 
246411677aeSAaron LI struct nd_neighbor_advert {	/* neighbor advertisement */
247411677aeSAaron LI 	struct icmp6_hdr	nd_na_hdr;
248*ed775ee7SAntonio Huete Jimenez 	nd_ipv6			nd_na_target;	/* target address */
249411677aeSAaron LI 	/* could be followed by options */
250411677aeSAaron LI };
251411677aeSAaron LI 
252411677aeSAaron LI #define nd_na_type		nd_na_hdr.icmp6_type
253411677aeSAaron LI #define nd_na_code		nd_na_hdr.icmp6_code
254411677aeSAaron LI #define nd_na_cksum		nd_na_hdr.icmp6_cksum
255411677aeSAaron LI #define nd_na_flags_reserved	nd_na_hdr.icmp6_data32[0]
256411677aeSAaron LI 
257411677aeSAaron LI #define ND_NA_FLAG_ROUTER		0x80000000
258411677aeSAaron LI #define ND_NA_FLAG_SOLICITED		0x40000000
259411677aeSAaron LI #define ND_NA_FLAG_OVERRIDE		0x20000000
260411677aeSAaron LI 
261411677aeSAaron LI struct nd_redirect {		/* redirect */
262411677aeSAaron LI 	struct icmp6_hdr	nd_rd_hdr;
263*ed775ee7SAntonio Huete Jimenez 	nd_ipv6			nd_rd_target;	/* target address */
264*ed775ee7SAntonio Huete Jimenez 	nd_ipv6			nd_rd_dst;	/* destination address */
265411677aeSAaron LI 	/* could be followed by options */
266411677aeSAaron LI };
267411677aeSAaron LI 
268411677aeSAaron LI #define nd_rd_type		nd_rd_hdr.icmp6_type
269411677aeSAaron LI #define nd_rd_code		nd_rd_hdr.icmp6_code
270411677aeSAaron LI #define nd_rd_cksum		nd_rd_hdr.icmp6_cksum
271411677aeSAaron LI #define nd_rd_reserved		nd_rd_hdr.icmp6_data32[0]
272411677aeSAaron LI 
273411677aeSAaron LI struct nd_opt_hdr {		/* Neighbor discovery option header */
274*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t	nd_opt_type;
275*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t	nd_opt_len;
276411677aeSAaron LI 	/* followed by option specific data*/
277411677aeSAaron LI };
278411677aeSAaron LI 
279411677aeSAaron LI #define ND_OPT_SOURCE_LINKADDR		1
280411677aeSAaron LI #define ND_OPT_TARGET_LINKADDR		2
281411677aeSAaron LI #define ND_OPT_PREFIX_INFORMATION	3
282411677aeSAaron LI #define ND_OPT_REDIRECTED_HEADER	4
283411677aeSAaron LI #define ND_OPT_MTU			5
284411677aeSAaron LI #define ND_OPT_ADVINTERVAL		7
285411677aeSAaron LI #define ND_OPT_HOMEAGENT_INFO		8
286411677aeSAaron LI #define ND_OPT_ROUTE_INFO		24	/* RFC4191 */
287411677aeSAaron LI #define ND_OPT_RDNSS			25
288411677aeSAaron LI #define ND_OPT_DNSSL			31
289411677aeSAaron LI 
290411677aeSAaron LI struct nd_opt_prefix_info {	/* prefix information */
291411677aeSAaron LI 	nd_uint8_t	nd_opt_pi_type;
292411677aeSAaron LI 	nd_uint8_t	nd_opt_pi_len;
293411677aeSAaron LI 	nd_uint8_t	nd_opt_pi_prefix_len;
294411677aeSAaron LI 	nd_uint8_t	nd_opt_pi_flags_reserved;
295411677aeSAaron LI 	nd_uint32_t	nd_opt_pi_valid_time;
296411677aeSAaron LI 	nd_uint32_t	nd_opt_pi_preferred_time;
297411677aeSAaron LI 	nd_uint32_t	nd_opt_pi_reserved2;
298*ed775ee7SAntonio Huete Jimenez 	nd_ipv6		nd_opt_pi_prefix;
299411677aeSAaron LI };
300411677aeSAaron LI 
301411677aeSAaron LI #define ND_OPT_PI_FLAG_ONLINK		0x80
302411677aeSAaron LI #define ND_OPT_PI_FLAG_AUTO		0x40
303411677aeSAaron LI #define ND_OPT_PI_FLAG_ROUTER		0x20	/*2292bis*/
304411677aeSAaron LI 
305411677aeSAaron LI struct nd_opt_rd_hdr {         /* redirected header */
306*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t	nd_opt_rh_type;
307*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t	nd_opt_rh_len;
308*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	nd_opt_rh_reserved1;
309*ed775ee7SAntonio Huete Jimenez 	nd_uint32_t	nd_opt_rh_reserved2;
310411677aeSAaron LI 	/* followed by IP header and data */
311411677aeSAaron LI };
312411677aeSAaron LI 
313411677aeSAaron LI struct nd_opt_mtu {		/* MTU option */
314*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t	nd_opt_mtu_type;
315*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t	nd_opt_mtu_len;
316*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	nd_opt_mtu_reserved;
317*ed775ee7SAntonio Huete Jimenez 	nd_uint32_t	nd_opt_mtu_mtu;
318411677aeSAaron LI };
319411677aeSAaron LI 
320411677aeSAaron LI struct nd_opt_rdnss {		/* RDNSS RFC 6106 5.1 */
321*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t	nd_opt_rdnss_type;
322*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t	nd_opt_rdnss_len;
323*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	nd_opt_rdnss_reserved;
324*ed775ee7SAntonio Huete Jimenez 	nd_uint32_t	nd_opt_rdnss_lifetime;
325*ed775ee7SAntonio Huete Jimenez 	nd_ipv6		nd_opt_rdnss_addr[1];	/* variable-length */
326411677aeSAaron LI };
327411677aeSAaron LI 
328411677aeSAaron LI struct nd_opt_dnssl {		/* DNSSL RFC 6106 5.2 */
329*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t  nd_opt_dnssl_type;
330*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t  nd_opt_dnssl_len;
331*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t nd_opt_dnssl_reserved;
332*ed775ee7SAntonio Huete Jimenez 	nd_uint32_t nd_opt_dnssl_lifetime;
333411677aeSAaron LI 	/* followed by list of DNS search domains, variable-length */
334411677aeSAaron LI };
335411677aeSAaron LI 
336411677aeSAaron LI struct nd_opt_advinterval {	/* Advertisement interval option */
337*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t	nd_opt_adv_type;
338*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t	nd_opt_adv_len;
339*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	nd_opt_adv_reserved;
340*ed775ee7SAntonio Huete Jimenez 	nd_uint32_t	nd_opt_adv_interval;
341411677aeSAaron LI };
342411677aeSAaron LI 
343411677aeSAaron LI struct nd_opt_homeagent_info {	/* Home Agent info */
344*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t	nd_opt_hai_type;
345*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t	nd_opt_hai_len;
346*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	nd_opt_hai_reserved;
347*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	nd_opt_hai_preference;
348*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	nd_opt_hai_lifetime;
349411677aeSAaron LI };
350411677aeSAaron LI 
351411677aeSAaron LI struct nd_opt_route_info {	/* route info */
352*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t	nd_opt_rti_type;
353*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t	nd_opt_rti_len;
354*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t	nd_opt_rti_prefixlen;
355*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t	nd_opt_rti_flags;
356*ed775ee7SAntonio Huete Jimenez 	nd_uint32_t	nd_opt_rti_lifetime;
357411677aeSAaron LI 	/* prefix follows */
358411677aeSAaron LI };
359411677aeSAaron LI 
360411677aeSAaron LI /*
361411677aeSAaron LI  * icmp6 namelookup
362411677aeSAaron LI  */
363411677aeSAaron LI 
364411677aeSAaron LI struct icmp6_namelookup {
365411677aeSAaron LI 	struct icmp6_hdr	icmp6_nl_hdr;
366*ed775ee7SAntonio Huete Jimenez 	nd_byte			icmp6_nl_nonce[8];
367*ed775ee7SAntonio Huete Jimenez 	nd_int32_t		icmp6_nl_ttl;
368411677aeSAaron LI #if 0
369*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t		icmp6_nl_len;
370*ed775ee7SAntonio Huete Jimenez 	nd_byte			icmp6_nl_name[3];
371411677aeSAaron LI #endif
372411677aeSAaron LI 	/* could be followed by options */
373411677aeSAaron LI };
374411677aeSAaron LI 
375411677aeSAaron LI /*
376411677aeSAaron LI  * icmp6 node information
377411677aeSAaron LI  */
378411677aeSAaron LI struct icmp6_nodeinfo {
379411677aeSAaron LI 	struct icmp6_hdr icmp6_ni_hdr;
380*ed775ee7SAntonio Huete Jimenez 	nd_byte icmp6_ni_nonce[8];
381411677aeSAaron LI 	/* could be followed by reply data */
382411677aeSAaron LI };
383411677aeSAaron LI 
384411677aeSAaron LI #define ni_type		icmp6_ni_hdr.icmp6_type
385411677aeSAaron LI #define ni_code		icmp6_ni_hdr.icmp6_code
386411677aeSAaron LI #define ni_cksum	icmp6_ni_hdr.icmp6_cksum
387411677aeSAaron LI #define ni_qtype	icmp6_ni_hdr.icmp6_data16[0]
388411677aeSAaron LI #define ni_flags	icmp6_ni_hdr.icmp6_data16[1]
389411677aeSAaron LI 
390411677aeSAaron LI #define NI_QTYPE_NOOP		0 /* NOOP  */
391*ed775ee7SAntonio Huete Jimenez #define NI_QTYPE_SUPTYPES	1 /* Supported Qtypes (drafts up to 09) */
392411677aeSAaron LI #define NI_QTYPE_FQDN		2 /* FQDN (draft 04) */
393411677aeSAaron LI #define NI_QTYPE_DNSNAME	2 /* DNS Name */
394411677aeSAaron LI #define NI_QTYPE_NODEADDR	3 /* Node Addresses */
395411677aeSAaron LI #define NI_QTYPE_IPV4ADDR	4 /* IPv4 Addresses */
396411677aeSAaron LI 
397411677aeSAaron LI /* network endian */
398411677aeSAaron LI #define NI_SUPTYPE_FLAG_COMPRESS	((uint16_t)htons(0x1))
399411677aeSAaron LI #define NI_FQDN_FLAG_VALIDTTL		((uint16_t)htons(0x1))
400411677aeSAaron LI 
401411677aeSAaron LI /* network endian */
402411677aeSAaron LI #define NI_NODEADDR_FLAG_TRUNCATE	((uint16_t)htons(0x1))
403411677aeSAaron LI #define NI_NODEADDR_FLAG_ALL		((uint16_t)htons(0x2))
404411677aeSAaron LI #define NI_NODEADDR_FLAG_COMPAT		((uint16_t)htons(0x4))
405411677aeSAaron LI #define NI_NODEADDR_FLAG_LINKLOCAL	((uint16_t)htons(0x8))
406411677aeSAaron LI #define NI_NODEADDR_FLAG_SITELOCAL	((uint16_t)htons(0x10))
407411677aeSAaron LI #define NI_NODEADDR_FLAG_GLOBAL		((uint16_t)htons(0x20))
408411677aeSAaron LI #define NI_NODEADDR_FLAG_ANYCAST	((uint16_t)htons(0x40)) /* just experimental. not in spec */
409411677aeSAaron LI 
410411677aeSAaron LI struct ni_reply_fqdn {
411*ed775ee7SAntonio Huete Jimenez 	nd_uint32_t ni_fqdn_ttl;	/* TTL */
412*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t ni_fqdn_namelen; /* length in octets of the FQDN */
413*ed775ee7SAntonio Huete Jimenez 	nd_byte ni_fqdn_name[3]; /* XXX: alignment */
414411677aeSAaron LI };
415411677aeSAaron LI 
416411677aeSAaron LI /*
417411677aeSAaron LI  * Router Renumbering. as router-renum-08.txt
418411677aeSAaron LI  */
419411677aeSAaron LI struct icmp6_router_renum {	/* router renumbering header */
420411677aeSAaron LI 	struct icmp6_hdr	rr_hdr;
421*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t		rr_segnum;
422*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t		rr_flags;
423*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t		rr_maxdelay;
424*ed775ee7SAntonio Huete Jimenez 	nd_uint32_t		rr_reserved;
425411677aeSAaron LI };
426411677aeSAaron LI #define ICMP6_RR_FLAGS_TEST		0x80
427411677aeSAaron LI #define ICMP6_RR_FLAGS_REQRESULT	0x40
428411677aeSAaron LI #define ICMP6_RR_FLAGS_FORCEAPPLY	0x20
429411677aeSAaron LI #define ICMP6_RR_FLAGS_SPECSITE		0x10
430411677aeSAaron LI #define ICMP6_RR_FLAGS_PREVDONE		0x08
431411677aeSAaron LI 
432411677aeSAaron LI #define rr_type		rr_hdr.icmp6_type
433411677aeSAaron LI #define rr_code		rr_hdr.icmp6_code
434411677aeSAaron LI #define rr_cksum	rr_hdr.icmp6_cksum
435411677aeSAaron LI #define rr_seqnum 	rr_hdr.icmp6_data32[0]
436411677aeSAaron LI 
437411677aeSAaron LI struct rr_pco_match {		/* match prefix part */
438*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t		rpm_code;
439*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t		rpm_len;
440*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t		rpm_ordinal;
441*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t		rpm_matchlen;
442*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t		rpm_minlen;
443*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t		rpm_maxlen;
444*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t		rpm_reserved;
445*ed775ee7SAntonio Huete Jimenez 	nd_ipv6			rpm_prefix;
446411677aeSAaron LI };
447411677aeSAaron LI 
448411677aeSAaron LI #define RPM_PCO_ADD		1
449411677aeSAaron LI #define RPM_PCO_CHANGE		2
450411677aeSAaron LI #define RPM_PCO_SETGLOBAL	3
451411677aeSAaron LI #define RPM_PCO_MAX		4
452411677aeSAaron LI 
453411677aeSAaron LI struct rr_pco_use {		/* use prefix part */
454*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t	rpu_uselen;
455*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t	rpu_keeplen;
456*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t	rpu_ramask;
457*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t	rpu_raflags;
458*ed775ee7SAntonio Huete Jimenez 	nd_uint32_t	rpu_vltime;
459*ed775ee7SAntonio Huete Jimenez 	nd_uint32_t	rpu_pltime;
460*ed775ee7SAntonio Huete Jimenez 	nd_uint32_t	rpu_flags;
461*ed775ee7SAntonio Huete Jimenez 	nd_ipv6		rpu_prefix;
462411677aeSAaron LI };
463411677aeSAaron LI #define ICMP6_RR_PCOUSE_RAFLAGS_ONLINK	0x80
464411677aeSAaron LI #define ICMP6_RR_PCOUSE_RAFLAGS_AUTO	0x40
465411677aeSAaron LI 
466411677aeSAaron LI /* network endian */
467411677aeSAaron LI #define ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME     ((uint32_t)htonl(0x80000000))
468411677aeSAaron LI #define ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME     ((uint32_t)htonl(0x40000000))
469411677aeSAaron LI 
470411677aeSAaron LI struct rr_result {		/* router renumbering result message */
471*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	rrr_flags;
472*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t	rrr_ordinal;
473*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t	rrr_matchedlen;
474*ed775ee7SAntonio Huete Jimenez 	nd_uint32_t	rrr_ifid;
475*ed775ee7SAntonio Huete Jimenez 	nd_ipv6		rrr_prefix;
476411677aeSAaron LI };
477411677aeSAaron LI /* network endian */
478411677aeSAaron LI #define ICMP6_RR_RESULT_FLAGS_OOB		((uint16_t)htons(0x0002))
479411677aeSAaron LI #define ICMP6_RR_RESULT_FLAGS_FORBIDDEN		((uint16_t)htons(0x0001))
480411677aeSAaron LI 
48141c99275SPeter Avalos static const char *get_rtpref(u_int);
482411677aeSAaron LI static const char *get_lifetime(uint32_t);
483411677aeSAaron LI static void print_lladdr(netdissect_options *ndo, const u_char *, size_t);
484*ed775ee7SAntonio Huete Jimenez static int icmp6_opt_print(netdissect_options *ndo, const u_char *, int);
485411677aeSAaron LI static void mld6_print(netdissect_options *ndo, const u_char *);
486411677aeSAaron LI static void mldv2_report_print(netdissect_options *ndo, const u_char *, u_int);
487411677aeSAaron LI static void mldv2_query_print(netdissect_options *ndo, const u_char *, u_int);
488411677aeSAaron LI static const struct udphdr *get_upperlayer(netdissect_options *ndo, const u_char *, u_int *);
489411677aeSAaron LI static void dnsname_print(netdissect_options *ndo, const u_char *, const u_char *);
490411677aeSAaron LI static void icmp6_nodeinfo_print(netdissect_options *ndo, u_int, const u_char *, const u_char *);
491411677aeSAaron LI static void icmp6_rrenum_print(netdissect_options *ndo, const u_char *, const u_char *);
49241c99275SPeter Avalos 
49341c99275SPeter Avalos #ifndef abs
49441c99275SPeter Avalos #define abs(a)	((0 < (a)) ? (a) : -(a))
49541c99275SPeter Avalos #endif
49641c99275SPeter Avalos 
497*ed775ee7SAntonio Huete Jimenez /*
498*ed775ee7SAntonio Huete Jimenez  * DIO: Updated to RFC6550, as published in 2012: section 6. (page 30)
499*ed775ee7SAntonio Huete Jimenez  */
500*ed775ee7SAntonio Huete Jimenez 
501*ed775ee7SAntonio Huete Jimenez #define ND_RPL_MESSAGE 155  /* 0x9B */
502*ed775ee7SAntonio Huete Jimenez 
503*ed775ee7SAntonio Huete Jimenez enum ND_RPL_CODE {
504*ed775ee7SAntonio Huete Jimenez     ND_RPL_DAG_IS=0x00,
505*ed775ee7SAntonio Huete Jimenez     ND_RPL_DAG_IO=0x01,
506*ed775ee7SAntonio Huete Jimenez     ND_RPL_DAO   =0x02,
507*ed775ee7SAntonio Huete Jimenez     ND_RPL_DAO_ACK=0x03,
508*ed775ee7SAntonio Huete Jimenez     ND_RPL_SEC_DAG_IS = 0x80,
509*ed775ee7SAntonio Huete Jimenez     ND_RPL_SEC_DAG_IO = 0x81,
510*ed775ee7SAntonio Huete Jimenez     ND_RPL_SEC_DAG    = 0x82,
511*ed775ee7SAntonio Huete Jimenez     ND_RPL_SEC_DAG_ACK= 0x83,
512*ed775ee7SAntonio Huete Jimenez     ND_RPL_SEC_CONSIST= 0x8A
513*ed775ee7SAntonio Huete Jimenez };
514*ed775ee7SAntonio Huete Jimenez 
515*ed775ee7SAntonio Huete Jimenez enum ND_RPL_DIO_FLAGS {
516*ed775ee7SAntonio Huete Jimenez         ND_RPL_DIO_GROUNDED = 0x80,
517*ed775ee7SAntonio Huete Jimenez         ND_RPL_DIO_DATRIG   = 0x40,
518*ed775ee7SAntonio Huete Jimenez         ND_RPL_DIO_DASUPPORT= 0x20,
519*ed775ee7SAntonio Huete Jimenez         ND_RPL_DIO_RES4     = 0x10,
520*ed775ee7SAntonio Huete Jimenez         ND_RPL_DIO_RES3     = 0x08,
521*ed775ee7SAntonio Huete Jimenez         ND_RPL_DIO_PRF_MASK = 0x07  /* 3-bit preference */
522*ed775ee7SAntonio Huete Jimenez };
523*ed775ee7SAntonio Huete Jimenez 
524*ed775ee7SAntonio Huete Jimenez #define DAGID_LEN 16
525*ed775ee7SAntonio Huete Jimenez 
526*ed775ee7SAntonio Huete Jimenez /* section 6 of draft-ietf-roll-rpl-19 */
527*ed775ee7SAntonio Huete Jimenez struct nd_rpl_security {
528*ed775ee7SAntonio Huete Jimenez     nd_uint8_t  rpl_sec_t_reserved;     /* bit 7 is T-bit */
529*ed775ee7SAntonio Huete Jimenez     nd_uint8_t  rpl_sec_algo;
530*ed775ee7SAntonio Huete Jimenez     nd_uint16_t rpl_sec_kim_lvl_flags;  /* bit 15/14, KIM */
531*ed775ee7SAntonio Huete Jimenez                                       /* bit 10-8, LVL, bit 7-0 flags */
532*ed775ee7SAntonio Huete Jimenez     nd_uint32_t rpl_sec_counter;
533*ed775ee7SAntonio Huete Jimenez #if 0
534*ed775ee7SAntonio Huete Jimenez     nd_byte     rpl_sec_ki[0];          /* depends upon kim */
535*ed775ee7SAntonio Huete Jimenez #endif
536*ed775ee7SAntonio Huete Jimenez };
537*ed775ee7SAntonio Huete Jimenez 
538*ed775ee7SAntonio Huete Jimenez /* section 6.2.1, DODAG Information Solication (DIS_IS) */
539*ed775ee7SAntonio Huete Jimenez struct nd_rpl_dis_is {
540*ed775ee7SAntonio Huete Jimenez     nd_uint8_t rpl_dis_flags;
541*ed775ee7SAntonio Huete Jimenez     nd_uint8_t rpl_dis_reserved;
542*ed775ee7SAntonio Huete Jimenez #if 0
543*ed775ee7SAntonio Huete Jimenez     nd_byte    rpl_dis_options[0];
544*ed775ee7SAntonio Huete Jimenez #endif
545*ed775ee7SAntonio Huete Jimenez };
546*ed775ee7SAntonio Huete Jimenez 
547*ed775ee7SAntonio Huete Jimenez /* section 6.3.1, DODAG Information Object (DIO) */
548*ed775ee7SAntonio Huete Jimenez struct nd_rpl_dio {
549*ed775ee7SAntonio Huete Jimenez     nd_uint8_t  rpl_instanceid;
550*ed775ee7SAntonio Huete Jimenez     nd_uint8_t  rpl_version;
551*ed775ee7SAntonio Huete Jimenez     nd_uint16_t rpl_dagrank;
552*ed775ee7SAntonio Huete Jimenez     nd_uint8_t  rpl_mopprf;   /* bit 7=G, 5-3=MOP, 2-0=PRF */
553*ed775ee7SAntonio Huete Jimenez     nd_uint8_t  rpl_dtsn;     /* Dest. Advertisement Trigger Sequence Number */
554*ed775ee7SAntonio Huete Jimenez     nd_uint8_t  rpl_flags;    /* no flags defined yet */
555*ed775ee7SAntonio Huete Jimenez     nd_uint8_t  rpl_resv1;
556*ed775ee7SAntonio Huete Jimenez     nd_byte     rpl_dagid[DAGID_LEN];
557*ed775ee7SAntonio Huete Jimenez };
558*ed775ee7SAntonio Huete Jimenez #define RPL_DIO_GROUND_FLAG 0x80
559*ed775ee7SAntonio Huete Jimenez #define RPL_DIO_MOP_SHIFT   3
560*ed775ee7SAntonio Huete Jimenez #define RPL_DIO_MOP_MASK    (7 << RPL_DIO_MOP_SHIFT)
561*ed775ee7SAntonio Huete Jimenez #define RPL_DIO_PRF_SHIFT   0
562*ed775ee7SAntonio Huete Jimenez #define RPL_DIO_PRF_MASK    (7 << RPL_DIO_PRF_SHIFT)
563*ed775ee7SAntonio Huete Jimenez #define RPL_DIO_GROUNDED(X) ((X)&RPL_DIO_GROUND_FLAG)
564*ed775ee7SAntonio Huete Jimenez #define RPL_DIO_MOP(X)      (enum RPL_DIO_MOP)(((X)&RPL_DIO_MOP_MASK) >> RPL_DIO_MOP_SHIFT)
565*ed775ee7SAntonio Huete Jimenez #define RPL_DIO_PRF(X)      (((X)&RPL_DIO_PRF_MASK) >> RPL_DIO_PRF_SHIFT)
566*ed775ee7SAntonio Huete Jimenez 
567*ed775ee7SAntonio Huete Jimenez enum RPL_DIO_MOP {
568*ed775ee7SAntonio Huete Jimenez     RPL_DIO_NONSTORING= 0x0,
569*ed775ee7SAntonio Huete Jimenez     RPL_DIO_STORING   = 0x1,
570*ed775ee7SAntonio Huete Jimenez     RPL_DIO_NONSTORING_MULTICAST = 0x2,
571*ed775ee7SAntonio Huete Jimenez     RPL_DIO_STORING_MULTICAST    = 0x3
572*ed775ee7SAntonio Huete Jimenez };
573*ed775ee7SAntonio Huete Jimenez 
574*ed775ee7SAntonio Huete Jimenez enum RPL_SUBOPT {
575*ed775ee7SAntonio Huete Jimenez         RPL_OPT_PAD1        = 0,
576*ed775ee7SAntonio Huete Jimenez         RPL_OPT_PADN        = 1,
577*ed775ee7SAntonio Huete Jimenez         RPL_DIO_METRICS     = 2,
578*ed775ee7SAntonio Huete Jimenez         RPL_DIO_ROUTINGINFO = 3,
579*ed775ee7SAntonio Huete Jimenez         RPL_DIO_CONFIG      = 4,
580*ed775ee7SAntonio Huete Jimenez         RPL_DAO_RPLTARGET   = 5,
581*ed775ee7SAntonio Huete Jimenez         RPL_DAO_TRANSITINFO = 6,
582*ed775ee7SAntonio Huete Jimenez         RPL_DIO_DESTPREFIX  = 8,
583*ed775ee7SAntonio Huete Jimenez         RPL_DAO_RPLTARGET_DESC=9
584*ed775ee7SAntonio Huete Jimenez };
585*ed775ee7SAntonio Huete Jimenez 
586*ed775ee7SAntonio Huete Jimenez struct rpl_genoption {
587*ed775ee7SAntonio Huete Jimenez     nd_uint8_t rpl_dio_type;
588*ed775ee7SAntonio Huete Jimenez     nd_uint8_t rpl_dio_len;        /* suboption length, not including type/len */
589*ed775ee7SAntonio Huete Jimenez };
590*ed775ee7SAntonio Huete Jimenez #define RPL_GENOPTION_LEN	2
591*ed775ee7SAntonio Huete Jimenez 
592*ed775ee7SAntonio Huete Jimenez #define RPL_DIO_LIFETIME_INFINITE   0xffffffff
593*ed775ee7SAntonio Huete Jimenez #define RPL_DIO_LIFETIME_DISCONNECT 0
594*ed775ee7SAntonio Huete Jimenez 
595*ed775ee7SAntonio Huete Jimenez struct rpl_dio_destprefix {
596*ed775ee7SAntonio Huete Jimenez     nd_uint8_t rpl_dio_type;
597*ed775ee7SAntonio Huete Jimenez     nd_uint8_t rpl_dio_len;
598*ed775ee7SAntonio Huete Jimenez     nd_uint8_t rpl_dio_prefixlen;        /* in bits */
599*ed775ee7SAntonio Huete Jimenez     nd_uint8_t rpl_dio_prf;              /* flags, including Route Preference */
600*ed775ee7SAntonio Huete Jimenez     nd_uint32_t rpl_dio_prefixlifetime;  /* in seconds */
601*ed775ee7SAntonio Huete Jimenez #if 0
602*ed775ee7SAntonio Huete Jimenez     nd_byte     rpl_dio_prefix[0];       /* variable number of bytes */
603*ed775ee7SAntonio Huete Jimenez #endif
604*ed775ee7SAntonio Huete Jimenez };
605*ed775ee7SAntonio Huete Jimenez 
606*ed775ee7SAntonio Huete Jimenez /* section 6.4.1, DODAG Information Object (DIO) */
607*ed775ee7SAntonio Huete Jimenez struct nd_rpl_dao {
608*ed775ee7SAntonio Huete Jimenez     nd_uint8_t  rpl_instanceid;
609*ed775ee7SAntonio Huete Jimenez     nd_uint8_t  rpl_flags;      /* bit 7=K, 6=D */
610*ed775ee7SAntonio Huete Jimenez     nd_uint8_t  rpl_resv;
611*ed775ee7SAntonio Huete Jimenez     nd_uint8_t  rpl_daoseq;
612*ed775ee7SAntonio Huete Jimenez     nd_byte     rpl_dagid[DAGID_LEN];   /* present when D set. */
613*ed775ee7SAntonio Huete Jimenez };
614*ed775ee7SAntonio Huete Jimenez #define ND_RPL_DAO_MIN_LEN	4	/* length without DAGID */
615*ed775ee7SAntonio Huete Jimenez 
616*ed775ee7SAntonio Huete Jimenez /* indicates if this DAO is to be acK'ed */
617*ed775ee7SAntonio Huete Jimenez #define RPL_DAO_K_SHIFT   7
618*ed775ee7SAntonio Huete Jimenez #define RPL_DAO_K_MASK    (1 << RPL_DAO_K_SHIFT)
619*ed775ee7SAntonio Huete Jimenez #define RPL_DAO_K(X)      (((X)&RPL_DAO_K_MASK) >> RPL_DAO_K_SHIFT)
620*ed775ee7SAntonio Huete Jimenez 
621*ed775ee7SAntonio Huete Jimenez /* indicates if the DAGID is present */
622*ed775ee7SAntonio Huete Jimenez #define RPL_DAO_D_SHIFT   6
623*ed775ee7SAntonio Huete Jimenez #define RPL_DAO_D_MASK    (1 << RPL_DAO_D_SHIFT)
624*ed775ee7SAntonio Huete Jimenez #define RPL_DAO_D(X)      (((X)&RPL_DAO_D_MASK) >> RPL_DAO_D_SHIFT)
625*ed775ee7SAntonio Huete Jimenez 
626*ed775ee7SAntonio Huete Jimenez struct rpl_dao_target {
627*ed775ee7SAntonio Huete Jimenez     nd_uint8_t rpl_dao_type;
628*ed775ee7SAntonio Huete Jimenez     nd_uint8_t rpl_dao_len;
629*ed775ee7SAntonio Huete Jimenez     nd_uint8_t rpl_dao_flags;            /* unused */
630*ed775ee7SAntonio Huete Jimenez     nd_uint8_t rpl_dao_prefixlen;        /* in bits */
631*ed775ee7SAntonio Huete Jimenez #if 0
632*ed775ee7SAntonio Huete Jimenez     nd_byte    rpl_dao_prefix[0];        /* variable number of bytes */
633*ed775ee7SAntonio Huete Jimenez #endif
634*ed775ee7SAntonio Huete Jimenez };
635*ed775ee7SAntonio Huete Jimenez 
636*ed775ee7SAntonio Huete Jimenez /* section 6.5.1, Destination Advertisement Object Acknowledgement (DAO-ACK) */
637*ed775ee7SAntonio Huete Jimenez struct nd_rpl_daoack {
638*ed775ee7SAntonio Huete Jimenez     nd_uint8_t  rpl_instanceid;
639*ed775ee7SAntonio Huete Jimenez     nd_uint8_t  rpl_flags;      /* bit 7=D */
640*ed775ee7SAntonio Huete Jimenez     nd_uint8_t  rpl_daoseq;
641*ed775ee7SAntonio Huete Jimenez     nd_uint8_t  rpl_status;
642*ed775ee7SAntonio Huete Jimenez     nd_byte     rpl_dagid[DAGID_LEN];   /* present when D set. */
643*ed775ee7SAntonio Huete Jimenez };
644*ed775ee7SAntonio Huete Jimenez #define ND_RPL_DAOACK_MIN_LEN	4	/* length without DAGID */
645*ed775ee7SAntonio Huete Jimenez /* indicates if the DAGID is present */
646*ed775ee7SAntonio Huete Jimenez #define RPL_DAOACK_D_SHIFT   7
647*ed775ee7SAntonio Huete Jimenez #define RPL_DAOACK_D_MASK    (1 << RPL_DAOACK_D_SHIFT)
648*ed775ee7SAntonio Huete Jimenez #define RPL_DAOACK_D(X)      (((X)&RPL_DAOACK_D_MASK) >> RPL_DAOACK_D_SHIFT)
64927bfbee1SPeter Avalos 
650411677aeSAaron LI static const struct tok icmp6_type_values[] = {
65141c99275SPeter Avalos     { ICMP6_DST_UNREACH, "destination unreachable"},
65241c99275SPeter Avalos     { ICMP6_PACKET_TOO_BIG, "packet too big"},
65341c99275SPeter Avalos     { ICMP6_TIME_EXCEEDED, "time exceeded in-transit"},
65441c99275SPeter Avalos     { ICMP6_PARAM_PROB, "parameter problem"},
65541c99275SPeter Avalos     { ICMP6_ECHO_REQUEST, "echo request"},
65641c99275SPeter Avalos     { ICMP6_ECHO_REPLY, "echo reply"},
65741c99275SPeter Avalos     { MLD6_LISTENER_QUERY, "multicast listener query"},
65841c99275SPeter Avalos     { MLD6_LISTENER_REPORT, "multicast listener report"},
65941c99275SPeter Avalos     { MLD6_LISTENER_DONE, "multicast listener done"},
66041c99275SPeter Avalos     { ND_ROUTER_SOLICIT, "router solicitation"},
66141c99275SPeter Avalos     { ND_ROUTER_ADVERT, "router advertisement"},
66241c99275SPeter Avalos     { ND_NEIGHBOR_SOLICIT, "neighbor solicitation"},
66341c99275SPeter Avalos     { ND_NEIGHBOR_ADVERT, "neighbor advertisement"},
66441c99275SPeter Avalos     { ND_REDIRECT, "redirect"},
66541c99275SPeter Avalos     { ICMP6_ROUTER_RENUMBERING, "router renumbering"},
66641c99275SPeter Avalos     { IND_SOLICIT, "inverse neighbor solicitation"},
66741c99275SPeter Avalos     { IND_ADVERT, "inverse neighbor advertisement"},
66841c99275SPeter Avalos     { MLDV2_LISTENER_REPORT, "multicast listener report v2"},
66941c99275SPeter Avalos     { ICMP6_HADISCOV_REQUEST, "ha discovery request"},
67041c99275SPeter Avalos     { ICMP6_HADISCOV_REPLY, "ha discovery reply"},
67141c99275SPeter Avalos     { ICMP6_MOBILEPREFIX_SOLICIT, "mobile router solicitation"},
67241c99275SPeter Avalos     { ICMP6_MOBILEPREFIX_ADVERT, "mobile router advertisement"},
67341c99275SPeter Avalos     { ICMP6_WRUREQUEST, "who-are-you request"},
67441c99275SPeter Avalos     { ICMP6_WRUREPLY, "who-are-you reply"},
67541c99275SPeter Avalos     { ICMP6_NI_QUERY, "node information query"},
67641c99275SPeter Avalos     { ICMP6_NI_REPLY, "node information reply"},
67741c99275SPeter Avalos     { MLD6_MTRACE, "mtrace message"},
67841c99275SPeter Avalos     { MLD6_MTRACE_RESP, "mtrace response"},
67927bfbee1SPeter Avalos     { ND_RPL_MESSAGE,   "RPL"},
68041c99275SPeter Avalos     { 0,	NULL }
68141c99275SPeter Avalos };
68241c99275SPeter Avalos 
683411677aeSAaron LI static const struct tok icmp6_dst_unreach_code_values[] = {
68441c99275SPeter Avalos     { ICMP6_DST_UNREACH_NOROUTE, "unreachable route" },
68541c99275SPeter Avalos     { ICMP6_DST_UNREACH_ADMIN, " unreachable prohibited"},
68641c99275SPeter Avalos     { ICMP6_DST_UNREACH_BEYONDSCOPE, "beyond scope"},
68741c99275SPeter Avalos     { ICMP6_DST_UNREACH_ADDR, "unreachable address"},
68841c99275SPeter Avalos     { ICMP6_DST_UNREACH_NOPORT, "unreachable port"},
68941c99275SPeter Avalos     { 0,	NULL }
69041c99275SPeter Avalos };
69141c99275SPeter Avalos 
692411677aeSAaron LI static const struct tok icmp6_opt_pi_flag_values[] = {
69341c99275SPeter Avalos     { ND_OPT_PI_FLAG_ONLINK, "onlink" },
69441c99275SPeter Avalos     { ND_OPT_PI_FLAG_AUTO, "auto" },
69541c99275SPeter Avalos     { ND_OPT_PI_FLAG_ROUTER, "router" },
69641c99275SPeter Avalos     { 0,	NULL }
69741c99275SPeter Avalos };
69841c99275SPeter Avalos 
699411677aeSAaron LI static const struct tok icmp6_opt_ra_flag_values[] = {
70041c99275SPeter Avalos     { ND_RA_FLAG_MANAGED, "managed" },
70141c99275SPeter Avalos     { ND_RA_FLAG_OTHER, "other stateful"},
70241c99275SPeter Avalos     { ND_RA_FLAG_HOME_AGENT, "home agent"},
703*ed775ee7SAntonio Huete Jimenez     { ND_RA_FLAG_IPV6ONLY, "ipv6 only"},
70441c99275SPeter Avalos     { 0,	NULL }
70541c99275SPeter Avalos };
70641c99275SPeter Avalos 
707411677aeSAaron LI static const struct tok icmp6_nd_na_flag_values[] = {
70841c99275SPeter Avalos     { ND_NA_FLAG_ROUTER, "router" },
70941c99275SPeter Avalos     { ND_NA_FLAG_SOLICITED, "solicited" },
71041c99275SPeter Avalos     { ND_NA_FLAG_OVERRIDE, "override" },
71141c99275SPeter Avalos     { 0,	NULL }
71241c99275SPeter Avalos };
71341c99275SPeter Avalos 
71441c99275SPeter Avalos 
715411677aeSAaron LI static const struct tok icmp6_opt_values[] = {
71641c99275SPeter Avalos    { ND_OPT_SOURCE_LINKADDR, "source link-address"},
71741c99275SPeter Avalos    { ND_OPT_TARGET_LINKADDR, "destination link-address"},
71841c99275SPeter Avalos    { ND_OPT_PREFIX_INFORMATION, "prefix info"},
71941c99275SPeter Avalos    { ND_OPT_REDIRECTED_HEADER, "redirected header"},
72041c99275SPeter Avalos    { ND_OPT_MTU, "mtu"},
72127bfbee1SPeter Avalos    { ND_OPT_RDNSS, "rdnss"},
722411677aeSAaron LI    { ND_OPT_DNSSL, "dnssl"},
72341c99275SPeter Avalos    { ND_OPT_ADVINTERVAL, "advertisement interval"},
72441c99275SPeter Avalos    { ND_OPT_HOMEAGENT_INFO, "homeagent information"},
72541c99275SPeter Avalos    { ND_OPT_ROUTE_INFO, "route info"},
72641c99275SPeter Avalos    { 0,	NULL }
72741c99275SPeter Avalos };
72841c99275SPeter Avalos 
72941c99275SPeter Avalos /* mldv2 report types */
730411677aeSAaron LI static const struct tok mldv2report2str[] = {
73141c99275SPeter Avalos 	{ 1,	"is_in" },
73241c99275SPeter Avalos 	{ 2,	"is_ex" },
73341c99275SPeter Avalos 	{ 3,	"to_in" },
73441c99275SPeter Avalos 	{ 4,	"to_ex" },
73541c99275SPeter Avalos 	{ 5,	"allow" },
73641c99275SPeter Avalos 	{ 6,	"block" },
73741c99275SPeter Avalos 	{ 0,	NULL }
73841c99275SPeter Avalos };
73941c99275SPeter Avalos 
74041c99275SPeter Avalos static const char *
get_rtpref(u_int v)74141c99275SPeter Avalos get_rtpref(u_int v)
74241c99275SPeter Avalos {
74341c99275SPeter Avalos 	static const char *rtpref_str[] = {
74441c99275SPeter Avalos 		"medium",		/* 00 */
74541c99275SPeter Avalos 		"high",			/* 01 */
74641c99275SPeter Avalos 		"rsv",			/* 10 */
74741c99275SPeter Avalos 		"low"			/* 11 */
74841c99275SPeter Avalos 	};
74941c99275SPeter Avalos 
75041c99275SPeter Avalos 	return rtpref_str[((v & ND_RA_FLAG_RTPREF_MASK) >> 3) & 0xff];
75141c99275SPeter Avalos }
75241c99275SPeter Avalos 
75341c99275SPeter Avalos static const char *
get_lifetime(uint32_t v)754411677aeSAaron LI get_lifetime(uint32_t v)
75541c99275SPeter Avalos {
75641c99275SPeter Avalos 	static char buf[20];
75741c99275SPeter Avalos 
758411677aeSAaron LI 	if (v == (uint32_t)~0UL)
75941c99275SPeter Avalos 		return "infinity";
76041c99275SPeter Avalos 	else {
761411677aeSAaron LI 		snprintf(buf, sizeof(buf), "%us", v);
76241c99275SPeter Avalos 		return buf;
76341c99275SPeter Avalos 	}
76441c99275SPeter Avalos }
76541c99275SPeter Avalos 
76641c99275SPeter Avalos static void
print_lladdr(netdissect_options * ndo,const uint8_t * p,size_t l)767411677aeSAaron LI print_lladdr(netdissect_options *ndo, const uint8_t *p, size_t l)
76841c99275SPeter Avalos {
769411677aeSAaron LI 	const uint8_t *ep, *q;
77041c99275SPeter Avalos 
77141c99275SPeter Avalos 	q = p;
77241c99275SPeter Avalos 	ep = p + l;
77341c99275SPeter Avalos 	while (l > 0 && q < ep) {
77441c99275SPeter Avalos 		if (q > p)
775*ed775ee7SAntonio Huete Jimenez                         ND_PRINT(":");
776*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%02x", GET_U_1(q));
777*ed775ee7SAntonio Huete Jimenez 		q++;
77841c99275SPeter Avalos 		l--;
77941c99275SPeter Avalos 	}
78041c99275SPeter Avalos }
78141c99275SPeter Avalos 
icmp6_cksum(netdissect_options * ndo,const struct ip6_hdr * ip6,const struct icmp6_hdr * icp,u_int len)782*ed775ee7SAntonio Huete Jimenez static uint16_t icmp6_cksum(netdissect_options *ndo, const struct ip6_hdr *ip6,
783411677aeSAaron LI 	const struct icmp6_hdr *icp, u_int len)
78441c99275SPeter Avalos {
785411677aeSAaron LI 	return nextproto6_cksum(ndo, ip6, (const uint8_t *)(const void *)icp, len, len,
786411677aeSAaron LI 				IPPROTO_ICMPV6);
78741c99275SPeter Avalos }
78841c99275SPeter Avalos 
789411677aeSAaron LI static const struct tok rpl_mop_values[] = {
790411677aeSAaron LI         { RPL_DIO_NONSTORING,         "nonstoring"},
791411677aeSAaron LI         { RPL_DIO_STORING,            "storing"},
792411677aeSAaron LI         { RPL_DIO_NONSTORING_MULTICAST, "nonstoring-multicast"},
793411677aeSAaron LI         { RPL_DIO_STORING_MULTICAST,  "storing-multicast"},
794411677aeSAaron LI         { 0, NULL},
79527bfbee1SPeter Avalos };
79627bfbee1SPeter Avalos 
797411677aeSAaron LI static const struct tok rpl_subopt_values[] = {
798*ed775ee7SAntonio Huete Jimenez         { RPL_OPT_PAD1, "pad1"},
799411677aeSAaron LI         { RPL_OPT_PADN, "padN"},
800411677aeSAaron LI         { RPL_DIO_METRICS, "metrics"},
801411677aeSAaron LI         { RPL_DIO_ROUTINGINFO, "routinginfo"},
802411677aeSAaron LI         { RPL_DIO_CONFIG,    "config"},
803411677aeSAaron LI         { RPL_DAO_RPLTARGET, "rpltarget"},
804411677aeSAaron LI         { RPL_DAO_TRANSITINFO, "transitinfo"},
805411677aeSAaron LI         { RPL_DIO_DESTPREFIX, "destprefix"},
806411677aeSAaron LI         { RPL_DAO_RPLTARGET_DESC, "rpltargetdesc"},
807411677aeSAaron LI         { 0, NULL},
80827bfbee1SPeter Avalos };
80927bfbee1SPeter Avalos 
810411677aeSAaron LI static void
rpl_printopts(netdissect_options * ndo,const uint8_t * opts,u_int length)811*ed775ee7SAntonio Huete Jimenez rpl_printopts(netdissect_options *ndo, const uint8_t *opts, u_int length)
812411677aeSAaron LI {
813*ed775ee7SAntonio Huete Jimenez 	const struct rpl_genoption *opt;
814*ed775ee7SAntonio Huete Jimenez 	uint8_t dio_type;
815*ed775ee7SAntonio Huete Jimenez 	u_int optlen;
816411677aeSAaron LI 
817*ed775ee7SAntonio Huete Jimenez 	while (length != 0) {
818*ed775ee7SAntonio Huete Jimenez 		opt = (const struct rpl_genoption *)opts;
819*ed775ee7SAntonio Huete Jimenez 		dio_type = GET_U_1(opt->rpl_dio_type);
820*ed775ee7SAntonio Huete Jimenez 		if (dio_type == RPL_OPT_PAD1) {
821411677aeSAaron LI                         optlen = 1;
822*ed775ee7SAntonio Huete Jimenez                         ND_PRINT(" opt:pad1");
823411677aeSAaron LI                 } else {
824*ed775ee7SAntonio Huete Jimenez                 	if (length < RPL_GENOPTION_LEN)
825*ed775ee7SAntonio Huete Jimenez                 		goto trunc;
826*ed775ee7SAntonio Huete Jimenez 	                optlen = GET_U_1(opt->rpl_dio_len)+RPL_GENOPTION_LEN;
827*ed775ee7SAntonio Huete Jimenez                         ND_PRINT(" opt:%s len:%u ",
828*ed775ee7SAntonio Huete Jimenez                                   tok2str(rpl_subopt_values, "subopt:%u", dio_type),
829*ed775ee7SAntonio Huete Jimenez                                   optlen);
830*ed775ee7SAntonio Huete Jimenez                         ND_TCHECK_LEN(opt, optlen);
831*ed775ee7SAntonio Huete Jimenez                         if (length < optlen)
832*ed775ee7SAntonio Huete Jimenez                         	goto trunc;
833411677aeSAaron LI                         if (ndo->ndo_vflag > 2) {
834411677aeSAaron LI                                 hex_print(ndo,
835411677aeSAaron LI                                           " ",
836*ed775ee7SAntonio Huete Jimenez                                           opts + RPL_GENOPTION_LEN,  /* content of DIO option */
837*ed775ee7SAntonio Huete Jimenez                                           optlen - RPL_GENOPTION_LEN);
838411677aeSAaron LI                         }
839411677aeSAaron LI                 }
840*ed775ee7SAntonio Huete Jimenez                 opts += optlen;
841411677aeSAaron LI                 length -= optlen;
842411677aeSAaron LI         }
843411677aeSAaron LI         return;
844411677aeSAaron LI trunc:
845*ed775ee7SAntonio Huete Jimenez 	nd_print_trunc(ndo);
846411677aeSAaron LI }
847411677aeSAaron LI 
848411677aeSAaron LI static void
rpl_dio_print(netdissect_options * ndo,const u_char * bp,u_int length)849411677aeSAaron LI rpl_dio_print(netdissect_options *ndo,
850411677aeSAaron LI               const u_char *bp, u_int length)
851411677aeSAaron LI {
852411677aeSAaron LI         const struct nd_rpl_dio *dio = (const struct nd_rpl_dio *)bp;
853411677aeSAaron LI         const char *dagid_str;
854411677aeSAaron LI 
855*ed775ee7SAntonio Huete Jimenez         ND_TCHECK_SIZE(dio);
856411677aeSAaron LI         dagid_str = ip6addr_string (ndo, dio->rpl_dagid);
857411677aeSAaron LI 
858*ed775ee7SAntonio Huete Jimenez         ND_PRINT(" [dagid:%s,seq:%u,instance:%u,rank:%u,%smop:%s,prf:%u]",
859411677aeSAaron LI                   dagid_str,
860*ed775ee7SAntonio Huete Jimenez                   GET_U_1(dio->rpl_dtsn),
861*ed775ee7SAntonio Huete Jimenez                   GET_U_1(dio->rpl_instanceid),
862*ed775ee7SAntonio Huete Jimenez                   GET_BE_U_2(dio->rpl_dagrank),
863*ed775ee7SAntonio Huete Jimenez                   RPL_DIO_GROUNDED(GET_U_1(dio->rpl_mopprf)) ? "grounded,":"",
864*ed775ee7SAntonio Huete Jimenez                   tok2str(rpl_mop_values, "mop%u", RPL_DIO_MOP(GET_U_1(dio->rpl_mopprf))),
865*ed775ee7SAntonio Huete Jimenez                   RPL_DIO_PRF(GET_U_1(dio->rpl_mopprf)));
866411677aeSAaron LI 
867411677aeSAaron LI         if(ndo->ndo_vflag > 1) {
868*ed775ee7SAntonio Huete Jimenez                 rpl_printopts(ndo, bp + sizeof(struct nd_rpl_dio),
869*ed775ee7SAntonio Huete Jimenez                               length - sizeof(struct nd_rpl_dio));
870411677aeSAaron LI         }
871411677aeSAaron LI 	return;
872411677aeSAaron LI trunc:
873*ed775ee7SAntonio Huete Jimenez 	nd_print_trunc(ndo);
874411677aeSAaron LI }
875411677aeSAaron LI 
876411677aeSAaron LI static void
rpl_dao_print(netdissect_options * ndo,const u_char * bp,u_int length)877411677aeSAaron LI rpl_dao_print(netdissect_options *ndo,
878411677aeSAaron LI               const u_char *bp, u_int length)
879411677aeSAaron LI {
880411677aeSAaron LI         const struct nd_rpl_dao *dao = (const struct nd_rpl_dao *)bp;
881411677aeSAaron LI         const char *dagid_str = "<elided>";
882*ed775ee7SAntonio Huete Jimenez         uint8_t rpl_flags;
883411677aeSAaron LI 
884*ed775ee7SAntonio Huete Jimenez         ND_TCHECK_SIZE(dao);
885411677aeSAaron LI         if (length < ND_RPL_DAO_MIN_LEN)
886411677aeSAaron LI 		goto tooshort;
887411677aeSAaron LI 
888411677aeSAaron LI         bp += ND_RPL_DAO_MIN_LEN;
889411677aeSAaron LI         length -= ND_RPL_DAO_MIN_LEN;
890*ed775ee7SAntonio Huete Jimenez         rpl_flags = GET_U_1(dao->rpl_flags);
891*ed775ee7SAntonio Huete Jimenez         if(RPL_DAO_D(rpl_flags)) {
892*ed775ee7SAntonio Huete Jimenez                 ND_TCHECK_LEN(dao->rpl_dagid, DAGID_LEN);
893411677aeSAaron LI                 if (length < DAGID_LEN)
894411677aeSAaron LI                 	goto tooshort;
895411677aeSAaron LI                 dagid_str = ip6addr_string (ndo, dao->rpl_dagid);
896411677aeSAaron LI                 bp += DAGID_LEN;
897411677aeSAaron LI                 length -= DAGID_LEN;
898411677aeSAaron LI         }
899411677aeSAaron LI 
900*ed775ee7SAntonio Huete Jimenez         ND_PRINT(" [dagid:%s,seq:%u,instance:%u%s%s,%02x]",
901411677aeSAaron LI                   dagid_str,
902*ed775ee7SAntonio Huete Jimenez                   GET_U_1(dao->rpl_daoseq),
903*ed775ee7SAntonio Huete Jimenez                   GET_U_1(dao->rpl_instanceid),
904*ed775ee7SAntonio Huete Jimenez                   RPL_DAO_K(rpl_flags) ? ",acK":"",
905*ed775ee7SAntonio Huete Jimenez                   RPL_DAO_D(rpl_flags) ? ",Dagid":"",
906*ed775ee7SAntonio Huete Jimenez                   rpl_flags);
907411677aeSAaron LI 
908411677aeSAaron LI         if(ndo->ndo_vflag > 1) {
909*ed775ee7SAntonio Huete Jimenez                 rpl_printopts(ndo, bp, length);
910411677aeSAaron LI         }
911411677aeSAaron LI 	return;
912411677aeSAaron LI 
913411677aeSAaron LI trunc:
914*ed775ee7SAntonio Huete Jimenez 	nd_print_trunc(ndo);
915411677aeSAaron LI 	return;
916411677aeSAaron LI 
917411677aeSAaron LI tooshort:
918*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(" [|length too short]");
919411677aeSAaron LI }
920411677aeSAaron LI 
921411677aeSAaron LI static void
rpl_daoack_print(netdissect_options * ndo,const u_char * bp,u_int length)922411677aeSAaron LI rpl_daoack_print(netdissect_options *ndo,
923411677aeSAaron LI                  const u_char *bp, u_int length)
924411677aeSAaron LI {
925411677aeSAaron LI         const struct nd_rpl_daoack *daoack = (const struct nd_rpl_daoack *)bp;
926411677aeSAaron LI         const char *dagid_str = "<elided>";
927411677aeSAaron LI 
928*ed775ee7SAntonio Huete Jimenez         ND_TCHECK_LEN(daoack, ND_RPL_DAOACK_MIN_LEN);
929411677aeSAaron LI         if (length < ND_RPL_DAOACK_MIN_LEN)
930411677aeSAaron LI 		goto tooshort;
931411677aeSAaron LI 
932411677aeSAaron LI         bp += ND_RPL_DAOACK_MIN_LEN;
933411677aeSAaron LI         length -= ND_RPL_DAOACK_MIN_LEN;
934*ed775ee7SAntonio Huete Jimenez         if(RPL_DAOACK_D(GET_U_1(daoack->rpl_flags))) {
935*ed775ee7SAntonio Huete Jimenez                 ND_TCHECK_LEN(daoack->rpl_dagid, DAGID_LEN);
936411677aeSAaron LI                 if (length < DAGID_LEN)
937411677aeSAaron LI                 	goto tooshort;
938411677aeSAaron LI                 dagid_str = ip6addr_string (ndo, daoack->rpl_dagid);
939411677aeSAaron LI                 bp += DAGID_LEN;
940411677aeSAaron LI                 length -= DAGID_LEN;
941411677aeSAaron LI         }
942411677aeSAaron LI 
943*ed775ee7SAntonio Huete Jimenez         ND_PRINT(" [dagid:%s,seq:%u,instance:%u,status:%u]",
944411677aeSAaron LI                   dagid_str,
945*ed775ee7SAntonio Huete Jimenez                   GET_U_1(daoack->rpl_daoseq),
946*ed775ee7SAntonio Huete Jimenez                   GET_U_1(daoack->rpl_instanceid),
947*ed775ee7SAntonio Huete Jimenez                   GET_U_1(daoack->rpl_status));
948411677aeSAaron LI 
949411677aeSAaron LI         /* no officially defined options for DAOACK, but print any we find */
950411677aeSAaron LI         if(ndo->ndo_vflag > 1) {
951*ed775ee7SAntonio Huete Jimenez                 rpl_printopts(ndo, bp, length);
952411677aeSAaron LI         }
953411677aeSAaron LI 	return;
954411677aeSAaron LI 
955411677aeSAaron LI trunc:
956*ed775ee7SAntonio Huete Jimenez 	nd_print_trunc(ndo);
957411677aeSAaron LI 	return;
958411677aeSAaron LI 
959411677aeSAaron LI tooshort:
960*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(" [|dao-length too short]");
961411677aeSAaron LI }
96227bfbee1SPeter Avalos 
96327bfbee1SPeter Avalos static void
rpl_print(netdissect_options * ndo,uint8_t icmp6_code,const u_char * bp,u_int length)96427bfbee1SPeter Avalos rpl_print(netdissect_options *ndo,
965*ed775ee7SAntonio Huete Jimenez           uint8_t icmp6_code,
966411677aeSAaron LI           const u_char *bp, u_int length)
96727bfbee1SPeter Avalos {
968*ed775ee7SAntonio Huete Jimenez         int secured = icmp6_code & 0x80;
969*ed775ee7SAntonio Huete Jimenez         int basecode= icmp6_code & 0x7f;
97027bfbee1SPeter Avalos 
97127bfbee1SPeter Avalos         if(secured) {
972*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(", (SEC) [worktodo]");
973411677aeSAaron LI                 /* XXX
974411677aeSAaron LI                  * the next header pointer needs to move forward to
975411677aeSAaron LI                  * skip the secure part.
976411677aeSAaron LI                  */
977411677aeSAaron LI                 return;
97827bfbee1SPeter Avalos         } else {
979*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(", (CLR)");
98027bfbee1SPeter Avalos         }
98127bfbee1SPeter Avalos 
98227bfbee1SPeter Avalos         switch(basecode) {
983411677aeSAaron LI         case ND_RPL_DAG_IS:
984*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("DODAG Information Solicitation");
98527bfbee1SPeter Avalos                 if(ndo->ndo_vflag) {
98627bfbee1SPeter Avalos                 }
98727bfbee1SPeter Avalos                 break;
988411677aeSAaron LI         case ND_RPL_DAG_IO:
989*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("DODAG Information Object");
99027bfbee1SPeter Avalos                 if(ndo->ndo_vflag) {
991411677aeSAaron LI                         rpl_dio_print(ndo, bp, length);
99227bfbee1SPeter Avalos                 }
99327bfbee1SPeter Avalos                 break;
99427bfbee1SPeter Avalos         case ND_RPL_DAO:
995*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("Destination Advertisement Object");
99627bfbee1SPeter Avalos                 if(ndo->ndo_vflag) {
997411677aeSAaron LI                         rpl_dao_print(ndo, bp, length);
99827bfbee1SPeter Avalos                 }
99927bfbee1SPeter Avalos                 break;
100027bfbee1SPeter Avalos         case ND_RPL_DAO_ACK:
1001*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("Destination Advertisement Object Ack");
100227bfbee1SPeter Avalos                 if(ndo->ndo_vflag) {
1003411677aeSAaron LI                         rpl_daoack_print(ndo, bp, length);
100427bfbee1SPeter Avalos                 }
100527bfbee1SPeter Avalos                 break;
100627bfbee1SPeter Avalos         default:
1007*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("RPL message, unknown code %u",icmp6_code);
100827bfbee1SPeter Avalos                 break;
100927bfbee1SPeter Avalos         }
101027bfbee1SPeter Avalos 	return;
1011411677aeSAaron LI 
1012411677aeSAaron LI #if 0
101327bfbee1SPeter Avalos trunc:
1014*ed775ee7SAntonio Huete Jimenez 	nd_print_trunc(ndo);
101527bfbee1SPeter Avalos 	return;
1016411677aeSAaron LI #endif
101727bfbee1SPeter Avalos 
101827bfbee1SPeter Avalos }
101927bfbee1SPeter Avalos 
102027bfbee1SPeter Avalos 
102141c99275SPeter Avalos void
icmp6_print(netdissect_options * ndo,const u_char * bp,u_int length,const u_char * bp2,int fragmented)102227bfbee1SPeter Avalos icmp6_print(netdissect_options *ndo,
102327bfbee1SPeter Avalos             const u_char *bp, u_int length, const u_char *bp2, int fragmented)
102441c99275SPeter Avalos {
102541c99275SPeter Avalos 	const struct icmp6_hdr *dp;
1026*ed775ee7SAntonio Huete Jimenez 	uint8_t icmp6_type, icmp6_code;
102741c99275SPeter Avalos 	const struct ip6_hdr *ip;
102841c99275SPeter Avalos 	const struct ip6_hdr *oip;
102941c99275SPeter Avalos 	const struct udphdr *ouh;
1030*ed775ee7SAntonio Huete Jimenez 	uint16_t dport;
103141c99275SPeter Avalos 	const u_char *ep;
103241c99275SPeter Avalos 	u_int prot;
103341c99275SPeter Avalos 
1034*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_protocol = "icmp6";
1035411677aeSAaron LI 	dp = (const struct icmp6_hdr *)bp;
1036411677aeSAaron LI 	ip = (const struct ip6_hdr *)bp2;
1037411677aeSAaron LI 	oip = (const struct ip6_hdr *)(dp + 1);
103841c99275SPeter Avalos 	/* 'ep' points to the end of available data. */
1039411677aeSAaron LI 	ep = ndo->ndo_snapend;
1040*ed775ee7SAntonio Huete Jimenez 	if (length == 0) {
1041*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("ICMP6, length 0");
1042*ed775ee7SAntonio Huete Jimenez 		nd_print_invalid(ndo);
1043*ed775ee7SAntonio Huete Jimenez 		return;
1044*ed775ee7SAntonio Huete Jimenez 	}
104541c99275SPeter Avalos 
1046411677aeSAaron LI 	if (ndo->ndo_vflag && !fragmented) {
1047411677aeSAaron LI 		uint16_t sum, udp_sum;
104841c99275SPeter Avalos 
1049*ed775ee7SAntonio Huete Jimenez 		if (ND_TTEST_LEN(bp, length)) {
1050*ed775ee7SAntonio Huete Jimenez 			udp_sum = GET_BE_U_2(dp->icmp6_cksum);
1051411677aeSAaron LI 			sum = icmp6_cksum(ndo, ip, dp, length);
105241c99275SPeter Avalos 			if (sum != 0)
1053*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("[bad icmp6 cksum 0x%04x -> 0x%04x!] ",
105427bfbee1SPeter Avalos                                                 udp_sum,
1055*ed775ee7SAntonio Huete Jimenez                                                 in_cksum_shouldbe(udp_sum, sum));
105641c99275SPeter Avalos 			else
1057*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("[icmp6 sum ok] ");
105841c99275SPeter Avalos 		}
105941c99275SPeter Avalos 	}
106041c99275SPeter Avalos 
1061*ed775ee7SAntonio Huete Jimenez 	icmp6_type = GET_U_1(dp->icmp6_type);
1062*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("ICMP6, %s", tok2str(icmp6_type_values,"unknown icmp6 type (%u)",icmp6_type));
106341c99275SPeter Avalos 
106441c99275SPeter Avalos         /* display cosmetics: print the packet length for printer that use the vflag now */
1065*ed775ee7SAntonio Huete Jimenez         if (ndo->ndo_vflag && (icmp6_type == ND_ROUTER_SOLICIT ||
1066*ed775ee7SAntonio Huete Jimenez                       icmp6_type == ND_ROUTER_ADVERT ||
1067*ed775ee7SAntonio Huete Jimenez                       icmp6_type == ND_NEIGHBOR_ADVERT ||
1068*ed775ee7SAntonio Huete Jimenez                       icmp6_type == ND_NEIGHBOR_SOLICIT ||
1069*ed775ee7SAntonio Huete Jimenez                       icmp6_type == ND_REDIRECT ||
1070*ed775ee7SAntonio Huete Jimenez                       icmp6_type == ICMP6_HADISCOV_REPLY ||
1071*ed775ee7SAntonio Huete Jimenez                       icmp6_type == ICMP6_MOBILEPREFIX_ADVERT ))
1072*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(", length %u", length);
107341c99275SPeter Avalos 
1074*ed775ee7SAntonio Huete Jimenez 	icmp6_code = GET_U_1(dp->icmp6_code);
1075*ed775ee7SAntonio Huete Jimenez 
1076*ed775ee7SAntonio Huete Jimenez 	switch (icmp6_type) {
107741c99275SPeter Avalos 	case ICMP6_DST_UNREACH:
1078*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(", %s", tok2str(icmp6_dst_unreach_code_values,"unknown unreach code (%u)",icmp6_code));
1079*ed775ee7SAntonio Huete Jimenez 		switch (icmp6_code) {
108041c99275SPeter Avalos 
108141c99275SPeter Avalos 		case ICMP6_DST_UNREACH_NOROUTE: /* fall through */
108241c99275SPeter Avalos 		case ICMP6_DST_UNREACH_ADMIN:
108341c99275SPeter Avalos 		case ICMP6_DST_UNREACH_ADDR:
1084*ed775ee7SAntonio Huete Jimenez                         ND_PRINT(" %s",GET_IP6ADDR_STRING(oip->ip6_dst));
108541c99275SPeter Avalos                         break;
108641c99275SPeter Avalos 		case ICMP6_DST_UNREACH_BEYONDSCOPE:
1087*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" %s, source address %s",
1088*ed775ee7SAntonio Huete Jimenez 			       GET_IP6ADDR_STRING(oip->ip6_dst),
1089*ed775ee7SAntonio Huete Jimenez                                   GET_IP6ADDR_STRING(oip->ip6_src));
109041c99275SPeter Avalos 			break;
109141c99275SPeter Avalos 		case ICMP6_DST_UNREACH_NOPORT:
1092411677aeSAaron LI 			if ((ouh = get_upperlayer(ndo, (const u_char *)oip, &prot))
109341c99275SPeter Avalos 			    == NULL)
109441c99275SPeter Avalos 				goto trunc;
109541c99275SPeter Avalos 
1096*ed775ee7SAntonio Huete Jimenez 			dport = GET_BE_U_2(ouh->uh_dport);
109741c99275SPeter Avalos 			switch (prot) {
109841c99275SPeter Avalos 			case IPPROTO_TCP:
1099*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(", %s tcp port %s",
1100*ed775ee7SAntonio Huete Jimenez 					GET_IP6ADDR_STRING(oip->ip6_dst),
1101*ed775ee7SAntonio Huete Jimenez                                           tcpport_string(ndo, dport));
110241c99275SPeter Avalos 				break;
110341c99275SPeter Avalos 			case IPPROTO_UDP:
1104*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(", %s udp port %s",
1105*ed775ee7SAntonio Huete Jimenez 					GET_IP6ADDR_STRING(oip->ip6_dst),
1106*ed775ee7SAntonio Huete Jimenez                                           udpport_string(ndo, dport));
110741c99275SPeter Avalos 				break;
110841c99275SPeter Avalos 			default:
1109*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(", %s protocol %u port %u unreachable",
1110*ed775ee7SAntonio Huete Jimenez 					GET_IP6ADDR_STRING(oip->ip6_dst),
1111*ed775ee7SAntonio Huete Jimenez                                           prot, dport);
111241c99275SPeter Avalos 				break;
111341c99275SPeter Avalos 			}
111441c99275SPeter Avalos 			break;
111541c99275SPeter Avalos 		default:
1116411677aeSAaron LI                   if (ndo->ndo_vflag <= 1) {
1117411677aeSAaron LI                     print_unknown_data(ndo, bp,"\n\t",length);
111841c99275SPeter Avalos                     return;
111941c99275SPeter Avalos                   }
112041c99275SPeter Avalos                     break;
112141c99275SPeter Avalos 		}
112241c99275SPeter Avalos 		break;
112341c99275SPeter Avalos 	case ICMP6_PACKET_TOO_BIG:
1124*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", mtu %u", GET_BE_U_4(dp->icmp6_mtu));
112541c99275SPeter Avalos 		break;
112641c99275SPeter Avalos 	case ICMP6_TIME_EXCEEDED:
1127*ed775ee7SAntonio Huete Jimenez 		switch (icmp6_code) {
112841c99275SPeter Avalos 		case ICMP6_TIME_EXCEED_TRANSIT:
1129*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" for %s",
1130*ed775ee7SAntonio Huete Jimenez                                   GET_IP6ADDR_STRING(oip->ip6_dst));
113141c99275SPeter Avalos 			break;
113241c99275SPeter Avalos 		case ICMP6_TIME_EXCEED_REASSEMBLY:
1133*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" (reassembly)");
113441c99275SPeter Avalos 			break;
113541c99275SPeter Avalos 		default:
1136*ed775ee7SAntonio Huete Jimenez                         ND_PRINT(", unknown code (%u)", icmp6_code);
113741c99275SPeter Avalos 			break;
113841c99275SPeter Avalos 		}
113941c99275SPeter Avalos 		break;
114041c99275SPeter Avalos 	case ICMP6_PARAM_PROB:
1141*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_16(oip->ip6_dst);
1142*ed775ee7SAntonio Huete Jimenez 		switch (icmp6_code) {
114341c99275SPeter Avalos 		case ICMP6_PARAMPROB_HEADER:
1144*ed775ee7SAntonio Huete Jimenez                         ND_PRINT(", erroneous - octet %u",
1145*ed775ee7SAntonio Huete Jimenez 				 GET_BE_U_4(dp->icmp6_pptr));
114641c99275SPeter Avalos                         break;
114741c99275SPeter Avalos 		case ICMP6_PARAMPROB_NEXTHEADER:
1148*ed775ee7SAntonio Huete Jimenez                         ND_PRINT(", next header - octet %u",
1149*ed775ee7SAntonio Huete Jimenez 				 GET_BE_U_4(dp->icmp6_pptr));
115041c99275SPeter Avalos                         break;
115141c99275SPeter Avalos 		case ICMP6_PARAMPROB_OPTION:
1152*ed775ee7SAntonio Huete Jimenez                         ND_PRINT(", option - octet %u",
1153*ed775ee7SAntonio Huete Jimenez 				 GET_BE_U_4(dp->icmp6_pptr));
1154*ed775ee7SAntonio Huete Jimenez                         break;
1155*ed775ee7SAntonio Huete Jimenez 		case ICMP6_PARAMPROB_FRAGHDRCHAIN:
1156*ed775ee7SAntonio Huete Jimenez                         ND_PRINT(", incomplete header chain - octet %u",
1157*ed775ee7SAntonio Huete Jimenez 				 GET_BE_U_4(dp->icmp6_pptr));
115841c99275SPeter Avalos                         break;
115941c99275SPeter Avalos 		default:
1160*ed775ee7SAntonio Huete Jimenez                         ND_PRINT(", code-#%u",
1161*ed775ee7SAntonio Huete Jimenez                                   icmp6_code);
116241c99275SPeter Avalos                         break;
116341c99275SPeter Avalos 		}
116441c99275SPeter Avalos 		break;
116541c99275SPeter Avalos 	case ICMP6_ECHO_REQUEST:
116641c99275SPeter Avalos 	case ICMP6_ECHO_REPLY:
1167*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(", id %u, seq %u", GET_BE_U_2(dp->icmp6_id),
1168*ed775ee7SAntonio Huete Jimenez 			 GET_BE_U_2(dp->icmp6_seq));
116941c99275SPeter Avalos 		break;
117041c99275SPeter Avalos 	case ICMP6_MEMBERSHIP_QUERY:
117141c99275SPeter Avalos 		if (length == MLD_MINLEN) {
1172411677aeSAaron LI 			mld6_print(ndo, (const u_char *)dp);
117341c99275SPeter Avalos 		} else if (length >= MLDV2_MINLEN) {
1174*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" v2");
1175411677aeSAaron LI 			mldv2_query_print(ndo, (const u_char *)dp, length);
117641c99275SPeter Avalos 		} else {
1177*ed775ee7SAntonio Huete Jimenez                         ND_PRINT(" unknown-version (len %u) ", length);
117841c99275SPeter Avalos 		}
117941c99275SPeter Avalos 		break;
118041c99275SPeter Avalos 	case ICMP6_MEMBERSHIP_REPORT:
1181411677aeSAaron LI 		mld6_print(ndo, (const u_char *)dp);
118241c99275SPeter Avalos 		break;
118341c99275SPeter Avalos 	case ICMP6_MEMBERSHIP_REDUCTION:
1184411677aeSAaron LI 		mld6_print(ndo, (const u_char *)dp);
118541c99275SPeter Avalos 		break;
118641c99275SPeter Avalos 	case ND_ROUTER_SOLICIT:
118741c99275SPeter Avalos #define RTSOLLEN 8
1188411677aeSAaron LI 		if (ndo->ndo_vflag) {
1189*ed775ee7SAntonio Huete Jimenez 			if (icmp6_opt_print(ndo, (const u_char *)dp + RTSOLLEN,
1190*ed775ee7SAntonio Huete Jimenez 					    length - RTSOLLEN) == -1)
1191*ed775ee7SAntonio Huete Jimenez 				goto trunc;
119241c99275SPeter Avalos 		}
119341c99275SPeter Avalos 		break;
119441c99275SPeter Avalos 	case ND_ROUTER_ADVERT:
119541c99275SPeter Avalos #define RTADVLEN 16
1196411677aeSAaron LI 		if (ndo->ndo_vflag) {
1197411677aeSAaron LI 			const struct nd_router_advert *p;
119841c99275SPeter Avalos 
1199411677aeSAaron LI 			p = (const struct nd_router_advert *)dp;
1200*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("\n\thop limit %u, Flags [%s]"
1201411677aeSAaron LI                                   ", pref %s, router lifetime %us, reachable time %ums, retrans timer %ums",
1202*ed775ee7SAntonio Huete Jimenez                                   GET_U_1(p->nd_ra_curhoplimit),
1203*ed775ee7SAntonio Huete Jimenez                                   bittok2str(icmp6_opt_ra_flag_values,"none",GET_U_1(p->nd_ra_flags_reserved)),
1204*ed775ee7SAntonio Huete Jimenez                                   get_rtpref(GET_U_1(p->nd_ra_flags_reserved)),
1205*ed775ee7SAntonio Huete Jimenez                                   GET_BE_U_2(p->nd_ra_router_lifetime),
1206*ed775ee7SAntonio Huete Jimenez                                   GET_BE_U_4(p->nd_ra_reachable),
1207*ed775ee7SAntonio Huete Jimenez                                   GET_BE_U_4(p->nd_ra_retransmit));
120841c99275SPeter Avalos 
1209*ed775ee7SAntonio Huete Jimenez 			if (icmp6_opt_print(ndo, (const u_char *)dp + RTADVLEN,
1210*ed775ee7SAntonio Huete Jimenez 					    length - RTADVLEN) == -1)
1211*ed775ee7SAntonio Huete Jimenez 				goto trunc;
121241c99275SPeter Avalos 		}
121341c99275SPeter Avalos 		break;
121441c99275SPeter Avalos 	case ND_NEIGHBOR_SOLICIT:
121541c99275SPeter Avalos 	    {
1216411677aeSAaron LI 		const struct nd_neighbor_solicit *p;
1217411677aeSAaron LI 		p = (const struct nd_neighbor_solicit *)dp;
1218*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", who has %s", GET_IP6ADDR_STRING(p->nd_ns_target));
1219411677aeSAaron LI 		if (ndo->ndo_vflag) {
122041c99275SPeter Avalos #define NDSOLLEN 24
1221*ed775ee7SAntonio Huete Jimenez 			if (icmp6_opt_print(ndo, (const u_char *)dp + NDSOLLEN,
1222*ed775ee7SAntonio Huete Jimenez 					    length - NDSOLLEN) == -1)
1223*ed775ee7SAntonio Huete Jimenez 				goto trunc;
122441c99275SPeter Avalos 		}
122541c99275SPeter Avalos 	    }
122641c99275SPeter Avalos 		break;
122741c99275SPeter Avalos 	case ND_NEIGHBOR_ADVERT:
122841c99275SPeter Avalos 	    {
1229411677aeSAaron LI 		const struct nd_neighbor_advert *p;
123041c99275SPeter Avalos 
1231411677aeSAaron LI 		p = (const struct nd_neighbor_advert *)dp;
1232*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", tgt is %s",
1233*ed775ee7SAntonio Huete Jimenez                           GET_IP6ADDR_STRING(p->nd_na_target));
1234411677aeSAaron LI 		if (ndo->ndo_vflag) {
1235*ed775ee7SAntonio Huete Jimenez                         ND_PRINT(", Flags [%s]",
123641c99275SPeter Avalos                                   bittok2str(icmp6_nd_na_flag_values,
123741c99275SPeter Avalos                                              "none",
1238*ed775ee7SAntonio Huete Jimenez                                              GET_BE_U_4(p->nd_na_flags_reserved)));
123941c99275SPeter Avalos #define NDADVLEN 24
1240*ed775ee7SAntonio Huete Jimenez 			if (icmp6_opt_print(ndo, (const u_char *)dp + NDADVLEN,
1241*ed775ee7SAntonio Huete Jimenez 					    length - NDADVLEN) == -1)
1242*ed775ee7SAntonio Huete Jimenez 				goto trunc;
124341c99275SPeter Avalos #undef NDADVLEN
124441c99275SPeter Avalos 		}
124541c99275SPeter Avalos 	    }
124641c99275SPeter Avalos 		break;
124741c99275SPeter Avalos 	case ND_REDIRECT:
1248*ed775ee7SAntonio Huete Jimenez 	    {
1249*ed775ee7SAntonio Huete Jimenez 		const struct nd_redirect *p;
1250*ed775ee7SAntonio Huete Jimenez 
1251*ed775ee7SAntonio Huete Jimenez 		p = (const struct nd_redirect *)dp;
1252*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", %s", GET_IP6ADDR_STRING(p->nd_rd_dst));
1253*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(" to %s", GET_IP6ADDR_STRING(p->nd_rd_target));
125441c99275SPeter Avalos #define REDIRECTLEN 40
1255411677aeSAaron LI 		if (ndo->ndo_vflag) {
1256*ed775ee7SAntonio Huete Jimenez 			if (icmp6_opt_print(ndo, (const u_char *)dp + REDIRECTLEN,
1257*ed775ee7SAntonio Huete Jimenez 					    length - REDIRECTLEN) == -1)
1258*ed775ee7SAntonio Huete Jimenez 				goto trunc;
1259*ed775ee7SAntonio Huete Jimenez #undef REDIRECTLEN
1260*ed775ee7SAntonio Huete Jimenez 		}
126141c99275SPeter Avalos 	    }
126241c99275SPeter Avalos 		break;
126341c99275SPeter Avalos 	case ICMP6_ROUTER_RENUMBERING:
1264411677aeSAaron LI 		icmp6_rrenum_print(ndo, bp, ep);
126541c99275SPeter Avalos 		break;
126641c99275SPeter Avalos 	case ICMP6_NI_QUERY:
126741c99275SPeter Avalos 	case ICMP6_NI_REPLY:
1268411677aeSAaron LI 		icmp6_nodeinfo_print(ndo, length, bp, ep);
126941c99275SPeter Avalos 		break;
127041c99275SPeter Avalos 	case IND_SOLICIT:
127141c99275SPeter Avalos 	case IND_ADVERT:
127241c99275SPeter Avalos 		break;
127341c99275SPeter Avalos 	case ICMP6_V2_MEMBERSHIP_REPORT:
1274411677aeSAaron LI 		mldv2_report_print(ndo, (const u_char *) dp, length);
127541c99275SPeter Avalos 		break;
127641c99275SPeter Avalos 	case ICMP6_MOBILEPREFIX_SOLICIT: /* fall through */
127741c99275SPeter Avalos 	case ICMP6_HADISCOV_REQUEST:
1278*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(", id 0x%04x", GET_BE_U_2(dp->icmp6_data16[0]));
127941c99275SPeter Avalos                 break;
128041c99275SPeter Avalos 	case ICMP6_HADISCOV_REPLY:
1281411677aeSAaron LI 		if (ndo->ndo_vflag) {
1282411677aeSAaron LI 			const u_char *cp;
1283*ed775ee7SAntonio Huete Jimenez 			const u_char *p;
128441c99275SPeter Avalos 
1285*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(", id 0x%04x",
1286*ed775ee7SAntonio Huete Jimenez 				 GET_BE_U_2(dp->icmp6_data16[0]));
1287411677aeSAaron LI 			cp = (const u_char *)dp + length;
1288*ed775ee7SAntonio Huete Jimenez 			p = (const u_char *)(dp + 1);
1289*ed775ee7SAntonio Huete Jimenez 			while (p < cp) {
1290*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(", %s", GET_IP6ADDR_STRING(p));
1291*ed775ee7SAntonio Huete Jimenez 				p += 16;
129241c99275SPeter Avalos 			}
129341c99275SPeter Avalos 		}
129441c99275SPeter Avalos 		break;
129541c99275SPeter Avalos 	case ICMP6_MOBILEPREFIX_ADVERT:
1296411677aeSAaron LI 		if (ndo->ndo_vflag) {
1297*ed775ee7SAntonio Huete Jimenez 			uint16_t flags;
1298*ed775ee7SAntonio Huete Jimenez 
1299*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(", id 0x%04x",
1300*ed775ee7SAntonio Huete Jimenez 				 GET_BE_U_2(dp->icmp6_data16[0]));
1301*ed775ee7SAntonio Huete Jimenez 			flags = GET_BE_U_2(dp->icmp6_data16[1]);
1302*ed775ee7SAntonio Huete Jimenez 			if (flags & 0xc000)
1303*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(" ");
1304*ed775ee7SAntonio Huete Jimenez 			if (flags & 0x8000)
1305*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("M");
1306*ed775ee7SAntonio Huete Jimenez 			if (flags & 0x4000)
1307*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("O");
130841c99275SPeter Avalos #define MPADVLEN 8
1309*ed775ee7SAntonio Huete Jimenez 			if (icmp6_opt_print(ndo, (const u_char *)dp + MPADVLEN,
1310*ed775ee7SAntonio Huete Jimenez 					    length - MPADVLEN) == -1)
1311*ed775ee7SAntonio Huete Jimenez 				goto trunc;
131241c99275SPeter Avalos 		}
131341c99275SPeter Avalos 		break;
131427bfbee1SPeter Avalos         case ND_RPL_MESSAGE:
1315411677aeSAaron LI                 /* plus 4, because struct icmp6_hdr contains 4 bytes of icmp payload */
1316*ed775ee7SAntonio Huete Jimenez                 rpl_print(ndo, icmp6_code, dp->icmp6_data, length-sizeof(struct icmp6_hdr)+4);
131727bfbee1SPeter Avalos                 break;
131841c99275SPeter Avalos 	default:
1319*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(", length %u", length);
1320411677aeSAaron LI                 if (ndo->ndo_vflag <= 1)
1321411677aeSAaron LI                         print_unknown_data(ndo, bp,"\n\t", length);
132241c99275SPeter Avalos                 return;
132341c99275SPeter Avalos         }
1324411677aeSAaron LI         if (!ndo->ndo_vflag)
1325*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(", length %u", length);
132641c99275SPeter Avalos 	return;
132741c99275SPeter Avalos trunc:
1328*ed775ee7SAntonio Huete Jimenez 	nd_print_trunc(ndo);
132941c99275SPeter Avalos }
133041c99275SPeter Avalos 
1331411677aeSAaron LI static const struct udphdr *
get_upperlayer(netdissect_options * ndo,const u_char * bp,u_int * prot)1332411677aeSAaron LI get_upperlayer(netdissect_options *ndo, const u_char *bp, u_int *prot)
133341c99275SPeter Avalos {
133441c99275SPeter Avalos 	const u_char *ep;
1335411677aeSAaron LI 	const struct ip6_hdr *ip6 = (const struct ip6_hdr *)bp;
1336411677aeSAaron LI 	const struct udphdr *uh;
1337411677aeSAaron LI 	const struct ip6_hbh *hbh;
1338411677aeSAaron LI 	const struct ip6_frag *fragh;
1339411677aeSAaron LI 	const struct ah *ah;
134041c99275SPeter Avalos 	u_int nh;
134141c99275SPeter Avalos 	int hlen;
134241c99275SPeter Avalos 
134341c99275SPeter Avalos 	/* 'ep' points to the end of available data. */
1344411677aeSAaron LI 	ep = ndo->ndo_snapend;
134541c99275SPeter Avalos 
1346*ed775ee7SAntonio Huete Jimenez 	if (!ND_TTEST_1(ip6->ip6_nxt))
134741c99275SPeter Avalos 		return NULL;
134841c99275SPeter Avalos 
1349*ed775ee7SAntonio Huete Jimenez 	nh = GET_U_1(ip6->ip6_nxt);
135041c99275SPeter Avalos 	hlen = sizeof(struct ip6_hdr);
135141c99275SPeter Avalos 
135241c99275SPeter Avalos 	while (bp < ep) {
135341c99275SPeter Avalos 		bp += hlen;
135441c99275SPeter Avalos 
135541c99275SPeter Avalos 		switch(nh) {
135641c99275SPeter Avalos 		case IPPROTO_UDP:
135741c99275SPeter Avalos 		case IPPROTO_TCP:
1358411677aeSAaron LI 			uh = (const struct udphdr *)bp;
1359*ed775ee7SAntonio Huete Jimenez 			if (ND_TTEST_2(uh->uh_dport)) {
136041c99275SPeter Avalos 				*prot = nh;
136141c99275SPeter Avalos 				return(uh);
136241c99275SPeter Avalos 			}
136341c99275SPeter Avalos 			else
136441c99275SPeter Avalos 				return(NULL);
136541c99275SPeter Avalos 			/* NOTREACHED */
136641c99275SPeter Avalos 
136741c99275SPeter Avalos 		case IPPROTO_HOPOPTS:
136841c99275SPeter Avalos 		case IPPROTO_DSTOPTS:
136941c99275SPeter Avalos 		case IPPROTO_ROUTING:
1370411677aeSAaron LI 			hbh = (const struct ip6_hbh *)bp;
1371*ed775ee7SAntonio Huete Jimenez 			if (!ND_TTEST_1(hbh->ip6h_len))
137241c99275SPeter Avalos 				return(NULL);
1373*ed775ee7SAntonio Huete Jimenez 			nh = GET_U_1(hbh->ip6h_nxt);
1374*ed775ee7SAntonio Huete Jimenez 			hlen = (GET_U_1(hbh->ip6h_len) + 1) << 3;
137541c99275SPeter Avalos 			break;
137641c99275SPeter Avalos 
137741c99275SPeter Avalos 		case IPPROTO_FRAGMENT: /* this should be odd, but try anyway */
1378411677aeSAaron LI 			fragh = (const struct ip6_frag *)bp;
1379*ed775ee7SAntonio Huete Jimenez 			if (!ND_TTEST_2(fragh->ip6f_offlg))
138041c99275SPeter Avalos 				return(NULL);
138141c99275SPeter Avalos 			/* fragments with non-zero offset are meaningless */
1382*ed775ee7SAntonio Huete Jimenez 			if ((GET_BE_U_2(fragh->ip6f_offlg) & IP6F_OFF_MASK) != 0)
138341c99275SPeter Avalos 				return(NULL);
1384*ed775ee7SAntonio Huete Jimenez 			nh = GET_U_1(fragh->ip6f_nxt);
138541c99275SPeter Avalos 			hlen = sizeof(struct ip6_frag);
138641c99275SPeter Avalos 			break;
138741c99275SPeter Avalos 
138841c99275SPeter Avalos 		case IPPROTO_AH:
1389411677aeSAaron LI 			ah = (const struct ah *)bp;
1390*ed775ee7SAntonio Huete Jimenez 			if (!ND_TTEST_1(ah->ah_len))
139141c99275SPeter Avalos 				return(NULL);
1392*ed775ee7SAntonio Huete Jimenez 			nh = GET_U_1(ah->ah_nxt);
1393*ed775ee7SAntonio Huete Jimenez 			hlen = (GET_U_1(ah->ah_len) + 2) << 2;
139441c99275SPeter Avalos 			break;
139541c99275SPeter Avalos 
139641c99275SPeter Avalos 		default:	/* unknown or undecodable header */
139741c99275SPeter Avalos 			*prot = nh; /* meaningless, but set here anyway */
139841c99275SPeter Avalos 			return(NULL);
139941c99275SPeter Avalos 		}
140041c99275SPeter Avalos 	}
140141c99275SPeter Avalos 
140241c99275SPeter Avalos 	return(NULL);		/* should be notreached, though */
140341c99275SPeter Avalos }
140441c99275SPeter Avalos 
1405*ed775ee7SAntonio Huete Jimenez static int
icmp6_opt_print(netdissect_options * ndo,const u_char * bp,int resid)1406411677aeSAaron LI icmp6_opt_print(netdissect_options *ndo, const u_char *bp, int resid)
140741c99275SPeter Avalos {
140841c99275SPeter Avalos 	const struct nd_opt_hdr *op;
1409*ed775ee7SAntonio Huete Jimenez 	uint8_t opt_type;
1410*ed775ee7SAntonio Huete Jimenez 	u_int opt_len;
141141c99275SPeter Avalos 	const struct nd_opt_prefix_info *opp;
141241c99275SPeter Avalos 	const struct nd_opt_mtu *opm;
141327bfbee1SPeter Avalos 	const struct nd_opt_rdnss *oprd;
1414411677aeSAaron LI 	const struct nd_opt_dnssl *opds;
141541c99275SPeter Avalos 	const struct nd_opt_advinterval *opa;
141641c99275SPeter Avalos 	const struct nd_opt_homeagent_info *oph;
141741c99275SPeter Avalos 	const struct nd_opt_route_info *opri;
1418411677aeSAaron LI 	const u_char *cp, *ep, *domp;
1419*ed775ee7SAntonio Huete Jimenez 	nd_ipv6 in6;
142041c99275SPeter Avalos 	size_t l;
142127bfbee1SPeter Avalos 	u_int i;
142241c99275SPeter Avalos 
142341c99275SPeter Avalos 	cp = bp;
142441c99275SPeter Avalos 	/* 'ep' points to the end of available data. */
1425411677aeSAaron LI 	ep = ndo->ndo_snapend;
142641c99275SPeter Avalos 
142741c99275SPeter Avalos 	while (cp < ep) {
1428411677aeSAaron LI 		op = (const struct nd_opt_hdr *)cp;
142941c99275SPeter Avalos 
1430*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_1(op->nd_opt_len);
143141c99275SPeter Avalos 		if (resid <= 0)
1432*ed775ee7SAntonio Huete Jimenez 			return 0;
1433*ed775ee7SAntonio Huete Jimenez 		opt_type = GET_U_1(op->nd_opt_type);
1434*ed775ee7SAntonio Huete Jimenez 		opt_len = GET_U_1(op->nd_opt_len);
1435*ed775ee7SAntonio Huete Jimenez 		if (opt_len == 0)
143641c99275SPeter Avalos 			goto trunc;
1437*ed775ee7SAntonio Huete Jimenez 		if (cp + (opt_len << 3) > ep)
143841c99275SPeter Avalos 			goto trunc;
143941c99275SPeter Avalos 
1440*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("\n\t  %s option (%u), length %u (%u): ",
1441*ed775ee7SAntonio Huete Jimenez                           tok2str(icmp6_opt_values, "unknown", opt_type),
1442*ed775ee7SAntonio Huete Jimenez                           opt_type,
1443*ed775ee7SAntonio Huete Jimenez                           opt_len << 3,
1444*ed775ee7SAntonio Huete Jimenez                           opt_len);
144541c99275SPeter Avalos 
1446*ed775ee7SAntonio Huete Jimenez 		switch (opt_type) {
144741c99275SPeter Avalos 		case ND_OPT_SOURCE_LINKADDR:
1448*ed775ee7SAntonio Huete Jimenez 			l = (opt_len << 3) - 2;
1449411677aeSAaron LI 			print_lladdr(ndo, cp + 2, l);
145041c99275SPeter Avalos 			break;
145141c99275SPeter Avalos 		case ND_OPT_TARGET_LINKADDR:
1452*ed775ee7SAntonio Huete Jimenez 			l = (opt_len << 3) - 2;
1453411677aeSAaron LI 			print_lladdr(ndo, cp + 2, l);
145441c99275SPeter Avalos 			break;
145541c99275SPeter Avalos 		case ND_OPT_PREFIX_INFORMATION:
1456411677aeSAaron LI 			opp = (const struct nd_opt_prefix_info *)op;
1457*ed775ee7SAntonio Huete Jimenez                         ND_PRINT("%s/%u%s, Flags [%s], valid time %s",
1458*ed775ee7SAntonio Huete Jimenez                                   GET_IP6ADDR_STRING(opp->nd_opt_pi_prefix),
1459*ed775ee7SAntonio Huete Jimenez                                   GET_U_1(opp->nd_opt_pi_prefix_len),
1460*ed775ee7SAntonio Huete Jimenez                                   (opt_len != 4) ? "badlen" : "",
1461*ed775ee7SAntonio Huete Jimenez                                   bittok2str(icmp6_opt_pi_flag_values, "none", GET_U_1(opp->nd_opt_pi_flags_reserved)),
1462*ed775ee7SAntonio Huete Jimenez                                   get_lifetime(GET_BE_U_4(opp->nd_opt_pi_valid_time)));
1463*ed775ee7SAntonio Huete Jimenez                         ND_PRINT(", pref. time %s",
1464*ed775ee7SAntonio Huete Jimenez 				 get_lifetime(GET_BE_U_4(opp->nd_opt_pi_preferred_time)));
146541c99275SPeter Avalos 			break;
146641c99275SPeter Avalos 		case ND_OPT_REDIRECTED_HEADER:
1467*ed775ee7SAntonio Huete Jimenez                         print_unknown_data(ndo, bp,"\n\t    ",opt_len<<3);
146841c99275SPeter Avalos 			/* xxx */
146941c99275SPeter Avalos 			break;
147041c99275SPeter Avalos 		case ND_OPT_MTU:
1471411677aeSAaron LI 			opm = (const struct nd_opt_mtu *)op;
1472*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" %u%s",
1473*ed775ee7SAntonio Huete Jimenez                                GET_BE_U_4(opm->nd_opt_mtu_mtu),
1474*ed775ee7SAntonio Huete Jimenez                                (opt_len != 1) ? "bad option length" : "" );
147541c99275SPeter Avalos                         break;
147627bfbee1SPeter Avalos 		case ND_OPT_RDNSS:
1477411677aeSAaron LI 			oprd = (const struct nd_opt_rdnss *)op;
1478*ed775ee7SAntonio Huete Jimenez 			l = (opt_len - 1) / 2;
1479*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" lifetime %us,",
1480*ed775ee7SAntonio Huete Jimenez                                   GET_BE_U_4(oprd->nd_opt_rdnss_lifetime));
148127bfbee1SPeter Avalos 			for (i = 0; i < l; i++) {
1482*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(" addr: %s",
1483*ed775ee7SAntonio Huete Jimenez                                           GET_IP6ADDR_STRING(oprd->nd_opt_rdnss_addr[i]));
1484411677aeSAaron LI 			}
1485411677aeSAaron LI 			break;
1486411677aeSAaron LI 		case ND_OPT_DNSSL:
1487411677aeSAaron LI 			opds = (const struct nd_opt_dnssl *)op;
1488*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" lifetime %us, domain(s):",
1489*ed775ee7SAntonio Huete Jimenez                                   GET_BE_U_4(opds->nd_opt_dnssl_lifetime));
1490411677aeSAaron LI 			domp = cp + 8; /* domain names, variable-sized, RFC1035-encoded */
1491*ed775ee7SAntonio Huete Jimenez 			while (domp < cp + (opt_len << 3) && GET_U_1(domp) != '\0')
1492411677aeSAaron LI 			{
1493*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(" ");
1494*ed775ee7SAntonio Huete Jimenez 				if ((domp = fqdn_print(ndo, domp, bp)) == NULL)
1495411677aeSAaron LI 					goto trunc;
149627bfbee1SPeter Avalos 			}
149727bfbee1SPeter Avalos 			break;
149841c99275SPeter Avalos 		case ND_OPT_ADVINTERVAL:
1499411677aeSAaron LI 			opa = (const struct nd_opt_advinterval *)op;
1500*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" %ums",
1501*ed775ee7SAntonio Huete Jimenez 				 GET_BE_U_4(opa->nd_opt_adv_interval));
150241c99275SPeter Avalos 			break;
150341c99275SPeter Avalos                 case ND_OPT_HOMEAGENT_INFO:
1504411677aeSAaron LI 			oph = (const struct nd_opt_homeagent_info *)op;
1505*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" preference %u, lifetime %u",
1506*ed775ee7SAntonio Huete Jimenez                                   GET_BE_U_2(oph->nd_opt_hai_preference),
1507*ed775ee7SAntonio Huete Jimenez                                   GET_BE_U_2(oph->nd_opt_hai_lifetime));
150841c99275SPeter Avalos 			break;
150941c99275SPeter Avalos 		case ND_OPT_ROUTE_INFO:
1510411677aeSAaron LI 			opri = (const struct nd_opt_route_info *)op;
1511*ed775ee7SAntonio Huete Jimenez 			ND_TCHECK_4(opri->nd_opt_rti_lifetime);
151241c99275SPeter Avalos 			memset(&in6, 0, sizeof(in6));
1513*ed775ee7SAntonio Huete Jimenez 			switch (opt_len) {
151441c99275SPeter Avalos 			case 1:
151541c99275SPeter Avalos 				break;
151641c99275SPeter Avalos 			case 2:
1517*ed775ee7SAntonio Huete Jimenez 				GET_CPY_BYTES(&in6, opri + 1, 8);
151841c99275SPeter Avalos 				break;
151941c99275SPeter Avalos 			case 3:
1520*ed775ee7SAntonio Huete Jimenez 				GET_CPY_BYTES(&in6, opri + 1, 16);
152141c99275SPeter Avalos 				break;
152241c99275SPeter Avalos 			default:
152341c99275SPeter Avalos 				goto trunc;
152441c99275SPeter Avalos 			}
1525*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" %s/%u", ip6addr_string(ndo, (const u_char *)&in6),
1526*ed775ee7SAntonio Huete Jimenez                                   GET_U_1(opri->nd_opt_rti_prefixlen));
1527*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(", pref=%s",
1528*ed775ee7SAntonio Huete Jimenez 				 get_rtpref(GET_U_1(opri->nd_opt_rti_flags)));
1529*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(", lifetime=%s",
1530*ed775ee7SAntonio Huete Jimenez                                   get_lifetime(GET_BE_U_4(opri->nd_opt_rti_lifetime)));
153141c99275SPeter Avalos 			break;
153241c99275SPeter Avalos 		default:
1533411677aeSAaron LI                         if (ndo->ndo_vflag <= 1) {
1534*ed775ee7SAntonio Huete Jimenez                                 print_unknown_data(ndo,cp+2,"\n\t  ", (opt_len << 3) - 2); /* skip option header */
1535*ed775ee7SAntonio Huete Jimenez                             return 0;
153641c99275SPeter Avalos                         }
153741c99275SPeter Avalos                         break;
153841c99275SPeter Avalos 		}
153941c99275SPeter Avalos                 /* do we want to see an additional hexdump ? */
1540411677aeSAaron LI                 if (ndo->ndo_vflag> 1)
1541*ed775ee7SAntonio Huete Jimenez                         print_unknown_data(ndo, cp+2,"\n\t    ", (opt_len << 3) - 2); /* skip option header */
154241c99275SPeter Avalos 
1543*ed775ee7SAntonio Huete Jimenez 		cp += opt_len << 3;
1544*ed775ee7SAntonio Huete Jimenez 		resid -= opt_len << 3;
154541c99275SPeter Avalos 	}
1546*ed775ee7SAntonio Huete Jimenez 	return 0;
154741c99275SPeter Avalos 
154841c99275SPeter Avalos trunc:
1549*ed775ee7SAntonio Huete Jimenez 	return -1;
155041c99275SPeter Avalos }
155141c99275SPeter Avalos 
155241c99275SPeter Avalos static void
mld6_print(netdissect_options * ndo,const u_char * bp)1553411677aeSAaron LI mld6_print(netdissect_options *ndo, const u_char *bp)
155441c99275SPeter Avalos {
1555411677aeSAaron LI 	const struct mld6_hdr *mp = (const struct mld6_hdr *)bp;
155641c99275SPeter Avalos 	const u_char *ep;
155741c99275SPeter Avalos 
155841c99275SPeter Avalos 	/* 'ep' points to the end of available data. */
1559411677aeSAaron LI 	ep = ndo->ndo_snapend;
156041c99275SPeter Avalos 
1561411677aeSAaron LI 	if ((const u_char *)mp + sizeof(*mp) > ep)
156241c99275SPeter Avalos 		return;
156341c99275SPeter Avalos 
1564*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("max resp delay: %u ", GET_BE_U_2(mp->mld6_maxdelay));
1565*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("addr: %s", GET_IP6ADDR_STRING(mp->mld6_addr));
156641c99275SPeter Avalos }
156741c99275SPeter Avalos 
156841c99275SPeter Avalos static void
mldv2_report_print(netdissect_options * ndo,const u_char * bp,u_int len)1569411677aeSAaron LI mldv2_report_print(netdissect_options *ndo, const u_char *bp, u_int len)
157041c99275SPeter Avalos {
1571411677aeSAaron LI     const struct icmp6_hdr *icp = (const struct icmp6_hdr *) bp;
157241c99275SPeter Avalos     u_int group, nsrcs, ngroups;
157341c99275SPeter Avalos     u_int i, j;
157441c99275SPeter Avalos 
157541c99275SPeter Avalos     /* Minimum len is 8 */
157641c99275SPeter Avalos     if (len < 8) {
1577*ed775ee7SAntonio Huete Jimenez             ND_PRINT(" [invalid len %u]", len);
157841c99275SPeter Avalos             return;
157941c99275SPeter Avalos     }
158041c99275SPeter Avalos 
1581*ed775ee7SAntonio Huete Jimenez     ngroups = GET_BE_U_2(icp->icmp6_data16[1]);
1582*ed775ee7SAntonio Huete Jimenez     ND_PRINT(", %u group record(s)", ngroups);
1583411677aeSAaron LI     if (ndo->ndo_vflag > 0) {
158441c99275SPeter Avalos 	/* Print the group records */
158541c99275SPeter Avalos 	group = 8;
158641c99275SPeter Avalos         for (i = 0; i < ngroups; i++) {
158741c99275SPeter Avalos 	    /* type(1) + auxlen(1) + numsrc(2) + grp(16) */
158841c99275SPeter Avalos 	    if (len < group + 20) {
1589*ed775ee7SAntonio Huete Jimenez                     ND_PRINT(" [invalid number of groups]");
159041c99275SPeter Avalos                     return;
159141c99275SPeter Avalos 	    }
1592*ed775ee7SAntonio Huete Jimenez             ND_PRINT(" [gaddr %s", GET_IP6ADDR_STRING(bp + group + 4));
1593*ed775ee7SAntonio Huete Jimenez 	    ND_PRINT(" %s", tok2str(mldv2report2str, " [v2-report-#%u]",
1594*ed775ee7SAntonio Huete Jimenez                                          GET_U_1(bp + group)));
1595*ed775ee7SAntonio Huete Jimenez             nsrcs = GET_BE_U_2(bp + group + 2);
159641c99275SPeter Avalos 	    /* Check the number of sources and print them */
1597*ed775ee7SAntonio Huete Jimenez 	    if (len < group + 20 + (nsrcs * sizeof(nd_ipv6))) {
1598*ed775ee7SAntonio Huete Jimenez                     ND_PRINT(" [invalid number of sources %u]", nsrcs);
159941c99275SPeter Avalos                     return;
160041c99275SPeter Avalos 	    }
1601411677aeSAaron LI             if (ndo->ndo_vflag == 1)
1602*ed775ee7SAntonio Huete Jimenez                     ND_PRINT(", %u source(s)", nsrcs);
160341c99275SPeter Avalos             else {
160441c99275SPeter Avalos 		/* Print the sources */
1605*ed775ee7SAntonio Huete Jimenez                     ND_PRINT(" {");
160641c99275SPeter Avalos                 for (j = 0; j < nsrcs; j++) {
1607*ed775ee7SAntonio Huete Jimenez 		    ND_PRINT(" %s", GET_IP6ADDR_STRING(bp + group + 20 + (j * sizeof(nd_ipv6))));
160841c99275SPeter Avalos 		}
1609*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(" }");
161041c99275SPeter Avalos             }
161141c99275SPeter Avalos 	    /* Next group record */
1612*ed775ee7SAntonio Huete Jimenez             group += 20 + nsrcs * sizeof(nd_ipv6);
1613*ed775ee7SAntonio Huete Jimenez 	    ND_PRINT("]");
161441c99275SPeter Avalos         }
161541c99275SPeter Avalos     }
161641c99275SPeter Avalos }
161741c99275SPeter Avalos 
161841c99275SPeter Avalos static void
mldv2_query_print(netdissect_options * ndo,const u_char * bp,u_int len)1619411677aeSAaron LI mldv2_query_print(netdissect_options *ndo, const u_char *bp, u_int len)
162041c99275SPeter Avalos {
1621411677aeSAaron LI     const struct icmp6_hdr *icp = (const struct icmp6_hdr *) bp;
162241c99275SPeter Avalos     u_int mrc;
1623*ed775ee7SAntonio Huete Jimenez     u_int mrt, qqi;
162441c99275SPeter Avalos     u_int nsrcs;
1625*ed775ee7SAntonio Huete Jimenez     u_int i;
162641c99275SPeter Avalos 
162741c99275SPeter Avalos     /* Minimum len is 28 */
162841c99275SPeter Avalos     if (len < 28) {
1629*ed775ee7SAntonio Huete Jimenez         ND_PRINT(" [invalid len %u]", len);
163041c99275SPeter Avalos 	return;
163141c99275SPeter Avalos     }
1632*ed775ee7SAntonio Huete Jimenez     mrc = GET_BE_U_2(icp->icmp6_data16[0]);
163341c99275SPeter Avalos     if (mrc < 32768) {
163441c99275SPeter Avalos 	mrt = mrc;
163541c99275SPeter Avalos     } else {
163641c99275SPeter Avalos         mrt = ((mrc & 0x0fff) | 0x1000) << (((mrc & 0x7000) >> 12) + 3);
163741c99275SPeter Avalos     }
1638411677aeSAaron LI     if (ndo->ndo_vflag) {
1639*ed775ee7SAntonio Huete Jimenez             ND_PRINT(" [max resp delay=%u]", mrt);
164041c99275SPeter Avalos     }
1641*ed775ee7SAntonio Huete Jimenez     ND_PRINT(" [gaddr %s", GET_IP6ADDR_STRING(bp + 8));
164241c99275SPeter Avalos 
1643411677aeSAaron LI     if (ndo->ndo_vflag) {
1644*ed775ee7SAntonio Huete Jimenez 	if (GET_U_1(bp + 24) & 0x08) {
1645*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(" sflag");
164641c99275SPeter Avalos 	}
1647*ed775ee7SAntonio Huete Jimenez 	if (GET_U_1(bp + 24) & 0x07) {
1648*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(" robustness=%u", GET_U_1(bp + 24) & 0x07);
164941c99275SPeter Avalos 	}
1650*ed775ee7SAntonio Huete Jimenez 	if (GET_U_1(bp + 25) < 128) {
1651*ed775ee7SAntonio Huete Jimenez 		qqi = GET_U_1(bp + 25);
165241c99275SPeter Avalos 	} else {
1653*ed775ee7SAntonio Huete Jimenez 		qqi = ((GET_U_1(bp + 25) & 0x0f) | 0x10) <<
1654*ed775ee7SAntonio Huete Jimenez 		       (((GET_U_1(bp + 25) & 0x70) >> 4) + 3);
165541c99275SPeter Avalos 	}
1656*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(" qqi=%u", qqi);
165741c99275SPeter Avalos     }
165841c99275SPeter Avalos 
1659*ed775ee7SAntonio Huete Jimenez     nsrcs = GET_BE_U_2(bp + 26);
166041c99275SPeter Avalos     if (nsrcs > 0) {
1661*ed775ee7SAntonio Huete Jimenez 	if (len < 28 + nsrcs * sizeof(nd_ipv6))
1662*ed775ee7SAntonio Huete Jimenez 	    ND_PRINT(" [invalid number of sources]");
1663411677aeSAaron LI 	else if (ndo->ndo_vflag > 1) {
1664*ed775ee7SAntonio Huete Jimenez 	    ND_PRINT(" {");
166541c99275SPeter Avalos 	    for (i = 0; i < nsrcs; i++) {
1666*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(" %s", GET_IP6ADDR_STRING(bp + 28 + (i * sizeof(nd_ipv6))));
166741c99275SPeter Avalos 	    }
1668*ed775ee7SAntonio Huete Jimenez 	    ND_PRINT(" }");
166941c99275SPeter Avalos 	} else
1670*ed775ee7SAntonio Huete Jimenez                 ND_PRINT(", %u source(s)", nsrcs);
167141c99275SPeter Avalos     }
1672*ed775ee7SAntonio Huete Jimenez     ND_PRINT("]");
167341c99275SPeter Avalos }
167441c99275SPeter Avalos 
167527bfbee1SPeter Avalos static void
dnsname_print(netdissect_options * ndo,const u_char * cp,const u_char * ep)1676411677aeSAaron LI dnsname_print(netdissect_options *ndo, const u_char *cp, const u_char *ep)
167741c99275SPeter Avalos {
167841c99275SPeter Avalos 	int i;
167941c99275SPeter Avalos 
168041c99275SPeter Avalos 	/* DNS name decoding - no decompression */
1681*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(", \"");
168241c99275SPeter Avalos 	while (cp < ep) {
1683*ed775ee7SAntonio Huete Jimenez 		i = GET_U_1(cp);
1684*ed775ee7SAntonio Huete Jimenez 		cp++;
168541c99275SPeter Avalos 		if (i) {
168641c99275SPeter Avalos 			if (i > ep - cp) {
1687*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("???");
168841c99275SPeter Avalos 				break;
168941c99275SPeter Avalos 			}
169041c99275SPeter Avalos 			while (i-- && cp < ep) {
1691*ed775ee7SAntonio Huete Jimenez 				fn_print_char(ndo, GET_U_1(cp));
169241c99275SPeter Avalos 				cp++;
169341c99275SPeter Avalos 			}
1694*ed775ee7SAntonio Huete Jimenez 			if (cp + 1 < ep && GET_U_1(cp))
1695*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(".");
169641c99275SPeter Avalos 		} else {
169741c99275SPeter Avalos 			if (cp == ep) {
169841c99275SPeter Avalos 				/* FQDN */
1699*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(".");
1700*ed775ee7SAntonio Huete Jimenez 			} else if (cp + 1 == ep && GET_U_1(cp) == '\0') {
170141c99275SPeter Avalos 				/* truncated */
170241c99275SPeter Avalos 			} else {
170341c99275SPeter Avalos 				/* invalid */
1704*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("???");
170541c99275SPeter Avalos 			}
170641c99275SPeter Avalos 			break;
170741c99275SPeter Avalos 		}
170841c99275SPeter Avalos 	}
1709*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("\"");
171041c99275SPeter Avalos }
171141c99275SPeter Avalos 
171241c99275SPeter Avalos static void
icmp6_nodeinfo_print(netdissect_options * ndo,u_int icmp6len,const u_char * bp,const u_char * ep)1713411677aeSAaron LI icmp6_nodeinfo_print(netdissect_options *ndo, u_int icmp6len, const u_char *bp, const u_char *ep)
171441c99275SPeter Avalos {
1715411677aeSAaron LI 	const struct icmp6_nodeinfo *ni6;
1716411677aeSAaron LI 	const struct icmp6_hdr *dp;
171741c99275SPeter Avalos 	const u_char *cp;
171841c99275SPeter Avalos 	size_t siz, i;
171941c99275SPeter Avalos 	int needcomma;
172041c99275SPeter Avalos 
172141c99275SPeter Avalos 	if (ep < bp)
172241c99275SPeter Avalos 		return;
1723411677aeSAaron LI 	dp = (const struct icmp6_hdr *)bp;
1724411677aeSAaron LI 	ni6 = (const struct icmp6_nodeinfo *)bp;
172541c99275SPeter Avalos 	siz = ep - bp;
172641c99275SPeter Avalos 
1727*ed775ee7SAntonio Huete Jimenez 	switch (GET_U_1(ni6->ni_type)) {
172841c99275SPeter Avalos 	case ICMP6_NI_QUERY:
172941c99275SPeter Avalos 		if (siz == sizeof(*dp) + 4) {
173041c99275SPeter Avalos 			/* KAME who-are-you */
1731*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" who-are-you request");
173241c99275SPeter Avalos 			break;
173341c99275SPeter Avalos 		}
1734*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(" node information query");
173541c99275SPeter Avalos 
1736*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_LEN(dp, sizeof(*ni6));
1737411677aeSAaron LI 		ni6 = (const struct icmp6_nodeinfo *)dp;
1738*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(" (");	/*)*/
1739*ed775ee7SAntonio Huete Jimenez 		switch (GET_BE_U_2(ni6->ni_qtype)) {
174041c99275SPeter Avalos 		case NI_QTYPE_NOOP:
1741*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("noop");
174241c99275SPeter Avalos 			break;
174341c99275SPeter Avalos 		case NI_QTYPE_SUPTYPES:
1744*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("supported qtypes");
1745*ed775ee7SAntonio Huete Jimenez 			i = GET_BE_U_2(ni6->ni_flags);
174641c99275SPeter Avalos 			if (i)
1747*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(" [%s]", (i & 0x01) ? "C" : "");
174841c99275SPeter Avalos 			break;
174941c99275SPeter Avalos 		case NI_QTYPE_FQDN:
1750*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("DNS name");
175141c99275SPeter Avalos 			break;
175241c99275SPeter Avalos 		case NI_QTYPE_NODEADDR:
1753*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("node addresses");
1754*ed775ee7SAntonio Huete Jimenez 			i = GET_BE_U_2(ni6->ni_flags);
175541c99275SPeter Avalos 			if (!i)
175641c99275SPeter Avalos 				break;
175741c99275SPeter Avalos 			/* NI_NODEADDR_FLAG_TRUNCATE undefined for query */
1758*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" [%s%s%s%s%s%s]",
175941c99275SPeter Avalos 			    (i & NI_NODEADDR_FLAG_ANYCAST) ? "a" : "",
176041c99275SPeter Avalos 			    (i & NI_NODEADDR_FLAG_GLOBAL) ? "G" : "",
176141c99275SPeter Avalos 			    (i & NI_NODEADDR_FLAG_SITELOCAL) ? "S" : "",
176241c99275SPeter Avalos 			    (i & NI_NODEADDR_FLAG_LINKLOCAL) ? "L" : "",
176341c99275SPeter Avalos 			    (i & NI_NODEADDR_FLAG_COMPAT) ? "C" : "",
1764*ed775ee7SAntonio Huete Jimenez 			    (i & NI_NODEADDR_FLAG_ALL) ? "A" : "");
176541c99275SPeter Avalos 			break;
176641c99275SPeter Avalos 		default:
1767*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("unknown");
176841c99275SPeter Avalos 			break;
176941c99275SPeter Avalos 		}
177041c99275SPeter Avalos 
1771*ed775ee7SAntonio Huete Jimenez 		if (GET_BE_U_2(ni6->ni_qtype) == NI_QTYPE_NOOP ||
1772*ed775ee7SAntonio Huete Jimenez 		    GET_BE_U_2(ni6->ni_qtype) == NI_QTYPE_SUPTYPES) {
177341c99275SPeter Avalos 			if (siz != sizeof(*ni6))
1774411677aeSAaron LI 				if (ndo->ndo_vflag)
1775*ed775ee7SAntonio Huete Jimenez 					ND_PRINT(", invalid len");
177641c99275SPeter Avalos 			/*(*/
1777*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(")");
177841c99275SPeter Avalos 			break;
177941c99275SPeter Avalos 		}
178041c99275SPeter Avalos 
178141c99275SPeter Avalos 
178241c99275SPeter Avalos 		/* XXX backward compat, icmp-name-lookup-03 */
178341c99275SPeter Avalos 		if (siz == sizeof(*ni6)) {
1784*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(", 03 draft");
178541c99275SPeter Avalos 			/*(*/
1786*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(")");
178741c99275SPeter Avalos 			break;
178841c99275SPeter Avalos 		}
178941c99275SPeter Avalos 
1790*ed775ee7SAntonio Huete Jimenez 		cp = (const u_char *)(ni6 + 1);
1791*ed775ee7SAntonio Huete Jimenez 		switch (GET_U_1(ni6->ni_code)) {
179241c99275SPeter Avalos 		case ICMP6_NI_SUBJ_IPV6:
1793*ed775ee7SAntonio Huete Jimenez 			if (!ND_TTEST_LEN(dp, sizeof(*ni6) + sizeof(nd_ipv6)))
179441c99275SPeter Avalos 				break;
1795*ed775ee7SAntonio Huete Jimenez 			if (siz != sizeof(*ni6) + sizeof(nd_ipv6)) {
1796411677aeSAaron LI 				if (ndo->ndo_vflag)
1797*ed775ee7SAntonio Huete Jimenez 					ND_PRINT(", invalid subject len");
179841c99275SPeter Avalos 				break;
179941c99275SPeter Avalos 			}
1800*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(", subject=%s",
1801*ed775ee7SAntonio Huete Jimenez                                   GET_IP6ADDR_STRING(cp));
180241c99275SPeter Avalos 			break;
180341c99275SPeter Avalos 		case ICMP6_NI_SUBJ_FQDN:
1804*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(", subject=DNS name");
1805*ed775ee7SAntonio Huete Jimenez 			if (GET_U_1(cp) == ep - cp - 1) {
180641c99275SPeter Avalos 				/* icmp-name-lookup-03, pascal string */
1807411677aeSAaron LI 				if (ndo->ndo_vflag)
1808*ed775ee7SAntonio Huete Jimenez 					ND_PRINT(", 03 draft");
180941c99275SPeter Avalos 				cp++;
1810*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(", \"");
181141c99275SPeter Avalos 				while (cp < ep) {
1812*ed775ee7SAntonio Huete Jimenez 					fn_print_char(ndo, GET_U_1(cp));
181341c99275SPeter Avalos 					cp++;
181441c99275SPeter Avalos 				}
1815*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("\"");
181641c99275SPeter Avalos 			} else
1817411677aeSAaron LI 				dnsname_print(ndo, cp, ep);
181841c99275SPeter Avalos 			break;
181941c99275SPeter Avalos 		case ICMP6_NI_SUBJ_IPV4:
1820*ed775ee7SAntonio Huete Jimenez 			if (!ND_TTEST_LEN(dp, sizeof(*ni6) + sizeof(nd_ipv4)))
182141c99275SPeter Avalos 				break;
1822*ed775ee7SAntonio Huete Jimenez 			if (siz != sizeof(*ni6) + sizeof(nd_ipv4)) {
1823411677aeSAaron LI 				if (ndo->ndo_vflag)
1824*ed775ee7SAntonio Huete Jimenez 					ND_PRINT(", invalid subject len");
182541c99275SPeter Avalos 				break;
182641c99275SPeter Avalos 			}
1827*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(", subject=%s",
1828*ed775ee7SAntonio Huete Jimenez                                   GET_IPADDR_STRING(cp));
182941c99275SPeter Avalos 			break;
183041c99275SPeter Avalos 		default:
1831*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(", unknown subject");
183241c99275SPeter Avalos 			break;
183341c99275SPeter Avalos 		}
183441c99275SPeter Avalos 
183541c99275SPeter Avalos 		/*(*/
1836*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(")");
183741c99275SPeter Avalos 		break;
183841c99275SPeter Avalos 
183941c99275SPeter Avalos 	case ICMP6_NI_REPLY:
1840*ed775ee7SAntonio Huete Jimenez 		if (icmp6len > siz)
1841*ed775ee7SAntonio Huete Jimenez 			goto trunc;
184241c99275SPeter Avalos 
184341c99275SPeter Avalos 		needcomma = 0;
184441c99275SPeter Avalos 
1845*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_LEN(dp, sizeof(*ni6));
1846411677aeSAaron LI 		ni6 = (const struct icmp6_nodeinfo *)dp;
1847*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(" node information reply");
1848*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(" (");	/*)*/
1849*ed775ee7SAntonio Huete Jimenez 		switch (GET_U_1(ni6->ni_code)) {
185041c99275SPeter Avalos 		case ICMP6_NI_SUCCESS:
1851411677aeSAaron LI 			if (ndo->ndo_vflag) {
1852*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("success");
185341c99275SPeter Avalos 				needcomma++;
185441c99275SPeter Avalos 			}
185541c99275SPeter Avalos 			break;
185641c99275SPeter Avalos 		case ICMP6_NI_REFUSED:
1857*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("refused");
185841c99275SPeter Avalos 			needcomma++;
185941c99275SPeter Avalos 			if (siz != sizeof(*ni6))
1860411677aeSAaron LI 				if (ndo->ndo_vflag)
1861*ed775ee7SAntonio Huete Jimenez 					ND_PRINT(", invalid length");
186241c99275SPeter Avalos 			break;
186341c99275SPeter Avalos 		case ICMP6_NI_UNKNOWN:
1864*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("unknown");
186541c99275SPeter Avalos 			needcomma++;
186641c99275SPeter Avalos 			if (siz != sizeof(*ni6))
1867411677aeSAaron LI 				if (ndo->ndo_vflag)
1868*ed775ee7SAntonio Huete Jimenez 					ND_PRINT(", invalid length");
186941c99275SPeter Avalos 			break;
187041c99275SPeter Avalos 		}
187141c99275SPeter Avalos 
1872*ed775ee7SAntonio Huete Jimenez 		if (GET_U_1(ni6->ni_code) != ICMP6_NI_SUCCESS) {
187341c99275SPeter Avalos 			/*(*/
1874*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(")");
187541c99275SPeter Avalos 			break;
187641c99275SPeter Avalos 		}
187741c99275SPeter Avalos 
1878*ed775ee7SAntonio Huete Jimenez 		switch (GET_BE_U_2(ni6->ni_qtype)) {
187941c99275SPeter Avalos 		case NI_QTYPE_NOOP:
188041c99275SPeter Avalos 			if (needcomma)
1881*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(", ");
1882*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("noop");
188341c99275SPeter Avalos 			if (siz != sizeof(*ni6))
1884411677aeSAaron LI 				if (ndo->ndo_vflag)
1885*ed775ee7SAntonio Huete Jimenez 					ND_PRINT(", invalid length");
188641c99275SPeter Avalos 			break;
188741c99275SPeter Avalos 		case NI_QTYPE_SUPTYPES:
188841c99275SPeter Avalos 			if (needcomma)
1889*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(", ");
1890*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("supported qtypes");
1891*ed775ee7SAntonio Huete Jimenez 			i = GET_BE_U_2(ni6->ni_flags);
189241c99275SPeter Avalos 			if (i)
1893*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(" [%s]", (i & 0x01) ? "C" : "");
189441c99275SPeter Avalos 			break;
189541c99275SPeter Avalos 		case NI_QTYPE_FQDN:
189641c99275SPeter Avalos 			if (needcomma)
1897*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(", ");
1898*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("DNS name");
189941c99275SPeter Avalos 			cp = (const u_char *)(ni6 + 1) + 4;
1900*ed775ee7SAntonio Huete Jimenez 			if (GET_U_1(cp) == ep - cp - 1) {
190141c99275SPeter Avalos 				/* icmp-name-lookup-03, pascal string */
1902411677aeSAaron LI 				if (ndo->ndo_vflag)
1903*ed775ee7SAntonio Huete Jimenez 					ND_PRINT(", 03 draft");
190441c99275SPeter Avalos 				cp++;
1905*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(", \"");
190641c99275SPeter Avalos 				while (cp < ep) {
1907*ed775ee7SAntonio Huete Jimenez 					fn_print_char(ndo, GET_U_1(cp));
190841c99275SPeter Avalos 					cp++;
190941c99275SPeter Avalos 				}
1910*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("\"");
191141c99275SPeter Avalos 			} else
1912411677aeSAaron LI 				dnsname_print(ndo, cp, ep);
1913*ed775ee7SAntonio Huete Jimenez 			if ((GET_BE_U_2(ni6->ni_flags) & 0x01) != 0)
1914*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(" [TTL=%u]", GET_BE_U_4(ni6 + 1));
191541c99275SPeter Avalos 			break;
191641c99275SPeter Avalos 		case NI_QTYPE_NODEADDR:
191741c99275SPeter Avalos 			if (needcomma)
1918*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(", ");
1919*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("node addresses");
192041c99275SPeter Avalos 			i = sizeof(*ni6);
192141c99275SPeter Avalos 			while (i < siz) {
1922*ed775ee7SAntonio Huete Jimenez 				if (i + sizeof(uint32_t) + sizeof(nd_ipv6) > siz)
192341c99275SPeter Avalos 					break;
1924*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(" %s(%u)",
1925*ed775ee7SAntonio Huete Jimenez 				    GET_IP6ADDR_STRING(bp + i + sizeof(uint32_t)),
1926*ed775ee7SAntonio Huete Jimenez 				    GET_BE_U_4(bp + i));
1927*ed775ee7SAntonio Huete Jimenez 				i += sizeof(uint32_t) + sizeof(nd_ipv6);
192841c99275SPeter Avalos 			}
1929*ed775ee7SAntonio Huete Jimenez 			i = GET_BE_U_2(ni6->ni_flags);
193041c99275SPeter Avalos 			if (!i)
193141c99275SPeter Avalos 				break;
1932*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" [%s%s%s%s%s%s%s]",
193341c99275SPeter Avalos                                   (i & NI_NODEADDR_FLAG_ANYCAST) ? "a" : "",
193441c99275SPeter Avalos                                   (i & NI_NODEADDR_FLAG_GLOBAL) ? "G" : "",
193541c99275SPeter Avalos                                   (i & NI_NODEADDR_FLAG_SITELOCAL) ? "S" : "",
193641c99275SPeter Avalos                                   (i & NI_NODEADDR_FLAG_LINKLOCAL) ? "L" : "",
193741c99275SPeter Avalos                                   (i & NI_NODEADDR_FLAG_COMPAT) ? "C" : "",
193841c99275SPeter Avalos                                   (i & NI_NODEADDR_FLAG_ALL) ? "A" : "",
1939*ed775ee7SAntonio Huete Jimenez                                   (i & NI_NODEADDR_FLAG_TRUNCATE) ? "T" : "");
194041c99275SPeter Avalos 			break;
194141c99275SPeter Avalos 		default:
194241c99275SPeter Avalos 			if (needcomma)
1943*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(", ");
1944*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("unknown");
194541c99275SPeter Avalos 			break;
194641c99275SPeter Avalos 		}
194741c99275SPeter Avalos 
194841c99275SPeter Avalos 		/*(*/
1949*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(")");
195041c99275SPeter Avalos 		break;
195141c99275SPeter Avalos 	}
195241c99275SPeter Avalos 	return;
195341c99275SPeter Avalos 
195441c99275SPeter Avalos trunc:
1955*ed775ee7SAntonio Huete Jimenez 	nd_print_trunc(ndo);
195641c99275SPeter Avalos }
195741c99275SPeter Avalos 
195841c99275SPeter Avalos static void
icmp6_rrenum_print(netdissect_options * ndo,const u_char * bp,const u_char * ep)1959411677aeSAaron LI icmp6_rrenum_print(netdissect_options *ndo, const u_char *bp, const u_char *ep)
196041c99275SPeter Avalos {
1961411677aeSAaron LI 	const struct icmp6_router_renum *rr6;
196241c99275SPeter Avalos 	const char *cp;
1963411677aeSAaron LI 	const struct rr_pco_match *match;
1964411677aeSAaron LI 	const struct rr_pco_use *use;
196541c99275SPeter Avalos 	char hbuf[NI_MAXHOST];
196641c99275SPeter Avalos 	int n;
196741c99275SPeter Avalos 
196841c99275SPeter Avalos 	if (ep < bp)
196941c99275SPeter Avalos 		return;
1970411677aeSAaron LI 	rr6 = (const struct icmp6_router_renum *)bp;
197141c99275SPeter Avalos 	cp = (const char *)(rr6 + 1);
197241c99275SPeter Avalos 
1973*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_4(rr6->rr_reserved);
1974*ed775ee7SAntonio Huete Jimenez 	switch (GET_U_1(rr6->rr_code)) {
197541c99275SPeter Avalos 	case ICMP6_ROUTER_RENUMBERING_COMMAND:
1976*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("router renum: command");
197741c99275SPeter Avalos 		break;
197841c99275SPeter Avalos 	case ICMP6_ROUTER_RENUMBERING_RESULT:
1979*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("router renum: result");
198041c99275SPeter Avalos 		break;
198141c99275SPeter Avalos 	case ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET:
1982*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("router renum: sequence number reset");
198341c99275SPeter Avalos 		break;
198441c99275SPeter Avalos 	default:
1985*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("router renum: code-#%u", GET_U_1(rr6->rr_code));
198641c99275SPeter Avalos 		break;
198741c99275SPeter Avalos 	}
198841c99275SPeter Avalos 
1989*ed775ee7SAntonio Huete Jimenez         ND_PRINT(", seq=%u", GET_BE_U_4(rr6->rr_seqnum));
199041c99275SPeter Avalos 
1991411677aeSAaron LI 	if (ndo->ndo_vflag) {
1992*ed775ee7SAntonio Huete Jimenez 		uint8_t rr_flags = GET_U_1(rr6->rr_flags);
1993*ed775ee7SAntonio Huete Jimenez #define F(x, y)	(rr_flags & (x) ? (y) : "")
1994*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[");	/*]*/
1995*ed775ee7SAntonio Huete Jimenez 		if (rr_flags) {
1996*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("%s%s%s%s%s,", F(ICMP6_RR_FLAGS_TEST, "T"),
199741c99275SPeter Avalos                                   F(ICMP6_RR_FLAGS_REQRESULT, "R"),
199841c99275SPeter Avalos                                   F(ICMP6_RR_FLAGS_FORCEAPPLY, "A"),
199941c99275SPeter Avalos                                   F(ICMP6_RR_FLAGS_SPECSITE, "S"),
2000*ed775ee7SAntonio Huete Jimenez                                   F(ICMP6_RR_FLAGS_PREVDONE, "P"));
200141c99275SPeter Avalos 		}
2002*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("seg=%u,", GET_U_1(rr6->rr_segnum));
2003*ed775ee7SAntonio Huete Jimenez                 ND_PRINT("maxdelay=%u", GET_BE_U_2(rr6->rr_maxdelay));
2004*ed775ee7SAntonio Huete Jimenez 		if (GET_BE_U_4(rr6->rr_reserved))
2005*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("rsvd=0x%x", GET_BE_U_4(rr6->rr_reserved));
200641c99275SPeter Avalos 		/*[*/
2007*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("]");
200841c99275SPeter Avalos #undef F
200941c99275SPeter Avalos 	}
201041c99275SPeter Avalos 
2011*ed775ee7SAntonio Huete Jimenez 	if (GET_U_1(rr6->rr_code) == ICMP6_ROUTER_RENUMBERING_COMMAND) {
2012411677aeSAaron LI 		match = (const struct rr_pco_match *)cp;
201341c99275SPeter Avalos 		cp = (const char *)(match + 1);
201441c99275SPeter Avalos 
2015*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_16(match->rpm_prefix);
201641c99275SPeter Avalos 
2017411677aeSAaron LI 		if (ndo->ndo_vflag > 1)
2018*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("\n\t");
201941c99275SPeter Avalos 		else
2020*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" ");
2021*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("match(");	/*)*/
2022*ed775ee7SAntonio Huete Jimenez 		switch (GET_U_1(match->rpm_code)) {
2023*ed775ee7SAntonio Huete Jimenez 		case RPM_PCO_ADD:	ND_PRINT("add"); break;
2024*ed775ee7SAntonio Huete Jimenez 		case RPM_PCO_CHANGE:	ND_PRINT("change"); break;
2025*ed775ee7SAntonio Huete Jimenez 		case RPM_PCO_SETGLOBAL:	ND_PRINT("setglobal"); break;
2026*ed775ee7SAntonio Huete Jimenez 		default:		ND_PRINT("#%u",
2027*ed775ee7SAntonio Huete Jimenez 						 GET_U_1(match->rpm_code)); break;
202841c99275SPeter Avalos 		}
202941c99275SPeter Avalos 
2030411677aeSAaron LI 		if (ndo->ndo_vflag) {
2031*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(",ord=%u", GET_U_1(match->rpm_ordinal));
2032*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(",min=%u", GET_U_1(match->rpm_minlen));
2033*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(",max=%u", GET_U_1(match->rpm_maxlen));
203441c99275SPeter Avalos 		}
2035*ed775ee7SAntonio Huete Jimenez 		if (addrtostr6(match->rpm_prefix, hbuf, sizeof(hbuf)))
2036*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(",%s/%u", hbuf, GET_U_1(match->rpm_matchlen));
203741c99275SPeter Avalos 		else
2038*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(",?/%u", GET_U_1(match->rpm_matchlen));
203941c99275SPeter Avalos 		/*(*/
2040*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(")");
204141c99275SPeter Avalos 
2042*ed775ee7SAntonio Huete Jimenez 		n = GET_U_1(match->rpm_len) - 3;
204341c99275SPeter Avalos 		if (n % 4)
204441c99275SPeter Avalos 			goto trunc;
204541c99275SPeter Avalos 		n /= 4;
204641c99275SPeter Avalos 		while (n-- > 0) {
2047411677aeSAaron LI 			use = (const struct rr_pco_use *)cp;
204841c99275SPeter Avalos 			cp = (const char *)(use + 1);
204941c99275SPeter Avalos 
2050*ed775ee7SAntonio Huete Jimenez 			ND_TCHECK_16(use->rpu_prefix);
205141c99275SPeter Avalos 
2052411677aeSAaron LI 			if (ndo->ndo_vflag > 1)
2053*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("\n\t");
205441c99275SPeter Avalos 			else
2055*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(" ");
2056*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("use(");	/*)*/
2057*ed775ee7SAntonio Huete Jimenez 			if (GET_U_1(use->rpu_flags)) {
2058*ed775ee7SAntonio Huete Jimenez #define F(x, y)	(GET_U_1(use->rpu_flags) & (x) ? (y) : "")
2059*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("%s%s,",
206041c99275SPeter Avalos                                           F(ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME, "V"),
2061*ed775ee7SAntonio Huete Jimenez                                           F(ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME, "P"));
206241c99275SPeter Avalos #undef F
206341c99275SPeter Avalos 			}
2064411677aeSAaron LI 			if (ndo->ndo_vflag) {
2065*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("mask=0x%x,",
2066*ed775ee7SAntonio Huete Jimenez 					 GET_U_1(use->rpu_ramask));
2067*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("raflags=0x%x,",
2068*ed775ee7SAntonio Huete Jimenez 					 GET_U_1(use->rpu_raflags));
2069*ed775ee7SAntonio Huete Jimenez 				if (GET_BE_U_4(use->rpu_vltime) == 0xffffffff)
2070*ed775ee7SAntonio Huete Jimenez 					ND_PRINT("vltime=infty,");
207141c99275SPeter Avalos 				else
2072*ed775ee7SAntonio Huete Jimenez 					ND_PRINT("vltime=%u,",
2073*ed775ee7SAntonio Huete Jimenez                                                   GET_BE_U_4(use->rpu_vltime));
2074*ed775ee7SAntonio Huete Jimenez 				if (GET_BE_U_4(use->rpu_pltime) == 0xffffffff)
2075*ed775ee7SAntonio Huete Jimenez 					ND_PRINT("pltime=infty,");
207641c99275SPeter Avalos 				else
2077*ed775ee7SAntonio Huete Jimenez 					ND_PRINT("pltime=%u,",
2078*ed775ee7SAntonio Huete Jimenez                                                   GET_BE_U_4(use->rpu_pltime));
207941c99275SPeter Avalos 			}
2080*ed775ee7SAntonio Huete Jimenez 			if (addrtostr6(use->rpu_prefix, hbuf, sizeof(hbuf)))
2081*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("%s/%u/%u", hbuf,
2082*ed775ee7SAntonio Huete Jimenez                                           GET_U_1(use->rpu_uselen),
2083*ed775ee7SAntonio Huete Jimenez                                           GET_U_1(use->rpu_keeplen));
208441c99275SPeter Avalos 			else
2085*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("?/%u/%u", GET_U_1(use->rpu_uselen),
2086*ed775ee7SAntonio Huete Jimenez                                           GET_U_1(use->rpu_keeplen));
208741c99275SPeter Avalos 			/*(*/
2088*ed775ee7SAntonio Huete Jimenez                         ND_PRINT(")");
208941c99275SPeter Avalos 		}
209041c99275SPeter Avalos 	}
209141c99275SPeter Avalos 
209241c99275SPeter Avalos 	return;
209341c99275SPeter Avalos 
209441c99275SPeter Avalos trunc:
2095*ed775ee7SAntonio Huete Jimenez 	nd_print_trunc(ndo);
209641c99275SPeter Avalos }
2097