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