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.4 2006/02/13 01:32: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 #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); 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) 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); 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) 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)", 644 TTEST2(bp[0], len) && 645 in_cksum((const u_short*)bp, len, 0) ? "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 Lenght != 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 Lenght != 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(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