]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/print-pgm.c
Optionally bind ktls threads to NUMA domains
[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 /* \summary: Pragmatic General Multicast (PGM) printer */
17
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21
22 #include <netdissect-stdinc.h>
23
24 #include "netdissect.h"
25 #include "extract.h"
26 #include "addrtoname.h"
27 #include "addrtostr.h"
28
29 #include "ip.h"
30 #include "ip6.h"
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         u_int nla_afnum;
155         char nla_buf[INET6_ADDRSTRLEN];
156         register const struct ip6_hdr *ip6;
157         uint8_t opt_type, opt_len;
158         uint32_t seq, opts_len, len, offset;
159
160         pgm = (const struct pgm_header *)bp;
161         ip = (const struct ip *)bp2;
162         if (IP_V(ip) == 6)
163                 ip6 = (const struct ip6_hdr *)bp2;
164         else
165                 ip6 = NULL;
166         ch = '\0';
167         if (!ND_TTEST(pgm->pgm_dport)) {
168                 if (ip6) {
169                         ND_PRINT((ndo, "%s > %s: [|pgm]",
170                                 ip6addr_string(ndo, &ip6->ip6_src),
171                                 ip6addr_string(ndo, &ip6->ip6_dst)));
172                 } else {
173                         ND_PRINT((ndo, "%s > %s: [|pgm]",
174                                 ipaddr_string(ndo, &ip->ip_src),
175                                 ipaddr_string(ndo, &ip->ip_dst)));
176                 }
177                 return;
178         }
179
180         sport = EXTRACT_16BITS(&pgm->pgm_sport);
181         dport = EXTRACT_16BITS(&pgm->pgm_dport);
182
183         if (ip6) {
184                 if (ip6->ip6_nxt == IPPROTO_PGM) {
185                         ND_PRINT((ndo, "%s.%s > %s.%s: ",
186                                 ip6addr_string(ndo, &ip6->ip6_src),
187                                 tcpport_string(ndo, sport),
188                                 ip6addr_string(ndo, &ip6->ip6_dst),
189                                 tcpport_string(ndo, dport)));
190                 } else {
191                         ND_PRINT((ndo, "%s > %s: ",
192                                 tcpport_string(ndo, sport), tcpport_string(ndo, dport)));
193                 }
194         } else {
195                 if (ip->ip_p == IPPROTO_PGM) {
196                         ND_PRINT((ndo, "%s.%s > %s.%s: ",
197                                 ipaddr_string(ndo, &ip->ip_src),
198                                 tcpport_string(ndo, sport),
199                                 ipaddr_string(ndo, &ip->ip_dst),
200                                 tcpport_string(ndo, dport)));
201                 } else {
202                         ND_PRINT((ndo, "%s > %s: ",
203                                 tcpport_string(ndo, sport), tcpport_string(ndo, dport)));
204                 }
205         }
206
207         ND_TCHECK(*pgm);
208
209         ND_PRINT((ndo, "PGM, length %u", EXTRACT_16BITS(&pgm->pgm_length)));
210
211         if (!ndo->ndo_vflag)
212             return;
213
214         ND_PRINT((ndo, " 0x%02x%02x%02x%02x%02x%02x ",
215                      pgm->pgm_gsid[0],
216                      pgm->pgm_gsid[1],
217                      pgm->pgm_gsid[2],
218                      pgm->pgm_gsid[3],
219                      pgm->pgm_gsid[4],
220                      pgm->pgm_gsid[5]));
221         switch (pgm->pgm_type) {
222         case PGM_SPM: {
223             const struct pgm_spm *spm;
224
225             spm = (const struct pgm_spm *)(pgm + 1);
226             ND_TCHECK(*spm);
227             bp = (const u_char *) (spm + 1);
228
229             switch (EXTRACT_16BITS(&spm->pgms_nla_afi)) {
230             case AFNUM_INET:
231                 ND_TCHECK2(*bp, sizeof(struct in_addr));
232                 addrtostr(bp, nla_buf, sizeof(nla_buf));
233                 bp += sizeof(struct in_addr);
234                 break;
235             case AFNUM_INET6:
236                 ND_TCHECK2(*bp, sizeof(struct in6_addr));
237                 addrtostr6(bp, nla_buf, sizeof(nla_buf));
238                 bp += sizeof(struct in6_addr);
239                 break;
240             default:
241                 goto trunc;
242                 break;
243             }
244
245             ND_PRINT((ndo, "SPM seq %u trail %u lead %u nla %s",
246                          EXTRACT_32BITS(&spm->pgms_seq),
247                          EXTRACT_32BITS(&spm->pgms_trailseq),
248                          EXTRACT_32BITS(&spm->pgms_leadseq),
249                          nla_buf));
250             break;
251         }
252
253         case PGM_POLL: {
254             const struct pgm_poll *poll_msg;
255
256             poll_msg = (const struct pgm_poll *)(pgm + 1);
257             ND_TCHECK(*poll_msg);
258             ND_PRINT((ndo, "POLL seq %u round %u",
259                          EXTRACT_32BITS(&poll_msg->pgmp_seq),
260                          EXTRACT_16BITS(&poll_msg->pgmp_round)));
261             bp = (const u_char *) (poll_msg + 1);
262             break;
263         }
264         case PGM_POLR: {
265             const struct pgm_polr *polr;
266             uint32_t ivl, rnd, mask;
267
268             polr = (const struct pgm_polr *)(pgm + 1);
269             ND_TCHECK(*polr);
270             bp = (const u_char *) (polr + 1);
271
272             switch (EXTRACT_16BITS(&polr->pgmp_nla_afi)) {
273             case AFNUM_INET:
274                 ND_TCHECK2(*bp, sizeof(struct in_addr));
275                 addrtostr(bp, nla_buf, sizeof(nla_buf));
276                 bp += sizeof(struct in_addr);
277                 break;
278             case AFNUM_INET6:
279                 ND_TCHECK2(*bp, sizeof(struct in6_addr));
280                 addrtostr6(bp, nla_buf, sizeof(nla_buf));
281                 bp += sizeof(struct in6_addr);
282                 break;
283             default:
284                 goto trunc;
285                 break;
286             }
287
288             ND_TCHECK2(*bp, sizeof(uint32_t));
289             ivl = EXTRACT_32BITS(bp);
290             bp += sizeof(uint32_t);
291
292             ND_TCHECK2(*bp, sizeof(uint32_t));
293             rnd = EXTRACT_32BITS(bp);
294             bp += sizeof(uint32_t);
295
296             ND_TCHECK2(*bp, sizeof(uint32_t));
297             mask = EXTRACT_32BITS(bp);
298             bp += sizeof(uint32_t);
299
300             ND_PRINT((ndo, "POLR seq %u round %u nla %s ivl %u rnd 0x%08x "
301                          "mask 0x%08x", EXTRACT_32BITS(&polr->pgmp_seq),
302                          EXTRACT_16BITS(&polr->pgmp_round), nla_buf, ivl, rnd, mask));
303             break;
304         }
305         case PGM_ODATA: {
306             const struct pgm_data *odata;
307
308             odata = (const struct pgm_data *)(pgm + 1);
309             ND_TCHECK(*odata);
310             ND_PRINT((ndo, "ODATA trail %u seq %u",
311                          EXTRACT_32BITS(&odata->pgmd_trailseq),
312                          EXTRACT_32BITS(&odata->pgmd_seq)));
313             bp = (const u_char *) (odata + 1);
314             break;
315         }
316
317         case PGM_RDATA: {
318             const struct pgm_data *rdata;
319
320             rdata = (const struct pgm_data *)(pgm + 1);
321             ND_TCHECK(*rdata);
322             ND_PRINT((ndo, "RDATA trail %u seq %u",
323                          EXTRACT_32BITS(&rdata->pgmd_trailseq),
324                          EXTRACT_32BITS(&rdata->pgmd_seq)));
325             bp = (const u_char *) (rdata + 1);
326             break;
327         }
328
329         case PGM_NAK:
330         case PGM_NULLNAK:
331         case PGM_NCF: {
332             const struct pgm_nak *nak;
333             char source_buf[INET6_ADDRSTRLEN], group_buf[INET6_ADDRSTRLEN];
334
335             nak = (const struct pgm_nak *)(pgm + 1);
336             ND_TCHECK(*nak);
337             bp = (const u_char *) (nak + 1);
338
339             /*
340              * Skip past the source, saving info along the way
341              * and stopping if we don't have enough.
342              */
343             switch (EXTRACT_16BITS(&nak->pgmn_source_afi)) {
344             case AFNUM_INET:
345                 ND_TCHECK2(*bp, sizeof(struct in_addr));
346                 addrtostr(bp, source_buf, sizeof(source_buf));
347                 bp += sizeof(struct in_addr);
348                 break;
349             case AFNUM_INET6:
350                 ND_TCHECK2(*bp, sizeof(struct in6_addr));
351                 addrtostr6(bp, source_buf, sizeof(source_buf));
352                 bp += sizeof(struct in6_addr);
353                 break;
354             default:
355                 goto trunc;
356                 break;
357             }
358
359             /*
360              * Skip past the group, saving info along the way
361              * and stopping if we don't have enough.
362              */
363             bp += (2 * sizeof(uint16_t));
364             ND_TCHECK_16BITS(bp);
365             switch (EXTRACT_16BITS(bp)) {
366             case AFNUM_INET:
367                 ND_TCHECK2(*bp, sizeof(struct in_addr));
368                 addrtostr(bp, group_buf, sizeof(group_buf));
369                 bp += sizeof(struct in_addr);
370                 break;
371             case AFNUM_INET6:
372                 ND_TCHECK2(*bp, sizeof(struct in6_addr));
373                 addrtostr6(bp, group_buf, sizeof(group_buf));
374                 bp += sizeof(struct in6_addr);
375                 break;
376             default:
377                 goto trunc;
378                 break;
379             }
380
381             /*
382              * Options decoding can go here.
383              */
384             switch (pgm->pgm_type) {
385                 case PGM_NAK:
386                     ND_PRINT((ndo, "NAK "));
387                     break;
388                 case PGM_NULLNAK:
389                     ND_PRINT((ndo, "NNAK "));
390                     break;
391                 case PGM_NCF:
392                     ND_PRINT((ndo, "NCF "));
393                     break;
394                 default:
395                     break;
396             }
397             ND_PRINT((ndo, "(%s -> %s), seq %u",
398                          source_buf, group_buf, EXTRACT_32BITS(&nak->pgmn_seq)));
399             break;
400         }
401
402         case PGM_ACK: {
403             const struct pgm_ack *ack;
404
405             ack = (const struct pgm_ack *)(pgm + 1);
406             ND_TCHECK(*ack);
407             ND_PRINT((ndo, "ACK seq %u",
408                          EXTRACT_32BITS(&ack->pgma_rx_max_seq)));
409             bp = (const u_char *) (ack + 1);
410             break;
411         }
412
413         case PGM_SPMR:
414             ND_PRINT((ndo, "SPMR"));
415             break;
416
417         default:
418             ND_PRINT((ndo, "UNKNOWN type 0x%02x", pgm->pgm_type));
419             break;
420
421         }
422         if (pgm->pgm_options & PGM_OPT_BIT_PRESENT) {
423
424             /*
425              * make sure there's enough for the first option header
426              */
427             if (!ND_TTEST2(*bp, PGM_MIN_OPT_LEN)) {
428                 ND_PRINT((ndo, "[|OPT]"));
429                 return;
430             }
431
432             /*
433              * That option header MUST be an OPT_LENGTH option
434              * (see the first paragraph of section 9.1 in RFC 3208).
435              */
436             opt_type = *bp++;
437             if ((opt_type & PGM_OPT_MASK) != PGM_OPT_LENGTH) {
438                 ND_PRINT((ndo, "[First option bad, should be PGM_OPT_LENGTH, is %u]", opt_type & PGM_OPT_MASK));
439                 return;
440             }
441             opt_len = *bp++;
442             if (opt_len != 4) {
443                 ND_PRINT((ndo, "[Bad OPT_LENGTH option, length %u != 4]", opt_len));
444                 return;
445             }
446             opts_len = EXTRACT_16BITS(bp);
447             if (opts_len < 4) {
448                 ND_PRINT((ndo, "[Bad total option length %u < 4]", opts_len));
449                 return;
450             }
451             bp += sizeof(uint16_t);
452             ND_PRINT((ndo, " OPTS LEN %d", opts_len));
453             opts_len -= 4;
454
455             while (opts_len) {
456                 if (opts_len < PGM_MIN_OPT_LEN) {
457                     ND_PRINT((ndo, "[Total option length leaves no room for final option]"));
458                     return;
459                 }
460                 if (!ND_TTEST2(*bp, 2)) {
461                     ND_PRINT((ndo, " [|OPT]"));
462                     return;
463                 }
464                 opt_type = *bp++;
465                 opt_len = *bp++;
466                 if (opt_len < PGM_MIN_OPT_LEN) {
467                     ND_PRINT((ndo, "[Bad option, length %u < %u]", opt_len,
468                         PGM_MIN_OPT_LEN));
469                     break;
470                 }
471                 if (opts_len < opt_len) {
472                     ND_PRINT((ndo, "[Total option length leaves no room for final option]"));
473                     return;
474                 }
475                 if (!ND_TTEST2(*bp, opt_len - 2)) {
476                     ND_PRINT((ndo, " [|OPT]"));
477                     return;
478                 }
479
480                 switch (opt_type & PGM_OPT_MASK) {
481                 case PGM_OPT_LENGTH:
482 #define PGM_OPT_LENGTH_LEN      (2+2)
483                     if (opt_len != PGM_OPT_LENGTH_LEN) {
484                         ND_PRINT((ndo, "[Bad OPT_LENGTH option, length %u != %u]",
485                             opt_len, PGM_OPT_LENGTH_LEN));
486                         return;
487                     }
488                     ND_PRINT((ndo, " OPTS LEN (extra?) %d", EXTRACT_16BITS(bp)));
489                     bp += 2;
490                     opts_len -= PGM_OPT_LENGTH_LEN;
491                     break;
492
493                 case PGM_OPT_FRAGMENT:
494 #define PGM_OPT_FRAGMENT_LEN    (2+2+4+4+4)
495                     if (opt_len != PGM_OPT_FRAGMENT_LEN) {
496                         ND_PRINT((ndo, "[Bad OPT_FRAGMENT option, length %u != %u]",
497                             opt_len, PGM_OPT_FRAGMENT_LEN));
498                         return;
499                     }
500                     bp += 2;
501                     seq = EXTRACT_32BITS(bp);
502                     bp += 4;
503                     offset = EXTRACT_32BITS(bp);
504                     bp += 4;
505                     len = EXTRACT_32BITS(bp);
506                     bp += 4;
507                     ND_PRINT((ndo, " FRAG seq %u off %u len %u", seq, offset, len));
508                     opts_len -= PGM_OPT_FRAGMENT_LEN;
509                     break;
510
511                 case PGM_OPT_NAK_LIST:
512                     bp += 2;
513                     opt_len -= 4;       /* option header */
514                     ND_PRINT((ndo, " NAK LIST"));
515                     while (opt_len) {
516                         if (opt_len < 4) {
517                             ND_PRINT((ndo, "[Option length not a multiple of 4]"));
518                             return;
519                         }
520                         ND_TCHECK2(*bp, 4);
521                         ND_PRINT((ndo, " %u", EXTRACT_32BITS(bp)));
522                         bp += 4;
523                         opt_len -= 4;
524                         opts_len -= 4;
525                     }
526                     break;
527
528                 case PGM_OPT_JOIN:
529 #define PGM_OPT_JOIN_LEN        (2+2+4)
530                     if (opt_len != PGM_OPT_JOIN_LEN) {
531                         ND_PRINT((ndo, "[Bad OPT_JOIN option, length %u != %u]",
532                             opt_len, PGM_OPT_JOIN_LEN));
533                         return;
534                     }
535                     bp += 2;
536                     seq = EXTRACT_32BITS(bp);
537                     bp += 4;
538                     ND_PRINT((ndo, " JOIN %u", seq));
539                     opts_len -= PGM_OPT_JOIN_LEN;
540                     break;
541
542                 case PGM_OPT_NAK_BO_IVL:
543 #define PGM_OPT_NAK_BO_IVL_LEN  (2+2+4+4)
544                     if (opt_len != PGM_OPT_NAK_BO_IVL_LEN) {
545                         ND_PRINT((ndo, "[Bad OPT_NAK_BO_IVL option, length %u != %u]",
546                             opt_len, PGM_OPT_NAK_BO_IVL_LEN));
547                         return;
548                     }
549                     bp += 2;
550                     offset = EXTRACT_32BITS(bp);
551                     bp += 4;
552                     seq = EXTRACT_32BITS(bp);
553                     bp += 4;
554                     ND_PRINT((ndo, " BACKOFF ivl %u ivlseq %u", offset, seq));
555                     opts_len -= PGM_OPT_NAK_BO_IVL_LEN;
556                     break;
557
558                 case PGM_OPT_NAK_BO_RNG:
559 #define PGM_OPT_NAK_BO_RNG_LEN  (2+2+4+4)
560                     if (opt_len != PGM_OPT_NAK_BO_RNG_LEN) {
561                         ND_PRINT((ndo, "[Bad OPT_NAK_BO_RNG option, length %u != %u]",
562                             opt_len, PGM_OPT_NAK_BO_RNG_LEN));
563                         return;
564                     }
565                     bp += 2;
566                     offset = EXTRACT_32BITS(bp);
567                     bp += 4;
568                     seq = EXTRACT_32BITS(bp);
569                     bp += 4;
570                     ND_PRINT((ndo, " BACKOFF max %u min %u", offset, seq));
571                     opts_len -= PGM_OPT_NAK_BO_RNG_LEN;
572                     break;
573
574                 case PGM_OPT_REDIRECT:
575 #define PGM_OPT_REDIRECT_FIXED_LEN      (2+2+2+2)
576                     if (opt_len < PGM_OPT_REDIRECT_FIXED_LEN) {
577                         ND_PRINT((ndo, "[Bad OPT_REDIRECT option, length %u < %u]",
578                             opt_len, PGM_OPT_REDIRECT_FIXED_LEN));
579                         return;
580                     }
581                     bp += 2;
582                     nla_afnum = EXTRACT_16BITS(bp);
583                     bp += 2+2;
584                     switch (nla_afnum) {
585                     case AFNUM_INET:
586                         if (opt_len != PGM_OPT_REDIRECT_FIXED_LEN + sizeof(struct in_addr)) {
587                             ND_PRINT((ndo, "[Bad OPT_REDIRECT option, length %u != %u + address size]",
588                                 opt_len, PGM_OPT_REDIRECT_FIXED_LEN));
589                             return;
590                         }
591                         ND_TCHECK2(*bp, sizeof(struct in_addr));
592                         addrtostr(bp, nla_buf, sizeof(nla_buf));
593                         bp += sizeof(struct in_addr);
594                         opts_len -= PGM_OPT_REDIRECT_FIXED_LEN + sizeof(struct in_addr);
595                         break;
596                     case AFNUM_INET6:
597                         if (opt_len != PGM_OPT_REDIRECT_FIXED_LEN + sizeof(struct in6_addr)) {
598                             ND_PRINT((ndo, "[Bad OPT_REDIRECT option, length %u != %u + address size]",
599                                 PGM_OPT_REDIRECT_FIXED_LEN, opt_len));
600                             return;
601                         }
602                         ND_TCHECK2(*bp, sizeof(struct in6_addr));
603                         addrtostr6(bp, nla_buf, sizeof(nla_buf));
604                         bp += sizeof(struct in6_addr);
605                         opts_len -= PGM_OPT_REDIRECT_FIXED_LEN + sizeof(struct in6_addr);
606                         break;
607                     default:
608                         goto trunc;
609                         break;
610                     }
611
612                     ND_PRINT((ndo, " REDIRECT %s",  nla_buf));
613                     break;
614
615                 case PGM_OPT_PARITY_PRM:
616 #define PGM_OPT_PARITY_PRM_LEN  (2+2+4)
617                     if (opt_len != PGM_OPT_PARITY_PRM_LEN) {
618                         ND_PRINT((ndo, "[Bad OPT_PARITY_PRM option, length %u != %u]",
619                             opt_len, PGM_OPT_PARITY_PRM_LEN));
620                         return;
621                     }
622                     bp += 2;
623                     len = EXTRACT_32BITS(bp);
624                     bp += 4;
625                     ND_PRINT((ndo, " PARITY MAXTGS %u", len));
626                     opts_len -= PGM_OPT_PARITY_PRM_LEN;
627                     break;
628
629                 case PGM_OPT_PARITY_GRP:
630 #define PGM_OPT_PARITY_GRP_LEN  (2+2+4)
631                     if (opt_len != PGM_OPT_PARITY_GRP_LEN) {
632                         ND_PRINT((ndo, "[Bad OPT_PARITY_GRP option, length %u != %u]",
633                             opt_len, PGM_OPT_PARITY_GRP_LEN));
634                         return;
635                     }
636                     bp += 2;
637                     seq = EXTRACT_32BITS(bp);
638                     bp += 4;
639                     ND_PRINT((ndo, " PARITY GROUP %u", seq));
640                     opts_len -= PGM_OPT_PARITY_GRP_LEN;
641                     break;
642
643                 case PGM_OPT_CURR_TGSIZE:
644 #define PGM_OPT_CURR_TGSIZE_LEN (2+2+4)
645                     if (opt_len != PGM_OPT_CURR_TGSIZE_LEN) {
646                         ND_PRINT((ndo, "[Bad OPT_CURR_TGSIZE option, length %u != %u]",
647                             opt_len, PGM_OPT_CURR_TGSIZE_LEN));
648                         return;
649                     }
650                     bp += 2;
651                     len = EXTRACT_32BITS(bp);
652                     bp += 4;
653                     ND_PRINT((ndo, " PARITY ATGS %u", len));
654                     opts_len -= PGM_OPT_CURR_TGSIZE_LEN;
655                     break;
656
657                 case PGM_OPT_NBR_UNREACH:
658 #define PGM_OPT_NBR_UNREACH_LEN (2+2)
659                     if (opt_len != PGM_OPT_NBR_UNREACH_LEN) {
660                         ND_PRINT((ndo, "[Bad OPT_NBR_UNREACH option, length %u != %u]",
661                             opt_len, PGM_OPT_NBR_UNREACH_LEN));
662                         return;
663                     }
664                     bp += 2;
665                     ND_PRINT((ndo, " NBR_UNREACH"));
666                     opts_len -= PGM_OPT_NBR_UNREACH_LEN;
667                     break;
668
669                 case PGM_OPT_PATH_NLA:
670                     ND_PRINT((ndo, " PATH_NLA [%d]", opt_len));
671                     bp += opt_len;
672                     opts_len -= opt_len;
673                     break;
674
675                 case PGM_OPT_SYN:
676 #define PGM_OPT_SYN_LEN (2+2)
677                     if (opt_len != PGM_OPT_SYN_LEN) {
678                         ND_PRINT((ndo, "[Bad OPT_SYN option, length %u != %u]",
679                             opt_len, PGM_OPT_SYN_LEN));
680                         return;
681                     }
682                     bp += 2;
683                     ND_PRINT((ndo, " SYN"));
684                     opts_len -= PGM_OPT_SYN_LEN;
685                     break;
686
687                 case PGM_OPT_FIN:
688 #define PGM_OPT_FIN_LEN (2+2)
689                     if (opt_len != PGM_OPT_FIN_LEN) {
690                         ND_PRINT((ndo, "[Bad OPT_FIN option, length %u != %u]",
691                             opt_len, PGM_OPT_FIN_LEN));
692                         return;
693                     }
694                     bp += 2;
695                     ND_PRINT((ndo, " FIN"));
696                     opts_len -= PGM_OPT_FIN_LEN;
697                     break;
698
699                 case PGM_OPT_RST:
700 #define PGM_OPT_RST_LEN (2+2)
701                     if (opt_len != PGM_OPT_RST_LEN) {
702                         ND_PRINT((ndo, "[Bad OPT_RST option, length %u != %u]",
703                             opt_len, PGM_OPT_RST_LEN));
704                         return;
705                     }
706                     bp += 2;
707                     ND_PRINT((ndo, " RST"));
708                     opts_len -= PGM_OPT_RST_LEN;
709                     break;
710
711                 case PGM_OPT_CR:
712                     ND_PRINT((ndo, " CR"));
713                     bp += opt_len;
714                     opts_len -= opt_len;
715                     break;
716
717                 case PGM_OPT_CRQST:
718 #define PGM_OPT_CRQST_LEN       (2+2)
719                     if (opt_len != PGM_OPT_CRQST_LEN) {
720                         ND_PRINT((ndo, "[Bad OPT_CRQST option, length %u != %u]",
721                             opt_len, PGM_OPT_CRQST_LEN));
722                         return;
723                     }
724                     bp += 2;
725                     ND_PRINT((ndo, " CRQST"));
726                     opts_len -= PGM_OPT_CRQST_LEN;
727                     break;
728
729                 case PGM_OPT_PGMCC_DATA:
730 #define PGM_OPT_PGMCC_DATA_FIXED_LEN    (2+2+4+2+2)
731                     if (opt_len < PGM_OPT_PGMCC_DATA_FIXED_LEN) {
732                         ND_PRINT((ndo, "[Bad OPT_PGMCC_DATA option, length %u < %u]",
733                             opt_len, PGM_OPT_PGMCC_DATA_FIXED_LEN));
734                         return;
735                     }
736                     bp += 2;
737                     offset = EXTRACT_32BITS(bp);
738                     bp += 4;
739                     nla_afnum = EXTRACT_16BITS(bp);
740                     bp += 2+2;
741                     switch (nla_afnum) {
742                     case AFNUM_INET:
743                         if (opt_len != PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(struct in_addr)) {
744                             ND_PRINT((ndo, "[Bad OPT_PGMCC_DATA option, length %u != %u + address size]",
745                                 opt_len, PGM_OPT_PGMCC_DATA_FIXED_LEN));
746                             return;
747                         }
748                         ND_TCHECK2(*bp, sizeof(struct in_addr));
749                         addrtostr(bp, nla_buf, sizeof(nla_buf));
750                         bp += sizeof(struct in_addr);
751                         opts_len -= PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(struct in_addr);
752                         break;
753                     case AFNUM_INET6:
754                         if (opt_len != PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(struct in6_addr)) {
755                             ND_PRINT((ndo, "[Bad OPT_PGMCC_DATA option, length %u != %u + address size]",
756                                 opt_len, PGM_OPT_PGMCC_DATA_FIXED_LEN));
757                             return;
758                         }
759                         ND_TCHECK2(*bp, sizeof(struct in6_addr));
760                         addrtostr6(bp, nla_buf, sizeof(nla_buf));
761                         bp += sizeof(struct in6_addr);
762                         opts_len -= PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(struct in6_addr);
763                         break;
764                     default:
765                         goto trunc;
766                         break;
767                     }
768
769                     ND_PRINT((ndo, " PGMCC DATA %u %s", offset, nla_buf));
770                     break;
771
772                 case PGM_OPT_PGMCC_FEEDBACK:
773 #define PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN        (2+2+4+2+2)
774                     if (opt_len < PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN) {
775                         ND_PRINT((ndo, "[Bad PGM_OPT_PGMCC_FEEDBACK option, length %u < %u]",
776                             opt_len, PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN));
777                         return;
778                     }
779                     bp += 2;
780                     offset = EXTRACT_32BITS(bp);
781                     bp += 4;
782                     nla_afnum = EXTRACT_16BITS(bp);
783                     bp += 2+2;
784                     switch (nla_afnum) {
785                     case AFNUM_INET:
786                         if (opt_len != PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(struct in_addr)) {
787                             ND_PRINT((ndo, "[Bad OPT_PGMCC_FEEDBACK option, length %u != %u + address size]",
788                                 opt_len, PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN));
789                             return;
790                         }
791                         ND_TCHECK2(*bp, sizeof(struct in_addr));
792                         addrtostr(bp, nla_buf, sizeof(nla_buf));
793                         bp += sizeof(struct in_addr);
794                         opts_len -= PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(struct in_addr);
795                         break;
796                     case AFNUM_INET6:
797                         if (opt_len != PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(struct in6_addr)) {
798                             ND_PRINT((ndo, "[Bad OPT_PGMCC_FEEDBACK option, length %u != %u + address size]",
799                                 opt_len, PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN));
800                             return;
801                         }
802                         ND_TCHECK2(*bp, sizeof(struct in6_addr));
803                         addrtostr6(bp, nla_buf, sizeof(nla_buf));
804                         bp += sizeof(struct in6_addr);
805                         opts_len -= PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(struct in6_addr);
806                         break;
807                     default:
808                         goto trunc;
809                         break;
810                     }
811
812                     ND_PRINT((ndo, " PGMCC FEEDBACK %u %s", offset, nla_buf));
813                     break;
814
815                 default:
816                     ND_PRINT((ndo, " OPT_%02X [%d] ", opt_type, opt_len));
817                     bp += opt_len;
818                     opts_len -= opt_len;
819                     break;
820                 }
821
822                 if (opt_type & PGM_OPT_END)
823                     break;
824              }
825         }
826
827         ND_PRINT((ndo, " [%u]", length));
828         if (ndo->ndo_packettype == PT_PGM_ZMTP1 &&
829             (pgm->pgm_type == PGM_ODATA || pgm->pgm_type == PGM_RDATA))
830                 zmtp1_print_datagram(ndo, bp, EXTRACT_16BITS(&pgm->pgm_length));
831
832         return;
833
834 trunc:
835         ND_PRINT((ndo, "[|pgm]"));
836         if (ch != '\0')
837                 ND_PRINT((ndo, ">"));
838 }