blob: ccb0b46afef9982c4e1851063baa355f101e8b05 [file] [log] [blame]
The Android Open Source Project2949f582009-03-03 19:30:46 -08001/*
2 * Redistribution and use in source and binary forms, with or without
3 * modification, are permitted provided that: (1) source code
4 * distributions retain the above copyright notice and this paragraph
5 * in its entirety, and (2) distributions including binary code include
6 * the above copyright notice and this paragraph in its entirety in
7 * the documentation or other materials provided with the distribution.
8 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
9 * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
10 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
11 * FOR A PARTICULAR PURPOSE.
12 *
13 * Original code by Andy Heffernan (ahh@juniper.net)
14 */
15
Elliott Hughese2e3bd12017-05-15 10:59:29 -070016/* \summary: Pragmatic General Multicast (PGM) printer */
17
The Android Open Source Project2949f582009-03-03 19:30:46 -080018#ifdef HAVE_CONFIG_H
Elliott Hughes820eced2021-08-20 18:00:50 -070019#include <config.h>
The Android Open Source Project2949f582009-03-03 19:30:46 -080020#endif
21
Elliott Hughes820eced2021-08-20 18:00:50 -070022#include "netdissect-stdinc.h"
The Android Open Source Project2949f582009-03-03 19:30:46 -080023
Elliott Hughese2e3bd12017-05-15 10:59:29 -070024#include "netdissect.h"
The Android Open Source Project2949f582009-03-03 19:30:46 -080025#include "extract.h"
26#include "addrtoname.h"
Elliott Hughese2e3bd12017-05-15 10:59:29 -070027#include "addrtostr.h"
The Android Open Source Project2949f582009-03-03 19:30:46 -080028
29#include "ip.h"
The Android Open Source Project2949f582009-03-03 19:30:46 -080030#include "ip6.h"
The Android Open Source Project2949f582009-03-03 19:30:46 -080031#include "ipproto.h"
Elliott Hughes892a68b2015-10-19 14:43:53 -070032#include "af.h"
The Android Open Source Project2949f582009-03-03 19:30:46 -080033
34/*
35 * PGM header (RFC 3208)
36 */
37struct pgm_header {
Elliott Hughes820eced2021-08-20 18:00:50 -070038 nd_uint16_t pgm_sport;
39 nd_uint16_t pgm_dport;
40 nd_uint8_t pgm_type;
41 nd_uint8_t pgm_options;
42 nd_uint16_t pgm_sum;
43 nd_byte pgm_gsid[6];
44 nd_uint16_t pgm_length;
The Android Open Source Project2949f582009-03-03 19:30:46 -080045};
46
47struct pgm_spm {
Elliott Hughes820eced2021-08-20 18:00:50 -070048 nd_uint32_t pgms_seq;
49 nd_uint32_t pgms_trailseq;
50 nd_uint32_t pgms_leadseq;
51 nd_uint16_t pgms_nla_afi;
52 nd_uint16_t pgms_reserved;
Elliott Hughes892a68b2015-10-19 14:43:53 -070053 /* ... uint8_t pgms_nla[0]; */
The Android Open Source Project2949f582009-03-03 19:30:46 -080054 /* ... options */
55};
56
57struct pgm_nak {
Elliott Hughes820eced2021-08-20 18:00:50 -070058 nd_uint32_t pgmn_seq;
59 nd_uint16_t pgmn_source_afi;
60 nd_uint16_t pgmn_reserved;
Elliott Hughes892a68b2015-10-19 14:43:53 -070061 /* ... uint8_t pgmn_source[0]; */
62 /* ... uint16_t pgmn_group_afi */
63 /* ... uint16_t pgmn_reserved2; */
64 /* ... uint8_t pgmn_group[0]; */
The Android Open Source Project2949f582009-03-03 19:30:46 -080065 /* ... options */
66};
67
JP Abgrall53f17a92014-02-12 14:02:41 -080068struct pgm_ack {
Elliott Hughes820eced2021-08-20 18:00:50 -070069 nd_uint32_t pgma_rx_max_seq;
70 nd_uint32_t pgma_bitmap;
JP Abgrall53f17a92014-02-12 14:02:41 -080071 /* ... options */
72};
73
The Android Open Source Project2949f582009-03-03 19:30:46 -080074struct pgm_poll {
Elliott Hughes820eced2021-08-20 18:00:50 -070075 nd_uint32_t pgmp_seq;
76 nd_uint16_t pgmp_round;
77 nd_uint16_t pgmp_subtype;
78 nd_uint16_t pgmp_nla_afi;
79 nd_uint16_t pgmp_reserved;
Elliott Hughes892a68b2015-10-19 14:43:53 -070080 /* ... uint8_t pgmp_nla[0]; */
The Android Open Source Project2949f582009-03-03 19:30:46 -080081 /* ... options */
82};
83
Elliott Hughes820eced2021-08-20 18:00:50 -070084struct pgm_polr {
85 nd_uint32_t pgmp_seq;
86 nd_uint16_t pgmp_round;
87 nd_uint16_t pgmp_reserved;
88 /* ... options */
89};
90
The Android Open Source Project2949f582009-03-03 19:30:46 -080091struct pgm_data {
Elliott Hughes820eced2021-08-20 18:00:50 -070092 nd_uint32_t pgmd_seq;
93 nd_uint32_t pgmd_trailseq;
The Android Open Source Project2949f582009-03-03 19:30:46 -080094 /* ... options */
95};
96
97typedef enum _pgm_type {
98 PGM_SPM = 0, /* source path message */
99 PGM_POLL = 1, /* POLL Request */
100 PGM_POLR = 2, /* POLL Response */
101 PGM_ODATA = 4, /* original data */
102 PGM_RDATA = 5, /* repair data */
103 PGM_NAK = 8, /* NAK */
104 PGM_NULLNAK = 9, /* Null NAK */
105 PGM_NCF = 10, /* NAK Confirmation */
106 PGM_ACK = 11, /* ACK for congestion control */
107 PGM_SPMR = 12, /* SPM request */
108 PGM_MAX = 255
109} pgm_type;
110
111#define PGM_OPT_BIT_PRESENT 0x01
112#define PGM_OPT_BIT_NETWORK 0x02
113#define PGM_OPT_BIT_VAR_PKTLEN 0x40
114#define PGM_OPT_BIT_PARITY 0x80
115
116#define PGM_OPT_LENGTH 0x00
117#define PGM_OPT_FRAGMENT 0x01
118#define PGM_OPT_NAK_LIST 0x02
119#define PGM_OPT_JOIN 0x03
120#define PGM_OPT_NAK_BO_IVL 0x04
121#define PGM_OPT_NAK_BO_RNG 0x05
122
123#define PGM_OPT_REDIRECT 0x07
124#define PGM_OPT_PARITY_PRM 0x08
125#define PGM_OPT_PARITY_GRP 0x09
126#define PGM_OPT_CURR_TGSIZE 0x0A
127#define PGM_OPT_NBR_UNREACH 0x0B
128#define PGM_OPT_PATH_NLA 0x0C
129
130#define PGM_OPT_SYN 0x0D
131#define PGM_OPT_FIN 0x0E
132#define PGM_OPT_RST 0x0F
133#define PGM_OPT_CR 0x10
134#define PGM_OPT_CRQST 0x11
JP Abgrall53f17a92014-02-12 14:02:41 -0800135
136#define PGM_OPT_PGMCC_DATA 0x12
137#define PGM_OPT_PGMCC_FEEDBACK 0x13
Elliott Hughes892a68b2015-10-19 14:43:53 -0700138
The Android Open Source Project2949f582009-03-03 19:30:46 -0800139#define PGM_OPT_MASK 0x7f
140
141#define PGM_OPT_END 0x80 /* end of options marker */
142
143#define PGM_MIN_OPT_LEN 4
144
The Android Open Source Project2949f582009-03-03 19:30:46 -0800145void
Elliott Hughes892a68b2015-10-19 14:43:53 -0700146pgm_print(netdissect_options *ndo,
Elliott Hughes820eced2021-08-20 18:00:50 -0700147 const u_char *bp, u_int length,
148 const u_char *bp2)
The Android Open Source Project2949f582009-03-03 19:30:46 -0800149{
Elliott Hughes820eced2021-08-20 18:00:50 -0700150 const struct pgm_header *pgm;
151 const struct ip *ip;
152 uint8_t pgm_type_val;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700153 uint16_t sport, dport;
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700154 u_int nla_afnum;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800155 char nla_buf[INET6_ADDRSTRLEN];
Elliott Hughes820eced2021-08-20 18:00:50 -0700156 const struct ip6_hdr *ip6;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700157 uint8_t opt_type, opt_len;
158 uint32_t seq, opts_len, len, offset;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800159
Elliott Hughes820eced2021-08-20 18:00:50 -0700160 ndo->ndo_protocol = "pgm";
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700161 pgm = (const struct pgm_header *)bp;
162 ip = (const struct ip *)bp2;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800163 if (IP_V(ip) == 6)
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700164 ip6 = (const struct ip6_hdr *)bp2;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800165 else
166 ip6 = NULL;
Elliott Hughes820eced2021-08-20 18:00:50 -0700167 if (!ND_TTEST_2(pgm->pgm_dport)) {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800168 if (ip6) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700169 ND_PRINT("%s > %s:",
170 GET_IP6ADDR_STRING(ip6->ip6_src),
171 GET_IP6ADDR_STRING(ip6->ip6_dst));
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700172 } else {
Elliott Hughes820eced2021-08-20 18:00:50 -0700173 ND_PRINT("%s > %s:",
174 GET_IPADDR_STRING(ip->ip_src),
175 GET_IPADDR_STRING(ip->ip_dst));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800176 }
Elliott Hughes820eced2021-08-20 18:00:50 -0700177 nd_print_trunc(ndo);
Elliott Hughescec480a2017-12-19 16:54:57 -0800178 return;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800179 }
180
Elliott Hughes820eced2021-08-20 18:00:50 -0700181 sport = GET_BE_U_2(pgm->pgm_sport);
182 dport = GET_BE_U_2(pgm->pgm_dport);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800183
The Android Open Source Project2949f582009-03-03 19:30:46 -0800184 if (ip6) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700185 if (GET_U_1(ip6->ip6_nxt) == IPPROTO_PGM) {
186 ND_PRINT("%s.%s > %s.%s: ",
187 GET_IP6ADDR_STRING(ip6->ip6_src),
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700188 tcpport_string(ndo, sport),
Elliott Hughes820eced2021-08-20 18:00:50 -0700189 GET_IP6ADDR_STRING(ip6->ip6_dst),
190 tcpport_string(ndo, dport));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800191 } else {
Elliott Hughes820eced2021-08-20 18:00:50 -0700192 ND_PRINT("%s > %s: ",
193 tcpport_string(ndo, sport), tcpport_string(ndo, dport));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800194 }
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700195 } else {
Elliott Hughes820eced2021-08-20 18:00:50 -0700196 if (GET_U_1(ip->ip_p) == IPPROTO_PGM) {
197 ND_PRINT("%s.%s > %s.%s: ",
198 GET_IPADDR_STRING(ip->ip_src),
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700199 tcpport_string(ndo, sport),
Elliott Hughes820eced2021-08-20 18:00:50 -0700200 GET_IPADDR_STRING(ip->ip_dst),
201 tcpport_string(ndo, dport));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800202 } else {
Elliott Hughes820eced2021-08-20 18:00:50 -0700203 ND_PRINT("%s > %s: ",
204 tcpport_string(ndo, sport), tcpport_string(ndo, dport));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800205 }
206 }
207
Elliott Hughes820eced2021-08-20 18:00:50 -0700208 ND_TCHECK_SIZE(pgm);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800209
Elliott Hughes820eced2021-08-20 18:00:50 -0700210 ND_PRINT("PGM, length %u", GET_BE_U_2(pgm->pgm_length));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800211
Elliott Hughes892a68b2015-10-19 14:43:53 -0700212 if (!ndo->ndo_vflag)
The Android Open Source Project2949f582009-03-03 19:30:46 -0800213 return;
214
Elliott Hughes820eced2021-08-20 18:00:50 -0700215 pgm_type_val = GET_U_1(pgm->pgm_type);
216 ND_PRINT(" 0x%02x%02x%02x%02x%02x%02x ",
The Android Open Source Project2949f582009-03-03 19:30:46 -0800217 pgm->pgm_gsid[0],
218 pgm->pgm_gsid[1],
219 pgm->pgm_gsid[2],
220 pgm->pgm_gsid[3],
221 pgm->pgm_gsid[4],
Elliott Hughes820eced2021-08-20 18:00:50 -0700222 pgm->pgm_gsid[5]);
223 switch (pgm_type_val) {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800224 case PGM_SPM: {
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700225 const struct pgm_spm *spm;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800226
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700227 spm = (const struct pgm_spm *)(pgm + 1);
Elliott Hughes820eced2021-08-20 18:00:50 -0700228 ND_TCHECK_SIZE(spm);
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700229 bp = (const u_char *) (spm + 1);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800230
Elliott Hughes820eced2021-08-20 18:00:50 -0700231 switch (GET_BE_U_2(spm->pgms_nla_afi)) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700232 case AFNUM_INET:
Elliott Hughes820eced2021-08-20 18:00:50 -0700233 ND_TCHECK_LEN(bp, sizeof(nd_ipv4));
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700234 addrtostr(bp, nla_buf, sizeof(nla_buf));
Elliott Hughes820eced2021-08-20 18:00:50 -0700235 bp += sizeof(nd_ipv4);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800236 break;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700237 case AFNUM_INET6:
Elliott Hughes820eced2021-08-20 18:00:50 -0700238 ND_TCHECK_LEN(bp, sizeof(nd_ipv6));
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700239 addrtostr6(bp, nla_buf, sizeof(nla_buf));
Elliott Hughes820eced2021-08-20 18:00:50 -0700240 bp += sizeof(nd_ipv6);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800241 break;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800242 default:
243 goto trunc;
244 break;
245 }
The Android Open Source Project2949f582009-03-03 19:30:46 -0800246
Elliott Hughes820eced2021-08-20 18:00:50 -0700247 ND_PRINT("SPM seq %u trail %u lead %u nla %s",
248 GET_BE_U_4(spm->pgms_seq),
249 GET_BE_U_4(spm->pgms_trailseq),
250 GET_BE_U_4(spm->pgms_leadseq),
251 nla_buf);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800252 break;
253 }
254
255 case PGM_POLL: {
Elliott Hughes820eced2021-08-20 18:00:50 -0700256 const struct pgm_poll *pgm_poll;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700257 uint32_t ivl, rnd, mask;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800258
Elliott Hughes820eced2021-08-20 18:00:50 -0700259 pgm_poll = (const struct pgm_poll *)(pgm + 1);
260 ND_TCHECK_SIZE(pgm_poll);
261 bp = (const u_char *) (pgm_poll + 1);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800262
Elliott Hughes820eced2021-08-20 18:00:50 -0700263 switch (GET_BE_U_2(pgm_poll->pgmp_nla_afi)) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700264 case AFNUM_INET:
Elliott Hughes820eced2021-08-20 18:00:50 -0700265 ND_TCHECK_LEN(bp, sizeof(nd_ipv4));
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700266 addrtostr(bp, nla_buf, sizeof(nla_buf));
Elliott Hughes820eced2021-08-20 18:00:50 -0700267 bp += sizeof(nd_ipv4);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800268 break;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700269 case AFNUM_INET6:
Elliott Hughes820eced2021-08-20 18:00:50 -0700270 ND_TCHECK_LEN(bp, sizeof(nd_ipv6));
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700271 addrtostr6(bp, nla_buf, sizeof(nla_buf));
Elliott Hughes820eced2021-08-20 18:00:50 -0700272 bp += sizeof(nd_ipv6);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800273 break;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800274 default:
275 goto trunc;
276 break;
277 }
The Android Open Source Project2949f582009-03-03 19:30:46 -0800278
Elliott Hughes820eced2021-08-20 18:00:50 -0700279 ivl = GET_BE_U_4(bp);
Elliott Hughes892a68b2015-10-19 14:43:53 -0700280 bp += sizeof(uint32_t);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800281
Elliott Hughes820eced2021-08-20 18:00:50 -0700282 rnd = GET_BE_U_4(bp);
Elliott Hughes892a68b2015-10-19 14:43:53 -0700283 bp += sizeof(uint32_t);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800284
Elliott Hughes820eced2021-08-20 18:00:50 -0700285 mask = GET_BE_U_4(bp);
Elliott Hughes892a68b2015-10-19 14:43:53 -0700286 bp += sizeof(uint32_t);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800287
Elliott Hughes820eced2021-08-20 18:00:50 -0700288 ND_PRINT("POLL seq %u round %u nla %s ivl %u rnd 0x%08x "
289 "mask 0x%08x", GET_BE_U_4(pgm_poll->pgmp_seq),
290 GET_BE_U_2(pgm_poll->pgmp_round), nla_buf, ivl, rnd,
291 mask);
292 break;
293 }
294 case PGM_POLR: {
295 const struct pgm_polr *polr_msg;
296
297 polr_msg = (const struct pgm_polr *)(pgm + 1);
298 ND_TCHECK_SIZE(polr_msg);
299 ND_PRINT("POLR seq %u round %u",
300 GET_BE_U_4(polr_msg->pgmp_seq),
301 GET_BE_U_2(polr_msg->pgmp_round));
302 bp = (const u_char *) (polr_msg + 1);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800303 break;
304 }
305 case PGM_ODATA: {
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700306 const struct pgm_data *odata;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800307
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700308 odata = (const struct pgm_data *)(pgm + 1);
Elliott Hughes820eced2021-08-20 18:00:50 -0700309 ND_TCHECK_SIZE(odata);
310 ND_PRINT("ODATA trail %u seq %u",
311 GET_BE_U_4(odata->pgmd_trailseq),
312 GET_BE_U_4(odata->pgmd_seq));
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700313 bp = (const u_char *) (odata + 1);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800314 break;
315 }
316
317 case PGM_RDATA: {
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700318 const struct pgm_data *rdata;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800319
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700320 rdata = (const struct pgm_data *)(pgm + 1);
Elliott Hughes820eced2021-08-20 18:00:50 -0700321 ND_TCHECK_SIZE(rdata);
322 ND_PRINT("RDATA trail %u seq %u",
323 GET_BE_U_4(rdata->pgmd_trailseq),
324 GET_BE_U_4(rdata->pgmd_seq));
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700325 bp = (const u_char *) (rdata + 1);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800326 break;
327 }
328
329 case PGM_NAK:
330 case PGM_NULLNAK:
331 case PGM_NCF: {
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700332 const struct pgm_nak *nak;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800333 char source_buf[INET6_ADDRSTRLEN], group_buf[INET6_ADDRSTRLEN];
The Android Open Source Project2949f582009-03-03 19:30:46 -0800334
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700335 nak = (const struct pgm_nak *)(pgm + 1);
Elliott Hughes820eced2021-08-20 18:00:50 -0700336 ND_TCHECK_SIZE(nak);
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700337 bp = (const u_char *) (nak + 1);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800338
339 /*
340 * Skip past the source, saving info along the way
341 * and stopping if we don't have enough.
342 */
Elliott Hughes820eced2021-08-20 18:00:50 -0700343 switch (GET_BE_U_2(nak->pgmn_source_afi)) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700344 case AFNUM_INET:
Elliott Hughes820eced2021-08-20 18:00:50 -0700345 ND_TCHECK_LEN(bp, sizeof(nd_ipv4));
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700346 addrtostr(bp, source_buf, sizeof(source_buf));
Elliott Hughes820eced2021-08-20 18:00:50 -0700347 bp += sizeof(nd_ipv4);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800348 break;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700349 case AFNUM_INET6:
Elliott Hughes820eced2021-08-20 18:00:50 -0700350 ND_TCHECK_LEN(bp, sizeof(nd_ipv6));
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700351 addrtostr6(bp, source_buf, sizeof(source_buf));
Elliott Hughes820eced2021-08-20 18:00:50 -0700352 bp += sizeof(nd_ipv6);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800353 break;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800354 default:
355 goto trunc;
356 break;
357 }
The Android Open Source Project2949f582009-03-03 19:30:46 -0800358
359 /*
360 * Skip past the group, saving info along the way
361 * and stopping if we don't have enough.
362 */
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700363 bp += (2 * sizeof(uint16_t));
Elliott Hughes820eced2021-08-20 18:00:50 -0700364 switch (GET_BE_U_2(bp)) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700365 case AFNUM_INET:
Elliott Hughes820eced2021-08-20 18:00:50 -0700366 ND_TCHECK_LEN(bp, sizeof(nd_ipv4));
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700367 addrtostr(bp, group_buf, sizeof(group_buf));
Elliott Hughes820eced2021-08-20 18:00:50 -0700368 bp += sizeof(nd_ipv4);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800369 break;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700370 case AFNUM_INET6:
Elliott Hughes820eced2021-08-20 18:00:50 -0700371 ND_TCHECK_LEN(bp, sizeof(nd_ipv6));
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700372 addrtostr6(bp, group_buf, sizeof(group_buf));
Elliott Hughes820eced2021-08-20 18:00:50 -0700373 bp += sizeof(nd_ipv6);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800374 break;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800375 default:
376 goto trunc;
377 break;
378 }
The Android Open Source Project2949f582009-03-03 19:30:46 -0800379
380 /*
381 * Options decoding can go here.
382 */
Elliott Hughes820eced2021-08-20 18:00:50 -0700383 switch (pgm_type_val) {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800384 case PGM_NAK:
Elliott Hughes820eced2021-08-20 18:00:50 -0700385 ND_PRINT("NAK ");
The Android Open Source Project2949f582009-03-03 19:30:46 -0800386 break;
387 case PGM_NULLNAK:
Elliott Hughes820eced2021-08-20 18:00:50 -0700388 ND_PRINT("NNAK ");
The Android Open Source Project2949f582009-03-03 19:30:46 -0800389 break;
390 case PGM_NCF:
Elliott Hughes820eced2021-08-20 18:00:50 -0700391 ND_PRINT("NCF ");
The Android Open Source Project2949f582009-03-03 19:30:46 -0800392 break;
393 default:
394 break;
395 }
Elliott Hughes820eced2021-08-20 18:00:50 -0700396 ND_PRINT("(%s -> %s), seq %u",
397 source_buf, group_buf, GET_BE_U_4(nak->pgmn_seq));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800398 break;
399 }
400
JP Abgrall53f17a92014-02-12 14:02:41 -0800401 case PGM_ACK: {
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700402 const struct pgm_ack *ack;
JP Abgrall53f17a92014-02-12 14:02:41 -0800403
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700404 ack = (const struct pgm_ack *)(pgm + 1);
Elliott Hughes820eced2021-08-20 18:00:50 -0700405 ND_TCHECK_SIZE(ack);
406 ND_PRINT("ACK seq %u",
407 GET_BE_U_4(ack->pgma_rx_max_seq));
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700408 bp = (const u_char *) (ack + 1);
JP Abgrall53f17a92014-02-12 14:02:41 -0800409 break;
410 }
411
The Android Open Source Project2949f582009-03-03 19:30:46 -0800412 case PGM_SPMR:
Elliott Hughes820eced2021-08-20 18:00:50 -0700413 ND_PRINT("SPMR");
The Android Open Source Project2949f582009-03-03 19:30:46 -0800414 break;
415
416 default:
Elliott Hughes820eced2021-08-20 18:00:50 -0700417 ND_PRINT("UNKNOWN type 0x%02x", pgm_type_val);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800418 break;
419
420 }
Elliott Hughes820eced2021-08-20 18:00:50 -0700421 if (GET_U_1(pgm->pgm_options) & PGM_OPT_BIT_PRESENT) {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800422
423 /*
424 * make sure there's enough for the first option header
425 */
Elliott Hughes820eced2021-08-20 18:00:50 -0700426 ND_TCHECK_LEN(bp, PGM_MIN_OPT_LEN);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800427
428 /*
429 * That option header MUST be an OPT_LENGTH option
430 * (see the first paragraph of section 9.1 in RFC 3208).
431 */
Elliott Hughes820eced2021-08-20 18:00:50 -0700432 opt_type = GET_U_1(bp);
433 bp++;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800434 if ((opt_type & PGM_OPT_MASK) != PGM_OPT_LENGTH) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700435 ND_PRINT("[First option bad, should be PGM_OPT_LENGTH, is %u]", opt_type & PGM_OPT_MASK);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800436 return;
437 }
Elliott Hughes820eced2021-08-20 18:00:50 -0700438 opt_len = GET_U_1(bp);
439 bp++;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800440 if (opt_len != 4) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700441 ND_PRINT("[Bad OPT_LENGTH option, length %u != 4]", opt_len);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800442 return;
443 }
Elliott Hughes820eced2021-08-20 18:00:50 -0700444 opts_len = GET_BE_U_2(bp);
Elliott Hughes892a68b2015-10-19 14:43:53 -0700445 bp += sizeof(uint16_t);
Elliott Hughes820eced2021-08-20 18:00:50 -0700446 if (opts_len < 4) {
447 ND_PRINT("[Bad total option length %u < 4]", opts_len);
448 return;
449 }
450 ND_PRINT(" OPTS LEN %u", opts_len);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800451 opts_len -= 4;
452
453 while (opts_len) {
454 if (opts_len < PGM_MIN_OPT_LEN) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700455 ND_PRINT("[Total option length leaves no room for final option]");
The Android Open Source Project2949f582009-03-03 19:30:46 -0800456 return;
457 }
Elliott Hughes820eced2021-08-20 18:00:50 -0700458 opt_type = GET_U_1(bp);
459 bp++;
460 opt_len = GET_U_1(bp);
461 bp++;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800462 if (opt_len < PGM_MIN_OPT_LEN) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700463 ND_PRINT("[Bad option, length %u < %u]", opt_len,
464 PGM_MIN_OPT_LEN);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800465 break;
466 }
467 if (opts_len < opt_len) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700468 ND_PRINT("[Total option length leaves no room for final option]");
The Android Open Source Project2949f582009-03-03 19:30:46 -0800469 return;
470 }
Elliott Hughes820eced2021-08-20 18:00:50 -0700471 ND_TCHECK_LEN(bp, opt_len - 2);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800472
473 switch (opt_type & PGM_OPT_MASK) {
474 case PGM_OPT_LENGTH:
Elliott Hughescec480a2017-12-19 16:54:57 -0800475#define PGM_OPT_LENGTH_LEN (2+2)
476 if (opt_len != PGM_OPT_LENGTH_LEN) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700477 ND_PRINT("[Bad OPT_LENGTH option, length %u != %u]",
478 opt_len, PGM_OPT_LENGTH_LEN);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800479 return;
480 }
Elliott Hughes820eced2021-08-20 18:00:50 -0700481 ND_PRINT(" OPTS LEN (extra?) %u", GET_BE_U_2(bp));
Elliott Hughescec480a2017-12-19 16:54:57 -0800482 bp += 2;
483 opts_len -= PGM_OPT_LENGTH_LEN;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800484 break;
485
486 case PGM_OPT_FRAGMENT:
Elliott Hughescec480a2017-12-19 16:54:57 -0800487#define PGM_OPT_FRAGMENT_LEN (2+2+4+4+4)
488 if (opt_len != PGM_OPT_FRAGMENT_LEN) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700489 ND_PRINT("[Bad OPT_FRAGMENT option, length %u != %u]",
490 opt_len, PGM_OPT_FRAGMENT_LEN);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800491 return;
492 }
JP Abgrall53f17a92014-02-12 14:02:41 -0800493 bp += 2;
Elliott Hughes820eced2021-08-20 18:00:50 -0700494 seq = GET_BE_U_4(bp);
Elliott Hughescec480a2017-12-19 16:54:57 -0800495 bp += 4;
Elliott Hughes820eced2021-08-20 18:00:50 -0700496 offset = GET_BE_U_4(bp);
Elliott Hughescec480a2017-12-19 16:54:57 -0800497 bp += 4;
Elliott Hughes820eced2021-08-20 18:00:50 -0700498 len = GET_BE_U_4(bp);
Elliott Hughescec480a2017-12-19 16:54:57 -0800499 bp += 4;
Elliott Hughes820eced2021-08-20 18:00:50 -0700500 ND_PRINT(" FRAG seq %u off %u len %u", seq, offset, len);
Elliott Hughescec480a2017-12-19 16:54:57 -0800501 opts_len -= PGM_OPT_FRAGMENT_LEN;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800502 break;
503
504 case PGM_OPT_NAK_LIST:
JP Abgrall53f17a92014-02-12 14:02:41 -0800505 bp += 2;
Elliott Hughescec480a2017-12-19 16:54:57 -0800506 opt_len -= 4; /* option header */
Elliott Hughes820eced2021-08-20 18:00:50 -0700507 ND_PRINT(" NAK LIST");
The Android Open Source Project2949f582009-03-03 19:30:46 -0800508 while (opt_len) {
Elliott Hughescec480a2017-12-19 16:54:57 -0800509 if (opt_len < 4) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700510 ND_PRINT("[Option length not a multiple of 4]");
The Android Open Source Project2949f582009-03-03 19:30:46 -0800511 return;
512 }
Elliott Hughes820eced2021-08-20 18:00:50 -0700513 ND_PRINT(" %u", GET_BE_U_4(bp));
Elliott Hughescec480a2017-12-19 16:54:57 -0800514 bp += 4;
515 opt_len -= 4;
516 opts_len -= 4;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800517 }
518 break;
519
520 case PGM_OPT_JOIN:
Elliott Hughescec480a2017-12-19 16:54:57 -0800521#define PGM_OPT_JOIN_LEN (2+2+4)
522 if (opt_len != PGM_OPT_JOIN_LEN) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700523 ND_PRINT("[Bad OPT_JOIN option, length %u != %u]",
524 opt_len, PGM_OPT_JOIN_LEN);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800525 return;
526 }
JP Abgrall53f17a92014-02-12 14:02:41 -0800527 bp += 2;
Elliott Hughes820eced2021-08-20 18:00:50 -0700528 seq = GET_BE_U_4(bp);
Elliott Hughescec480a2017-12-19 16:54:57 -0800529 bp += 4;
Elliott Hughes820eced2021-08-20 18:00:50 -0700530 ND_PRINT(" JOIN %u", seq);
Elliott Hughescec480a2017-12-19 16:54:57 -0800531 opts_len -= PGM_OPT_JOIN_LEN;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800532 break;
533
534 case PGM_OPT_NAK_BO_IVL:
Elliott Hughescec480a2017-12-19 16:54:57 -0800535#define PGM_OPT_NAK_BO_IVL_LEN (2+2+4+4)
536 if (opt_len != PGM_OPT_NAK_BO_IVL_LEN) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700537 ND_PRINT("[Bad OPT_NAK_BO_IVL option, length %u != %u]",
538 opt_len, PGM_OPT_NAK_BO_IVL_LEN);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800539 return;
540 }
JP Abgrall53f17a92014-02-12 14:02:41 -0800541 bp += 2;
Elliott Hughes820eced2021-08-20 18:00:50 -0700542 offset = GET_BE_U_4(bp);
Elliott Hughescec480a2017-12-19 16:54:57 -0800543 bp += 4;
Elliott Hughes820eced2021-08-20 18:00:50 -0700544 seq = GET_BE_U_4(bp);
Elliott Hughescec480a2017-12-19 16:54:57 -0800545 bp += 4;
Elliott Hughes820eced2021-08-20 18:00:50 -0700546 ND_PRINT(" BACKOFF ivl %u ivlseq %u", offset, seq);
Elliott Hughescec480a2017-12-19 16:54:57 -0800547 opts_len -= PGM_OPT_NAK_BO_IVL_LEN;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800548 break;
549
550 case PGM_OPT_NAK_BO_RNG:
Elliott Hughescec480a2017-12-19 16:54:57 -0800551#define PGM_OPT_NAK_BO_RNG_LEN (2+2+4+4)
552 if (opt_len != PGM_OPT_NAK_BO_RNG_LEN) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700553 ND_PRINT("[Bad OPT_NAK_BO_RNG option, length %u != %u]",
554 opt_len, PGM_OPT_NAK_BO_RNG_LEN);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800555 return;
556 }
JP Abgrall53f17a92014-02-12 14:02:41 -0800557 bp += 2;
Elliott Hughes820eced2021-08-20 18:00:50 -0700558 offset = GET_BE_U_4(bp);
Elliott Hughescec480a2017-12-19 16:54:57 -0800559 bp += 4;
Elliott Hughes820eced2021-08-20 18:00:50 -0700560 seq = GET_BE_U_4(bp);
Elliott Hughescec480a2017-12-19 16:54:57 -0800561 bp += 4;
Elliott Hughes820eced2021-08-20 18:00:50 -0700562 ND_PRINT(" BACKOFF max %u min %u", offset, seq);
Elliott Hughescec480a2017-12-19 16:54:57 -0800563 opts_len -= PGM_OPT_NAK_BO_RNG_LEN;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800564 break;
565
566 case PGM_OPT_REDIRECT:
Elliott Hughescec480a2017-12-19 16:54:57 -0800567#define PGM_OPT_REDIRECT_FIXED_LEN (2+2+2+2)
568 if (opt_len < PGM_OPT_REDIRECT_FIXED_LEN) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700569 ND_PRINT("[Bad OPT_REDIRECT option, length %u < %u]",
570 opt_len, PGM_OPT_REDIRECT_FIXED_LEN);
Elliott Hughescec480a2017-12-19 16:54:57 -0800571 return;
572 }
JP Abgrall53f17a92014-02-12 14:02:41 -0800573 bp += 2;
Elliott Hughes820eced2021-08-20 18:00:50 -0700574 nla_afnum = GET_BE_U_2(bp);
Elliott Hughescec480a2017-12-19 16:54:57 -0800575 bp += 2+2;
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700576 switch (nla_afnum) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700577 case AFNUM_INET:
Elliott Hughes820eced2021-08-20 18:00:50 -0700578 if (opt_len != PGM_OPT_REDIRECT_FIXED_LEN + sizeof(nd_ipv4)) {
579 ND_PRINT("[Bad OPT_REDIRECT option, length %u != %u + address size]",
580 opt_len, PGM_OPT_REDIRECT_FIXED_LEN);
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700581 return;
582 }
Elliott Hughes820eced2021-08-20 18:00:50 -0700583 ND_TCHECK_LEN(bp, sizeof(nd_ipv4));
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700584 addrtostr(bp, nla_buf, sizeof(nla_buf));
Elliott Hughes820eced2021-08-20 18:00:50 -0700585 bp += sizeof(nd_ipv4);
586 opts_len -= PGM_OPT_REDIRECT_FIXED_LEN + sizeof(nd_ipv4);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800587 break;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700588 case AFNUM_INET6:
Elliott Hughes820eced2021-08-20 18:00:50 -0700589 if (opt_len != PGM_OPT_REDIRECT_FIXED_LEN + sizeof(nd_ipv6)) {
590 ND_PRINT("[Bad OPT_REDIRECT option, length %u != %u + address size]",
591 opt_len, PGM_OPT_REDIRECT_FIXED_LEN);
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700592 return;
593 }
Elliott Hughes820eced2021-08-20 18:00:50 -0700594 ND_TCHECK_LEN(bp, sizeof(nd_ipv6));
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700595 addrtostr6(bp, nla_buf, sizeof(nla_buf));
Elliott Hughes820eced2021-08-20 18:00:50 -0700596 bp += sizeof(nd_ipv6);
597 opts_len -= PGM_OPT_REDIRECT_FIXED_LEN + sizeof(nd_ipv6);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800598 break;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800599 default:
600 goto trunc;
601 break;
602 }
The Android Open Source Project2949f582009-03-03 19:30:46 -0800603
Elliott Hughes820eced2021-08-20 18:00:50 -0700604 ND_PRINT(" REDIRECT %s", nla_buf);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800605 break;
606
607 case PGM_OPT_PARITY_PRM:
Elliott Hughescec480a2017-12-19 16:54:57 -0800608#define PGM_OPT_PARITY_PRM_LEN (2+2+4)
609 if (opt_len != PGM_OPT_PARITY_PRM_LEN) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700610 ND_PRINT("[Bad OPT_PARITY_PRM option, length %u != %u]",
611 opt_len, PGM_OPT_PARITY_PRM_LEN);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800612 return;
613 }
JP Abgrall53f17a92014-02-12 14:02:41 -0800614 bp += 2;
Elliott Hughes820eced2021-08-20 18:00:50 -0700615 len = GET_BE_U_4(bp);
Elliott Hughescec480a2017-12-19 16:54:57 -0800616 bp += 4;
Elliott Hughes820eced2021-08-20 18:00:50 -0700617 ND_PRINT(" PARITY MAXTGS %u", len);
Elliott Hughescec480a2017-12-19 16:54:57 -0800618 opts_len -= PGM_OPT_PARITY_PRM_LEN;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800619 break;
620
621 case PGM_OPT_PARITY_GRP:
Elliott Hughescec480a2017-12-19 16:54:57 -0800622#define PGM_OPT_PARITY_GRP_LEN (2+2+4)
623 if (opt_len != PGM_OPT_PARITY_GRP_LEN) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700624 ND_PRINT("[Bad OPT_PARITY_GRP option, length %u != %u]",
625 opt_len, PGM_OPT_PARITY_GRP_LEN);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800626 return;
627 }
JP Abgrall53f17a92014-02-12 14:02:41 -0800628 bp += 2;
Elliott Hughes820eced2021-08-20 18:00:50 -0700629 seq = GET_BE_U_4(bp);
Elliott Hughescec480a2017-12-19 16:54:57 -0800630 bp += 4;
Elliott Hughes820eced2021-08-20 18:00:50 -0700631 ND_PRINT(" PARITY GROUP %u", seq);
Elliott Hughescec480a2017-12-19 16:54:57 -0800632 opts_len -= PGM_OPT_PARITY_GRP_LEN;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800633 break;
634
635 case PGM_OPT_CURR_TGSIZE:
Elliott Hughescec480a2017-12-19 16:54:57 -0800636#define PGM_OPT_CURR_TGSIZE_LEN (2+2+4)
637 if (opt_len != PGM_OPT_CURR_TGSIZE_LEN) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700638 ND_PRINT("[Bad OPT_CURR_TGSIZE option, length %u != %u]",
639 opt_len, PGM_OPT_CURR_TGSIZE_LEN);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800640 return;
641 }
JP Abgrall53f17a92014-02-12 14:02:41 -0800642 bp += 2;
Elliott Hughes820eced2021-08-20 18:00:50 -0700643 len = GET_BE_U_4(bp);
Elliott Hughescec480a2017-12-19 16:54:57 -0800644 bp += 4;
Elliott Hughes820eced2021-08-20 18:00:50 -0700645 ND_PRINT(" PARITY ATGS %u", len);
Elliott Hughescec480a2017-12-19 16:54:57 -0800646 opts_len -= PGM_OPT_CURR_TGSIZE_LEN;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800647 break;
648
649 case PGM_OPT_NBR_UNREACH:
Elliott Hughescec480a2017-12-19 16:54:57 -0800650#define PGM_OPT_NBR_UNREACH_LEN (2+2)
651 if (opt_len != PGM_OPT_NBR_UNREACH_LEN) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700652 ND_PRINT("[Bad OPT_NBR_UNREACH option, length %u != %u]",
653 opt_len, PGM_OPT_NBR_UNREACH_LEN);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800654 return;
655 }
JP Abgrall53f17a92014-02-12 14:02:41 -0800656 bp += 2;
Elliott Hughes820eced2021-08-20 18:00:50 -0700657 ND_PRINT(" NBR_UNREACH");
Elliott Hughescec480a2017-12-19 16:54:57 -0800658 opts_len -= PGM_OPT_NBR_UNREACH_LEN;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800659 break;
660
661 case PGM_OPT_PATH_NLA:
Elliott Hughes820eced2021-08-20 18:00:50 -0700662 ND_PRINT(" PATH_NLA [%u]", opt_len);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800663 bp += opt_len;
664 opts_len -= opt_len;
665 break;
666
667 case PGM_OPT_SYN:
Elliott Hughescec480a2017-12-19 16:54:57 -0800668#define PGM_OPT_SYN_LEN (2+2)
669 if (opt_len != PGM_OPT_SYN_LEN) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700670 ND_PRINT("[Bad OPT_SYN option, length %u != %u]",
671 opt_len, PGM_OPT_SYN_LEN);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800672 return;
673 }
JP Abgrall53f17a92014-02-12 14:02:41 -0800674 bp += 2;
Elliott Hughes820eced2021-08-20 18:00:50 -0700675 ND_PRINT(" SYN");
Elliott Hughescec480a2017-12-19 16:54:57 -0800676 opts_len -= PGM_OPT_SYN_LEN;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800677 break;
678
679 case PGM_OPT_FIN:
Elliott Hughescec480a2017-12-19 16:54:57 -0800680#define PGM_OPT_FIN_LEN (2+2)
681 if (opt_len != PGM_OPT_FIN_LEN) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700682 ND_PRINT("[Bad OPT_FIN option, length %u != %u]",
683 opt_len, PGM_OPT_FIN_LEN);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800684 return;
685 }
JP Abgrall53f17a92014-02-12 14:02:41 -0800686 bp += 2;
Elliott Hughes820eced2021-08-20 18:00:50 -0700687 ND_PRINT(" FIN");
Elliott Hughescec480a2017-12-19 16:54:57 -0800688 opts_len -= PGM_OPT_FIN_LEN;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800689 break;
690
691 case PGM_OPT_RST:
Elliott Hughescec480a2017-12-19 16:54:57 -0800692#define PGM_OPT_RST_LEN (2+2)
693 if (opt_len != PGM_OPT_RST_LEN) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700694 ND_PRINT("[Bad OPT_RST option, length %u != %u]",
695 opt_len, PGM_OPT_RST_LEN);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800696 return;
697 }
JP Abgrall53f17a92014-02-12 14:02:41 -0800698 bp += 2;
Elliott Hughes820eced2021-08-20 18:00:50 -0700699 ND_PRINT(" RST");
Elliott Hughescec480a2017-12-19 16:54:57 -0800700 opts_len -= PGM_OPT_RST_LEN;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800701 break;
702
703 case PGM_OPT_CR:
Elliott Hughes820eced2021-08-20 18:00:50 -0700704 ND_PRINT(" CR");
The Android Open Source Project2949f582009-03-03 19:30:46 -0800705 bp += opt_len;
706 opts_len -= opt_len;
707 break;
708
709 case PGM_OPT_CRQST:
Elliott Hughescec480a2017-12-19 16:54:57 -0800710#define PGM_OPT_CRQST_LEN (2+2)
711 if (opt_len != PGM_OPT_CRQST_LEN) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700712 ND_PRINT("[Bad OPT_CRQST option, length %u != %u]",
713 opt_len, PGM_OPT_CRQST_LEN);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800714 return;
715 }
JP Abgrall53f17a92014-02-12 14:02:41 -0800716 bp += 2;
Elliott Hughes820eced2021-08-20 18:00:50 -0700717 ND_PRINT(" CRQST");
Elliott Hughescec480a2017-12-19 16:54:57 -0800718 opts_len -= PGM_OPT_CRQST_LEN;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800719 break;
720
JP Abgrall53f17a92014-02-12 14:02:41 -0800721 case PGM_OPT_PGMCC_DATA:
Elliott Hughescec480a2017-12-19 16:54:57 -0800722#define PGM_OPT_PGMCC_DATA_FIXED_LEN (2+2+4+2+2)
723 if (opt_len < PGM_OPT_PGMCC_DATA_FIXED_LEN) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700724 ND_PRINT("[Bad OPT_PGMCC_DATA option, length %u < %u]",
725 opt_len, PGM_OPT_PGMCC_DATA_FIXED_LEN);
Elliott Hughescec480a2017-12-19 16:54:57 -0800726 return;
727 }
JP Abgrall53f17a92014-02-12 14:02:41 -0800728 bp += 2;
Elliott Hughes820eced2021-08-20 18:00:50 -0700729 offset = GET_BE_U_4(bp);
Elliott Hughescec480a2017-12-19 16:54:57 -0800730 bp += 4;
Elliott Hughes820eced2021-08-20 18:00:50 -0700731 nla_afnum = GET_BE_U_2(bp);
Elliott Hughescec480a2017-12-19 16:54:57 -0800732 bp += 2+2;
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700733 switch (nla_afnum) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700734 case AFNUM_INET:
Elliott Hughes820eced2021-08-20 18:00:50 -0700735 if (opt_len != PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(nd_ipv4)) {
736 ND_PRINT("[Bad OPT_PGMCC_DATA option, length %u != %u + address size]",
737 opt_len, PGM_OPT_PGMCC_DATA_FIXED_LEN);
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700738 return;
739 }
Elliott Hughes820eced2021-08-20 18:00:50 -0700740 ND_TCHECK_LEN(bp, sizeof(nd_ipv4));
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700741 addrtostr(bp, nla_buf, sizeof(nla_buf));
Elliott Hughes820eced2021-08-20 18:00:50 -0700742 bp += sizeof(nd_ipv4);
743 opts_len -= PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(nd_ipv4);
JP Abgrall53f17a92014-02-12 14:02:41 -0800744 break;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700745 case AFNUM_INET6:
Elliott Hughes820eced2021-08-20 18:00:50 -0700746 if (opt_len != PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(nd_ipv6)) {
747 ND_PRINT("[Bad OPT_PGMCC_DATA option, length %u != %u + address size]",
748 opt_len, PGM_OPT_PGMCC_DATA_FIXED_LEN);
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700749 return;
750 }
Elliott Hughes820eced2021-08-20 18:00:50 -0700751 ND_TCHECK_LEN(bp, sizeof(nd_ipv6));
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700752 addrtostr6(bp, nla_buf, sizeof(nla_buf));
Elliott Hughes820eced2021-08-20 18:00:50 -0700753 bp += sizeof(nd_ipv6);
754 opts_len -= PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(nd_ipv6);
JP Abgrall53f17a92014-02-12 14:02:41 -0800755 break;
JP Abgrall53f17a92014-02-12 14:02:41 -0800756 default:
757 goto trunc;
758 break;
759 }
JP Abgrall53f17a92014-02-12 14:02:41 -0800760
Elliott Hughes820eced2021-08-20 18:00:50 -0700761 ND_PRINT(" PGMCC DATA %u %s", offset, nla_buf);
JP Abgrall53f17a92014-02-12 14:02:41 -0800762 break;
763
764 case PGM_OPT_PGMCC_FEEDBACK:
Elliott Hughescec480a2017-12-19 16:54:57 -0800765#define PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN (2+2+4+2+2)
766 if (opt_len < PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN) {
Elliott Hughes820eced2021-08-20 18:00:50 -0700767 ND_PRINT("[Bad PGM_OPT_PGMCC_FEEDBACK option, length %u < %u]",
768 opt_len, PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN);
Elliott Hughescec480a2017-12-19 16:54:57 -0800769 return;
770 }
JP Abgrall53f17a92014-02-12 14:02:41 -0800771 bp += 2;
Elliott Hughes820eced2021-08-20 18:00:50 -0700772 offset = GET_BE_U_4(bp);
Elliott Hughescec480a2017-12-19 16:54:57 -0800773 bp += 4;
Elliott Hughes820eced2021-08-20 18:00:50 -0700774 nla_afnum = GET_BE_U_2(bp);
Elliott Hughescec480a2017-12-19 16:54:57 -0800775 bp += 2+2;
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700776 switch (nla_afnum) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700777 case AFNUM_INET:
Elliott Hughes820eced2021-08-20 18:00:50 -0700778 if (opt_len != PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(nd_ipv4)) {
779 ND_PRINT("[Bad OPT_PGMCC_FEEDBACK option, length %u != %u + address size]",
780 opt_len, PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN);
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700781 return;
782 }
Elliott Hughes820eced2021-08-20 18:00:50 -0700783 ND_TCHECK_LEN(bp, sizeof(nd_ipv4));
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700784 addrtostr(bp, nla_buf, sizeof(nla_buf));
Elliott Hughes820eced2021-08-20 18:00:50 -0700785 bp += sizeof(nd_ipv4);
786 opts_len -= PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(nd_ipv4);
JP Abgrall53f17a92014-02-12 14:02:41 -0800787 break;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700788 case AFNUM_INET6:
Elliott Hughes820eced2021-08-20 18:00:50 -0700789 if (opt_len != PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(nd_ipv6)) {
790 ND_PRINT("[Bad OPT_PGMCC_FEEDBACK option, length %u != %u + address size]",
791 opt_len, PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN);
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700792 return;
793 }
Elliott Hughes820eced2021-08-20 18:00:50 -0700794 ND_TCHECK_LEN(bp, sizeof(nd_ipv6));
Elliott Hughese2e3bd12017-05-15 10:59:29 -0700795 addrtostr6(bp, nla_buf, sizeof(nla_buf));
Elliott Hughes820eced2021-08-20 18:00:50 -0700796 bp += sizeof(nd_ipv6);
797 opts_len -= PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(nd_ipv6);
JP Abgrall53f17a92014-02-12 14:02:41 -0800798 break;
JP Abgrall53f17a92014-02-12 14:02:41 -0800799 default:
800 goto trunc;
801 break;
802 }
JP Abgrall53f17a92014-02-12 14:02:41 -0800803
Elliott Hughes820eced2021-08-20 18:00:50 -0700804 ND_PRINT(" PGMCC FEEDBACK %u %s", offset, nla_buf);
JP Abgrall53f17a92014-02-12 14:02:41 -0800805 break;
806
The Android Open Source Project2949f582009-03-03 19:30:46 -0800807 default:
Elliott Hughes820eced2021-08-20 18:00:50 -0700808 ND_PRINT(" OPT_%02X [%u] ", opt_type, opt_len);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800809 bp += opt_len;
810 opts_len -= opt_len;
811 break;
812 }
813
814 if (opt_type & PGM_OPT_END)
815 break;
816 }
817 }
818
Elliott Hughes820eced2021-08-20 18:00:50 -0700819 ND_PRINT(" [%u]", length);
Elliott Hughes892a68b2015-10-19 14:43:53 -0700820 if (ndo->ndo_packettype == PT_PGM_ZMTP1 &&
Elliott Hughes820eced2021-08-20 18:00:50 -0700821 (pgm_type_val == PGM_ODATA || pgm_type_val == PGM_RDATA))
822 zmtp1_datagram_print(ndo, bp,
823 GET_BE_U_2(pgm->pgm_length));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800824
825 return;
826
827trunc:
Elliott Hughes820eced2021-08-20 18:00:50 -0700828 nd_print_trunc(ndo);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800829}