xref: /dflybsd-src/contrib/tcpdump/print-pgm.c (revision 59c07fbdf8168fa08c76c515186d561b5a92690c)
141c99275SPeter Avalos /*
241c99275SPeter Avalos  * Redistribution and use in source and binary forms, with or without
341c99275SPeter Avalos  * modification, are permitted provided that: (1) source code
441c99275SPeter Avalos  * distributions retain the above copyright notice and this paragraph
541c99275SPeter Avalos  * in its entirety, and (2) distributions including binary code include
641c99275SPeter Avalos  * the above copyright notice and this paragraph in its entirety in
741c99275SPeter Avalos  * the documentation or other materials provided with the distribution.
841c99275SPeter Avalos  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
941c99275SPeter Avalos  * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
1041c99275SPeter Avalos  * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
1141c99275SPeter Avalos  * FOR A PARTICULAR PURPOSE.
1241c99275SPeter Avalos  *
1341c99275SPeter Avalos  * Original code by Andy Heffernan (ahh@juniper.net)
1441c99275SPeter Avalos  */
1541c99275SPeter Avalos 
16411677aeSAaron LI /* \summary: Pragmatic General Multicast (PGM) printer */
1741c99275SPeter Avalos 
1841c99275SPeter Avalos #ifdef HAVE_CONFIG_H
19*ed775ee7SAntonio Huete Jimenez #include <config.h>
2041c99275SPeter Avalos #endif
2141c99275SPeter Avalos 
22*ed775ee7SAntonio Huete Jimenez #include "netdissect-stdinc.h"
2341c99275SPeter Avalos 
24411677aeSAaron LI #include "netdissect.h"
2541c99275SPeter Avalos #include "extract.h"
2641c99275SPeter Avalos #include "addrtoname.h"
27411677aeSAaron LI #include "addrtostr.h"
2841c99275SPeter Avalos 
2941c99275SPeter Avalos #include "ip.h"
3041c99275SPeter Avalos #include "ip6.h"
3141c99275SPeter Avalos #include "ipproto.h"
32411677aeSAaron LI #include "af.h"
3341c99275SPeter Avalos 
3441c99275SPeter Avalos /*
3541c99275SPeter Avalos  * PGM header (RFC 3208)
3641c99275SPeter Avalos  */
3741c99275SPeter Avalos struct pgm_header {
38*ed775ee7SAntonio Huete Jimenez     nd_uint16_t	pgm_sport;
39*ed775ee7SAntonio Huete Jimenez     nd_uint16_t	pgm_dport;
40*ed775ee7SAntonio Huete Jimenez     nd_uint8_t	pgm_type;
41*ed775ee7SAntonio Huete Jimenez     nd_uint8_t	pgm_options;
42*ed775ee7SAntonio Huete Jimenez     nd_uint16_t	pgm_sum;
43*ed775ee7SAntonio Huete Jimenez     nd_byte	pgm_gsid[6];
44*ed775ee7SAntonio Huete Jimenez     nd_uint16_t	pgm_length;
4541c99275SPeter Avalos };
4641c99275SPeter Avalos 
4741c99275SPeter Avalos struct pgm_spm {
48*ed775ee7SAntonio Huete Jimenez     nd_uint32_t	pgms_seq;
49*ed775ee7SAntonio Huete Jimenez     nd_uint32_t	pgms_trailseq;
50*ed775ee7SAntonio Huete Jimenez     nd_uint32_t	pgms_leadseq;
51*ed775ee7SAntonio Huete Jimenez     nd_uint16_t	pgms_nla_afi;
52*ed775ee7SAntonio Huete Jimenez     nd_uint16_t	pgms_reserved;
53411677aeSAaron LI     /* ... uint8_t	pgms_nla[0]; */
5441c99275SPeter Avalos     /* ... options */
5541c99275SPeter Avalos };
5641c99275SPeter Avalos 
5741c99275SPeter Avalos struct pgm_nak {
58*ed775ee7SAntonio Huete Jimenez     nd_uint32_t	pgmn_seq;
59*ed775ee7SAntonio Huete Jimenez     nd_uint16_t	pgmn_source_afi;
60*ed775ee7SAntonio Huete Jimenez     nd_uint16_t	pgmn_reserved;
61411677aeSAaron LI     /* ... uint8_t	pgmn_source[0]; */
62411677aeSAaron LI     /* ... uint16_t	pgmn_group_afi */
63411677aeSAaron LI     /* ... uint16_t	pgmn_reserved2; */
64411677aeSAaron LI     /* ... uint8_t	pgmn_group[0]; */
6541c99275SPeter Avalos     /* ... options */
6641c99275SPeter Avalos };
6741c99275SPeter Avalos 
6827bfbee1SPeter Avalos struct pgm_ack {
69*ed775ee7SAntonio Huete Jimenez     nd_uint32_t	pgma_rx_max_seq;
70*ed775ee7SAntonio Huete Jimenez     nd_uint32_t	pgma_bitmap;
7127bfbee1SPeter Avalos     /* ... options */
7227bfbee1SPeter Avalos };
7327bfbee1SPeter Avalos 
7441c99275SPeter Avalos struct pgm_poll {
75*ed775ee7SAntonio Huete Jimenez     nd_uint32_t	pgmp_seq;
76*ed775ee7SAntonio Huete Jimenez     nd_uint16_t	pgmp_round;
77*ed775ee7SAntonio Huete Jimenez     nd_uint16_t	pgmp_subtype;
78*ed775ee7SAntonio Huete Jimenez     nd_uint16_t	pgmp_nla_afi;
79*ed775ee7SAntonio Huete Jimenez     nd_uint16_t	pgmp_reserved;
80411677aeSAaron LI     /* ... uint8_t	pgmp_nla[0]; */
8141c99275SPeter Avalos     /* ... options */
8241c99275SPeter Avalos };
8341c99275SPeter Avalos 
84*ed775ee7SAntonio Huete Jimenez struct pgm_polr {
85*ed775ee7SAntonio Huete Jimenez     nd_uint32_t	pgmp_seq;
86*ed775ee7SAntonio Huete Jimenez     nd_uint16_t	pgmp_round;
87*ed775ee7SAntonio Huete Jimenez     nd_uint16_t	pgmp_reserved;
88*ed775ee7SAntonio Huete Jimenez     /* ... options */
89*ed775ee7SAntonio Huete Jimenez };
90*ed775ee7SAntonio Huete Jimenez 
9141c99275SPeter Avalos struct pgm_data {
92*ed775ee7SAntonio Huete Jimenez     nd_uint32_t	pgmd_seq;
93*ed775ee7SAntonio Huete Jimenez     nd_uint32_t	pgmd_trailseq;
9441c99275SPeter Avalos     /* ... options */
9541c99275SPeter Avalos };
9641c99275SPeter Avalos 
9741c99275SPeter Avalos typedef enum _pgm_type {
9841c99275SPeter Avalos     PGM_SPM = 0,		/* source path message */
9941c99275SPeter Avalos     PGM_POLL = 1,		/* POLL Request */
10041c99275SPeter Avalos     PGM_POLR = 2,		/* POLL Response */
10141c99275SPeter Avalos     PGM_ODATA = 4,		/* original data */
10241c99275SPeter Avalos     PGM_RDATA = 5,		/* repair data */
10341c99275SPeter Avalos     PGM_NAK = 8,		/* NAK */
10441c99275SPeter Avalos     PGM_NULLNAK = 9,		/* Null NAK */
10541c99275SPeter Avalos     PGM_NCF = 10,		/* NAK Confirmation */
10641c99275SPeter Avalos     PGM_ACK = 11,		/* ACK for congestion control */
10741c99275SPeter Avalos     PGM_SPMR = 12,		/* SPM request */
10841c99275SPeter Avalos     PGM_MAX = 255
10941c99275SPeter Avalos } pgm_type;
11041c99275SPeter Avalos 
11141c99275SPeter Avalos #define PGM_OPT_BIT_PRESENT	0x01
11241c99275SPeter Avalos #define PGM_OPT_BIT_NETWORK	0x02
11341c99275SPeter Avalos #define PGM_OPT_BIT_VAR_PKTLEN	0x40
11441c99275SPeter Avalos #define PGM_OPT_BIT_PARITY	0x80
11541c99275SPeter Avalos 
11641c99275SPeter Avalos #define PGM_OPT_LENGTH		0x00
11741c99275SPeter Avalos #define PGM_OPT_FRAGMENT        0x01
11841c99275SPeter Avalos #define PGM_OPT_NAK_LIST        0x02
11941c99275SPeter Avalos #define PGM_OPT_JOIN            0x03
12041c99275SPeter Avalos #define PGM_OPT_NAK_BO_IVL	0x04
12141c99275SPeter Avalos #define PGM_OPT_NAK_BO_RNG	0x05
12241c99275SPeter Avalos 
12341c99275SPeter Avalos #define PGM_OPT_REDIRECT        0x07
12441c99275SPeter Avalos #define PGM_OPT_PARITY_PRM      0x08
12541c99275SPeter Avalos #define PGM_OPT_PARITY_GRP      0x09
12641c99275SPeter Avalos #define PGM_OPT_CURR_TGSIZE     0x0A
12741c99275SPeter Avalos #define PGM_OPT_NBR_UNREACH	0x0B
12841c99275SPeter Avalos #define PGM_OPT_PATH_NLA	0x0C
12941c99275SPeter Avalos 
13041c99275SPeter Avalos #define PGM_OPT_SYN             0x0D
13141c99275SPeter Avalos #define PGM_OPT_FIN             0x0E
13241c99275SPeter Avalos #define PGM_OPT_RST             0x0F
13341c99275SPeter Avalos #define PGM_OPT_CR		0x10
13441c99275SPeter Avalos #define PGM_OPT_CRQST		0x11
13541c99275SPeter Avalos 
13627bfbee1SPeter Avalos #define PGM_OPT_PGMCC_DATA	0x12
13727bfbee1SPeter Avalos #define PGM_OPT_PGMCC_FEEDBACK	0x13
13827bfbee1SPeter Avalos 
13941c99275SPeter Avalos #define PGM_OPT_MASK		0x7f
14041c99275SPeter Avalos 
14141c99275SPeter Avalos #define PGM_OPT_END		0x80    /* end of options marker */
14241c99275SPeter Avalos 
14341c99275SPeter Avalos #define PGM_MIN_OPT_LEN		4
14441c99275SPeter Avalos 
14541c99275SPeter Avalos void
pgm_print(netdissect_options * ndo,const u_char * bp,u_int length,const u_char * bp2)146411677aeSAaron LI pgm_print(netdissect_options *ndo,
147*ed775ee7SAntonio Huete Jimenez           const u_char *bp, u_int length,
148*ed775ee7SAntonio Huete Jimenez           const u_char *bp2)
14941c99275SPeter Avalos {
150*ed775ee7SAntonio Huete Jimenez 	const struct pgm_header *pgm;
151*ed775ee7SAntonio Huete Jimenez 	const struct ip *ip;
152*ed775ee7SAntonio Huete Jimenez 	uint8_t pgm_type_val;
153411677aeSAaron LI 	uint16_t sport, dport;
154411677aeSAaron LI 	u_int nla_afnum;
15541c99275SPeter Avalos 	char nla_buf[INET6_ADDRSTRLEN];
156*ed775ee7SAntonio Huete Jimenez 	const struct ip6_hdr *ip6;
157411677aeSAaron LI 	uint8_t opt_type, opt_len;
158411677aeSAaron LI 	uint32_t seq, opts_len, len, offset;
15941c99275SPeter Avalos 
160*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_protocol = "pgm";
161411677aeSAaron LI 	pgm = (const struct pgm_header *)bp;
162411677aeSAaron LI 	ip = (const struct ip *)bp2;
16341c99275SPeter Avalos 	if (IP_V(ip) == 6)
164411677aeSAaron LI 		ip6 = (const struct ip6_hdr *)bp2;
16541c99275SPeter Avalos 	else
16641c99275SPeter Avalos 		ip6 = NULL;
167*ed775ee7SAntonio Huete Jimenez 	if (!ND_TTEST_2(pgm->pgm_dport)) {
16841c99275SPeter Avalos 		if (ip6) {
169*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("%s > %s:",
170*ed775ee7SAntonio Huete Jimenez 				GET_IP6ADDR_STRING(ip6->ip6_src),
171*ed775ee7SAntonio Huete Jimenez 				GET_IP6ADDR_STRING(ip6->ip6_dst));
172411677aeSAaron LI 		} else {
173*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("%s > %s:",
174*ed775ee7SAntonio Huete Jimenez 				GET_IPADDR_STRING(ip->ip_src),
175*ed775ee7SAntonio Huete Jimenez 				GET_IPADDR_STRING(ip->ip_dst));
17641c99275SPeter Avalos 		}
177*ed775ee7SAntonio Huete Jimenez 		nd_print_trunc(ndo);
178411677aeSAaron LI 		return;
17941c99275SPeter Avalos 	}
18041c99275SPeter Avalos 
181*ed775ee7SAntonio Huete Jimenez 	sport = GET_BE_U_2(pgm->pgm_sport);
182*ed775ee7SAntonio Huete Jimenez 	dport = GET_BE_U_2(pgm->pgm_dport);
18341c99275SPeter Avalos 
18441c99275SPeter Avalos 	if (ip6) {
185*ed775ee7SAntonio Huete Jimenez 		if (GET_U_1(ip6->ip6_nxt) == IPPROTO_PGM) {
186*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("%s.%s > %s.%s: ",
187*ed775ee7SAntonio Huete Jimenez 				GET_IP6ADDR_STRING(ip6->ip6_src),
188411677aeSAaron LI 				tcpport_string(ndo, sport),
189*ed775ee7SAntonio Huete Jimenez 				GET_IP6ADDR_STRING(ip6->ip6_dst),
190*ed775ee7SAntonio Huete Jimenez 				tcpport_string(ndo, dport));
19141c99275SPeter Avalos 		} else {
192*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("%s > %s: ",
193*ed775ee7SAntonio Huete Jimenez 				tcpport_string(ndo, sport), tcpport_string(ndo, dport));
19441c99275SPeter Avalos 		}
195411677aeSAaron LI 	} else {
196*ed775ee7SAntonio Huete Jimenez 		if (GET_U_1(ip->ip_p) == IPPROTO_PGM) {
197*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("%s.%s > %s.%s: ",
198*ed775ee7SAntonio Huete Jimenez 				GET_IPADDR_STRING(ip->ip_src),
199411677aeSAaron LI 				tcpport_string(ndo, sport),
200*ed775ee7SAntonio Huete Jimenez 				GET_IPADDR_STRING(ip->ip_dst),
201*ed775ee7SAntonio Huete Jimenez 				tcpport_string(ndo, dport));
20241c99275SPeter Avalos 		} else {
203*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("%s > %s: ",
204*ed775ee7SAntonio Huete Jimenez 				tcpport_string(ndo, sport), tcpport_string(ndo, dport));
20541c99275SPeter Avalos 		}
20641c99275SPeter Avalos 	}
20741c99275SPeter Avalos 
208*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_SIZE(pgm);
20941c99275SPeter Avalos 
210*ed775ee7SAntonio Huete Jimenez         ND_PRINT("PGM, length %u", GET_BE_U_2(pgm->pgm_length));
21141c99275SPeter Avalos 
212411677aeSAaron LI         if (!ndo->ndo_vflag)
21341c99275SPeter Avalos             return;
21441c99275SPeter Avalos 
215*ed775ee7SAntonio Huete Jimenez 	pgm_type_val = GET_U_1(pgm->pgm_type);
216*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(" 0x%02x%02x%02x%02x%02x%02x ",
21741c99275SPeter Avalos 		     pgm->pgm_gsid[0],
21841c99275SPeter Avalos                      pgm->pgm_gsid[1],
21941c99275SPeter Avalos                      pgm->pgm_gsid[2],
22041c99275SPeter Avalos 		     pgm->pgm_gsid[3],
22141c99275SPeter Avalos                      pgm->pgm_gsid[4],
222*ed775ee7SAntonio Huete Jimenez                      pgm->pgm_gsid[5]);
223*ed775ee7SAntonio Huete Jimenez 	switch (pgm_type_val) {
22441c99275SPeter Avalos 	case PGM_SPM: {
225411677aeSAaron LI 	    const struct pgm_spm *spm;
22641c99275SPeter Avalos 
227411677aeSAaron LI 	    spm = (const struct pgm_spm *)(pgm + 1);
228*ed775ee7SAntonio Huete Jimenez 	    ND_TCHECK_SIZE(spm);
229411677aeSAaron LI 	    bp = (const u_char *) (spm + 1);
23041c99275SPeter Avalos 
231*ed775ee7SAntonio Huete Jimenez 	    switch (GET_BE_U_2(spm->pgms_nla_afi)) {
232411677aeSAaron LI 	    case AFNUM_INET:
233*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_LEN(bp, sizeof(nd_ipv4));
234411677aeSAaron LI 		addrtostr(bp, nla_buf, sizeof(nla_buf));
235*ed775ee7SAntonio Huete Jimenez 		bp += sizeof(nd_ipv4);
23641c99275SPeter Avalos 		break;
237411677aeSAaron LI 	    case AFNUM_INET6:
238*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_LEN(bp, sizeof(nd_ipv6));
239411677aeSAaron LI 		addrtostr6(bp, nla_buf, sizeof(nla_buf));
240*ed775ee7SAntonio Huete Jimenez 		bp += sizeof(nd_ipv6);
24141c99275SPeter Avalos 		break;
24241c99275SPeter Avalos 	    default:
24341c99275SPeter Avalos 		goto trunc;
24441c99275SPeter Avalos 		break;
24541c99275SPeter Avalos 	    }
24641c99275SPeter Avalos 
247*ed775ee7SAntonio Huete Jimenez 	    ND_PRINT("SPM seq %u trail %u lead %u nla %s",
248*ed775ee7SAntonio Huete Jimenez 			 GET_BE_U_4(spm->pgms_seq),
249*ed775ee7SAntonio Huete Jimenez 			 GET_BE_U_4(spm->pgms_trailseq),
250*ed775ee7SAntonio Huete Jimenez 			 GET_BE_U_4(spm->pgms_leadseq),
251*ed775ee7SAntonio Huete Jimenez 			 nla_buf);
25241c99275SPeter Avalos 	    break;
25341c99275SPeter Avalos 	}
25441c99275SPeter Avalos 
25541c99275SPeter Avalos 	case PGM_POLL: {
256*ed775ee7SAntonio Huete Jimenez 	    const struct pgm_poll *pgm_poll;
257411677aeSAaron LI 	    uint32_t ivl, rnd, mask;
25841c99275SPeter Avalos 
259*ed775ee7SAntonio Huete Jimenez 	    pgm_poll = (const struct pgm_poll *)(pgm + 1);
260*ed775ee7SAntonio Huete Jimenez 	    ND_TCHECK_SIZE(pgm_poll);
261*ed775ee7SAntonio Huete Jimenez 	    bp = (const u_char *) (pgm_poll + 1);
26241c99275SPeter Avalos 
263*ed775ee7SAntonio Huete Jimenez 	    switch (GET_BE_U_2(pgm_poll->pgmp_nla_afi)) {
264411677aeSAaron LI 	    case AFNUM_INET:
265*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_LEN(bp, sizeof(nd_ipv4));
266411677aeSAaron LI 		addrtostr(bp, nla_buf, sizeof(nla_buf));
267*ed775ee7SAntonio Huete Jimenez 		bp += sizeof(nd_ipv4);
26841c99275SPeter Avalos 		break;
269411677aeSAaron LI 	    case AFNUM_INET6:
270*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_LEN(bp, sizeof(nd_ipv6));
271411677aeSAaron LI 		addrtostr6(bp, nla_buf, sizeof(nla_buf));
272*ed775ee7SAntonio Huete Jimenez 		bp += sizeof(nd_ipv6);
27341c99275SPeter Avalos 		break;
27441c99275SPeter Avalos 	    default:
27541c99275SPeter Avalos 		goto trunc;
27641c99275SPeter Avalos 		break;
27741c99275SPeter Avalos 	    }
27841c99275SPeter Avalos 
279*ed775ee7SAntonio Huete Jimenez 	    ivl = GET_BE_U_4(bp);
280411677aeSAaron LI 	    bp += sizeof(uint32_t);
28141c99275SPeter Avalos 
282*ed775ee7SAntonio Huete Jimenez 	    rnd = GET_BE_U_4(bp);
283411677aeSAaron LI 	    bp += sizeof(uint32_t);
28441c99275SPeter Avalos 
285*ed775ee7SAntonio Huete Jimenez 	    mask = GET_BE_U_4(bp);
286411677aeSAaron LI 	    bp += sizeof(uint32_t);
28741c99275SPeter Avalos 
288*ed775ee7SAntonio Huete Jimenez 	    ND_PRINT("POLL seq %u round %u nla %s ivl %u rnd 0x%08x "
289*ed775ee7SAntonio Huete Jimenez 			 "mask 0x%08x", GET_BE_U_4(pgm_poll->pgmp_seq),
290*ed775ee7SAntonio Huete Jimenez 			 GET_BE_U_2(pgm_poll->pgmp_round), nla_buf, ivl, rnd,
291*ed775ee7SAntonio Huete Jimenez 			 mask);
292*ed775ee7SAntonio Huete Jimenez 	    break;
293*ed775ee7SAntonio Huete Jimenez 	}
294*ed775ee7SAntonio Huete Jimenez 	case PGM_POLR: {
295*ed775ee7SAntonio Huete Jimenez 	    const struct pgm_polr *polr_msg;
296*ed775ee7SAntonio Huete Jimenez 
297*ed775ee7SAntonio Huete Jimenez 	    polr_msg = (const struct pgm_polr *)(pgm + 1);
298*ed775ee7SAntonio Huete Jimenez 	    ND_TCHECK_SIZE(polr_msg);
299*ed775ee7SAntonio Huete Jimenez 	    ND_PRINT("POLR seq %u round %u",
300*ed775ee7SAntonio Huete Jimenez 			 GET_BE_U_4(polr_msg->pgmp_seq),
301*ed775ee7SAntonio Huete Jimenez 			 GET_BE_U_2(polr_msg->pgmp_round));
302*ed775ee7SAntonio Huete Jimenez 	    bp = (const u_char *) (polr_msg + 1);
30341c99275SPeter Avalos 	    break;
30441c99275SPeter Avalos 	}
30541c99275SPeter Avalos 	case PGM_ODATA: {
306411677aeSAaron LI 	    const struct pgm_data *odata;
30741c99275SPeter Avalos 
308411677aeSAaron LI 	    odata = (const struct pgm_data *)(pgm + 1);
309*ed775ee7SAntonio Huete Jimenez 	    ND_TCHECK_SIZE(odata);
310*ed775ee7SAntonio Huete Jimenez 	    ND_PRINT("ODATA trail %u seq %u",
311*ed775ee7SAntonio Huete Jimenez 			 GET_BE_U_4(odata->pgmd_trailseq),
312*ed775ee7SAntonio Huete Jimenez 			 GET_BE_U_4(odata->pgmd_seq));
313411677aeSAaron LI 	    bp = (const u_char *) (odata + 1);
31441c99275SPeter Avalos 	    break;
31541c99275SPeter Avalos 	}
31641c99275SPeter Avalos 
31741c99275SPeter Avalos 	case PGM_RDATA: {
318411677aeSAaron LI 	    const struct pgm_data *rdata;
31941c99275SPeter Avalos 
320411677aeSAaron LI 	    rdata = (const struct pgm_data *)(pgm + 1);
321*ed775ee7SAntonio Huete Jimenez 	    ND_TCHECK_SIZE(rdata);
322*ed775ee7SAntonio Huete Jimenez 	    ND_PRINT("RDATA trail %u seq %u",
323*ed775ee7SAntonio Huete Jimenez 			 GET_BE_U_4(rdata->pgmd_trailseq),
324*ed775ee7SAntonio Huete Jimenez 			 GET_BE_U_4(rdata->pgmd_seq));
325411677aeSAaron LI 	    bp = (const u_char *) (rdata + 1);
32641c99275SPeter Avalos 	    break;
32741c99275SPeter Avalos 	}
32841c99275SPeter Avalos 
32941c99275SPeter Avalos 	case PGM_NAK:
33041c99275SPeter Avalos 	case PGM_NULLNAK:
33141c99275SPeter Avalos 	case PGM_NCF: {
332411677aeSAaron LI 	    const struct pgm_nak *nak;
33341c99275SPeter Avalos 	    char source_buf[INET6_ADDRSTRLEN], group_buf[INET6_ADDRSTRLEN];
33441c99275SPeter Avalos 
335411677aeSAaron LI 	    nak = (const struct pgm_nak *)(pgm + 1);
336*ed775ee7SAntonio Huete Jimenez 	    ND_TCHECK_SIZE(nak);
337411677aeSAaron LI 	    bp = (const u_char *) (nak + 1);
33841c99275SPeter Avalos 
33941c99275SPeter Avalos 	    /*
34041c99275SPeter Avalos 	     * Skip past the source, saving info along the way
34141c99275SPeter Avalos 	     * and stopping if we don't have enough.
34241c99275SPeter Avalos 	     */
343*ed775ee7SAntonio Huete Jimenez 	    switch (GET_BE_U_2(nak->pgmn_source_afi)) {
344411677aeSAaron LI 	    case AFNUM_INET:
345*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_LEN(bp, sizeof(nd_ipv4));
346411677aeSAaron LI 		addrtostr(bp, source_buf, sizeof(source_buf));
347*ed775ee7SAntonio Huete Jimenez 		bp += sizeof(nd_ipv4);
34841c99275SPeter Avalos 		break;
349411677aeSAaron LI 	    case AFNUM_INET6:
350*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_LEN(bp, sizeof(nd_ipv6));
351411677aeSAaron LI 		addrtostr6(bp, source_buf, sizeof(source_buf));
352*ed775ee7SAntonio Huete Jimenez 		bp += sizeof(nd_ipv6);
35341c99275SPeter Avalos 		break;
35441c99275SPeter Avalos 	    default:
35541c99275SPeter Avalos 		goto trunc;
35641c99275SPeter Avalos 		break;
35741c99275SPeter Avalos 	    }
35841c99275SPeter Avalos 
35941c99275SPeter Avalos 	    /*
36041c99275SPeter Avalos 	     * Skip past the group, saving info along the way
36141c99275SPeter Avalos 	     * and stopping if we don't have enough.
36241c99275SPeter Avalos 	     */
363411677aeSAaron LI 	    bp += (2 * sizeof(uint16_t));
364*ed775ee7SAntonio Huete Jimenez 	    switch (GET_BE_U_2(bp)) {
365411677aeSAaron LI 	    case AFNUM_INET:
366*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_LEN(bp, sizeof(nd_ipv4));
367411677aeSAaron LI 		addrtostr(bp, group_buf, sizeof(group_buf));
368*ed775ee7SAntonio Huete Jimenez 		bp += sizeof(nd_ipv4);
36941c99275SPeter Avalos 		break;
370411677aeSAaron LI 	    case AFNUM_INET6:
371*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_LEN(bp, sizeof(nd_ipv6));
372411677aeSAaron LI 		addrtostr6(bp, group_buf, sizeof(group_buf));
373*ed775ee7SAntonio Huete Jimenez 		bp += sizeof(nd_ipv6);
37441c99275SPeter Avalos 		break;
37541c99275SPeter Avalos 	    default:
37641c99275SPeter Avalos 		goto trunc;
37741c99275SPeter Avalos 		break;
37841c99275SPeter Avalos 	    }
37941c99275SPeter Avalos 
38041c99275SPeter Avalos 	    /*
38141c99275SPeter Avalos 	     * Options decoding can go here.
38241c99275SPeter Avalos 	     */
383*ed775ee7SAntonio Huete Jimenez 	    switch (pgm_type_val) {
38441c99275SPeter Avalos 		case PGM_NAK:
385*ed775ee7SAntonio Huete Jimenez 		    ND_PRINT("NAK ");
38641c99275SPeter Avalos 		    break;
38741c99275SPeter Avalos 		case PGM_NULLNAK:
388*ed775ee7SAntonio Huete Jimenez 		    ND_PRINT("NNAK ");
38941c99275SPeter Avalos 		    break;
39041c99275SPeter Avalos 		case PGM_NCF:
391*ed775ee7SAntonio Huete Jimenez 		    ND_PRINT("NCF ");
39241c99275SPeter Avalos 		    break;
39341c99275SPeter Avalos 		default:
39441c99275SPeter Avalos                     break;
39541c99275SPeter Avalos 	    }
396*ed775ee7SAntonio Huete Jimenez 	    ND_PRINT("(%s -> %s), seq %u",
397*ed775ee7SAntonio Huete Jimenez 			 source_buf, group_buf, GET_BE_U_4(nak->pgmn_seq));
39841c99275SPeter Avalos 	    break;
39941c99275SPeter Avalos 	}
40041c99275SPeter Avalos 
40127bfbee1SPeter Avalos 	case PGM_ACK: {
402411677aeSAaron LI 	    const struct pgm_ack *ack;
40327bfbee1SPeter Avalos 
404411677aeSAaron LI 	    ack = (const struct pgm_ack *)(pgm + 1);
405*ed775ee7SAntonio Huete Jimenez 	    ND_TCHECK_SIZE(ack);
406*ed775ee7SAntonio Huete Jimenez 	    ND_PRINT("ACK seq %u",
407*ed775ee7SAntonio Huete Jimenez 			 GET_BE_U_4(ack->pgma_rx_max_seq));
408411677aeSAaron LI 	    bp = (const u_char *) (ack + 1);
40927bfbee1SPeter Avalos 	    break;
41027bfbee1SPeter Avalos 	}
41127bfbee1SPeter Avalos 
41241c99275SPeter Avalos 	case PGM_SPMR:
413*ed775ee7SAntonio Huete Jimenez 	    ND_PRINT("SPMR");
41441c99275SPeter Avalos 	    break;
41541c99275SPeter Avalos 
41641c99275SPeter Avalos 	default:
417*ed775ee7SAntonio Huete Jimenez 	    ND_PRINT("UNKNOWN type 0x%02x", pgm_type_val);
41841c99275SPeter Avalos 	    break;
41941c99275SPeter Avalos 
42041c99275SPeter Avalos 	}
421*ed775ee7SAntonio Huete Jimenez 	if (GET_U_1(pgm->pgm_options) & PGM_OPT_BIT_PRESENT) {
42241c99275SPeter Avalos 
42341c99275SPeter Avalos 	    /*
42441c99275SPeter Avalos 	     * make sure there's enough for the first option header
42541c99275SPeter Avalos 	     */
426*ed775ee7SAntonio Huete Jimenez 	    ND_TCHECK_LEN(bp, PGM_MIN_OPT_LEN);
42741c99275SPeter Avalos 
42841c99275SPeter Avalos 	    /*
42941c99275SPeter Avalos 	     * That option header MUST be an OPT_LENGTH option
43041c99275SPeter Avalos 	     * (see the first paragraph of section 9.1 in RFC 3208).
43141c99275SPeter Avalos 	     */
432*ed775ee7SAntonio Huete Jimenez 	    opt_type = GET_U_1(bp);
433*ed775ee7SAntonio Huete Jimenez 	    bp++;
43441c99275SPeter Avalos 	    if ((opt_type & PGM_OPT_MASK) != PGM_OPT_LENGTH) {
435*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[First option bad, should be PGM_OPT_LENGTH, is %u]", opt_type & PGM_OPT_MASK);
43641c99275SPeter Avalos 		return;
43741c99275SPeter Avalos 	    }
438*ed775ee7SAntonio Huete Jimenez 	    opt_len = GET_U_1(bp);
439*ed775ee7SAntonio Huete Jimenez 	    bp++;
44041c99275SPeter Avalos 	    if (opt_len != 4) {
441*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[Bad OPT_LENGTH option, length %u != 4]", opt_len);
44241c99275SPeter Avalos 		return;
44341c99275SPeter Avalos 	    }
444*ed775ee7SAntonio Huete Jimenez 	    opts_len = GET_BE_U_2(bp);
445411677aeSAaron LI 	    bp += sizeof(uint16_t);
446*ed775ee7SAntonio Huete Jimenez 	    if (opts_len < 4) {
447*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("[Bad total option length %u < 4]", opts_len);
448*ed775ee7SAntonio Huete Jimenez 		return;
449*ed775ee7SAntonio Huete Jimenez 	    }
450*ed775ee7SAntonio Huete Jimenez 	    ND_PRINT(" OPTS LEN %u", opts_len);
45141c99275SPeter Avalos 	    opts_len -= 4;
45241c99275SPeter Avalos 
45341c99275SPeter Avalos 	    while (opts_len) {
45441c99275SPeter Avalos 		if (opts_len < PGM_MIN_OPT_LEN) {
455*ed775ee7SAntonio Huete Jimenez 		    ND_PRINT("[Total option length leaves no room for final option]");
456411677aeSAaron LI 		    return;
457411677aeSAaron LI 		}
458*ed775ee7SAntonio Huete Jimenez 		opt_type = GET_U_1(bp);
459*ed775ee7SAntonio Huete Jimenez 		bp++;
460*ed775ee7SAntonio Huete Jimenez 		opt_len = GET_U_1(bp);
461*ed775ee7SAntonio Huete Jimenez 		bp++;
46241c99275SPeter Avalos 		if (opt_len < PGM_MIN_OPT_LEN) {
463*ed775ee7SAntonio Huete Jimenez 		    ND_PRINT("[Bad option, length %u < %u]", opt_len,
464*ed775ee7SAntonio Huete Jimenez 		        PGM_MIN_OPT_LEN);
46541c99275SPeter Avalos 		    break;
46641c99275SPeter Avalos 		}
46741c99275SPeter Avalos 		if (opts_len < opt_len) {
468*ed775ee7SAntonio Huete Jimenez 		    ND_PRINT("[Total option length leaves no room for final option]");
46941c99275SPeter Avalos 		    return;
47041c99275SPeter Avalos 		}
471*ed775ee7SAntonio Huete Jimenez 		ND_TCHECK_LEN(bp, opt_len - 2);
47241c99275SPeter Avalos 
47341c99275SPeter Avalos 		switch (opt_type & PGM_OPT_MASK) {
47441c99275SPeter Avalos 		case PGM_OPT_LENGTH:
475411677aeSAaron LI #define PGM_OPT_LENGTH_LEN	(2+2)
476411677aeSAaron LI 		    if (opt_len != PGM_OPT_LENGTH_LEN) {
477*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("[Bad OPT_LENGTH option, length %u != %u]",
478*ed775ee7SAntonio Huete Jimenez 			    opt_len, PGM_OPT_LENGTH_LEN);
47941c99275SPeter Avalos 			return;
48041c99275SPeter Avalos 		    }
481*ed775ee7SAntonio Huete Jimenez 		    ND_PRINT(" OPTS LEN (extra?) %u", GET_BE_U_2(bp));
482411677aeSAaron LI 		    bp += 2;
483411677aeSAaron LI 		    opts_len -= PGM_OPT_LENGTH_LEN;
48441c99275SPeter Avalos 		    break;
48541c99275SPeter Avalos 
48641c99275SPeter Avalos 		case PGM_OPT_FRAGMENT:
487411677aeSAaron LI #define PGM_OPT_FRAGMENT_LEN	(2+2+4+4+4)
488411677aeSAaron LI 		    if (opt_len != PGM_OPT_FRAGMENT_LEN) {
489*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("[Bad OPT_FRAGMENT option, length %u != %u]",
490*ed775ee7SAntonio Huete Jimenez 			    opt_len, PGM_OPT_FRAGMENT_LEN);
49141c99275SPeter Avalos 			return;
49241c99275SPeter Avalos 		    }
493411677aeSAaron LI 		    bp += 2;
494*ed775ee7SAntonio Huete Jimenez 		    seq = GET_BE_U_4(bp);
495411677aeSAaron LI 		    bp += 4;
496*ed775ee7SAntonio Huete Jimenez 		    offset = GET_BE_U_4(bp);
497411677aeSAaron LI 		    bp += 4;
498*ed775ee7SAntonio Huete Jimenez 		    len = GET_BE_U_4(bp);
499411677aeSAaron LI 		    bp += 4;
500*ed775ee7SAntonio Huete Jimenez 		    ND_PRINT(" FRAG seq %u off %u len %u", seq, offset, len);
501411677aeSAaron LI 		    opts_len -= PGM_OPT_FRAGMENT_LEN;
50241c99275SPeter Avalos 		    break;
50341c99275SPeter Avalos 
50441c99275SPeter Avalos 		case PGM_OPT_NAK_LIST:
505411677aeSAaron LI 		    bp += 2;
506411677aeSAaron LI 		    opt_len -= 4;	/* option header */
507*ed775ee7SAntonio Huete Jimenez 		    ND_PRINT(" NAK LIST");
50841c99275SPeter Avalos 		    while (opt_len) {
509411677aeSAaron LI 			if (opt_len < 4) {
510*ed775ee7SAntonio Huete Jimenez 			    ND_PRINT("[Option length not a multiple of 4]");
51141c99275SPeter Avalos 			    return;
51241c99275SPeter Avalos 			}
513*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" %u", GET_BE_U_4(bp));
514411677aeSAaron LI 			bp += 4;
515411677aeSAaron LI 			opt_len -= 4;
516411677aeSAaron LI 			opts_len -= 4;
51741c99275SPeter Avalos 		    }
51841c99275SPeter Avalos 		    break;
51941c99275SPeter Avalos 
52041c99275SPeter Avalos 		case PGM_OPT_JOIN:
521411677aeSAaron LI #define PGM_OPT_JOIN_LEN	(2+2+4)
522411677aeSAaron LI 		    if (opt_len != PGM_OPT_JOIN_LEN) {
523*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("[Bad OPT_JOIN option, length %u != %u]",
524*ed775ee7SAntonio Huete Jimenez 			    opt_len, PGM_OPT_JOIN_LEN);
52541c99275SPeter Avalos 			return;
52641c99275SPeter Avalos 		    }
527411677aeSAaron LI 		    bp += 2;
528*ed775ee7SAntonio Huete Jimenez 		    seq = GET_BE_U_4(bp);
529411677aeSAaron LI 		    bp += 4;
530*ed775ee7SAntonio Huete Jimenez 		    ND_PRINT(" JOIN %u", seq);
531411677aeSAaron LI 		    opts_len -= PGM_OPT_JOIN_LEN;
53241c99275SPeter Avalos 		    break;
53341c99275SPeter Avalos 
53441c99275SPeter Avalos 		case PGM_OPT_NAK_BO_IVL:
535411677aeSAaron LI #define PGM_OPT_NAK_BO_IVL_LEN	(2+2+4+4)
536411677aeSAaron LI 		    if (opt_len != PGM_OPT_NAK_BO_IVL_LEN) {
537*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("[Bad OPT_NAK_BO_IVL option, length %u != %u]",
538*ed775ee7SAntonio Huete Jimenez 			    opt_len, PGM_OPT_NAK_BO_IVL_LEN);
53941c99275SPeter Avalos 			return;
54041c99275SPeter Avalos 		    }
541411677aeSAaron LI 		    bp += 2;
542*ed775ee7SAntonio Huete Jimenez 		    offset = GET_BE_U_4(bp);
543411677aeSAaron LI 		    bp += 4;
544*ed775ee7SAntonio Huete Jimenez 		    seq = GET_BE_U_4(bp);
545411677aeSAaron LI 		    bp += 4;
546*ed775ee7SAntonio Huete Jimenez 		    ND_PRINT(" BACKOFF ivl %u ivlseq %u", offset, seq);
547411677aeSAaron LI 		    opts_len -= PGM_OPT_NAK_BO_IVL_LEN;
54841c99275SPeter Avalos 		    break;
54941c99275SPeter Avalos 
55041c99275SPeter Avalos 		case PGM_OPT_NAK_BO_RNG:
551411677aeSAaron LI #define PGM_OPT_NAK_BO_RNG_LEN	(2+2+4+4)
552411677aeSAaron LI 		    if (opt_len != PGM_OPT_NAK_BO_RNG_LEN) {
553*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("[Bad OPT_NAK_BO_RNG option, length %u != %u]",
554*ed775ee7SAntonio Huete Jimenez 			    opt_len, PGM_OPT_NAK_BO_RNG_LEN);
55541c99275SPeter Avalos 			return;
55641c99275SPeter Avalos 		    }
557411677aeSAaron LI 		    bp += 2;
558*ed775ee7SAntonio Huete Jimenez 		    offset = GET_BE_U_4(bp);
559411677aeSAaron LI 		    bp += 4;
560*ed775ee7SAntonio Huete Jimenez 		    seq = GET_BE_U_4(bp);
561411677aeSAaron LI 		    bp += 4;
562*ed775ee7SAntonio Huete Jimenez 		    ND_PRINT(" BACKOFF max %u min %u", offset, seq);
563411677aeSAaron LI 		    opts_len -= PGM_OPT_NAK_BO_RNG_LEN;
56441c99275SPeter Avalos 		    break;
56541c99275SPeter Avalos 
56641c99275SPeter Avalos 		case PGM_OPT_REDIRECT:
567411677aeSAaron LI #define PGM_OPT_REDIRECT_FIXED_LEN	(2+2+2+2)
568411677aeSAaron LI 		    if (opt_len < PGM_OPT_REDIRECT_FIXED_LEN) {
569*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("[Bad OPT_REDIRECT option, length %u < %u]",
570*ed775ee7SAntonio Huete Jimenez 			    opt_len, PGM_OPT_REDIRECT_FIXED_LEN);
571411677aeSAaron LI 			return;
572411677aeSAaron LI 		    }
573411677aeSAaron LI 		    bp += 2;
574*ed775ee7SAntonio Huete Jimenez 		    nla_afnum = GET_BE_U_2(bp);
575411677aeSAaron LI 		    bp += 2+2;
576411677aeSAaron LI 		    switch (nla_afnum) {
577411677aeSAaron LI 		    case AFNUM_INET:
578*ed775ee7SAntonio Huete Jimenez 			if (opt_len != PGM_OPT_REDIRECT_FIXED_LEN + sizeof(nd_ipv4)) {
579*ed775ee7SAntonio Huete Jimenez 			    ND_PRINT("[Bad OPT_REDIRECT option, length %u != %u + address size]",
580*ed775ee7SAntonio Huete Jimenez 			        opt_len, PGM_OPT_REDIRECT_FIXED_LEN);
581411677aeSAaron LI 			    return;
582411677aeSAaron LI 			}
583*ed775ee7SAntonio Huete Jimenez 			ND_TCHECK_LEN(bp, sizeof(nd_ipv4));
584411677aeSAaron LI 			addrtostr(bp, nla_buf, sizeof(nla_buf));
585*ed775ee7SAntonio Huete Jimenez 			bp += sizeof(nd_ipv4);
586*ed775ee7SAntonio Huete Jimenez 			opts_len -= PGM_OPT_REDIRECT_FIXED_LEN + sizeof(nd_ipv4);
58741c99275SPeter Avalos 			break;
588411677aeSAaron LI 		    case AFNUM_INET6:
589*ed775ee7SAntonio Huete Jimenez 			if (opt_len != PGM_OPT_REDIRECT_FIXED_LEN + sizeof(nd_ipv6)) {
590*ed775ee7SAntonio Huete Jimenez 			    ND_PRINT("[Bad OPT_REDIRECT option, length %u != %u + address size]",
591*ed775ee7SAntonio Huete Jimenez 			        opt_len, PGM_OPT_REDIRECT_FIXED_LEN);
592411677aeSAaron LI 			    return;
593411677aeSAaron LI 			}
594*ed775ee7SAntonio Huete Jimenez 			ND_TCHECK_LEN(bp, sizeof(nd_ipv6));
595411677aeSAaron LI 			addrtostr6(bp, nla_buf, sizeof(nla_buf));
596*ed775ee7SAntonio Huete Jimenez 			bp += sizeof(nd_ipv6);
597*ed775ee7SAntonio Huete Jimenez 			opts_len -= PGM_OPT_REDIRECT_FIXED_LEN + sizeof(nd_ipv6);
59841c99275SPeter Avalos 			break;
59941c99275SPeter Avalos 		    default:
60041c99275SPeter Avalos 			goto trunc;
60141c99275SPeter Avalos 			break;
60241c99275SPeter Avalos 		    }
60341c99275SPeter Avalos 
604*ed775ee7SAntonio Huete Jimenez 		    ND_PRINT(" REDIRECT %s",  nla_buf);
60541c99275SPeter Avalos 		    break;
60641c99275SPeter Avalos 
60741c99275SPeter Avalos 		case PGM_OPT_PARITY_PRM:
608411677aeSAaron LI #define PGM_OPT_PARITY_PRM_LEN	(2+2+4)
609411677aeSAaron LI 		    if (opt_len != PGM_OPT_PARITY_PRM_LEN) {
610*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("[Bad OPT_PARITY_PRM option, length %u != %u]",
611*ed775ee7SAntonio Huete Jimenez 			    opt_len, PGM_OPT_PARITY_PRM_LEN);
61241c99275SPeter Avalos 			return;
61341c99275SPeter Avalos 		    }
614411677aeSAaron LI 		    bp += 2;
615*ed775ee7SAntonio Huete Jimenez 		    len = GET_BE_U_4(bp);
616411677aeSAaron LI 		    bp += 4;
617*ed775ee7SAntonio Huete Jimenez 		    ND_PRINT(" PARITY MAXTGS %u", len);
618411677aeSAaron LI 		    opts_len -= PGM_OPT_PARITY_PRM_LEN;
61941c99275SPeter Avalos 		    break;
62041c99275SPeter Avalos 
62141c99275SPeter Avalos 		case PGM_OPT_PARITY_GRP:
622411677aeSAaron LI #define PGM_OPT_PARITY_GRP_LEN	(2+2+4)
623411677aeSAaron LI 		    if (opt_len != PGM_OPT_PARITY_GRP_LEN) {
624*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("[Bad OPT_PARITY_GRP option, length %u != %u]",
625*ed775ee7SAntonio Huete Jimenez 			    opt_len, PGM_OPT_PARITY_GRP_LEN);
62641c99275SPeter Avalos 			return;
62741c99275SPeter Avalos 		    }
628411677aeSAaron LI 		    bp += 2;
629*ed775ee7SAntonio Huete Jimenez 		    seq = GET_BE_U_4(bp);
630411677aeSAaron LI 		    bp += 4;
631*ed775ee7SAntonio Huete Jimenez 		    ND_PRINT(" PARITY GROUP %u", seq);
632411677aeSAaron LI 		    opts_len -= PGM_OPT_PARITY_GRP_LEN;
63341c99275SPeter Avalos 		    break;
63441c99275SPeter Avalos 
63541c99275SPeter Avalos 		case PGM_OPT_CURR_TGSIZE:
636411677aeSAaron LI #define PGM_OPT_CURR_TGSIZE_LEN	(2+2+4)
637411677aeSAaron LI 		    if (opt_len != PGM_OPT_CURR_TGSIZE_LEN) {
638*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("[Bad OPT_CURR_TGSIZE option, length %u != %u]",
639*ed775ee7SAntonio Huete Jimenez 			    opt_len, PGM_OPT_CURR_TGSIZE_LEN);
64041c99275SPeter Avalos 			return;
64141c99275SPeter Avalos 		    }
642411677aeSAaron LI 		    bp += 2;
643*ed775ee7SAntonio Huete Jimenez 		    len = GET_BE_U_4(bp);
644411677aeSAaron LI 		    bp += 4;
645*ed775ee7SAntonio Huete Jimenez 		    ND_PRINT(" PARITY ATGS %u", len);
646411677aeSAaron LI 		    opts_len -= PGM_OPT_CURR_TGSIZE_LEN;
64741c99275SPeter Avalos 		    break;
64841c99275SPeter Avalos 
64941c99275SPeter Avalos 		case PGM_OPT_NBR_UNREACH:
650411677aeSAaron LI #define PGM_OPT_NBR_UNREACH_LEN	(2+2)
651411677aeSAaron LI 		    if (opt_len != PGM_OPT_NBR_UNREACH_LEN) {
652*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("[Bad OPT_NBR_UNREACH option, length %u != %u]",
653*ed775ee7SAntonio Huete Jimenez 			    opt_len, PGM_OPT_NBR_UNREACH_LEN);
65441c99275SPeter Avalos 			return;
65541c99275SPeter Avalos 		    }
656411677aeSAaron LI 		    bp += 2;
657*ed775ee7SAntonio Huete Jimenez 		    ND_PRINT(" NBR_UNREACH");
658411677aeSAaron LI 		    opts_len -= PGM_OPT_NBR_UNREACH_LEN;
65941c99275SPeter Avalos 		    break;
66041c99275SPeter Avalos 
66141c99275SPeter Avalos 		case PGM_OPT_PATH_NLA:
662*ed775ee7SAntonio Huete Jimenez 		    ND_PRINT(" PATH_NLA [%u]", opt_len);
66341c99275SPeter Avalos 		    bp += opt_len;
66441c99275SPeter Avalos 		    opts_len -= opt_len;
66541c99275SPeter Avalos 		    break;
66641c99275SPeter Avalos 
66741c99275SPeter Avalos 		case PGM_OPT_SYN:
668411677aeSAaron LI #define PGM_OPT_SYN_LEN	(2+2)
669411677aeSAaron LI 		    if (opt_len != PGM_OPT_SYN_LEN) {
670*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("[Bad OPT_SYN option, length %u != %u]",
671*ed775ee7SAntonio Huete Jimenez 			    opt_len, PGM_OPT_SYN_LEN);
67241c99275SPeter Avalos 			return;
67341c99275SPeter Avalos 		    }
674411677aeSAaron LI 		    bp += 2;
675*ed775ee7SAntonio Huete Jimenez 		    ND_PRINT(" SYN");
676411677aeSAaron LI 		    opts_len -= PGM_OPT_SYN_LEN;
67741c99275SPeter Avalos 		    break;
67841c99275SPeter Avalos 
67941c99275SPeter Avalos 		case PGM_OPT_FIN:
680411677aeSAaron LI #define PGM_OPT_FIN_LEN	(2+2)
681411677aeSAaron LI 		    if (opt_len != PGM_OPT_FIN_LEN) {
682*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("[Bad OPT_FIN option, length %u != %u]",
683*ed775ee7SAntonio Huete Jimenez 			    opt_len, PGM_OPT_FIN_LEN);
68441c99275SPeter Avalos 			return;
68541c99275SPeter Avalos 		    }
686411677aeSAaron LI 		    bp += 2;
687*ed775ee7SAntonio Huete Jimenez 		    ND_PRINT(" FIN");
688411677aeSAaron LI 		    opts_len -= PGM_OPT_FIN_LEN;
68941c99275SPeter Avalos 		    break;
69041c99275SPeter Avalos 
69141c99275SPeter Avalos 		case PGM_OPT_RST:
692411677aeSAaron LI #define PGM_OPT_RST_LEN	(2+2)
693411677aeSAaron LI 		    if (opt_len != PGM_OPT_RST_LEN) {
694*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("[Bad OPT_RST option, length %u != %u]",
695*ed775ee7SAntonio Huete Jimenez 			    opt_len, PGM_OPT_RST_LEN);
69641c99275SPeter Avalos 			return;
69741c99275SPeter Avalos 		    }
698411677aeSAaron LI 		    bp += 2;
699*ed775ee7SAntonio Huete Jimenez 		    ND_PRINT(" RST");
700411677aeSAaron LI 		    opts_len -= PGM_OPT_RST_LEN;
70141c99275SPeter Avalos 		    break;
70241c99275SPeter Avalos 
70341c99275SPeter Avalos 		case PGM_OPT_CR:
704*ed775ee7SAntonio Huete Jimenez 		    ND_PRINT(" CR");
70541c99275SPeter Avalos 		    bp += opt_len;
70641c99275SPeter Avalos 		    opts_len -= opt_len;
70741c99275SPeter Avalos 		    break;
70841c99275SPeter Avalos 
70941c99275SPeter Avalos 		case PGM_OPT_CRQST:
710411677aeSAaron LI #define PGM_OPT_CRQST_LEN	(2+2)
711411677aeSAaron LI 		    if (opt_len != PGM_OPT_CRQST_LEN) {
712*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("[Bad OPT_CRQST option, length %u != %u]",
713*ed775ee7SAntonio Huete Jimenez 			    opt_len, PGM_OPT_CRQST_LEN);
71441c99275SPeter Avalos 			return;
71541c99275SPeter Avalos 		    }
716411677aeSAaron LI 		    bp += 2;
717*ed775ee7SAntonio Huete Jimenez 		    ND_PRINT(" CRQST");
718411677aeSAaron LI 		    opts_len -= PGM_OPT_CRQST_LEN;
71941c99275SPeter Avalos 		    break;
72041c99275SPeter Avalos 
72127bfbee1SPeter Avalos 		case PGM_OPT_PGMCC_DATA:
722411677aeSAaron LI #define PGM_OPT_PGMCC_DATA_FIXED_LEN	(2+2+4+2+2)
723411677aeSAaron LI 		    if (opt_len < PGM_OPT_PGMCC_DATA_FIXED_LEN) {
724*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("[Bad OPT_PGMCC_DATA option, length %u < %u]",
725*ed775ee7SAntonio Huete Jimenez 			    opt_len, PGM_OPT_PGMCC_DATA_FIXED_LEN);
726411677aeSAaron LI 			return;
727411677aeSAaron LI 		    }
728411677aeSAaron LI 		    bp += 2;
729*ed775ee7SAntonio Huete Jimenez 		    offset = GET_BE_U_4(bp);
730411677aeSAaron LI 		    bp += 4;
731*ed775ee7SAntonio Huete Jimenez 		    nla_afnum = GET_BE_U_2(bp);
732411677aeSAaron LI 		    bp += 2+2;
733411677aeSAaron LI 		    switch (nla_afnum) {
734411677aeSAaron LI 		    case AFNUM_INET:
735*ed775ee7SAntonio Huete Jimenez 			if (opt_len != PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(nd_ipv4)) {
736*ed775ee7SAntonio Huete Jimenez 			    ND_PRINT("[Bad OPT_PGMCC_DATA option, length %u != %u + address size]",
737*ed775ee7SAntonio Huete Jimenez 			        opt_len, PGM_OPT_PGMCC_DATA_FIXED_LEN);
738411677aeSAaron LI 			    return;
739411677aeSAaron LI 			}
740*ed775ee7SAntonio Huete Jimenez 			ND_TCHECK_LEN(bp, sizeof(nd_ipv4));
741411677aeSAaron LI 			addrtostr(bp, nla_buf, sizeof(nla_buf));
742*ed775ee7SAntonio Huete Jimenez 			bp += sizeof(nd_ipv4);
743*ed775ee7SAntonio Huete Jimenez 			opts_len -= PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(nd_ipv4);
74427bfbee1SPeter Avalos 			break;
745411677aeSAaron LI 		    case AFNUM_INET6:
746*ed775ee7SAntonio Huete Jimenez 			if (opt_len != PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(nd_ipv6)) {
747*ed775ee7SAntonio Huete Jimenez 			    ND_PRINT("[Bad OPT_PGMCC_DATA option, length %u != %u + address size]",
748*ed775ee7SAntonio Huete Jimenez 			        opt_len, PGM_OPT_PGMCC_DATA_FIXED_LEN);
749411677aeSAaron LI 			    return;
750411677aeSAaron LI 			}
751*ed775ee7SAntonio Huete Jimenez 			ND_TCHECK_LEN(bp, sizeof(nd_ipv6));
752411677aeSAaron LI 			addrtostr6(bp, nla_buf, sizeof(nla_buf));
753*ed775ee7SAntonio Huete Jimenez 			bp += sizeof(nd_ipv6);
754*ed775ee7SAntonio Huete Jimenez 			opts_len -= PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(nd_ipv6);
75527bfbee1SPeter Avalos 			break;
75627bfbee1SPeter Avalos 		    default:
75727bfbee1SPeter Avalos 			goto trunc;
75827bfbee1SPeter Avalos 			break;
75927bfbee1SPeter Avalos 		    }
76027bfbee1SPeter Avalos 
761*ed775ee7SAntonio Huete Jimenez 		    ND_PRINT(" PGMCC DATA %u %s", offset, nla_buf);
76227bfbee1SPeter Avalos 		    break;
76327bfbee1SPeter Avalos 
76427bfbee1SPeter Avalos 		case PGM_OPT_PGMCC_FEEDBACK:
765411677aeSAaron LI #define PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN	(2+2+4+2+2)
766411677aeSAaron LI 		    if (opt_len < PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN) {
767*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("[Bad PGM_OPT_PGMCC_FEEDBACK option, length %u < %u]",
768*ed775ee7SAntonio Huete Jimenez 			    opt_len, PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN);
769411677aeSAaron LI 			return;
770411677aeSAaron LI 		    }
771411677aeSAaron LI 		    bp += 2;
772*ed775ee7SAntonio Huete Jimenez 		    offset = GET_BE_U_4(bp);
773411677aeSAaron LI 		    bp += 4;
774*ed775ee7SAntonio Huete Jimenez 		    nla_afnum = GET_BE_U_2(bp);
775411677aeSAaron LI 		    bp += 2+2;
776411677aeSAaron LI 		    switch (nla_afnum) {
777411677aeSAaron LI 		    case AFNUM_INET:
778*ed775ee7SAntonio Huete Jimenez 			if (opt_len != PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(nd_ipv4)) {
779*ed775ee7SAntonio Huete Jimenez 			    ND_PRINT("[Bad OPT_PGMCC_FEEDBACK option, length %u != %u + address size]",
780*ed775ee7SAntonio Huete Jimenez 			        opt_len, PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN);
781411677aeSAaron LI 			    return;
782411677aeSAaron LI 			}
783*ed775ee7SAntonio Huete Jimenez 			ND_TCHECK_LEN(bp, sizeof(nd_ipv4));
784411677aeSAaron LI 			addrtostr(bp, nla_buf, sizeof(nla_buf));
785*ed775ee7SAntonio Huete Jimenez 			bp += sizeof(nd_ipv4);
786*ed775ee7SAntonio Huete Jimenez 			opts_len -= PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(nd_ipv4);
78727bfbee1SPeter Avalos 			break;
788411677aeSAaron LI 		    case AFNUM_INET6:
789*ed775ee7SAntonio Huete Jimenez 			if (opt_len != PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(nd_ipv6)) {
790*ed775ee7SAntonio Huete Jimenez 			    ND_PRINT("[Bad OPT_PGMCC_FEEDBACK option, length %u != %u + address size]",
791*ed775ee7SAntonio Huete Jimenez 			        opt_len, PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN);
792411677aeSAaron LI 			    return;
793411677aeSAaron LI 			}
794*ed775ee7SAntonio Huete Jimenez 			ND_TCHECK_LEN(bp, sizeof(nd_ipv6));
795411677aeSAaron LI 			addrtostr6(bp, nla_buf, sizeof(nla_buf));
796*ed775ee7SAntonio Huete Jimenez 			bp += sizeof(nd_ipv6);
797*ed775ee7SAntonio Huete Jimenez 			opts_len -= PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(nd_ipv6);
79827bfbee1SPeter Avalos 			break;
79927bfbee1SPeter Avalos 		    default:
80027bfbee1SPeter Avalos 			goto trunc;
80127bfbee1SPeter Avalos 			break;
80227bfbee1SPeter Avalos 		    }
80327bfbee1SPeter Avalos 
804*ed775ee7SAntonio Huete Jimenez 		    ND_PRINT(" PGMCC FEEDBACK %u %s", offset, nla_buf);
80527bfbee1SPeter Avalos 		    break;
80627bfbee1SPeter Avalos 
80741c99275SPeter Avalos 		default:
808*ed775ee7SAntonio Huete Jimenez 		    ND_PRINT(" OPT_%02X [%u] ", opt_type, opt_len);
80941c99275SPeter Avalos 		    bp += opt_len;
81041c99275SPeter Avalos 		    opts_len -= opt_len;
81141c99275SPeter Avalos 		    break;
81241c99275SPeter Avalos 		}
81341c99275SPeter Avalos 
81441c99275SPeter Avalos 		if (opt_type & PGM_OPT_END)
81541c99275SPeter Avalos 		    break;
81641c99275SPeter Avalos 	     }
81741c99275SPeter Avalos 	}
81841c99275SPeter Avalos 
819*ed775ee7SAntonio Huete Jimenez 	ND_PRINT(" [%u]", length);
820411677aeSAaron LI 	if (ndo->ndo_packettype == PT_PGM_ZMTP1 &&
821*ed775ee7SAntonio Huete Jimenez 	    (pgm_type_val == PGM_ODATA || pgm_type_val == PGM_RDATA))
822*ed775ee7SAntonio Huete Jimenez 		zmtp1_datagram_print(ndo, bp,
823*ed775ee7SAntonio Huete Jimenez 				     GET_BE_U_2(pgm->pgm_length));
82441c99275SPeter Avalos 
82541c99275SPeter Avalos 	return;
82641c99275SPeter Avalos 
82741c99275SPeter Avalos trunc:
828*ed775ee7SAntonio Huete Jimenez 	nd_print_trunc(ndo);
82941c99275SPeter Avalos }
830