etc/services - sync with NetBSD-8
[minix.git] / external / bsd / tcpdump / dist / print-pgm.c
blobc7a9dc153b8cd5ede086d4bee9491d444d6ba29c
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.
13 * Original code by Andy Heffernan (ahh@juniper.net)
16 #include <sys/cdefs.h>
17 #ifndef lint
18 __RCSID("$NetBSD: print-pgm.c,v 1.6 2014/11/20 03:05:03 christos Exp $");
19 #endif
21 #define NETDISSECT_REWORKED
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
26 #include <tcpdump-stdinc.h>
28 #include "interface.h"
29 #include "extract.h"
30 #include "addrtoname.h"
32 #include "ip.h"
33 #ifdef INET6
34 #include "ip6.h"
35 #endif
36 #include "ipproto.h"
37 #include "af.h"
40 * PGM header (RFC 3208)
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;
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 */
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 */
73 struct pgm_ack {
74 uint32_t pgma_rx_max_seq;
75 uint32_t pgma_bitmap;
76 /* ... options */
79 struct pgm_poll {
80 uint32_t pgmp_seq;
81 uint16_t pgmp_round;
82 uint16_t pgmp_reserved;
83 /* ... options */
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 */
96 struct pgm_data {
97 uint32_t pgmd_seq;
98 uint32_t pgmd_trailseq;
99 /* ... options */
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;
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
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
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
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
141 #define PGM_OPT_PGMCC_DATA 0x12
142 #define PGM_OPT_PGMCC_FEEDBACK 0x13
144 #define PGM_OPT_MASK 0x7f
146 #define PGM_OPT_END 0x80 /* end of options marker */
148 #define PGM_MIN_OPT_LEN 4
150 void
151 pgm_print(netdissect_options *ndo,
152 register const u_char *bp, register u_int length,
153 register const u_char *bp2)
155 register const struct pgm_header *pgm;
156 register const struct ip *ip;
157 register char ch;
158 uint16_t sport, dport;
159 int addr_size;
160 const void *nla;
161 int nla_af;
162 #ifdef INET6
163 char nla_buf[INET6_ADDRSTRLEN];
164 register const struct ip6_hdr *ip6;
165 #else
166 char nla_buf[INET_ADDRSTRLEN];
167 #endif
168 uint8_t opt_type, opt_len;
169 uint32_t seq, opts_len, len, offset;
171 pgm = (struct pgm_header *)bp;
172 ip = (struct ip *)bp2;
173 #ifdef INET6
174 if (IP_V(ip) == 6)
175 ip6 = (struct ip6_hdr *)bp2;
176 else
177 ip6 = NULL;
178 #else /* INET6 */
179 if (IP_V(ip) == 6) {
180 ND_PRINT((ndo, "Can't handle IPv6"));
181 return;
183 #endif /* INET6 */
184 ch = '\0';
185 if (!ND_TTEST(pgm->pgm_dport)) {
186 #ifdef INET6
187 if (ip6) {
188 ND_PRINT((ndo, "%s > %s: [|pgm]",
189 ip6addr_string(ndo, &ip6->ip6_src),
190 ip6addr_string(ndo, &ip6->ip6_dst)));
191 return;
192 } else
193 #endif /* INET6 */
195 ND_PRINT((ndo, "%s > %s: [|pgm]",
196 ipaddr_string(ndo, &ip->ip_src),
197 ipaddr_string(ndo, &ip->ip_dst)));
198 return;
202 sport = EXTRACT_16BITS(&pgm->pgm_sport);
203 dport = EXTRACT_16BITS(&pgm->pgm_dport);
205 #ifdef INET6
206 if (ip6) {
207 if (ip6->ip6_nxt == IPPROTO_PGM) {
208 ND_PRINT((ndo, "%s.%s > %s.%s: ",
209 ip6addr_string(ndo, &ip6->ip6_src),
210 tcpport_string(sport),
211 ip6addr_string(ndo, &ip6->ip6_dst),
212 tcpport_string(dport)));
213 } else {
214 ND_PRINT((ndo, "%s > %s: ",
215 tcpport_string(sport), tcpport_string(dport)));
217 } else
218 #endif /*INET6*/
220 if (ip->ip_p == IPPROTO_PGM) {
221 ND_PRINT((ndo, "%s.%s > %s.%s: ",
222 ipaddr_string(ndo, &ip->ip_src),
223 tcpport_string(sport),
224 ipaddr_string(ndo, &ip->ip_dst),
225 tcpport_string(dport)));
226 } else {
227 ND_PRINT((ndo, "%s > %s: ",
228 tcpport_string(sport), tcpport_string(dport)));
232 ND_TCHECK(*pgm);
234 ND_PRINT((ndo, "PGM, length %u", EXTRACT_16BITS(&pgm->pgm_length)));
236 if (!ndo->ndo_vflag)
237 return;
239 ND_PRINT((ndo, " 0x%02x%02x%02x%02x%02x%02x ",
240 pgm->pgm_gsid[0],
241 pgm->pgm_gsid[1],
242 pgm->pgm_gsid[2],
243 pgm->pgm_gsid[3],
244 pgm->pgm_gsid[4],
245 pgm->pgm_gsid[5]));
246 switch (pgm->pgm_type) {
247 case PGM_SPM: {
248 struct pgm_spm *spm;
250 spm = (struct pgm_spm *)(pgm + 1);
251 ND_TCHECK(*spm);
253 switch (EXTRACT_16BITS(&spm->pgms_nla_afi)) {
254 case AFNUM_INET:
255 addr_size = sizeof(struct in_addr);
256 nla_af = AF_INET;
257 break;
258 #ifdef INET6
259 case AFNUM_INET6:
260 addr_size = sizeof(struct in6_addr);
261 nla_af = AF_INET6;
262 break;
263 #endif
264 default:
265 goto trunc;
266 break;
268 bp = (u_char *) (spm + 1);
269 ND_TCHECK2(*bp, addr_size);
270 nla = bp;
271 bp += addr_size;
273 inet_ntop(nla_af, nla, nla_buf, sizeof(nla_buf));
274 ND_PRINT((ndo, "SPM seq %u trail %u lead %u nla %s",
275 EXTRACT_32BITS(&spm->pgms_seq),
276 EXTRACT_32BITS(&spm->pgms_trailseq),
277 EXTRACT_32BITS(&spm->pgms_leadseq),
278 nla_buf));
279 break;
282 case PGM_POLL: {
283 struct pgm_poll *poll;
285 poll = (struct pgm_poll *)(pgm + 1);
286 ND_TCHECK(*poll);
287 ND_PRINT((ndo, "POLL seq %u round %u",
288 EXTRACT_32BITS(&poll->pgmp_seq),
289 EXTRACT_16BITS(&poll->pgmp_round)));
290 bp = (u_char *) (poll + 1);
291 break;
293 case PGM_POLR: {
294 struct pgm_polr *polr;
295 uint32_t ivl, rnd, mask;
297 polr = (struct pgm_polr *)(pgm + 1);
298 ND_TCHECK(*polr);
300 switch (EXTRACT_16BITS(&polr->pgmp_nla_afi)) {
301 case AFNUM_INET:
302 addr_size = sizeof(struct in_addr);
303 nla_af = AF_INET;
304 break;
305 #ifdef INET6
306 case AFNUM_INET6:
307 addr_size = sizeof(struct in6_addr);
308 nla_af = AF_INET6;
309 break;
310 #endif
311 default:
312 goto trunc;
313 break;
315 bp = (u_char *) (polr + 1);
316 ND_TCHECK2(*bp, addr_size);
317 nla = bp;
318 bp += addr_size;
320 inet_ntop(nla_af, nla, nla_buf, sizeof(nla_buf));
322 ND_TCHECK2(*bp, sizeof(uint32_t));
323 ivl = EXTRACT_32BITS(bp);
324 bp += sizeof(uint32_t);
326 ND_TCHECK2(*bp, sizeof(uint32_t));
327 rnd = EXTRACT_32BITS(bp);
328 bp += sizeof(uint32_t);
330 ND_TCHECK2(*bp, sizeof(uint32_t));
331 mask = EXTRACT_32BITS(bp);
332 bp += sizeof(uint32_t);
334 ND_PRINT((ndo, "POLR seq %u round %u nla %s ivl %u rnd 0x%08x "
335 "mask 0x%08x", EXTRACT_32BITS(&polr->pgmp_seq),
336 EXTRACT_16BITS(&polr->pgmp_round), nla_buf, ivl, rnd, mask));
337 break;
339 case PGM_ODATA: {
340 struct pgm_data *odata;
342 odata = (struct pgm_data *)(pgm + 1);
343 ND_TCHECK(*odata);
344 ND_PRINT((ndo, "ODATA trail %u seq %u",
345 EXTRACT_32BITS(&odata->pgmd_trailseq),
346 EXTRACT_32BITS(&odata->pgmd_seq)));
347 bp = (u_char *) (odata + 1);
348 break;
351 case PGM_RDATA: {
352 struct pgm_data *rdata;
354 rdata = (struct pgm_data *)(pgm + 1);
355 ND_TCHECK(*rdata);
356 ND_PRINT((ndo, "RDATA trail %u seq %u",
357 EXTRACT_32BITS(&rdata->pgmd_trailseq),
358 EXTRACT_32BITS(&rdata->pgmd_seq)));
359 bp = (u_char *) (rdata + 1);
360 break;
363 case PGM_NAK:
364 case PGM_NULLNAK:
365 case PGM_NCF: {
366 struct pgm_nak *nak;
367 const void *source, *group;
368 int source_af, group_af;
369 #ifdef INET6
370 char source_buf[INET6_ADDRSTRLEN], group_buf[INET6_ADDRSTRLEN];
371 #else
372 char source_buf[INET_ADDRSTRLEN], group_buf[INET_ADDRSTRLEN];
373 #endif
375 nak = (struct pgm_nak *)(pgm + 1);
376 ND_TCHECK(*nak);
379 * Skip past the source, saving info along the way
380 * and stopping if we don't have enough.
382 switch (EXTRACT_16BITS(&nak->pgmn_source_afi)) {
383 case AFNUM_INET:
384 addr_size = sizeof(struct in_addr);
385 source_af = AF_INET;
386 break;
387 #ifdef INET6
388 case AFNUM_INET6:
389 addr_size = sizeof(struct in6_addr);
390 source_af = AF_INET6;
391 break;
392 #endif
393 default:
394 goto trunc;
395 break;
397 bp = (u_char *) (nak + 1);
398 ND_TCHECK2(*bp, addr_size);
399 source = bp;
400 bp += addr_size;
403 * Skip past the group, saving info along the way
404 * and stopping if we don't have enough.
406 switch (EXTRACT_16BITS(bp)) {
407 case AFNUM_INET:
408 addr_size = sizeof(struct in_addr);
409 group_af = AF_INET;
410 break;
411 #ifdef INET6
412 case AFNUM_INET6:
413 addr_size = sizeof(struct in6_addr);
414 group_af = AF_INET6;
415 break;
416 #endif
417 default:
418 goto trunc;
419 break;
421 bp += (2 * sizeof(uint16_t));
422 ND_TCHECK2(*bp, addr_size);
423 group = bp;
424 bp += addr_size;
427 * Options decoding can go here.
429 inet_ntop(source_af, source, source_buf, sizeof(source_buf));
430 inet_ntop(group_af, group, group_buf, sizeof(group_buf));
431 switch (pgm->pgm_type) {
432 case PGM_NAK:
433 ND_PRINT((ndo, "NAK "));
434 break;
435 case PGM_NULLNAK:
436 ND_PRINT((ndo, "NNAK "));
437 break;
438 case PGM_NCF:
439 ND_PRINT((ndo, "NCF "));
440 break;
441 default:
442 break;
444 ND_PRINT((ndo, "(%s -> %s), seq %u",
445 source_buf, group_buf, EXTRACT_32BITS(&nak->pgmn_seq)));
446 break;
449 case PGM_ACK: {
450 struct pgm_ack *ack;
452 ack = (struct pgm_ack *)(pgm + 1);
453 ND_TCHECK(*ack);
454 ND_PRINT((ndo, "ACK seq %u",
455 EXTRACT_32BITS(&ack->pgma_rx_max_seq)));
456 bp = (u_char *) (ack + 1);
457 break;
460 case PGM_SPMR:
461 ND_PRINT((ndo, "SPMR"));
462 break;
464 default:
465 ND_PRINT((ndo, "UNKNOWN type 0x%02x", pgm->pgm_type));
466 break;
469 if (pgm->pgm_options & PGM_OPT_BIT_PRESENT) {
472 * make sure there's enough for the first option header
474 if (!ND_TTEST2(*bp, PGM_MIN_OPT_LEN)) {
475 ND_PRINT((ndo, "[|OPT]"));
476 return;
480 * That option header MUST be an OPT_LENGTH option
481 * (see the first paragraph of section 9.1 in RFC 3208).
483 opt_type = *bp++;
484 if ((opt_type & PGM_OPT_MASK) != PGM_OPT_LENGTH) {
485 ND_PRINT((ndo, "[First option bad, should be PGM_OPT_LENGTH, is %u]", opt_type & PGM_OPT_MASK));
486 return;
488 opt_len = *bp++;
489 if (opt_len != 4) {
490 ND_PRINT((ndo, "[Bad OPT_LENGTH option, length %u != 4]", opt_len));
491 return;
493 opts_len = EXTRACT_16BITS(bp);
494 if (opts_len < 4) {
495 ND_PRINT((ndo, "[Bad total option length %u < 4]", opts_len));
496 return;
498 bp += sizeof(uint16_t);
499 ND_PRINT((ndo, " OPTS LEN %d", opts_len));
500 opts_len -= 4;
502 while (opts_len) {
503 if (opts_len < PGM_MIN_OPT_LEN) {
504 ND_PRINT((ndo, "[Total option length leaves no room for final option]"));
505 return;
507 opt_type = *bp++;
508 opt_len = *bp++;
509 if (opt_len < PGM_MIN_OPT_LEN) {
510 ND_PRINT((ndo, "[Bad option, length %u < %u]", opt_len,
511 PGM_MIN_OPT_LEN));
512 break;
514 if (opts_len < opt_len) {
515 ND_PRINT((ndo, "[Total option length leaves no room for final option]"));
516 return;
518 if (!ND_TTEST2(*bp, opt_len - 2)) {
519 ND_PRINT((ndo, " [|OPT]"));
520 return;
523 switch (opt_type & PGM_OPT_MASK) {
524 case PGM_OPT_LENGTH:
525 if (opt_len != 4) {
526 ND_PRINT((ndo, "[Bad OPT_LENGTH option, length %u != 4]", opt_len));
527 return;
529 ND_PRINT((ndo, " OPTS LEN (extra?) %d", EXTRACT_16BITS(bp)));
530 bp += sizeof(uint16_t);
531 opts_len -= 4;
532 break;
534 case PGM_OPT_FRAGMENT:
535 if (opt_len != 16) {
536 ND_PRINT((ndo, "[Bad OPT_FRAGMENT option, length %u != 16]", opt_len));
537 return;
539 bp += 2;
540 seq = EXTRACT_32BITS(bp);
541 bp += sizeof(uint32_t);
542 offset = EXTRACT_32BITS(bp);
543 bp += sizeof(uint32_t);
544 len = EXTRACT_32BITS(bp);
545 bp += sizeof(uint32_t);
546 ND_PRINT((ndo, " FRAG seq %u off %u len %u", seq, offset, len));
547 opts_len -= 16;
548 break;
550 case PGM_OPT_NAK_LIST:
551 bp += 2;
552 opt_len -= sizeof(uint32_t); /* option header */
553 ND_PRINT((ndo, " NAK LIST"));
554 while (opt_len) {
555 if (opt_len < sizeof(uint32_t)) {
556 ND_PRINT((ndo, "[Option length not a multiple of 4]"));
557 return;
559 ND_TCHECK2(*bp, sizeof(uint32_t));
560 ND_PRINT((ndo, " %u", EXTRACT_32BITS(bp)));
561 bp += sizeof(uint32_t);
562 opt_len -= sizeof(uint32_t);
563 opts_len -= sizeof(uint32_t);
565 break;
567 case PGM_OPT_JOIN:
568 if (opt_len != 8) {
569 ND_PRINT((ndo, "[Bad OPT_JOIN option, length %u != 8]", opt_len));
570 return;
572 bp += 2;
573 seq = EXTRACT_32BITS(bp);
574 bp += sizeof(uint32_t);
575 ND_PRINT((ndo, " JOIN %u", seq));
576 opts_len -= 8;
577 break;
579 case PGM_OPT_NAK_BO_IVL:
580 if (opt_len != 12) {
581 ND_PRINT((ndo, "[Bad OPT_NAK_BO_IVL option, length %u != 12]", opt_len));
582 return;
584 bp += 2;
585 offset = EXTRACT_32BITS(bp);
586 bp += sizeof(uint32_t);
587 seq = EXTRACT_32BITS(bp);
588 bp += sizeof(uint32_t);
589 ND_PRINT((ndo, " BACKOFF ivl %u ivlseq %u", offset, seq));
590 opts_len -= 12;
591 break;
593 case PGM_OPT_NAK_BO_RNG:
594 if (opt_len != 12) {
595 ND_PRINT((ndo, "[Bad OPT_NAK_BO_RNG option, length %u != 12]", opt_len));
596 return;
598 bp += 2;
599 offset = EXTRACT_32BITS(bp);
600 bp += sizeof(uint32_t);
601 seq = EXTRACT_32BITS(bp);
602 bp += sizeof(uint32_t);
603 ND_PRINT((ndo, " BACKOFF max %u min %u", offset, seq));
604 opts_len -= 12;
605 break;
607 case PGM_OPT_REDIRECT:
608 bp += 2;
609 switch (EXTRACT_16BITS(bp)) {
610 case AFNUM_INET:
611 addr_size = sizeof(struct in_addr);
612 nla_af = AF_INET;
613 break;
614 #ifdef INET6
615 case AFNUM_INET6:
616 addr_size = sizeof(struct in6_addr);
617 nla_af = AF_INET6;
618 break;
619 #endif
620 default:
621 goto trunc;
622 break;
624 bp += (2 * sizeof(uint16_t));
625 if (opt_len != 4 + addr_size) {
626 ND_PRINT((ndo, "[Bad OPT_REDIRECT option, length %u != 4 + address size]", opt_len));
627 return;
629 ND_TCHECK2(*bp, addr_size);
630 nla = bp;
631 bp += addr_size;
633 inet_ntop(nla_af, nla, nla_buf, sizeof(nla_buf));
634 ND_PRINT((ndo, " REDIRECT %s", (char *)nla));
635 opts_len -= 4 + addr_size;
636 break;
638 case PGM_OPT_PARITY_PRM:
639 if (opt_len != 8) {
640 ND_PRINT((ndo, "[Bad OPT_PARITY_PRM option, length %u != 8]", opt_len));
641 return;
643 bp += 2;
644 len = EXTRACT_32BITS(bp);
645 bp += sizeof(uint32_t);
646 ND_PRINT((ndo, " PARITY MAXTGS %u", len));
647 opts_len -= 8;
648 break;
650 case PGM_OPT_PARITY_GRP:
651 if (opt_len != 8) {
652 ND_PRINT((ndo, "[Bad OPT_PARITY_GRP option, length %u != 8]", opt_len));
653 return;
655 bp += 2;
656 seq = EXTRACT_32BITS(bp);
657 bp += sizeof(uint32_t);
658 ND_PRINT((ndo, " PARITY GROUP %u", seq));
659 opts_len -= 8;
660 break;
662 case PGM_OPT_CURR_TGSIZE:
663 if (opt_len != 8) {
664 ND_PRINT((ndo, "[Bad OPT_CURR_TGSIZE option, length %u != 8]", opt_len));
665 return;
667 bp += 2;
668 len = EXTRACT_32BITS(bp);
669 bp += sizeof(uint32_t);
670 ND_PRINT((ndo, " PARITY ATGS %u", len));
671 opts_len -= 8;
672 break;
674 case PGM_OPT_NBR_UNREACH:
675 if (opt_len != 4) {
676 ND_PRINT((ndo, "[Bad OPT_NBR_UNREACH option, length %u != 4]", opt_len));
677 return;
679 bp += 2;
680 ND_PRINT((ndo, " NBR_UNREACH"));
681 opts_len -= 4;
682 break;
684 case PGM_OPT_PATH_NLA:
685 ND_PRINT((ndo, " PATH_NLA [%d]", opt_len));
686 bp += opt_len;
687 opts_len -= opt_len;
688 break;
690 case PGM_OPT_SYN:
691 if (opt_len != 4) {
692 ND_PRINT((ndo, "[Bad OPT_SYN option, length %u != 4]", opt_len));
693 return;
695 bp += 2;
696 ND_PRINT((ndo, " SYN"));
697 opts_len -= 4;
698 break;
700 case PGM_OPT_FIN:
701 if (opt_len != 4) {
702 ND_PRINT((ndo, "[Bad OPT_FIN option, length %u != 4]", opt_len));
703 return;
705 bp += 2;
706 ND_PRINT((ndo, " FIN"));
707 opts_len -= 4;
708 break;
710 case PGM_OPT_RST:
711 if (opt_len != 4) {
712 ND_PRINT((ndo, "[Bad OPT_RST option, length %u != 4]", opt_len));
713 return;
715 bp += 2;
716 ND_PRINT((ndo, " RST"));
717 opts_len -= 4;
718 break;
720 case PGM_OPT_CR:
721 ND_PRINT((ndo, " CR"));
722 bp += opt_len;
723 opts_len -= opt_len;
724 break;
726 case PGM_OPT_CRQST:
727 if (opt_len != 4) {
728 ND_PRINT((ndo, "[Bad OPT_CRQST option, length %u != 4]", opt_len));
729 return;
731 bp += 2;
732 ND_PRINT((ndo, " CRQST"));
733 opts_len -= 4;
734 break;
736 case PGM_OPT_PGMCC_DATA:
737 bp += 2;
738 offset = EXTRACT_32BITS(bp);
739 bp += sizeof(uint32_t);
740 switch (EXTRACT_16BITS(bp)) {
741 case AFNUM_INET:
742 addr_size = sizeof(struct in_addr);
743 nla_af = AF_INET;
744 break;
745 #ifdef INET6
746 case AFNUM_INET6:
747 addr_size = sizeof(struct in6_addr);
748 nla_af = AF_INET6;
749 break;
750 #endif
751 default:
752 goto trunc;
753 break;
755 bp += (2 * sizeof(uint16_t));
756 if (opt_len != 12 + addr_size) {
757 ND_PRINT((ndo, "[Bad OPT_PGMCC_DATA option, length %u != 12 + address size]", opt_len));
758 return;
760 ND_TCHECK2(*bp, addr_size);
761 nla = bp;
762 bp += addr_size;
764 inet_ntop(nla_af, nla, nla_buf, sizeof(nla_buf));
765 ND_PRINT((ndo, " PGMCC DATA %u %s", offset, (char*)nla));
766 opts_len -= 16;
767 break;
769 case PGM_OPT_PGMCC_FEEDBACK:
770 bp += 2;
771 offset = EXTRACT_32BITS(bp);
772 bp += sizeof(uint32_t);
773 switch (EXTRACT_16BITS(bp)) {
774 case AFNUM_INET:
775 addr_size = sizeof(struct in_addr);
776 nla_af = AF_INET;
777 break;
778 #ifdef INET6
779 case AFNUM_INET6:
780 addr_size = sizeof(struct in6_addr);
781 nla_af = AF_INET6;
782 break;
783 #endif
784 default:
785 goto trunc;
786 break;
788 bp += (2 * sizeof(uint16_t));
789 if (opt_len != 12 + addr_size) {
790 ND_PRINT((ndo, "[Bad OPT_PGMCC_FEEDBACK option, length %u != 12 + address size]", opt_len));
791 return;
793 ND_TCHECK2(*bp, addr_size);
794 nla = bp;
795 bp += addr_size;
797 inet_ntop(nla_af, nla, nla_buf, sizeof(nla_buf));
798 ND_PRINT((ndo, " PGMCC FEEDBACK %u %s", offset, (char*)nla));
799 opts_len -= 16;
800 break;
802 default:
803 ND_PRINT((ndo, " OPT_%02X [%d] ", opt_type, opt_len));
804 bp += opt_len;
805 opts_len -= opt_len;
806 break;
809 if (opt_type & PGM_OPT_END)
810 break;
814 ND_PRINT((ndo, " [%u]", length));
815 if (ndo->ndo_packettype == PT_PGM_ZMTP1 &&
816 (pgm->pgm_type == PGM_ODATA || pgm->pgm_type == PGM_RDATA))
817 zmtp1_print_datagram(ndo, bp, EXTRACT_16BITS(&pgm->pgm_length));
819 return;
821 trunc:
822 ND_PRINT((ndo, "[|pgm]"));
823 if (ch != '\0')
824 ND_PRINT((ndo, ">"));