4 * Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that: (1) source code distributions
9 * retain the above copyright notice and this paragraph in its entirety, (2)
10 * distributions including binary code include the above copyright notice and
11 * this paragraph in its entirety in the documentation or other materials
12 * provided with the distribution, and (3) all advertising materials mentioning
13 * features or use of this software display the following acknowledgement:
14 * ``This product includes software developed by the University of California,
15 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
16 * the University nor the names of its contributors may be used to endorse
17 * or promote products derived from this software without specific prior
19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
24 #include <sys/cdefs.h>
27 static const char rcsid
[] _U_
=
28 "@(#) Header: /tcpdump/master/tcpdump/print-icmp6.c,v 1.79.2.6 2005/09/05 09:29:28 guy Exp";
30 __RCSID("$NetBSD: tcpdump2rcsid.ex,v 1.1 2001/06/25 20:09:58 itojun Exp $");
40 #include <tcpdump-stdinc.h>
45 #include "interface.h"
46 #include "addrtoname.h"
56 static const char *get_rtpref(u_int
);
57 static const char *get_lifetime(u_int32_t
);
58 static void print_lladdr(const u_char
*, size_t);
59 static void icmp6_opt_print(const u_char
*, int);
60 static void mld6_print(const u_char
*);
61 static void mldv2_report_print(const u_char
*, u_int
);
62 static void mldv2_query_print(const u_char
*, u_int
);
63 static struct udphdr
*get_upperlayer(u_char
*, u_int
*);
64 static void dnsname_print(const u_char
*, const u_char
*);
65 static void icmp6_nodeinfo_print(u_int
, const u_char
*, const u_char
*);
66 static void icmp6_rrenum_print(const u_char
*, const u_char
*);
69 #define abs(a) ((0 < (a)) ? (a) : -(a))
72 static struct tok icmp6_type_values
[] = {
73 { ICMP6_DST_UNREACH
, "destination unreachable"},
74 { ICMP6_PACKET_TOO_BIG
, "packet too big"},
75 { ICMP6_TIME_EXCEEDED
, "time exceeded in-transit"},
76 { ICMP6_PARAM_PROB
, "parameter problem"},
77 { ICMP6_ECHO_REQUEST
, "echo request"},
78 { ICMP6_ECHO_REPLY
, "echo reply"},
79 { MLD6_LISTENER_QUERY
, "multicast listener query"},
80 { MLD6_LISTENER_REPORT
, "multicast listener report"},
81 { MLD6_LISTENER_DONE
, "multicast listener done"},
82 { ND_ROUTER_SOLICIT
, "router solicitation"},
83 { ND_ROUTER_ADVERT
, "router advertisement"},
84 { ND_NEIGHBOR_SOLICIT
, "neighbor solicitation"},
85 { ND_NEIGHBOR_ADVERT
, "neighbor advertisement"},
86 { ND_REDIRECT
, "redirect"},
87 { ICMP6_ROUTER_RENUMBERING
, "router renumbering"},
88 { IND_SOLICIT
, "inverse neighbor solicitation"},
89 { IND_ADVERT
, "inverse neighbor advertisement"},
90 { MLDV2_LISTENER_REPORT
, "multicast listener report v2"},
91 { ICMP6_HADISCOV_REQUEST
, "ha discovery request"},
92 { ICMP6_HADISCOV_REPLY
, "ha discovery reply"},
93 { ICMP6_MOBILEPREFIX_SOLICIT
, "mobile router solicitation"},
94 { ICMP6_MOBILEPREFIX_ADVERT
, "mobile router advertisement"},
95 { ICMP6_WRUREQUEST
, "who-are-you request"},
96 { ICMP6_WRUREPLY
, "who-are-you reply"},
97 { ICMP6_NI_QUERY
, "node information query"},
98 { ICMP6_NI_REPLY
, "node information reply"},
99 { MLD6_MTRACE
, "mtrace message"},
100 { MLD6_MTRACE_RESP
, "mtrace response"},
104 static struct tok icmp6_dst_unreach_code_values
[] = {
105 { ICMP6_DST_UNREACH_NOROUTE
, "unreachable route" },
106 { ICMP6_DST_UNREACH_ADMIN
, " unreachable prohibited"},
107 { ICMP6_DST_UNREACH_BEYONDSCOPE
, "beyond scope"},
108 { ICMP6_DST_UNREACH_ADDR
, "unreachable address"},
109 { ICMP6_DST_UNREACH_NOPORT
, "unreachable port"},
113 static struct tok icmp6_opt_pi_flag_values
[] = {
114 { ND_OPT_PI_FLAG_ONLINK
, "onlink" },
115 { ND_OPT_PI_FLAG_AUTO
, "auto" },
116 { ND_OPT_PI_FLAG_ROUTER
, "router" },
120 static struct tok icmp6_opt_ra_flag_values
[] = {
121 { ND_RA_FLAG_MANAGED
, "managed" },
122 { ND_RA_FLAG_OTHER
, "other stateful"},
123 { ND_RA_FLAG_HOME_AGENT
, "home agent"},
127 static struct tok icmp6_nd_na_flag_values
[] = {
128 { ND_NA_FLAG_ROUTER
, "router" },
129 { ND_NA_FLAG_SOLICITED
, "solicited" },
130 { ND_NA_FLAG_OVERRIDE
, "override" },
135 static struct tok icmp6_opt_values
[] = {
136 { ND_OPT_SOURCE_LINKADDR
, "source link-address"},
137 { ND_OPT_TARGET_LINKADDR
, "destination link-address"},
138 { ND_OPT_PREFIX_INFORMATION
, "prefix info"},
139 { ND_OPT_REDIRECTED_HEADER
, "redirected header"},
140 { ND_OPT_MTU
, "mtu"},
141 { ND_OPT_ADVINTERVAL
, "advertisement interval"},
142 { ND_OPT_HOMEAGENT_INFO
, "homeagent information"},
143 { ND_OPT_ROUTE_INFO
, "route info"},
147 /* mldv2 report types */
148 static struct tok mldv2report2str
[] = {
161 static const char *rtpref_str
[] = {
168 return rtpref_str
[((v
& ND_RA_FLAG_RTPREF_MASK
) >> 3) & 0xff];
172 get_lifetime(u_int32_t v
)
176 if (v
== (u_int32_t
)~0UL)
179 snprintf(buf
, sizeof(buf
), "%u", v
);
185 print_lladdr(const u_int8_t
*p
, size_t l
)
187 const u_int8_t
*ep
, *q
;
191 while (l
> 0 && q
< ep
) {
194 printf("%02x", *q
++);
199 static int icmp6_cksum(const struct ip6_hdr
*ip6
, const struct icmp6_hdr
*icp
,
203 register const u_int16_t
*sp
;
207 struct in6_addr ph_src
;
208 struct in6_addr ph_dst
;
217 memset(&phu
, 0, sizeof(phu
));
218 phu
.ph
.ph_src
= ip6
->ip6_src
;
219 phu
.ph
.ph_dst
= ip6
->ip6_dst
;
220 phu
.ph
.ph_len
= htonl(len
);
221 phu
.ph
.ph_nxt
= IPPROTO_ICMPV6
;
224 for (i
= 0; i
< sizeof(phu
.pa
) / sizeof(phu
.pa
[0]); i
++)
227 sp
= (const u_int16_t
*)icp
;
229 for (i
= 0; i
< (len
& ~1); i
+= 2)
233 sum
+= htons((*(const u_int8_t
*)sp
) << 8);
236 sum
= (sum
& 0xffff) + (sum
>> 16);
243 icmp6_print(const u_char
*bp
, u_int length
, const u_char
*bp2
, int fragmented
)
245 const struct icmp6_hdr
*dp
;
246 const struct ip6_hdr
*ip
;
247 const struct ip6_hdr
*oip
;
248 const struct udphdr
*ouh
;
253 dp
= (struct icmp6_hdr
*)bp
;
254 ip
= (struct ip6_hdr
*)bp2
;
255 oip
= (struct ip6_hdr
*)(dp
+ 1);
256 /* 'ep' points to the end of available data. */
259 TCHECK(dp
->icmp6_cksum
);
261 if (vflag
&& !fragmented
) {
262 int sum
= dp
->icmp6_cksum
;
264 if (TTEST2(bp
[0], length
)) {
265 sum
= icmp6_cksum(ip
, dp
, length
);
267 (void)printf("[bad icmp6 cksum %x!] ", sum
);
269 (void)printf("[icmp6 sum ok] ");
273 printf("ICMP6, %s", tok2str(icmp6_type_values
,"unknown icmp6 type (%u)",dp
->icmp6_type
));
275 /* display cosmetics: print the packet length for printer that use the vflag now */
276 if (vflag
&& (dp
->icmp6_type
==
279 ND_NEIGHBOR_ADVERT
||
280 ND_NEIGHBOR_SOLICIT
||
282 ICMP6_HADISCOV_REPLY
||
283 ICMP6_MOBILEPREFIX_ADVERT
))
284 printf(", length %u", length
);
286 switch (dp
->icmp6_type
) {
287 case ICMP6_DST_UNREACH
:
288 TCHECK(oip
->ip6_dst
);
289 printf(", %s", tok2str(icmp6_dst_unreach_code_values
,"unknown unreach code (%u)",dp
->icmp6_code
));
290 switch (dp
->icmp6_code
) {
292 case ICMP6_DST_UNREACH_NOROUTE
: /* fall through */
293 case ICMP6_DST_UNREACH_ADMIN
:
294 case ICMP6_DST_UNREACH_ADDR
:
295 printf(" %s",ip6addr_string(&oip
->ip6_dst
));
297 case ICMP6_DST_UNREACH_BEYONDSCOPE
:
298 printf(" %s, source address %s",
299 ip6addr_string(&oip
->ip6_dst
),
300 ip6addr_string(&oip
->ip6_src
));
302 case ICMP6_DST_UNREACH_NOPORT
:
303 if ((ouh
= get_upperlayer((u_char
*)oip
, &prot
))
307 dport
= EXTRACT_16BITS(&ouh
->uh_dport
);
310 printf(", %s tcp port %s",
311 ip6addr_string(&oip
->ip6_dst
),
312 tcpport_string(dport
));
315 printf(", %s udp port %s",
316 ip6addr_string(&oip
->ip6_dst
),
317 udpport_string(dport
));
320 printf(", %s protocol %d port %d unreachable",
321 ip6addr_string(&oip
->ip6_dst
),
322 oip
->ip6_nxt
, dport
);
328 print_unknown_data(bp
,"\n\t",length
);
334 case ICMP6_PACKET_TOO_BIG
:
335 TCHECK(dp
->icmp6_mtu
);
336 printf(", mtu %u", EXTRACT_32BITS(&dp
->icmp6_mtu
));
338 case ICMP6_TIME_EXCEEDED
:
339 TCHECK(oip
->ip6_dst
);
340 switch (dp
->icmp6_code
) {
341 case ICMP6_TIME_EXCEED_TRANSIT
:
343 ip6addr_string(&oip
->ip6_dst
));
345 case ICMP6_TIME_EXCEED_REASSEMBLY
:
346 printf(" (reassembly)");
349 printf(", unknown code (%u)", dp
->icmp6_code
);
353 case ICMP6_PARAM_PROB
:
354 TCHECK(oip
->ip6_dst
);
355 switch (dp
->icmp6_code
) {
356 case ICMP6_PARAMPROB_HEADER
:
357 printf(", errorneous - octet %u", EXTRACT_32BITS(&dp
->icmp6_pptr
));
359 case ICMP6_PARAMPROB_NEXTHEADER
:
360 printf(", next header - octet %u", EXTRACT_32BITS(&dp
->icmp6_pptr
));
362 case ICMP6_PARAMPROB_OPTION
:
363 printf(", option - octet %u", EXTRACT_32BITS(&dp
->icmp6_pptr
));
371 case ICMP6_ECHO_REQUEST
:
372 case ICMP6_ECHO_REPLY
:
373 TCHECK(dp
->icmp6_seq
);
374 printf(", seq %u", EXTRACT_16BITS(&dp
->icmp6_seq
));
376 case ICMP6_MEMBERSHIP_QUERY
:
377 if (length
== MLD_MINLEN
) {
378 mld6_print((const u_char
*)dp
);
379 } else if (length
>= MLDV2_MINLEN
) {
381 mldv2_query_print((const u_char
*)dp
, length
);
383 printf(" unknown-version (len %u) ", length
);
386 case ICMP6_MEMBERSHIP_REPORT
:
387 mld6_print((const u_char
*)dp
);
389 case ICMP6_MEMBERSHIP_REDUCTION
:
390 mld6_print((const u_char
*)dp
);
392 case ND_ROUTER_SOLICIT
:
395 icmp6_opt_print((const u_char
*)dp
+ RTSOLLEN
,
399 case ND_ROUTER_ADVERT
:
402 struct nd_router_advert
*p
;
404 p
= (struct nd_router_advert
*)dp
;
405 TCHECK(p
->nd_ra_retransmit
);
406 printf("\n\thop limit %u, Flags [%s]" \
407 ", pref %s, router lifetime %us, reachable time %us, retrans time %us",
408 (u_int
)p
->nd_ra_curhoplimit
,
409 bittok2str(icmp6_opt_ra_flag_values
,"none",(p
->nd_ra_flags_reserved
)),
410 get_rtpref(p
->nd_ra_flags_reserved
),
411 EXTRACT_16BITS(&p
->nd_ra_router_lifetime
),
412 EXTRACT_32BITS(&p
->nd_ra_reachable
),
413 EXTRACT_32BITS(&p
->nd_ra_retransmit
));
415 icmp6_opt_print((const u_char
*)dp
+ RTADVLEN
,
419 case ND_NEIGHBOR_SOLICIT
:
421 struct nd_neighbor_solicit
*p
;
422 p
= (struct nd_neighbor_solicit
*)dp
;
423 TCHECK(p
->nd_ns_target
);
424 printf(", who has %s", ip6addr_string(&p
->nd_ns_target
));
427 icmp6_opt_print((const u_char
*)dp
+ NDSOLLEN
,
432 case ND_NEIGHBOR_ADVERT
:
434 struct nd_neighbor_advert
*p
;
436 p
= (struct nd_neighbor_advert
*)dp
;
437 TCHECK(p
->nd_na_target
);
438 printf(", tgt is %s",
439 ip6addr_string(&p
->nd_na_target
));
441 printf(", Flags [%s]",
442 bittok2str(icmp6_nd_na_flag_values
,
444 EXTRACT_32BITS(&p
->nd_na_flags_reserved
)));
446 icmp6_opt_print((const u_char
*)dp
+ NDADVLEN
,
453 #define RDR(i) ((struct nd_redirect *)(i))
454 TCHECK(RDR(dp
)->nd_rd_dst
);
455 printf(", %s", getname6((const u_char
*)&RDR(dp
)->nd_rd_dst
));
456 TCHECK(RDR(dp
)->nd_rd_target
);
458 getname6((const u_char
*)&RDR(dp
)->nd_rd_target
));
459 #define REDIRECTLEN 40
461 icmp6_opt_print((const u_char
*)dp
+ REDIRECTLEN
,
462 length
- REDIRECTLEN
);
467 case ICMP6_ROUTER_RENUMBERING
:
468 icmp6_rrenum_print(bp
, ep
);
472 icmp6_nodeinfo_print(length
, bp
, ep
);
477 case ICMP6_V2_MEMBERSHIP_REPORT
:
478 mldv2_report_print((const u_char
*) dp
, length
);
480 case ICMP6_MOBILEPREFIX_SOLICIT
: /* fall through */
481 case ICMP6_HADISCOV_REQUEST
:
482 TCHECK(dp
->icmp6_data16
[0]);
483 printf(", id 0x%04x", EXTRACT_16BITS(&dp
->icmp6_data16
[0]));
485 case ICMP6_HADISCOV_REPLY
:
487 struct in6_addr
*in6
;
490 TCHECK(dp
->icmp6_data16
[0]);
491 printf(", id 0x%04x", EXTRACT_16BITS(&dp
->icmp6_data16
[0]));
492 cp
= (u_char
*)dp
+ length
;
493 in6
= (struct in6_addr
*)(dp
+ 1);
494 for (; (u_char
*)in6
< cp
; in6
++) {
496 printf(", %s", ip6addr_string(in6
));
500 case ICMP6_MOBILEPREFIX_ADVERT
:
502 TCHECK(dp
->icmp6_data16
[0]);
503 printf(", id 0x%04x", EXTRACT_16BITS(&dp
->icmp6_data16
[0]));
504 if (dp
->icmp6_data16
[1] & 0xc0)
506 if (dp
->icmp6_data16
[1] & 0x80)
508 if (dp
->icmp6_data16
[1] & 0x40)
511 icmp6_opt_print((const u_char
*)dp
+ MPADVLEN
,
516 printf(", length %u", length
);
518 print_unknown_data(bp
,"\n\t", length
);
522 printf(", length %u", length
);
525 fputs("[|icmp6]", stdout
);
528 static struct udphdr
*
529 get_upperlayer(u_char
*bp
, u_int
*prot
)
532 struct ip6_hdr
*ip6
= (struct ip6_hdr
*)bp
;
535 struct ip6_frag
*fragh
;
540 /* 'ep' points to the end of available data. */
543 if (!TTEST(ip6
->ip6_nxt
))
547 hlen
= sizeof(struct ip6_hdr
);
555 uh
= (struct udphdr
*)bp
;
556 if (TTEST(uh
->uh_dport
)) {
564 case IPPROTO_HOPOPTS
:
565 case IPPROTO_DSTOPTS
:
566 case IPPROTO_ROUTING
:
567 hbh
= (struct ip6_hbh
*)bp
;
568 if (!TTEST(hbh
->ip6h_len
))
571 hlen
= (hbh
->ip6h_len
+ 1) << 3;
574 case IPPROTO_FRAGMENT
: /* this should be odd, but try anyway */
575 fragh
= (struct ip6_frag
*)bp
;
576 if (!TTEST(fragh
->ip6f_offlg
))
578 /* fragments with non-zero offset are meaningless */
579 if ((EXTRACT_16BITS(&fragh
->ip6f_offlg
) & IP6F_OFF_MASK
) != 0)
581 nh
= fragh
->ip6f_nxt
;
582 hlen
= sizeof(struct ip6_frag
);
586 ah
= (struct ah
*)bp
;
587 if (!TTEST(ah
->ah_len
))
590 hlen
= (ah
->ah_len
+ 2) << 2;
593 default: /* unknown or undecodable header */
594 *prot
= nh
; /* meaningless, but set here anyway */
599 return(NULL
); /* should be notreached, though */
603 icmp6_opt_print(const u_char
*bp
, int resid
)
605 const struct nd_opt_hdr
*op
;
606 const struct nd_opt_hdr
*opl
; /* why there's no struct? */
607 const struct nd_opt_prefix_info
*opp
;
608 const struct icmp6_opts_redirect
*opr
;
609 const struct nd_opt_mtu
*opm
;
610 const struct nd_opt_advinterval
*opa
;
611 const struct nd_opt_homeagent_info
*oph
;
612 const struct nd_opt_route_info
*opri
;
613 const u_char
*cp
, *ep
;
614 struct in6_addr in6
, *in6p
;
617 #define ECHECK(var) if ((u_char *)&(var) > ep - sizeof(var)) return
620 /* 'ep' points to the end of available data. */
624 op
= (struct nd_opt_hdr
*)cp
;
626 ECHECK(op
->nd_opt_len
);
629 if (op
->nd_opt_len
== 0)
631 if (cp
+ (op
->nd_opt_len
<< 3) > ep
)
634 printf("\n\t %s option (%u), length %u (%u): ",
635 tok2str(icmp6_opt_values
, "unknown", op
->nd_opt_type
),
640 switch (op
->nd_opt_type
) {
641 case ND_OPT_SOURCE_LINKADDR
:
642 opl
= (struct nd_opt_hdr
*)op
;
643 l
= (op
->nd_opt_len
<< 3) - 2;
644 print_lladdr(cp
+ 2, l
);
646 case ND_OPT_TARGET_LINKADDR
:
647 opl
= (struct nd_opt_hdr
*)op
;
648 l
= (op
->nd_opt_len
<< 3) - 2;
649 print_lladdr(cp
+ 2, l
);
651 case ND_OPT_PREFIX_INFORMATION
:
652 opp
= (struct nd_opt_prefix_info
*)op
;
653 TCHECK(opp
->nd_opt_pi_prefix
);
654 printf("%s/%u%s, Flags [%s], valid time %ss",
655 ip6addr_string(&opp
->nd_opt_pi_prefix
),
656 opp
->nd_opt_pi_prefix_len
,
657 (op
->nd_opt_len
!= 4) ? "badlen" : "",
658 bittok2str(icmp6_opt_pi_flag_values
, "none", opp
->nd_opt_pi_flags_reserved
),
659 get_lifetime(EXTRACT_32BITS(&opp
->nd_opt_pi_valid_time
)));
660 printf(", pref. time %ss", get_lifetime(EXTRACT_32BITS(&opp
->nd_opt_pi_preferred_time
)));
662 case ND_OPT_REDIRECTED_HEADER
:
663 opr
= (struct icmp6_opts_redirect
*)op
;
664 print_unknown_data(bp
,"\n\t ",op
->nd_opt_len
<<3);
668 opm
= (struct nd_opt_mtu
*)op
;
669 TCHECK(opm
->nd_opt_mtu_mtu
);
671 EXTRACT_32BITS(&opm
->nd_opt_mtu_mtu
),
672 (op
->nd_opt_len
!= 1) ? "bad option length" : "" );
674 case ND_OPT_ADVINTERVAL
:
675 opa
= (struct nd_opt_advinterval
*)op
;
676 TCHECK(opa
->nd_opt_adv_interval
);
677 printf(" %us", EXTRACT_32BITS(&opa
->nd_opt_adv_interval
));
679 case ND_OPT_HOMEAGENT_INFO
:
680 oph
= (struct nd_opt_homeagent_info
*)op
;
681 TCHECK(oph
->nd_opt_hai_lifetime
);
682 printf(" preference %u, lifetime %u",
683 EXTRACT_16BITS(&oph
->nd_opt_hai_preference
),
684 EXTRACT_16BITS(&oph
->nd_opt_hai_lifetime
));
686 case ND_OPT_ROUTE_INFO
:
687 opri
= (struct nd_opt_route_info
*)op
;
688 TCHECK(opri
->nd_opt_rti_lifetime
);
689 memset(&in6
, 0, sizeof(in6
));
690 in6p
= (struct in6_addr
*)(opri
+ 1);
691 switch (op
->nd_opt_len
) {
696 memcpy(&in6
, opri
+ 1, 8);
700 memcpy(&in6
, opri
+ 1, sizeof(in6
));
705 printf(" %s/%u", ip6addr_string(&in6
),
706 opri
->nd_opt_rti_prefixlen
);
707 printf(", pref=%s", get_rtpref(opri
->nd_opt_rti_flags
));
708 printf(", lifetime=%s",
709 get_lifetime(EXTRACT_32BITS(&opri
->nd_opt_rti_lifetime
)));
713 print_unknown_data(cp
+2,"\n\t ", (op
->nd_opt_len
<< 3) - 2); /* skip option header */
718 /* do we want to see an additional hexdump ? */
720 print_unknown_data(cp
+2,"\n\t ", (op
->nd_opt_len
<< 3) - 2); /* skip option header */
722 cp
+= op
->nd_opt_len
<< 3;
723 resid
-= op
->nd_opt_len
<< 3;
728 fputs("[ndp opt]", stdout
);
734 mld6_print(const u_char
*bp
)
736 struct mld6_hdr
*mp
= (struct mld6_hdr
*)bp
;
739 /* 'ep' points to the end of available data. */
742 if ((u_char
*)mp
+ sizeof(*mp
) > ep
)
745 printf("max resp delay: %d ", EXTRACT_16BITS(&mp
->mld6_maxdelay
));
746 printf("addr: %s", ip6addr_string(&mp
->mld6_addr
));
750 mldv2_report_print(const u_char
*bp
, u_int len
)
752 struct icmp6_hdr
*icp
= (struct icmp6_hdr
*) bp
;
753 u_int group
, nsrcs
, ngroups
;
756 /* Minimum len is 8 */
758 printf(" [invalid len %d]", len
);
762 TCHECK(icp
->icmp6_data16
[1]);
763 ngroups
= ntohs(icp
->icmp6_data16
[1]);
764 printf(", %d group record(s)", ngroups
);
766 /* Print the group records */
768 for (i
= 0; i
< ngroups
; i
++) {
769 /* type(1) + auxlen(1) + numsrc(2) + grp(16) */
770 if (len
< group
+ 20) {
771 printf(" [invalid number of groups]");
774 TCHECK2(bp
[group
+ 4], sizeof(struct in6_addr
));
775 printf(" [gaddr %s", ip6addr_string(&bp
[group
+ 4]));
776 printf(" %s", tok2str(mldv2report2str
, " [v2-report-#%d]",
778 nsrcs
= (bp
[group
+ 2] << 8) + bp
[group
+ 3];
779 /* Check the number of sources and print them */
780 if (len
< group
+ 20 + (nsrcs
* sizeof(struct in6_addr
))) {
781 printf(" [invalid number of sources %d]", nsrcs
);
785 printf(", %d source(s)", nsrcs
);
787 /* Print the sources */
789 for (j
= 0; j
< nsrcs
; j
++) {
790 TCHECK2(bp
[group
+ 20 + j
* sizeof(struct in6_addr
)],
791 sizeof(struct in6_addr
));
792 printf(" %s", ip6addr_string(&bp
[group
+ 20 + j
* sizeof(struct in6_addr
)]));
796 /* Next group record */
797 group
+= 20 + nsrcs
* sizeof(struct in6_addr
);
803 (void)printf("[|icmp6]");
808 mldv2_query_print(const u_char
*bp
, u_int len
)
810 struct icmp6_hdr
*icp
= (struct icmp6_hdr
*) bp
;
816 /* Minimum len is 28 */
818 printf(" [invalid len %d]", len
);
821 TCHECK(icp
->icmp6_data16
[0]);
822 mrc
= ntohs(icp
->icmp6_data16
[0]);
826 mrt
= ((mrc
& 0x0fff) | 0x1000) << (((mrc
& 0x7000) >> 12) + 3);
829 (void)printf(" [max resp delay=%d]", mrt
);
831 TCHECK2(bp
[8], sizeof(struct in6_addr
));
832 printf(" [gaddr %s", ip6addr_string(&bp
[8]));
840 printf(" robustness=%d", bp
[24] & 0x07);
845 qqi
= ((bp
[25] & 0x0f) | 0x10) << (((bp
[25] & 0x70) >> 4) + 3);
847 printf(" qqi=%d", qqi
);
851 nsrcs
= ntohs(*(u_short
*)&bp
[26]);
853 if (len
< 28 + nsrcs
* sizeof(struct in6_addr
))
854 printf(" [invalid number of sources]");
855 else if (vflag
> 1) {
857 for (i
= 0; i
< nsrcs
; i
++) {
858 TCHECK2(bp
[28 + i
* sizeof(struct in6_addr
)],
859 sizeof(struct in6_addr
));
860 printf(" %s", ip6addr_string(&bp
[28 + i
* sizeof(struct in6_addr
)]));
864 printf(", %d source(s)", nsrcs
);
869 (void)printf("[|icmp6]");
874 dnsname_print(const u_char
*cp
, const u_char
*ep
)
878 /* DNS name decoding - no decompression */
887 while (i
-- && cp
< ep
) {
891 if (cp
+ 1 < ep
&& *cp
)
897 } else if (cp
+ 1 == ep
&& *cp
== '\0') {
910 icmp6_nodeinfo_print(u_int icmp6len
, const u_char
*bp
, const u_char
*ep
)
912 struct icmp6_nodeinfo
*ni6
;
913 struct icmp6_hdr
*dp
;
920 dp
= (struct icmp6_hdr
*)bp
;
921 ni6
= (struct icmp6_nodeinfo
*)bp
;
924 switch (ni6
->ni_type
) {
926 if (siz
== sizeof(*dp
) + 4) {
927 /* KAME who-are-you */
928 printf(" who-are-you request");
931 printf(" node information query");
933 TCHECK2(*dp
, sizeof(*ni6
));
934 ni6
= (struct icmp6_nodeinfo
*)dp
;
936 switch (EXTRACT_16BITS(&ni6
->ni_qtype
)) {
940 case NI_QTYPE_SUPTYPES
:
941 printf("supported qtypes");
942 i
= EXTRACT_16BITS(&ni6
->ni_flags
);
944 printf(" [%s]", (i
& 0x01) ? "C" : "");
950 case NI_QTYPE_NODEADDR
:
951 printf("node addresses");
955 /* NI_NODEADDR_FLAG_TRUNCATE undefined for query */
956 printf(" [%s%s%s%s%s%s]",
957 (i
& NI_NODEADDR_FLAG_ANYCAST
) ? "a" : "",
958 (i
& NI_NODEADDR_FLAG_GLOBAL
) ? "G" : "",
959 (i
& NI_NODEADDR_FLAG_SITELOCAL
) ? "S" : "",
960 (i
& NI_NODEADDR_FLAG_LINKLOCAL
) ? "L" : "",
961 (i
& NI_NODEADDR_FLAG_COMPAT
) ? "C" : "",
962 (i
& NI_NODEADDR_FLAG_ALL
) ? "A" : "");
969 if (ni6
->ni_qtype
== NI_QTYPE_NOOP
||
970 ni6
->ni_qtype
== NI_QTYPE_SUPTYPES
) {
971 if (siz
!= sizeof(*ni6
))
973 printf(", invalid len");
980 /* XXX backward compat, icmp-name-lookup-03 */
981 if (siz
== sizeof(*ni6
)) {
982 printf(", 03 draft");
988 switch (ni6
->ni_code
) {
989 case ICMP6_NI_SUBJ_IPV6
:
991 sizeof(*ni6
) + sizeof(struct in6_addr
)))
993 if (siz
!= sizeof(*ni6
) + sizeof(struct in6_addr
)) {
995 printf(", invalid subject len");
998 printf(", subject=%s",
999 getname6((const u_char
*)(ni6
+ 1)));
1001 case ICMP6_NI_SUBJ_FQDN
:
1002 printf(", subject=DNS name");
1003 cp
= (const u_char
*)(ni6
+ 1);
1004 if (cp
[0] == ep
- cp
- 1) {
1005 /* icmp-name-lookup-03, pascal string */
1007 printf(", 03 draft");
1016 dnsname_print(cp
, ep
);
1018 case ICMP6_NI_SUBJ_IPV4
:
1019 if (!TTEST2(*dp
, sizeof(*ni6
) + sizeof(struct in_addr
)))
1021 if (siz
!= sizeof(*ni6
) + sizeof(struct in_addr
)) {
1023 printf(", invalid subject len");
1026 printf(", subject=%s",
1027 getname((const u_char
*)(ni6
+ 1)));
1030 printf(", unknown subject");
1038 case ICMP6_NI_REPLY
:
1039 if (icmp6len
> siz
) {
1040 printf("[|icmp6: node information reply]");
1046 ni6
= (struct icmp6_nodeinfo
*)dp
;
1047 printf(" node information reply");
1049 switch (ni6
->ni_code
) {
1050 case ICMP6_NI_SUCCESS
:
1056 case ICMP6_NI_REFUSED
:
1059 if (siz
!= sizeof(*ni6
))
1061 printf(", invalid length");
1063 case ICMP6_NI_UNKNOWN
:
1066 if (siz
!= sizeof(*ni6
))
1068 printf(", invalid length");
1072 if (ni6
->ni_code
!= ICMP6_NI_SUCCESS
) {
1078 switch (EXTRACT_16BITS(&ni6
->ni_qtype
)) {
1083 if (siz
!= sizeof(*ni6
))
1085 printf(", invalid length");
1087 case NI_QTYPE_SUPTYPES
:
1090 printf("supported qtypes");
1091 i
= EXTRACT_16BITS(&ni6
->ni_flags
);
1093 printf(" [%s]", (i
& 0x01) ? "C" : "");
1099 cp
= (const u_char
*)(ni6
+ 1) + 4;
1100 if (cp
[0] == ep
- cp
- 1) {
1101 /* icmp-name-lookup-03, pascal string */
1103 printf(", 03 draft");
1112 dnsname_print(cp
, ep
);
1113 if ((EXTRACT_16BITS(&ni6
->ni_flags
) & 0x01) != 0)
1114 printf(" [TTL=%u]", *(u_int32_t
*)(ni6
+ 1));
1116 case NI_QTYPE_NODEADDR
:
1119 printf("node addresses");
1122 if (i
+ sizeof(struct in6_addr
) + sizeof(int32_t) > siz
)
1124 printf(" %s", getname6(bp
+ i
));
1125 i
+= sizeof(struct in6_addr
);
1126 printf("(%d)", (int32_t)EXTRACT_32BITS(bp
+ i
));
1127 i
+= sizeof(int32_t);
1132 printf(" [%s%s%s%s%s%s%s]",
1133 (i
& NI_NODEADDR_FLAG_ANYCAST
) ? "a" : "",
1134 (i
& NI_NODEADDR_FLAG_GLOBAL
) ? "G" : "",
1135 (i
& NI_NODEADDR_FLAG_SITELOCAL
) ? "S" : "",
1136 (i
& NI_NODEADDR_FLAG_LINKLOCAL
) ? "L" : "",
1137 (i
& NI_NODEADDR_FLAG_COMPAT
) ? "C" : "",
1138 (i
& NI_NODEADDR_FLAG_ALL
) ? "A" : "",
1139 (i
& NI_NODEADDR_FLAG_TRUNCATE
) ? "T" : "");
1155 fputs("[|icmp6]", stdout
);
1159 icmp6_rrenum_print(const u_char
*bp
, const u_char
*ep
)
1161 struct icmp6_router_renum
*rr6
;
1163 struct rr_pco_match
*match
;
1164 struct rr_pco_use
*use
;
1165 char hbuf
[NI_MAXHOST
];
1170 rr6
= (struct icmp6_router_renum
*)bp
;
1171 cp
= (const char *)(rr6
+ 1);
1173 TCHECK(rr6
->rr_reserved
);
1174 switch (rr6
->rr_code
) {
1175 case ICMP6_ROUTER_RENUMBERING_COMMAND
:
1176 printf("router renum: command");
1178 case ICMP6_ROUTER_RENUMBERING_RESULT
:
1179 printf("router renum: result");
1181 case ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET
:
1182 printf("router renum: sequence number reset");
1185 printf("router renum: code-#%d", rr6
->rr_code
);
1189 printf(", seq=%u", EXTRACT_32BITS(&rr6
->rr_seqnum
));
1192 #define F(x, y) ((rr6->rr_flags) & (x) ? (y) : "")
1194 if (rr6
->rr_flags
) {
1195 printf("%s%s%s%s%s,", F(ICMP6_RR_FLAGS_TEST
, "T"),
1196 F(ICMP6_RR_FLAGS_REQRESULT
, "R"),
1197 F(ICMP6_RR_FLAGS_FORCEAPPLY
, "A"),
1198 F(ICMP6_RR_FLAGS_SPECSITE
, "S"),
1199 F(ICMP6_RR_FLAGS_PREVDONE
, "P"));
1201 printf("seg=%u,", rr6
->rr_segnum
);
1202 printf("maxdelay=%u", rr6
->rr_maxdelay
);
1203 if (rr6
->rr_reserved
)
1204 printf("rsvd=0x%x", EXTRACT_16BITS(&rr6
->rr_reserved
));
1210 if (rr6
->rr_code
== ICMP6_ROUTER_RENUMBERING_COMMAND
) {
1211 match
= (struct rr_pco_match
*)cp
;
1212 cp
= (const char *)(match
+ 1);
1214 TCHECK(match
->rpm_prefix
);
1220 printf("match("); /*)*/
1221 switch (match
->rpm_code
) {
1222 case RPM_PCO_ADD
: printf("add"); break;
1223 case RPM_PCO_CHANGE
: printf("change"); break;
1224 case RPM_PCO_SETGLOBAL
: printf("setglobal"); break;
1225 default: printf("#%u", match
->rpm_code
); break;
1229 printf(",ord=%u", match
->rpm_ordinal
);
1230 printf(",min=%u", match
->rpm_minlen
);
1231 printf(",max=%u", match
->rpm_maxlen
);
1233 if (inet_ntop(AF_INET6
, &match
->rpm_prefix
, hbuf
, sizeof(hbuf
)))
1234 printf(",%s/%u", hbuf
, match
->rpm_matchlen
);
1236 printf(",?/%u", match
->rpm_matchlen
);
1240 n
= match
->rpm_len
- 3;
1245 use
= (struct rr_pco_use
*)cp
;
1246 cp
= (const char *)(use
+ 1);
1248 TCHECK(use
->rpu_prefix
);
1254 printf("use("); /*)*/
1255 if (use
->rpu_flags
) {
1256 #define F(x, y) ((use->rpu_flags) & (x) ? (y) : "")
1258 F(ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME
, "V"),
1259 F(ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME
, "P"));
1263 printf("mask=0x%x,", use
->rpu_ramask
);
1264 printf("raflags=0x%x,", use
->rpu_raflags
);
1265 if (~use
->rpu_vltime
== 0)
1266 printf("vltime=infty,");
1268 printf("vltime=%u,",
1269 EXTRACT_32BITS(&use
->rpu_vltime
));
1270 if (~use
->rpu_pltime
== 0)
1271 printf("pltime=infty,");
1273 printf("pltime=%u,",
1274 EXTRACT_32BITS(&use
->rpu_pltime
));
1276 if (inet_ntop(AF_INET6
, &use
->rpu_prefix
, hbuf
,
1278 printf("%s/%u/%u", hbuf
, use
->rpu_uselen
,
1281 printf("?/%u/%u", use
->rpu_uselen
,
1291 fputs("[|icmp6]", stdout
);