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