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