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