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