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