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