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