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.9 2017/09/08 14:01:13 christos 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 */ 42 struct 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 52 struct 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 62 struct 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 73 struct pgm_ack { 74 uint32_t pgma_rx_max_seq; 75 uint32_t pgma_bitmap; 76 /* ... options */ 77 }; 78 79 struct pgm_poll { 80 uint32_t pgmp_seq; 81 uint16_t pgmp_round; 82 uint16_t pgmp_reserved; 83 /* ... options */ 84 }; 85 86 struct 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 96 struct pgm_data { 97 uint32_t pgmd_seq; 98 uint32_t pgmd_trailseq; 99 /* ... options */ 100 }; 101 102 typedef 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 150 void 151 pgm_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 } else { 178 ND_PRINT((ndo, "%s > %s: [|pgm]", 179 ipaddr_string(ndo, &ip->ip_src), 180 ipaddr_string(ndo, &ip->ip_dst))); 181 } 182 return; 183 } 184 185 sport = EXTRACT_16BITS(&pgm->pgm_sport); 186 dport = EXTRACT_16BITS(&pgm->pgm_dport); 187 188 if (ip6) { 189 if (ip6->ip6_nxt == IPPROTO_PGM) { 190 ND_PRINT((ndo, "%s.%s > %s.%s: ", 191 ip6addr_string(ndo, &ip6->ip6_src), 192 tcpport_string(ndo, sport), 193 ip6addr_string(ndo, &ip6->ip6_dst), 194 tcpport_string(ndo, dport))); 195 } else { 196 ND_PRINT((ndo, "%s > %s: ", 197 tcpport_string(ndo, sport), tcpport_string(ndo, dport))); 198 } 199 } else { 200 if (ip->ip_p == IPPROTO_PGM) { 201 ND_PRINT((ndo, "%s.%s > %s.%s: ", 202 ipaddr_string(ndo, &ip->ip_src), 203 tcpport_string(ndo, sport), 204 ipaddr_string(ndo, &ip->ip_dst), 205 tcpport_string(ndo, dport))); 206 } else { 207 ND_PRINT((ndo, "%s > %s: ", 208 tcpport_string(ndo, sport), tcpport_string(ndo, dport))); 209 } 210 } 211 212 ND_TCHECK(*pgm); 213 214 ND_PRINT((ndo, "PGM, length %u", EXTRACT_16BITS(&pgm->pgm_length))); 215 216 if (!ndo->ndo_vflag) 217 return; 218 219 ND_PRINT((ndo, " 0x%02x%02x%02x%02x%02x%02x ", 220 pgm->pgm_gsid[0], 221 pgm->pgm_gsid[1], 222 pgm->pgm_gsid[2], 223 pgm->pgm_gsid[3], 224 pgm->pgm_gsid[4], 225 pgm->pgm_gsid[5])); 226 switch (pgm->pgm_type) { 227 case PGM_SPM: { 228 const struct pgm_spm *spm; 229 230 spm = (const struct pgm_spm *)(pgm + 1); 231 ND_TCHECK(*spm); 232 bp = (const u_char *) (spm + 1); 233 234 switch (EXTRACT_16BITS(&spm->pgms_nla_afi)) { 235 case AFNUM_INET: 236 ND_TCHECK2(*bp, sizeof(struct in_addr)); 237 addrtostr(bp, nla_buf, sizeof(nla_buf)); 238 bp += sizeof(struct in_addr); 239 break; 240 case AFNUM_INET6: 241 ND_TCHECK2(*bp, sizeof(struct in6_addr)); 242 addrtostr6(bp, nla_buf, sizeof(nla_buf)); 243 bp += sizeof(struct in6_addr); 244 break; 245 default: 246 goto trunc; 247 break; 248 } 249 250 ND_PRINT((ndo, "SPM seq %u trail %u lead %u nla %s", 251 EXTRACT_32BITS(&spm->pgms_seq), 252 EXTRACT_32BITS(&spm->pgms_trailseq), 253 EXTRACT_32BITS(&spm->pgms_leadseq), 254 nla_buf)); 255 break; 256 } 257 258 case PGM_POLL: { 259 const struct pgm_poll *poll_msg; 260 261 poll_msg = (const struct pgm_poll *)(pgm + 1); 262 ND_TCHECK(*poll_msg); 263 ND_PRINT((ndo, "POLL seq %u round %u", 264 EXTRACT_32BITS(&poll_msg->pgmp_seq), 265 EXTRACT_16BITS(&poll_msg->pgmp_round))); 266 bp = (const u_char *) (poll_msg + 1); 267 break; 268 } 269 case PGM_POLR: { 270 const struct pgm_polr *polr; 271 uint32_t ivl, rnd, mask; 272 273 polr = (const struct pgm_polr *)(pgm + 1); 274 ND_TCHECK(*polr); 275 bp = (const u_char *) (polr + 1); 276 277 switch (EXTRACT_16BITS(&polr->pgmp_nla_afi)) { 278 case AFNUM_INET: 279 ND_TCHECK2(*bp, sizeof(struct in_addr)); 280 addrtostr(bp, nla_buf, sizeof(nla_buf)); 281 bp += sizeof(struct in_addr); 282 break; 283 case AFNUM_INET6: 284 ND_TCHECK2(*bp, sizeof(struct in6_addr)); 285 addrtostr6(bp, nla_buf, sizeof(nla_buf)); 286 bp += sizeof(struct in6_addr); 287 break; 288 default: 289 goto trunc; 290 break; 291 } 292 293 ND_TCHECK2(*bp, sizeof(uint32_t)); 294 ivl = EXTRACT_32BITS(bp); 295 bp += sizeof(uint32_t); 296 297 ND_TCHECK2(*bp, sizeof(uint32_t)); 298 rnd = EXTRACT_32BITS(bp); 299 bp += sizeof(uint32_t); 300 301 ND_TCHECK2(*bp, sizeof(uint32_t)); 302 mask = EXTRACT_32BITS(bp); 303 bp += sizeof(uint32_t); 304 305 ND_PRINT((ndo, "POLR seq %u round %u nla %s ivl %u rnd 0x%08x " 306 "mask 0x%08x", EXTRACT_32BITS(&polr->pgmp_seq), 307 EXTRACT_16BITS(&polr->pgmp_round), nla_buf, ivl, rnd, mask)); 308 break; 309 } 310 case PGM_ODATA: { 311 const struct pgm_data *odata; 312 313 odata = (const struct pgm_data *)(pgm + 1); 314 ND_TCHECK(*odata); 315 ND_PRINT((ndo, "ODATA trail %u seq %u", 316 EXTRACT_32BITS(&odata->pgmd_trailseq), 317 EXTRACT_32BITS(&odata->pgmd_seq))); 318 bp = (const u_char *) (odata + 1); 319 break; 320 } 321 322 case PGM_RDATA: { 323 const struct pgm_data *rdata; 324 325 rdata = (const struct pgm_data *)(pgm + 1); 326 ND_TCHECK(*rdata); 327 ND_PRINT((ndo, "RDATA trail %u seq %u", 328 EXTRACT_32BITS(&rdata->pgmd_trailseq), 329 EXTRACT_32BITS(&rdata->pgmd_seq))); 330 bp = (const u_char *) (rdata + 1); 331 break; 332 } 333 334 case PGM_NAK: 335 case PGM_NULLNAK: 336 case PGM_NCF: { 337 const struct pgm_nak *nak; 338 char source_buf[INET6_ADDRSTRLEN], group_buf[INET6_ADDRSTRLEN]; 339 340 nak = (const struct pgm_nak *)(pgm + 1); 341 ND_TCHECK(*nak); 342 bp = (const u_char *) (nak + 1); 343 344 /* 345 * Skip past the source, saving info along the way 346 * and stopping if we don't have enough. 347 */ 348 switch (EXTRACT_16BITS(&nak->pgmn_source_afi)) { 349 case AFNUM_INET: 350 ND_TCHECK2(*bp, sizeof(struct in_addr)); 351 addrtostr(bp, source_buf, sizeof(source_buf)); 352 bp += sizeof(struct in_addr); 353 break; 354 case AFNUM_INET6: 355 ND_TCHECK2(*bp, sizeof(struct in6_addr)); 356 addrtostr6(bp, source_buf, sizeof(source_buf)); 357 bp += sizeof(struct in6_addr); 358 break; 359 default: 360 goto trunc; 361 break; 362 } 363 364 /* 365 * Skip past the group, saving info along the way 366 * and stopping if we don't have enough. 367 */ 368 bp += (2 * sizeof(uint16_t)); 369 ND_TCHECK_16BITS(bp); 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 if (!ND_TTEST2(*bp, 2)) { 466 ND_PRINT((ndo, " [|OPT]")); 467 return; 468 } 469 opt_type = *bp++; 470 opt_len = *bp++; 471 if (opt_len < PGM_MIN_OPT_LEN) { 472 ND_PRINT((ndo, "[Bad option, length %u < %u]", opt_len, 473 PGM_MIN_OPT_LEN)); 474 break; 475 } 476 if (opts_len < opt_len) { 477 ND_PRINT((ndo, "[Total option length leaves no room for final option]")); 478 return; 479 } 480 if (!ND_TTEST2(*bp, opt_len - 2)) { 481 ND_PRINT((ndo, " [|OPT]")); 482 return; 483 } 484 485 switch (opt_type & PGM_OPT_MASK) { 486 case PGM_OPT_LENGTH: 487 #define PGM_OPT_LENGTH_LEN (2+2) 488 if (opt_len != PGM_OPT_LENGTH_LEN) { 489 ND_PRINT((ndo, "[Bad OPT_LENGTH option, length %u != %u]", 490 opt_len, PGM_OPT_LENGTH_LEN)); 491 return; 492 } 493 ND_PRINT((ndo, " OPTS LEN (extra?) %d", EXTRACT_16BITS(bp))); 494 bp += 2; 495 opts_len -= PGM_OPT_LENGTH_LEN; 496 break; 497 498 case PGM_OPT_FRAGMENT: 499 #define PGM_OPT_FRAGMENT_LEN (2+2+4+4+4) 500 if (opt_len != PGM_OPT_FRAGMENT_LEN) { 501 ND_PRINT((ndo, "[Bad OPT_FRAGMENT option, length %u != %u]", 502 opt_len, PGM_OPT_FRAGMENT_LEN)); 503 return; 504 } 505 bp += 2; 506 seq = EXTRACT_32BITS(bp); 507 bp += 4; 508 offset = EXTRACT_32BITS(bp); 509 bp += 4; 510 len = EXTRACT_32BITS(bp); 511 bp += 4; 512 ND_PRINT((ndo, " FRAG seq %u off %u len %u", seq, offset, len)); 513 opts_len -= PGM_OPT_FRAGMENT_LEN; 514 break; 515 516 case PGM_OPT_NAK_LIST: 517 bp += 2; 518 opt_len -= 4; /* option header */ 519 ND_PRINT((ndo, " NAK LIST")); 520 while (opt_len) { 521 if (opt_len < 4) { 522 ND_PRINT((ndo, "[Option length not a multiple of 4]")); 523 return; 524 } 525 ND_TCHECK2(*bp, 4); 526 ND_PRINT((ndo, " %u", EXTRACT_32BITS(bp))); 527 bp += 4; 528 opt_len -= 4; 529 opts_len -= 4; 530 } 531 break; 532 533 case PGM_OPT_JOIN: 534 #define PGM_OPT_JOIN_LEN (2+2+4) 535 if (opt_len != PGM_OPT_JOIN_LEN) { 536 ND_PRINT((ndo, "[Bad OPT_JOIN option, length %u != %u]", 537 opt_len, PGM_OPT_JOIN_LEN)); 538 return; 539 } 540 bp += 2; 541 seq = EXTRACT_32BITS(bp); 542 bp += 4; 543 ND_PRINT((ndo, " JOIN %u", seq)); 544 opts_len -= PGM_OPT_JOIN_LEN; 545 break; 546 547 case PGM_OPT_NAK_BO_IVL: 548 #define PGM_OPT_NAK_BO_IVL_LEN (2+2+4+4) 549 if (opt_len != PGM_OPT_NAK_BO_IVL_LEN) { 550 ND_PRINT((ndo, "[Bad OPT_NAK_BO_IVL option, length %u != %u]", 551 opt_len, PGM_OPT_NAK_BO_IVL_LEN)); 552 return; 553 } 554 bp += 2; 555 offset = EXTRACT_32BITS(bp); 556 bp += 4; 557 seq = EXTRACT_32BITS(bp); 558 bp += 4; 559 ND_PRINT((ndo, " BACKOFF ivl %u ivlseq %u", offset, seq)); 560 opts_len -= PGM_OPT_NAK_BO_IVL_LEN; 561 break; 562 563 case PGM_OPT_NAK_BO_RNG: 564 #define PGM_OPT_NAK_BO_RNG_LEN (2+2+4+4) 565 if (opt_len != PGM_OPT_NAK_BO_RNG_LEN) { 566 ND_PRINT((ndo, "[Bad OPT_NAK_BO_RNG option, length %u != %u]", 567 opt_len, PGM_OPT_NAK_BO_RNG_LEN)); 568 return; 569 } 570 bp += 2; 571 offset = EXTRACT_32BITS(bp); 572 bp += 4; 573 seq = EXTRACT_32BITS(bp); 574 bp += 4; 575 ND_PRINT((ndo, " BACKOFF max %u min %u", offset, seq)); 576 opts_len -= PGM_OPT_NAK_BO_RNG_LEN; 577 break; 578 579 case PGM_OPT_REDIRECT: 580 #define PGM_OPT_REDIRECT_FIXED_LEN (2+2+2+2) 581 if (opt_len < PGM_OPT_REDIRECT_FIXED_LEN) { 582 ND_PRINT((ndo, "[Bad OPT_REDIRECT option, length %u < %u]", 583 opt_len, PGM_OPT_REDIRECT_FIXED_LEN)); 584 return; 585 } 586 bp += 2; 587 nla_afnum = EXTRACT_16BITS(bp); 588 bp += 2+2; 589 switch (nla_afnum) { 590 case AFNUM_INET: 591 if (opt_len != PGM_OPT_REDIRECT_FIXED_LEN + sizeof(struct in_addr)) { 592 ND_PRINT((ndo, "[Bad OPT_REDIRECT option, length %u != %u + address size]", 593 opt_len, PGM_OPT_REDIRECT_FIXED_LEN)); 594 return; 595 } 596 ND_TCHECK2(*bp, sizeof(struct in_addr)); 597 addrtostr(bp, nla_buf, sizeof(nla_buf)); 598 bp += sizeof(struct in_addr); 599 opts_len -= PGM_OPT_REDIRECT_FIXED_LEN + sizeof(struct in_addr); 600 break; 601 case AFNUM_INET6: 602 if (opt_len != PGM_OPT_REDIRECT_FIXED_LEN + sizeof(struct in6_addr)) { 603 ND_PRINT((ndo, "[Bad OPT_REDIRECT option, length %u != %u + address size]", 604 PGM_OPT_REDIRECT_FIXED_LEN, opt_len)); 605 return; 606 } 607 ND_TCHECK2(*bp, sizeof(struct in6_addr)); 608 addrtostr6(bp, nla_buf, sizeof(nla_buf)); 609 bp += sizeof(struct in6_addr); 610 opts_len -= PGM_OPT_REDIRECT_FIXED_LEN + sizeof(struct in6_addr); 611 break; 612 default: 613 goto trunc; 614 break; 615 } 616 617 ND_PRINT((ndo, " REDIRECT %s", nla_buf)); 618 break; 619 620 case PGM_OPT_PARITY_PRM: 621 #define PGM_OPT_PARITY_PRM_LEN (2+2+4) 622 if (opt_len != PGM_OPT_PARITY_PRM_LEN) { 623 ND_PRINT((ndo, "[Bad OPT_PARITY_PRM option, length %u != %u]", 624 opt_len, PGM_OPT_PARITY_PRM_LEN)); 625 return; 626 } 627 bp += 2; 628 len = EXTRACT_32BITS(bp); 629 bp += 4; 630 ND_PRINT((ndo, " PARITY MAXTGS %u", len)); 631 opts_len -= PGM_OPT_PARITY_PRM_LEN; 632 break; 633 634 case PGM_OPT_PARITY_GRP: 635 #define PGM_OPT_PARITY_GRP_LEN (2+2+4) 636 if (opt_len != PGM_OPT_PARITY_GRP_LEN) { 637 ND_PRINT((ndo, "[Bad OPT_PARITY_GRP option, length %u != %u]", 638 opt_len, PGM_OPT_PARITY_GRP_LEN)); 639 return; 640 } 641 bp += 2; 642 seq = EXTRACT_32BITS(bp); 643 bp += 4; 644 ND_PRINT((ndo, " PARITY GROUP %u", seq)); 645 opts_len -= PGM_OPT_PARITY_GRP_LEN; 646 break; 647 648 case PGM_OPT_CURR_TGSIZE: 649 #define PGM_OPT_CURR_TGSIZE_LEN (2+2+4) 650 if (opt_len != PGM_OPT_CURR_TGSIZE_LEN) { 651 ND_PRINT((ndo, "[Bad OPT_CURR_TGSIZE option, length %u != %u]", 652 opt_len, PGM_OPT_CURR_TGSIZE_LEN)); 653 return; 654 } 655 bp += 2; 656 len = EXTRACT_32BITS(bp); 657 bp += 4; 658 ND_PRINT((ndo, " PARITY ATGS %u", len)); 659 opts_len -= PGM_OPT_CURR_TGSIZE_LEN; 660 break; 661 662 case PGM_OPT_NBR_UNREACH: 663 #define PGM_OPT_NBR_UNREACH_LEN (2+2) 664 if (opt_len != PGM_OPT_NBR_UNREACH_LEN) { 665 ND_PRINT((ndo, "[Bad OPT_NBR_UNREACH option, length %u != %u]", 666 opt_len, PGM_OPT_NBR_UNREACH_LEN)); 667 return; 668 } 669 bp += 2; 670 ND_PRINT((ndo, " NBR_UNREACH")); 671 opts_len -= PGM_OPT_NBR_UNREACH_LEN; 672 break; 673 674 case PGM_OPT_PATH_NLA: 675 ND_PRINT((ndo, " PATH_NLA [%d]", opt_len)); 676 bp += opt_len; 677 opts_len -= opt_len; 678 break; 679 680 case PGM_OPT_SYN: 681 #define PGM_OPT_SYN_LEN (2+2) 682 if (opt_len != PGM_OPT_SYN_LEN) { 683 ND_PRINT((ndo, "[Bad OPT_SYN option, length %u != %u]", 684 opt_len, PGM_OPT_SYN_LEN)); 685 return; 686 } 687 bp += 2; 688 ND_PRINT((ndo, " SYN")); 689 opts_len -= PGM_OPT_SYN_LEN; 690 break; 691 692 case PGM_OPT_FIN: 693 #define PGM_OPT_FIN_LEN (2+2) 694 if (opt_len != PGM_OPT_FIN_LEN) { 695 ND_PRINT((ndo, "[Bad OPT_FIN option, length %u != %u]", 696 opt_len, PGM_OPT_FIN_LEN)); 697 return; 698 } 699 bp += 2; 700 ND_PRINT((ndo, " FIN")); 701 opts_len -= PGM_OPT_FIN_LEN; 702 break; 703 704 case PGM_OPT_RST: 705 #define PGM_OPT_RST_LEN (2+2) 706 if (opt_len != PGM_OPT_RST_LEN) { 707 ND_PRINT((ndo, "[Bad OPT_RST option, length %u != %u]", 708 opt_len, PGM_OPT_RST_LEN)); 709 return; 710 } 711 bp += 2; 712 ND_PRINT((ndo, " RST")); 713 opts_len -= PGM_OPT_RST_LEN; 714 break; 715 716 case PGM_OPT_CR: 717 ND_PRINT((ndo, " CR")); 718 bp += opt_len; 719 opts_len -= opt_len; 720 break; 721 722 case PGM_OPT_CRQST: 723 #define PGM_OPT_CRQST_LEN (2+2) 724 if (opt_len != PGM_OPT_CRQST_LEN) { 725 ND_PRINT((ndo, "[Bad OPT_CRQST option, length %u != %u]", 726 opt_len, PGM_OPT_CRQST_LEN)); 727 return; 728 } 729 bp += 2; 730 ND_PRINT((ndo, " CRQST")); 731 opts_len -= PGM_OPT_CRQST_LEN; 732 break; 733 734 case PGM_OPT_PGMCC_DATA: 735 #define PGM_OPT_PGMCC_DATA_FIXED_LEN (2+2+4+2+2) 736 if (opt_len < PGM_OPT_PGMCC_DATA_FIXED_LEN) { 737 ND_PRINT((ndo, "[Bad OPT_PGMCC_DATA option, length %u < %u]", 738 opt_len, PGM_OPT_PGMCC_DATA_FIXED_LEN)); 739 return; 740 } 741 bp += 2; 742 offset = EXTRACT_32BITS(bp); 743 bp += 4; 744 nla_afnum = EXTRACT_16BITS(bp); 745 bp += 2+2; 746 switch (nla_afnum) { 747 case AFNUM_INET: 748 if (opt_len != PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(struct in_addr)) { 749 ND_PRINT((ndo, "[Bad OPT_PGMCC_DATA option, length %u != %u + address size]", 750 opt_len, PGM_OPT_PGMCC_DATA_FIXED_LEN)); 751 return; 752 } 753 ND_TCHECK2(*bp, sizeof(struct in_addr)); 754 addrtostr(bp, nla_buf, sizeof(nla_buf)); 755 bp += sizeof(struct in_addr); 756 opts_len -= PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(struct in_addr); 757 break; 758 case AFNUM_INET6: 759 if (opt_len != PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(struct in6_addr)) { 760 ND_PRINT((ndo, "[Bad OPT_PGMCC_DATA option, length %u != %u + address size]", 761 opt_len, PGM_OPT_PGMCC_DATA_FIXED_LEN)); 762 return; 763 } 764 ND_TCHECK2(*bp, sizeof(struct in6_addr)); 765 addrtostr6(bp, nla_buf, sizeof(nla_buf)); 766 bp += sizeof(struct in6_addr); 767 opts_len -= PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(struct in6_addr); 768 break; 769 default: 770 goto trunc; 771 break; 772 } 773 774 ND_PRINT((ndo, " PGMCC DATA %u %s", offset, nla_buf)); 775 break; 776 777 case PGM_OPT_PGMCC_FEEDBACK: 778 #define PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN (2+2+4+2+2) 779 if (opt_len < PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN) { 780 ND_PRINT((ndo, "[Bad PGM_OPT_PGMCC_FEEDBACK option, length %u < %u]", 781 opt_len, PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN)); 782 return; 783 } 784 bp += 2; 785 offset = EXTRACT_32BITS(bp); 786 bp += 4; 787 nla_afnum = EXTRACT_16BITS(bp); 788 bp += 2+2; 789 switch (nla_afnum) { 790 case AFNUM_INET: 791 if (opt_len != PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(struct in_addr)) { 792 ND_PRINT((ndo, "[Bad OPT_PGMCC_FEEDBACK option, length %u != %u + address size]", 793 opt_len, PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN)); 794 return; 795 } 796 ND_TCHECK2(*bp, sizeof(struct in_addr)); 797 addrtostr(bp, nla_buf, sizeof(nla_buf)); 798 bp += sizeof(struct in_addr); 799 opts_len -= PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(struct in_addr); 800 break; 801 case AFNUM_INET6: 802 if (opt_len != PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(struct in6_addr)) { 803 ND_PRINT((ndo, "[Bad OPT_PGMCC_FEEDBACK option, length %u != %u + address size]", 804 opt_len, PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN)); 805 return; 806 } 807 ND_TCHECK2(*bp, sizeof(struct in6_addr)); 808 addrtostr6(bp, nla_buf, sizeof(nla_buf)); 809 bp += sizeof(struct in6_addr); 810 opts_len -= PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(struct in6_addr); 811 break; 812 default: 813 goto trunc; 814 break; 815 } 816 817 ND_PRINT((ndo, " PGMCC FEEDBACK %u %s", offset, nla_buf)); 818 break; 819 820 default: 821 ND_PRINT((ndo, " OPT_%02X [%d] ", opt_type, opt_len)); 822 bp += opt_len; 823 opts_len -= opt_len; 824 break; 825 } 826 827 if (opt_type & PGM_OPT_END) 828 break; 829 } 830 } 831 832 ND_PRINT((ndo, " [%u]", length)); 833 if (ndo->ndo_packettype == PT_PGM_ZMTP1 && 834 (pgm->pgm_type == PGM_ODATA || pgm->pgm_type == PGM_RDATA)) 835 zmtp1_print_datagram(ndo, bp, EXTRACT_16BITS(&pgm->pgm_length)); 836 837 return; 838 839 trunc: 840 ND_PRINT((ndo, "[|pgm]")); 841 if (ch != '\0') 842 ND_PRINT((ndo, ">")); 843 } 844