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