1 /* 2 * Redistribution and use in source and binary forms, with or without 3 * modification, are permitted provided that: (1) source code 4 * distributions retain the above copyright notice and this paragraph 5 * in its entirety, and (2) distributions including binary code include 6 * the above copyright notice and this paragraph in its entirety in 7 * the documentation or other materials provided with the distribution. 8 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 9 * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT 10 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 11 * FOR A PARTICULAR PURPOSE. 12 * 13 * Original code by Andy Heffernan (ahh@juniper.net) 14 */ 15 16 /* \summary: Pragmatic General Multicast (PGM) printer */ 17 18 #ifdef HAVE_CONFIG_H 19 #include <config.h> 20 #endif 21 22 #include "netdissect-stdinc.h" 23 24 #include "netdissect.h" 25 #include "extract.h" 26 #include "addrtoname.h" 27 #include "addrtostr.h" 28 29 #include "ip.h" 30 #include "ip6.h" 31 #include "ipproto.h" 32 #include "af.h" 33 34 /* 35 * PGM header (RFC 3208) 36 */ 37 struct pgm_header { 38 nd_uint16_t pgm_sport; 39 nd_uint16_t pgm_dport; 40 nd_uint8_t pgm_type; 41 nd_uint8_t pgm_options; 42 nd_uint16_t pgm_sum; 43 nd_byte pgm_gsid[6]; 44 nd_uint16_t pgm_length; 45 }; 46 47 struct pgm_spm { 48 nd_uint32_t pgms_seq; 49 nd_uint32_t pgms_trailseq; 50 nd_uint32_t pgms_leadseq; 51 nd_uint16_t pgms_nla_afi; 52 nd_uint16_t pgms_reserved; 53 /* ... uint8_t pgms_nla[0]; */ 54 /* ... options */ 55 }; 56 57 struct pgm_nak { 58 nd_uint32_t pgmn_seq; 59 nd_uint16_t pgmn_source_afi; 60 nd_uint16_t pgmn_reserved; 61 /* ... uint8_t pgmn_source[0]; */ 62 /* ... uint16_t pgmn_group_afi */ 63 /* ... uint16_t pgmn_reserved2; */ 64 /* ... uint8_t pgmn_group[0]; */ 65 /* ... options */ 66 }; 67 68 struct pgm_ack { 69 nd_uint32_t pgma_rx_max_seq; 70 nd_uint32_t pgma_bitmap; 71 /* ... options */ 72 }; 73 74 struct pgm_poll { 75 nd_uint32_t pgmp_seq; 76 nd_uint16_t pgmp_round; 77 nd_uint16_t pgmp_subtype; 78 nd_uint16_t pgmp_nla_afi; 79 nd_uint16_t pgmp_reserved; 80 /* ... uint8_t pgmp_nla[0]; */ 81 /* ... options */ 82 }; 83 84 struct pgm_polr { 85 nd_uint32_t pgmp_seq; 86 nd_uint16_t pgmp_round; 87 nd_uint16_t pgmp_reserved; 88 /* ... options */ 89 }; 90 91 struct pgm_data { 92 nd_uint32_t pgmd_seq; 93 nd_uint32_t pgmd_trailseq; 94 /* ... options */ 95 }; 96 97 typedef enum _pgm_type { 98 PGM_SPM = 0, /* source path message */ 99 PGM_POLL = 1, /* POLL Request */ 100 PGM_POLR = 2, /* POLL Response */ 101 PGM_ODATA = 4, /* original data */ 102 PGM_RDATA = 5, /* repair data */ 103 PGM_NAK = 8, /* NAK */ 104 PGM_NULLNAK = 9, /* Null NAK */ 105 PGM_NCF = 10, /* NAK Confirmation */ 106 PGM_ACK = 11, /* ACK for congestion control */ 107 PGM_SPMR = 12, /* SPM request */ 108 PGM_MAX = 255 109 } pgm_type; 110 111 #define PGM_OPT_BIT_PRESENT 0x01 112 #define PGM_OPT_BIT_NETWORK 0x02 113 #define PGM_OPT_BIT_VAR_PKTLEN 0x40 114 #define PGM_OPT_BIT_PARITY 0x80 115 116 #define PGM_OPT_LENGTH 0x00 117 #define PGM_OPT_FRAGMENT 0x01 118 #define PGM_OPT_NAK_LIST 0x02 119 #define PGM_OPT_JOIN 0x03 120 #define PGM_OPT_NAK_BO_IVL 0x04 121 #define PGM_OPT_NAK_BO_RNG 0x05 122 123 #define PGM_OPT_REDIRECT 0x07 124 #define PGM_OPT_PARITY_PRM 0x08 125 #define PGM_OPT_PARITY_GRP 0x09 126 #define PGM_OPT_CURR_TGSIZE 0x0A 127 #define PGM_OPT_NBR_UNREACH 0x0B 128 #define PGM_OPT_PATH_NLA 0x0C 129 130 #define PGM_OPT_SYN 0x0D 131 #define PGM_OPT_FIN 0x0E 132 #define PGM_OPT_RST 0x0F 133 #define PGM_OPT_CR 0x10 134 #define PGM_OPT_CRQST 0x11 135 136 #define PGM_OPT_PGMCC_DATA 0x12 137 #define PGM_OPT_PGMCC_FEEDBACK 0x13 138 139 #define PGM_OPT_MASK 0x7f 140 141 #define PGM_OPT_END 0x80 /* end of options marker */ 142 143 #define PGM_MIN_OPT_LEN 4 144 145 void 146 pgm_print(netdissect_options *ndo, 147 const u_char *bp, u_int length, 148 const u_char *bp2) 149 { 150 const struct pgm_header *pgm; 151 const struct ip *ip; 152 uint8_t pgm_type_val; 153 uint16_t sport, dport; 154 u_int nla_afnum; 155 char nla_buf[INET6_ADDRSTRLEN]; 156 const struct ip6_hdr *ip6; 157 uint8_t opt_type, opt_len; 158 uint32_t seq, opts_len, len, offset; 159 160 ndo->ndo_protocol = "pgm"; 161 pgm = (const struct pgm_header *)bp; 162 ip = (const struct ip *)bp2; 163 if (IP_V(ip) == 6) 164 ip6 = (const struct ip6_hdr *)bp2; 165 else 166 ip6 = NULL; 167 if (!ND_TTEST_2(pgm->pgm_dport)) { 168 if (ip6) { 169 ND_PRINT("%s > %s:", 170 GET_IP6ADDR_STRING(ip6->ip6_src), 171 GET_IP6ADDR_STRING(ip6->ip6_dst)); 172 } else { 173 ND_PRINT("%s > %s:", 174 GET_IPADDR_STRING(ip->ip_src), 175 GET_IPADDR_STRING(ip->ip_dst)); 176 } 177 nd_print_trunc(ndo); 178 return; 179 } 180 181 sport = GET_BE_U_2(pgm->pgm_sport); 182 dport = GET_BE_U_2(pgm->pgm_dport); 183 184 if (ip6) { 185 if (GET_U_1(ip6->ip6_nxt) == IPPROTO_PGM) { 186 ND_PRINT("%s.%s > %s.%s: ", 187 GET_IP6ADDR_STRING(ip6->ip6_src), 188 tcpport_string(ndo, sport), 189 GET_IP6ADDR_STRING(ip6->ip6_dst), 190 tcpport_string(ndo, dport)); 191 } else { 192 ND_PRINT("%s > %s: ", 193 tcpport_string(ndo, sport), tcpport_string(ndo, dport)); 194 } 195 } else { 196 if (GET_U_1(ip->ip_p) == IPPROTO_PGM) { 197 ND_PRINT("%s.%s > %s.%s: ", 198 GET_IPADDR_STRING(ip->ip_src), 199 tcpport_string(ndo, sport), 200 GET_IPADDR_STRING(ip->ip_dst), 201 tcpport_string(ndo, dport)); 202 } else { 203 ND_PRINT("%s > %s: ", 204 tcpport_string(ndo, sport), tcpport_string(ndo, dport)); 205 } 206 } 207 208 ND_TCHECK_SIZE(pgm); 209 210 ND_PRINT("PGM, length %u", GET_BE_U_2(pgm->pgm_length)); 211 212 if (!ndo->ndo_vflag) 213 return; 214 215 pgm_type_val = GET_U_1(pgm->pgm_type); 216 ND_PRINT(" 0x%02x%02x%02x%02x%02x%02x ", 217 pgm->pgm_gsid[0], 218 pgm->pgm_gsid[1], 219 pgm->pgm_gsid[2], 220 pgm->pgm_gsid[3], 221 pgm->pgm_gsid[4], 222 pgm->pgm_gsid[5]); 223 switch (pgm_type_val) { 224 case PGM_SPM: { 225 const struct pgm_spm *spm; 226 227 spm = (const struct pgm_spm *)(pgm + 1); 228 ND_TCHECK_SIZE(spm); 229 bp = (const u_char *) (spm + 1); 230 231 switch (GET_BE_U_2(spm->pgms_nla_afi)) { 232 case AFNUM_INET: 233 ND_TCHECK_LEN(bp, sizeof(nd_ipv4)); 234 addrtostr(bp, nla_buf, sizeof(nla_buf)); 235 bp += sizeof(nd_ipv4); 236 break; 237 case AFNUM_INET6: 238 ND_TCHECK_LEN(bp, sizeof(nd_ipv6)); 239 addrtostr6(bp, nla_buf, sizeof(nla_buf)); 240 bp += sizeof(nd_ipv6); 241 break; 242 default: 243 goto trunc; 244 break; 245 } 246 247 ND_PRINT("SPM seq %u trail %u lead %u nla %s", 248 GET_BE_U_4(spm->pgms_seq), 249 GET_BE_U_4(spm->pgms_trailseq), 250 GET_BE_U_4(spm->pgms_leadseq), 251 nla_buf); 252 break; 253 } 254 255 case PGM_POLL: { 256 const struct pgm_poll *pgm_poll; 257 uint32_t ivl, rnd, mask; 258 259 pgm_poll = (const struct pgm_poll *)(pgm + 1); 260 ND_TCHECK_SIZE(pgm_poll); 261 bp = (const u_char *) (pgm_poll + 1); 262 263 switch (GET_BE_U_2(pgm_poll->pgmp_nla_afi)) { 264 case AFNUM_INET: 265 ND_TCHECK_LEN(bp, sizeof(nd_ipv4)); 266 addrtostr(bp, nla_buf, sizeof(nla_buf)); 267 bp += sizeof(nd_ipv4); 268 break; 269 case AFNUM_INET6: 270 ND_TCHECK_LEN(bp, sizeof(nd_ipv6)); 271 addrtostr6(bp, nla_buf, sizeof(nla_buf)); 272 bp += sizeof(nd_ipv6); 273 break; 274 default: 275 goto trunc; 276 break; 277 } 278 279 ivl = GET_BE_U_4(bp); 280 bp += sizeof(uint32_t); 281 282 rnd = GET_BE_U_4(bp); 283 bp += sizeof(uint32_t); 284 285 mask = GET_BE_U_4(bp); 286 bp += sizeof(uint32_t); 287 288 ND_PRINT("POLL seq %u round %u nla %s ivl %u rnd 0x%08x " 289 "mask 0x%08x", GET_BE_U_4(pgm_poll->pgmp_seq), 290 GET_BE_U_2(pgm_poll->pgmp_round), nla_buf, ivl, rnd, 291 mask); 292 break; 293 } 294 case PGM_POLR: { 295 const struct pgm_polr *polr_msg; 296 297 polr_msg = (const struct pgm_polr *)(pgm + 1); 298 ND_TCHECK_SIZE(polr_msg); 299 ND_PRINT("POLR seq %u round %u", 300 GET_BE_U_4(polr_msg->pgmp_seq), 301 GET_BE_U_2(polr_msg->pgmp_round)); 302 bp = (const u_char *) (polr_msg + 1); 303 break; 304 } 305 case PGM_ODATA: { 306 const struct pgm_data *odata; 307 308 odata = (const struct pgm_data *)(pgm + 1); 309 ND_TCHECK_SIZE(odata); 310 ND_PRINT("ODATA trail %u seq %u", 311 GET_BE_U_4(odata->pgmd_trailseq), 312 GET_BE_U_4(odata->pgmd_seq)); 313 bp = (const u_char *) (odata + 1); 314 break; 315 } 316 317 case PGM_RDATA: { 318 const struct pgm_data *rdata; 319 320 rdata = (const struct pgm_data *)(pgm + 1); 321 ND_TCHECK_SIZE(rdata); 322 ND_PRINT("RDATA trail %u seq %u", 323 GET_BE_U_4(rdata->pgmd_trailseq), 324 GET_BE_U_4(rdata->pgmd_seq)); 325 bp = (const u_char *) (rdata + 1); 326 break; 327 } 328 329 case PGM_NAK: 330 case PGM_NULLNAK: 331 case PGM_NCF: { 332 const struct pgm_nak *nak; 333 char source_buf[INET6_ADDRSTRLEN], group_buf[INET6_ADDRSTRLEN]; 334 335 nak = (const struct pgm_nak *)(pgm + 1); 336 ND_TCHECK_SIZE(nak); 337 bp = (const u_char *) (nak + 1); 338 339 /* 340 * Skip past the source, saving info along the way 341 * and stopping if we don't have enough. 342 */ 343 switch (GET_BE_U_2(nak->pgmn_source_afi)) { 344 case AFNUM_INET: 345 ND_TCHECK_LEN(bp, sizeof(nd_ipv4)); 346 addrtostr(bp, source_buf, sizeof(source_buf)); 347 bp += sizeof(nd_ipv4); 348 break; 349 case AFNUM_INET6: 350 ND_TCHECK_LEN(bp, sizeof(nd_ipv6)); 351 addrtostr6(bp, source_buf, sizeof(source_buf)); 352 bp += sizeof(nd_ipv6); 353 break; 354 default: 355 goto trunc; 356 break; 357 } 358 359 /* 360 * Skip past the group, saving info along the way 361 * and stopping if we don't have enough. 362 */ 363 bp += (2 * sizeof(uint16_t)); 364 switch (GET_BE_U_2(bp)) { 365 case AFNUM_INET: 366 ND_TCHECK_LEN(bp, sizeof(nd_ipv4)); 367 addrtostr(bp, group_buf, sizeof(group_buf)); 368 bp += sizeof(nd_ipv4); 369 break; 370 case AFNUM_INET6: 371 ND_TCHECK_LEN(bp, sizeof(nd_ipv6)); 372 addrtostr6(bp, group_buf, sizeof(group_buf)); 373 bp += sizeof(nd_ipv6); 374 break; 375 default: 376 goto trunc; 377 break; 378 } 379 380 /* 381 * Options decoding can go here. 382 */ 383 switch (pgm_type_val) { 384 case PGM_NAK: 385 ND_PRINT("NAK "); 386 break; 387 case PGM_NULLNAK: 388 ND_PRINT("NNAK "); 389 break; 390 case PGM_NCF: 391 ND_PRINT("NCF "); 392 break; 393 default: 394 break; 395 } 396 ND_PRINT("(%s -> %s), seq %u", 397 source_buf, group_buf, GET_BE_U_4(nak->pgmn_seq)); 398 break; 399 } 400 401 case PGM_ACK: { 402 const struct pgm_ack *ack; 403 404 ack = (const struct pgm_ack *)(pgm + 1); 405 ND_TCHECK_SIZE(ack); 406 ND_PRINT("ACK seq %u", 407 GET_BE_U_4(ack->pgma_rx_max_seq)); 408 bp = (const u_char *) (ack + 1); 409 break; 410 } 411 412 case PGM_SPMR: 413 ND_PRINT("SPMR"); 414 break; 415 416 default: 417 ND_PRINT("UNKNOWN type 0x%02x", pgm_type_val); 418 break; 419 420 } 421 if (GET_U_1(pgm->pgm_options) & PGM_OPT_BIT_PRESENT) { 422 423 /* 424 * make sure there's enough for the first option header 425 */ 426 ND_TCHECK_LEN(bp, PGM_MIN_OPT_LEN); 427 428 /* 429 * That option header MUST be an OPT_LENGTH option 430 * (see the first paragraph of section 9.1 in RFC 3208). 431 */ 432 opt_type = GET_U_1(bp); 433 bp++; 434 if ((opt_type & PGM_OPT_MASK) != PGM_OPT_LENGTH) { 435 ND_PRINT("[First option bad, should be PGM_OPT_LENGTH, is %u]", opt_type & PGM_OPT_MASK); 436 return; 437 } 438 opt_len = GET_U_1(bp); 439 bp++; 440 if (opt_len != 4) { 441 ND_PRINT("[Bad OPT_LENGTH option, length %u != 4]", opt_len); 442 return; 443 } 444 opts_len = GET_BE_U_2(bp); 445 bp += sizeof(uint16_t); 446 if (opts_len < 4) { 447 ND_PRINT("[Bad total option length %u < 4]", opts_len); 448 return; 449 } 450 ND_PRINT(" OPTS LEN %u", opts_len); 451 opts_len -= 4; 452 453 while (opts_len) { 454 if (opts_len < PGM_MIN_OPT_LEN) { 455 ND_PRINT("[Total option length leaves no room for final option]"); 456 return; 457 } 458 opt_type = GET_U_1(bp); 459 bp++; 460 opt_len = GET_U_1(bp); 461 bp++; 462 if (opt_len < PGM_MIN_OPT_LEN) { 463 ND_PRINT("[Bad option, length %u < %u]", opt_len, 464 PGM_MIN_OPT_LEN); 465 break; 466 } 467 if (opts_len < opt_len) { 468 ND_PRINT("[Total option length leaves no room for final option]"); 469 return; 470 } 471 ND_TCHECK_LEN(bp, opt_len - 2); 472 473 switch (opt_type & PGM_OPT_MASK) { 474 case PGM_OPT_LENGTH: 475 #define PGM_OPT_LENGTH_LEN (2+2) 476 if (opt_len != PGM_OPT_LENGTH_LEN) { 477 ND_PRINT("[Bad OPT_LENGTH option, length %u != %u]", 478 opt_len, PGM_OPT_LENGTH_LEN); 479 return; 480 } 481 ND_PRINT(" OPTS LEN (extra?) %u", GET_BE_U_2(bp)); 482 bp += 2; 483 opts_len -= PGM_OPT_LENGTH_LEN; 484 break; 485 486 case PGM_OPT_FRAGMENT: 487 #define PGM_OPT_FRAGMENT_LEN (2+2+4+4+4) 488 if (opt_len != PGM_OPT_FRAGMENT_LEN) { 489 ND_PRINT("[Bad OPT_FRAGMENT option, length %u != %u]", 490 opt_len, PGM_OPT_FRAGMENT_LEN); 491 return; 492 } 493 bp += 2; 494 seq = GET_BE_U_4(bp); 495 bp += 4; 496 offset = GET_BE_U_4(bp); 497 bp += 4; 498 len = GET_BE_U_4(bp); 499 bp += 4; 500 ND_PRINT(" FRAG seq %u off %u len %u", seq, offset, len); 501 opts_len -= PGM_OPT_FRAGMENT_LEN; 502 break; 503 504 case PGM_OPT_NAK_LIST: 505 bp += 2; 506 opt_len -= 4; /* option header */ 507 ND_PRINT(" NAK LIST"); 508 while (opt_len) { 509 if (opt_len < 4) { 510 ND_PRINT("[Option length not a multiple of 4]"); 511 return; 512 } 513 ND_PRINT(" %u", GET_BE_U_4(bp)); 514 bp += 4; 515 opt_len -= 4; 516 opts_len -= 4; 517 } 518 break; 519 520 case PGM_OPT_JOIN: 521 #define PGM_OPT_JOIN_LEN (2+2+4) 522 if (opt_len != PGM_OPT_JOIN_LEN) { 523 ND_PRINT("[Bad OPT_JOIN option, length %u != %u]", 524 opt_len, PGM_OPT_JOIN_LEN); 525 return; 526 } 527 bp += 2; 528 seq = GET_BE_U_4(bp); 529 bp += 4; 530 ND_PRINT(" JOIN %u", seq); 531 opts_len -= PGM_OPT_JOIN_LEN; 532 break; 533 534 case PGM_OPT_NAK_BO_IVL: 535 #define PGM_OPT_NAK_BO_IVL_LEN (2+2+4+4) 536 if (opt_len != PGM_OPT_NAK_BO_IVL_LEN) { 537 ND_PRINT("[Bad OPT_NAK_BO_IVL option, length %u != %u]", 538 opt_len, PGM_OPT_NAK_BO_IVL_LEN); 539 return; 540 } 541 bp += 2; 542 offset = GET_BE_U_4(bp); 543 bp += 4; 544 seq = GET_BE_U_4(bp); 545 bp += 4; 546 ND_PRINT(" BACKOFF ivl %u ivlseq %u", offset, seq); 547 opts_len -= PGM_OPT_NAK_BO_IVL_LEN; 548 break; 549 550 case PGM_OPT_NAK_BO_RNG: 551 #define PGM_OPT_NAK_BO_RNG_LEN (2+2+4+4) 552 if (opt_len != PGM_OPT_NAK_BO_RNG_LEN) { 553 ND_PRINT("[Bad OPT_NAK_BO_RNG option, length %u != %u]", 554 opt_len, PGM_OPT_NAK_BO_RNG_LEN); 555 return; 556 } 557 bp += 2; 558 offset = GET_BE_U_4(bp); 559 bp += 4; 560 seq = GET_BE_U_4(bp); 561 bp += 4; 562 ND_PRINT(" BACKOFF max %u min %u", offset, seq); 563 opts_len -= PGM_OPT_NAK_BO_RNG_LEN; 564 break; 565 566 case PGM_OPT_REDIRECT: 567 #define PGM_OPT_REDIRECT_FIXED_LEN (2+2+2+2) 568 if (opt_len < PGM_OPT_REDIRECT_FIXED_LEN) { 569 ND_PRINT("[Bad OPT_REDIRECT option, length %u < %u]", 570 opt_len, PGM_OPT_REDIRECT_FIXED_LEN); 571 return; 572 } 573 bp += 2; 574 nla_afnum = GET_BE_U_2(bp); 575 bp += 2+2; 576 switch (nla_afnum) { 577 case AFNUM_INET: 578 if (opt_len != PGM_OPT_REDIRECT_FIXED_LEN + sizeof(nd_ipv4)) { 579 ND_PRINT("[Bad OPT_REDIRECT option, length %u != %u + address size]", 580 opt_len, PGM_OPT_REDIRECT_FIXED_LEN); 581 return; 582 } 583 ND_TCHECK_LEN(bp, sizeof(nd_ipv4)); 584 addrtostr(bp, nla_buf, sizeof(nla_buf)); 585 bp += sizeof(nd_ipv4); 586 opts_len -= PGM_OPT_REDIRECT_FIXED_LEN + sizeof(nd_ipv4); 587 break; 588 case AFNUM_INET6: 589 if (opt_len != PGM_OPT_REDIRECT_FIXED_LEN + sizeof(nd_ipv6)) { 590 ND_PRINT("[Bad OPT_REDIRECT option, length %u != %u + address size]", 591 opt_len, PGM_OPT_REDIRECT_FIXED_LEN); 592 return; 593 } 594 ND_TCHECK_LEN(bp, sizeof(nd_ipv6)); 595 addrtostr6(bp, nla_buf, sizeof(nla_buf)); 596 bp += sizeof(nd_ipv6); 597 opts_len -= PGM_OPT_REDIRECT_FIXED_LEN + sizeof(nd_ipv6); 598 break; 599 default: 600 goto trunc; 601 break; 602 } 603 604 ND_PRINT(" REDIRECT %s", nla_buf); 605 break; 606 607 case PGM_OPT_PARITY_PRM: 608 #define PGM_OPT_PARITY_PRM_LEN (2+2+4) 609 if (opt_len != PGM_OPT_PARITY_PRM_LEN) { 610 ND_PRINT("[Bad OPT_PARITY_PRM option, length %u != %u]", 611 opt_len, PGM_OPT_PARITY_PRM_LEN); 612 return; 613 } 614 bp += 2; 615 len = GET_BE_U_4(bp); 616 bp += 4; 617 ND_PRINT(" PARITY MAXTGS %u", len); 618 opts_len -= PGM_OPT_PARITY_PRM_LEN; 619 break; 620 621 case PGM_OPT_PARITY_GRP: 622 #define PGM_OPT_PARITY_GRP_LEN (2+2+4) 623 if (opt_len != PGM_OPT_PARITY_GRP_LEN) { 624 ND_PRINT("[Bad OPT_PARITY_GRP option, length %u != %u]", 625 opt_len, PGM_OPT_PARITY_GRP_LEN); 626 return; 627 } 628 bp += 2; 629 seq = GET_BE_U_4(bp); 630 bp += 4; 631 ND_PRINT(" PARITY GROUP %u", seq); 632 opts_len -= PGM_OPT_PARITY_GRP_LEN; 633 break; 634 635 case PGM_OPT_CURR_TGSIZE: 636 #define PGM_OPT_CURR_TGSIZE_LEN (2+2+4) 637 if (opt_len != PGM_OPT_CURR_TGSIZE_LEN) { 638 ND_PRINT("[Bad OPT_CURR_TGSIZE option, length %u != %u]", 639 opt_len, PGM_OPT_CURR_TGSIZE_LEN); 640 return; 641 } 642 bp += 2; 643 len = GET_BE_U_4(bp); 644 bp += 4; 645 ND_PRINT(" PARITY ATGS %u", len); 646 opts_len -= PGM_OPT_CURR_TGSIZE_LEN; 647 break; 648 649 case PGM_OPT_NBR_UNREACH: 650 #define PGM_OPT_NBR_UNREACH_LEN (2+2) 651 if (opt_len != PGM_OPT_NBR_UNREACH_LEN) { 652 ND_PRINT("[Bad OPT_NBR_UNREACH option, length %u != %u]", 653 opt_len, PGM_OPT_NBR_UNREACH_LEN); 654 return; 655 } 656 bp += 2; 657 ND_PRINT(" NBR_UNREACH"); 658 opts_len -= PGM_OPT_NBR_UNREACH_LEN; 659 break; 660 661 case PGM_OPT_PATH_NLA: 662 ND_PRINT(" PATH_NLA [%u]", opt_len); 663 bp += opt_len; 664 opts_len -= opt_len; 665 break; 666 667 case PGM_OPT_SYN: 668 #define PGM_OPT_SYN_LEN (2+2) 669 if (opt_len != PGM_OPT_SYN_LEN) { 670 ND_PRINT("[Bad OPT_SYN option, length %u != %u]", 671 opt_len, PGM_OPT_SYN_LEN); 672 return; 673 } 674 bp += 2; 675 ND_PRINT(" SYN"); 676 opts_len -= PGM_OPT_SYN_LEN; 677 break; 678 679 case PGM_OPT_FIN: 680 #define PGM_OPT_FIN_LEN (2+2) 681 if (opt_len != PGM_OPT_FIN_LEN) { 682 ND_PRINT("[Bad OPT_FIN option, length %u != %u]", 683 opt_len, PGM_OPT_FIN_LEN); 684 return; 685 } 686 bp += 2; 687 ND_PRINT(" FIN"); 688 opts_len -= PGM_OPT_FIN_LEN; 689 break; 690 691 case PGM_OPT_RST: 692 #define PGM_OPT_RST_LEN (2+2) 693 if (opt_len != PGM_OPT_RST_LEN) { 694 ND_PRINT("[Bad OPT_RST option, length %u != %u]", 695 opt_len, PGM_OPT_RST_LEN); 696 return; 697 } 698 bp += 2; 699 ND_PRINT(" RST"); 700 opts_len -= PGM_OPT_RST_LEN; 701 break; 702 703 case PGM_OPT_CR: 704 ND_PRINT(" CR"); 705 bp += opt_len; 706 opts_len -= opt_len; 707 break; 708 709 case PGM_OPT_CRQST: 710 #define PGM_OPT_CRQST_LEN (2+2) 711 if (opt_len != PGM_OPT_CRQST_LEN) { 712 ND_PRINT("[Bad OPT_CRQST option, length %u != %u]", 713 opt_len, PGM_OPT_CRQST_LEN); 714 return; 715 } 716 bp += 2; 717 ND_PRINT(" CRQST"); 718 opts_len -= PGM_OPT_CRQST_LEN; 719 break; 720 721 case PGM_OPT_PGMCC_DATA: 722 #define PGM_OPT_PGMCC_DATA_FIXED_LEN (2+2+4+2+2) 723 if (opt_len < PGM_OPT_PGMCC_DATA_FIXED_LEN) { 724 ND_PRINT("[Bad OPT_PGMCC_DATA option, length %u < %u]", 725 opt_len, PGM_OPT_PGMCC_DATA_FIXED_LEN); 726 return; 727 } 728 bp += 2; 729 offset = GET_BE_U_4(bp); 730 bp += 4; 731 nla_afnum = GET_BE_U_2(bp); 732 bp += 2+2; 733 switch (nla_afnum) { 734 case AFNUM_INET: 735 if (opt_len != PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(nd_ipv4)) { 736 ND_PRINT("[Bad OPT_PGMCC_DATA option, length %u != %u + address size]", 737 opt_len, PGM_OPT_PGMCC_DATA_FIXED_LEN); 738 return; 739 } 740 ND_TCHECK_LEN(bp, sizeof(nd_ipv4)); 741 addrtostr(bp, nla_buf, sizeof(nla_buf)); 742 bp += sizeof(nd_ipv4); 743 opts_len -= PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(nd_ipv4); 744 break; 745 case AFNUM_INET6: 746 if (opt_len != PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(nd_ipv6)) { 747 ND_PRINT("[Bad OPT_PGMCC_DATA option, length %u != %u + address size]", 748 opt_len, PGM_OPT_PGMCC_DATA_FIXED_LEN); 749 return; 750 } 751 ND_TCHECK_LEN(bp, sizeof(nd_ipv6)); 752 addrtostr6(bp, nla_buf, sizeof(nla_buf)); 753 bp += sizeof(nd_ipv6); 754 opts_len -= PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(nd_ipv6); 755 break; 756 default: 757 goto trunc; 758 break; 759 } 760 761 ND_PRINT(" PGMCC DATA %u %s", offset, nla_buf); 762 break; 763 764 case PGM_OPT_PGMCC_FEEDBACK: 765 #define PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN (2+2+4+2+2) 766 if (opt_len < PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN) { 767 ND_PRINT("[Bad PGM_OPT_PGMCC_FEEDBACK option, length %u < %u]", 768 opt_len, PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN); 769 return; 770 } 771 bp += 2; 772 offset = GET_BE_U_4(bp); 773 bp += 4; 774 nla_afnum = GET_BE_U_2(bp); 775 bp += 2+2; 776 switch (nla_afnum) { 777 case AFNUM_INET: 778 if (opt_len != PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(nd_ipv4)) { 779 ND_PRINT("[Bad OPT_PGMCC_FEEDBACK option, length %u != %u + address size]", 780 opt_len, PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN); 781 return; 782 } 783 ND_TCHECK_LEN(bp, sizeof(nd_ipv4)); 784 addrtostr(bp, nla_buf, sizeof(nla_buf)); 785 bp += sizeof(nd_ipv4); 786 opts_len -= PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(nd_ipv4); 787 break; 788 case AFNUM_INET6: 789 if (opt_len != PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(nd_ipv6)) { 790 ND_PRINT("[Bad OPT_PGMCC_FEEDBACK option, length %u != %u + address size]", 791 opt_len, PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN); 792 return; 793 } 794 ND_TCHECK_LEN(bp, sizeof(nd_ipv6)); 795 addrtostr6(bp, nla_buf, sizeof(nla_buf)); 796 bp += sizeof(nd_ipv6); 797 opts_len -= PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(nd_ipv6); 798 break; 799 default: 800 goto trunc; 801 break; 802 } 803 804 ND_PRINT(" PGMCC FEEDBACK %u %s", offset, nla_buf); 805 break; 806 807 default: 808 ND_PRINT(" OPT_%02X [%u] ", opt_type, opt_len); 809 bp += opt_len; 810 opts_len -= opt_len; 811 break; 812 } 813 814 if (opt_type & PGM_OPT_END) 815 break; 816 } 817 } 818 819 ND_PRINT(" [%u]", length); 820 if (ndo->ndo_packettype == PT_PGM_ZMTP1 && 821 (pgm_type_val == PGM_ODATA || pgm_type_val == PGM_RDATA)) 822 zmtp1_datagram_print(ndo, bp, 823 GET_BE_U_2(pgm->pgm_length)); 824 825 return; 826 827 trunc: 828 nd_print_trunc(ndo); 829 } 830