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