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.42 2000/12/13 07:57:05 itojun Exp $";
35 #include <sys/param.h>
37 #include <sys/types.h>
38 #include <sys/socket.h>
41 #include <netinet/in.h>
43 #include <arpa/inet.h>
51 #include "interface.h"
52 #include "addrtoname.h"
57 void icmp6_opt_print(const u_char *, int);
58 void mld6_print(const u_char *);
59 static struct udphdr *get_upperlayer(u_char *, int *);
60 static void dnsname_print(const u_char *, const u_char *);
61 void icmp6_nodeinfo_print(int, const u_char *, const u_char *);
62 void icmp6_rrenum_print(int, const u_char *, const u_char *);
65 #define abs(a) ((0 < (a)) ? (a) : -(a))
69 icmp6_print(register const u_char *bp, register const u_char *bp2)
71 const struct icmp6_hdr *dp;
72 register const struct ip6_hdr *ip;
73 register const char *str;
74 register const struct ip6_hdr *oip;
75 register const struct udphdr *ouh;
77 register const u_char *ep;
82 #define TCHECK(var) if ((u_char *)&(var) > ep - sizeof(var)) goto trunc
85 dp = (struct icmp6_hdr *)bp;
86 ip = (struct ip6_hdr *)bp2;
87 oip = (struct ip6_hdr *)(dp + 1);
89 /* 'ep' points to the end of available data. */
92 icmp6len = (ntohs(ip->ip6_plen) + sizeof(struct ip6_hdr) -
94 else /* XXX: jumbo payload case... */
95 icmp6len = snapend - bp;
98 (void)printf("%s > %s: ",
99 ip6addr_string(&ip->ip6_src),
100 ip6addr_string(&ip->ip6_dst));
103 TCHECK(dp->icmp6_code);
104 switch (dp->icmp6_type) {
105 case ICMP6_DST_UNREACH:
106 TCHECK(oip->ip6_dst);
107 switch (dp->icmp6_code) {
108 case ICMP6_DST_UNREACH_NOROUTE:
109 printf("icmp6: %s unreachable route",
110 ip6addr_string(&oip->ip6_dst));
112 case ICMP6_DST_UNREACH_ADMIN:
113 printf("icmp6: %s unreachable prohibited",
114 ip6addr_string(&oip->ip6_dst));
116 case ICMP6_DST_UNREACH_BEYONDSCOPE:
117 printf("icmp6: %s beyond scope of source address %s",
118 ip6addr_string(&oip->ip6_dst),
119 ip6addr_string(&oip->ip6_src));
121 case ICMP6_DST_UNREACH_ADDR:
122 printf("icmp6: %s unreachable address",
123 ip6addr_string(&oip->ip6_dst));
125 case ICMP6_DST_UNREACH_NOPORT:
126 if ((ouh = get_upperlayer((u_char *)oip, &prot))
130 dport = ntohs(ouh->uh_dport);
133 printf("icmp6: %s tcp port %s unreachable",
134 ip6addr_string(&oip->ip6_dst),
135 tcpport_string(dport));
138 printf("icmp6: %s udp port %s unreachable",
139 ip6addr_string(&oip->ip6_dst),
140 udpport_string(dport));
143 printf("icmp6: %s protocol %d port %d unreachable",
144 ip6addr_string(&oip->ip6_dst),
145 oip->ip6_nxt, dport);
150 printf("icmp6: %s unreachable code-#%d",
151 ip6addr_string(&oip->ip6_dst),
156 case ICMP6_PACKET_TOO_BIG:
157 TCHECK(dp->icmp6_mtu);
158 printf("icmp6: too big %u\n", (u_int32_t)ntohl(dp->icmp6_mtu));
160 case ICMP6_TIME_EXCEEDED:
161 TCHECK(oip->ip6_dst);
162 switch (dp->icmp6_code) {
163 case ICMP6_TIME_EXCEED_TRANSIT:
164 printf("icmp6: time exceeded in-transit for %s",
165 ip6addr_string(&oip->ip6_dst));
167 case ICMP6_TIME_EXCEED_REASSEMBLY:
168 printf("icmp6: ip6 reassembly time exceeded");
171 printf("icmp6: time exceeded code-#%d",
176 case ICMP6_PARAM_PROB:
177 TCHECK(oip->ip6_dst);
178 switch (dp->icmp6_code) {
179 case ICMP6_PARAMPROB_HEADER:
180 printf("icmp6: parameter problem errorneous - octet %u\n",
181 (u_int32_t)ntohl(dp->icmp6_pptr));
183 case ICMP6_PARAMPROB_NEXTHEADER:
184 printf("icmp6: parameter problem next header - octet %u\n",
185 (u_int32_t)ntohl(dp->icmp6_pptr));
187 case ICMP6_PARAMPROB_OPTION:
188 printf("icmp6: parameter problem option - octet %u\n",
189 (u_int32_t)ntohl(dp->icmp6_pptr));
192 printf("icmp6: parameter problem code-#%d",
197 case ICMP6_ECHO_REQUEST:
198 printf("icmp6: echo request");
200 case ICMP6_ECHO_REPLY:
201 printf("icmp6: echo reply");
203 case ICMP6_MEMBERSHIP_QUERY:
204 printf("icmp6: multicast listener query ");
205 mld6_print((const u_char *)dp);
207 case ICMP6_MEMBERSHIP_REPORT:
208 printf("icmp6: multicast listener report ");
209 mld6_print((const u_char *)dp);
211 case ICMP6_MEMBERSHIP_REDUCTION:
212 printf("icmp6: multicast listener done ");
213 mld6_print((const u_char *)dp);
215 case ND_ROUTER_SOLICIT:
216 printf("icmp6: router solicitation ");
219 icmp6_opt_print((const u_char *)dp + RTSOLLEN,
220 icmp6len - RTSOLLEN);
223 case ND_ROUTER_ADVERT:
224 printf("icmp6: router advertisement");
226 struct nd_router_advert *p;
228 p = (struct nd_router_advert *)dp;
229 TCHECK(p->nd_ra_retransmit);
230 printf("(chlim=%d, ", (int)p->nd_ra_curhoplimit);
231 if (p->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED)
233 if (p->nd_ra_flags_reserved & ND_RA_FLAG_OTHER)
235 #ifndef ND_RA_FLAG_HA
236 #define ND_RA_FLAG_HA 0x20
238 if (p->nd_ra_flags_reserved & ND_RA_FLAG_HA)
240 if (p->nd_ra_flags_reserved != 0)
242 printf("router_ltime=%d, ", ntohs(p->nd_ra_router_lifetime));
243 printf("reachable_time=%u, ",
244 (u_int32_t)ntohl(p->nd_ra_reachable));
245 printf("retrans_time=%u)",
246 (u_int32_t)ntohl(p->nd_ra_retransmit));
248 icmp6_opt_print((const u_char *)dp + RTADVLEN,
249 icmp6len - RTADVLEN);
252 case ND_NEIGHBOR_SOLICIT:
254 struct nd_neighbor_solicit *p;
255 p = (struct nd_neighbor_solicit *)dp;
256 TCHECK(p->nd_ns_target);
257 printf("icmp6: neighbor sol: who has %s",
258 ip6addr_string(&p->nd_ns_target));
261 icmp6_opt_print((const u_char *)dp + NDSOLLEN,
262 icmp6len - NDSOLLEN);
266 case ND_NEIGHBOR_ADVERT:
268 struct nd_neighbor_advert *p;
270 p = (struct nd_neighbor_advert *)dp;
271 TCHECK(p->nd_na_target);
272 printf("icmp6: neighbor adv: tgt is %s",
273 ip6addr_string(&p->nd_na_target));
275 #define ND_NA_FLAG_ALL \
276 (ND_NA_FLAG_ROUTER|ND_NA_FLAG_SOLICITED|ND_NA_FLAG_OVERRIDE)
277 /* we don't need ntohl() here. see advanced-api-04. */
278 if (p->nd_na_flags_reserved & ND_NA_FLAG_ALL) {
279 #undef ND_NA_FLAG_ALL
282 flags = p->nd_na_flags_reserved;
284 if (flags & ND_NA_FLAG_ROUTER)
286 if (flags & ND_NA_FLAG_SOLICITED)
288 if (flags & ND_NA_FLAG_OVERRIDE)
293 icmp6_opt_print((const u_char *)dp + NDADVLEN,
294 icmp6len - NDADVLEN);
300 #define RDR(i) ((struct nd_redirect *)(i))
301 TCHECK(RDR(dp)->nd_rd_dst);
302 printf("icmp6: redirect %s",
303 getname6((const u_char *)&RDR(dp)->nd_rd_dst));
305 getname6((const u_char*)&RDR(dp)->nd_rd_target));
306 #define REDIRECTLEN 40
308 icmp6_opt_print((const u_char *)dp + REDIRECTLEN,
309 icmp6len - REDIRECTLEN);
314 case ICMP6_ROUTER_RENUMBERING:
315 icmp6_rrenum_print(icmp6len, bp, ep);
319 icmp6_nodeinfo_print(icmp6len, bp, ep);
322 printf("icmp6: type-#%d", dp->icmp6_type);
327 fputs("[|icmp6]", stdout);
333 static struct udphdr *
334 get_upperlayer(register u_char *bp, int *prot)
336 register const u_char *ep;
337 struct ip6_hdr *ip6 = (struct ip6_hdr *)bp;
340 struct ip6_frag *fragh;
344 /* 'ep' points to the end of available data. */
347 if (TTEST(ip6->ip6_nxt) == 0)
351 hlen = sizeof(struct ip6_hdr);
353 while (bp < snapend) {
359 uh = (struct udphdr *)bp;
360 if (TTEST(uh->uh_dport)) {
368 case IPPROTO_HOPOPTS:
369 case IPPROTO_DSTOPTS:
370 case IPPROTO_ROUTING:
371 hbh = (struct ip6_hbh *)bp;
372 if (TTEST(hbh->ip6h_len) == 0)
375 hlen = (hbh->ip6h_len + 1) << 3;
378 case IPPROTO_FRAGMENT: /* this should be odd, but try anyway */
379 fragh = (struct ip6_frag *)bp;
380 if (TTEST(fragh->ip6f_offlg) == 0)
382 /* fragments with non-zero offset are meaningless */
383 if ((fragh->ip6f_offlg & IP6F_OFF_MASK) != 0)
385 nh = fragh->ip6f_nxt;
386 hlen = sizeof(struct ip6_frag);
390 ah = (struct ah *)bp;
391 if (TTEST(ah->ah_len) == 0)
394 hlen = (ah->ah_len + 2) << 2;
397 default: /* unknown or undecodable header */
398 *prot = nh; /* meaningless, but set here anyway */
403 return(NULL); /* should be notreached, though */
407 icmp6_opt_print(register const u_char *bp, int resid)
409 register const struct nd_opt_hdr *op;
410 register const struct nd_opt_hdr *opl; /* why there's no struct? */
411 register const struct nd_opt_prefix_info *opp;
412 register const struct icmp6_opts_redirect *opr;
413 register const struct nd_opt_mtu *opm;
414 register const struct nd_opt_advint *opa;
415 register const u_char *ep;
418 register const struct ip6_hdr *ip;
419 register const char *str;
420 register const struct ip6_hdr *oip;
421 register const struct udphdr *ouh;
422 register int hlen, dport;
426 #define ECHECK(var) if ((u_char *)&(var) > ep - sizeof(var)) return
428 op = (struct nd_opt_hdr *)bp;
430 ip = (struct ip6_hdr *)bp2;
431 oip = &dp->icmp6_ip6;
434 /* 'ep' points to the end of available data. */
437 ECHECK(op->nd_opt_len);
440 switch (op->nd_opt_type) {
441 case ND_OPT_SOURCE_LINKADDR:
442 opl = (struct nd_opt_hdr *)op;
444 if ((u_char *)opl + (opl->nd_opt_len << 3) > ep)
447 TCHECK((u_char *)opl + (opl->nd_opt_len << 3) - 1);
449 printf("(src lladdr: %s", /*)*/
450 etheraddr_string((u_char *)(opl + 1)));
451 if (opl->nd_opt_len != 1)
455 icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3),
456 resid - (op->nd_opt_len << 3));
458 case ND_OPT_TARGET_LINKADDR:
459 opl = (struct nd_opt_hdr *)op;
461 if ((u_char *)opl + (opl->nd_opt_len << 3) > ep)
464 TCHECK((u_char *)opl + (opl->nd_opt_len << 3) - 1);
466 printf("(tgt lladdr: %s", /*)*/
467 etheraddr_string((u_char *)(opl + 1)));
468 if (opl->nd_opt_len != 1)
472 icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3),
473 resid - (op->nd_opt_len << 3));
475 case ND_OPT_PREFIX_INFORMATION:
476 opp = (struct nd_opt_prefix_info *)op;
477 TCHECK(opp->nd_opt_pi_prefix);
478 printf("(prefix info: "); /*)*/
479 if (opp->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ONLINK)
481 if (opp->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_AUTO)
483 if (opp->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ROUTER)
485 if (opp->nd_opt_pi_flags_reserved)
487 printf("valid_ltime=");
488 if ((u_int32_t)ntohl(opp->nd_opt_pi_valid_time) == ~0U)
491 printf("%u", (u_int32_t)ntohl(opp->nd_opt_pi_valid_time));
494 printf("preffered_ltime=");
495 if ((u_int32_t)ntohl(opp->nd_opt_pi_preferred_time) == ~0U)
498 printf("%u", (u_int32_t)ntohl(opp->nd_opt_pi_preferred_time));
501 printf("prefix=%s/%d", ip6addr_string(&opp->nd_opt_pi_prefix),
502 opp->nd_opt_pi_prefix_len);
503 if (opp->nd_opt_pi_len != 4)
507 icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3),
508 resid - (op->nd_opt_len << 3));
510 case ND_OPT_REDIRECTED_HEADER:
511 opr = (struct icmp6_opts_redirect *)op;
512 printf("(redirect)");
514 icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3),
515 resid - (op->nd_opt_len << 3));
518 opm = (struct nd_opt_mtu *)op;
519 TCHECK(opm->nd_opt_mtu_mtu);
520 printf("(mtu: "); /*)*/
521 printf("mtu=%u", (u_int32_t)ntohl(opm->nd_opt_mtu_mtu));
522 if (opm->nd_opt_mtu_len != 1)
525 icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3),
526 resid - (op->nd_opt_len << 3));
529 opa = (struct nd_opt_advint *)op;
530 TCHECK(opa->nd_opt_advint_advint);
531 printf("(advint: "); /*)*/
533 (u_int32_t)ntohl(opa->nd_opt_advint_advint));
536 icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3),
537 resid - (op->nd_opt_len << 3));
540 opts_len = op->nd_opt_len;
541 printf("(unknwon opt_type=%d, opt_len=%d)",
542 op->nd_opt_type, opts_len);
544 opts_len = 1; /* XXX */
545 icmp6_opt_print((const u_char *)op + (opts_len << 3),
546 resid - (opts_len << 3));
551 fputs("[ndp opt]", stdout);
557 mld6_print(register const u_char *bp)
559 register struct mld6_hdr *mp = (struct mld6_hdr *)bp;
560 register const u_char *ep;
562 /* 'ep' points to the end of available data. */
565 if ((u_char *)mp + sizeof(*mp) > ep)
568 printf("max resp delay: %d ", ntohs(mp->mld6_maxdelay));
569 printf("addr: %s", ip6addr_string(&mp->mld6_addr));
573 dnsname_print(const u_char *cp, const u_char *ep)
577 /* DNS name decoding - no decompression */
586 while (i-- && cp < ep) {
590 if (cp + 1 < ep && *cp)
596 } else if (cp + 1 == ep && *cp == '\0') {
609 icmp6_nodeinfo_print(int icmp6len, const u_char *bp, const u_char *ep)
611 struct icmp6_nodeinfo *ni6;
612 struct icmp6_hdr *dp;
617 dp = (struct icmp6_hdr *)bp;
618 ni6 = (struct icmp6_nodeinfo *)bp;
621 switch (ni6->ni_type) {
623 if (siz == sizeof(*dp) + 4) {
624 /* KAME who-are-you */
625 printf("icmp6: who-are-you request");
628 printf("icmp6: node information query");
630 TCHECK2(*dp, sizeof(*ni6));
631 ni6 = (struct icmp6_nodeinfo *)dp;
633 switch (ntohs(ni6->ni_qtype)) {
637 case NI_QTYPE_SUPTYPES:
638 printf("supported qtypes");
639 i = ntohs(ni6->ni_flags);
641 printf(" [%s]", (i & 0x01) ? "C" : "");
647 case NI_QTYPE_NODEADDR:
648 printf("node addresses");
652 /* NI_NODEADDR_FLAG_TRUNCATE undefined for query */
653 printf(" [%s%s%s%s%s%s]",
654 (i & NI_NODEADDR_FLAG_ANYCAST) ? "a" : "",
655 (i & NI_NODEADDR_FLAG_GLOBAL) ? "G" : "",
656 (i & NI_NODEADDR_FLAG_SITELOCAL) ? "S" : "",
657 (i & NI_NODEADDR_FLAG_LINKLOCAL) ? "L" : "",
658 (i & NI_NODEADDR_FLAG_COMPAT) ? "C" : "",
659 (i & NI_NODEADDR_FLAG_ALL) ? "A" : "");
666 if (ni6->ni_qtype == NI_QTYPE_NOOP ||
667 ni6->ni_qtype == NI_QTYPE_SUPTYPES) {
668 if (siz != sizeof(*ni6))
670 printf(", invalid len");
677 /* XXX backward compat, icmp-name-lookup-03 */
678 if (siz == sizeof(*ni6)) {
679 printf(", 03 draft");
685 switch (ni6->ni_code) {
686 case ICMP6_NI_SUBJ_IPV6:
688 sizeof(*ni6) + sizeof(struct in6_addr)))
690 if (siz != sizeof(*ni6) + sizeof(struct in6_addr)) {
692 printf(", invalid subject len");
695 printf(", subject=%s",
696 getname6((const u_char *)(ni6 + 1)));
698 case ICMP6_NI_SUBJ_FQDN:
699 printf(", subject=DNS name");
700 cp = (const u_char *)(ni6 + 1);
701 if (cp[0] == ep - cp - 1) {
702 /* icmp-name-lookup-03, pascal string */
704 printf(", 03 draft");
713 dnsname_print(cp, ep);
715 case ICMP6_NI_SUBJ_IPV4:
716 if (!TTEST2(*dp, sizeof(*ni6) + sizeof(struct in_addr)))
718 if (siz != sizeof(*ni6) + sizeof(struct in_addr)) {
720 printf(", invalid subject len");
723 printf(", subject=%s",
724 getname((const u_char *)(ni6 + 1)));
727 printf(", unknown subject");
736 if (icmp6len > siz) {
737 printf("[|icmp6: node information reply]");
743 ni6 = (struct icmp6_nodeinfo *)dp;
744 printf("icmp6: node information reply");
746 switch (ni6->ni_code) {
747 case ICMP6_NI_SUCCESS:
753 case ICMP6_NI_REFUSED:
756 if (siz != sizeof(*ni6))
758 printf(", invalid length");
760 case ICMP6_NI_UNKNOWN:
763 if (siz != sizeof(*ni6))
765 printf(", invalid length");
769 if (ni6->ni_code != ICMP6_NI_SUCCESS) {
775 switch (ntohs(ni6->ni_qtype)) {
780 if (siz != sizeof(*ni6))
782 printf(", invalid length");
784 case NI_QTYPE_SUPTYPES:
787 printf("supported qtypes");
788 i = ntohs(ni6->ni_flags);
790 printf(" [%s]", (i & 0x01) ? "C" : "");
796 cp = (const u_char *)(ni6 + 1) + 4;
797 if (cp[0] == ep - cp - 1) {
798 /* icmp-name-lookup-03, pascal string */
800 printf(", 03 draft");
809 dnsname_print(cp, ep);
810 if ((ntohs(ni6->ni_flags) & 0x01) != 0)
811 printf(" [TTL=%u]", *(u_int32_t *)(ni6 + 1));
813 case NI_QTYPE_NODEADDR:
816 printf("node addresses");
819 if (i + sizeof(struct in6_addr) + sizeof(int32_t) > siz)
821 printf(" %s", getname6(bp + i));
822 i += sizeof(struct in6_addr);
823 printf("(%d)", ntohl(*(int32_t *)(bp + i)));
824 i += sizeof(int32_t);
829 printf(" [%s%s%s%s%s%s%s]",
830 (i & NI_NODEADDR_FLAG_ANYCAST) ? "a" : "",
831 (i & NI_NODEADDR_FLAG_GLOBAL) ? "G" : "",
832 (i & NI_NODEADDR_FLAG_SITELOCAL) ? "S" : "",
833 (i & NI_NODEADDR_FLAG_LINKLOCAL) ? "L" : "",
834 (i & NI_NODEADDR_FLAG_COMPAT) ? "C" : "",
835 (i & NI_NODEADDR_FLAG_ALL) ? "A" : "",
836 (i & NI_NODEADDR_FLAG_TRUNCATE) ? "T" : "");
852 fputs("[|icmp6]", stdout);
856 icmp6_rrenum_print(int icmp6len, const u_char *bp, const u_char *ep)
858 struct icmp6_router_renum *rr6;
859 struct icmp6_hdr *dp;
862 struct rr_pco_match *match;
863 struct rr_pco_use *use;
864 char hbuf[NI_MAXHOST];
867 dp = (struct icmp6_hdr *)bp;
868 rr6 = (struct icmp6_router_renum *)bp;
870 cp = (const char *)(rr6 + 1);
872 TCHECK(rr6->rr_reserved);
873 switch (rr6->rr_code) {
874 case ICMP6_ROUTER_RENUMBERING_COMMAND:
875 printf("router renum: command");
877 case ICMP6_ROUTER_RENUMBERING_RESULT:
878 printf("router renum: result");
880 case ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET:
881 printf("router renum: sequence number reset");
884 printf("router renum: code-#%d", rr6->rr_code);
888 printf(", seq=%u", (u_int32_t)ntohl(rr6->rr_seqnum));
891 #define F(x, y) ((rr6->rr_flags) & (x) ? (y) : "")
894 printf("%s%s%s%s%s,", F(ICMP6_RR_FLAGS_TEST, "T"),
895 F(ICMP6_RR_FLAGS_REQRESULT, "R"),
896 F(ICMP6_RR_FLAGS_ALLIF, "A"),
897 F(ICMP6_RR_FLAGS_SPECSITE, "S"),
898 F(ICMP6_RR_FLAGS_PREVDONE, "P"));
900 printf("seg=%u,", rr6->rr_segnum);
901 printf("maxdelay=%u", rr6->rr_maxdelay);
902 if (rr6->rr_reserved)
903 printf("rsvd=0x%x", (u_int16_t)ntohs(rr6->rr_reserved));
909 if (rr6->rr_code == ICMP6_ROUTER_RENUMBERING_COMMAND) {
910 match = (struct rr_pco_match *)cp;
911 cp = (const char *)(match + 1);
913 TCHECK(match->rpm_prefix);
919 printf("match("); /*)*/
920 switch (match->rpm_code) {
921 case RPM_PCO_ADD: printf("add"); break;
922 case RPM_PCO_CHANGE: printf("change"); break;
923 case RPM_PCO_SETGLOBAL: printf("setglobal"); break;
924 default: printf("#%u", match->rpm_code); break;
928 printf(",ord=%u", match->rpm_ordinal);
929 printf(",min=%u", match->rpm_minlen);
930 printf(",max=%u", match->rpm_maxlen);
932 if (inet_ntop(AF_INET6, &match->rpm_prefix, hbuf, sizeof(hbuf)))
933 printf(",%s/%u", hbuf, match->rpm_matchlen);
935 printf(",?/%u", match->rpm_matchlen);
939 n = match->rpm_len - 3;
944 use = (struct rr_pco_use *)cp;
945 cp = (const char *)(use + 1);
947 TCHECK(use->rpu_prefix);
953 printf("use("); /*)*/
954 if (use->rpu_flags) {
955 #define F(x, y) ((use->rpu_flags) & (x) ? (y) : "")
957 F(ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME, "V"),
958 F(ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME, "P"));
962 printf("mask=0x%x,", use->rpu_ramask);
963 printf("raflags=0x%x,", use->rpu_raflags);
964 if (~use->rpu_vltime == 0)
965 printf("vltime=infty,");
968 (u_int32_t)ntohl(use->rpu_vltime));
969 if (~use->rpu_pltime == 0)
970 printf("pltime=infty,");
973 (u_int32_t)ntohl(use->rpu_pltime));
975 if (inet_ntop(AF_INET6, &use->rpu_prefix, hbuf,
977 printf("%s/%u/%u", hbuf, use->rpu_uselen,
980 printf("?/%u/%u", use->rpu_uselen,
990 fputs("[|icmp6]", stdout);