1 /* 2 * Copyright (c) 1995, 1996 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 * $FreeBSD$ 22 */ 23 24 #ifndef lint 25 static const char rcsid[] = 26 "@(#) $Header: /tcpdump/master/tcpdump/print-pim.c,v 1.29 2001/07/04 21:36:15 fenner Exp $ (LBL)"; 27 #endif 28 29 #ifdef HAVE_CONFIG_H 30 #include "config.h" 31 #endif 32 33 #include <sys/param.h> 34 #include <sys/time.h> 35 #include <sys/socket.h> 36 37 #include <netinet/in.h> 38 39 /* 40 * XXX: We consider a case where IPv6 is not ready yet for portability, 41 * but PIM dependent defintions should be independent of IPv6... 42 */ 43 44 struct pim { 45 u_int8_t pim_typever; 46 /* upper 4bit: PIM version number; 2 for PIMv2 */ 47 /* lower 4bit: the PIM message type, currently they are: 48 * Hello, Register, Register-Stop, Join/Prune, 49 * Bootstrap, Assert, Graft (PIM-DM only), 50 * Graft-Ack (PIM-DM only), C-RP-Adv 51 */ 52 #define PIM_VER(x) (((x) & 0xf0) >> 4) 53 #define PIM_TYPE(x) ((x) & 0x0f) 54 u_char pim_rsv; /* Reserved */ 55 u_short pim_cksum; /* IP style check sum */ 56 }; 57 58 59 #include <stdio.h> 60 #include <stdlib.h> 61 #include <unistd.h> 62 63 #include "interface.h" 64 #include "addrtoname.h" 65 #include "extract.h" 66 67 #include "ip.h" 68 69 static void pimv2_print(register const u_char *bp, register u_int len); 70 71 static void 72 pimv1_join_prune_print(register const u_char *bp, register u_int len) 73 { 74 int maddrlen, addrlen, ngroups, njoin, nprune; 75 int njp; 76 77 /* If it's a single group and a single source, use 1-line output. */ 78 if (TTEST2(bp[0], 30) && bp[11] == 1 && 79 ((njoin = EXTRACT_16BITS(&bp[20])) + EXTRACT_16BITS(&bp[22])) == 1) { 80 int hold; 81 82 (void)printf(" RPF %s ", ipaddr_string(bp)); 83 hold = EXTRACT_16BITS(&bp[6]); 84 if (hold != 180) { 85 (void)printf("Hold "); 86 relts_print(hold); 87 } 88 (void)printf("%s (%s/%d, %s", njoin ? "Join" : "Prune", 89 ipaddr_string(&bp[26]), bp[25] & 0x3f, 90 ipaddr_string(&bp[12])); 91 if (EXTRACT_32BITS(&bp[16]) != 0xffffffff) 92 (void)printf("/%s", ipaddr_string(&bp[16])); 93 (void)printf(") %s%s %s", 94 (bp[24] & 0x01) ? "Sparse" : "Dense", 95 (bp[25] & 0x80) ? " WC" : "", 96 (bp[25] & 0x40) ? "RP" : "SPT"); 97 return; 98 } 99 100 TCHECK2(bp[0], 4); 101 if (vflag > 1) 102 (void)printf("\n"); 103 (void)printf(" Upstream Nbr: %s", ipaddr_string(bp)); 104 TCHECK2(bp[6], 2); 105 if (vflag > 1) 106 (void)printf("\n"); 107 (void)printf(" Hold time: "); 108 relts_print(EXTRACT_16BITS(&bp[6])); 109 if (vflag < 2) 110 return; 111 bp += 8; 112 len -= 8; 113 114 TCHECK2(bp[0], 4); 115 maddrlen = bp[1]; 116 addrlen = bp[2]; 117 ngroups = bp[3]; 118 bp += 4; 119 len -= 4; 120 while (ngroups--) { 121 TCHECK2(bp[0], 4); 122 (void)printf("\n\tGroup: %s", ipaddr_string(bp)); 123 if (EXTRACT_32BITS(&bp[4]) != 0xffffffff) 124 (void)printf("/%s", ipaddr_string(&bp[4])); 125 TCHECK2(bp[8], 4); 126 njoin = EXTRACT_16BITS(&bp[8]); 127 nprune = EXTRACT_16BITS(&bp[10]); 128 (void)printf(" joined: %d pruned: %d", njoin, nprune); 129 bp += 12; 130 len -= 12; 131 for (njp = 0; njp < (njoin + nprune); njp++) { 132 char *type; 133 134 if (njp < njoin) 135 type = "Join "; 136 else 137 type = "Prune"; 138 TCHECK2(bp[0], 6); 139 (void)printf("\n\t%s %s%s%s%s/%d", type, 140 (bp[0] & 0x01) ? "Sparse " : "Dense ", 141 (bp[1] & 0x80) ? "WC " : "", 142 (bp[1] & 0x40) ? "RP " : "SPT ", 143 ipaddr_string(&bp[2]), bp[1] & 0x3f); 144 bp += 6; 145 len -= 6; 146 } 147 } 148 return; 149 trunc: 150 (void)printf("[|pim]"); 151 return; 152 } 153 154 void 155 pimv1_print(register const u_char *bp, register u_int len) 156 { 157 register const u_char *ep; 158 register u_char type; 159 160 ep = (const u_char *)snapend; 161 if (bp >= ep) 162 return; 163 164 type = bp[1]; 165 166 switch (type) { 167 case 0: 168 (void)printf(" Query"); 169 if (TTEST(bp[8])) { 170 switch (bp[8] >> 4) { 171 case 0: 172 (void)printf(" Dense-mode"); 173 break; 174 case 1: 175 (void)printf(" Sparse-mode"); 176 break; 177 case 2: 178 (void)printf(" Sparse-Dense-mode"); 179 break; 180 default: 181 (void)printf(" mode-%d", bp[8] >> 4); 182 break; 183 } 184 } 185 if (vflag) { 186 TCHECK2(bp[10],2); 187 (void)printf(" (Hold-time "); 188 relts_print(EXTRACT_16BITS(&bp[10])); 189 (void)printf(")"); 190 } 191 break; 192 193 case 1: 194 (void)printf(" Register"); 195 TCHECK2(bp[8], 20); /* ip header */ 196 (void)printf(" for %s > %s", ipaddr_string(&bp[20]), 197 ipaddr_string(&bp[24])); 198 break; 199 case 2: 200 (void)printf(" Register-Stop"); 201 TCHECK2(bp[12], 4); 202 (void)printf(" for %s > %s", ipaddr_string(&bp[8]), 203 ipaddr_string(&bp[12])); 204 break; 205 case 3: 206 (void)printf(" Join/Prune"); 207 if (vflag) 208 pimv1_join_prune_print(&bp[8], len - 8); 209 break; 210 case 4: 211 (void)printf(" RP-reachable"); 212 if (vflag) { 213 TCHECK2(bp[22], 2); 214 (void)printf(" group %s", 215 ipaddr_string(&bp[8])); 216 if (EXTRACT_32BITS(&bp[12]) != 0xffffffff) 217 (void)printf("/%s", ipaddr_string(&bp[12])); 218 (void)printf(" RP %s hold ", ipaddr_string(&bp[16])); 219 relts_print(EXTRACT_16BITS(&bp[22])); 220 } 221 break; 222 case 5: 223 (void)printf(" Assert"); 224 TCHECK2(bp[16], 4); 225 (void)printf(" for %s > %s", ipaddr_string(&bp[16]), 226 ipaddr_string(&bp[8])); 227 if (EXTRACT_32BITS(&bp[12]) != 0xffffffff) 228 (void)printf("/%s", ipaddr_string(&bp[12])); 229 TCHECK2(bp[24], 4); 230 (void)printf(" %s pref %d metric %d", 231 (bp[20] & 0x80) ? "RP-tree" : "SPT", 232 EXTRACT_32BITS(&bp[20]) & 0x7fffffff, 233 EXTRACT_32BITS(&bp[24])); 234 break; 235 case 6: 236 (void)printf(" Graft"); 237 if (vflag) 238 pimv1_join_prune_print(&bp[8], len - 8); 239 break; 240 case 7: 241 (void)printf(" Graft-ACK"); 242 if (vflag) 243 pimv1_join_prune_print(&bp[8], len - 8); 244 break; 245 case 8: 246 (void)printf(" Mode"); 247 break; 248 default: 249 (void)printf(" [type %d]", type); 250 break; 251 } 252 if ((bp[4] >> 4) != 1) 253 (void)printf(" [v%d]", bp[4] >> 4); 254 return; 255 256 trunc: 257 (void)printf("[|pim]"); 258 return; 259 } 260 261 /* 262 * auto-RP is a cisco protocol, documented at 263 * ftp://ftpeng.cisco.com/ipmulticast/specs/pim-autorp-spec01.txt 264 * 265 * This implements version 1+, dated Sept 9, 1998. 266 */ 267 void 268 cisco_autorp_print(register const u_char *bp, register u_int len) 269 { 270 int type; 271 int numrps; 272 int hold; 273 274 TCHECK(bp[0]); 275 (void)printf(" auto-rp "); 276 type = bp[0]; 277 switch (type) { 278 case 0x11: 279 (void)printf("candidate-advert"); 280 break; 281 case 0x12: 282 (void)printf("mapping"); 283 break; 284 default: 285 (void)printf("type-0x%02x", type); 286 break; 287 } 288 289 TCHECK(bp[1]); 290 numrps = bp[1]; 291 292 TCHECK2(bp[2], 2); 293 (void)printf(" Hold "); 294 hold = EXTRACT_16BITS(&bp[2]); 295 if (hold) 296 relts_print(EXTRACT_16BITS(&bp[2])); 297 else 298 printf("FOREVER"); 299 300 /* Next 4 bytes are reserved. */ 301 302 bp += 8; len -= 8; 303 304 /*XXX skip unless -v? */ 305 306 /* 307 * Rest of packet: 308 * numrps entries of the form: 309 * 32 bits: RP 310 * 6 bits: reserved 311 * 2 bits: PIM version supported, bit 0 is "supports v1", 1 is "v2". 312 * 8 bits: # of entries for this RP 313 * each entry: 7 bits: reserved, 1 bit: negative, 314 * 8 bits: mask 32 bits: source 315 * lather, rinse, repeat. 316 */ 317 while (numrps--) { 318 int nentries; 319 char s; 320 321 TCHECK2(bp[0], 4); 322 (void)printf(" RP %s", ipaddr_string(bp)); 323 TCHECK(bp[4]); 324 switch (bp[4] & 0x3) { 325 case 0: printf(" PIMv?"); 326 break; 327 case 1: printf(" PIMv1"); 328 break; 329 case 2: printf(" PIMv2"); 330 break; 331 case 3: printf(" PIMv1+2"); 332 break; 333 } 334 if (bp[4] & 0xfc) 335 (void)printf(" [rsvd=0x%02x]", bp[4] & 0xfc); 336 TCHECK(bp[5]); 337 nentries = bp[5]; 338 bp += 6; len -= 6; 339 s = ' '; 340 for (; nentries; nentries--) { 341 TCHECK2(bp[0], 6); 342 (void)printf("%c%s%s/%d", s, bp[0] & 1 ? "!" : "", 343 ipaddr_string(&bp[2]), bp[1]); 344 if (bp[0] & 0xfe) 345 (void)printf("[rsvd=0x%02x]", bp[0] & 0xfe); 346 s = ','; 347 bp += 6; len -= 6; 348 } 349 } 350 return; 351 352 trunc: 353 (void)printf("[|autorp]"); 354 return; 355 } 356 357 void 358 pim_print(register const u_char *bp, register u_int len) 359 { 360 register const u_char *ep; 361 register struct pim *pim = (struct pim *)bp; 362 363 ep = (const u_char *)snapend; 364 if (bp >= ep) 365 return; 366 #ifdef notyet /* currently we see only version and type */ 367 TCHECK(pim->pim_rsv); 368 #endif 369 370 switch (PIM_VER(pim->pim_typever)) { 371 case 2: /* avoid hardcoding? */ 372 (void)printf("pim v2"); 373 pimv2_print(bp, len); 374 break; 375 default: 376 (void)printf("pim v%d", PIM_VER(pim->pim_typever)); 377 break; 378 } 379 return; 380 } 381 382 /* 383 * PIMv2 uses encoded address representations. 384 * 385 * The last PIM-SM I-D before RFC2117 was published specified the 386 * following representation for unicast addresses. However, RFC2117 387 * specified no encoding for unicast addresses with the unicast 388 * address length specified in the header. Therefore, we have to 389 * guess which encoding is being used (Cisco's PIMv2 implementation 390 * uses the non-RFC encoding). RFC2117 turns a previously "Reserved" 391 * field into a 'unicast-address-length-in-bytes' field. We guess 392 * that it's the draft encoding if this reserved field is zero. 393 * 394 * RFC2362 goes back to the encoded format, and calls the addr length 395 * field "reserved" again. 396 * 397 * The first byte is the address family, from: 398 * 399 * 0 Reserved 400 * 1 IP (IP version 4) 401 * 2 IP6 (IP version 6) 402 * 3 NSAP 403 * 4 HDLC (8-bit multidrop) 404 * 5 BBN 1822 405 * 6 802 (includes all 802 media plus Ethernet "canonical format") 406 * 7 E.163 407 * 8 E.164 (SMDS, Frame Relay, ATM) 408 * 9 F.69 (Telex) 409 * 10 X.121 (X.25, Frame Relay) 410 * 11 IPX 411 * 12 Appletalk 412 * 13 Decnet IV 413 * 14 Banyan Vines 414 * 15 E.164 with NSAP format subaddress 415 * 416 * In addition, the second byte is an "Encoding". 0 is the default 417 * encoding for the address family, and no other encodings are currently 418 * specified. 419 * 420 */ 421 422 static int pimv2_addr_len; 423 424 enum pimv2_addrtype { 425 pimv2_unicast, pimv2_group, pimv2_source 426 }; 427 428 /* 0 1 2 3 429 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 430 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 431 * | Addr Family | Encoding Type | Unicast Address | 432 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+++++++ 433 * 0 1 2 3 434 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 435 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 436 * | Addr Family | Encoding Type | Reserved | Mask Len | 437 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 438 * | Group multicast Address | 439 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 440 * 0 1 2 3 441 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 442 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 443 * | Addr Family | Encoding Type | Rsrvd |S|W|R| Mask Len | 444 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 445 * | Source Address | 446 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 447 */ 448 static int 449 pimv2_addr_print(const u_char *bp, enum pimv2_addrtype at, int silent) 450 { 451 int af; 452 char *afstr; 453 int len, hdrlen; 454 455 TCHECK(bp[0]); 456 457 if (pimv2_addr_len == 0) { 458 TCHECK(bp[1]); 459 switch (bp[0]) { 460 case 1: 461 af = AF_INET; 462 afstr = "IPv4"; 463 len = 4; 464 break; 465 #ifdef INET6 466 case 2: 467 af = AF_INET6; 468 afstr = "IPv6"; 469 len = 16; 470 break; 471 #endif 472 default: 473 return -1; 474 } 475 if (bp[1] != 0) 476 return -1; 477 hdrlen = 2; 478 } else { 479 switch (pimv2_addr_len) { 480 case 4: 481 af = AF_INET; 482 afstr = "IPv4"; 483 break; 484 #ifdef INET6 485 case 16: 486 af = AF_INET6; 487 afstr = "IPv6"; 488 break; 489 #endif 490 default: 491 return -1; 492 break; 493 } 494 len = pimv2_addr_len; 495 hdrlen = 0; 496 } 497 498 bp += hdrlen; 499 switch (at) { 500 case pimv2_unicast: 501 TCHECK2(bp[0], len); 502 if (af == AF_INET) { 503 if (!silent) 504 (void)printf("%s", ipaddr_string(bp)); 505 } 506 #ifdef INET6 507 else if (af == AF_INET6) { 508 if (!silent) 509 (void)printf("%s", ip6addr_string(bp)); 510 } 511 #endif 512 return hdrlen + len; 513 case pimv2_group: 514 case pimv2_source: 515 TCHECK2(bp[0], len + 2); 516 if (af == AF_INET) { 517 if (!silent) { 518 (void)printf("%s", ipaddr_string(bp + 2)); 519 if (bp[1] != 32) 520 (void)printf("/%u", bp[1]); 521 } 522 } 523 #ifdef INET6 524 else if (af == AF_INET6) { 525 if (!silent) { 526 (void)printf("%s", ip6addr_string(bp + 2)); 527 if (bp[1] != 128) 528 (void)printf("/%u", bp[1]); 529 } 530 } 531 #endif 532 if (bp[0] && !silent) { 533 if (at == pimv2_group) { 534 (void)printf("(0x%02x)", bp[0]); 535 } else { 536 (void)printf("(%s%s%s", 537 bp[0] & 0x04 ? "S" : "", 538 bp[0] & 0x02 ? "W" : "", 539 bp[0] & 0x01 ? "R" : ""); 540 if (bp[0] & 0xf8) { 541 (void) printf("+0x%02x", bp[0] & 0xf8); 542 } 543 (void)printf(")"); 544 } 545 } 546 return hdrlen + 2 + len; 547 default: 548 return -1; 549 } 550 trunc: 551 return -1; 552 } 553 554 static void 555 pimv2_print(register const u_char *bp, register u_int len) 556 { 557 register const u_char *ep; 558 register struct pim *pim = (struct pim *)bp; 559 int advance; 560 561 ep = (const u_char *)snapend; 562 if (bp >= ep) 563 return; 564 if (ep > bp + len) 565 ep = bp + len; 566 TCHECK(pim->pim_rsv); 567 pimv2_addr_len = pim->pim_rsv; 568 if (pimv2_addr_len != 0) 569 (void)printf("[RFC2117-encoding] "); 570 571 switch (PIM_TYPE(pim->pim_typever)) { 572 case 0: 573 { 574 u_int16_t otype, olen; 575 (void)printf(" Hello"); 576 bp += 4; 577 while (bp < ep) { 578 TCHECK2(bp[0], 4); 579 otype = EXTRACT_16BITS(&bp[0]); 580 olen = EXTRACT_16BITS(&bp[2]); 581 TCHECK2(bp[0], 4 + olen); 582 switch (otype) { 583 case 1: /* Hold time */ 584 (void)printf(" (Hold-time "); 585 relts_print(EXTRACT_16BITS(&bp[4])); 586 (void)printf(")"); 587 break; 588 589 case 19: /* DR-Priority */ 590 (void)printf(" (DR-Priority: "); 591 if (olen != 4) { 592 (void)printf("!olen=%d!)", olen); 593 } else { 594 (void)printf("%d)", EXTRACT_32BITS(&bp[4])); 595 } 596 break; 597 598 case 20: 599 (void)printf(" (Genid: 0x%08x)", EXTRACT_32BITS(&bp[4])); 600 break; 601 602 case 21: 603 (void)printf(" (State Refresh Capable; v%d", bp[4]); 604 if (bp[5] != 0) { 605 (void)printf(" interval "); 606 relts_print(bp[5]); 607 } 608 if (EXTRACT_16BITS(&bp[6]) != 0) { 609 (void)printf(" ?0x%04x?", EXTRACT_16BITS(&bp[6])); 610 } 611 (void)printf(")"); 612 break; 613 614 case 22: /* Bidir-Capable */ 615 (void)printf(" (bidir-capable)"); 616 break; 617 618 default: 619 if (vflag) 620 (void)printf(" [Hello option %d]", otype); 621 } 622 bp += 4 + olen; 623 } 624 break; 625 } 626 627 case 1: 628 { 629 struct ip *ip; 630 631 (void)printf(" Register"); 632 if (vflag && bp + 8 <= ep) { 633 (void)printf(" %s%s", bp[4] & 0x80 ? "B" : "", 634 bp[4] & 0x40 ? "N" : ""); 635 } 636 bp += 8; len -= 8; 637 638 /* encapsulated multicast packet */ 639 if (bp >= ep) 640 break; 641 ip = (struct ip *)bp; 642 switch (IP_V(ip)) { 643 case 4: /* IPv4 */ 644 printf(" "); 645 ip_print(bp, len); 646 break; 647 #ifdef INET6 648 case 6: /* IPv6 */ 649 printf(" "); 650 ip6_print(bp, len); 651 break; 652 #endif 653 default: 654 (void)printf(" IP ver %d", IP_V(ip)); 655 break; 656 } 657 break; 658 } 659 660 case 2: 661 (void)printf(" Register-Stop"); 662 bp += 4; len -= 4; 663 if (bp >= ep) 664 break; 665 (void)printf(" group="); 666 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 667 (void)printf("..."); 668 break; 669 } 670 bp += advance; len -= advance; 671 if (bp >= ep) 672 break; 673 (void)printf(" source="); 674 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 675 (void)printf("..."); 676 break; 677 } 678 bp += advance; len -= advance; 679 break; 680 681 case 3: 682 case 6: 683 case 7: 684 { 685 u_int8_t ngroup; 686 u_int16_t holdtime; 687 u_int16_t njoin; 688 u_int16_t nprune; 689 int i, j; 690 691 switch (PIM_TYPE(pim->pim_typever)) { 692 case 3: 693 (void)printf(" Join/Prune"); 694 break; 695 case 6: 696 (void)printf(" Graft"); 697 break; 698 case 7: 699 (void)printf(" Graft-ACK"); 700 break; 701 } 702 bp += 4; len -= 4; 703 if (PIM_TYPE(pim->pim_typever) != 7) { /*not for Graft-ACK*/ 704 if (bp >= ep) 705 break; 706 (void)printf(" upstream-neighbor="); 707 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 708 (void)printf("..."); 709 break; 710 } 711 bp += advance; len -= advance; 712 } 713 if (bp + 4 > ep) 714 break; 715 ngroup = bp[1]; 716 holdtime = EXTRACT_16BITS(&bp[2]); 717 (void)printf(" groups=%u", ngroup); 718 if (PIM_TYPE(pim->pim_typever) != 7) { /*not for Graft-ACK*/ 719 (void)printf(" holdtime="); 720 if (holdtime == 0xffff) 721 (void)printf("infty"); 722 else 723 relts_print(holdtime); 724 } 725 bp += 4; len -= 4; 726 for (i = 0; i < ngroup; i++) { 727 if (bp >= ep) 728 goto jp_done; 729 (void)printf(" (group%d: ", i); 730 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 731 (void)printf("...)"); 732 goto jp_done; 733 } 734 bp += advance; len -= advance; 735 if (bp + 4 > ep) { 736 (void)printf("...)"); 737 goto jp_done; 738 } 739 njoin = EXTRACT_16BITS(&bp[0]); 740 nprune = EXTRACT_16BITS(&bp[2]); 741 (void)printf(" join=%u", njoin); 742 bp += 4; len -= 4; 743 for (j = 0; j < njoin; j++) { 744 (void)printf(" "); 745 if ((advance = pimv2_addr_print(bp, pimv2_source, 0)) < 0) { 746 (void)printf("...)"); 747 goto jp_done; 748 } 749 bp += advance; len -= advance; 750 } 751 (void)printf(" prune=%u", nprune); 752 for (j = 0; j < nprune; j++) { 753 (void)printf(" "); 754 if ((advance = pimv2_addr_print(bp, pimv2_source, 0)) < 0) { 755 (void)printf("...)"); 756 goto jp_done; 757 } 758 bp += advance; len -= advance; 759 } 760 (void)printf(")"); 761 } 762 jp_done: 763 break; 764 } 765 766 case 4: 767 { 768 int i, j, frpcnt; 769 770 (void)printf(" Bootstrap"); 771 bp += 4; 772 773 /* Fragment Tag, Hash Mask len, and BSR-priority */ 774 if (bp + sizeof(u_int16_t) >= ep) break; 775 (void)printf(" tag=%x", EXTRACT_16BITS(bp)); 776 bp += sizeof(u_int16_t); 777 if (bp >= ep) break; 778 (void)printf(" hashmlen=%d", bp[0]); 779 if (bp + 1 >= ep) break; 780 (void)printf(" BSRprio=%d", bp[1]); 781 bp += 2; 782 783 /* Encoded-Unicast-BSR-Address */ 784 if (bp >= ep) break; 785 (void)printf(" BSR="); 786 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 787 (void)printf("..."); 788 break; 789 } 790 bp += advance; 791 792 for (i = 0; bp < ep; i++) { 793 /* Encoded-Group Address */ 794 (void)printf(" (group%d: ", i); 795 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) 796 < 0) { 797 (void)printf("...)"); 798 goto bs_done; 799 } 800 bp += advance; 801 802 /* RP-Count, Frag RP-Cnt, and rsvd */ 803 if (bp >= ep) { 804 (void)printf("...)"); 805 goto bs_done; 806 } 807 (void)printf(" RPcnt=%d", bp[0]); 808 if (bp + 1 >= ep) { 809 (void)printf("...)"); 810 goto bs_done; 811 } 812 (void)printf(" FRPcnt=%d", frpcnt = bp[1]); 813 bp += 4; 814 815 for (j = 0; j < frpcnt && bp < ep; j++) { 816 /* each RP info */ 817 (void)printf(" RP%d=", j); 818 if ((advance = pimv2_addr_print(bp, 819 pimv2_unicast, 820 0)) < 0) { 821 (void)printf("...)"); 822 goto bs_done; 823 } 824 bp += advance; 825 826 if (bp + 1 >= ep) { 827 (void)printf("...)"); 828 goto bs_done; 829 } 830 (void)printf(",holdtime="); 831 relts_print(EXTRACT_16BITS(bp)); 832 if (bp + 2 >= ep) { 833 (void)printf("...)"); 834 goto bs_done; 835 } 836 (void)printf(",prio=%d", bp[2]); 837 bp += 4; 838 } 839 (void)printf(")"); 840 } 841 bs_done: 842 break; 843 } 844 case 5: 845 (void)printf(" Assert"); 846 bp += 4; len -= 4; 847 if (bp >= ep) 848 break; 849 (void)printf(" group="); 850 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 851 (void)printf("..."); 852 break; 853 } 854 bp += advance; len -= advance; 855 if (bp >= ep) 856 break; 857 (void)printf(" src="); 858 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 859 (void)printf("..."); 860 break; 861 } 862 bp += advance; len -= advance; 863 if (bp + 8 > ep) 864 break; 865 if (bp[0] & 0x80) 866 (void)printf(" RPT"); 867 (void)printf(" pref=%u", EXTRACT_32BITS(&bp[0]) & 0x7fffffff); 868 (void)printf(" metric=%u", EXTRACT_32BITS(&bp[4])); 869 break; 870 871 case 8: 872 { 873 int i, pfxcnt; 874 875 (void)printf(" Candidate-RP-Advertisement"); 876 bp += 4; 877 878 /* Prefix-Cnt, Priority, and Holdtime */ 879 if (bp >= ep) break; 880 (void)printf(" prefix-cnt=%d", bp[0]); 881 pfxcnt = bp[0]; 882 if (bp + 1 >= ep) break; 883 (void)printf(" prio=%d", bp[1]); 884 if (bp + 3 >= ep) break; 885 (void)printf(" holdtime="); 886 relts_print(EXTRACT_16BITS(&bp[2])); 887 bp += 4; 888 889 /* Encoded-Unicast-RP-Address */ 890 if (bp >= ep) break; 891 (void)printf(" RP="); 892 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 893 (void)printf("..."); 894 break; 895 } 896 bp += advance; 897 898 /* Encoded-Group Addresses */ 899 for (i = 0; i < pfxcnt && bp < ep; i++) { 900 (void)printf(" Group%d=", i); 901 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) 902 < 0) { 903 (void)printf("..."); 904 break; 905 } 906 bp += advance; 907 } 908 break; 909 } 910 911 case 9: 912 (void)printf(" Prune-Refresh"); 913 (void)printf(" src="); 914 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 915 (void)printf("..."); 916 break; 917 } 918 bp += advance; 919 (void)printf(" grp="); 920 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 921 (void)printf("..."); 922 break; 923 } 924 bp += advance; 925 (void)printf(" forwarder="); 926 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 927 (void)printf("..."); 928 break; 929 } 930 bp += advance; 931 TCHECK2(bp[0], 2); 932 (void)printf(" TUNR "); 933 relts_print(EXTRACT_16BITS(bp)); 934 break; 935 936 937 default: 938 (void)printf(" [type %d]", PIM_TYPE(pim->pim_typever)); 939 break; 940 } 941 942 return; 943 944 trunc: 945 (void)printf("[|pim]"); 946 } 947