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