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