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