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