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