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