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