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.45.2.4 2006/02/13 01:32:34 hannes Exp $ (LBL)"; 25 #endif 26 27 #ifdef HAVE_CONFIG_H 28 #include "config.h" 29 #endif 30 31 #include <tcpdump-stdinc.h> 32 #include "interface.h" 33 34 #define PIMV2_TYPE_HELLO 0 35 #define PIMV2_TYPE_REGISTER 1 36 #define PIMV2_TYPE_REGISTER_STOP 2 37 #define PIMV2_TYPE_JOIN_PRUNE 3 38 #define PIMV2_TYPE_BOOTSTRAP 4 39 #define PIMV2_TYPE_ASSERT 5 40 #define PIMV2_TYPE_GRAFT 6 41 #define PIMV2_TYPE_GRAFT_ACK 7 42 #define PIMV2_TYPE_CANDIDATE_RP 8 43 #define PIMV2_TYPE_PRUNE_REFRESH 9 44 45 static struct tok pimv2_type_values[] = { 46 { PIMV2_TYPE_HELLO, "Hello" }, 47 { PIMV2_TYPE_REGISTER, "Register" }, 48 { PIMV2_TYPE_REGISTER_STOP, "Register Stop" }, 49 { PIMV2_TYPE_JOIN_PRUNE, "Join / Prune" }, 50 { PIMV2_TYPE_BOOTSTRAP, "Bootstrap" }, 51 { PIMV2_TYPE_ASSERT, "Assert" }, 52 { PIMV2_TYPE_GRAFT, "Graft" }, 53 { PIMV2_TYPE_GRAFT_ACK, "Graft Acknowledgement" }, 54 { PIMV2_TYPE_CANDIDATE_RP, "Candidate RP Advertisement" }, 55 { PIMV2_TYPE_PRUNE_REFRESH, "Prune Refresh" }, 56 { 0, NULL} 57 }; 58 59 #define PIMV2_HELLO_OPTION_HOLDTIME 1 60 #define PIMV2_HELLO_OPTION_LANPRUNEDELAY 2 61 #define PIMV2_HELLO_OPTION_DR_PRIORITY_OLD 18 62 #define PIMV2_HELLO_OPTION_DR_PRIORITY 19 63 #define PIMV2_HELLO_OPTION_GENID 20 64 #define PIMV2_HELLO_OPTION_REFRESH_CAP 21 65 #define PIMV2_HELLO_OPTION_BIDIR_CAP 22 66 #define PIMV2_HELLO_OPTION_ADDRESS_LIST 24 67 #define PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD 65001 68 69 static struct tok pimv2_hello_option_values[] = { 70 { PIMV2_HELLO_OPTION_HOLDTIME, "Hold Time" }, 71 { PIMV2_HELLO_OPTION_LANPRUNEDELAY, "LAN Prune Delay" }, 72 { PIMV2_HELLO_OPTION_DR_PRIORITY_OLD, "DR Priority (Old)" }, 73 { PIMV2_HELLO_OPTION_DR_PRIORITY, "DR Priority" }, 74 { PIMV2_HELLO_OPTION_GENID, "Generation ID" }, 75 { PIMV2_HELLO_OPTION_REFRESH_CAP, "State Refresh Capability" }, 76 { PIMV2_HELLO_OPTION_BIDIR_CAP, "Bi-Directional Capability" }, 77 { PIMV2_HELLO_OPTION_ADDRESS_LIST, "Address List" }, 78 { PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD, "Address List (Old)" }, 79 { 0, NULL} 80 }; 81 82 #define PIMV2_REGISTER_FLAG_LEN 4 83 #define PIMV2_REGISTER_FLAG_BORDER 0x80000000 84 #define PIMV2_REGISTER_FLAG_NULL 0x40000000 85 86 static struct tok pimv2_register_flag_values[] = { 87 { PIMV2_REGISTER_FLAG_BORDER, "Border" }, 88 { PIMV2_REGISTER_FLAG_NULL, "Null" }, 89 { 0, NULL} 90 }; 91 92 /* 93 * XXX: We consider a case where IPv6 is not ready yet for portability, 94 * but PIM dependent defintions should be independent of IPv6... 95 */ 96 97 struct pim { 98 u_int8_t pim_typever; 99 /* upper 4bit: PIM version number; 2 for PIMv2 */ 100 /* lower 4bit: the PIM message type, currently they are: 101 * Hello, Register, Register-Stop, Join/Prune, 102 * Bootstrap, Assert, Graft (PIM-DM only), 103 * Graft-Ack (PIM-DM only), C-RP-Adv 104 */ 105 #define PIM_VER(x) (((x) & 0xf0) >> 4) 106 #define PIM_TYPE(x) ((x) & 0x0f) 107 u_char pim_rsv; /* Reserved */ 108 u_short pim_cksum; /* IP style check sum */ 109 }; 110 111 112 #include <stdio.h> 113 #include <stdlib.h> 114 115 #include "interface.h" 116 #include "addrtoname.h" 117 #include "extract.h" 118 119 #include "ip.h" 120 121 static void pimv2_print(register const u_char *bp, register u_int len); 122 123 static void 124 pimv1_join_prune_print(register const u_char *bp, register u_int len) 125 { 126 int maddrlen, addrlen, ngroups, njoin, nprune; 127 int njp; 128 129 /* If it's a single group and a single source, use 1-line output. */ 130 if (TTEST2(bp[0], 30) && bp[11] == 1 && 131 ((njoin = EXTRACT_16BITS(&bp[20])) + EXTRACT_16BITS(&bp[22])) == 1) { 132 int hold; 133 134 (void)printf(" RPF %s ", ipaddr_string(bp)); 135 hold = EXTRACT_16BITS(&bp[6]); 136 if (hold != 180) { 137 (void)printf("Hold "); 138 relts_print(hold); 139 } 140 (void)printf("%s (%s/%d, %s", njoin ? "Join" : "Prune", 141 ipaddr_string(&bp[26]), bp[25] & 0x3f, 142 ipaddr_string(&bp[12])); 143 if (EXTRACT_32BITS(&bp[16]) != 0xffffffff) 144 (void)printf("/%s", ipaddr_string(&bp[16])); 145 (void)printf(") %s%s %s", 146 (bp[24] & 0x01) ? "Sparse" : "Dense", 147 (bp[25] & 0x80) ? " WC" : "", 148 (bp[25] & 0x40) ? "RP" : "SPT"); 149 return; 150 } 151 152 TCHECK2(bp[0], sizeof(struct in_addr)); 153 if (vflag > 1) 154 (void)printf("\n"); 155 (void)printf(" Upstream Nbr: %s", ipaddr_string(bp)); 156 TCHECK2(bp[6], 2); 157 if (vflag > 1) 158 (void)printf("\n"); 159 (void)printf(" Hold time: "); 160 relts_print(EXTRACT_16BITS(&bp[6])); 161 if (vflag < 2) 162 return; 163 bp += 8; 164 len -= 8; 165 166 TCHECK2(bp[0], 4); 167 maddrlen = bp[1]; 168 addrlen = bp[2]; 169 ngroups = bp[3]; 170 bp += 4; 171 len -= 4; 172 while (ngroups--) { 173 /* 174 * XXX - does the address have length "addrlen" and the 175 * mask length "maddrlen"? 176 */ 177 TCHECK2(bp[0], sizeof(struct in_addr)); 178 (void)printf("\n\tGroup: %s", ipaddr_string(bp)); 179 TCHECK2(bp[4], sizeof(struct in_addr)); 180 if (EXTRACT_32BITS(&bp[4]) != 0xffffffff) 181 (void)printf("/%s", ipaddr_string(&bp[4])); 182 TCHECK2(bp[8], 4); 183 njoin = EXTRACT_16BITS(&bp[8]); 184 nprune = EXTRACT_16BITS(&bp[10]); 185 (void)printf(" joined: %d pruned: %d", njoin, nprune); 186 bp += 12; 187 len -= 12; 188 for (njp = 0; njp < (njoin + nprune); njp++) { 189 const char *type; 190 191 if (njp < njoin) 192 type = "Join "; 193 else 194 type = "Prune"; 195 TCHECK2(bp[0], 6); 196 (void)printf("\n\t%s %s%s%s%s/%d", type, 197 (bp[0] & 0x01) ? "Sparse " : "Dense ", 198 (bp[1] & 0x80) ? "WC " : "", 199 (bp[1] & 0x40) ? "RP " : "SPT ", 200 ipaddr_string(&bp[2]), bp[1] & 0x3f); 201 bp += 6; 202 len -= 6; 203 } 204 } 205 return; 206 trunc: 207 (void)printf("[|pim]"); 208 return; 209 } 210 211 void 212 pimv1_print(register const u_char *bp, register u_int len) 213 { 214 register const u_char *ep; 215 register u_char type; 216 217 ep = (const u_char *)snapend; 218 if (bp >= ep) 219 return; 220 221 TCHECK(bp[1]); 222 type = bp[1]; 223 224 switch (type) { 225 case 0: 226 (void)printf(" Query"); 227 if (TTEST(bp[8])) { 228 switch (bp[8] >> 4) { 229 case 0: 230 (void)printf(" Dense-mode"); 231 break; 232 case 1: 233 (void)printf(" Sparse-mode"); 234 break; 235 case 2: 236 (void)printf(" Sparse-Dense-mode"); 237 break; 238 default: 239 (void)printf(" mode-%d", bp[8] >> 4); 240 break; 241 } 242 } 243 if (vflag) { 244 TCHECK2(bp[10],2); 245 (void)printf(" (Hold-time "); 246 relts_print(EXTRACT_16BITS(&bp[10])); 247 (void)printf(")"); 248 } 249 break; 250 251 case 1: 252 (void)printf(" Register"); 253 TCHECK2(bp[8], 20); /* ip header */ 254 (void)printf(" for %s > %s", ipaddr_string(&bp[20]), 255 ipaddr_string(&bp[24])); 256 break; 257 case 2: 258 (void)printf(" Register-Stop"); 259 TCHECK2(bp[12], sizeof(struct in_addr)); 260 (void)printf(" for %s > %s", ipaddr_string(&bp[8]), 261 ipaddr_string(&bp[12])); 262 break; 263 case 3: 264 (void)printf(" Join/Prune"); 265 if (vflag) 266 pimv1_join_prune_print(&bp[8], len - 8); 267 break; 268 case 4: 269 (void)printf(" RP-reachable"); 270 if (vflag) { 271 TCHECK2(bp[22], 2); 272 (void)printf(" group %s", 273 ipaddr_string(&bp[8])); 274 if (EXTRACT_32BITS(&bp[12]) != 0xffffffff) 275 (void)printf("/%s", ipaddr_string(&bp[12])); 276 (void)printf(" RP %s hold ", ipaddr_string(&bp[16])); 277 relts_print(EXTRACT_16BITS(&bp[22])); 278 } 279 break; 280 case 5: 281 (void)printf(" Assert"); 282 TCHECK2(bp[16], sizeof(struct in_addr)); 283 (void)printf(" for %s > %s", ipaddr_string(&bp[16]), 284 ipaddr_string(&bp[8])); 285 if (EXTRACT_32BITS(&bp[12]) != 0xffffffff) 286 (void)printf("/%s", ipaddr_string(&bp[12])); 287 TCHECK2(bp[24], 4); 288 (void)printf(" %s pref %d metric %d", 289 (bp[20] & 0x80) ? "RP-tree" : "SPT", 290 EXTRACT_32BITS(&bp[20]) & 0x7fffffff, 291 EXTRACT_32BITS(&bp[24])); 292 break; 293 case 6: 294 (void)printf(" Graft"); 295 if (vflag) 296 pimv1_join_prune_print(&bp[8], len - 8); 297 break; 298 case 7: 299 (void)printf(" Graft-ACK"); 300 if (vflag) 301 pimv1_join_prune_print(&bp[8], len - 8); 302 break; 303 case 8: 304 (void)printf(" Mode"); 305 break; 306 default: 307 (void)printf(" [type %d]", type); 308 break; 309 } 310 if ((bp[4] >> 4) != 1) 311 (void)printf(" [v%d]", bp[4] >> 4); 312 return; 313 314 trunc: 315 (void)printf("[|pim]"); 316 return; 317 } 318 319 /* 320 * auto-RP is a cisco protocol, documented at 321 * ftp://ftpeng.cisco.com/ipmulticast/specs/pim-autorp-spec01.txt 322 * 323 * This implements version 1+, dated Sept 9, 1998. 324 */ 325 void 326 cisco_autorp_print(register const u_char *bp, register u_int len) 327 { 328 int type; 329 int numrps; 330 int hold; 331 332 TCHECK(bp[0]); 333 (void)printf(" auto-rp "); 334 type = bp[0]; 335 switch (type) { 336 case 0x11: 337 (void)printf("candidate-advert"); 338 break; 339 case 0x12: 340 (void)printf("mapping"); 341 break; 342 default: 343 (void)printf("type-0x%02x", type); 344 break; 345 } 346 347 TCHECK(bp[1]); 348 numrps = bp[1]; 349 350 TCHECK2(bp[2], 2); 351 (void)printf(" Hold "); 352 hold = EXTRACT_16BITS(&bp[2]); 353 if (hold) 354 relts_print(EXTRACT_16BITS(&bp[2])); 355 else 356 printf("FOREVER"); 357 358 /* Next 4 bytes are reserved. */ 359 360 bp += 8; len -= 8; 361 362 /*XXX skip unless -v? */ 363 364 /* 365 * Rest of packet: 366 * numrps entries of the form: 367 * 32 bits: RP 368 * 6 bits: reserved 369 * 2 bits: PIM version supported, bit 0 is "supports v1", 1 is "v2". 370 * 8 bits: # of entries for this RP 371 * each entry: 7 bits: reserved, 1 bit: negative, 372 * 8 bits: mask 32 bits: source 373 * lather, rinse, repeat. 374 */ 375 while (numrps--) { 376 int nentries; 377 char s; 378 379 TCHECK2(bp[0], 4); 380 (void)printf(" RP %s", ipaddr_string(bp)); 381 TCHECK(bp[4]); 382 switch (bp[4] & 0x3) { 383 case 0: printf(" PIMv?"); 384 break; 385 case 1: printf(" PIMv1"); 386 break; 387 case 2: printf(" PIMv2"); 388 break; 389 case 3: printf(" PIMv1+2"); 390 break; 391 } 392 if (bp[4] & 0xfc) 393 (void)printf(" [rsvd=0x%02x]", bp[4] & 0xfc); 394 TCHECK(bp[5]); 395 nentries = bp[5]; 396 bp += 6; len -= 6; 397 s = ' '; 398 for (; nentries; nentries--) { 399 TCHECK2(bp[0], 6); 400 (void)printf("%c%s%s/%d", s, bp[0] & 1 ? "!" : "", 401 ipaddr_string(&bp[2]), bp[1]); 402 if (bp[0] & 0xfe) 403 (void)printf("[rsvd=0x%02x]", bp[0] & 0xfe); 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) 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); 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) 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)", 642 TTEST2(bp[0], len) && 643 in_cksum((const u_short*)bp, len, 0) ? "in" : "" ); 644 } 645 646 switch (PIM_TYPE(pim->pim_typever)) { 647 case PIMV2_TYPE_HELLO: 648 { 649 u_int16_t otype, olen; 650 bp += 4; 651 while (bp < ep) { 652 TCHECK2(bp[0], 4); 653 otype = EXTRACT_16BITS(&bp[0]); 654 olen = EXTRACT_16BITS(&bp[2]); 655 TCHECK2(bp[0], 4 + olen); 656 657 printf("\n\t %s Option (%u), length %u, Value: ", 658 tok2str( pimv2_hello_option_values,"Unknown",otype), 659 otype, 660 olen); 661 bp += 4; 662 663 switch (otype) { 664 case PIMV2_HELLO_OPTION_HOLDTIME: 665 relts_print(EXTRACT_16BITS(bp)); 666 break; 667 668 case PIMV2_HELLO_OPTION_LANPRUNEDELAY: 669 if (olen != 4) { 670 (void)printf("ERROR: Option Lenght != 4 Bytes (%u)", olen); 671 } else { 672 char t_bit; 673 u_int16_t lan_delay, override_interval; 674 lan_delay = EXTRACT_16BITS(bp); 675 override_interval = EXTRACT_16BITS(bp+2); 676 t_bit = (lan_delay & 0x8000)? 1 : 0; 677 lan_delay &= ~0x8000; 678 (void)printf("\n\t T-bit=%d, LAN delay %dms, Override interval %dms", 679 t_bit, lan_delay, override_interval); 680 } 681 break; 682 683 case PIMV2_HELLO_OPTION_DR_PRIORITY_OLD: 684 case PIMV2_HELLO_OPTION_DR_PRIORITY: 685 switch (olen) { 686 case 0: 687 printf("Bi-Directional Capability (Old)"); 688 break; 689 case 4: 690 printf("%u", EXTRACT_32BITS(bp)); 691 break; 692 default: 693 printf("ERROR: Option Lenght != 4 Bytes (%u)", olen); 694 break; 695 } 696 break; 697 698 case PIMV2_HELLO_OPTION_GENID: 699 (void)printf("0x%08x", EXTRACT_32BITS(bp)); 700 break; 701 702 case PIMV2_HELLO_OPTION_REFRESH_CAP: 703 (void)printf("v%d", *bp); 704 if (*(bp+1) != 0) { 705 (void)printf(", interval "); 706 relts_print(*(bp+1)); 707 } 708 if (EXTRACT_16BITS(bp+2) != 0) { 709 (void)printf(" ?0x%04x?", EXTRACT_16BITS(bp+2)); 710 } 711 break; 712 713 case PIMV2_HELLO_OPTION_BIDIR_CAP: 714 break; 715 716 case PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD: 717 case PIMV2_HELLO_OPTION_ADDRESS_LIST: 718 if (vflag > 1) { 719 const u_char *ptr = bp; 720 while (ptr < (bp+olen)) { 721 int advance; 722 723 printf("\n\t "); 724 advance = pimv2_addr_print(ptr, pimv2_unicast, 0); 725 if (advance < 0) { 726 printf("..."); 727 break; 728 } 729 ptr += advance; 730 } 731 } 732 break; 733 default: 734 if (vflag <= 1) 735 print_unknown_data(bp,"\n\t ",olen); 736 break; 737 } 738 /* do we want to see an additionally hexdump ? */ 739 if (vflag> 1) 740 print_unknown_data(bp,"\n\t ",olen); 741 bp += olen; 742 } 743 break; 744 } 745 746 case PIMV2_TYPE_REGISTER: 747 { 748 struct ip *ip; 749 750 if (!TTEST2(*(bp+4), PIMV2_REGISTER_FLAG_LEN)) 751 goto trunc; 752 753 printf(", Flags [ %s ]\n\t", 754 tok2str(pimv2_register_flag_values, 755 "none", 756 EXTRACT_32BITS(bp+4))); 757 758 bp += 8; len -= 8; 759 /* encapsulated multicast packet */ 760 ip = (struct ip *)bp; 761 switch (IP_V(ip)) { 762 case 0: /* Null header */ 763 (void)printf("IP-Null-header %s > %s", 764 ipaddr_string(&ip->ip_src), 765 ipaddr_string(&ip->ip_dst)); 766 break; 767 768 case 4: /* IPv4 */ 769 ip_print(gndo, bp, len); 770 break; 771 #ifdef INET6 772 case 6: /* IPv6 */ 773 ip6_print(bp, len); 774 break; 775 #endif 776 default: 777 (void)printf("IP ver %d", IP_V(ip)); 778 break; 779 } 780 break; 781 } 782 783 case PIMV2_TYPE_REGISTER_STOP: 784 bp += 4; len -= 4; 785 if (bp >= ep) 786 break; 787 (void)printf(" group="); 788 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 789 (void)printf("..."); 790 break; 791 } 792 bp += advance; len -= advance; 793 if (bp >= ep) 794 break; 795 (void)printf(" source="); 796 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 797 (void)printf("..."); 798 break; 799 } 800 bp += advance; len -= advance; 801 break; 802 803 case PIMV2_TYPE_JOIN_PRUNE: 804 case PIMV2_TYPE_GRAFT: 805 case PIMV2_TYPE_GRAFT_ACK: 806 807 808 /* 809 * 0 1 2 3 810 * 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 811 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 812 * |PIM Ver| Type | Addr length | Checksum | 813 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 814 * | Unicast-Upstream Neighbor Address | 815 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 816 * | Reserved | Num groups | Holdtime | 817 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 818 * | Encoded-Multicast Group Address-1 | 819 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 820 * | Number of Joined Sources | Number of Pruned Sources | 821 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 822 * | Encoded-Joined Source Address-1 | 823 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 824 * | . | 825 * | . | 826 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 827 * | Encoded-Joined Source Address-n | 828 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 829 * | Encoded-Pruned Source Address-1 | 830 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 831 * | . | 832 * | . | 833 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 834 * | Encoded-Pruned Source Address-n | 835 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 836 * | . | 837 * | . | 838 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 839 * | Encoded-Multicast Group Address-n | 840 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 841 */ 842 843 { 844 u_int8_t ngroup; 845 u_int16_t holdtime; 846 u_int16_t njoin; 847 u_int16_t nprune; 848 int i, j; 849 850 bp += 4; len -= 4; 851 if (PIM_TYPE(pim->pim_typever) != 7) { /*not for Graft-ACK*/ 852 if (bp >= ep) 853 break; 854 (void)printf(", upstream-neighbor: "); 855 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 856 (void)printf("..."); 857 break; 858 } 859 bp += advance; len -= advance; 860 } 861 if (bp + 4 > ep) 862 break; 863 ngroup = bp[1]; 864 holdtime = EXTRACT_16BITS(&bp[2]); 865 (void)printf("\n\t %u group(s)", ngroup); 866 if (PIM_TYPE(pim->pim_typever) != 7) { /*not for Graft-ACK*/ 867 (void)printf(", holdtime: "); 868 if (holdtime == 0xffff) 869 (void)printf("infinite"); 870 else 871 relts_print(holdtime); 872 } 873 bp += 4; len -= 4; 874 for (i = 0; i < ngroup; i++) { 875 if (bp >= ep) 876 goto jp_done; 877 (void)printf("\n\t group #%u: ", i+1); 878 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 879 (void)printf("...)"); 880 goto jp_done; 881 } 882 bp += advance; len -= advance; 883 if (bp + 4 > ep) { 884 (void)printf("...)"); 885 goto jp_done; 886 } 887 njoin = EXTRACT_16BITS(&bp[0]); 888 nprune = EXTRACT_16BITS(&bp[2]); 889 (void)printf(", joined sources: %u, pruned sources: %u", njoin,nprune); 890 bp += 4; len -= 4; 891 for (j = 0; j < njoin; j++) { 892 (void)printf("\n\t joined source #%u: ",j+1); 893 if ((advance = pimv2_addr_print(bp, pimv2_source, 0)) < 0) { 894 (void)printf("...)"); 895 goto jp_done; 896 } 897 bp += advance; len -= advance; 898 } 899 for (j = 0; j < nprune; j++) { 900 (void)printf("\n\t pruned source #%u: ",j+1); 901 if ((advance = pimv2_addr_print(bp, pimv2_source, 0)) < 0) { 902 (void)printf("...)"); 903 goto jp_done; 904 } 905 bp += advance; len -= advance; 906 } 907 } 908 jp_done: 909 break; 910 } 911 912 case PIMV2_TYPE_BOOTSTRAP: 913 { 914 int i, j, frpcnt; 915 bp += 4; 916 917 /* Fragment Tag, Hash Mask len, and BSR-priority */ 918 if (bp + sizeof(u_int16_t) >= ep) break; 919 (void)printf(" tag=%x", EXTRACT_16BITS(bp)); 920 bp += sizeof(u_int16_t); 921 if (bp >= ep) break; 922 (void)printf(" hashmlen=%d", bp[0]); 923 if (bp + 1 >= ep) break; 924 (void)printf(" BSRprio=%d", bp[1]); 925 bp += 2; 926 927 /* Encoded-Unicast-BSR-Address */ 928 if (bp >= ep) break; 929 (void)printf(" BSR="); 930 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 931 (void)printf("..."); 932 break; 933 } 934 bp += advance; 935 936 for (i = 0; bp < ep; i++) { 937 /* Encoded-Group Address */ 938 (void)printf(" (group%d: ", i); 939 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) 940 < 0) { 941 (void)printf("...)"); 942 goto bs_done; 943 } 944 bp += advance; 945 946 /* RP-Count, Frag RP-Cnt, and rsvd */ 947 if (bp >= ep) { 948 (void)printf("...)"); 949 goto bs_done; 950 } 951 (void)printf(" RPcnt=%d", bp[0]); 952 if (bp + 1 >= ep) { 953 (void)printf("...)"); 954 goto bs_done; 955 } 956 (void)printf(" FRPcnt=%d", frpcnt = bp[1]); 957 bp += 4; 958 959 for (j = 0; j < frpcnt && bp < ep; j++) { 960 /* each RP info */ 961 (void)printf(" RP%d=", j); 962 if ((advance = pimv2_addr_print(bp, 963 pimv2_unicast, 964 0)) < 0) { 965 (void)printf("...)"); 966 goto bs_done; 967 } 968 bp += advance; 969 970 if (bp + 1 >= ep) { 971 (void)printf("...)"); 972 goto bs_done; 973 } 974 (void)printf(",holdtime="); 975 relts_print(EXTRACT_16BITS(bp)); 976 if (bp + 2 >= ep) { 977 (void)printf("...)"); 978 goto bs_done; 979 } 980 (void)printf(",prio=%d", bp[2]); 981 bp += 4; 982 } 983 (void)printf(")"); 984 } 985 bs_done: 986 break; 987 } 988 case PIMV2_TYPE_ASSERT: 989 bp += 4; len -= 4; 990 if (bp >= ep) 991 break; 992 (void)printf(" group="); 993 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 994 (void)printf("..."); 995 break; 996 } 997 bp += advance; len -= advance; 998 if (bp >= ep) 999 break; 1000 (void)printf(" src="); 1001 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 1002 (void)printf("..."); 1003 break; 1004 } 1005 bp += advance; len -= advance; 1006 if (bp + 8 > ep) 1007 break; 1008 if (bp[0] & 0x80) 1009 (void)printf(" RPT"); 1010 (void)printf(" pref=%u", EXTRACT_32BITS(&bp[0]) & 0x7fffffff); 1011 (void)printf(" metric=%u", EXTRACT_32BITS(&bp[4])); 1012 break; 1013 1014 case PIMV2_TYPE_CANDIDATE_RP: 1015 { 1016 int i, pfxcnt; 1017 bp += 4; 1018 1019 /* Prefix-Cnt, Priority, and Holdtime */ 1020 if (bp >= ep) break; 1021 (void)printf(" prefix-cnt=%d", bp[0]); 1022 pfxcnt = bp[0]; 1023 if (bp + 1 >= ep) break; 1024 (void)printf(" prio=%d", bp[1]); 1025 if (bp + 3 >= ep) break; 1026 (void)printf(" holdtime="); 1027 relts_print(EXTRACT_16BITS(&bp[2])); 1028 bp += 4; 1029 1030 /* Encoded-Unicast-RP-Address */ 1031 if (bp >= ep) break; 1032 (void)printf(" RP="); 1033 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 1034 (void)printf("..."); 1035 break; 1036 } 1037 bp += advance; 1038 1039 /* Encoded-Group Addresses */ 1040 for (i = 0; i < pfxcnt && bp < ep; i++) { 1041 (void)printf(" Group%d=", i); 1042 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) 1043 < 0) { 1044 (void)printf("..."); 1045 break; 1046 } 1047 bp += advance; 1048 } 1049 break; 1050 } 1051 1052 case PIMV2_TYPE_PRUNE_REFRESH: 1053 (void)printf(" src="); 1054 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 1055 (void)printf("..."); 1056 break; 1057 } 1058 bp += advance; 1059 (void)printf(" grp="); 1060 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 1061 (void)printf("..."); 1062 break; 1063 } 1064 bp += advance; 1065 (void)printf(" forwarder="); 1066 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 1067 (void)printf("..."); 1068 break; 1069 } 1070 bp += advance; 1071 TCHECK2(bp[0], 2); 1072 (void)printf(" TUNR "); 1073 relts_print(EXTRACT_16BITS(bp)); 1074 break; 1075 1076 1077 default: 1078 (void)printf(" [type %d]", PIM_TYPE(pim->pim_typever)); 1079 break; 1080 } 1081 1082 return; 1083 1084 trunc: 1085 (void)printf("[|pim]"); 1086 } 1087 1088 /* 1089 * Local Variables: 1090 * c-style: whitesmith 1091 * c-basic-offset: 8 1092 * End: 1093 */ 1094