tcpdump  4.99.1
About: tcpdump is a tool for network monitoring and data acquisition.
  Fossies Dox: tcpdump-4.99.1.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

print-pgm.c
Go to the documentation of this file.
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 {
45 };
46 
47 struct pgm_spm {
53  /* ... uint8_t pgms_nla[0]; */
54  /* ... options */
55 };
56 
57 struct pgm_nak {
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 {
71  /* ... options */
72 };
73 
74 struct pgm_poll {
80  /* ... uint8_t pgmp_nla[0]; */
81  /* ... options */
82 };
83 
84 struct pgm_polr {
88  /* ... options */
89 };
90 
91 struct pgm_data {
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
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
147  const u_char *bp, u_int length,
148  const u_char *bp2)
149 {
150  const struct pgm_header *pgm;
151  const struct ip *ip;
152  uint8_t pgm_type_val;
153  uint16_t sport, dport;
154  u_int nla_afnum;
155  char nla_buf[INET6_ADDRSTRLEN];
156  const struct ip6_hdr *ip6;
157  uint8_t opt_type, opt_len;
158  uint32_t seq, opts_len, len, offset;
159 
160  ndo->ndo_protocol = "pgm";
161  pgm = (const struct pgm_header *)bp;
162  ip = (const struct ip *)bp2;
163  if (IP_V(ip) == 6)
164  ip6 = (const struct ip6_hdr *)bp2;
165  else
166  ip6 = NULL;
167  if (!ND_TTEST_2(pgm->pgm_dport)) {
168  if (ip6) {
169  ND_PRINT("%s > %s:",
172  } else {
173  ND_PRINT("%s > %s:",
176  }
177  nd_print_trunc(ndo);
178  return;
179  }
180 
181  sport = GET_BE_U_2(pgm->pgm_sport);
182  dport = GET_BE_U_2(pgm->pgm_dport);
183 
184  if (ip6) {
185  if (GET_U_1(ip6->ip6_nxt) == IPPROTO_PGM) {
186  ND_PRINT("%s.%s > %s.%s: ",
188  tcpport_string(ndo, sport),
190  tcpport_string(ndo, dport));
191  } else {
192  ND_PRINT("%s > %s: ",
193  tcpport_string(ndo, sport), tcpport_string(ndo, dport));
194  }
195  } else {
196  if (GET_U_1(ip->ip_p) == IPPROTO_PGM) {
197  ND_PRINT("%s.%s > %s.%s: ",
199  tcpport_string(ndo, sport),
201  tcpport_string(ndo, dport));
202  } else {
203  ND_PRINT("%s > %s: ",
204  tcpport_string(ndo, sport), tcpport_string(ndo, dport));
205  }
206  }
207 
208  ND_TCHECK_SIZE(pgm);
209 
210  ND_PRINT("PGM, length %u", GET_BE_U_2(pgm->pgm_length));
211 
212  if (!ndo->ndo_vflag)
213  return;
214 
215  pgm_type_val = GET_U_1(pgm->pgm_type);
216  ND_PRINT(" 0x%02x%02x%02x%02x%02x%02x ",
217  pgm->pgm_gsid[0],
218  pgm->pgm_gsid[1],
219  pgm->pgm_gsid[2],
220  pgm->pgm_gsid[3],
221  pgm->pgm_gsid[4],
222  pgm->pgm_gsid[5]);
223  switch (pgm_type_val) {
224  case PGM_SPM: {
225  const struct pgm_spm *spm;
226 
227  spm = (const struct pgm_spm *)(pgm + 1);
228  ND_TCHECK_SIZE(spm);
229  bp = (const u_char *) (spm + 1);
230 
231  switch (GET_BE_U_2(spm->pgms_nla_afi)) {
232  case AFNUM_INET:
233  ND_TCHECK_LEN(bp, sizeof(nd_ipv4));
234  addrtostr(bp, nla_buf, sizeof(nla_buf));
235  bp += sizeof(nd_ipv4);
236  break;
237  case AFNUM_INET6:
238  ND_TCHECK_LEN(bp, sizeof(nd_ipv6));
239  addrtostr6(bp, nla_buf, sizeof(nla_buf));
240  bp += sizeof(nd_ipv6);
241  break;
242  default:
243  goto trunc;
244  break;
245  }
246 
247  ND_PRINT("SPM seq %u trail %u lead %u nla %s",
248  GET_BE_U_4(spm->pgms_seq),
250  GET_BE_U_4(spm->pgms_leadseq),
251  nla_buf);
252  break;
253  }
254 
255  case PGM_POLL: {
256  const struct pgm_poll *pgm_poll;
257  uint32_t ivl, rnd, mask;
258 
259  pgm_poll = (const struct pgm_poll *)(pgm + 1);
261  bp = (const u_char *) (pgm_poll + 1);
262 
263  switch (GET_BE_U_2(pgm_poll->pgmp_nla_afi)) {
264  case AFNUM_INET:
265  ND_TCHECK_LEN(bp, sizeof(nd_ipv4));
266  addrtostr(bp, nla_buf, sizeof(nla_buf));
267  bp += sizeof(nd_ipv4);
268  break;
269  case AFNUM_INET6:
270  ND_TCHECK_LEN(bp, sizeof(nd_ipv6));
271  addrtostr6(bp, nla_buf, sizeof(nla_buf));
272  bp += sizeof(nd_ipv6);
273  break;
274  default:
275  goto trunc;
276  break;
277  }
278 
279  ivl = GET_BE_U_4(bp);
280  bp += sizeof(uint32_t);
281 
282  rnd = GET_BE_U_4(bp);
283  bp += sizeof(uint32_t);
284 
285  mask = GET_BE_U_4(bp);
286  bp += sizeof(uint32_t);
287 
288  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);
303  break;
304  }
305  case PGM_ODATA: {
306  const struct pgm_data *odata;
307 
308  odata = (const struct pgm_data *)(pgm + 1);
309  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));
313  bp = (const u_char *) (odata + 1);
314  break;
315  }
316 
317  case PGM_RDATA: {
318  const struct pgm_data *rdata;
319 
320  rdata = (const struct pgm_data *)(pgm + 1);
321  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));
325  bp = (const u_char *) (rdata + 1);
326  break;
327  }
328 
329  case PGM_NAK:
330  case PGM_NULLNAK:
331  case PGM_NCF: {
332  const struct pgm_nak *nak;
333  char source_buf[INET6_ADDRSTRLEN], group_buf[INET6_ADDRSTRLEN];
334 
335  nak = (const struct pgm_nak *)(pgm + 1);
336  ND_TCHECK_SIZE(nak);
337  bp = (const u_char *) (nak + 1);
338 
339  /*
340  * Skip past the source, saving info along the way
341  * and stopping if we don't have enough.
342  */
343  switch (GET_BE_U_2(nak->pgmn_source_afi)) {
344  case AFNUM_INET:
345  ND_TCHECK_LEN(bp, sizeof(nd_ipv4));
346  addrtostr(bp, source_buf, sizeof(source_buf));
347  bp += sizeof(nd_ipv4);
348  break;
349  case AFNUM_INET6:
350  ND_TCHECK_LEN(bp, sizeof(nd_ipv6));
351  addrtostr6(bp, source_buf, sizeof(source_buf));
352  bp += sizeof(nd_ipv6);
353  break;
354  default:
355  goto trunc;
356  break;
357  }
358 
359  /*
360  * Skip past the group, saving info along the way
361  * and stopping if we don't have enough.
362  */
363  bp += (2 * sizeof(uint16_t));
364  switch (GET_BE_U_2(bp)) {
365  case AFNUM_INET:
366  ND_TCHECK_LEN(bp, sizeof(nd_ipv4));
367  addrtostr(bp, group_buf, sizeof(group_buf));
368  bp += sizeof(nd_ipv4);
369  break;
370  case AFNUM_INET6:
371  ND_TCHECK_LEN(bp, sizeof(nd_ipv6));
372  addrtostr6(bp, group_buf, sizeof(group_buf));
373  bp += sizeof(nd_ipv6);
374  break;
375  default:
376  goto trunc;
377  break;
378  }
379 
380  /*
381  * Options decoding can go here.
382  */
383  switch (pgm_type_val) {
384  case PGM_NAK:
385  ND_PRINT("NAK ");
386  break;
387  case PGM_NULLNAK:
388  ND_PRINT("NNAK ");
389  break;
390  case PGM_NCF:
391  ND_PRINT("NCF ");
392  break;
393  default:
394  break;
395  }
396  ND_PRINT("(%s -> %s), seq %u",
397  source_buf, group_buf, GET_BE_U_4(nak->pgmn_seq));
398  break;
399  }
400 
401  case PGM_ACK: {
402  const struct pgm_ack *ack;
403 
404  ack = (const struct pgm_ack *)(pgm + 1);
405  ND_TCHECK_SIZE(ack);
406  ND_PRINT("ACK seq %u",
408  bp = (const u_char *) (ack + 1);
409  break;
410  }
411 
412  case PGM_SPMR:
413  ND_PRINT("SPMR");
414  break;
415 
416  default:
417  ND_PRINT("UNKNOWN type 0x%02x", pgm_type_val);
418  break;
419 
420  }
422 
423  /*
424  * make sure there's enough for the first option header
425  */
427 
428  /*
429  * That option header MUST be an OPT_LENGTH option
430  * (see the first paragraph of section 9.1 in RFC 3208).
431  */
432  opt_type = GET_U_1(bp);
433  bp++;
434  if ((opt_type & PGM_OPT_MASK) != PGM_OPT_LENGTH) {
435  ND_PRINT("[First option bad, should be PGM_OPT_LENGTH, is %u]", opt_type & PGM_OPT_MASK);
436  return;
437  }
438  opt_len = GET_U_1(bp);
439  bp++;
440  if (opt_len != 4) {
441  ND_PRINT("[Bad OPT_LENGTH option, length %u != 4]", opt_len);
442  return;
443  }
444  opts_len = GET_BE_U_2(bp);
445  bp += sizeof(uint16_t);
446  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);
451  opts_len -= 4;
452 
453  while (opts_len) {
454  if (opts_len < PGM_MIN_OPT_LEN) {
455  ND_PRINT("[Total option length leaves no room for final option]");
456  return;
457  }
458  opt_type = GET_U_1(bp);
459  bp++;
460  opt_len = GET_U_1(bp);
461  bp++;
462  if (opt_len < PGM_MIN_OPT_LEN) {
463  ND_PRINT("[Bad option, length %u < %u]", opt_len,
465  break;
466  }
467  if (opts_len < opt_len) {
468  ND_PRINT("[Total option length leaves no room for final option]");
469  return;
470  }
471  ND_TCHECK_LEN(bp, opt_len - 2);
472 
473  switch (opt_type & PGM_OPT_MASK) {
474  case PGM_OPT_LENGTH:
475 #define PGM_OPT_LENGTH_LEN (2+2)
476  if (opt_len != PGM_OPT_LENGTH_LEN) {
477  ND_PRINT("[Bad OPT_LENGTH option, length %u != %u]",
478  opt_len, PGM_OPT_LENGTH_LEN);
479  return;
480  }
481  ND_PRINT(" OPTS LEN (extra?) %u", GET_BE_U_2(bp));
482  bp += 2;
483  opts_len -= PGM_OPT_LENGTH_LEN;
484  break;
485 
486  case PGM_OPT_FRAGMENT:
487 #define PGM_OPT_FRAGMENT_LEN (2+2+4+4+4)
488  if (opt_len != PGM_OPT_FRAGMENT_LEN) {
489  ND_PRINT("[Bad OPT_FRAGMENT option, length %u != %u]",
490  opt_len, PGM_OPT_FRAGMENT_LEN);
491  return;
492  }
493  bp += 2;
494  seq = GET_BE_U_4(bp);
495  bp += 4;
496  offset = GET_BE_U_4(bp);
497  bp += 4;
498  len = GET_BE_U_4(bp);
499  bp += 4;
500  ND_PRINT(" FRAG seq %u off %u len %u", seq, offset, len);
501  opts_len -= PGM_OPT_FRAGMENT_LEN;
502  break;
503 
504  case PGM_OPT_NAK_LIST:
505  bp += 2;
506  opt_len -= 4; /* option header */
507  ND_PRINT(" NAK LIST");
508  while (opt_len) {
509  if (opt_len < 4) {
510  ND_PRINT("[Option length not a multiple of 4]");
511  return;
512  }
513  ND_PRINT(" %u", GET_BE_U_4(bp));
514  bp += 4;
515  opt_len -= 4;
516  opts_len -= 4;
517  }
518  break;
519 
520  case PGM_OPT_JOIN:
521 #define PGM_OPT_JOIN_LEN (2+2+4)
522  if (opt_len != PGM_OPT_JOIN_LEN) {
523  ND_PRINT("[Bad OPT_JOIN option, length %u != %u]",
524  opt_len, PGM_OPT_JOIN_LEN);
525  return;
526  }
527  bp += 2;
528  seq = GET_BE_U_4(bp);
529  bp += 4;
530  ND_PRINT(" JOIN %u", seq);
531  opts_len -= PGM_OPT_JOIN_LEN;
532  break;
533 
534  case PGM_OPT_NAK_BO_IVL:
535 #define PGM_OPT_NAK_BO_IVL_LEN (2+2+4+4)
536  if (opt_len != PGM_OPT_NAK_BO_IVL_LEN) {
537  ND_PRINT("[Bad OPT_NAK_BO_IVL option, length %u != %u]",
538  opt_len, PGM_OPT_NAK_BO_IVL_LEN);
539  return;
540  }
541  bp += 2;
542  offset = GET_BE_U_4(bp);
543  bp += 4;
544  seq = GET_BE_U_4(bp);
545  bp += 4;
546  ND_PRINT(" BACKOFF ivl %u ivlseq %u", offset, seq);
547  opts_len -= PGM_OPT_NAK_BO_IVL_LEN;
548  break;
549 
550  case PGM_OPT_NAK_BO_RNG:
551 #define PGM_OPT_NAK_BO_RNG_LEN (2+2+4+4)
552  if (opt_len != PGM_OPT_NAK_BO_RNG_LEN) {
553  ND_PRINT("[Bad OPT_NAK_BO_RNG option, length %u != %u]",
554  opt_len, PGM_OPT_NAK_BO_RNG_LEN);
555  return;
556  }
557  bp += 2;
558  offset = GET_BE_U_4(bp);
559  bp += 4;
560  seq = GET_BE_U_4(bp);
561  bp += 4;
562  ND_PRINT(" BACKOFF max %u min %u", offset, seq);
563  opts_len -= PGM_OPT_NAK_BO_RNG_LEN;
564  break;
565 
566  case PGM_OPT_REDIRECT:
567 #define PGM_OPT_REDIRECT_FIXED_LEN (2+2+2+2)
568  if (opt_len < PGM_OPT_REDIRECT_FIXED_LEN) {
569  ND_PRINT("[Bad OPT_REDIRECT option, length %u < %u]",
570  opt_len, PGM_OPT_REDIRECT_FIXED_LEN);
571  return;
572  }
573  bp += 2;
574  nla_afnum = GET_BE_U_2(bp);
575  bp += 2+2;
576  switch (nla_afnum) {
577  case AFNUM_INET:
578  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);
581  return;
582  }
583  ND_TCHECK_LEN(bp, sizeof(nd_ipv4));
584  addrtostr(bp, nla_buf, sizeof(nla_buf));
585  bp += sizeof(nd_ipv4);
586  opts_len -= PGM_OPT_REDIRECT_FIXED_LEN + sizeof(nd_ipv4);
587  break;
588  case AFNUM_INET6:
589  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);
592  return;
593  }
594  ND_TCHECK_LEN(bp, sizeof(nd_ipv6));
595  addrtostr6(bp, nla_buf, sizeof(nla_buf));
596  bp += sizeof(nd_ipv6);
597  opts_len -= PGM_OPT_REDIRECT_FIXED_LEN + sizeof(nd_ipv6);
598  break;
599  default:
600  goto trunc;
601  break;
602  }
603 
604  ND_PRINT(" REDIRECT %s", nla_buf);
605  break;
606 
607  case PGM_OPT_PARITY_PRM:
608 #define PGM_OPT_PARITY_PRM_LEN (2+2+4)
609  if (opt_len != PGM_OPT_PARITY_PRM_LEN) {
610  ND_PRINT("[Bad OPT_PARITY_PRM option, length %u != %u]",
611  opt_len, PGM_OPT_PARITY_PRM_LEN);
612  return;
613  }
614  bp += 2;
615  len = GET_BE_U_4(bp);
616  bp += 4;
617  ND_PRINT(" PARITY MAXTGS %u", len);
618  opts_len -= PGM_OPT_PARITY_PRM_LEN;
619  break;
620 
621  case PGM_OPT_PARITY_GRP:
622 #define PGM_OPT_PARITY_GRP_LEN (2+2+4)
623  if (opt_len != PGM_OPT_PARITY_GRP_LEN) {
624  ND_PRINT("[Bad OPT_PARITY_GRP option, length %u != %u]",
625  opt_len, PGM_OPT_PARITY_GRP_LEN);
626  return;
627  }
628  bp += 2;
629  seq = GET_BE_U_4(bp);
630  bp += 4;
631  ND_PRINT(" PARITY GROUP %u", seq);
632  opts_len -= PGM_OPT_PARITY_GRP_LEN;
633  break;
634 
635  case PGM_OPT_CURR_TGSIZE:
636 #define PGM_OPT_CURR_TGSIZE_LEN (2+2+4)
637  if (opt_len != PGM_OPT_CURR_TGSIZE_LEN) {
638  ND_PRINT("[Bad OPT_CURR_TGSIZE option, length %u != %u]",
639  opt_len, PGM_OPT_CURR_TGSIZE_LEN);
640  return;
641  }
642  bp += 2;
643  len = GET_BE_U_4(bp);
644  bp += 4;
645  ND_PRINT(" PARITY ATGS %u", len);
646  opts_len -= PGM_OPT_CURR_TGSIZE_LEN;
647  break;
648 
649  case PGM_OPT_NBR_UNREACH:
650 #define PGM_OPT_NBR_UNREACH_LEN (2+2)
651  if (opt_len != PGM_OPT_NBR_UNREACH_LEN) {
652  ND_PRINT("[Bad OPT_NBR_UNREACH option, length %u != %u]",
653  opt_len, PGM_OPT_NBR_UNREACH_LEN);
654  return;
655  }
656  bp += 2;
657  ND_PRINT(" NBR_UNREACH");
658  opts_len -= PGM_OPT_NBR_UNREACH_LEN;
659  break;
660 
661  case PGM_OPT_PATH_NLA:
662  ND_PRINT(" PATH_NLA [%u]", opt_len);
663  bp += opt_len;
664  opts_len -= opt_len;
665  break;
666 
667  case PGM_OPT_SYN:
668 #define PGM_OPT_SYN_LEN (2+2)
669  if (opt_len != PGM_OPT_SYN_LEN) {
670  ND_PRINT("[Bad OPT_SYN option, length %u != %u]",
671  opt_len, PGM_OPT_SYN_LEN);
672  return;
673  }
674  bp += 2;
675  ND_PRINT(" SYN");
676  opts_len -= PGM_OPT_SYN_LEN;
677  break;
678 
679  case PGM_OPT_FIN:
680 #define PGM_OPT_FIN_LEN (2+2)
681  if (opt_len != PGM_OPT_FIN_LEN) {
682  ND_PRINT("[Bad OPT_FIN option, length %u != %u]",
683  opt_len, PGM_OPT_FIN_LEN);
684  return;
685  }
686  bp += 2;
687  ND_PRINT(" FIN");
688  opts_len -= PGM_OPT_FIN_LEN;
689  break;
690 
691  case PGM_OPT_RST:
692 #define PGM_OPT_RST_LEN (2+2)
693  if (opt_len != PGM_OPT_RST_LEN) {
694  ND_PRINT("[Bad OPT_RST option, length %u != %u]",
695  opt_len, PGM_OPT_RST_LEN);
696  return;
697  }
698  bp += 2;
699  ND_PRINT(" RST");
700  opts_len -= PGM_OPT_RST_LEN;
701  break;
702 
703  case PGM_OPT_CR:
704  ND_PRINT(" CR");
705  bp += opt_len;
706  opts_len -= opt_len;
707  break;
708 
709  case PGM_OPT_CRQST:
710 #define PGM_OPT_CRQST_LEN (2+2)
711  if (opt_len != PGM_OPT_CRQST_LEN) {
712  ND_PRINT("[Bad OPT_CRQST option, length %u != %u]",
713  opt_len, PGM_OPT_CRQST_LEN);
714  return;
715  }
716  bp += 2;
717  ND_PRINT(" CRQST");
718  opts_len -= PGM_OPT_CRQST_LEN;
719  break;
720 
721  case PGM_OPT_PGMCC_DATA:
722 #define PGM_OPT_PGMCC_DATA_FIXED_LEN (2+2+4+2+2)
723  if (opt_len < PGM_OPT_PGMCC_DATA_FIXED_LEN) {
724  ND_PRINT("[Bad OPT_PGMCC_DATA option, length %u < %u]",
726  return;
727  }
728  bp += 2;
729  offset = GET_BE_U_4(bp);
730  bp += 4;
731  nla_afnum = GET_BE_U_2(bp);
732  bp += 2+2;
733  switch (nla_afnum) {
734  case AFNUM_INET:
735  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]",
738  return;
739  }
740  ND_TCHECK_LEN(bp, sizeof(nd_ipv4));
741  addrtostr(bp, nla_buf, sizeof(nla_buf));
742  bp += sizeof(nd_ipv4);
743  opts_len -= PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(nd_ipv4);
744  break;
745  case AFNUM_INET6:
746  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]",
749  return;
750  }
751  ND_TCHECK_LEN(bp, sizeof(nd_ipv6));
752  addrtostr6(bp, nla_buf, sizeof(nla_buf));
753  bp += sizeof(nd_ipv6);
754  opts_len -= PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(nd_ipv6);
755  break;
756  default:
757  goto trunc;
758  break;
759  }
760 
761  ND_PRINT(" PGMCC DATA %u %s", offset, nla_buf);
762  break;
763 
765 #define PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN (2+2+4+2+2)
766  if (opt_len < PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN) {
767  ND_PRINT("[Bad PGM_OPT_PGMCC_FEEDBACK option, length %u < %u]",
769  return;
770  }
771  bp += 2;
772  offset = GET_BE_U_4(bp);
773  bp += 4;
774  nla_afnum = GET_BE_U_2(bp);
775  bp += 2+2;
776  switch (nla_afnum) {
777  case AFNUM_INET:
778  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]",
781  return;
782  }
783  ND_TCHECK_LEN(bp, sizeof(nd_ipv4));
784  addrtostr(bp, nla_buf, sizeof(nla_buf));
785  bp += sizeof(nd_ipv4);
786  opts_len -= PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(nd_ipv4);
787  break;
788  case AFNUM_INET6:
789  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]",
792  return;
793  }
794  ND_TCHECK_LEN(bp, sizeof(nd_ipv6));
795  addrtostr6(bp, nla_buf, sizeof(nla_buf));
796  bp += sizeof(nd_ipv6);
797  opts_len -= PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(nd_ipv6);
798  break;
799  default:
800  goto trunc;
801  break;
802  }
803 
804  ND_PRINT(" PGMCC FEEDBACK %u %s", offset, nla_buf);
805  break;
806 
807  default:
808  ND_PRINT(" OPT_%02X [%u] ", opt_type, opt_len);
809  bp += opt_len;
810  opts_len -= opt_len;
811  break;
812  }
813 
814  if (opt_type & PGM_OPT_END)
815  break;
816  }
817  }
818 
819  ND_PRINT(" [%u]", length);
820  if (ndo->ndo_packettype == PT_PGM_ZMTP1 &&
821  (pgm_type_val == PGM_ODATA || pgm_type_val == PGM_RDATA))
822  zmtp1_datagram_print(ndo, bp,
823  GET_BE_U_2(pgm->pgm_length));
824 
825  return;
826 
827 trunc:
828  nd_print_trunc(ndo);
829 }
const char * tcpport_string(netdissect_options *ndo, u_short port)
Definition: addrtoname.c:739
#define GET_IPADDR_STRING(p)
Definition: addrtoname.h:120
#define GET_IP6ADDR_STRING(p)
Definition: addrtoname.h:121
#define INET6_ADDRSTRLEN
Definition: addrtoname.h:29
const char * addrtostr(const void *src, char *dst, size_t size)
Definition: addrtostr.c:62
const char * addrtostr6(const void *src, char *dst, size_t size)
Definition: addrtostr.c:99
#define AFNUM_INET6
Definition: af.h:23
#define AFNUM_INET
Definition: af.h:22
#define GET_BE_U_4(p)
Definition: extract.h:877
#define GET_BE_U_2(p)
Definition: extract.h:875
#define ND_TTEST_2(p)
Definition: extract.h:554
#define GET_U_1(p)
Definition: extract.h:872
#define IP_V(ip)
Definition: ip.h:54
#define IPPROTO_PGM
Definition: ipproto.h:135
unsigned char nd_uint16_t[2]
Definition: netdissect.h:47
void zmtp1_datagram_print(netdissect_options *, const u_char *, const u_int)
Definition: print-zeromq.c:207
#define ND_TCHECK_LEN(p, l)
Definition: netdissect.h:368
#define ND_TCHECK_SIZE(p)
Definition: netdissect.h:372
unsigned char nd_byte
Definition: netdissect.h:108
void nd_print_trunc(netdissect_options *)
Definition: util-print.c:409
#define PT_PGM_ZMTP1
Definition: netdissect.h:287
unsigned char nd_ipv4[4]
Definition: netdissect.h:92
#define ND_PRINT(...)
Definition: netdissect.h:385
unsigned char nd_uint32_t[4]
Definition: netdissect.h:49
unsigned char nd_uint8_t[1]
Definition: netdissect.h:46
unsigned char nd_ipv6[16]
Definition: netdissect.h:97
#define PGM_OPT_NAK_BO_RNG
Definition: print-pgm.c:121
#define PGM_OPT_PGMCC_DATA
Definition: print-pgm.c:136
_pgm_type
Definition: print-pgm.c:97
@ PGM_SPMR
Definition: print-pgm.c:107
@ PGM_MAX
Definition: print-pgm.c:108
@ PGM_POLR
Definition: print-pgm.c:100
@ PGM_NCF
Definition: print-pgm.c:105
@ PGM_SPM
Definition: print-pgm.c:98
@ PGM_ACK
Definition: print-pgm.c:106
@ PGM_NAK
Definition: print-pgm.c:103
@ PGM_NULLNAK
Definition: print-pgm.c:104
@ PGM_POLL
Definition: print-pgm.c:99
@ PGM_ODATA
Definition: print-pgm.c:101
@ PGM_RDATA
Definition: print-pgm.c:102
#define PGM_OPT_NAK_BO_IVL_LEN
#define PGM_OPT_PARITY_GRP_LEN
#define PGM_OPT_JOIN
Definition: print-pgm.c:119
#define PGM_OPT_RST
Definition: print-pgm.c:132
#define PGM_OPT_FRAGMENT
Definition: print-pgm.c:117
enum _pgm_type pgm_type
#define PGM_OPT_PGMCC_DATA_FIXED_LEN
#define PGM_OPT_JOIN_LEN
#define PGM_OPT_REDIRECT_FIXED_LEN
#define PGM_OPT_PGMCC_FEEDBACK
Definition: print-pgm.c:137
#define PGM_OPT_NBR_UNREACH
Definition: print-pgm.c:127
#define PGM_OPT_BIT_PRESENT
Definition: print-pgm.c:111
#define PGM_OPT_CR
Definition: print-pgm.c:133
#define PGM_OPT_PATH_NLA
Definition: print-pgm.c:128
#define PGM_OPT_LENGTH_LEN
#define PGM_MIN_OPT_LEN
Definition: print-pgm.c:143
#define PGM_OPT_REDIRECT
Definition: print-pgm.c:123
#define PGM_OPT_NAK_BO_RNG_LEN
#define PGM_OPT_NBR_UNREACH_LEN
#define PGM_OPT_SYN
Definition: print-pgm.c:130
#define PGM_OPT_SYN_LEN
#define PGM_OPT_LENGTH
Definition: print-pgm.c:116
void pgm_print(netdissect_options *ndo, const u_char *bp, u_int length, const u_char *bp2)
Definition: print-pgm.c:146
#define PGM_OPT_PARITY_PRM
Definition: print-pgm.c:124
#define PGM_OPT_PARITY_GRP
Definition: print-pgm.c:125
#define PGM_OPT_END
Definition: print-pgm.c:141
#define PGM_OPT_RST_LEN
#define PGM_OPT_CRQST
Definition: print-pgm.c:134
#define PGM_OPT_NAK_LIST
Definition: print-pgm.c:118
#define PGM_OPT_NAK_BO_IVL
Definition: print-pgm.c:120
#define PGM_OPT_CURR_TGSIZE_LEN
#define PGM_OPT_CRQST_LEN
#define PGM_OPT_PARITY_PRM_LEN
#define PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN
#define PGM_OPT_MASK
Definition: print-pgm.c:139
#define PGM_OPT_FRAGMENT_LEN
#define PGM_OPT_FIN_LEN
#define PGM_OPT_CURR_TGSIZE
Definition: print-pgm.c:126
#define PGM_OPT_FIN
Definition: print-pgm.c:131
Definition: ip6.h:76
nd_ipv6 ip6_dst
Definition: ip6.h:87
nd_ipv6 ip6_src
Definition: ip6.h:86
Definition: ip.h:52
nd_ipv4 ip_dst
Definition: ip.h:66
nd_uint8_t ip_p
Definition: ip.h:64
nd_ipv4 ip_src
Definition: ip.h:66
const char * ndo_protocol
Definition: netdissect.h:218
nd_uint32_t pgma_bitmap
Definition: print-pgm.c:70
nd_uint32_t pgma_rx_max_seq
Definition: print-pgm.c:69
nd_uint32_t pgmd_seq
Definition: print-pgm.c:92
nd_uint32_t pgmd_trailseq
Definition: print-pgm.c:93
nd_uint16_t pgm_dport
Definition: print-pgm.c:39
nd_uint16_t pgm_sport
Definition: print-pgm.c:38
nd_uint16_t pgm_sum
Definition: print-pgm.c:42
nd_uint8_t pgm_options
Definition: print-pgm.c:41
nd_uint16_t pgm_length
Definition: print-pgm.c:44
nd_byte pgm_gsid[6]
Definition: print-pgm.c:43
nd_uint8_t pgm_type
Definition: print-pgm.c:40
nd_uint32_t pgmn_seq
Definition: print-pgm.c:58
nd_uint16_t pgmn_reserved
Definition: print-pgm.c:60
nd_uint16_t pgmn_source_afi
Definition: print-pgm.c:59
nd_uint16_t pgmp_subtype
Definition: print-pgm.c:77
nd_uint32_t pgmp_seq
Definition: print-pgm.c:75
nd_uint16_t pgmp_reserved
Definition: print-pgm.c:79
nd_uint16_t pgmp_round
Definition: print-pgm.c:76
nd_uint16_t pgmp_nla_afi
Definition: print-pgm.c:78
nd_uint16_t pgmp_round
Definition: print-pgm.c:86
nd_uint32_t pgmp_seq
Definition: print-pgm.c:85
nd_uint16_t pgmp_reserved
Definition: print-pgm.c:87
nd_uint32_t pgms_seq
Definition: print-pgm.c:48
nd_uint16_t pgms_reserved
Definition: print-pgm.c:52
nd_uint16_t pgms_nla_afi
Definition: print-pgm.c:51
nd_uint32_t pgms_leadseq
Definition: print-pgm.c:50
nd_uint32_t pgms_trailseq
Definition: print-pgm.c:49