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.3 2013/04/06 19:33:08 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, flags1, flags2; 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", pgm->pgm_length); 246 247 if (!vflag) 248 return; 249 250 if (length > pgm->pgm_length) 251 length = pgm->pgm_length; 252 253 (void)printf(" 0x%02x%02x%02x%02x%02x%02x ", 254 pgm->pgm_gsid[0], 255 pgm->pgm_gsid[1], 256 pgm->pgm_gsid[2], 257 pgm->pgm_gsid[3], 258 pgm->pgm_gsid[4], 259 pgm->pgm_gsid[5]); 260 switch (pgm->pgm_type) { 261 case PGM_SPM: { 262 struct pgm_spm *spm; 263 264 spm = (struct pgm_spm *)(pgm + 1); 265 TCHECK(*spm); 266 267 switch (EXTRACT_16BITS(&spm->pgms_nla_afi)) { 268 case AFI_IP: 269 addr_size = sizeof(struct in_addr); 270 nla_af = AF_INET; 271 break; 272 #ifdef INET6 273 case AFI_IP6: 274 addr_size = sizeof(struct in6_addr); 275 nla_af = AF_INET6; 276 break; 277 #endif 278 default: 279 goto trunc; 280 break; 281 } 282 bp = (u_char *) (spm + 1); 283 TCHECK2(*bp, addr_size); 284 nla = bp; 285 bp += addr_size; 286 287 inet_ntop(nla_af, nla, nla_buf, sizeof(nla_buf)); 288 (void)printf("SPM seq %u trail %u lead %u nla %s", 289 EXTRACT_32BITS(&spm->pgms_seq), 290 EXTRACT_32BITS(&spm->pgms_trailseq), 291 EXTRACT_32BITS(&spm->pgms_leadseq), 292 nla_buf); 293 break; 294 } 295 296 case PGM_POLL: { 297 struct pgm_poll *poll; 298 299 poll = (struct pgm_poll *)(pgm + 1); 300 TCHECK(*poll); 301 (void)printf("POLL seq %u round %u", 302 EXTRACT_32BITS(&poll->pgmp_seq), 303 EXTRACT_16BITS(&poll->pgmp_round)); 304 bp = (u_char *) (poll + 1); 305 break; 306 } 307 case PGM_POLR: { 308 struct pgm_polr *polr; 309 u_int32_t ivl, rnd, mask; 310 311 polr = (struct pgm_polr *)(pgm + 1); 312 TCHECK(*polr); 313 314 switch (EXTRACT_16BITS(&polr->pgmp_nla_afi)) { 315 case AFI_IP: 316 addr_size = sizeof(struct in_addr); 317 nla_af = AF_INET; 318 break; 319 #ifdef INET6 320 case AFI_IP6: 321 addr_size = sizeof(struct in6_addr); 322 nla_af = AF_INET6; 323 break; 324 #endif 325 default: 326 goto trunc; 327 break; 328 } 329 bp = (u_char *) (polr + 1); 330 TCHECK2(*bp, addr_size); 331 nla = bp; 332 bp += addr_size; 333 334 inet_ntop(nla_af, nla, nla_buf, sizeof(nla_buf)); 335 336 TCHECK2(*bp, sizeof(u_int32_t)); 337 ivl = EXTRACT_32BITS(bp); 338 bp += sizeof(u_int32_t); 339 340 TCHECK2(*bp, sizeof(u_int32_t)); 341 rnd = EXTRACT_32BITS(bp); 342 bp += sizeof(u_int32_t); 343 344 TCHECK2(*bp, sizeof(u_int32_t)); 345 mask = EXTRACT_32BITS(bp); 346 bp += sizeof(u_int32_t); 347 348 (void)printf("POLR seq %u round %u nla %s ivl %u rnd 0x%08x " 349 "mask 0x%08x", EXTRACT_32BITS(&polr->pgmp_seq), 350 EXTRACT_16BITS(&polr->pgmp_round), nla_buf, ivl, rnd, mask); 351 break; 352 } 353 case PGM_ODATA: { 354 struct pgm_data *odata; 355 356 odata = (struct pgm_data *)(pgm + 1); 357 TCHECK(*odata); 358 (void)printf("ODATA trail %u seq %u", 359 EXTRACT_32BITS(&odata->pgmd_trailseq), 360 EXTRACT_32BITS(&odata->pgmd_seq)); 361 bp = (u_char *) (odata + 1); 362 break; 363 } 364 365 case PGM_RDATA: { 366 struct pgm_data *rdata; 367 368 rdata = (struct pgm_data *)(pgm + 1); 369 TCHECK(*rdata); 370 (void)printf("RDATA trail %u seq %u", 371 EXTRACT_32BITS(&rdata->pgmd_trailseq), 372 EXTRACT_32BITS(&rdata->pgmd_seq)); 373 bp = (u_char *) (rdata + 1); 374 break; 375 } 376 377 case PGM_NAK: 378 case PGM_NULLNAK: 379 case PGM_NCF: { 380 struct pgm_nak *nak; 381 const void *source, *group; 382 int source_af, group_af; 383 #ifdef INET6 384 char source_buf[INET6_ADDRSTRLEN], group_buf[INET6_ADDRSTRLEN]; 385 #else 386 char source_buf[INET_ADDRSTRLEN], group_buf[INET_ADDRSTRLEN]; 387 #endif 388 389 nak = (struct pgm_nak *)(pgm + 1); 390 TCHECK(*nak); 391 392 /* 393 * Skip past the source, saving info along the way 394 * and stopping if we don't have enough. 395 */ 396 switch (EXTRACT_16BITS(&nak->pgmn_source_afi)) { 397 case AFI_IP: 398 addr_size = sizeof(struct in_addr); 399 source_af = AF_INET; 400 break; 401 #ifdef INET6 402 case AFI_IP6: 403 addr_size = sizeof(struct in6_addr); 404 source_af = AF_INET6; 405 break; 406 #endif 407 default: 408 goto trunc; 409 break; 410 } 411 bp = (u_char *) (nak + 1); 412 TCHECK2(*bp, addr_size); 413 source = bp; 414 bp += addr_size; 415 416 /* 417 * Skip past the group, saving info along the way 418 * and stopping if we don't have enough. 419 */ 420 switch (EXTRACT_16BITS(bp)) { 421 case AFI_IP: 422 addr_size = sizeof(struct in_addr); 423 group_af = AF_INET; 424 break; 425 #ifdef INET6 426 case AFI_IP6: 427 addr_size = sizeof(struct in6_addr); 428 group_af = AF_INET6; 429 break; 430 #endif 431 default: 432 goto trunc; 433 break; 434 } 435 bp += (2 * sizeof(u_int16_t)); 436 TCHECK2(*bp, addr_size); 437 group = bp; 438 bp += addr_size; 439 440 /* 441 * Options decoding can go here. 442 */ 443 inet_ntop(source_af, source, source_buf, sizeof(source_buf)); 444 inet_ntop(group_af, group, group_buf, sizeof(group_buf)); 445 switch (pgm->pgm_type) { 446 case PGM_NAK: 447 (void)printf("NAK "); 448 break; 449 case PGM_NULLNAK: 450 (void)printf("NNAK "); 451 break; 452 case PGM_NCF: 453 (void)printf("NCF "); 454 break; 455 default: 456 break; 457 } 458 (void)printf("(%s -> %s), seq %u", 459 source_buf, group_buf, EXTRACT_32BITS(&nak->pgmn_seq)); 460 break; 461 } 462 463 case PGM_ACK: { 464 struct pgm_ack *ack; 465 466 ack = (struct pgm_ack *)(pgm + 1); 467 TCHECK(*ack); 468 (void)printf("ACK seq %u", 469 EXTRACT_32BITS(&ack->pgma_rx_max_seq)); 470 bp = (u_char *) (ack + 1); 471 break; 472 } 473 474 case PGM_SPMR: 475 (void)printf("SPMR"); 476 break; 477 478 default: 479 (void)printf("UNKNOWN type %0x02x", pgm->pgm_type); 480 break; 481 482 } 483 if (pgm->pgm_options & PGM_OPT_BIT_PRESENT) { 484 485 /* 486 * make sure there's enough for the first option header 487 */ 488 if (!TTEST2(*bp, PGM_MIN_OPT_LEN)) { 489 (void)printf("[|OPT]"); 490 return; 491 } 492 493 /* 494 * That option header MUST be an OPT_LENGTH option 495 * (see the first paragraph of section 9.1 in RFC 3208). 496 */ 497 opt_type = *bp++; 498 if ((opt_type & PGM_OPT_MASK) != PGM_OPT_LENGTH) { 499 (void)printf("[First option bad, should be PGM_OPT_LENGTH, is %u]", opt_type & PGM_OPT_MASK); 500 return; 501 } 502 opt_len = *bp++; 503 if (opt_len != 4) { 504 (void)printf("[Bad OPT_LENGTH option, length %u != 4]", opt_len); 505 return; 506 } 507 opts_len = EXTRACT_16BITS(bp); 508 if (opts_len < 4) { 509 (void)printf("[Bad total option length %u < 4]", opts_len); 510 return; 511 } 512 bp += sizeof(u_int16_t); 513 (void)printf(" OPTS LEN %d", opts_len); 514 opts_len -= 4; 515 516 while (opts_len) { 517 if (opts_len < PGM_MIN_OPT_LEN) { 518 (void)printf("[Total option length leaves no room for final option]"); 519 return; 520 } 521 opt_type = *bp++; 522 opt_len = *bp++; 523 if (opt_len < PGM_MIN_OPT_LEN) { 524 (void)printf("[Bad option, length %u < %u]", opt_len, 525 PGM_MIN_OPT_LEN); 526 break; 527 } 528 if (opts_len < opt_len) { 529 (void)printf("[Total option length leaves no room for final option]"); 530 return; 531 } 532 if (!TTEST2(*bp, opt_len - 2)) { 533 (void)printf(" [|OPT]"); 534 return; 535 } 536 537 switch (opt_type & PGM_OPT_MASK) { 538 case PGM_OPT_LENGTH: 539 if (opt_len != 4) { 540 (void)printf("[Bad OPT_LENGTH option, length %u != 4]", opt_len); 541 return; 542 } 543 (void)printf(" OPTS LEN (extra?) %d", EXTRACT_16BITS(bp)); 544 bp += sizeof(u_int16_t); 545 opts_len -= 4; 546 break; 547 548 case PGM_OPT_FRAGMENT: 549 if (opt_len != 16) { 550 (void)printf("[Bad OPT_FRAGMENT option, length %u != 16]", opt_len); 551 return; 552 } 553 flags1 = *bp++; 554 flags2 = *bp++; 555 seq = EXTRACT_32BITS(bp); 556 bp += sizeof(u_int32_t); 557 offset = EXTRACT_32BITS(bp); 558 bp += sizeof(u_int32_t); 559 len = EXTRACT_32BITS(bp); 560 bp += sizeof(u_int32_t); 561 (void)printf(" FRAG seq %u off %u len %u", seq, offset, len); 562 opts_len -= 16; 563 break; 564 565 case PGM_OPT_NAK_LIST: 566 flags1 = *bp++; 567 flags2 = *bp++; 568 opt_len -= sizeof(u_int32_t); /* option header */ 569 (void)printf(" NAK LIST"); 570 while (opt_len) { 571 if (opt_len < sizeof(u_int32_t)) { 572 (void)printf("[Option length not a multiple of 4]"); 573 return; 574 } 575 TCHECK2(*bp, sizeof(u_int32_t)); 576 (void)printf(" %u", EXTRACT_32BITS(bp)); 577 bp += sizeof(u_int32_t); 578 opt_len -= sizeof(u_int32_t); 579 opts_len -= sizeof(u_int32_t); 580 } 581 break; 582 583 case PGM_OPT_JOIN: 584 if (opt_len != 8) { 585 (void)printf("[Bad OPT_JOIN option, length %u != 8]", opt_len); 586 return; 587 } 588 flags1 = *bp++; 589 flags2 = *bp++; 590 seq = EXTRACT_32BITS(bp); 591 bp += sizeof(u_int32_t); 592 (void)printf(" JOIN %u", seq); 593 opts_len -= 8; 594 break; 595 596 case PGM_OPT_NAK_BO_IVL: 597 if (opt_len != 12) { 598 (void)printf("[Bad OPT_NAK_BO_IVL option, length %u != 12]", opt_len); 599 return; 600 } 601 flags1 = *bp++; 602 flags2 = *bp++; 603 offset = EXTRACT_32BITS(bp); 604 bp += sizeof(u_int32_t); 605 seq = EXTRACT_32BITS(bp); 606 bp += sizeof(u_int32_t); 607 (void)printf(" BACKOFF ivl %u ivlseq %u", offset, seq); 608 opts_len -= 12; 609 break; 610 611 case PGM_OPT_NAK_BO_RNG: 612 if (opt_len != 12) { 613 (void)printf("[Bad OPT_NAK_BO_RNG option, length %u != 12]", opt_len); 614 return; 615 } 616 flags1 = *bp++; 617 flags2 = *bp++; 618 offset = EXTRACT_32BITS(bp); 619 bp += sizeof(u_int32_t); 620 seq = EXTRACT_32BITS(bp); 621 bp += sizeof(u_int32_t); 622 (void)printf(" BACKOFF max %u min %u", offset, seq); 623 opts_len -= 12; 624 break; 625 626 case PGM_OPT_REDIRECT: 627 flags1 = *bp++; 628 flags2 = *bp++; 629 switch (EXTRACT_16BITS(bp)) { 630 case AFI_IP: 631 addr_size = sizeof(struct in_addr); 632 nla_af = AF_INET; 633 break; 634 #ifdef INET6 635 case AFI_IP6: 636 addr_size = sizeof(struct in6_addr); 637 nla_af = AF_INET6; 638 break; 639 #endif 640 default: 641 goto trunc; 642 break; 643 } 644 bp += (2 * sizeof(u_int16_t)); 645 if (opt_len != 4 + addr_size) { 646 (void)printf("[Bad OPT_REDIRECT option, length %u != 4 + address size]", opt_len); 647 return; 648 } 649 TCHECK2(*bp, addr_size); 650 nla = bp; 651 bp += addr_size; 652 653 inet_ntop(nla_af, nla, nla_buf, sizeof(nla_buf)); 654 (void)printf(" REDIRECT %s", (char *)nla); 655 opts_len -= 4 + addr_size; 656 break; 657 658 case PGM_OPT_PARITY_PRM: 659 if (opt_len != 8) { 660 (void)printf("[Bad OPT_PARITY_PRM option, length %u != 8]", opt_len); 661 return; 662 } 663 flags1 = *bp++; 664 flags2 = *bp++; 665 len = EXTRACT_32BITS(bp); 666 bp += sizeof(u_int32_t); 667 (void)printf(" PARITY MAXTGS %u", len); 668 opts_len -= 8; 669 break; 670 671 case PGM_OPT_PARITY_GRP: 672 if (opt_len != 8) { 673 (void)printf("[Bad OPT_PARITY_GRP option, length %u != 8]", opt_len); 674 return; 675 } 676 flags1 = *bp++; 677 flags2 = *bp++; 678 seq = EXTRACT_32BITS(bp); 679 bp += sizeof(u_int32_t); 680 (void)printf(" PARITY GROUP %u", seq); 681 opts_len -= 8; 682 break; 683 684 case PGM_OPT_CURR_TGSIZE: 685 if (opt_len != 8) { 686 (void)printf("[Bad OPT_CURR_TGSIZE option, length %u != 8]", opt_len); 687 return; 688 } 689 flags1 = *bp++; 690 flags2 = *bp++; 691 len = EXTRACT_32BITS(bp); 692 bp += sizeof(u_int32_t); 693 (void)printf(" PARITY ATGS %u", len); 694 opts_len -= 8; 695 break; 696 697 case PGM_OPT_NBR_UNREACH: 698 if (opt_len != 4) { 699 (void)printf("[Bad OPT_NBR_UNREACH option, length %u != 4]", opt_len); 700 return; 701 } 702 flags1 = *bp++; 703 flags2 = *bp++; 704 (void)printf(" NBR_UNREACH"); 705 opts_len -= 4; 706 break; 707 708 case PGM_OPT_PATH_NLA: 709 (void)printf(" PATH_NLA [%d]", opt_len); 710 bp += opt_len; 711 opts_len -= opt_len; 712 break; 713 714 case PGM_OPT_SYN: 715 if (opt_len != 4) { 716 (void)printf("[Bad OPT_SYN option, length %u != 4]", opt_len); 717 return; 718 } 719 flags1 = *bp++; 720 flags2 = *bp++; 721 (void)printf(" SYN"); 722 opts_len -= 4; 723 break; 724 725 case PGM_OPT_FIN: 726 if (opt_len != 4) { 727 (void)printf("[Bad OPT_FIN option, length %u != 4]", opt_len); 728 return; 729 } 730 flags1 = *bp++; 731 flags2 = *bp++; 732 (void)printf(" FIN"); 733 opts_len -= 4; 734 break; 735 736 case PGM_OPT_RST: 737 if (opt_len != 4) { 738 (void)printf("[Bad OPT_RST option, length %u != 4]", opt_len); 739 return; 740 } 741 flags1 = *bp++; 742 flags2 = *bp++; 743 (void)printf(" RST"); 744 opts_len -= 4; 745 break; 746 747 case PGM_OPT_CR: 748 (void)printf(" CR"); 749 bp += opt_len; 750 opts_len -= opt_len; 751 break; 752 753 case PGM_OPT_CRQST: 754 if (opt_len != 4) { 755 (void)printf("[Bad OPT_CRQST option, length %u != 4]", opt_len); 756 return; 757 } 758 flags1 = *bp++; 759 flags2 = *bp++; 760 (void)printf(" CRQST"); 761 opts_len -= 4; 762 break; 763 764 case PGM_OPT_PGMCC_DATA: 765 flags1 = *bp++; 766 flags2 = *bp++; 767 offset = EXTRACT_32BITS(bp); 768 bp += sizeof(u_int32_t); 769 switch (EXTRACT_16BITS(bp)) { 770 case AFI_IP: 771 addr_size = sizeof(struct in_addr); 772 nla_af = AF_INET; 773 break; 774 #ifdef INET6 775 case AFI_IP6: 776 addr_size = sizeof(struct in6_addr); 777 nla_af = AF_INET6; 778 break; 779 #endif 780 default: 781 goto trunc; 782 break; 783 } 784 bp += (2 * sizeof(u_int16_t)); 785 if (opt_len != 12 + addr_size) { 786 (void)printf("[Bad OPT_PGMCC_DATA option, length %u != 12 + address size]", opt_len); 787 return; 788 } 789 TCHECK2(*bp, addr_size); 790 nla = bp; 791 bp += addr_size; 792 793 inet_ntop(nla_af, nla, nla_buf, sizeof(nla_buf)); 794 (void)printf(" PGMCC DATA %u %s", offset, (char*)nla); 795 opts_len -= 16; 796 break; 797 798 case PGM_OPT_PGMCC_FEEDBACK: 799 flags1 = *bp++; 800 flags2 = *bp++; 801 offset = EXTRACT_32BITS(bp); 802 bp += sizeof(u_int32_t); 803 switch (EXTRACT_16BITS(bp)) { 804 case AFI_IP: 805 addr_size = sizeof(struct in_addr); 806 nla_af = AF_INET; 807 break; 808 #ifdef INET6 809 case AFI_IP6: 810 addr_size = sizeof(struct in6_addr); 811 nla_af = AF_INET6; 812 break; 813 #endif 814 default: 815 goto trunc; 816 break; 817 } 818 bp += (2 * sizeof(u_int16_t)); 819 if (opt_len != 12 + addr_size) { 820 (void)printf("[Bad OPT_PGMCC_FEEDBACK option, length %u != 12 + address size]", opt_len); 821 return; 822 } 823 TCHECK2(*bp, addr_size); 824 nla = bp; 825 bp += addr_size; 826 827 inet_ntop(nla_af, nla, nla_buf, sizeof(nla_buf)); 828 (void)printf(" PGMCC FEEDBACK %u %s", offset, (char*)nla); 829 opts_len -= 16; 830 break; 831 832 default: 833 (void)printf(" OPT_%02X [%d] ", opt_type, opt_len); 834 bp += opt_len; 835 opts_len -= opt_len; 836 break; 837 } 838 839 if (opt_type & PGM_OPT_END) 840 break; 841 } 842 } 843 844 (void)printf(" [%u]", EXTRACT_16BITS(&pgm->pgm_length)); 845 846 return; 847 848 trunc: 849 fputs("[|pgm]", stdout); 850 if (ch != '\0') 851 putchar('>'); 852 } 853