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