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