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