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