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 35 #include <stdio.h> 36 #include <stdlib.h> 37 38 #include "interface.h" 39 #include "addrtoname.h" 40 #include "extract.h" 41 42 #include "ip.h" 43 44 #define PIMV2_TYPE_HELLO 0 45 #define PIMV2_TYPE_REGISTER 1 46 #define PIMV2_TYPE_REGISTER_STOP 2 47 #define PIMV2_TYPE_JOIN_PRUNE 3 48 #define PIMV2_TYPE_BOOTSTRAP 4 49 #define PIMV2_TYPE_ASSERT 5 50 #define PIMV2_TYPE_GRAFT 6 51 #define PIMV2_TYPE_GRAFT_ACK 7 52 #define PIMV2_TYPE_CANDIDATE_RP 8 53 #define PIMV2_TYPE_PRUNE_REFRESH 9 54 55 static struct tok pimv2_type_values[] = { 56 { PIMV2_TYPE_HELLO, "Hello" }, 57 { PIMV2_TYPE_REGISTER, "Register" }, 58 { PIMV2_TYPE_REGISTER_STOP, "Register Stop" }, 59 { PIMV2_TYPE_JOIN_PRUNE, "Join / Prune" }, 60 { PIMV2_TYPE_BOOTSTRAP, "Bootstrap" }, 61 { PIMV2_TYPE_ASSERT, "Assert" }, 62 { PIMV2_TYPE_GRAFT, "Graft" }, 63 { PIMV2_TYPE_GRAFT_ACK, "Graft Acknowledgement" }, 64 { PIMV2_TYPE_CANDIDATE_RP, "Candidate RP Advertisement" }, 65 { PIMV2_TYPE_PRUNE_REFRESH, "Prune Refresh" }, 66 { 0, NULL} 67 }; 68 69 #define PIMV2_HELLO_OPTION_HOLDTIME 1 70 #define PIMV2_HELLO_OPTION_LANPRUNEDELAY 2 71 #define PIMV2_HELLO_OPTION_DR_PRIORITY_OLD 18 72 #define PIMV2_HELLO_OPTION_DR_PRIORITY 19 73 #define PIMV2_HELLO_OPTION_GENID 20 74 #define PIMV2_HELLO_OPTION_REFRESH_CAP 21 75 #define PIMV2_HELLO_OPTION_BIDIR_CAP 22 76 #define PIMV2_HELLO_OPTION_ADDRESS_LIST 24 77 #define PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD 65001 78 79 static struct tok pimv2_hello_option_values[] = { 80 { PIMV2_HELLO_OPTION_HOLDTIME, "Hold Time" }, 81 { PIMV2_HELLO_OPTION_LANPRUNEDELAY, "LAN Prune Delay" }, 82 { PIMV2_HELLO_OPTION_DR_PRIORITY_OLD, "DR Priority (Old)" }, 83 { PIMV2_HELLO_OPTION_DR_PRIORITY, "DR Priority" }, 84 { PIMV2_HELLO_OPTION_GENID, "Generation ID" }, 85 { PIMV2_HELLO_OPTION_REFRESH_CAP, "State Refresh Capability" }, 86 { PIMV2_HELLO_OPTION_BIDIR_CAP, "Bi-Directional Capability" }, 87 { PIMV2_HELLO_OPTION_ADDRESS_LIST, "Address List" }, 88 { PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD, "Address List (Old)" }, 89 { 0, NULL} 90 }; 91 92 #define PIMV2_REGISTER_FLAG_LEN 4 93 #define PIMV2_REGISTER_FLAG_BORDER 0x80000000 94 #define PIMV2_REGISTER_FLAG_NULL 0x40000000 95 96 static struct tok pimv2_register_flag_values[] = { 97 { PIMV2_REGISTER_FLAG_BORDER, "Border" }, 98 { PIMV2_REGISTER_FLAG_NULL, "Null" }, 99 { 0, NULL} 100 }; 101 102 /* 103 * XXX: We consider a case where IPv6 is not ready yet for portability, 104 * but PIM dependent defintions should be independent of IPv6... 105 */ 106 107 struct pim { 108 u_int8_t pim_typever; 109 /* upper 4bit: PIM version number; 2 for PIMv2 */ 110 /* lower 4bit: the PIM message type, currently they are: 111 * Hello, Register, Register-Stop, Join/Prune, 112 * Bootstrap, Assert, Graft (PIM-DM only), 113 * Graft-Ack (PIM-DM only), C-RP-Adv 114 */ 115 #define PIM_VER(x) (((x) & 0xf0) >> 4) 116 #define PIM_TYPE(x) ((x) & 0x0f) 117 u_char pim_rsv; /* Reserved */ 118 u_short pim_cksum; /* IP style check sum */ 119 }; 120 121 static void pimv2_print(register const u_char *bp, register u_int len, u_int cksum); 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] & 0x02) { 403 (void)printf(" bidir"); 404 } 405 if (bp[0] & 0xfc) { 406 (void)printf("[rsvd=0x%02x]", bp[0] & 0xfc); 407 } 408 s = ','; 409 bp += 6; len -= 6; 410 } 411 } 412 return; 413 414 trunc: 415 (void)printf("[|autorp]"); 416 return; 417 } 418 419 void 420 pim_print(register const u_char *bp, register u_int len, u_int cksum) 421 { 422 register const u_char *ep; 423 register struct pim *pim = (struct pim *)bp; 424 425 ep = (const u_char *)snapend; 426 if (bp >= ep) 427 return; 428 #ifdef notyet /* currently we see only version and type */ 429 TCHECK(pim->pim_rsv); 430 #endif 431 432 switch (PIM_VER(pim->pim_typever)) { 433 case 2: 434 if (!vflag) { 435 printf("PIMv%u, %s, length %u", 436 PIM_VER(pim->pim_typever), 437 tok2str(pimv2_type_values,"Unknown Type",PIM_TYPE(pim->pim_typever)), 438 len); 439 return; 440 } else { 441 printf("PIMv%u, length %u\n\t%s", 442 PIM_VER(pim->pim_typever), 443 len, 444 tok2str(pimv2_type_values,"Unknown Type",PIM_TYPE(pim->pim_typever))); 445 pimv2_print(bp, len, cksum); 446 } 447 break; 448 default: 449 printf("PIMv%u, length %u", 450 PIM_VER(pim->pim_typever), 451 len); 452 break; 453 } 454 return; 455 } 456 457 /* 458 * PIMv2 uses encoded address representations. 459 * 460 * The last PIM-SM I-D before RFC2117 was published specified the 461 * following representation for unicast addresses. However, RFC2117 462 * specified no encoding for unicast addresses with the unicast 463 * address length specified in the header. Therefore, we have to 464 * guess which encoding is being used (Cisco's PIMv2 implementation 465 * uses the non-RFC encoding). RFC2117 turns a previously "Reserved" 466 * field into a 'unicast-address-length-in-bytes' field. We guess 467 * that it's the draft encoding if this reserved field is zero. 468 * 469 * RFC2362 goes back to the encoded format, and calls the addr length 470 * field "reserved" again. 471 * 472 * The first byte is the address family, from: 473 * 474 * 0 Reserved 475 * 1 IP (IP version 4) 476 * 2 IP6 (IP version 6) 477 * 3 NSAP 478 * 4 HDLC (8-bit multidrop) 479 * 5 BBN 1822 480 * 6 802 (includes all 802 media plus Ethernet "canonical format") 481 * 7 E.163 482 * 8 E.164 (SMDS, Frame Relay, ATM) 483 * 9 F.69 (Telex) 484 * 10 X.121 (X.25, Frame Relay) 485 * 11 IPX 486 * 12 Appletalk 487 * 13 Decnet IV 488 * 14 Banyan Vines 489 * 15 E.164 with NSAP format subaddress 490 * 491 * In addition, the second byte is an "Encoding". 0 is the default 492 * encoding for the address family, and no other encodings are currently 493 * specified. 494 * 495 */ 496 497 static int pimv2_addr_len; 498 499 enum pimv2_addrtype { 500 pimv2_unicast, pimv2_group, pimv2_source 501 }; 502 503 /* 0 1 2 3 504 * 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 505 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 506 * | Addr Family | Encoding Type | Unicast Address | 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 | Reserved | Mask Len | 512 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 513 * | Group multicast Address | 514 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 515 * 0 1 2 3 516 * 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 517 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 518 * | Addr Family | Encoding Type | Rsrvd |S|W|R| Mask Len | 519 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 520 * | Source Address | 521 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 522 */ 523 static int 524 pimv2_addr_print(const u_char *bp, enum pimv2_addrtype at, int silent) 525 { 526 int af; 527 int len, hdrlen; 528 529 TCHECK(bp[0]); 530 531 if (pimv2_addr_len == 0) { 532 TCHECK(bp[1]); 533 switch (bp[0]) { 534 case 1: 535 af = AF_INET; 536 len = sizeof(struct in_addr); 537 break; 538 #ifdef INET6 539 case 2: 540 af = AF_INET6; 541 len = sizeof(struct in6_addr); 542 break; 543 #endif 544 default: 545 return -1; 546 } 547 if (bp[1] != 0) 548 return -1; 549 hdrlen = 2; 550 } else { 551 switch (pimv2_addr_len) { 552 case sizeof(struct in_addr): 553 af = AF_INET; 554 break; 555 #ifdef INET6 556 case sizeof(struct in6_addr): 557 af = AF_INET6; 558 break; 559 #endif 560 default: 561 return -1; 562 break; 563 } 564 len = pimv2_addr_len; 565 hdrlen = 0; 566 } 567 568 bp += hdrlen; 569 switch (at) { 570 case pimv2_unicast: 571 TCHECK2(bp[0], len); 572 if (af == AF_INET) { 573 if (!silent) 574 (void)printf("%s", ipaddr_string(bp)); 575 } 576 #ifdef INET6 577 else if (af == AF_INET6) { 578 if (!silent) 579 (void)printf("%s", ip6addr_string(bp)); 580 } 581 #endif 582 return hdrlen + len; 583 case pimv2_group: 584 case pimv2_source: 585 TCHECK2(bp[0], len + 2); 586 if (af == AF_INET) { 587 if (!silent) { 588 (void)printf("%s", ipaddr_string(bp + 2)); 589 if (bp[1] != 32) 590 (void)printf("/%u", bp[1]); 591 } 592 } 593 #ifdef INET6 594 else if (af == AF_INET6) { 595 if (!silent) { 596 (void)printf("%s", ip6addr_string(bp + 2)); 597 if (bp[1] != 128) 598 (void)printf("/%u", bp[1]); 599 } 600 } 601 #endif 602 if (bp[0] && !silent) { 603 if (at == pimv2_group) { 604 (void)printf("(0x%02x)", bp[0]); 605 } else { 606 (void)printf("(%s%s%s", 607 bp[0] & 0x04 ? "S" : "", 608 bp[0] & 0x02 ? "W" : "", 609 bp[0] & 0x01 ? "R" : ""); 610 if (bp[0] & 0xf8) { 611 (void) printf("+0x%02x", bp[0] & 0xf8); 612 } 613 (void)printf(")"); 614 } 615 } 616 return hdrlen + 2 + len; 617 default: 618 return -1; 619 } 620 trunc: 621 return -1; 622 } 623 624 static void 625 pimv2_print(register const u_char *bp, register u_int len, u_int cksum) 626 { 627 register const u_char *ep; 628 register struct pim *pim = (struct pim *)bp; 629 int advance; 630 631 ep = (const u_char *)snapend; 632 if (bp >= ep) 633 return; 634 if (ep > bp + len) 635 ep = bp + len; 636 TCHECK(pim->pim_rsv); 637 pimv2_addr_len = pim->pim_rsv; 638 if (pimv2_addr_len != 0) 639 (void)printf(", RFC2117-encoding"); 640 641 printf(", cksum 0x%04x ", EXTRACT_16BITS(&pim->pim_cksum)); 642 if (EXTRACT_16BITS(&pim->pim_cksum) == 0) { 643 printf("(unverified)"); 644 } else { 645 printf("(%scorrect)", TTEST2(bp[0], len) && cksum ? "in" : "" ); 646 } 647 648 switch (PIM_TYPE(pim->pim_typever)) { 649 case PIMV2_TYPE_HELLO: 650 { 651 u_int16_t otype, olen; 652 bp += 4; 653 while (bp < ep) { 654 TCHECK2(bp[0], 4); 655 otype = EXTRACT_16BITS(&bp[0]); 656 olen = EXTRACT_16BITS(&bp[2]); 657 TCHECK2(bp[0], 4 + olen); 658 659 printf("\n\t %s Option (%u), length %u, Value: ", 660 tok2str( pimv2_hello_option_values,"Unknown",otype), 661 otype, 662 olen); 663 bp += 4; 664 665 switch (otype) { 666 case PIMV2_HELLO_OPTION_HOLDTIME: 667 relts_print(EXTRACT_16BITS(bp)); 668 break; 669 670 case PIMV2_HELLO_OPTION_LANPRUNEDELAY: 671 if (olen != 4) { 672 (void)printf("ERROR: Option Length != 4 Bytes (%u)", olen); 673 } else { 674 char t_bit; 675 u_int16_t lan_delay, override_interval; 676 lan_delay = EXTRACT_16BITS(bp); 677 override_interval = EXTRACT_16BITS(bp+2); 678 t_bit = (lan_delay & 0x8000)? 1 : 0; 679 lan_delay &= ~0x8000; 680 (void)printf("\n\t T-bit=%d, LAN delay %dms, Override interval %dms", 681 t_bit, lan_delay, override_interval); 682 } 683 break; 684 685 case PIMV2_HELLO_OPTION_DR_PRIORITY_OLD: 686 case PIMV2_HELLO_OPTION_DR_PRIORITY: 687 switch (olen) { 688 case 0: 689 printf("Bi-Directional Capability (Old)"); 690 break; 691 case 4: 692 printf("%u", EXTRACT_32BITS(bp)); 693 break; 694 default: 695 printf("ERROR: Option Length != 4 Bytes (%u)", olen); 696 break; 697 } 698 break; 699 700 case PIMV2_HELLO_OPTION_GENID: 701 (void)printf("0x%08x", EXTRACT_32BITS(bp)); 702 break; 703 704 case PIMV2_HELLO_OPTION_REFRESH_CAP: 705 (void)printf("v%d", *bp); 706 if (*(bp+1) != 0) { 707 (void)printf(", interval "); 708 relts_print(*(bp+1)); 709 } 710 if (EXTRACT_16BITS(bp+2) != 0) { 711 (void)printf(" ?0x%04x?", EXTRACT_16BITS(bp+2)); 712 } 713 break; 714 715 case PIMV2_HELLO_OPTION_BIDIR_CAP: 716 break; 717 718 case PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD: 719 case PIMV2_HELLO_OPTION_ADDRESS_LIST: 720 if (vflag > 1) { 721 const u_char *ptr = bp; 722 while (ptr < (bp+olen)) { 723 int advance; 724 725 printf("\n\t "); 726 advance = pimv2_addr_print(ptr, pimv2_unicast, 0); 727 if (advance < 0) { 728 printf("..."); 729 break; 730 } 731 ptr += advance; 732 } 733 } 734 break; 735 default: 736 if (vflag <= 1) 737 print_unknown_data(bp,"\n\t ",olen); 738 break; 739 } 740 /* do we want to see an additionally hexdump ? */ 741 if (vflag> 1) 742 print_unknown_data(bp,"\n\t ",olen); 743 bp += olen; 744 } 745 break; 746 } 747 748 case PIMV2_TYPE_REGISTER: 749 { 750 struct ip *ip; 751 752 if (!TTEST2(*(bp+4), PIMV2_REGISTER_FLAG_LEN)) 753 goto trunc; 754 755 printf(", Flags [ %s ]\n\t", 756 tok2str(pimv2_register_flag_values, 757 "none", 758 EXTRACT_32BITS(bp+4))); 759 760 bp += 8; len -= 8; 761 /* encapsulated multicast packet */ 762 ip = (struct ip *)bp; 763 switch (IP_V(ip)) { 764 case 0: /* Null header */ 765 (void)printf("IP-Null-header %s > %s", 766 ipaddr_string(&ip->ip_src), 767 ipaddr_string(&ip->ip_dst)); 768 break; 769 770 case 4: /* IPv4 */ 771 ip_print(gndo, bp, len); 772 break; 773 #ifdef INET6 774 case 6: /* IPv6 */ 775 ip6_print(gndo, bp, len); 776 break; 777 #endif 778 default: 779 (void)printf("IP ver %d", IP_V(ip)); 780 break; 781 } 782 break; 783 } 784 785 case PIMV2_TYPE_REGISTER_STOP: 786 bp += 4; len -= 4; 787 if (bp >= ep) 788 break; 789 (void)printf(" group="); 790 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 791 (void)printf("..."); 792 break; 793 } 794 bp += advance; len -= advance; 795 if (bp >= ep) 796 break; 797 (void)printf(" source="); 798 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 799 (void)printf("..."); 800 break; 801 } 802 bp += advance; len -= advance; 803 break; 804 805 case PIMV2_TYPE_JOIN_PRUNE: 806 case PIMV2_TYPE_GRAFT: 807 case PIMV2_TYPE_GRAFT_ACK: 808 809 810 /* 811 * 0 1 2 3 812 * 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 813 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 814 * |PIM Ver| Type | Addr length | Checksum | 815 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 816 * | Unicast-Upstream Neighbor Address | 817 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 818 * | Reserved | Num groups | Holdtime | 819 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 820 * | Encoded-Multicast Group Address-1 | 821 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 822 * | Number of Joined Sources | Number of Pruned Sources | 823 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 824 * | Encoded-Joined Source Address-1 | 825 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 826 * | . | 827 * | . | 828 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 829 * | Encoded-Joined Source Address-n | 830 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 831 * | Encoded-Pruned Source Address-1 | 832 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 833 * | . | 834 * | . | 835 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 836 * | Encoded-Pruned Source Address-n | 837 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 838 * | . | 839 * | . | 840 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 841 * | Encoded-Multicast Group Address-n | 842 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 843 */ 844 845 { 846 u_int8_t ngroup; 847 u_int16_t holdtime; 848 u_int16_t njoin; 849 u_int16_t nprune; 850 int i, j; 851 852 bp += 4; len -= 4; 853 if (PIM_TYPE(pim->pim_typever) != 7) { /*not for Graft-ACK*/ 854 if (bp >= ep) 855 break; 856 (void)printf(", upstream-neighbor: "); 857 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 858 (void)printf("..."); 859 break; 860 } 861 bp += advance; len -= advance; 862 } 863 if (bp + 4 > ep) 864 break; 865 ngroup = bp[1]; 866 holdtime = EXTRACT_16BITS(&bp[2]); 867 (void)printf("\n\t %u group(s)", ngroup); 868 if (PIM_TYPE(pim->pim_typever) != 7) { /*not for Graft-ACK*/ 869 (void)printf(", holdtime: "); 870 if (holdtime == 0xffff) 871 (void)printf("infinite"); 872 else 873 relts_print(holdtime); 874 } 875 bp += 4; len -= 4; 876 for (i = 0; i < ngroup; i++) { 877 if (bp >= ep) 878 goto jp_done; 879 (void)printf("\n\t group #%u: ", i+1); 880 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 881 (void)printf("...)"); 882 goto jp_done; 883 } 884 bp += advance; len -= advance; 885 if (bp + 4 > ep) { 886 (void)printf("...)"); 887 goto jp_done; 888 } 889 njoin = EXTRACT_16BITS(&bp[0]); 890 nprune = EXTRACT_16BITS(&bp[2]); 891 (void)printf(", joined sources: %u, pruned sources: %u", njoin,nprune); 892 bp += 4; len -= 4; 893 for (j = 0; j < njoin; j++) { 894 (void)printf("\n\t joined source #%u: ",j+1); 895 if ((advance = pimv2_addr_print(bp, pimv2_source, 0)) < 0) { 896 (void)printf("...)"); 897 goto jp_done; 898 } 899 bp += advance; len -= advance; 900 } 901 for (j = 0; j < nprune; j++) { 902 (void)printf("\n\t pruned source #%u: ",j+1); 903 if ((advance = pimv2_addr_print(bp, pimv2_source, 0)) < 0) { 904 (void)printf("...)"); 905 goto jp_done; 906 } 907 bp += advance; len -= advance; 908 } 909 } 910 jp_done: 911 break; 912 } 913 914 case PIMV2_TYPE_BOOTSTRAP: 915 { 916 int i, j, frpcnt; 917 bp += 4; 918 919 /* Fragment Tag, Hash Mask len, and BSR-priority */ 920 if (bp + sizeof(u_int16_t) >= ep) break; 921 (void)printf(" tag=%x", EXTRACT_16BITS(bp)); 922 bp += sizeof(u_int16_t); 923 if (bp >= ep) break; 924 (void)printf(" hashmlen=%d", bp[0]); 925 if (bp + 1 >= ep) break; 926 (void)printf(" BSRprio=%d", bp[1]); 927 bp += 2; 928 929 /* Encoded-Unicast-BSR-Address */ 930 if (bp >= ep) break; 931 (void)printf(" BSR="); 932 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 933 (void)printf("..."); 934 break; 935 } 936 bp += advance; 937 938 for (i = 0; bp < ep; i++) { 939 /* Encoded-Group Address */ 940 (void)printf(" (group%d: ", i); 941 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) 942 < 0) { 943 (void)printf("...)"); 944 goto bs_done; 945 } 946 bp += advance; 947 948 /* RP-Count, Frag RP-Cnt, and rsvd */ 949 if (bp >= ep) { 950 (void)printf("...)"); 951 goto bs_done; 952 } 953 (void)printf(" RPcnt=%d", bp[0]); 954 if (bp + 1 >= ep) { 955 (void)printf("...)"); 956 goto bs_done; 957 } 958 (void)printf(" FRPcnt=%d", frpcnt = bp[1]); 959 bp += 4; 960 961 for (j = 0; j < frpcnt && bp < ep; j++) { 962 /* each RP info */ 963 (void)printf(" RP%d=", j); 964 if ((advance = pimv2_addr_print(bp, 965 pimv2_unicast, 966 0)) < 0) { 967 (void)printf("...)"); 968 goto bs_done; 969 } 970 bp += advance; 971 972 if (bp + 1 >= ep) { 973 (void)printf("...)"); 974 goto bs_done; 975 } 976 (void)printf(",holdtime="); 977 relts_print(EXTRACT_16BITS(bp)); 978 if (bp + 2 >= ep) { 979 (void)printf("...)"); 980 goto bs_done; 981 } 982 (void)printf(",prio=%d", bp[2]); 983 bp += 4; 984 } 985 (void)printf(")"); 986 } 987 bs_done: 988 break; 989 } 990 case PIMV2_TYPE_ASSERT: 991 bp += 4; len -= 4; 992 if (bp >= ep) 993 break; 994 (void)printf(" group="); 995 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 996 (void)printf("..."); 997 break; 998 } 999 bp += advance; len -= advance; 1000 if (bp >= ep) 1001 break; 1002 (void)printf(" src="); 1003 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 1004 (void)printf("..."); 1005 break; 1006 } 1007 bp += advance; len -= advance; 1008 if (bp + 8 > ep) 1009 break; 1010 if (bp[0] & 0x80) 1011 (void)printf(" RPT"); 1012 (void)printf(" pref=%u", EXTRACT_32BITS(&bp[0]) & 0x7fffffff); 1013 (void)printf(" metric=%u", EXTRACT_32BITS(&bp[4])); 1014 break; 1015 1016 case PIMV2_TYPE_CANDIDATE_RP: 1017 { 1018 int i, pfxcnt; 1019 bp += 4; 1020 1021 /* Prefix-Cnt, Priority, and Holdtime */ 1022 if (bp >= ep) break; 1023 (void)printf(" prefix-cnt=%d", bp[0]); 1024 pfxcnt = bp[0]; 1025 if (bp + 1 >= ep) break; 1026 (void)printf(" prio=%d", bp[1]); 1027 if (bp + 3 >= ep) break; 1028 (void)printf(" holdtime="); 1029 relts_print(EXTRACT_16BITS(&bp[2])); 1030 bp += 4; 1031 1032 /* Encoded-Unicast-RP-Address */ 1033 if (bp >= ep) break; 1034 (void)printf(" RP="); 1035 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 1036 (void)printf("..."); 1037 break; 1038 } 1039 bp += advance; 1040 1041 /* Encoded-Group Addresses */ 1042 for (i = 0; i < pfxcnt && bp < ep; i++) { 1043 (void)printf(" Group%d=", i); 1044 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) 1045 < 0) { 1046 (void)printf("..."); 1047 break; 1048 } 1049 bp += advance; 1050 } 1051 break; 1052 } 1053 1054 case PIMV2_TYPE_PRUNE_REFRESH: 1055 (void)printf(" src="); 1056 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 1057 (void)printf("..."); 1058 break; 1059 } 1060 bp += advance; 1061 (void)printf(" grp="); 1062 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) { 1063 (void)printf("..."); 1064 break; 1065 } 1066 bp += advance; 1067 (void)printf(" forwarder="); 1068 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) { 1069 (void)printf("..."); 1070 break; 1071 } 1072 bp += advance; 1073 TCHECK2(bp[0], 2); 1074 (void)printf(" TUNR "); 1075 relts_print(EXTRACT_16BITS(bp)); 1076 break; 1077 1078 1079 default: 1080 (void)printf(" [type %d]", PIM_TYPE(pim->pim_typever)); 1081 break; 1082 } 1083 1084 return; 1085 1086 trunc: 1087 (void)printf("[|pim]"); 1088 } 1089 1090 /* 1091 * Local Variables: 1092 * c-style: whitesmith 1093 * c-basic-offset: 8 1094 * End: 1095 */ 1096