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-pim.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 1995, 1996
3  * The Regents of the University of California. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that: (1) source code distributions
7  * retain the above copyright notice and this paragraph in its entirety, (2)
8  * distributions including binary code include the above copyright notice and
9  * this paragraph in its entirety in the documentation or other materials
10  * provided with the distribution, and (3) all advertising materials mentioning
11  * features or use of this software display the following acknowledgement:
12  * ``This product includes software developed by the University of California,
13  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14  * the University nor the names of its contributors may be used to endorse
15  * or promote products derived from this software without specific prior
16  * written permission.
17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20  */
21 
22 /* \summary: Protocol Independent Multicast (PIM) printer */
23 
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27 
28 #include "netdissect-stdinc.h"
29 
30 #include "netdissect.h"
31 #include "addrtoname.h"
32 #include "extract.h"
33 
34 #include "ip.h"
35 #include "ip6.h"
36 #include "ipproto.h"
37 
38 #define PIMV1_TYPE_QUERY 0
39 #define PIMV1_TYPE_REGISTER 1
40 #define PIMV1_TYPE_REGISTER_STOP 2
41 #define PIMV1_TYPE_JOIN_PRUNE 3
42 #define PIMV1_TYPE_RP_REACHABILITY 4
43 #define PIMV1_TYPE_ASSERT 5
44 #define PIMV1_TYPE_GRAFT 6
45 #define PIMV1_TYPE_GRAFT_ACK 7
46 
47 static const struct tok pimv1_type_str[] = {
48  { PIMV1_TYPE_QUERY, "Query" },
49  { PIMV1_TYPE_REGISTER, "Register" },
50  { PIMV1_TYPE_REGISTER_STOP, "Register-Stop" },
51  { PIMV1_TYPE_JOIN_PRUNE, "Join/Prune" },
52  { PIMV1_TYPE_RP_REACHABILITY, "RP-reachable" },
53  { PIMV1_TYPE_ASSERT, "Assert" },
54  { PIMV1_TYPE_GRAFT, "Graft" },
55  { PIMV1_TYPE_GRAFT_ACK, "Graft-ACK" },
56  { 0, NULL }
57 };
58 
59 #define PIMV2_TYPE_HELLO 0
60 #define PIMV2_TYPE_REGISTER 1
61 #define PIMV2_TYPE_REGISTER_STOP 2
62 #define PIMV2_TYPE_JOIN_PRUNE 3
63 #define PIMV2_TYPE_BOOTSTRAP 4
64 #define PIMV2_TYPE_ASSERT 5
65 #define PIMV2_TYPE_GRAFT 6
66 #define PIMV2_TYPE_GRAFT_ACK 7
67 #define PIMV2_TYPE_CANDIDATE_RP 8
68 #define PIMV2_TYPE_PRUNE_REFRESH 9
69 #define PIMV2_TYPE_DF_ELECTION 10
70 #define PIMV2_TYPE_ECMP_REDIRECT 11
71 
72 static const struct tok pimv2_type_values[] = {
73  { PIMV2_TYPE_HELLO, "Hello" },
74  { PIMV2_TYPE_REGISTER, "Register" },
75  { PIMV2_TYPE_REGISTER_STOP, "Register Stop" },
76  { PIMV2_TYPE_JOIN_PRUNE, "Join / Prune" },
77  { PIMV2_TYPE_BOOTSTRAP, "Bootstrap" },
78  { PIMV2_TYPE_ASSERT, "Assert" },
79  { PIMV2_TYPE_GRAFT, "Graft" },
80  { PIMV2_TYPE_GRAFT_ACK, "Graft Acknowledgement" },
81  { PIMV2_TYPE_CANDIDATE_RP, "Candidate RP Advertisement" },
82  { PIMV2_TYPE_PRUNE_REFRESH, "Prune Refresh" },
83  { PIMV2_TYPE_DF_ELECTION, "DF Election" },
84  { PIMV2_TYPE_ECMP_REDIRECT, "ECMP Redirect" },
85  { 0, NULL}
86 };
87 
88 #define PIMV2_HELLO_OPTION_HOLDTIME 1
89 #define PIMV2_HELLO_OPTION_LANPRUNEDELAY 2
90 #define PIMV2_HELLO_OPTION_DR_PRIORITY_OLD 18
91 #define PIMV2_HELLO_OPTION_DR_PRIORITY 19
92 #define PIMV2_HELLO_OPTION_GENID 20
93 #define PIMV2_HELLO_OPTION_REFRESH_CAP 21
94 #define PIMV2_HELLO_OPTION_BIDIR_CAP 22
95 #define PIMV2_HELLO_OPTION_ADDRESS_LIST 24
96 #define PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD 65001
97 
98 static const struct tok pimv2_hello_option_values[] = {
99  { PIMV2_HELLO_OPTION_HOLDTIME, "Hold Time" },
100  { PIMV2_HELLO_OPTION_LANPRUNEDELAY, "LAN Prune Delay" },
101  { PIMV2_HELLO_OPTION_DR_PRIORITY_OLD, "DR Priority (Old)" },
102  { PIMV2_HELLO_OPTION_DR_PRIORITY, "DR Priority" },
103  { PIMV2_HELLO_OPTION_GENID, "Generation ID" },
104  { PIMV2_HELLO_OPTION_REFRESH_CAP, "State Refresh Capability" },
105  { PIMV2_HELLO_OPTION_BIDIR_CAP, "Bi-Directional Capability" },
106  { PIMV2_HELLO_OPTION_ADDRESS_LIST, "Address List" },
107  { PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD, "Address List (Old)" },
108  { 0, NULL}
109 };
110 
111 #define PIMV2_REGISTER_FLAG_LEN 4
112 #define PIMV2_REGISTER_FLAG_BORDER 0x80000000
113 #define PIMV2_REGISTER_FLAG_NULL 0x40000000
114 
115 static const struct tok pimv2_register_flag_values[] = {
116  { PIMV2_REGISTER_FLAG_BORDER, "Border" },
117  { PIMV2_REGISTER_FLAG_NULL, "Null" },
118  { 0, NULL}
119 };
120 
121 #define PIMV2_DF_ELECTION_OFFER 1
122 #define PIMV2_DF_ELECTION_WINNER 2
123 #define PIMV2_DF_ELECTION_BACKOFF 3
124 #define PIMV2_DF_ELECTION_PASS 4
125 
126 static const struct tok pimv2_df_election_flag_values[] = {
127  { PIMV2_DF_ELECTION_OFFER, "Offer" },
128  { PIMV2_DF_ELECTION_WINNER, "Winner" },
129  { PIMV2_DF_ELECTION_BACKOFF, "Backoff" },
130  { PIMV2_DF_ELECTION_PASS, "Pass" },
131  { 0, NULL}
132 };
133 
134 #define PIMV2_DF_ELECTION_PASS_BACKOFF_STR(x) ( \
135  x == PIMV2_DF_ELECTION_BACKOFF ? "offer" : "new winner" )
136 
137 
138 /*
139  * XXX: We consider a case where IPv6 is not ready yet for portability,
140  * but PIM dependent definitions should be independent of IPv6...
141  */
142 
143 struct pim {
145  /* upper 4bit: PIM version number; 2 for PIMv2 */
146  /* lower 4bit: the PIM message type, currently they are:
147  * Hello, Register, Register-Stop, Join/Prune,
148  * Bootstrap, Assert, Graft (PIM-DM only),
149  * Graft-Ack (PIM-DM only), C-RP-Adv
150  */
151 #define PIM_VER(x) (((x) & 0xf0) >> 4)
152 #define PIM_TYPE(x) ((x) & 0x0f)
153  nd_uint8_t pim_rsv; /* Reserved in v1, subtype+address length in v2 */
154 #define PIM_SUBTYPE(x) (((x) & 0xf0) >> 4)
155  nd_uint16_t pim_cksum; /* IP style check sum */
156 };
157 
158 static void pimv2_print(netdissect_options *, const u_char *bp, u_int len, const u_char *);
159 
160 static void
162  const u_char *bp, u_int len)
163 {
164  u_int ngroups, njoin, nprune;
165  u_int njp;
166 
167  /* If it's a single group and a single source, use 1-line output. */
168  if (ND_TTEST_LEN(bp, 30) && GET_U_1(bp + 11) == 1 &&
169  ((njoin = GET_BE_U_2(bp + 20)) + GET_BE_U_2(bp + 22)) == 1) {
170  u_int hold;
171 
172  ND_PRINT(" RPF %s ", GET_IPADDR_STRING(bp));
173  hold = GET_BE_U_2(bp + 6);
174  if (hold != 180) {
175  ND_PRINT("Hold ");
176  unsigned_relts_print(ndo, hold);
177  }
178  ND_PRINT("%s (%s/%u, %s", njoin ? "Join" : "Prune",
179  GET_IPADDR_STRING(bp + 26), GET_U_1(bp + 25) & 0x3f,
180  GET_IPADDR_STRING(bp + 12));
181  if (GET_BE_U_4(bp + 16) != 0xffffffff)
182  ND_PRINT("/%s", GET_IPADDR_STRING(bp + 16));
183  ND_PRINT(") %s%s %s",
184  (GET_U_1(bp + 24) & 0x01) ? "Sparse" : "Dense",
185  (GET_U_1(bp + 25) & 0x80) ? " WC" : "",
186  (GET_U_1(bp + 25) & 0x40) ? "RP" : "SPT");
187  return;
188  }
189 
190  if (len < sizeof(nd_ipv4))
191  goto trunc;
192  if (ndo->ndo_vflag > 1)
193  ND_PRINT("\n");
194  ND_PRINT(" Upstream Nbr: %s", GET_IPADDR_STRING(bp));
195  bp += 4;
196  len -= 4;
197  if (len < 4)
198  goto trunc;
199  if (ndo->ndo_vflag > 1)
200  ND_PRINT("\n");
201  ND_PRINT(" Hold time: ");
202  unsigned_relts_print(ndo, GET_BE_U_2(bp + 2));
203  if (ndo->ndo_vflag < 2)
204  return;
205  bp += 4;
206  len -= 4;
207 
208  if (len < 4)
209  goto trunc;
210  ngroups = GET_U_1(bp + 3);
211  bp += 4;
212  len -= 4;
213  while (ngroups != 0) {
214  /*
215  * XXX - does the address have length "addrlen" and the
216  * mask length "maddrlen"?
217  */
218  if (len < 4)
219  goto trunc;
220  ND_PRINT("\n\tGroup: %s", GET_IPADDR_STRING(bp));
221  bp += 4;
222  len -= 4;
223  if (len < 4)
224  goto trunc;
225  if (GET_BE_U_4(bp) != 0xffffffff)
226  ND_PRINT("/%s", GET_IPADDR_STRING(bp));
227  bp += 4;
228  len -= 4;
229  if (len < 4)
230  goto trunc;
231  njoin = GET_BE_U_2(bp);
232  nprune = GET_BE_U_2(bp + 2);
233  ND_PRINT(" joined: %u pruned: %u", njoin, nprune);
234  bp += 4;
235  len -= 4;
236  for (njp = 0; njp < (njoin + nprune); njp++) {
237  const char *type;
238 
239  if (njp < njoin)
240  type = "Join ";
241  else
242  type = "Prune";
243  if (len < 6)
244  goto trunc;
245  ND_PRINT("\n\t%s %s%s%s%s/%u", type,
246  (GET_U_1(bp) & 0x01) ? "Sparse " : "Dense ",
247  (GET_U_1(bp + 1) & 0x80) ? "WC " : "",
248  (GET_U_1(bp + 1) & 0x40) ? "RP " : "SPT ",
249  GET_IPADDR_STRING(bp + 2),
250  GET_U_1(bp + 1) & 0x3f);
251  bp += 6;
252  len -= 6;
253  }
254  ngroups--;
255  }
256  return;
257 trunc:
258  nd_print_trunc(ndo);
259 }
260 
261 void
263  const u_char *bp, u_int len)
264 {
265  u_char type;
266 
267  ndo->ndo_protocol = "pimv1";
268  type = GET_U_1(bp + 1);
269 
270  ND_PRINT(" %s", tok2str(pimv1_type_str, "[type %u]", type));
271  switch (type) {
272  case PIMV1_TYPE_QUERY:
273  if (ND_TTEST_1(bp + 8)) {
274  switch (GET_U_1(bp + 8) >> 4) {
275  case 0:
276  ND_PRINT(" Dense-mode");
277  break;
278  case 1:
279  ND_PRINT(" Sparse-mode");
280  break;
281  case 2:
282  ND_PRINT(" Sparse-Dense-mode");
283  break;
284  default:
285  ND_PRINT(" mode-%u", GET_U_1(bp + 8) >> 4);
286  break;
287  }
288  }
289  if (ndo->ndo_vflag) {
290  ND_PRINT(" (Hold-time ");
291  unsigned_relts_print(ndo, GET_BE_U_2(bp + 10));
292  ND_PRINT(")");
293  }
294  break;
295 
296  case PIMV1_TYPE_REGISTER:
297  ND_TCHECK_LEN(bp + 8, 20); /* ip header */
298  ND_PRINT(" for %s > %s", GET_IPADDR_STRING(bp + 20),
299  GET_IPADDR_STRING(bp + 24));
300  break;
302  ND_PRINT(" for %s > %s", GET_IPADDR_STRING(bp + 8),
303  GET_IPADDR_STRING(bp + 12));
304  break;
306  if (ndo->ndo_vflag) {
307  ND_PRINT(" group %s", GET_IPADDR_STRING(bp + 8));
308  if (GET_BE_U_4(bp + 12) != 0xffffffff)
309  ND_PRINT("/%s", GET_IPADDR_STRING(bp + 12));
310  ND_PRINT(" RP %s hold ", GET_IPADDR_STRING(bp + 16));
311  unsigned_relts_print(ndo, GET_BE_U_2(bp + 22));
312  }
313  break;
314  case PIMV1_TYPE_ASSERT:
315  ND_PRINT(" for %s > %s", GET_IPADDR_STRING(bp + 16),
316  GET_IPADDR_STRING(bp + 8));
317  if (GET_BE_U_4(bp + 12) != 0xffffffff)
318  ND_PRINT("/%s", GET_IPADDR_STRING(bp + 12));
319  ND_PRINT(" %s pref %u metric %u",
320  (GET_U_1(bp + 20) & 0x80) ? "RP-tree" : "SPT",
321  GET_BE_U_4(bp + 20) & 0x7fffffff,
322  GET_BE_U_4(bp + 24));
323  break;
325  case PIMV1_TYPE_GRAFT:
327  if (ndo->ndo_vflag) {
328  if (len < 8)
329  goto trunc;
330  pimv1_join_prune_print(ndo, bp + 8, len - 8);
331  }
332  break;
333  }
334  if ((GET_U_1(bp + 4) >> 4) != 1)
335  ND_PRINT(" [v%u]", GET_U_1(bp + 4) >> 4);
336  return;
337 
338 trunc:
339  nd_print_trunc(ndo);
340 }
341 
342 /*
343  * auto-RP is a cisco protocol, documented at
344  * ftp://ftpeng.cisco.com/ipmulticast/specs/pim-autorp-spec01.txt
345  *
346  * This implements version 1+, dated Sept 9, 1998.
347  */
348 void
350  const u_char *bp, u_int len)
351 {
352  u_int type;
353  u_int numrps;
354  u_int hold;
355 
356  ndo->ndo_protocol = "cisco_autorp";
357  if (len < 8)
358  goto trunc;
359  ND_PRINT(" auto-rp ");
360  type = GET_U_1(bp);
361  switch (type) {
362  case 0x11:
363  ND_PRINT("candidate-advert");
364  break;
365  case 0x12:
366  ND_PRINT("mapping");
367  break;
368  default:
369  ND_PRINT("type-0x%02x", type);
370  break;
371  }
372 
373  numrps = GET_U_1(bp + 1);
374 
375  ND_PRINT(" Hold ");
376  hold = GET_BE_U_2(bp + 2);
377  if (hold)
378  unsigned_relts_print(ndo, GET_BE_U_2(bp + 2));
379  else
380  ND_PRINT("FOREVER");
381 
382  /* Next 4 bytes are reserved. */
383 
384  bp += 8; len -= 8;
385 
386  /*XXX skip unless -v? */
387 
388  /*
389  * Rest of packet:
390  * numrps entries of the form:
391  * 32 bits: RP
392  * 6 bits: reserved
393  * 2 bits: PIM version supported, bit 0 is "supports v1", 1 is "v2".
394  * 8 bits: # of entries for this RP
395  * each entry: 7 bits: reserved, 1 bit: negative,
396  * 8 bits: mask 32 bits: source
397  * lather, rinse, repeat.
398  */
399  while (numrps != 0) {
400  u_int nentries;
401  char s;
402 
403  if (len < 4)
404  goto trunc;
405  ND_PRINT(" RP %s", GET_IPADDR_STRING(bp));
406  bp += 4;
407  len -= 4;
408  if (len < 1)
409  goto trunc;
410  switch (GET_U_1(bp) & 0x3) {
411  case 0: ND_PRINT(" PIMv?");
412  break;
413  case 1: ND_PRINT(" PIMv1");
414  break;
415  case 2: ND_PRINT(" PIMv2");
416  break;
417  case 3: ND_PRINT(" PIMv1+2");
418  break;
419  }
420  if (GET_U_1(bp) & 0xfc)
421  ND_PRINT(" [rsvd=0x%02x]", GET_U_1(bp) & 0xfc);
422  bp += 1;
423  len -= 1;
424  if (len < 1)
425  goto trunc;
426  nentries = GET_U_1(bp);
427  bp += 1;
428  len -= 1;
429  s = ' ';
430  while (nentries != 0) {
431  if (len < 6)
432  goto trunc;
433  ND_PRINT("%c%s%s/%u", s, GET_U_1(bp) & 1 ? "!" : "",
434  GET_IPADDR_STRING(bp + 2), GET_U_1(bp + 1));
435  if (GET_U_1(bp) & 0x02) {
436  ND_PRINT(" bidir");
437  }
438  if (GET_U_1(bp) & 0xfc) {
439  ND_PRINT("[rsvd=0x%02x]", GET_U_1(bp) & 0xfc);
440  }
441  s = ',';
442  bp += 6; len -= 6;
443  nentries--;
444  }
445  numrps--;
446  }
447  return;
448 
449 trunc:
450  nd_print_trunc(ndo);
451 }
452 
453 void
455  const u_char *bp, u_int len, const u_char *bp2)
456 {
457  const struct pim *pim = (const struct pim *)bp;
458  uint8_t pim_typever;
459 
460  ndo->ndo_protocol = "pim";
461 
463  switch (PIM_VER(pim_typever)) {
464  case 2:
465  if (!ndo->ndo_vflag) {
466  ND_PRINT("PIMv%u, %s, length %u",
469  len);
470  return;
471  } else {
472  ND_PRINT("PIMv%u, length %u\n\t%s",
474  len,
475  tok2str(pimv2_type_values,"Unknown Type",PIM_TYPE(pim_typever)));
476  pimv2_print(ndo, bp, len, bp2);
477  }
478  break;
479  default:
480  ND_PRINT("PIMv%u, length %u",
482  len);
483  break;
484  }
485 }
486 
487 /*
488  * PIMv2 uses encoded address representations.
489  *
490  * The last PIM-SM I-D before RFC2117 was published specified the
491  * following representation for unicast addresses. However, RFC2117
492  * specified no encoding for unicast addresses with the unicast
493  * address length specified in the header. Therefore, we have to
494  * guess which encoding is being used (Cisco's PIMv2 implementation
495  * uses the non-RFC encoding). RFC2117 turns a previously "Reserved"
496  * field into a 'unicast-address-length-in-bytes' field. We guess
497  * that it's the draft encoding if this reserved field is zero.
498  *
499  * RFC2362 goes back to the encoded format, and calls the addr length
500  * field "reserved" again.
501  *
502  * The first byte is the address family, from:
503  *
504  * 0 Reserved
505  * 1 IP (IP version 4)
506  * 2 IP6 (IP version 6)
507  * 3 NSAP
508  * 4 HDLC (8-bit multidrop)
509  * 5 BBN 1822
510  * 6 802 (includes all 802 media plus Ethernet "canonical format")
511  * 7 E.163
512  * 8 E.164 (SMDS, Frame Relay, ATM)
513  * 9 F.69 (Telex)
514  * 10 X.121 (X.25, Frame Relay)
515  * 11 IPX
516  * 12 Appletalk
517  * 13 Decnet IV
518  * 14 Banyan Vines
519  * 15 E.164 with NSAP format subaddress
520  *
521  * In addition, the second byte is an "Encoding". 0 is the default
522  * encoding for the address family, and no other encodings are currently
523  * specified.
524  *
525  */
526 
529 };
530 
531 /* 0 1 2 3
532  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
533  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
534  * | Addr Family | Encoding Type | Unicast Address |
535  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+++++++
536  * 0 1 2 3
537  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
538  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
539  * | Addr Family | Encoding Type | Reserved | Mask Len |
540  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
541  * | Group multicast Address |
542  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
543  * 0 1 2 3
544  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
545  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
546  * | Addr Family | Encoding Type | Rsrvd |S|W|R| Mask Len |
547  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
548  * | Source Address |
549  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
550  */
551 static int
553  const u_char *bp, u_int len, enum pimv2_addrtype at,
554  u_int addr_len, int silent)
555 {
556  u_int af;
557  int hdrlen;
558 
559  if (addr_len == 0) {
560  if (len < 2)
561  goto trunc;
562  switch (GET_U_1(bp)) {
563  case 1:
564  af = AF_INET;
565  addr_len = (u_int)sizeof(nd_ipv4);
566  break;
567  case 2:
568  af = AF_INET6;
569  addr_len = (u_int)sizeof(nd_ipv6);
570  break;
571  default:
572  return -1;
573  }
574  if (GET_U_1(bp + 1) != 0)
575  return -1;
576  hdrlen = 2;
577  } else {
578  switch (addr_len) {
579  case sizeof(nd_ipv4):
580  af = AF_INET;
581  break;
582  case sizeof(nd_ipv6):
583  af = AF_INET6;
584  break;
585  default:
586  return -1;
587  break;
588  }
589  hdrlen = 0;
590  }
591 
592  bp += hdrlen;
593  len -= hdrlen;
594  switch (at) {
595  case pimv2_unicast:
596  if (len < addr_len)
597  goto trunc;
598  ND_TCHECK_LEN(bp, addr_len);
599  if (af == AF_INET) {
600  if (!silent)
601  ND_PRINT("%s", GET_IPADDR_STRING(bp));
602  }
603  else if (af == AF_INET6) {
604  if (!silent)
605  ND_PRINT("%s", GET_IP6ADDR_STRING(bp));
606  }
607  return hdrlen + addr_len;
608  case pimv2_group:
609  case pimv2_source:
610  if (len < addr_len + 2)
611  goto trunc;
612  ND_TCHECK_LEN(bp, addr_len + 2);
613  if (af == AF_INET) {
614  if (!silent) {
615  ND_PRINT("%s", GET_IPADDR_STRING(bp + 2));
616  if (GET_U_1(bp + 1) != 32)
617  ND_PRINT("/%u", GET_U_1(bp + 1));
618  }
619  }
620  else if (af == AF_INET6) {
621  if (!silent) {
622  ND_PRINT("%s", GET_IP6ADDR_STRING(bp + 2));
623  if (GET_U_1(bp + 1) != 128)
624  ND_PRINT("/%u", GET_U_1(bp + 1));
625  }
626  }
627  if (GET_U_1(bp) && !silent) {
628  if (at == pimv2_group) {
629  ND_PRINT("(0x%02x)", GET_U_1(bp));
630  } else {
631  ND_PRINT("(%s%s%s",
632  GET_U_1(bp) & 0x04 ? "S" : "",
633  GET_U_1(bp) & 0x02 ? "W" : "",
634  GET_U_1(bp) & 0x01 ? "R" : "");
635  if (GET_U_1(bp) & 0xf8) {
636  ND_PRINT("+0x%02x",
637  GET_U_1(bp) & 0xf8);
638  }
639  ND_PRINT(")");
640  }
641  }
642  return hdrlen + 2 + addr_len;
643  default:
644  return -1;
645  }
646 trunc:
647  return -1;
648 }
649 
653  UNVERIFIED
654 };
655 
656 static enum checksum_status
657 pimv2_check_checksum(netdissect_options *ndo, const u_char *bp,
658  const u_char *bp2, u_int len)
659 {
660  const struct ip *ip;
661  u_int cksum;
662 
663  if (!ND_TTEST_LEN(bp, len)) {
664  /* We don't have all the data. */
665  return (UNVERIFIED);
666  }
667  ip = (const struct ip *)bp2;
668  if (IP_V(ip) == 4) {
669  struct cksum_vec vec[1];
670 
671  vec[0].ptr = bp;
672  vec[0].len = len;
673  cksum = in_cksum(vec, 1);
674  return (cksum ? INCORRECT : CORRECT);
675  } else if (IP_V(ip) == 6) {
676  const struct ip6_hdr *ip6;
677 
678  ip6 = (const struct ip6_hdr *)bp2;
679  cksum = nextproto6_cksum(ndo, ip6, bp, len, len, IPPROTO_PIM);
680  return (cksum ? INCORRECT : CORRECT);
681  } else {
682  return (UNVERIFIED);
683  }
684 }
685 
686 static void
688  const u_char *bp, u_int len, const u_char *bp2)
689 {
690  const struct pim *pim = (const struct pim *)bp;
691  int advance;
692  int subtype;
693  enum checksum_status cksum_status;
694  u_int pim_typever;
695  u_int pimv2_addr_len;
696 
697  ndo->ndo_protocol = "pimv2";
698  if (len < 2) {
699  ND_PRINT("[length %u < 2]", len);
700  nd_print_invalid(ndo);
701  return;
702  }
704  /* RFC5015 allocates the high 4 bits of pim_rsv for "subtype". */
705  pimv2_addr_len = GET_U_1(pim->pim_rsv) & 0x0f;
706  if (pimv2_addr_len != 0)
707  ND_PRINT(", RFC2117-encoding");
708 
709  if (len < 4) {
710  ND_PRINT("[length %u < 4]", len);
711  nd_print_invalid(ndo);
712  return;
713  }
714  ND_PRINT(", cksum 0x%04x ", GET_BE_U_2(pim->pim_cksum));
715  if (GET_BE_U_2(pim->pim_cksum) == 0) {
716  ND_PRINT("(unverified)");
717  } else {
719  /*
720  * The checksum only covers the packet header,
721  * not the encapsulated packet.
722  */
723  cksum_status = pimv2_check_checksum(ndo, bp, bp2, 8);
724  if (cksum_status == INCORRECT) {
725  /*
726  * To quote RFC 4601, "For interoperability
727  * reasons, a message carrying a checksum
728  * calculated over the entire PIM Register
729  * message should also be accepted."
730  */
731  cksum_status = pimv2_check_checksum(ndo, bp, bp2, len);
732  }
733  } else {
734  /*
735  * The checksum covers the entire packet.
736  */
737  cksum_status = pimv2_check_checksum(ndo, bp, bp2, len);
738  }
739  switch (cksum_status) {
740 
741  case CORRECT:
742  ND_PRINT("(correct)");
743  break;
744 
745  case INCORRECT:
746  ND_PRINT("(incorrect)");
747  break;
748 
749  case UNVERIFIED:
750  ND_PRINT("(unverified)");
751  break;
752  }
753  }
754  bp += 4;
755  len -= 4;
756 
757  switch (PIM_TYPE(pim_typever)) {
758  case PIMV2_TYPE_HELLO:
759  {
760  uint16_t otype, olen;
761  while (len > 0) {
762  if (len < 4)
763  goto trunc;
764  otype = GET_BE_U_2(bp);
765  olen = GET_BE_U_2(bp + 2);
766  ND_PRINT("\n\t %s Option (%u), length %u, Value: ",
767  tok2str(pimv2_hello_option_values, "Unknown", otype),
768  otype,
769  olen);
770  bp += 4;
771  len -= 4;
772 
773  if (len < olen)
774  goto trunc;
775  ND_TCHECK_LEN(bp, olen);
776  switch (otype) {
778  if (olen != 2) {
779  ND_PRINT("[option length %u != 2]", olen);
780  nd_print_invalid(ndo);
781  return;
782  } else {
784  GET_BE_U_2(bp));
785  }
786  break;
787 
789  if (olen != 4) {
790  ND_PRINT("[option length %u != 4]", olen);
791  nd_print_invalid(ndo);
792  return;
793  } else {
794  char t_bit;
795  uint16_t lan_delay, override_interval;
796  lan_delay = GET_BE_U_2(bp);
797  override_interval = GET_BE_U_2(bp + 2);
798  t_bit = (lan_delay & 0x8000)? 1 : 0;
799  lan_delay &= ~0x8000;
800  ND_PRINT("\n\t T-bit=%u, LAN delay %ums, Override interval %ums",
801  t_bit, lan_delay, override_interval);
802  }
803  break;
804 
807  switch (olen) {
808  case 0:
809  ND_PRINT("Bi-Directional Capability (Old)");
810  break;
811  case 4:
812  ND_PRINT("%u", GET_BE_U_4(bp));
813  break;
814  default:
815  ND_PRINT("[option length %u != 4]", olen);
816  nd_print_invalid(ndo);
817  return;
818  break;
819  }
820  break;
821 
823  if (olen != 4) {
824  ND_PRINT("[option length %u != 4]", olen);
825  nd_print_invalid(ndo);
826  return;
827  } else {
828  ND_PRINT("0x%08x", GET_BE_U_4(bp));
829  }
830  break;
831 
833  if (olen != 4) {
834  ND_PRINT("[option length %u != 4]", olen);
835  nd_print_invalid(ndo);
836  return;
837  } else {
838  ND_PRINT("v%u", GET_U_1(bp));
839  if (GET_U_1(bp + 1) != 0) {
840  ND_PRINT(", interval ");
842  GET_U_1(bp + 1));
843  }
844  if (GET_BE_U_2(bp + 2) != 0) {
845  ND_PRINT(" ?0x%04x?",
846  GET_BE_U_2(bp + 2));
847  }
848  }
849  break;
850 
852  break;
853 
856  if (ndo->ndo_vflag > 1) {
857  const u_char *ptr = bp;
858  u_int plen = len;
859  while (ptr < (bp+olen)) {
860  ND_PRINT("\n\t ");
861  advance = pimv2_addr_print(ndo, ptr, plen, pimv2_unicast, pimv2_addr_len, 0);
862  if (advance < 0)
863  goto trunc;
864  ptr += advance;
865  plen -= advance;
866  }
867  }
868  break;
869  default:
870  if (ndo->ndo_vflag <= 1)
871  print_unknown_data(ndo, bp, "\n\t ", olen);
872  break;
873  }
874  /* do we want to see an additionally hexdump ? */
875  if (ndo->ndo_vflag> 1)
876  print_unknown_data(ndo, bp, "\n\t ", olen);
877  bp += olen;
878  len -= olen;
879  }
880  break;
881  }
882 
883  case PIMV2_TYPE_REGISTER:
884  {
885  const struct ip *ip;
886 
887  if (len < 4)
888  goto trunc;
890 
891  ND_PRINT(", Flags [ %s ]\n\t",
893  "none",
894  GET_BE_U_4(bp)));
895 
896  bp += 4; len -= 4;
897  /* encapsulated multicast packet */
898  if (len == 0)
899  goto trunc;
900  ip = (const struct ip *)bp;
901  switch (IP_V(ip)) {
902  case 0: /* Null header */
903  ND_PRINT("IP-Null-header %s > %s",
906  break;
907 
908  case 4: /* IPv4 */
909  ip_print(ndo, bp, len);
910  break;
911 
912  case 6: /* IPv6 */
913  ip6_print(ndo, bp, len);
914  break;
915 
916  default:
917  ND_PRINT("IP ver %u", IP_V(ip));
918  break;
919  }
920  break;
921  }
922 
924  ND_PRINT(" group=");
925  if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0)
926  goto trunc;
927  bp += advance; len -= advance;
928  ND_PRINT(" source=");
929  if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0)
930  goto trunc;
931  bp += advance; len -= advance;
932  break;
933 
935  case PIMV2_TYPE_GRAFT:
937 
938 
939  /*
940  * 0 1 2 3
941  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
942  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
943  * |PIM Ver| Type | Addr length | Checksum |
944  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
945  * | Unicast-Upstream Neighbor Address |
946  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
947  * | Reserved | Num groups | Holdtime |
948  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
949  * | Encoded-Multicast Group Address-1 |
950  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
951  * | Number of Joined Sources | Number of Pruned Sources |
952  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
953  * | Encoded-Joined Source Address-1 |
954  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
955  * | . |
956  * | . |
957  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
958  * | Encoded-Joined Source Address-n |
959  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
960  * | Encoded-Pruned Source Address-1 |
961  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
962  * | . |
963  * | . |
964  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
965  * | Encoded-Pruned Source Address-n |
966  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
967  * | . |
968  * | . |
969  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
970  * | Encoded-Multicast Group Address-n |
971  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
972  */
973 
974  {
975  uint8_t ngroup;
976  uint16_t holdtime;
977  uint16_t njoin;
978  uint16_t nprune;
979  u_int i, j;
980 
981  if (PIM_TYPE(pim_typever) != 7) { /*not for Graft-ACK*/
982  ND_PRINT(", upstream-neighbor: ");
983  if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0)
984  goto trunc;
985  bp += advance; len -= advance;
986  }
987  if (len < 4)
988  goto trunc;
989  ND_TCHECK_4(bp);
990  ngroup = GET_U_1(bp + 1);
991  holdtime = GET_BE_U_2(bp + 2);
992  ND_PRINT("\n\t %u group(s)", ngroup);
993  if (PIM_TYPE(pim_typever) != 7) { /*not for Graft-ACK*/
994  ND_PRINT(", holdtime: ");
995  if (holdtime == 0xffff)
996  ND_PRINT("infinite");
997  else
998  unsigned_relts_print(ndo, holdtime);
999  }
1000  bp += 4; len -= 4;
1001  for (i = 0; i < ngroup; i++) {
1002  ND_PRINT("\n\t group #%u: ", i+1);
1003  if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0)
1004  goto trunc;
1005  bp += advance; len -= advance;
1006  if (len < 4)
1007  goto trunc;
1008  ND_TCHECK_4(bp);
1009  njoin = GET_BE_U_2(bp);
1010  nprune = GET_BE_U_2(bp + 2);
1011  ND_PRINT(", joined sources: %u, pruned sources: %u", njoin, nprune);
1012  bp += 4; len -= 4;
1013  for (j = 0; j < njoin; j++) {
1014  ND_PRINT("\n\t joined source #%u: ", j+1);
1015  if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_source, pimv2_addr_len, 0)) < 0)
1016  goto trunc;
1017  bp += advance; len -= advance;
1018  }
1019  for (j = 0; j < nprune; j++) {
1020  ND_PRINT("\n\t pruned source #%u: ", j+1);
1021  if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_source, pimv2_addr_len, 0)) < 0)
1022  goto trunc;
1023  bp += advance; len -= advance;
1024  }
1025  }
1026  break;
1027  }
1028 
1029  case PIMV2_TYPE_BOOTSTRAP:
1030  {
1031  u_int i, j, frpcnt;
1032 
1033  /* Fragment Tag, Hash Mask len, and BSR-priority */
1034  if (len < 2)
1035  goto trunc;
1036  ND_PRINT(" tag=%x", GET_BE_U_2(bp));
1037  bp += 2;
1038  len -= 2;
1039  if (len < 1)
1040  goto trunc;
1041  ND_PRINT(" hashmlen=%u", GET_U_1(bp));
1042  if (len < 2)
1043  goto trunc;
1044  ND_TCHECK_1(bp + 2);
1045  ND_PRINT(" BSRprio=%u", GET_U_1(bp + 1));
1046  bp += 2;
1047  len -= 2;
1048 
1049  /* Encoded-Unicast-BSR-Address */
1050  ND_PRINT(" BSR=");
1051  if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0)
1052  goto trunc;
1053  bp += advance;
1054  len -= advance;
1055 
1056  for (i = 0; len > 0; i++) {
1057  /* Encoded-Group Address */
1058  ND_PRINT(" (group%u: ", i);
1059  if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0)
1060  goto trunc;
1061  bp += advance;
1062  len -= advance;
1063 
1064  /* RP-Count, Frag RP-Cnt, and rsvd */
1065  if (len < 1)
1066  goto trunc;
1067  ND_PRINT(" RPcnt=%u", GET_U_1(bp));
1068  if (len < 2)
1069  goto trunc;
1070  frpcnt = GET_U_1(bp + 1);
1071  ND_PRINT(" FRPcnt=%u", frpcnt);
1072  if (len < 4)
1073  goto trunc;
1074  bp += 4;
1075  len -= 4;
1076 
1077  for (j = 0; j < frpcnt && len > 0; j++) {
1078  /* each RP info */
1079  ND_PRINT(" RP%u=", j);
1080  if ((advance = pimv2_addr_print(ndo, bp, len,
1081  pimv2_unicast,
1082  pimv2_addr_len,
1083  0)) < 0)
1084  goto trunc;
1085  bp += advance;
1086  len -= advance;
1087 
1088  if (len < 2)
1089  goto trunc;
1090  ND_PRINT(",holdtime=");
1092  GET_BE_U_2(bp));
1093  if (len < 3)
1094  goto trunc;
1095  ND_PRINT(",prio=%u", GET_U_1(bp + 2));
1096  if (len < 4)
1097  goto trunc;
1098  bp += 4;
1099  len -= 4;
1100  }
1101  ND_PRINT(")");
1102  }
1103  break;
1104  }
1105  case PIMV2_TYPE_ASSERT:
1106  ND_PRINT(" group=");
1107  if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0)
1108  goto trunc;
1109  bp += advance; len -= advance;
1110  ND_PRINT(" src=");
1111  if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0)
1112  goto trunc;
1113  bp += advance; len -= advance;
1114  if (len < 8)
1115  goto trunc;
1116  ND_TCHECK_8(bp);
1117  if (GET_U_1(bp) & 0x80)
1118  ND_PRINT(" RPT");
1119  ND_PRINT(" pref=%u", GET_BE_U_4(bp) & 0x7fffffff);
1120  ND_PRINT(" metric=%u", GET_BE_U_4(bp + 4));
1121  break;
1122 
1124  {
1125  u_int i, pfxcnt;
1126 
1127  /* Prefix-Cnt, Priority, and Holdtime */
1128  if (len < 1)
1129  goto trunc;
1130  ND_PRINT(" prefix-cnt=%u", GET_U_1(bp));
1131  pfxcnt = GET_U_1(bp);
1132  if (len < 2)
1133  goto trunc;
1134  ND_PRINT(" prio=%u", GET_U_1(bp + 1));
1135  if (len < 4)
1136  goto trunc;
1137  ND_PRINT(" holdtime=");
1138  unsigned_relts_print(ndo, GET_BE_U_2(bp + 2));
1139  bp += 4;
1140  len -= 4;
1141 
1142  /* Encoded-Unicast-RP-Address */
1143  ND_PRINT(" RP=");
1144  if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0)
1145  goto trunc;
1146  bp += advance;
1147  len -= advance;
1148 
1149  /* Encoded-Group Addresses */
1150  for (i = 0; i < pfxcnt && len > 0; i++) {
1151  ND_PRINT(" Group%u=", i);
1152  if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0)
1153  goto trunc;
1154  bp += advance;
1155  len -= advance;
1156  }
1157  break;
1158  }
1159 
1161  ND_PRINT(" src=");
1162  if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0)
1163  goto trunc;
1164  bp += advance;
1165  len -= advance;
1166  ND_PRINT(" grp=");
1167  if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0)
1168  goto trunc;
1169  bp += advance;
1170  len -= advance;
1171  ND_PRINT(" forwarder=");
1172  if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0)
1173  goto trunc;
1174  bp += advance;
1175  len -= advance;
1176  if (len < 2)
1177  goto trunc;
1178  ND_PRINT(" TUNR ");
1179  unsigned_relts_print(ndo, GET_BE_U_2(bp));
1180  break;
1181 
1183  subtype = PIM_SUBTYPE(GET_U_1(pim->pim_rsv));
1185  "Unknown", subtype) );
1186 
1187  ND_PRINT(" rpa=");
1188  if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0) {
1189  goto trunc;
1190  }
1191  bp += advance;
1192  len -= advance;
1193  ND_PRINT(" sender pref=%u", GET_BE_U_4(bp) );
1194  ND_PRINT(" sender metric=%u", GET_BE_U_4(bp + 4));
1195 
1196  bp += 8;
1197  len -= 8;
1198 
1199  switch (subtype) {
1202  ND_PRINT("\n\t %s addr=", PIMV2_DF_ELECTION_PASS_BACKOFF_STR(subtype));
1203  if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0) {
1204  goto trunc;
1205  }
1206  bp += advance;
1207  len -= advance;
1208 
1209  ND_PRINT(" %s pref=%u", PIMV2_DF_ELECTION_PASS_BACKOFF_STR(subtype), GET_BE_U_4(bp) );
1210  ND_PRINT(" %s metric=%u", PIMV2_DF_ELECTION_PASS_BACKOFF_STR(subtype), GET_BE_U_4(bp + 4));
1211 
1212  bp += 8;
1213  len -= 8;
1214 
1215  if (subtype == PIMV2_DF_ELECTION_BACKOFF) {
1216  ND_PRINT(" interval %dms", GET_BE_U_2(bp));
1217  }
1218 
1219  break;
1220  default:
1221  break;
1222  }
1223  break;
1224 
1225  default:
1226  ND_PRINT(" [type %u]", PIM_TYPE(pim_typever));
1227  break;
1228  }
1229 
1230  return;
1231 
1232 trunc:
1233  nd_print_trunc(ndo);
1234 }
#define GET_IPADDR_STRING(p)
Definition: addrtoname.h:120
#define GET_IP6ADDR_STRING(p)
Definition: addrtoname.h:121
#define GET_BE_U_4(p)
Definition: extract.h:877
#define GET_BE_U_2(p)
Definition: extract.h:875
#define ND_TCHECK_8(p)
Definition: extract.h:573
#define GET_U_1(p)
Definition: extract.h:872
#define ND_TCHECK_4(p)
Definition: extract.h:561
#define ND_TTEST_1(p)
Definition: extract.h:551
#define ND_TCHECK_1(p)
Definition: extract.h:552
uint16_t in_cksum(const struct cksum_vec *vec, int veclen)
Definition: in_cksum.c:57
#define IP_V(ip)
Definition: ip.h:54
#define IPPROTO_PIM
Definition: ipproto.h:126
#define AF_INET6
unsigned char nd_uint16_t[2]
Definition: netdissect.h:47
void unsigned_relts_print(netdissect_options *, uint32_t)
Definition: util-print.c:350
void ip6_print(netdissect_options *, const u_char *, u_int)
Definition: print-ip6.c:226
uint16_t nextproto6_cksum(netdissect_options *, const struct ip6_hdr *, const uint8_t *, u_int, u_int, uint8_t)
Definition: print-ip6.c:173
int print_unknown_data(netdissect_options *, const u_char *, const char *, u_int)
Definition: util-print.c:441
#define ND_TCHECK_LEN(p, l)
Definition: netdissect.h:368
const char * tok2str(const struct tok *, const char *, u_int)
Definition: util-print.c:485
#define ND_TTEST_LEN(p, l)
Definition: netdissect.h:356
void nd_print_invalid(netdissect_options *)
Definition: util-print.c:429
void nd_print_trunc(netdissect_options *)
Definition: util-print.c:409
void ip_print(netdissect_options *, const u_char *, u_int)
Definition: print-ip.c:319
unsigned char nd_ipv4[4]
Definition: netdissect.h:92
#define ND_PRINT(...)
Definition: netdissect.h:385
unsigned char nd_uint8_t[1]
Definition: netdissect.h:46
unsigned char nd_ipv6[16]
Definition: netdissect.h:97
#define PIMV2_TYPE_PRUNE_REFRESH
Definition: print-pim.c:68
static const struct tok pimv2_register_flag_values[]
Definition: print-pim.c:115
#define PIMV2_HELLO_OPTION_REFRESH_CAP
Definition: print-pim.c:93
#define PIMV2_REGISTER_FLAG_LEN
Definition: print-pim.c:111
#define PIMV2_TYPE_GRAFT_ACK
Definition: print-pim.c:66
#define PIMV2_DF_ELECTION_WINNER
Definition: print-pim.c:122
#define PIMV2_TYPE_GRAFT
Definition: print-pim.c:65
#define PIMV1_TYPE_REGISTER_STOP
Definition: print-pim.c:40
#define PIM_TYPE(x)
Definition: print-pim.c:152
#define PIMV2_HELLO_OPTION_GENID
Definition: print-pim.c:92
#define PIM_VER(x)
Definition: print-pim.c:151
void cisco_autorp_print(netdissect_options *ndo, const u_char *bp, u_int len)
Definition: print-pim.c:349
#define PIMV2_HELLO_OPTION_ADDRESS_LIST
Definition: print-pim.c:95
#define PIMV1_TYPE_QUERY
Definition: print-pim.c:38
#define PIMV1_TYPE_RP_REACHABILITY
Definition: print-pim.c:42
pimv2_addrtype
Definition: print-pim.c:527
@ pimv2_group
Definition: print-pim.c:528
@ pimv2_source
Definition: print-pim.c:528
@ pimv2_unicast
Definition: print-pim.c:528
#define PIMV2_REGISTER_FLAG_NULL
Definition: print-pim.c:113
#define PIMV2_DF_ELECTION_BACKOFF
Definition: print-pim.c:123
static const struct tok pimv1_type_str[]
Definition: print-pim.c:47
#define PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD
Definition: print-pim.c:96
#define PIMV2_TYPE_JOIN_PRUNE
Definition: print-pim.c:62
void pim_print(netdissect_options *ndo, const u_char *bp, u_int len, const u_char *bp2)
Definition: print-pim.c:454
static void pimv2_print(netdissect_options *, const u_char *bp, u_int len, const u_char *)
Definition: print-pim.c:687
#define PIMV2_TYPE_ASSERT
Definition: print-pim.c:64
#define PIMV2_TYPE_CANDIDATE_RP
Definition: print-pim.c:67
#define PIMV2_TYPE_ECMP_REDIRECT
Definition: print-pim.c:70
static const struct tok pimv2_type_values[]
Definition: print-pim.c:72
#define PIMV2_REGISTER_FLAG_BORDER
Definition: print-pim.c:112
#define PIMV2_DF_ELECTION_PASS_BACKOFF_STR(x)
Definition: print-pim.c:134
#define PIMV2_TYPE_REGISTER
Definition: print-pim.c:60
#define PIMV2_HELLO_OPTION_DR_PRIORITY
Definition: print-pim.c:91
#define PIMV2_HELLO_OPTION_DR_PRIORITY_OLD
Definition: print-pim.c:90
static int pimv2_addr_print(netdissect_options *ndo, const u_char *bp, u_int len, enum pimv2_addrtype at, u_int addr_len, int silent)
Definition: print-pim.c:552
#define PIMV2_HELLO_OPTION_HOLDTIME
Definition: print-pim.c:88
#define PIMV2_DF_ELECTION_OFFER
Definition: print-pim.c:121
#define PIMV2_DF_ELECTION_PASS
Definition: print-pim.c:124
checksum_status
Definition: print-pim.c:650
@ INCORRECT
Definition: print-pim.c:652
@ UNVERIFIED
Definition: print-pim.c:653
@ CORRECT
Definition: print-pim.c:651
static enum checksum_status pimv2_check_checksum(netdissect_options *ndo, const u_char *bp, const u_char *bp2, u_int len)
Definition: print-pim.c:657
static void pimv1_join_prune_print(netdissect_options *ndo, const u_char *bp, u_int len)
Definition: print-pim.c:161
void pimv1_print(netdissect_options *ndo, const u_char *bp, u_int len)
Definition: print-pim.c:262
#define PIMV1_TYPE_REGISTER
Definition: print-pim.c:39
#define PIMV1_TYPE_GRAFT
Definition: print-pim.c:44
#define PIMV1_TYPE_ASSERT
Definition: print-pim.c:43
static const struct tok pimv2_hello_option_values[]
Definition: print-pim.c:98
#define PIMV1_TYPE_JOIN_PRUNE
Definition: print-pim.c:41
#define PIMV2_HELLO_OPTION_LANPRUNEDELAY
Definition: print-pim.c:89
#define PIMV2_HELLO_OPTION_BIDIR_CAP
Definition: print-pim.c:94
static const struct tok pimv2_df_election_flag_values[]
Definition: print-pim.c:126
#define PIMV2_TYPE_REGISTER_STOP
Definition: print-pim.c:61
#define PIMV2_TYPE_BOOTSTRAP
Definition: print-pim.c:63
#define PIMV2_TYPE_DF_ELECTION
Definition: print-pim.c:69
#define PIMV1_TYPE_GRAFT_ACK
Definition: print-pim.c:45
#define PIM_SUBTYPE(x)
Definition: print-pim.c:154
#define PIMV2_TYPE_HELLO
Definition: print-pim.c:59
const uint8_t * ptr
Definition: netdissect.h:722
Definition: ip6.h:76
Definition: ip.h:52
nd_ipv4 ip_dst
Definition: ip.h:66
nd_ipv4 ip_src
Definition: ip.h:66
const char * ndo_protocol
Definition: netdissect.h:218
Definition: print-pim.c:143
nd_uint16_t pim_cksum
Definition: print-pim.c:155
nd_uint8_t pim_typever
Definition: print-pim.c:144
nd_uint8_t pim_rsv
Definition: print-pim.c:153