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