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