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