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.49 2006-02-13 01:31:35 hannes Exp $ (LBL)"; 27 #endif 28 29 #ifdef HAVE_CONFIG_H 30 #include "config.h" 31 #endif 32 33 #include <tcpdump-stdinc.h> 34 #include "interface.h" 35 36 #define PIMV2_TYPE_HELLO 0 37 #define PIMV2_TYPE_REGISTER 1 38 #define PIMV2_TYPE_REGISTER_STOP 2 39 #define PIMV2_TYPE_JOIN_PRUNE 3 40 #define PIMV2_TYPE_BOOTSTRAP 4 41 #define PIMV2_TYPE_ASSERT 5 42 #define PIMV2_TYPE_GRAFT 6 43 #define PIMV2_TYPE_GRAFT_ACK 7 44 #define PIMV2_TYPE_CANDIDATE_RP 8 45 #define PIMV2_TYPE_PRUNE_REFRESH 9 46 47 static struct tok pimv2_type_values[] = { 48 { PIMV2_TYPE_HELLO, "Hello" }, 49 { PIMV2_TYPE_REGISTER, "Register" }, 50 { PIMV2_TYPE_REGISTER_STOP, "Register Stop" }, 51 { PIMV2_TYPE_JOIN_PRUNE, "Join / Prune" }, 52 { PIMV2_TYPE_BOOTSTRAP, "Bootstrap" }, 53 { PIMV2_TYPE_ASSERT, "Assert" }, 54 { PIMV2_TYPE_GRAFT, "Graft" }, 55 { PIMV2_TYPE_GRAFT_ACK, "Graft Acknowledgement" }, 56 { PIMV2_TYPE_CANDIDATE_RP, "Candidate RP Advertisement" }, 57 { PIMV2_TYPE_PRUNE_REFRESH, "Prune Refresh" }, 58 { 0, NULL} 59 }; 60 61 #define PIMV2_HELLO_OPTION_HOLDTIME 1 62 #define PIMV2_HELLO_OPTION_LANPRUNEDELAY 2 63 #define PIMV2_HELLO_OPTION_DR_PRIORITY_OLD 18 64 #define PIMV2_HELLO_OPTION_DR_PRIORITY 19 65 #define PIMV2_HELLO_OPTION_GENID 20 66 #define PIMV2_HELLO_OPTION_REFRESH_CAP 21 67 #define PIMV2_HELLO_OPTION_BIDIR_CAP 22 68 #define PIMV2_HELLO_OPTION_ADDRESS_LIST 24 69 #define PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD 65001 70 71 static struct tok pimv2_hello_option_values[] = { 72 { PIMV2_HELLO_OPTION_HOLDTIME, "Hold Time" }, 73 { PIMV2_HELLO_OPTION_LANPRUNEDELAY, "LAN Prune Delay" }, 74 { PIMV2_HELLO_OPTION_DR_PRIORITY_OLD, "DR Priority (Old)" }, 75 { PIMV2_HELLO_OPTION_DR_PRIORITY, "DR Priority" }, 76 { PIMV2_HELLO_OPTION_GENID, "Generation ID" }, 77 { PIMV2_HELLO_OPTION_REFRESH_CAP, "State Refresh Capability" }, 78 { PIMV2_HELLO_OPTION_BIDIR_CAP, "Bi-Directional Capability" }, 79 { PIMV2_HELLO_OPTION_ADDRESS_LIST, "Address List" }, 80 { PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD, "Address List (Old)" }, 81 { 0, NULL} 82 }; 83 84 #define PIMV2_REGISTER_FLAG_LEN 4 85 #define PIMV2_REGISTER_FLAG_BORDER 0x80000000 86 #define PIMV2_REGISTER_FLAG_NULL 0x40000000 87 88 static struct tok pimv2_register_flag_values[] = { 89 { PIMV2_REGISTER_FLAG_BORDER, "Border" }, 90 { PIMV2_REGISTER_FLAG_NULL, "Null" }, 91 { 0, NULL} 92 }; 93 94 /* 95 * XXX: We consider a case where IPv6 is not ready yet for portability, 96 * but PIM dependent defintions should be independent of IPv6... 97 */ 98 99 struct pim { 100 u_int8_t pim_typever; 101 /* upper 4bit: PIM version number; 2 for PIMv2 */ 102 /* lower 4bit: the PIM message type, currently they are: 103 * Hello, Register, Register-Stop, Join/Prune, 104 * Bootstrap, Assert, Graft (PIM-DM only), 105 * Graft-Ack (PIM-DM only), C-RP-Adv 106 */ 107 #define PIM_VER(x) (((x) & 0xf0) >> 4) 108 #define PIM_TYPE(x) ((x) & 0x0f) 109 u_char pim_rsv; /* Reserved */ 110 u_short pim_cksum; /* IP style check sum */ 111 }; 112 113 114 #include <stdio.h> 115 #include <stdlib.h> 116 117 #include "interface.h" 118 #include "addrtoname.h" 119 #include "extract.h" 120 121 #include "ip.h" 122 123 static void pimv2_print(register const u_char *bp, register u_int len, u_int cksum); 124 125 static void 126 pimv1_join_prune_print(register const u_char *bp, register u_int len) 127 { 128 int maddrlen, addrlen, ngroups, njoin, nprune; 129 int njp; 130 131 /* If it's a single group and a single source, use 1-line output. */ 132 if (TTEST2(bp[0], 30) && bp[11] == 1 && 133 ((njoin = EXTRACT_16BITS(&bp[20])) + EXTRACT_16BITS(&bp[22])) == 1) { 134 int hold; 135 136 (void)printf(" RPF %s ", ipaddr_string(bp)); 137 hold = EXTRACT_16BITS(&bp[6]); 138 if (hold != 180) { 139 (void)printf("Hold "); 140 relts_print(hold); 141 } 142 (void)printf("%s (%s/%d, %s", njoin ? "Join" : "Prune", 143 ipaddr_string(&bp[26]), bp[25] & 0x3f, 144 ipaddr_string(&bp[12])); 145 if (EXTRACT_32BITS(&bp[16]) != 0xffffffff) 146 (void)printf("/%s", ipaddr_string(&bp[16])); 147 (void)printf(") %s%s %s", 148 (bp[24] & 0x01) ? "Sparse" : "Dense", 149 (bp[25] & 0x80) ? " WC" : "", 150 (bp[25] & 0x40) ? "RP" : "SPT"); 151 return; 152 } 153 154 TCHECK2(bp[0], sizeof(struct in_addr)); 155 if (vflag > 1) 156 (void)printf("\n"); 157 (void)printf(" Upstream Nbr: %s", ipaddr_string(bp)); 158 TCHECK2(bp[6], 2); 159 if (vflag > 1) 160 (void)printf("\n"); 161 (void)printf(" Hold time: "); 162 relts_print(EXTRACT_16BITS(&bp[6])); 163 if (vflag < 2) 164 return; 165 bp += 8; 166 len -= 8; 167 168 TCHECK2(bp[0], 4); 169 maddrlen = bp[1]; 170 addrlen = bp[2]; 171 ngroups = bp[3]; 172 bp += 4; 173 len -= 4; 174 while (ngroups--) { 175 /* 176 * XXX - does the address have length "addrlen" and the 177 * mask length "maddrlen"? 178 */ 179 TCHECK2(bp[0], sizeof(struct in_addr)); 180 (void)printf("\n\tGroup: %s", ipaddr_string(bp)); 181 TCHECK2(bp[4], sizeof(struct in_addr)); 182 if (EXTRACT_32BITS(&bp[4]) != 0xffffffff) 183 (void)printf("/%s", ipaddr_string(&bp[4])); 184 TCHECK2(bp[8], 4); 185 njoin = EXTRACT_16BITS(&bp[8]); 186 nprune = EXTRACT_16BITS(&bp[10]); 187 (void)printf(" joined: %d pruned: %d", njoin, nprune); 188 bp += 12; 189 len -= 12; 190 for (njp = 0; njp < (njoin + nprune); njp++) { 191 const char *type; 192 193 if (njp < njoin) 194 type = "Join "; 195 else 196 type = "Prune"; 197 TCHECK2(bp[0], 6); 198 (void)printf("\n\t%s %s%s%s%s/%d", type, 199 (bp[0] & 0x01) ? "Sparse " : "Dense ", 200 (bp[1] & 0x80) ? "WC " : "", 201 (bp[1] & 0x40) ? "RP " : "SPT ", 202 ipaddr_string(&bp[2]), bp[1] & 0x3f); 203 bp += 6; 204 len -= 6; 205 } 206 } 207 return; 208 trunc: 209 (void)printf("[|pim]"); 210 return; 211 } 212 213 void 214 pimv1_print(register const u_char *bp, register u_int len) 215 { 216 register const u_char *ep; 217 register u_char type; 218 219 ep = (const u_char *)snapend; 220 if (bp >= ep) 221 return; 222 223 TCHECK(bp[1]); 224 type = bp[1]; 225 226 switch (type) { 227 case 0: 228 (void)printf(" Query"); 229 if (TTEST(bp[8])) { 230 switch (bp[8] >> 4) { 231 case 0: 232 (void)printf(" Dense-mode"); 233 break; 234 case 1: 235 (void)printf(" Sparse-mode"); 236 break; 237 case 2: 238 (void)printf(" Sparse-Dense-mode"); 239 break; 240 default: 241 (void)printf(" mode-%d", bp[8] >> 4); 242 break; 243 } 244 } 245 if (vflag) { 246 TCHECK2(bp[10],2); 247 (void)printf(" (Hold-time "); 248 relts_print(EXTRACT_16BITS(&bp[10])); 249 (void)printf(")"); 250 } 251 break; 252 253 case 1: 254 (void)printf(" Register"); 255 TCHECK2(bp[8], 20); /* ip header */ 256 (void)printf(" for %s > %s", ipaddr_string(&bp[20]), 257 ipaddr_string(&bp[24])); 258 break; 259 case 2: 260 (void)printf(" Register-Stop"); 261 TCHECK2(bp[12], sizeof(struct in_addr)); 262 (void)printf(" for %s > %s", ipaddr_string(&bp[8]), 263 ipaddr_string(&bp[12])); 264 break; 265 case 3: 266 (void)printf(" Join/Prune"); 267 if (vflag) 268 pimv1_join_prune_print(&bp[8], len - 8); 269 break; 270 case 4: 271 (void)printf(" RP-reachable"); 272 if (vflag) { 273 TCHECK2(bp[22], 2); 274 (void)printf(" group %s", 275 ipaddr_string(&bp[8])); 276 if (EXTRACT_32BITS(&bp[12]) != 0xffffffff) 277 (void)printf("/%s", ipaddr_string(&bp[12])); 278 (void)printf(" RP %s hold ", ipaddr_string(&bp[16])); 279 relts_print(EXTRACT_16BITS(&bp[22])); 280 } 281 break; 282 case 5: 283 (void)printf(" Assert"); 284 TCHECK2(bp[16], sizeof(struct in_addr)); 285 (void)printf(" for %s > %s", ipaddr_string(&bp[16]), 286 ipaddr_string(&bp[8])); 287 if (EXTRACT_32BITS(&bp[12]) != 0xffffffff) 288 (void)printf("/%s", ipaddr_string(&bp[12])); 289 TCHECK2(bp[24], 4); 290 (void)printf(" %s pref %d metric %d", 291 (bp[20] & 0x80) ? "RP-tree" : "SPT", 292 EXTRACT_32BITS(&bp[20]) & 0x7fffffff, 293 EXTRACT_32BITS(&bp[24])); 294 break; 295 case 6: 296 (void)printf(" Graft"); 297 if (vflag) 298 pimv1_join_prune_print(&bp[8], len - 8); 299 break; 300 case 7: 301 (void)printf(" Graft-ACK"); 302 if (vflag) 303 pimv1_join_prune_print(&bp[8], len - 8); 304 break; 305 case 8: 306 (void)printf(" Mode"); 307 break; 308 default: 309 (void)printf(" [type %d]", type); 310 break; 311 } 312 if ((bp[4] >> 4) != 1) 313 (void)printf(" [v%d]", bp[4] >> 4); 314 return; 315 316 trunc: 317 (void)printf("[|pim]"); 318 return; 319 } 320 321 /* 322 * auto-RP is a cisco protocol, documented at 323 * ftp://ftpeng.cisco.com/ipmulticast/specs/pim-autorp-spec01.txt 324 * 325 * This implements version 1+, dated Sept 9, 1998. 326 */ 327 void 328 cisco_autorp_print(register const u_char *bp, register u_int len) 329 { 330 int type; 331 int numrps; 332 int hold; 333 334 TCHECK(bp[0]); 335 (void)printf(" auto-rp "); 336 type = bp[0]; 337 switch (type) { 338 case 0x11: 339 (void)printf("candidate-advert"); 340 break; 341 case 0x12: 342 (void)printf("mapping"); 343 break; 344 default: 345 (void)printf("type-0x%02x", type); 346 break; 347 } 348 349 TCHECK(bp[1]); 350 numrps = bp[1]; 351 352 TCHECK2(bp[2], 2); 353 (void)printf(" Hold "); 354 hold = EXTRACT_16BITS(&bp[2]); 355 if (hold) 356 relts_print(EXTRACT_16BITS(&bp[2])); 357 else 358 printf("FOREVER"); 359 360 /* Next 4 bytes are reserved. */ 361 362 bp += 8; len -= 8; 363 364 /*XXX skip unless -v? */ 365 366 /* 367 * Rest of packet: 368 * numrps entries of the form: 369 * 32 bits: RP 370 * 6 bits: reserved 371 * 2 bits: PIM version supported, bit 0 is "supports v1", 1 is "v2". 372 * 8 bits: # of entries for this RP 373 * each entry: 7 bits: reserved, 1 bit: negative, 374 * 8 bits: mask 32 bits: source 375 * lather, rinse, repeat. 376 */ 377 while (numrps--) { 378 int nentries; 379 char s; 380 381 TCHECK2(bp[0], 4); 382 (void)printf(" RP %s", ipaddr_string(bp)); 383 TCHECK(bp[4]); 384 switch (bp[4] & 0x3) { 385 case 0: printf(" PIMv?"); 386 break; 387 case 1: printf(" PIMv1"); 388 break; 389 case 2: printf(" PIMv2"); 390 break; 391 case 3: printf(" PIMv1+2"); 392 break; 393 } 394 if (bp[4] & 0xfc) 395 (void)printf(" [rsvd=0x%02x]", bp[4] & 0xfc); 396 TCHECK(bp[5]); 397 nentries = bp[5]; 398 bp += 6; len -= 6; 399 s = ' '; 400 for (; nentries; nentries--) { 401 TCHECK2(bp[0], 6); 402 (void)printf("%c%s%s/%d", s, bp[0] & 1 ? "!" : "", 403 ipaddr_string(&bp[2]), bp[1]); 404 if (bp[0] & 0xfe) 405 (void)printf("[rsvd=0x%02x]", bp[0] & 0xfe); 406 s = ','; 407 bp += 6; len -= 6; 408 } 409 } 410 return; 411 412 trunc: 413 (void)printf("[|autorp]"); 414 return; 415 } 416 417 void 418 pim_print(register const u_char *bp, register u_int len, u_int cksum) 419 { 420 register const u_char *ep; 421 register struct pim *pim = (struct pim *)bp; 422 423 ep = (const u_char *)snapend; 424 if (bp >= ep) 425 return; 426 #ifdef notyet /* currently we see only version and type */ 427 TCHECK(pim->pim_rsv); 428 #endif 429 430 switch (PIM_VER(pim->pim_typever)) { 431 case 2: 432 if (!vflag) { 433 printf("PIMv%u, %s, length %u", 434 PIM_VER(pim->pim_typever), 435 tok2str(pimv2_type_values,"Unknown Type",PIM_TYPE(pim->pim_typever)), 436 len); 437 return; 438 } else { 439 printf("PIMv%u, length %u\n\t%s", 440 PIM_VER(pim->pim_typever), 441 len, 442 tok2str(pimv2_type_values,"Unknown Type",PIM_TYPE(pim->pim_typever))); 443 pimv2_print(bp, len, cksum); 444 } 445 break; 446 default: 447 printf("PIMv%u, length %u", 448 PIM_VER(pim->pim_typever), 449 len); 450 break; 451 } 452 return; 453 } 454 455 /* 456 * PIMv2 uses encoded address representations. 457 * 458 * The last PIM-SM I-D before RFC2117 was published specified the 459 * following representation for unicast addresses. However, RFC2117 460 * specified no encoding for unicast addresses with the unicast 461 * address length specified in the header. Therefore, we have to 462 * guess which encoding is being used (Cisco's PIMv2 implementation 463 * uses the non-RFC encoding). RFC2117 turns a previously "Reserved" 464 * field into a 'unicast-address-length-in-bytes' field. We guess 465 * that it's the draft encoding if this reserved field is zero. 466 * 467 * RFC2362 goes back to the encoded format, and calls the addr length 468 * field "reserved" again. 469 * 470 * The first byte is the address family, from: 471 * 472 * 0 Reserved 473 * 1 IP (IP version 4) 474 * 2 IP6 (IP version 6) 475 * 3 NSAP 476 * 4 HDLC (8-bit multidrop) 477 * 5 BBN 1822 478 * 6 802 (includes all 802 media plus Ethernet "canonical format") 479 * 7 E.163 480 * 8 E.164 (SMDS, Frame Relay, ATM) 481 * 9 F.69 (Telex) 482 * 10 X.121 (X.25, Frame Relay) 483 * 11 IPX 484 * 12 Appletalk 485 * 13 Decnet IV 486 * 14 Banyan Vines 487 * 15 E.164 with NSAP format subaddress 488 * 489 * In addition, the second byte is an "Encoding". 0 is the default 490 * encoding for the address family, and no other encodings are currently 491 * specified. 492 * 493 */ 494 495 static int pimv2_addr_len; 496 497 enum pimv2_addrtype { 498 pimv2_unicast, pimv2_group, pimv2_source 499 }; 500 501 /* 0 1 2 3 502 * 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 503 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 504 * | Addr Family | Encoding Type | Unicast Address | 505 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+++++++ 506 * 0 1 2 3 507 * 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 508 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 509 * | Addr Family | Encoding Type | Reserved | Mask Len | 510 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 511 * | Group multicast 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 | Rsrvd |S|W|R| Mask Len | 517 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 518 * | Source Address | 519 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 520 */ 521 static int 522 pimv2_addr_print(const u_char *bp, enum pimv2_addrtype at, int silent) 523 { 524 int af; 525 int len, hdrlen; 526 527 TCHECK(bp[0]); 528 529 if (pimv2_addr_len == 0) { 530 TCHECK(bp[1]); 531 switch (bp[0]) { 532 case 1: 533 af = AF_INET; 534 len = sizeof(struct in_addr); 535 break; 536 #ifdef INET6 537 case 2: 538 af = AF_INET6; 539 len = sizeof(struct in6_addr); 540 break; 541 #endif 542 default: 543 return -1; 544 } 545 if (bp[1] != 0) 546 return -1; 547 hdrlen = 2; 548 } else { 549 switch (pimv2_addr_len) { 550 case sizeof(struct in_addr): 551 af = AF_INET; 552 break; 553 #ifdef INET6 554 case sizeof(struct in6_addr): 555 af = AF_INET6; 556 break; 557 #endif 558 default: 559 return -1; 560 break; 561 } 562 len = pimv2_addr_len; 563 hdrlen = 0; 564 } 565 566 bp += hdrlen; 567 switch (at) { 568 case pimv2_unicast: 569 TCHECK2(bp[0], len); 570 if (af == AF_INET) { 571 if (!silent) 572 (void)printf("%s", ipaddr_string(bp)); 573 } 574 #ifdef INET6 575 else if (af == AF_INET6) { 576 if (!silent) 577 (void)printf("%s", ip6addr_string(bp)); 578 } 579 #endif 580 return hdrlen + len; 581 case pimv2_group: 582 case pimv2_source: 583 TCHECK2(bp[0], len + 2); 584 if (af == AF_INET) { 585 if (!silent) { 586 (void)printf("%s", ipaddr_string(bp + 2)); 587 if (bp[1] != 32) 588 (void)printf("/%u", bp[1]); 589 } 590 } 591 #ifdef INET6 592 else if (af == AF_INET6) { 593 if (!silent) { 594 (void)printf("%s", ip6addr_string(bp + 2)); 595 if (bp[1] != 128) 596 (void)printf("/%u", bp[1]); 597 } 598 } 599 #endif 600 if (bp[0] && !silent) { 601 if (at == pimv2_group) { 602 (void)printf("(0x%02x)", bp[0]); 603 } else { 604 (void)printf("(%s%s%s", 605 bp[0] & 0x04 ? "S" : "", 606 bp[0] & 0x02 ? "W" : "", 607 bp[0] & 0x01 ? "R" : ""); 608 if (bp[0] & 0xf8) { 609 (void) printf("+0x%02x", bp[0] & 0xf8); 610 } 611 (void)printf(")"); 612 } 613 } 614 return hdrlen + 2 + len; 615 default: 616 return -1; 617 } 618 trunc: 619 return -1; 620 } 621 622 static void 623 pimv2_print(register const u_char *bp, register u_int len, u_int cksum) 624 { 625 register const u_char *ep; 626 register struct pim *pim = (struct pim *)bp; 627 int advance; 628 629 ep = (const u_char *)snapend; 630 if (bp >= ep) 631 return; 632 if (ep > bp + len) 633 ep = bp + len; 634 TCHECK(pim->pim_rsv); 635 pimv2_addr_len = pim->pim_rsv; 636 if (pimv2_addr_len != 0) 637 (void)printf(", RFC2117-encoding"); 638 639 printf(", cksum 0x%04x ", EXTRACT_16BITS(&pim->pim_cksum)); 640 if (EXTRACT_16BITS(&pim->pim_cksum) == 0) { 641 printf("(unverified)"); 642 } else { 643 printf("(%scorrect)", TTEST2(bp[0], len) && cksum ? "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