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