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