1 /* 2 * Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 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 16 * written permission. 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. 20 */ 21 22 #ifndef lint 23 static const char rcsid[] = 24 "@(#) $Header: /tcpdump/master/tcpdump/print-icmp6.c,v 1.42 2000/12/13 07:57:05 itojun Exp $"; 25 #endif 26 27 #ifdef HAVE_CONFIG_H 28 #include "config.h" 29 #endif 30 31 #ifdef INET6 32 33 #include <ctype.h> 34 35 #include <sys/param.h> 36 #include <sys/time.h> 37 #include <sys/types.h> 38 #include <sys/socket.h> 39 40 41 #include <netinet/in.h> 42 43 #include <arpa/inet.h> 44 45 #include <stdio.h> 46 #include <netdb.h> 47 48 #include "ip6.h" 49 #include "icmp6.h" 50 51 #include "interface.h" 52 #include "addrtoname.h" 53 54 #include "udp.h" 55 #include "ah.h" 56 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 *); 63 64 #ifndef abs 65 #define abs(a) ((0 < (a)) ? (a) : -(a)) 66 #endif 67 68 void 69 icmp6_print(register const u_char *bp, register const u_char *bp2) 70 { 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; 76 register int dport; 77 register const u_char *ep; 78 char buf[256]; 79 int icmp6len, prot; 80 81 #if 0 82 #define TCHECK(var) if ((u_char *)&(var) > ep - sizeof(var)) goto trunc 83 #endif 84 85 dp = (struct icmp6_hdr *)bp; 86 ip = (struct ip6_hdr *)bp2; 87 oip = (struct ip6_hdr *)(dp + 1); 88 str = buf; 89 /* 'ep' points to the end of available data. */ 90 ep = snapend; 91 if (ip->ip6_plen) 92 icmp6len = (ntohs(ip->ip6_plen) + sizeof(struct ip6_hdr) - 93 (bp - bp2)); 94 else /* XXX: jumbo payload case... */ 95 icmp6len = snapend - bp; 96 97 #if 0 98 (void)printf("%s > %s: ", 99 ip6addr_string(&ip->ip6_src), 100 ip6addr_string(&ip->ip6_dst)); 101 #endif 102 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)); 111 break; 112 case ICMP6_DST_UNREACH_ADMIN: 113 printf("icmp6: %s unreachable prohibited", 114 ip6addr_string(&oip->ip6_dst)); 115 break; 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)); 120 break; 121 case ICMP6_DST_UNREACH_ADDR: 122 printf("icmp6: %s unreachable address", 123 ip6addr_string(&oip->ip6_dst)); 124 break; 125 case ICMP6_DST_UNREACH_NOPORT: 126 if ((ouh = get_upperlayer((u_char *)oip, &prot)) 127 == NULL) 128 goto trunc; 129 130 dport = ntohs(ouh->uh_dport); 131 switch (prot) { 132 case IPPROTO_TCP: 133 printf("icmp6: %s tcp port %s unreachable", 134 ip6addr_string(&oip->ip6_dst), 135 tcpport_string(dport)); 136 break; 137 case IPPROTO_UDP: 138 printf("icmp6: %s udp port %s unreachable", 139 ip6addr_string(&oip->ip6_dst), 140 udpport_string(dport)); 141 break; 142 default: 143 printf("icmp6: %s protocol %d port %d unreachable", 144 ip6addr_string(&oip->ip6_dst), 145 oip->ip6_nxt, dport); 146 break; 147 } 148 break; 149 default: 150 printf("icmp6: %s unreachable code-#%d", 151 ip6addr_string(&oip->ip6_dst), 152 dp->icmp6_code); 153 break; 154 } 155 break; 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)); 159 break; 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)); 166 break; 167 case ICMP6_TIME_EXCEED_REASSEMBLY: 168 printf("icmp6: ip6 reassembly time exceeded"); 169 break; 170 default: 171 printf("icmp6: time exceeded code-#%d", 172 dp->icmp6_code); 173 break; 174 } 175 break; 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)); 182 break; 183 case ICMP6_PARAMPROB_NEXTHEADER: 184 printf("icmp6: parameter problem next header - octet %u\n", 185 (u_int32_t)ntohl(dp->icmp6_pptr)); 186 break; 187 case ICMP6_PARAMPROB_OPTION: 188 printf("icmp6: parameter problem option - octet %u\n", 189 (u_int32_t)ntohl(dp->icmp6_pptr)); 190 break; 191 default: 192 printf("icmp6: parameter problem code-#%d", 193 dp->icmp6_code); 194 break; 195 } 196 break; 197 case ICMP6_ECHO_REQUEST: 198 printf("icmp6: echo request"); 199 break; 200 case ICMP6_ECHO_REPLY: 201 printf("icmp6: echo reply"); 202 break; 203 case ICMP6_MEMBERSHIP_QUERY: 204 printf("icmp6: multicast listener query "); 205 mld6_print((const u_char *)dp); 206 break; 207 case ICMP6_MEMBERSHIP_REPORT: 208 printf("icmp6: multicast listener report "); 209 mld6_print((const u_char *)dp); 210 break; 211 case ICMP6_MEMBERSHIP_REDUCTION: 212 printf("icmp6: multicast listener done "); 213 mld6_print((const u_char *)dp); 214 break; 215 case ND_ROUTER_SOLICIT: 216 printf("icmp6: router solicitation "); 217 if (vflag) { 218 #define RTSOLLEN 8 219 icmp6_opt_print((const u_char *)dp + RTSOLLEN, 220 icmp6len - RTSOLLEN); 221 } 222 break; 223 case ND_ROUTER_ADVERT: 224 printf("icmp6: router advertisement"); 225 if (vflag) { 226 struct nd_router_advert *p; 227 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) 232 printf("M"); 233 if (p->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) 234 printf("O"); 235 #ifndef ND_RA_FLAG_HA 236 #define ND_RA_FLAG_HA 0x20 237 #endif 238 if (p->nd_ra_flags_reserved & ND_RA_FLAG_HA) 239 printf("H"); 240 if (p->nd_ra_flags_reserved != 0) 241 printf(" "); 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)); 247 #define RTADVLEN 16 248 icmp6_opt_print((const u_char *)dp + RTADVLEN, 249 icmp6len - RTADVLEN); 250 } 251 break; 252 case ND_NEIGHBOR_SOLICIT: 253 { 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)); 259 if (vflag) { 260 #define NDSOLLEN 24 261 icmp6_opt_print((const u_char *)dp + NDSOLLEN, 262 icmp6len - NDSOLLEN); 263 } 264 } 265 break; 266 case ND_NEIGHBOR_ADVERT: 267 { 268 struct nd_neighbor_advert *p; 269 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)); 274 if (vflag) { 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 280 u_int32_t flags; 281 282 flags = p->nd_na_flags_reserved; 283 printf("("); 284 if (flags & ND_NA_FLAG_ROUTER) 285 printf("R"); 286 if (flags & ND_NA_FLAG_SOLICITED) 287 printf("S"); 288 if (flags & ND_NA_FLAG_OVERRIDE) 289 printf("O"); 290 printf(")"); 291 } 292 #define NDADVLEN 24 293 icmp6_opt_print((const u_char *)dp + NDADVLEN, 294 icmp6len - NDADVLEN); 295 #undef NDADVLEN 296 } 297 } 298 break; 299 case ND_REDIRECT: 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)); 304 printf(" to %s", 305 getname6((const u_char*)&RDR(dp)->nd_rd_target)); 306 #define REDIRECTLEN 40 307 if (vflag) { 308 icmp6_opt_print((const u_char *)dp + REDIRECTLEN, 309 icmp6len - REDIRECTLEN); 310 } 311 break; 312 #undef REDIRECTLEN 313 #undef RDR 314 case ICMP6_ROUTER_RENUMBERING: 315 icmp6_rrenum_print(icmp6len, bp, ep); 316 break; 317 case ICMP6_NI_QUERY: 318 case ICMP6_NI_REPLY: 319 icmp6_nodeinfo_print(icmp6len, bp, ep); 320 break; 321 default: 322 printf("icmp6: type-#%d", dp->icmp6_type); 323 break; 324 } 325 return; 326 trunc: 327 fputs("[|icmp6]", stdout); 328 #if 0 329 #undef TCHECK 330 #endif 331 } 332 333 static struct udphdr * 334 get_upperlayer(register u_char *bp, int *prot) 335 { 336 register const u_char *ep; 337 struct ip6_hdr *ip6 = (struct ip6_hdr *)bp; 338 struct udphdr *uh; 339 struct ip6_hbh *hbh; 340 struct ip6_frag *fragh; 341 struct ah *ah; 342 int nh, hlen; 343 344 /* 'ep' points to the end of available data. */ 345 ep = snapend; 346 347 if (TTEST(ip6->ip6_nxt) == 0) 348 return NULL; 349 350 nh = ip6->ip6_nxt; 351 hlen = sizeof(struct ip6_hdr); 352 353 while (bp < snapend) { 354 bp += hlen; 355 356 switch(nh) { 357 case IPPROTO_UDP: 358 case IPPROTO_TCP: 359 uh = (struct udphdr *)bp; 360 if (TTEST(uh->uh_dport)) { 361 *prot = nh; 362 return(uh); 363 } 364 else 365 return(NULL); 366 /* NOTREACHED */ 367 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) 373 return(NULL); 374 nh = hbh->ip6h_nxt; 375 hlen = (hbh->ip6h_len + 1) << 3; 376 break; 377 378 case IPPROTO_FRAGMENT: /* this should be odd, but try anyway */ 379 fragh = (struct ip6_frag *)bp; 380 if (TTEST(fragh->ip6f_offlg) == 0) 381 return(NULL); 382 /* fragments with non-zero offset are meaningless */ 383 if ((fragh->ip6f_offlg & IP6F_OFF_MASK) != 0) 384 return(NULL); 385 nh = fragh->ip6f_nxt; 386 hlen = sizeof(struct ip6_frag); 387 break; 388 389 case IPPROTO_AH: 390 ah = (struct ah *)bp; 391 if (TTEST(ah->ah_len) == 0) 392 return(NULL); 393 nh = ah->ah_nxt; 394 hlen = (ah->ah_len + 2) << 2; 395 break; 396 397 default: /* unknown or undecodable header */ 398 *prot = nh; /* meaningless, but set here anyway */ 399 return(NULL); 400 } 401 } 402 403 return(NULL); /* should be notreached, though */ 404 } 405 406 void 407 icmp6_opt_print(register const u_char *bp, int resid) 408 { 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; 416 int opts_len; 417 #if 0 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; 423 char buf[256]; 424 #endif 425 426 #define ECHECK(var) if ((u_char *)&(var) > ep - sizeof(var)) return 427 428 op = (struct nd_opt_hdr *)bp; 429 #if 0 430 ip = (struct ip6_hdr *)bp2; 431 oip = &dp->icmp6_ip6; 432 str = buf; 433 #endif 434 /* 'ep' points to the end of available data. */ 435 ep = snapend; 436 437 ECHECK(op->nd_opt_len); 438 if (resid <= 0) 439 return; 440 switch (op->nd_opt_type) { 441 case ND_OPT_SOURCE_LINKADDR: 442 opl = (struct nd_opt_hdr *)op; 443 #if 1 444 if ((u_char *)opl + (opl->nd_opt_len << 3) > ep) 445 goto trunc; 446 #else 447 TCHECK((u_char *)opl + (opl->nd_opt_len << 3) - 1); 448 #endif 449 printf("(src lladdr: %s", /*)*/ 450 etheraddr_string((u_char *)(opl + 1))); 451 if (opl->nd_opt_len != 1) 452 printf("!"); 453 /*(*/ 454 printf(")"); 455 icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3), 456 resid - (op->nd_opt_len << 3)); 457 break; 458 case ND_OPT_TARGET_LINKADDR: 459 opl = (struct nd_opt_hdr *)op; 460 #if 1 461 if ((u_char *)opl + (opl->nd_opt_len << 3) > ep) 462 goto trunc; 463 #else 464 TCHECK((u_char *)opl + (opl->nd_opt_len << 3) - 1); 465 #endif 466 printf("(tgt lladdr: %s", /*)*/ 467 etheraddr_string((u_char *)(opl + 1))); 468 if (opl->nd_opt_len != 1) 469 printf("!"); 470 /*(*/ 471 printf(")"); 472 icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3), 473 resid - (op->nd_opt_len << 3)); 474 break; 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) 480 printf("L"); 481 if (opp->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_AUTO) 482 printf("A"); 483 if (opp->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ROUTER) 484 printf("R"); 485 if (opp->nd_opt_pi_flags_reserved) 486 printf(" "); 487 printf("valid_ltime="); 488 if ((u_int32_t)ntohl(opp->nd_opt_pi_valid_time) == ~0U) 489 printf("infinity"); 490 else { 491 printf("%u", (u_int32_t)ntohl(opp->nd_opt_pi_valid_time)); 492 } 493 printf(", "); 494 printf("preffered_ltime="); 495 if ((u_int32_t)ntohl(opp->nd_opt_pi_preferred_time) == ~0U) 496 printf("infinity"); 497 else { 498 printf("%u", (u_int32_t)ntohl(opp->nd_opt_pi_preferred_time)); 499 } 500 printf(", "); 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) 504 printf("!"); 505 /*(*/ 506 printf(")"); 507 icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3), 508 resid - (op->nd_opt_len << 3)); 509 break; 510 case ND_OPT_REDIRECTED_HEADER: 511 opr = (struct icmp6_opts_redirect *)op; 512 printf("(redirect)"); 513 /* xxx */ 514 icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3), 515 resid - (op->nd_opt_len << 3)); 516 break; 517 case ND_OPT_MTU: 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) 523 printf("!"); 524 printf(")"); 525 icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3), 526 resid - (op->nd_opt_len << 3)); 527 break; 528 case ND_OPT_ADVINT: 529 opa = (struct nd_opt_advint *)op; 530 TCHECK(opa->nd_opt_advint_advint); 531 printf("(advint: "); /*)*/ 532 printf("advint=%u", 533 (u_int32_t)ntohl(opa->nd_opt_advint_advint)); 534 /*(*/ 535 printf(")"); 536 icmp6_opt_print((const u_char *)op + (op->nd_opt_len << 3), 537 resid - (op->nd_opt_len << 3)); 538 break; 539 default: 540 opts_len = op->nd_opt_len; 541 printf("(unknwon opt_type=%d, opt_len=%d)", 542 op->nd_opt_type, opts_len); 543 if (opts_len == 0) 544 opts_len = 1; /* XXX */ 545 icmp6_opt_print((const u_char *)op + (opts_len << 3), 546 resid - (opts_len << 3)); 547 break; 548 } 549 return; 550 trunc: 551 fputs("[ndp opt]", stdout); 552 return; 553 #undef ECHECK 554 } 555 556 void 557 mld6_print(register const u_char *bp) 558 { 559 register struct mld6_hdr *mp = (struct mld6_hdr *)bp; 560 register const u_char *ep; 561 562 /* 'ep' points to the end of available data. */ 563 ep = snapend; 564 565 if ((u_char *)mp + sizeof(*mp) > ep) 566 return; 567 568 printf("max resp delay: %d ", ntohs(mp->mld6_maxdelay)); 569 printf("addr: %s", ip6addr_string(&mp->mld6_addr)); 570 } 571 572 static void 573 dnsname_print(const u_char *cp, const u_char *ep) 574 { 575 int i; 576 577 /* DNS name decoding - no decompression */ 578 printf(", \""); 579 while (cp < ep) { 580 i = *cp++; 581 if (i) { 582 if (i > ep - cp) { 583 printf("???"); 584 break; 585 } 586 while (i-- && cp < ep) { 587 safeputchar(*cp); 588 cp++; 589 } 590 if (cp + 1 < ep && *cp) 591 printf("."); 592 } else { 593 if (cp == ep) { 594 /* FQDN */ 595 printf("."); 596 } else if (cp + 1 == ep && *cp == '\0') { 597 /* truncated */ 598 } else { 599 /* invalid */ 600 printf("???"); 601 } 602 break; 603 } 604 } 605 printf("\""); 606 } 607 608 void 609 icmp6_nodeinfo_print(int icmp6len, const u_char *bp, const u_char *ep) 610 { 611 struct icmp6_nodeinfo *ni6; 612 struct icmp6_hdr *dp; 613 const u_char *cp; 614 int siz, i; 615 int needcomma; 616 617 dp = (struct icmp6_hdr *)bp; 618 ni6 = (struct icmp6_nodeinfo *)bp; 619 siz = ep - bp; 620 621 switch (ni6->ni_type) { 622 case ICMP6_NI_QUERY: 623 if (siz == sizeof(*dp) + 4) { 624 /* KAME who-are-you */ 625 printf("icmp6: who-are-you request"); 626 break; 627 } 628 printf("icmp6: node information query"); 629 630 TCHECK2(*dp, sizeof(*ni6)); 631 ni6 = (struct icmp6_nodeinfo *)dp; 632 printf(" ("); /*)*/ 633 switch (ntohs(ni6->ni_qtype)) { 634 case NI_QTYPE_NOOP: 635 printf("noop"); 636 break; 637 case NI_QTYPE_SUPTYPES: 638 printf("supported qtypes"); 639 i = ntohs(ni6->ni_flags); 640 if (i) 641 printf(" [%s]", (i & 0x01) ? "C" : ""); 642 break; 643 break; 644 case NI_QTYPE_FQDN: 645 printf("DNS name"); 646 break; 647 case NI_QTYPE_NODEADDR: 648 printf("node addresses"); 649 i = ni6->ni_flags; 650 if (!i) 651 break; 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" : ""); 660 break; 661 default: 662 printf("unknown"); 663 break; 664 } 665 666 if (ni6->ni_qtype == NI_QTYPE_NOOP || 667 ni6->ni_qtype == NI_QTYPE_SUPTYPES) { 668 if (siz != sizeof(*ni6)) 669 if (vflag) 670 printf(", invalid len"); 671 /*(*/ 672 printf(")"); 673 break; 674 } 675 676 677 /* XXX backward compat, icmp-name-lookup-03 */ 678 if (siz == sizeof(*ni6)) { 679 printf(", 03 draft"); 680 /*(*/ 681 printf(")"); 682 break; 683 } 684 685 switch (ni6->ni_code) { 686 case ICMP6_NI_SUBJ_IPV6: 687 if (!TTEST2(*dp, 688 sizeof(*ni6) + sizeof(struct in6_addr))) 689 break; 690 if (siz != sizeof(*ni6) + sizeof(struct in6_addr)) { 691 if (vflag) 692 printf(", invalid subject len"); 693 break; 694 } 695 printf(", subject=%s", 696 getname6((const u_char *)(ni6 + 1))); 697 break; 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 */ 703 if (vflag) 704 printf(", 03 draft"); 705 cp++; 706 printf(", \""); 707 while (cp < ep) { 708 safeputchar(*cp); 709 cp++; 710 } 711 printf("\""); 712 } else 713 dnsname_print(cp, ep); 714 break; 715 case ICMP6_NI_SUBJ_IPV4: 716 if (!TTEST2(*dp, sizeof(*ni6) + sizeof(struct in_addr))) 717 break; 718 if (siz != sizeof(*ni6) + sizeof(struct in_addr)) { 719 if (vflag) 720 printf(", invalid subject len"); 721 break; 722 } 723 printf(", subject=%s", 724 getname((const u_char *)(ni6 + 1))); 725 break; 726 default: 727 printf(", unknown subject"); 728 break; 729 } 730 731 /*(*/ 732 printf(")"); 733 break; 734 735 case ICMP6_NI_REPLY: 736 if (icmp6len > siz) { 737 printf("[|icmp6: node information reply]"); 738 break; 739 } 740 741 needcomma = 0; 742 743 ni6 = (struct icmp6_nodeinfo *)dp; 744 printf("icmp6: node information reply"); 745 printf(" ("); /*)*/ 746 switch (ni6->ni_code) { 747 case ICMP6_NI_SUCCESS: 748 if (vflag) { 749 printf("success"); 750 needcomma++; 751 } 752 break; 753 case ICMP6_NI_REFUSED: 754 printf("refused"); 755 needcomma++; 756 if (siz != sizeof(*ni6)) 757 if (vflag) 758 printf(", invalid length"); 759 break; 760 case ICMP6_NI_UNKNOWN: 761 printf("unknown"); 762 needcomma++; 763 if (siz != sizeof(*ni6)) 764 if (vflag) 765 printf(", invalid length"); 766 break; 767 } 768 769 if (ni6->ni_code != ICMP6_NI_SUCCESS) { 770 /*(*/ 771 printf(")"); 772 break; 773 } 774 775 switch (ntohs(ni6->ni_qtype)) { 776 case NI_QTYPE_NOOP: 777 if (needcomma) 778 printf(", "); 779 printf("noop"); 780 if (siz != sizeof(*ni6)) 781 if (vflag) 782 printf(", invalid length"); 783 break; 784 case NI_QTYPE_SUPTYPES: 785 if (needcomma) 786 printf(", "); 787 printf("supported qtypes"); 788 i = ntohs(ni6->ni_flags); 789 if (i) 790 printf(" [%s]", (i & 0x01) ? "C" : ""); 791 break; 792 case NI_QTYPE_FQDN: 793 if (needcomma) 794 printf(", "); 795 printf("DNS name"); 796 cp = (const u_char *)(ni6 + 1) + 4; 797 if (cp[0] == ep - cp - 1) { 798 /* icmp-name-lookup-03, pascal string */ 799 if (vflag) 800 printf(", 03 draft"); 801 cp++; 802 printf(", \""); 803 while (cp < ep) { 804 safeputchar(*cp); 805 cp++; 806 } 807 printf("\""); 808 } else 809 dnsname_print(cp, ep); 810 if ((ntohs(ni6->ni_flags) & 0x01) != 0) 811 printf(" [TTL=%u]", *(u_int32_t *)(ni6 + 1)); 812 break; 813 case NI_QTYPE_NODEADDR: 814 if (needcomma) 815 printf(", "); 816 printf("node addresses"); 817 i = sizeof(*ni6); 818 while (i < siz) { 819 if (i + sizeof(struct in6_addr) + sizeof(int32_t) > siz) 820 break; 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); 825 } 826 i = ni6->ni_flags; 827 if (!i) 828 break; 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" : ""); 837 break; 838 default: 839 if (needcomma) 840 printf(", "); 841 printf("unknown"); 842 break; 843 } 844 845 /*(*/ 846 printf(")"); 847 break; 848 } 849 return; 850 851 trunc: 852 fputs("[|icmp6]", stdout); 853 } 854 855 void 856 icmp6_rrenum_print(int icmp6len, const u_char *bp, const u_char *ep) 857 { 858 struct icmp6_router_renum *rr6; 859 struct icmp6_hdr *dp; 860 size_t siz; 861 const char *cp; 862 struct rr_pco_match *match; 863 struct rr_pco_use *use; 864 char hbuf[NI_MAXHOST]; 865 int n; 866 867 dp = (struct icmp6_hdr *)bp; 868 rr6 = (struct icmp6_router_renum *)bp; 869 siz = ep - bp; 870 cp = (const char *)(rr6 + 1); 871 872 TCHECK(rr6->rr_reserved); 873 switch (rr6->rr_code) { 874 case ICMP6_ROUTER_RENUMBERING_COMMAND: 875 printf("router renum: command"); 876 break; 877 case ICMP6_ROUTER_RENUMBERING_RESULT: 878 printf("router renum: result"); 879 break; 880 case ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET: 881 printf("router renum: sequence number reset"); 882 break; 883 default: 884 printf("router renum: code-#%d", rr6->rr_code); 885 break; 886 } 887 888 printf(", seq=%u", (u_int32_t)ntohl(rr6->rr_seqnum)); 889 890 if (vflag) { 891 #define F(x, y) ((rr6->rr_flags) & (x) ? (y) : "") 892 printf("["); /*]*/ 893 if (rr6->rr_flags) { 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")); 899 } 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)); 904 /*[*/ 905 printf("]"); 906 #undef F 907 } 908 909 if (rr6->rr_code == ICMP6_ROUTER_RENUMBERING_COMMAND) { 910 match = (struct rr_pco_match *)cp; 911 cp = (const char *)(match + 1); 912 913 TCHECK(match->rpm_prefix); 914 915 if (vflag) 916 printf("\n\t"); 917 else 918 printf(" "); 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; 925 } 926 927 if (vflag) { 928 printf(",ord=%u", match->rpm_ordinal); 929 printf(",min=%u", match->rpm_minlen); 930 printf(",max=%u", match->rpm_maxlen); 931 } 932 if (inet_ntop(AF_INET6, &match->rpm_prefix, hbuf, sizeof(hbuf))) 933 printf(",%s/%u", hbuf, match->rpm_matchlen); 934 else 935 printf(",?/%u", match->rpm_matchlen); 936 /*(*/ 937 printf(")"); 938 939 n = match->rpm_len - 3; 940 if (n % 4) 941 goto trunc; 942 n /= 4; 943 while (n-- > 0) { 944 use = (struct rr_pco_use *)cp; 945 cp = (const char *)(use + 1); 946 947 TCHECK(use->rpu_prefix); 948 949 if (vflag) 950 printf("\n\t"); 951 else 952 printf(" "); 953 printf("use("); /*)*/ 954 if (use->rpu_flags) { 955 #define F(x, y) ((use->rpu_flags) & (x) ? (y) : "") 956 printf("%s%s,", 957 F(ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME, "V"), 958 F(ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME, "P")); 959 #undef F 960 } 961 if (vflag) { 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,"); 966 else 967 printf("vltime=%u,", 968 (u_int32_t)ntohl(use->rpu_vltime)); 969 if (~use->rpu_pltime == 0) 970 printf("pltime=infty,"); 971 else 972 printf("pltime=%u,", 973 (u_int32_t)ntohl(use->rpu_pltime)); 974 } 975 if (inet_ntop(AF_INET6, &use->rpu_prefix, hbuf, 976 sizeof(hbuf))) 977 printf("%s/%u/%u", hbuf, use->rpu_uselen, 978 use->rpu_keeplen); 979 else 980 printf("?/%u/%u", use->rpu_uselen, 981 use->rpu_keeplen); 982 /*(*/ 983 printf(")"); 984 } 985 } 986 987 return; 988 989 trunc: 990 fputs("[|icmp6]", stdout); 991 } 992 993 #endif /* INET6 */ 994