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.4.1 2002/05/07 18:30:19 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 18: /* Old DR-Priority */ 590 if (olen == 4) 591 (void)printf(" (OLD-DR-Priority: %d)", 592 EXTRACT_32BITS(&bp[4])); 593 else 594 goto unknown; 595 break; 596 597 598 case 19: /* DR-Priority */ 599 if (olen == 0) { 600 (void)printf(" (OLD-bidir-capable)"); 601 break; 602 } 603 (void)printf(" (DR-Priority: "); 604 if (olen != 4) { 605 (void)printf("!olen=%d!)", olen); 606 } else { 607 (void)printf("%d)", EXTRACT_32BITS(&bp[4])); 608 } 609 break; 610 611 case 20: 612 (void)printf(" (Genid: 0x%08x)", EXTRACT_32BITS(&bp[4])); 613 break; 614 615 case 21: 616 (void)printf(" (State Refresh Capable; v%d", bp[4]); 617 if (bp[5] != 0) { 618 (void)printf(" interval "); 619 relts_print(bp[5]); 620 } 621 if (EXTRACT_16BITS(&bp[6]) != 0) { 622 (void)printf(" ?0x%04x?", EXTRACT_16BITS(&bp[6])); 623 } 624 (void)printf(")"); 625 break; 626 627 case 22: /* Bidir-Capable */ 628 (void)printf(" (bidir-capable)"); 629 break; 630 631 default: 632 unknown: 633 if (vflag) 634 (void)printf(" [Hello option %d]", otype); 635 } 636 bp += 4 + olen; 637 } 638 break; 639 } 640 641 case 1: 642 { 643 struct ip *ip; 644 645 (void)printf(" Register"); 646 if (vflag && bp + 8 <= ep) { 647 (void)printf(" %s%s", bp[4] & 0x80 ? "B" : "", 648 bp[4] & 0x40 ? "N" : ""); 649 } 650 bp += 8; len -= 8; 651 652 /* encapsulated multicast packet */ 653 if (bp >= ep) 654 break; 655 ip = (struct ip *)bp; 656 switch (IP_V(ip)) { 657 case 4: /* IPv4 */ 658 printf(" "); 659 ip_print(bp, len); 660 break; 661 #ifdef INET6 662 case 6: /* IPv6 */ 663 printf(" "); 664 ip6_print(bp, len); 665 break; 666 #endif 667 default: 668 (void)printf(" IP ver %d", IP_V(ip)); 669 break; 670 } 671 break; 672 } 673 674 case 2: 675 (void)printf(" Register-Stop"); 676 bp += 4; len -= 4; 677 if (bp >= ep) 678 break; 679 (void)printf(" group="); 680 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 681 (void)printf("..."); 682 break; 683 } 684 bp += advance; len -= advance; 685 if (bp >= ep) 686 break; 687 (void)printf(" source="); 688 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 689 (void)printf("..."); 690 break; 691 } 692 bp += advance; len -= advance; 693 break; 694 695 case 3: 696 case 6: 697 case 7: 698 { 699 u_int8_t ngroup; 700 u_int16_t holdtime; 701 u_int16_t njoin; 702 u_int16_t nprune; 703 int i, j; 704 705 switch (PIM_TYPE(pim->pim_typever)) { 706 case 3: 707 (void)printf(" Join/Prune"); 708 break; 709 case 6: 710 (void)printf(" Graft"); 711 break; 712 case 7: 713 (void)printf(" Graft-ACK"); 714 break; 715 } 716 bp += 4; len -= 4; 717 if (PIM_TYPE(pim->pim_typever) != 7) { /*not for Graft-ACK*/ 718 if (bp >= ep) 719 break; 720 (void)printf(" upstream-neighbor="); 721 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 722 (void)printf("..."); 723 break; 724 } 725 bp += advance; len -= advance; 726 } 727 if (bp + 4 > ep) 728 break; 729 ngroup = bp[1]; 730 holdtime = EXTRACT_16BITS(&bp[2]); 731 (void)printf(" groups=%u", ngroup); 732 if (PIM_TYPE(pim->pim_typever) != 7) { /*not for Graft-ACK*/ 733 (void)printf(" holdtime="); 734 if (holdtime == 0xffff) 735 (void)printf("infty"); 736 else 737 relts_print(holdtime); 738 } 739 bp += 4; len -= 4; 740 for (i = 0; i < ngroup; i++) { 741 if (bp >= ep) 742 goto jp_done; 743 (void)printf(" (group%d: ", i); 744 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 745 (void)printf("...)"); 746 goto jp_done; 747 } 748 bp += advance; len -= advance; 749 if (bp + 4 > ep) { 750 (void)printf("...)"); 751 goto jp_done; 752 } 753 njoin = EXTRACT_16BITS(&bp[0]); 754 nprune = EXTRACT_16BITS(&bp[2]); 755 (void)printf(" join=%u", njoin); 756 bp += 4; len -= 4; 757 for (j = 0; j < njoin; j++) { 758 (void)printf(" "); 759 if ((advance = pimv2_addr_print(bp, pimv2_source, 0)) < 0) { 760 (void)printf("...)"); 761 goto jp_done; 762 } 763 bp += advance; len -= advance; 764 } 765 (void)printf(" prune=%u", nprune); 766 for (j = 0; j < nprune; j++) { 767 (void)printf(" "); 768 if ((advance = pimv2_addr_print(bp, pimv2_source, 0)) < 0) { 769 (void)printf("...)"); 770 goto jp_done; 771 } 772 bp += advance; len -= advance; 773 } 774 (void)printf(")"); 775 } 776 jp_done: 777 break; 778 } 779 780 case 4: 781 { 782 int i, j, frpcnt; 783 784 (void)printf(" Bootstrap"); 785 bp += 4; 786 787 /* Fragment Tag, Hash Mask len, and BSR-priority */ 788 if (bp + sizeof(u_int16_t) >= ep) break; 789 (void)printf(" tag=%x", EXTRACT_16BITS(bp)); 790 bp += sizeof(u_int16_t); 791 if (bp >= ep) break; 792 (void)printf(" hashmlen=%d", bp[0]); 793 if (bp + 1 >= ep) break; 794 (void)printf(" BSRprio=%d", bp[1]); 795 bp += 2; 796 797 /* Encoded-Unicast-BSR-Address */ 798 if (bp >= ep) break; 799 (void)printf(" BSR="); 800 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 801 (void)printf("..."); 802 break; 803 } 804 bp += advance; 805 806 for (i = 0; bp < ep; i++) { 807 /* Encoded-Group Address */ 808 (void)printf(" (group%d: ", i); 809 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) 810 < 0) { 811 (void)printf("...)"); 812 goto bs_done; 813 } 814 bp += advance; 815 816 /* RP-Count, Frag RP-Cnt, and rsvd */ 817 if (bp >= ep) { 818 (void)printf("...)"); 819 goto bs_done; 820 } 821 (void)printf(" RPcnt=%d", bp[0]); 822 if (bp + 1 >= ep) { 823 (void)printf("...)"); 824 goto bs_done; 825 } 826 (void)printf(" FRPcnt=%d", frpcnt = bp[1]); 827 bp += 4; 828 829 for (j = 0; j < frpcnt && bp < ep; j++) { 830 /* each RP info */ 831 (void)printf(" RP%d=", j); 832 if ((advance = pimv2_addr_print(bp, 833 pimv2_unicast, 834 0)) < 0) { 835 (void)printf("...)"); 836 goto bs_done; 837 } 838 bp += advance; 839 840 if (bp + 1 >= ep) { 841 (void)printf("...)"); 842 goto bs_done; 843 } 844 (void)printf(",holdtime="); 845 relts_print(EXTRACT_16BITS(bp)); 846 if (bp + 2 >= ep) { 847 (void)printf("...)"); 848 goto bs_done; 849 } 850 (void)printf(",prio=%d", bp[2]); 851 bp += 4; 852 } 853 (void)printf(")"); 854 } 855 bs_done: 856 break; 857 } 858 case 5: 859 (void)printf(" Assert"); 860 bp += 4; len -= 4; 861 if (bp >= ep) 862 break; 863 (void)printf(" group="); 864 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 865 (void)printf("..."); 866 break; 867 } 868 bp += advance; len -= advance; 869 if (bp >= ep) 870 break; 871 (void)printf(" src="); 872 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 873 (void)printf("..."); 874 break; 875 } 876 bp += advance; len -= advance; 877 if (bp + 8 > ep) 878 break; 879 if (bp[0] & 0x80) 880 (void)printf(" RPT"); 881 (void)printf(" pref=%u", EXTRACT_32BITS(&bp[0]) & 0x7fffffff); 882 (void)printf(" metric=%u", EXTRACT_32BITS(&bp[4])); 883 break; 884 885 case 8: 886 { 887 int i, pfxcnt; 888 889 (void)printf(" Candidate-RP-Advertisement"); 890 bp += 4; 891 892 /* Prefix-Cnt, Priority, and Holdtime */ 893 if (bp >= ep) break; 894 (void)printf(" prefix-cnt=%d", bp[0]); 895 pfxcnt = bp[0]; 896 if (bp + 1 >= ep) break; 897 (void)printf(" prio=%d", bp[1]); 898 if (bp + 3 >= ep) break; 899 (void)printf(" holdtime="); 900 relts_print(EXTRACT_16BITS(&bp[2])); 901 bp += 4; 902 903 /* Encoded-Unicast-RP-Address */ 904 if (bp >= ep) break; 905 (void)printf(" RP="); 906 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 907 (void)printf("..."); 908 break; 909 } 910 bp += advance; 911 912 /* Encoded-Group Addresses */ 913 for (i = 0; i < pfxcnt && bp < ep; i++) { 914 (void)printf(" Group%d=", i); 915 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) 916 < 0) { 917 (void)printf("..."); 918 break; 919 } 920 bp += advance; 921 } 922 break; 923 } 924 925 case 9: 926 (void)printf(" Prune-Refresh"); 927 (void)printf(" src="); 928 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 929 (void)printf("..."); 930 break; 931 } 932 bp += advance; 933 (void)printf(" grp="); 934 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 935 (void)printf("..."); 936 break; 937 } 938 bp += advance; 939 (void)printf(" forwarder="); 940 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 941 (void)printf("..."); 942 break; 943 } 944 bp += advance; 945 TCHECK2(bp[0], 2); 946 (void)printf(" TUNR "); 947 relts_print(EXTRACT_16BITS(bp)); 948 break; 949 950 951 default: 952 (void)printf(" [type %d]", PIM_TYPE(pim->pim_typever)); 953 break; 954 } 955 956 return; 957 958 trunc: 959 (void)printf("[|pim]"); 960 } 961