xref: /netbsd/external/bsd/tcpdump/dist/print-pgm.c (revision 141b0ad2)
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
pgm_print(netdissect_options * ndo,register const u_char * bp,register u_int length,register const u_char * bp2)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