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