2 * Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the University of California,
13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
23 static const char rcsid
[] =
24 "@(#) $Header: /tcpdump/master/tcpdump/print-icmp6.c,v 1.63 2002-08-01 08:53:09 risso Exp $";
35 #include <tcpdump-stdinc.h>
43 #include "interface.h"
44 #include "addrtoname.h"
49 static const char *get_rtpref(u_int
);
50 static const char *get_lifetime(u_int32_t
);
51 static void print_lladdr(const u_char
*, size_t);
52 void icmp6_opt_print(const u_char
*, int);
53 void mld6_print(const u_char
*);
54 static struct udphdr
*get_upperlayer(u_char
*, int *);
55 static void dnsname_print(const u_char
*, const u_char
*);
56 void icmp6_nodeinfo_print(int, const u_char
*, const u_char
*);
57 void icmp6_rrenum_print(int, const u_char
*, const u_char
*);
60 #define abs(a) ((0 < (a)) ? (a) : -(a))
66 static const char *rtpref_str
[] = {
73 return rtpref_str
[((v
& ND_RA_FLAG_RTPREF_MASK
) >> 3) & 0xff];
77 get_lifetime(u_int32_t v
)
81 if (v
== (u_int32_t
)~0UL)
84 snprintf(buf
, sizeof(buf
), "%u", v
);
90 print_lladdr(const u_int8_t
*p
, size_t l
)
92 const u_int8_t
*ep
, *q
;
96 while (l
> 0 && q
< ep
) {
105 icmp6_print(const u_char
*bp
, const u_char
*bp2
)
107 const struct icmp6_hdr
*dp
;
108 const struct ip6_hdr
*ip
;
110 const struct ip6_hdr
*oip
;
111 const struct udphdr
*ouh
;
117 dp
= (struct icmp6_hdr
*)bp
;
118 ip
= (struct ip6_hdr
*)bp2
;
119 oip
= (struct ip6_hdr
*)(dp
+ 1);
121 /* 'ep' points to the end of available data. */
124 icmp6len
= (ntohs(ip
->ip6_plen
) + sizeof(struct ip6_hdr
) -
126 else /* XXX: jumbo payload case... */
127 icmp6len
= snapend
- bp
;
129 TCHECK(dp
->icmp6_code
);
130 switch (dp
->icmp6_type
) {
131 case ICMP6_DST_UNREACH
:
132 TCHECK(oip
->ip6_dst
);
133 switch (dp
->icmp6_code
) {
134 case ICMP6_DST_UNREACH_NOROUTE
:
135 printf("icmp6: %s unreachable route",
136 ip6addr_string(&oip
->ip6_dst
));
138 case ICMP6_DST_UNREACH_ADMIN
:
139 printf("icmp6: %s unreachable prohibited",
140 ip6addr_string(&oip
->ip6_dst
));
142 case ICMP6_DST_UNREACH_BEYONDSCOPE
:
143 printf("icmp6: %s beyond scope of source address %s",
144 ip6addr_string(&oip
->ip6_dst
),
145 ip6addr_string(&oip
->ip6_src
));
147 case ICMP6_DST_UNREACH_ADDR
:
148 printf("icmp6: %s unreachable address",
149 ip6addr_string(&oip
->ip6_dst
));
151 case ICMP6_DST_UNREACH_NOPORT
:
152 if ((ouh
= get_upperlayer((u_char
*)oip
, &prot
))
156 dport
= ntohs(ouh
->uh_dport
);
159 printf("icmp6: %s tcp port %s unreachable",
160 ip6addr_string(&oip
->ip6_dst
),
161 tcpport_string(dport
));
164 printf("icmp6: %s udp port %s unreachable",
165 ip6addr_string(&oip
->ip6_dst
),
166 udpport_string(dport
));
169 printf("icmp6: %s protocol %d port %d unreachable",
170 ip6addr_string(&oip
->ip6_dst
),
171 oip
->ip6_nxt
, dport
);
176 printf("icmp6: %s unreachable code-#%d",
177 ip6addr_string(&oip
->ip6_dst
),
182 case ICMP6_PACKET_TOO_BIG
:
183 TCHECK(dp
->icmp6_mtu
);
184 printf("icmp6: too big %u", (u_int32_t
)ntohl(dp
->icmp6_mtu
));
186 case ICMP6_TIME_EXCEEDED
:
187 TCHECK(oip
->ip6_dst
);
188 switch (dp
->icmp6_code
) {
189 case ICMP6_TIME_EXCEED_TRANSIT
:
190 printf("icmp6: time exceeded in-transit for %s",
191 ip6addr_string(&oip
->ip6_dst
));
193 case ICMP6_TIME_EXCEED_REASSEMBLY
:
194 printf("icmp6: ip6 reassembly time exceeded");
197 printf("icmp6: time exceeded code-#%d",
202 case ICMP6_PARAM_PROB
:
203 TCHECK(oip
->ip6_dst
);
204 switch (dp
->icmp6_code
) {
205 case ICMP6_PARAMPROB_HEADER
:
206 printf("icmp6: parameter problem errorneous - octet %u",
207 (u_int32_t
)ntohl(dp
->icmp6_pptr
));
209 case ICMP6_PARAMPROB_NEXTHEADER
:
210 printf("icmp6: parameter problem next header - octet %u",
211 (u_int32_t
)ntohl(dp
->icmp6_pptr
));
213 case ICMP6_PARAMPROB_OPTION
:
214 printf("icmp6: parameter problem option - octet %u",
215 (u_int32_t
)ntohl(dp
->icmp6_pptr
));
218 printf("icmp6: parameter problem code-#%d",
223 case ICMP6_ECHO_REQUEST
:
224 printf("icmp6: echo request");
226 case ICMP6_ECHO_REPLY
:
227 printf("icmp6: echo reply");
229 case ICMP6_MEMBERSHIP_QUERY
:
230 printf("icmp6: multicast listener query ");
231 mld6_print((const u_char
*)dp
);
233 case ICMP6_MEMBERSHIP_REPORT
:
234 printf("icmp6: multicast listener report ");
235 mld6_print((const u_char
*)dp
);
237 case ICMP6_MEMBERSHIP_REDUCTION
:
238 printf("icmp6: multicast listener done ");
239 mld6_print((const u_char
*)dp
);
241 case ND_ROUTER_SOLICIT
:
242 printf("icmp6: router solicitation ");
245 icmp6_opt_print((const u_char
*)dp
+ RTSOLLEN
,
246 icmp6len
- RTSOLLEN
);
249 case ND_ROUTER_ADVERT
:
250 printf("icmp6: router advertisement");
252 struct nd_router_advert
*p
;
254 p
= (struct nd_router_advert
*)dp
;
255 TCHECK(p
->nd_ra_retransmit
);
256 printf("(chlim=%d, ", (int)p
->nd_ra_curhoplimit
);
257 if (p
->nd_ra_flags_reserved
& ND_RA_FLAG_MANAGED
)
259 if (p
->nd_ra_flags_reserved
& ND_RA_FLAG_OTHER
)
261 if (p
->nd_ra_flags_reserved
& ND_RA_FLAG_HOME_AGENT
)
264 if ((p
->nd_ra_flags_reserved
& ~ND_RA_FLAG_RTPREF_MASK
)
269 get_rtpref(p
->nd_ra_flags_reserved
));
271 printf("router_ltime=%d, ", ntohs(p
->nd_ra_router_lifetime
));
272 printf("reachable_time=%u, ",
273 (u_int32_t
)ntohl(p
->nd_ra_reachable
));
274 printf("retrans_time=%u)",
275 (u_int32_t
)ntohl(p
->nd_ra_retransmit
));
277 icmp6_opt_print((const u_char
*)dp
+ RTADVLEN
,
278 icmp6len
- RTADVLEN
);
281 case ND_NEIGHBOR_SOLICIT
:
283 struct nd_neighbor_solicit
*p
;
284 p
= (struct nd_neighbor_solicit
*)dp
;
285 TCHECK(p
->nd_ns_target
);
286 printf("icmp6: neighbor sol: who has %s",
287 ip6addr_string(&p
->nd_ns_target
));
290 icmp6_opt_print((const u_char
*)dp
+ NDSOLLEN
,
291 icmp6len
- NDSOLLEN
);
295 case ND_NEIGHBOR_ADVERT
:
297 struct nd_neighbor_advert
*p
;
299 p
= (struct nd_neighbor_advert
*)dp
;
300 TCHECK(p
->nd_na_target
);
301 printf("icmp6: neighbor adv: tgt is %s",
302 ip6addr_string(&p
->nd_na_target
));
304 #define ND_NA_FLAG_ALL \
305 (ND_NA_FLAG_ROUTER|ND_NA_FLAG_SOLICITED|ND_NA_FLAG_OVERRIDE)
306 /* we don't need ntohl() here. see advanced-api-04. */
307 if (p
->nd_na_flags_reserved
& ND_NA_FLAG_ALL
) {
308 #undef ND_NA_FLAG_ALL
311 flags
= p
->nd_na_flags_reserved
;
313 if (flags
& ND_NA_FLAG_ROUTER
)
315 if (flags
& ND_NA_FLAG_SOLICITED
)
317 if (flags
& ND_NA_FLAG_OVERRIDE
)
322 icmp6_opt_print((const u_char
*)dp
+ NDADVLEN
,
323 icmp6len
- NDADVLEN
);
329 #define RDR(i) ((struct nd_redirect *)(i))
330 TCHECK(RDR(dp
)->nd_rd_dst
);
331 printf("icmp6: redirect %s",
332 getname6((const u_char
*)&RDR(dp
)->nd_rd_dst
));
334 getname6((const u_char
*)&RDR(dp
)->nd_rd_target
));
335 #define REDIRECTLEN 40
337 icmp6_opt_print((const u_char
*)dp
+ REDIRECTLEN
,
338 icmp6len
- REDIRECTLEN
);
343 case ICMP6_ROUTER_RENUMBERING
:
344 icmp6_rrenum_print(icmp6len
, bp
, ep
);
348 icmp6_nodeinfo_print(icmp6len
, bp
, ep
);
350 case ICMP6_HADISCOV_REQUEST
:
351 printf("icmp6: ha discovery request");
353 TCHECK(dp
->icmp6_data16
[0]);
354 printf("(id=%d)", ntohs(dp
->icmp6_data16
[0]));
357 case ICMP6_HADISCOV_REPLY
:
358 printf("icmp6: ha discovery reply");
360 struct in6_addr
*in6
;
364 TCHECK(dp
->icmp6_data16
[0]);
365 printf("(id=%d", ntohs(dp
->icmp6_data16
[0]));
366 cp
= (u_char
*)dp
+ icmp6len
;
367 res
= (u_int32_t
*)(dp
+ 1);
368 in6
= (struct in6_addr
*)(res
+ 2);
369 for (; (u_char
*)in6
< cp
; in6
++) {
371 printf(", %s", ip6addr_string(in6
));
376 case ICMP6_MOBILEPREFIX_SOLICIT
:
377 printf("icmp6: mobile router solicitation");
379 case ICMP6_MOBILEPREFIX_ADVERT
:
380 printf("icmp6: mobile router advertisement");
383 icmp6_opt_print((const u_char
*)dp
+ MPADVLEN
,
384 icmp6len
- MPADVLEN
);
388 printf("icmp6: type-#%d", dp
->icmp6_type
);
393 fputs("[|icmp6]", stdout
);
396 static struct udphdr
*
397 get_upperlayer(u_char
*bp
, int *prot
)
400 struct ip6_hdr
*ip6
= (struct ip6_hdr
*)bp
;
403 struct ip6_frag
*fragh
;
407 /* 'ep' points to the end of available data. */
410 if (TTEST(ip6
->ip6_nxt
) == 0)
414 hlen
= sizeof(struct ip6_hdr
);
416 while (bp
< snapend
) {
422 uh
= (struct udphdr
*)bp
;
423 if (TTEST(uh
->uh_dport
)) {
431 case IPPROTO_HOPOPTS
:
432 case IPPROTO_DSTOPTS
:
433 case IPPROTO_ROUTING
:
434 hbh
= (struct ip6_hbh
*)bp
;
435 if (TTEST(hbh
->ip6h_len
) == 0)
438 hlen
= (hbh
->ip6h_len
+ 1) << 3;
441 case IPPROTO_FRAGMENT
: /* this should be odd, but try anyway */
442 fragh
= (struct ip6_frag
*)bp
;
443 if (TTEST(fragh
->ip6f_offlg
) == 0)
445 /* fragments with non-zero offset are meaningless */
446 if ((fragh
->ip6f_offlg
& IP6F_OFF_MASK
) != 0)
448 nh
= fragh
->ip6f_nxt
;
449 hlen
= sizeof(struct ip6_frag
);
453 ah
= (struct ah
*)bp
;
454 if (TTEST(ah
->ah_len
) == 0)
457 hlen
= (ah
->ah_len
+ 2) << 2;
460 default: /* unknown or undecodable header */
461 *prot
= nh
; /* meaningless, but set here anyway */
466 return(NULL
); /* should be notreached, though */
470 icmp6_opt_print(const u_char
*bp
, int resid
)
472 const struct nd_opt_hdr
*op
;
473 const struct nd_opt_hdr
*opl
; /* why there's no struct? */
474 const struct nd_opt_prefix_info
*opp
;
475 const struct icmp6_opts_redirect
*opr
;
476 const struct nd_opt_mtu
*opm
;
477 const struct nd_opt_advinterval
*opa
;
478 const struct nd_opt_homeagent_info
*oph
;
479 const struct nd_opt_route_info
*opri
;
480 const u_char
*cp
, *ep
;
481 struct in6_addr in6
, *in6p
;
484 #define ECHECK(var) if ((u_char *)&(var) > ep - sizeof(var)) return
487 /* 'ep' points to the end of available data. */
491 op
= (struct nd_opt_hdr
*)cp
;
493 ECHECK(op
->nd_opt_len
);
496 if (op
->nd_opt_len
== 0)
498 if (cp
+ (op
->nd_opt_len
<< 3) > ep
)
501 switch (op
->nd_opt_type
) {
502 case ND_OPT_SOURCE_LINKADDR
:
503 opl
= (struct nd_opt_hdr
*)op
;
504 printf("(src lladdr: ");
505 l
= (op
->nd_opt_len
<< 3) - 2;
506 print_lladdr(cp
+ 2, l
);
510 case ND_OPT_TARGET_LINKADDR
:
511 opl
= (struct nd_opt_hdr
*)op
;
512 printf("(tgt lladdr: ");
513 l
= (op
->nd_opt_len
<< 3) - 2;
514 print_lladdr(cp
+ 2, l
);
518 case ND_OPT_PREFIX_INFORMATION
:
519 opp
= (struct nd_opt_prefix_info
*)op
;
520 TCHECK(opp
->nd_opt_pi_prefix
);
521 printf("(prefix info: "); /*)*/
522 if (op
->nd_opt_len
!= 4) {
528 if (opp
->nd_opt_pi_flags_reserved
& ND_OPT_PI_FLAG_ONLINK
)
530 if (opp
->nd_opt_pi_flags_reserved
& ND_OPT_PI_FLAG_AUTO
)
532 if (opp
->nd_opt_pi_flags_reserved
& ND_OPT_PI_FLAG_ROUTER
)
534 if (opp
->nd_opt_pi_flags_reserved
)
536 printf("valid_ltime=%s,",
537 get_lifetime((u_int32_t
)ntohl(opp
->nd_opt_pi_valid_time
)));
538 printf("preferred_ltime=%s,",
539 get_lifetime((u_int32_t
)ntohl(opp
->nd_opt_pi_preferred_time
)));
540 printf("prefix=%s/%d",
541 ip6addr_string(&opp
->nd_opt_pi_prefix
),
542 opp
->nd_opt_pi_prefix_len
);
543 if (opp
->nd_opt_pi_len
!= 4)
548 case ND_OPT_REDIRECTED_HEADER
:
549 opr
= (struct icmp6_opts_redirect
*)op
;
550 printf("(redirect)");
554 opm
= (struct nd_opt_mtu
*)op
;
555 TCHECK(opm
->nd_opt_mtu_mtu
);
556 printf("(mtu:"); /*)*/
557 if (op
->nd_opt_len
!= 1) {
563 printf(" mtu=%u", (u_int32_t
)ntohl(opm
->nd_opt_mtu_mtu
));
564 if (opm
->nd_opt_mtu_len
!= 1)
568 case ND_OPT_ADVINTERVAL
:
569 opa
= (struct nd_opt_advinterval
*)op
;
570 TCHECK(opa
->nd_opt_adv_interval
);
571 printf("(advint:"); /*)*/
573 (u_int32_t
)ntohl(opa
->nd_opt_adv_interval
));
577 case ND_OPT_HOMEAGENT_INFO
:
578 oph
= (struct nd_opt_homeagent_info
*)op
;
579 TCHECK(oph
->nd_opt_hai_lifetime
);
580 printf("(ha info:"); /*)*/
581 printf(" pref=%d", ntohs(oph
->nd_opt_hai_preference
));
582 printf(", lifetime=%u", ntohs(oph
->nd_opt_hai_lifetime
));
585 case ND_OPT_ROUTE_INFO
:
586 opri
= (struct nd_opt_route_info
*)op
;
587 TCHECK(opri
->nd_opt_rti_lifetime
);
588 memset(&in6
, 0, sizeof(in6
));
589 in6p
= (struct in6_addr
*)(opri
+ 1);
590 switch (op
->nd_opt_len
) {
595 memcpy(&in6
, opri
+ 1, 8);
599 memcpy(&in6
, opri
+ 1, sizeof(in6
));
604 printf("(rtinfo:"); /*)*/
605 printf(" %s/%u", ip6addr_string(&in6
),
606 opri
->nd_opt_rti_prefixlen
);
607 printf(", pref=%s", get_rtpref(opri
->nd_opt_rti_flags
));
608 printf(", lifetime=%s",
609 get_lifetime((u_int32_t
)ntohl(opri
->nd_opt_rti_lifetime
)));
614 printf("(unknown opt_type=%d, opt_len=%d)",
615 op
->nd_opt_type
, op
->nd_opt_len
);
619 cp
+= op
->nd_opt_len
<< 3;
620 resid
-= op
->nd_opt_len
<< 3;
625 fputs("[ndp opt]", stdout
);
631 mld6_print(const u_char
*bp
)
633 struct mld6_hdr
*mp
= (struct mld6_hdr
*)bp
;
636 /* 'ep' points to the end of available data. */
639 if ((u_char
*)mp
+ sizeof(*mp
) > ep
)
642 printf("max resp delay: %d ", ntohs(mp
->mld6_maxdelay
));
643 printf("addr: %s", ip6addr_string(&mp
->mld6_addr
));
647 dnsname_print(const u_char
*cp
, const u_char
*ep
)
651 /* DNS name decoding - no decompression */
660 while (i
-- && cp
< ep
) {
664 if (cp
+ 1 < ep
&& *cp
)
670 } else if (cp
+ 1 == ep
&& *cp
== '\0') {
683 icmp6_nodeinfo_print(int icmp6len
, const u_char
*bp
, const u_char
*ep
)
685 struct icmp6_nodeinfo
*ni6
;
686 struct icmp6_hdr
*dp
;
691 dp
= (struct icmp6_hdr
*)bp
;
692 ni6
= (struct icmp6_nodeinfo
*)bp
;
695 switch (ni6
->ni_type
) {
697 if (siz
== sizeof(*dp
) + 4) {
698 /* KAME who-are-you */
699 printf("icmp6: who-are-you request");
702 printf("icmp6: node information query");
704 TCHECK2(*dp
, sizeof(*ni6
));
705 ni6
= (struct icmp6_nodeinfo
*)dp
;
707 switch (ntohs(ni6
->ni_qtype
)) {
711 case NI_QTYPE_SUPTYPES
:
712 printf("supported qtypes");
713 i
= ntohs(ni6
->ni_flags
);
715 printf(" [%s]", (i
& 0x01) ? "C" : "");
721 case NI_QTYPE_NODEADDR
:
722 printf("node addresses");
726 /* NI_NODEADDR_FLAG_TRUNCATE undefined for query */
727 printf(" [%s%s%s%s%s%s]",
728 (i
& NI_NODEADDR_FLAG_ANYCAST
) ? "a" : "",
729 (i
& NI_NODEADDR_FLAG_GLOBAL
) ? "G" : "",
730 (i
& NI_NODEADDR_FLAG_SITELOCAL
) ? "S" : "",
731 (i
& NI_NODEADDR_FLAG_LINKLOCAL
) ? "L" : "",
732 (i
& NI_NODEADDR_FLAG_COMPAT
) ? "C" : "",
733 (i
& NI_NODEADDR_FLAG_ALL
) ? "A" : "");
740 if (ni6
->ni_qtype
== NI_QTYPE_NOOP
||
741 ni6
->ni_qtype
== NI_QTYPE_SUPTYPES
) {
742 if (siz
!= sizeof(*ni6
))
744 printf(", invalid len");
751 /* XXX backward compat, icmp-name-lookup-03 */
752 if (siz
== sizeof(*ni6
)) {
753 printf(", 03 draft");
759 switch (ni6
->ni_code
) {
760 case ICMP6_NI_SUBJ_IPV6
:
762 sizeof(*ni6
) + sizeof(struct in6_addr
)))
764 if (siz
!= sizeof(*ni6
) + sizeof(struct in6_addr
)) {
766 printf(", invalid subject len");
769 printf(", subject=%s",
770 getname6((const u_char
*)(ni6
+ 1)));
772 case ICMP6_NI_SUBJ_FQDN
:
773 printf(", subject=DNS name");
774 cp
= (const u_char
*)(ni6
+ 1);
775 if (cp
[0] == ep
- cp
- 1) {
776 /* icmp-name-lookup-03, pascal string */
778 printf(", 03 draft");
787 dnsname_print(cp
, ep
);
789 case ICMP6_NI_SUBJ_IPV4
:
790 if (!TTEST2(*dp
, sizeof(*ni6
) + sizeof(struct in_addr
)))
792 if (siz
!= sizeof(*ni6
) + sizeof(struct in_addr
)) {
794 printf(", invalid subject len");
797 printf(", subject=%s",
798 getname((const u_char
*)(ni6
+ 1)));
801 printf(", unknown subject");
810 if (icmp6len
> siz
) {
811 printf("[|icmp6: node information reply]");
817 ni6
= (struct icmp6_nodeinfo
*)dp
;
818 printf("icmp6: node information reply");
820 switch (ni6
->ni_code
) {
821 case ICMP6_NI_SUCCESS
:
827 case ICMP6_NI_REFUSED
:
830 if (siz
!= sizeof(*ni6
))
832 printf(", invalid length");
834 case ICMP6_NI_UNKNOWN
:
837 if (siz
!= sizeof(*ni6
))
839 printf(", invalid length");
843 if (ni6
->ni_code
!= ICMP6_NI_SUCCESS
) {
849 switch (ntohs(ni6
->ni_qtype
)) {
854 if (siz
!= sizeof(*ni6
))
856 printf(", invalid length");
858 case NI_QTYPE_SUPTYPES
:
861 printf("supported qtypes");
862 i
= ntohs(ni6
->ni_flags
);
864 printf(" [%s]", (i
& 0x01) ? "C" : "");
870 cp
= (const u_char
*)(ni6
+ 1) + 4;
871 if (cp
[0] == ep
- cp
- 1) {
872 /* icmp-name-lookup-03, pascal string */
874 printf(", 03 draft");
883 dnsname_print(cp
, ep
);
884 if ((ntohs(ni6
->ni_flags
) & 0x01) != 0)
885 printf(" [TTL=%u]", *(u_int32_t
*)(ni6
+ 1));
887 case NI_QTYPE_NODEADDR
:
890 printf("node addresses");
893 if (i
+ sizeof(struct in6_addr
) + sizeof(int32_t) > siz
)
895 printf(" %s", getname6(bp
+ i
));
896 i
+= sizeof(struct in6_addr
);
897 printf("(%d)", (int32_t)ntohl(*(int32_t *)(bp
+ i
)));
898 i
+= sizeof(int32_t);
903 printf(" [%s%s%s%s%s%s%s]",
904 (i
& NI_NODEADDR_FLAG_ANYCAST
) ? "a" : "",
905 (i
& NI_NODEADDR_FLAG_GLOBAL
) ? "G" : "",
906 (i
& NI_NODEADDR_FLAG_SITELOCAL
) ? "S" : "",
907 (i
& NI_NODEADDR_FLAG_LINKLOCAL
) ? "L" : "",
908 (i
& NI_NODEADDR_FLAG_COMPAT
) ? "C" : "",
909 (i
& NI_NODEADDR_FLAG_ALL
) ? "A" : "",
910 (i
& NI_NODEADDR_FLAG_TRUNCATE
) ? "T" : "");
926 fputs("[|icmp6]", stdout
);
930 icmp6_rrenum_print(int icmp6len
, const u_char
*bp
, const u_char
*ep
)
932 struct icmp6_router_renum
*rr6
;
933 struct icmp6_hdr
*dp
;
936 struct rr_pco_match
*match
;
937 struct rr_pco_use
*use
;
938 char hbuf
[NI_MAXHOST
];
941 dp
= (struct icmp6_hdr
*)bp
;
942 rr6
= (struct icmp6_router_renum
*)bp
;
944 cp
= (const char *)(rr6
+ 1);
946 TCHECK(rr6
->rr_reserved
);
947 switch (rr6
->rr_code
) {
948 case ICMP6_ROUTER_RENUMBERING_COMMAND
:
949 printf("router renum: command");
951 case ICMP6_ROUTER_RENUMBERING_RESULT
:
952 printf("router renum: result");
954 case ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET
:
955 printf("router renum: sequence number reset");
958 printf("router renum: code-#%d", rr6
->rr_code
);
962 printf(", seq=%u", (u_int32_t
)ntohl(rr6
->rr_seqnum
));
965 #define F(x, y) ((rr6->rr_flags) & (x) ? (y) : "")
968 printf("%s%s%s%s%s,", F(ICMP6_RR_FLAGS_TEST
, "T"),
969 F(ICMP6_RR_FLAGS_REQRESULT
, "R"),
970 F(ICMP6_RR_FLAGS_FORCEAPPLY
, "A"),
971 F(ICMP6_RR_FLAGS_SPECSITE
, "S"),
972 F(ICMP6_RR_FLAGS_PREVDONE
, "P"));
974 printf("seg=%u,", rr6
->rr_segnum
);
975 printf("maxdelay=%u", rr6
->rr_maxdelay
);
976 if (rr6
->rr_reserved
)
977 printf("rsvd=0x%x", (u_int16_t
)ntohs(rr6
->rr_reserved
));
983 if (rr6
->rr_code
== ICMP6_ROUTER_RENUMBERING_COMMAND
) {
984 match
= (struct rr_pco_match
*)cp
;
985 cp
= (const char *)(match
+ 1);
987 TCHECK(match
->rpm_prefix
);
993 printf("match("); /*)*/
994 switch (match
->rpm_code
) {
995 case RPM_PCO_ADD
: printf("add"); break;
996 case RPM_PCO_CHANGE
: printf("change"); break;
997 case RPM_PCO_SETGLOBAL
: printf("setglobal"); break;
998 default: printf("#%u", match
->rpm_code
); break;
1002 printf(",ord=%u", match
->rpm_ordinal
);
1003 printf(",min=%u", match
->rpm_minlen
);
1004 printf(",max=%u", match
->rpm_maxlen
);
1006 if (inet_ntop(AF_INET6
, &match
->rpm_prefix
, hbuf
, sizeof(hbuf
)))
1007 printf(",%s/%u", hbuf
, match
->rpm_matchlen
);
1009 printf(",?/%u", match
->rpm_matchlen
);
1013 n
= match
->rpm_len
- 3;
1018 use
= (struct rr_pco_use
*)cp
;
1019 cp
= (const char *)(use
+ 1);
1021 TCHECK(use
->rpu_prefix
);
1027 printf("use("); /*)*/
1028 if (use
->rpu_flags
) {
1029 #define F(x, y) ((use->rpu_flags) & (x) ? (y) : "")
1031 F(ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME
, "V"),
1032 F(ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME
, "P"));
1036 printf("mask=0x%x,", use
->rpu_ramask
);
1037 printf("raflags=0x%x,", use
->rpu_raflags
);
1038 if (~use
->rpu_vltime
== 0)
1039 printf("vltime=infty,");
1041 printf("vltime=%u,",
1042 (u_int32_t
)ntohl(use
->rpu_vltime
));
1043 if (~use
->rpu_pltime
== 0)
1044 printf("pltime=infty,");
1046 printf("pltime=%u,",
1047 (u_int32_t
)ntohl(use
->rpu_pltime
));
1049 if (inet_ntop(AF_INET6
, &use
->rpu_prefix
, hbuf
,
1051 printf("%s/%u/%u", hbuf
, use
->rpu_uselen
,
1054 printf("?/%u/%u", use
->rpu_uselen
,
1064 fputs("[|icmp6]", stdout
);