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.10 2020/02/24 18:39:47 kamil 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 UNALIGNED_OK 151 void 152 pgm_print(netdissect_options *ndo, 153 register const u_char *bp, register u_int length, 154 register const u_char *bp2) 155 { 156 register const struct pgm_header *pgm; 157 register const struct ip *ip; 158 register char ch; 159 uint16_t sport, dport; 160 u_int nla_afnum; 161 char nla_buf[INET6_ADDRSTRLEN]; 162 register const struct ip6_hdr *ip6; 163 uint8_t opt_type, opt_len; 164 uint32_t seq, opts_len, len, offset; 165 166 pgm = (const struct pgm_header *)bp; 167 ip = (const struct ip *)bp2; 168 if (IP_V(ip) == 6) 169 ip6 = (const struct ip6_hdr *)bp2; 170 else 171 ip6 = NULL; 172 ch = '\0'; 173 if (!ND_TTEST(pgm->pgm_dport)) { 174 if (ip6) { 175 ND_PRINT((ndo, "%s > %s: [|pgm]", 176 ip6addr_string(ndo, &ip6->ip6_src), 177 ip6addr_string(ndo, &ip6->ip6_dst))); 178 } else { 179 ND_PRINT((ndo, "%s > %s: [|pgm]", 180 ipaddr_string(ndo, &ip->ip_src), 181 ipaddr_string(ndo, &ip->ip_dst))); 182 } 183 return; 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 ND_TCHECK_16BITS(bp); 371 switch (EXTRACT_16BITS(bp)) { 372 case AFNUM_INET: 373 ND_TCHECK2(*bp, sizeof(struct in_addr)); 374 addrtostr(bp, group_buf, sizeof(group_buf)); 375 bp += sizeof(struct in_addr); 376 break; 377 case AFNUM_INET6: 378 ND_TCHECK2(*bp, sizeof(struct in6_addr)); 379 addrtostr6(bp, group_buf, sizeof(group_buf)); 380 bp += sizeof(struct in6_addr); 381 break; 382 default: 383 goto trunc; 384 break; 385 } 386 387 /* 388 * Options decoding can go here. 389 */ 390 switch (pgm->pgm_type) { 391 case PGM_NAK: 392 ND_PRINT((ndo, "NAK ")); 393 break; 394 case PGM_NULLNAK: 395 ND_PRINT((ndo, "NNAK ")); 396 break; 397 case PGM_NCF: 398 ND_PRINT((ndo, "NCF ")); 399 break; 400 default: 401 break; 402 } 403 ND_PRINT((ndo, "(%s -> %s), seq %u", 404 source_buf, group_buf, EXTRACT_32BITS(&nak->pgmn_seq))); 405 break; 406 } 407 408 case PGM_ACK: { 409 const struct pgm_ack *ack; 410 411 ack = (const struct pgm_ack *)(pgm + 1); 412 ND_TCHECK(*ack); 413 ND_PRINT((ndo, "ACK seq %u", 414 EXTRACT_32BITS(&ack->pgma_rx_max_seq))); 415 bp = (const u_char *) (ack + 1); 416 break; 417 } 418 419 case PGM_SPMR: 420 ND_PRINT((ndo, "SPMR")); 421 break; 422 423 default: 424 ND_PRINT((ndo, "UNKNOWN type 0x%02x", pgm->pgm_type)); 425 break; 426 427 } 428 if (pgm->pgm_options & PGM_OPT_BIT_PRESENT) { 429 430 /* 431 * make sure there's enough for the first option header 432 */ 433 if (!ND_TTEST2(*bp, PGM_MIN_OPT_LEN)) { 434 ND_PRINT((ndo, "[|OPT]")); 435 return; 436 } 437 438 /* 439 * That option header MUST be an OPT_LENGTH option 440 * (see the first paragraph of section 9.1 in RFC 3208). 441 */ 442 opt_type = *bp++; 443 if ((opt_type & PGM_OPT_MASK) != PGM_OPT_LENGTH) { 444 ND_PRINT((ndo, "[First option bad, should be PGM_OPT_LENGTH, is %u]", opt_type & PGM_OPT_MASK)); 445 return; 446 } 447 opt_len = *bp++; 448 if (opt_len != 4) { 449 ND_PRINT((ndo, "[Bad OPT_LENGTH option, length %u != 4]", opt_len)); 450 return; 451 } 452 opts_len = EXTRACT_16BITS(bp); 453 if (opts_len < 4) { 454 ND_PRINT((ndo, "[Bad total option length %u < 4]", opts_len)); 455 return; 456 } 457 bp += sizeof(uint16_t); 458 ND_PRINT((ndo, " OPTS LEN %d", opts_len)); 459 opts_len -= 4; 460 461 while (opts_len) { 462 if (opts_len < PGM_MIN_OPT_LEN) { 463 ND_PRINT((ndo, "[Total option length leaves no room for final option]")); 464 return; 465 } 466 if (!ND_TTEST2(*bp, 2)) { 467 ND_PRINT((ndo, " [|OPT]")); 468 return; 469 } 470 opt_type = *bp++; 471 opt_len = *bp++; 472 if (opt_len < PGM_MIN_OPT_LEN) { 473 ND_PRINT((ndo, "[Bad option, length %u < %u]", opt_len, 474 PGM_MIN_OPT_LEN)); 475 break; 476 } 477 if (opts_len < opt_len) { 478 ND_PRINT((ndo, "[Total option length leaves no room for final option]")); 479 return; 480 } 481 if (!ND_TTEST2(*bp, opt_len - 2)) { 482 ND_PRINT((ndo, " [|OPT]")); 483 return; 484 } 485 486 switch (opt_type & PGM_OPT_MASK) { 487 case PGM_OPT_LENGTH: 488 #define PGM_OPT_LENGTH_LEN (2+2) 489 if (opt_len != PGM_OPT_LENGTH_LEN) { 490 ND_PRINT((ndo, "[Bad OPT_LENGTH option, length %u != %u]", 491 opt_len, PGM_OPT_LENGTH_LEN)); 492 return; 493 } 494 ND_PRINT((ndo, " OPTS LEN (extra?) %d", EXTRACT_16BITS(bp))); 495 bp += 2; 496 opts_len -= PGM_OPT_LENGTH_LEN; 497 break; 498 499 case PGM_OPT_FRAGMENT: 500 #define PGM_OPT_FRAGMENT_LEN (2+2+4+4+4) 501 if (opt_len != PGM_OPT_FRAGMENT_LEN) { 502 ND_PRINT((ndo, "[Bad OPT_FRAGMENT option, length %u != %u]", 503 opt_len, PGM_OPT_FRAGMENT_LEN)); 504 return; 505 } 506 bp += 2; 507 seq = EXTRACT_32BITS(bp); 508 bp += 4; 509 offset = EXTRACT_32BITS(bp); 510 bp += 4; 511 len = EXTRACT_32BITS(bp); 512 bp += 4; 513 ND_PRINT((ndo, " FRAG seq %u off %u len %u", seq, offset, len)); 514 opts_len -= PGM_OPT_FRAGMENT_LEN; 515 break; 516 517 case PGM_OPT_NAK_LIST: 518 bp += 2; 519 opt_len -= 4; /* option header */ 520 ND_PRINT((ndo, " NAK LIST")); 521 while (opt_len) { 522 if (opt_len < 4) { 523 ND_PRINT((ndo, "[Option length not a multiple of 4]")); 524 return; 525 } 526 ND_TCHECK2(*bp, 4); 527 ND_PRINT((ndo, " %u", EXTRACT_32BITS(bp))); 528 bp += 4; 529 opt_len -= 4; 530 opts_len -= 4; 531 } 532 break; 533 534 case PGM_OPT_JOIN: 535 #define PGM_OPT_JOIN_LEN (2+2+4) 536 if (opt_len != PGM_OPT_JOIN_LEN) { 537 ND_PRINT((ndo, "[Bad OPT_JOIN option, length %u != %u]", 538 opt_len, PGM_OPT_JOIN_LEN)); 539 return; 540 } 541 bp += 2; 542 seq = EXTRACT_32BITS(bp); 543 bp += 4; 544 ND_PRINT((ndo, " JOIN %u", seq)); 545 opts_len -= PGM_OPT_JOIN_LEN; 546 break; 547 548 case PGM_OPT_NAK_BO_IVL: 549 #define PGM_OPT_NAK_BO_IVL_LEN (2+2+4+4) 550 if (opt_len != PGM_OPT_NAK_BO_IVL_LEN) { 551 ND_PRINT((ndo, "[Bad OPT_NAK_BO_IVL option, length %u != %u]", 552 opt_len, PGM_OPT_NAK_BO_IVL_LEN)); 553 return; 554 } 555 bp += 2; 556 offset = EXTRACT_32BITS(bp); 557 bp += 4; 558 seq = EXTRACT_32BITS(bp); 559 bp += 4; 560 ND_PRINT((ndo, " BACKOFF ivl %u ivlseq %u", offset, seq)); 561 opts_len -= PGM_OPT_NAK_BO_IVL_LEN; 562 break; 563 564 case PGM_OPT_NAK_BO_RNG: 565 #define PGM_OPT_NAK_BO_RNG_LEN (2+2+4+4) 566 if (opt_len != PGM_OPT_NAK_BO_RNG_LEN) { 567 ND_PRINT((ndo, "[Bad OPT_NAK_BO_RNG option, length %u != %u]", 568 opt_len, PGM_OPT_NAK_BO_RNG_LEN)); 569 return; 570 } 571 bp += 2; 572 offset = EXTRACT_32BITS(bp); 573 bp += 4; 574 seq = EXTRACT_32BITS(bp); 575 bp += 4; 576 ND_PRINT((ndo, " BACKOFF max %u min %u", offset, seq)); 577 opts_len -= PGM_OPT_NAK_BO_RNG_LEN; 578 break; 579 580 case PGM_OPT_REDIRECT: 581 #define PGM_OPT_REDIRECT_FIXED_LEN (2+2+2+2) 582 if (opt_len < PGM_OPT_REDIRECT_FIXED_LEN) { 583 ND_PRINT((ndo, "[Bad OPT_REDIRECT option, length %u < %u]", 584 opt_len, PGM_OPT_REDIRECT_FIXED_LEN)); 585 return; 586 } 587 bp += 2; 588 nla_afnum = EXTRACT_16BITS(bp); 589 bp += 2+2; 590 switch (nla_afnum) { 591 case AFNUM_INET: 592 if (opt_len != PGM_OPT_REDIRECT_FIXED_LEN + sizeof(struct in_addr)) { 593 ND_PRINT((ndo, "[Bad OPT_REDIRECT option, length %u != %u + address size]", 594 opt_len, PGM_OPT_REDIRECT_FIXED_LEN)); 595 return; 596 } 597 ND_TCHECK2(*bp, sizeof(struct in_addr)); 598 addrtostr(bp, nla_buf, sizeof(nla_buf)); 599 bp += sizeof(struct in_addr); 600 opts_len -= PGM_OPT_REDIRECT_FIXED_LEN + sizeof(struct in_addr); 601 break; 602 case AFNUM_INET6: 603 if (opt_len != PGM_OPT_REDIRECT_FIXED_LEN + sizeof(struct in6_addr)) { 604 ND_PRINT((ndo, "[Bad OPT_REDIRECT option, length %u != %u + address size]", 605 PGM_OPT_REDIRECT_FIXED_LEN, opt_len)); 606 return; 607 } 608 ND_TCHECK2(*bp, sizeof(struct in6_addr)); 609 addrtostr6(bp, nla_buf, sizeof(nla_buf)); 610 bp += sizeof(struct in6_addr); 611 opts_len -= PGM_OPT_REDIRECT_FIXED_LEN + sizeof(struct in6_addr); 612 break; 613 default: 614 goto trunc; 615 break; 616 } 617 618 ND_PRINT((ndo, " REDIRECT %s", nla_buf)); 619 break; 620 621 case PGM_OPT_PARITY_PRM: 622 #define PGM_OPT_PARITY_PRM_LEN (2+2+4) 623 if (opt_len != PGM_OPT_PARITY_PRM_LEN) { 624 ND_PRINT((ndo, "[Bad OPT_PARITY_PRM option, length %u != %u]", 625 opt_len, PGM_OPT_PARITY_PRM_LEN)); 626 return; 627 } 628 bp += 2; 629 len = EXTRACT_32BITS(bp); 630 bp += 4; 631 ND_PRINT((ndo, " PARITY MAXTGS %u", len)); 632 opts_len -= PGM_OPT_PARITY_PRM_LEN; 633 break; 634 635 case PGM_OPT_PARITY_GRP: 636 #define PGM_OPT_PARITY_GRP_LEN (2+2+4) 637 if (opt_len != PGM_OPT_PARITY_GRP_LEN) { 638 ND_PRINT((ndo, "[Bad OPT_PARITY_GRP option, length %u != %u]", 639 opt_len, PGM_OPT_PARITY_GRP_LEN)); 640 return; 641 } 642 bp += 2; 643 seq = EXTRACT_32BITS(bp); 644 bp += 4; 645 ND_PRINT((ndo, " PARITY GROUP %u", seq)); 646 opts_len -= PGM_OPT_PARITY_GRP_LEN; 647 break; 648 649 case PGM_OPT_CURR_TGSIZE: 650 #define PGM_OPT_CURR_TGSIZE_LEN (2+2+4) 651 if (opt_len != PGM_OPT_CURR_TGSIZE_LEN) { 652 ND_PRINT((ndo, "[Bad OPT_CURR_TGSIZE option, length %u != %u]", 653 opt_len, PGM_OPT_CURR_TGSIZE_LEN)); 654 return; 655 } 656 bp += 2; 657 len = EXTRACT_32BITS(bp); 658 bp += 4; 659 ND_PRINT((ndo, " PARITY ATGS %u", len)); 660 opts_len -= PGM_OPT_CURR_TGSIZE_LEN; 661 break; 662 663 case PGM_OPT_NBR_UNREACH: 664 #define PGM_OPT_NBR_UNREACH_LEN (2+2) 665 if (opt_len != PGM_OPT_NBR_UNREACH_LEN) { 666 ND_PRINT((ndo, "[Bad OPT_NBR_UNREACH option, length %u != %u]", 667 opt_len, PGM_OPT_NBR_UNREACH_LEN)); 668 return; 669 } 670 bp += 2; 671 ND_PRINT((ndo, " NBR_UNREACH")); 672 opts_len -= PGM_OPT_NBR_UNREACH_LEN; 673 break; 674 675 case PGM_OPT_PATH_NLA: 676 ND_PRINT((ndo, " PATH_NLA [%d]", opt_len)); 677 bp += opt_len; 678 opts_len -= opt_len; 679 break; 680 681 case PGM_OPT_SYN: 682 #define PGM_OPT_SYN_LEN (2+2) 683 if (opt_len != PGM_OPT_SYN_LEN) { 684 ND_PRINT((ndo, "[Bad OPT_SYN option, length %u != %u]", 685 opt_len, PGM_OPT_SYN_LEN)); 686 return; 687 } 688 bp += 2; 689 ND_PRINT((ndo, " SYN")); 690 opts_len -= PGM_OPT_SYN_LEN; 691 break; 692 693 case PGM_OPT_FIN: 694 #define PGM_OPT_FIN_LEN (2+2) 695 if (opt_len != PGM_OPT_FIN_LEN) { 696 ND_PRINT((ndo, "[Bad OPT_FIN option, length %u != %u]", 697 opt_len, PGM_OPT_FIN_LEN)); 698 return; 699 } 700 bp += 2; 701 ND_PRINT((ndo, " FIN")); 702 opts_len -= PGM_OPT_FIN_LEN; 703 break; 704 705 case PGM_OPT_RST: 706 #define PGM_OPT_RST_LEN (2+2) 707 if (opt_len != PGM_OPT_RST_LEN) { 708 ND_PRINT((ndo, "[Bad OPT_RST option, length %u != %u]", 709 opt_len, PGM_OPT_RST_LEN)); 710 return; 711 } 712 bp += 2; 713 ND_PRINT((ndo, " RST")); 714 opts_len -= PGM_OPT_RST_LEN; 715 break; 716 717 case PGM_OPT_CR: 718 ND_PRINT((ndo, " CR")); 719 bp += opt_len; 720 opts_len -= opt_len; 721 break; 722 723 case PGM_OPT_CRQST: 724 #define PGM_OPT_CRQST_LEN (2+2) 725 if (opt_len != PGM_OPT_CRQST_LEN) { 726 ND_PRINT((ndo, "[Bad OPT_CRQST option, length %u != %u]", 727 opt_len, PGM_OPT_CRQST_LEN)); 728 return; 729 } 730 bp += 2; 731 ND_PRINT((ndo, " CRQST")); 732 opts_len -= PGM_OPT_CRQST_LEN; 733 break; 734 735 case PGM_OPT_PGMCC_DATA: 736 #define PGM_OPT_PGMCC_DATA_FIXED_LEN (2+2+4+2+2) 737 if (opt_len < PGM_OPT_PGMCC_DATA_FIXED_LEN) { 738 ND_PRINT((ndo, "[Bad OPT_PGMCC_DATA option, length %u < %u]", 739 opt_len, PGM_OPT_PGMCC_DATA_FIXED_LEN)); 740 return; 741 } 742 bp += 2; 743 offset = EXTRACT_32BITS(bp); 744 bp += 4; 745 nla_afnum = EXTRACT_16BITS(bp); 746 bp += 2+2; 747 switch (nla_afnum) { 748 case AFNUM_INET: 749 if (opt_len != PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(struct in_addr)) { 750 ND_PRINT((ndo, "[Bad OPT_PGMCC_DATA option, length %u != %u + address size]", 751 opt_len, PGM_OPT_PGMCC_DATA_FIXED_LEN)); 752 return; 753 } 754 ND_TCHECK2(*bp, sizeof(struct in_addr)); 755 addrtostr(bp, nla_buf, sizeof(nla_buf)); 756 bp += sizeof(struct in_addr); 757 opts_len -= PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(struct in_addr); 758 break; 759 case AFNUM_INET6: 760 if (opt_len != PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(struct in6_addr)) { 761 ND_PRINT((ndo, "[Bad OPT_PGMCC_DATA option, length %u != %u + address size]", 762 opt_len, PGM_OPT_PGMCC_DATA_FIXED_LEN)); 763 return; 764 } 765 ND_TCHECK2(*bp, sizeof(struct in6_addr)); 766 addrtostr6(bp, nla_buf, sizeof(nla_buf)); 767 bp += sizeof(struct in6_addr); 768 opts_len -= PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(struct in6_addr); 769 break; 770 default: 771 goto trunc; 772 break; 773 } 774 775 ND_PRINT((ndo, " PGMCC DATA %u %s", offset, nla_buf)); 776 break; 777 778 case PGM_OPT_PGMCC_FEEDBACK: 779 #define PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN (2+2+4+2+2) 780 if (opt_len < PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN) { 781 ND_PRINT((ndo, "[Bad PGM_OPT_PGMCC_FEEDBACK option, length %u < %u]", 782 opt_len, PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN)); 783 return; 784 } 785 bp += 2; 786 offset = EXTRACT_32BITS(bp); 787 bp += 4; 788 nla_afnum = EXTRACT_16BITS(bp); 789 bp += 2+2; 790 switch (nla_afnum) { 791 case AFNUM_INET: 792 if (opt_len != PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(struct in_addr)) { 793 ND_PRINT((ndo, "[Bad OPT_PGMCC_FEEDBACK option, length %u != %u + address size]", 794 opt_len, PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN)); 795 return; 796 } 797 ND_TCHECK2(*bp, sizeof(struct in_addr)); 798 addrtostr(bp, nla_buf, sizeof(nla_buf)); 799 bp += sizeof(struct in_addr); 800 opts_len -= PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(struct in_addr); 801 break; 802 case AFNUM_INET6: 803 if (opt_len != PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(struct in6_addr)) { 804 ND_PRINT((ndo, "[Bad OPT_PGMCC_FEEDBACK option, length %u != %u + address size]", 805 opt_len, PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN)); 806 return; 807 } 808 ND_TCHECK2(*bp, sizeof(struct in6_addr)); 809 addrtostr6(bp, nla_buf, sizeof(nla_buf)); 810 bp += sizeof(struct in6_addr); 811 opts_len -= PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(struct in6_addr); 812 break; 813 default: 814 goto trunc; 815 break; 816 } 817 818 ND_PRINT((ndo, " PGMCC FEEDBACK %u %s", offset, nla_buf)); 819 break; 820 821 default: 822 ND_PRINT((ndo, " OPT_%02X [%d] ", opt_type, opt_len)); 823 bp += opt_len; 824 opts_len -= opt_len; 825 break; 826 } 827 828 if (opt_type & PGM_OPT_END) 829 break; 830 } 831 } 832 833 ND_PRINT((ndo, " [%u]", length)); 834 if (ndo->ndo_packettype == PT_PGM_ZMTP1 && 835 (pgm->pgm_type == PGM_ODATA || pgm->pgm_type == PGM_RDATA)) 836 zmtp1_print_datagram(ndo, bp, EXTRACT_16BITS(&pgm->pgm_length)); 837 838 return; 839 840 trunc: 841 ND_PRINT((ndo, "[|pgm]")); 842 if (ch != '\0') 843 ND_PRINT((ndo, ">")); 844 } 845