Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / tcpdump / print-pim.c
blob0354f24920371ae85a6bfe41e4ae0bd3d126a8bf
1 /* $NetBSD$ */
3 /*
4 * Copyright (c) 1995, 1996
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that: (1) source code distributions
9 * retain the above copyright notice and this paragraph in its entirety, (2)
10 * distributions including binary code include the above copyright notice and
11 * this paragraph in its entirety in the documentation or other materials
12 * provided with the distribution, and (3) all advertising materials mentioning
13 * features or use of this software display the following acknowledgement:
14 * ``This product includes software developed by the University of California,
15 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
16 * the University nor the names of its contributors may be used to endorse
17 * or promote products derived from this software without specific prior
18 * written permission.
19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
24 #include <sys/cdefs.h>
25 #ifndef lint
26 #if 0
27 static const char rcsid[] _U_ =
28 "@(#) Header: /tcpdump/master/tcpdump/print-pim.c,v 1.45.2.4 2006/02/13 01:32:34 hannes Exp (LBL)";
29 #else
30 __RCSID("$NetBSD: tcpdump2rcsid.ex,v 1.1 2001/06/25 20:09:58 itojun Exp $");
31 #endif
32 #endif
34 #ifdef HAVE_CONFIG_H
35 #include "config.h"
36 #endif
38 #include <tcpdump-stdinc.h>
39 #include "interface.h"
41 #define PIMV2_TYPE_HELLO 0
42 #define PIMV2_TYPE_REGISTER 1
43 #define PIMV2_TYPE_REGISTER_STOP 2
44 #define PIMV2_TYPE_JOIN_PRUNE 3
45 #define PIMV2_TYPE_BOOTSTRAP 4
46 #define PIMV2_TYPE_ASSERT 5
47 #define PIMV2_TYPE_GRAFT 6
48 #define PIMV2_TYPE_GRAFT_ACK 7
49 #define PIMV2_TYPE_CANDIDATE_RP 8
50 #define PIMV2_TYPE_PRUNE_REFRESH 9
52 static struct tok pimv2_type_values[] = {
53 { PIMV2_TYPE_HELLO, "Hello" },
54 { PIMV2_TYPE_REGISTER, "Register" },
55 { PIMV2_TYPE_REGISTER_STOP, "Register Stop" },
56 { PIMV2_TYPE_JOIN_PRUNE, "Join / Prune" },
57 { PIMV2_TYPE_BOOTSTRAP, "Bootstrap" },
58 { PIMV2_TYPE_ASSERT, "Assert" },
59 { PIMV2_TYPE_GRAFT, "Graft" },
60 { PIMV2_TYPE_GRAFT_ACK, "Graft Acknowledgement" },
61 { PIMV2_TYPE_CANDIDATE_RP, "Candidate RP Advertisement" },
62 { PIMV2_TYPE_PRUNE_REFRESH, "Prune Refresh" },
63 { 0, NULL}
66 #define PIMV2_HELLO_OPTION_HOLDTIME 1
67 #define PIMV2_HELLO_OPTION_LANPRUNEDELAY 2
68 #define PIMV2_HELLO_OPTION_DR_PRIORITY_OLD 18
69 #define PIMV2_HELLO_OPTION_DR_PRIORITY 19
70 #define PIMV2_HELLO_OPTION_GENID 20
71 #define PIMV2_HELLO_OPTION_REFRESH_CAP 21
72 #define PIMV2_HELLO_OPTION_BIDIR_CAP 22
73 #define PIMV2_HELLO_OPTION_ADDRESS_LIST 24
74 #define PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD 65001
76 static struct tok pimv2_hello_option_values[] = {
77 { PIMV2_HELLO_OPTION_HOLDTIME, "Hold Time" },
78 { PIMV2_HELLO_OPTION_LANPRUNEDELAY, "LAN Prune Delay" },
79 { PIMV2_HELLO_OPTION_DR_PRIORITY_OLD, "DR Priority (Old)" },
80 { PIMV2_HELLO_OPTION_DR_PRIORITY, "DR Priority" },
81 { PIMV2_HELLO_OPTION_GENID, "Generation ID" },
82 { PIMV2_HELLO_OPTION_REFRESH_CAP, "State Refresh Capability" },
83 { PIMV2_HELLO_OPTION_BIDIR_CAP, "Bi-Directional Capability" },
84 { PIMV2_HELLO_OPTION_ADDRESS_LIST, "Address List" },
85 { PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD, "Address List (Old)" },
86 { 0, NULL}
89 #define PIMV2_REGISTER_FLAG_LEN 4
90 #define PIMV2_REGISTER_FLAG_BORDER 0x80000000
91 #define PIMV2_REGISTER_FLAG_NULL 0x40000000
93 static struct tok pimv2_register_flag_values[] = {
94 { PIMV2_REGISTER_FLAG_BORDER, "Border" },
95 { PIMV2_REGISTER_FLAG_NULL, "Null" },
96 { 0, NULL}
97 };
100 * XXX: We consider a case where IPv6 is not ready yet for portability,
101 * but PIM dependent defintions should be independent of IPv6...
104 struct pim {
105 u_int8_t pim_typever;
106 /* upper 4bit: PIM version number; 2 for PIMv2 */
107 /* lower 4bit: the PIM message type, currently they are:
108 * Hello, Register, Register-Stop, Join/Prune,
109 * Bootstrap, Assert, Graft (PIM-DM only),
110 * Graft-Ack (PIM-DM only), C-RP-Adv
112 #define PIM_VER(x) (((x) & 0xf0) >> 4)
113 #define PIM_TYPE(x) ((x) & 0x0f)
114 u_char pim_rsv; /* Reserved */
115 u_short pim_cksum; /* IP style check sum */
119 #include <stdio.h>
120 #include <stdlib.h>
122 #include "interface.h"
123 #include "addrtoname.h"
124 #include "extract.h"
126 #include "ip.h"
128 static void pimv2_print(register const u_char *bp, register u_int len);
130 static void
131 pimv1_join_prune_print(register const u_char *bp, register u_int len)
133 int maddrlen, addrlen, ngroups, njoin, nprune;
134 int njp;
136 /* If it's a single group and a single source, use 1-line output. */
137 if (TTEST2(bp[0], 30) && bp[11] == 1 &&
138 ((njoin = EXTRACT_16BITS(&bp[20])) + EXTRACT_16BITS(&bp[22])) == 1) {
139 int hold;
141 (void)printf(" RPF %s ", ipaddr_string(bp));
142 hold = EXTRACT_16BITS(&bp[6]);
143 if (hold != 180) {
144 (void)printf("Hold ");
145 relts_print(hold);
147 (void)printf("%s (%s/%d, %s", njoin ? "Join" : "Prune",
148 ipaddr_string(&bp[26]), bp[25] & 0x3f,
149 ipaddr_string(&bp[12]));
150 if (EXTRACT_32BITS(&bp[16]) != 0xffffffff)
151 (void)printf("/%s", ipaddr_string(&bp[16]));
152 (void)printf(") %s%s %s",
153 (bp[24] & 0x01) ? "Sparse" : "Dense",
154 (bp[25] & 0x80) ? " WC" : "",
155 (bp[25] & 0x40) ? "RP" : "SPT");
156 return;
159 TCHECK2(bp[0], sizeof(struct in_addr));
160 if (vflag > 1)
161 (void)printf("\n");
162 (void)printf(" Upstream Nbr: %s", ipaddr_string(bp));
163 TCHECK2(bp[6], 2);
164 if (vflag > 1)
165 (void)printf("\n");
166 (void)printf(" Hold time: ");
167 relts_print(EXTRACT_16BITS(&bp[6]));
168 if (vflag < 2)
169 return;
170 bp += 8;
171 len -= 8;
173 TCHECK2(bp[0], 4);
174 maddrlen = bp[1];
175 addrlen = bp[2];
176 ngroups = bp[3];
177 bp += 4;
178 len -= 4;
179 while (ngroups--) {
181 * XXX - does the address have length "addrlen" and the
182 * mask length "maddrlen"?
184 TCHECK2(bp[0], sizeof(struct in_addr));
185 (void)printf("\n\tGroup: %s", ipaddr_string(bp));
186 TCHECK2(bp[4], sizeof(struct in_addr));
187 if (EXTRACT_32BITS(&bp[4]) != 0xffffffff)
188 (void)printf("/%s", ipaddr_string(&bp[4]));
189 TCHECK2(bp[8], 4);
190 njoin = EXTRACT_16BITS(&bp[8]);
191 nprune = EXTRACT_16BITS(&bp[10]);
192 (void)printf(" joined: %d pruned: %d", njoin, nprune);
193 bp += 12;
194 len -= 12;
195 for (njp = 0; njp < (njoin + nprune); njp++) {
196 const char *type;
198 if (njp < njoin)
199 type = "Join ";
200 else
201 type = "Prune";
202 TCHECK2(bp[0], 6);
203 (void)printf("\n\t%s %s%s%s%s/%d", type,
204 (bp[0] & 0x01) ? "Sparse " : "Dense ",
205 (bp[1] & 0x80) ? "WC " : "",
206 (bp[1] & 0x40) ? "RP " : "SPT ",
207 ipaddr_string(&bp[2]), bp[1] & 0x3f);
208 bp += 6;
209 len -= 6;
212 return;
213 trunc:
214 (void)printf("[|pim]");
215 return;
218 void
219 pimv1_print(register const u_char *bp, register u_int len)
221 register const u_char *ep;
222 register u_char type;
224 ep = (const u_char *)snapend;
225 if (bp >= ep)
226 return;
228 TCHECK(bp[1]);
229 type = bp[1];
231 switch (type) {
232 case 0:
233 (void)printf(" Query");
234 if (TTEST(bp[8])) {
235 switch (bp[8] >> 4) {
236 case 0:
237 (void)printf(" Dense-mode");
238 break;
239 case 1:
240 (void)printf(" Sparse-mode");
241 break;
242 case 2:
243 (void)printf(" Sparse-Dense-mode");
244 break;
245 default:
246 (void)printf(" mode-%d", bp[8] >> 4);
247 break;
250 if (vflag) {
251 TCHECK2(bp[10],2);
252 (void)printf(" (Hold-time ");
253 relts_print(EXTRACT_16BITS(&bp[10]));
254 (void)printf(")");
256 break;
258 case 1:
259 (void)printf(" Register");
260 TCHECK2(bp[8], 20); /* ip header */
261 (void)printf(" for %s > %s", ipaddr_string(&bp[20]),
262 ipaddr_string(&bp[24]));
263 break;
264 case 2:
265 (void)printf(" Register-Stop");
266 TCHECK2(bp[12], sizeof(struct in_addr));
267 (void)printf(" for %s > %s", ipaddr_string(&bp[8]),
268 ipaddr_string(&bp[12]));
269 break;
270 case 3:
271 (void)printf(" Join/Prune");
272 if (vflag)
273 pimv1_join_prune_print(&bp[8], len - 8);
274 break;
275 case 4:
276 (void)printf(" RP-reachable");
277 if (vflag) {
278 TCHECK2(bp[22], 2);
279 (void)printf(" group %s",
280 ipaddr_string(&bp[8]));
281 if (EXTRACT_32BITS(&bp[12]) != 0xffffffff)
282 (void)printf("/%s", ipaddr_string(&bp[12]));
283 (void)printf(" RP %s hold ", ipaddr_string(&bp[16]));
284 relts_print(EXTRACT_16BITS(&bp[22]));
286 break;
287 case 5:
288 (void)printf(" Assert");
289 TCHECK2(bp[16], sizeof(struct in_addr));
290 (void)printf(" for %s > %s", ipaddr_string(&bp[16]),
291 ipaddr_string(&bp[8]));
292 if (EXTRACT_32BITS(&bp[12]) != 0xffffffff)
293 (void)printf("/%s", ipaddr_string(&bp[12]));
294 TCHECK2(bp[24], 4);
295 (void)printf(" %s pref %d metric %d",
296 (bp[20] & 0x80) ? "RP-tree" : "SPT",
297 EXTRACT_32BITS(&bp[20]) & 0x7fffffff,
298 EXTRACT_32BITS(&bp[24]));
299 break;
300 case 6:
301 (void)printf(" Graft");
302 if (vflag)
303 pimv1_join_prune_print(&bp[8], len - 8);
304 break;
305 case 7:
306 (void)printf(" Graft-ACK");
307 if (vflag)
308 pimv1_join_prune_print(&bp[8], len - 8);
309 break;
310 case 8:
311 (void)printf(" Mode");
312 break;
313 default:
314 (void)printf(" [type %d]", type);
315 break;
317 if ((bp[4] >> 4) != 1)
318 (void)printf(" [v%d]", bp[4] >> 4);
319 return;
321 trunc:
322 (void)printf("[|pim]");
323 return;
327 * auto-RP is a cisco protocol, documented at
328 * ftp://ftpeng.cisco.com/ipmulticast/specs/pim-autorp-spec01.txt
330 * This implements version 1+, dated Sept 9, 1998.
332 void
333 cisco_autorp_print(register const u_char *bp, register u_int len)
335 int type;
336 int numrps;
337 int hold;
339 TCHECK(bp[0]);
340 (void)printf(" auto-rp ");
341 type = bp[0];
342 switch (type) {
343 case 0x11:
344 (void)printf("candidate-advert");
345 break;
346 case 0x12:
347 (void)printf("mapping");
348 break;
349 default:
350 (void)printf("type-0x%02x", type);
351 break;
354 TCHECK(bp[1]);
355 numrps = bp[1];
357 TCHECK2(bp[2], 2);
358 (void)printf(" Hold ");
359 hold = EXTRACT_16BITS(&bp[2]);
360 if (hold)
361 relts_print(EXTRACT_16BITS(&bp[2]));
362 else
363 printf("FOREVER");
365 /* Next 4 bytes are reserved. */
367 bp += 8; len -= 8;
369 /*XXX skip unless -v? */
372 * Rest of packet:
373 * numrps entries of the form:
374 * 32 bits: RP
375 * 6 bits: reserved
376 * 2 bits: PIM version supported, bit 0 is "supports v1", 1 is "v2".
377 * 8 bits: # of entries for this RP
378 * each entry: 7 bits: reserved, 1 bit: negative,
379 * 8 bits: mask 32 bits: source
380 * lather, rinse, repeat.
382 while (numrps--) {
383 int nentries;
384 char s;
386 TCHECK2(bp[0], 4);
387 (void)printf(" RP %s", ipaddr_string(bp));
388 TCHECK(bp[4]);
389 switch (bp[4] & 0x3) {
390 case 0: printf(" PIMv?");
391 break;
392 case 1: printf(" PIMv1");
393 break;
394 case 2: printf(" PIMv2");
395 break;
396 case 3: printf(" PIMv1+2");
397 break;
399 if (bp[4] & 0xfc)
400 (void)printf(" [rsvd=0x%02x]", bp[4] & 0xfc);
401 TCHECK(bp[5]);
402 nentries = bp[5];
403 bp += 6; len -= 6;
404 s = ' ';
405 for (; nentries; nentries--) {
406 TCHECK2(bp[0], 6);
407 (void)printf("%c%s%s/%d", s, bp[0] & 1 ? "!" : "",
408 ipaddr_string(&bp[2]), bp[1]);
409 if (bp[0] & 0xfe)
410 (void)printf("[rsvd=0x%02x]", bp[0] & 0xfe);
411 s = ',';
412 bp += 6; len -= 6;
415 return;
417 trunc:
418 (void)printf("[|autorp]");
419 return;
422 void
423 pim_print(register const u_char *bp, register u_int len)
425 register const u_char *ep;
426 register struct pim *pim = (struct pim *)bp;
428 ep = (const u_char *)snapend;
429 if (bp >= ep)
430 return;
431 #ifdef notyet /* currently we see only version and type */
432 TCHECK(pim->pim_rsv);
433 #endif
435 switch (PIM_VER(pim->pim_typever)) {
436 case 2:
437 if (!vflag) {
438 printf("PIMv%u, %s, length %u",
439 PIM_VER(pim->pim_typever),
440 tok2str(pimv2_type_values,"Unknown Type",PIM_TYPE(pim->pim_typever)),
441 len);
442 return;
443 } else {
444 printf("PIMv%u, length %u\n\t%s",
445 PIM_VER(pim->pim_typever),
446 len,
447 tok2str(pimv2_type_values,"Unknown Type",PIM_TYPE(pim->pim_typever)));
448 pimv2_print(bp, len);
450 break;
451 default:
452 printf("PIMv%u, length %u",
453 PIM_VER(pim->pim_typever),
454 len);
455 break;
457 return;
461 * PIMv2 uses encoded address representations.
463 * The last PIM-SM I-D before RFC2117 was published specified the
464 * following representation for unicast addresses. However, RFC2117
465 * specified no encoding for unicast addresses with the unicast
466 * address length specified in the header. Therefore, we have to
467 * guess which encoding is being used (Cisco's PIMv2 implementation
468 * uses the non-RFC encoding). RFC2117 turns a previously "Reserved"
469 * field into a 'unicast-address-length-in-bytes' field. We guess
470 * that it's the draft encoding if this reserved field is zero.
472 * RFC2362 goes back to the encoded format, and calls the addr length
473 * field "reserved" again.
475 * The first byte is the address family, from:
477 * 0 Reserved
478 * 1 IP (IP version 4)
479 * 2 IP6 (IP version 6)
480 * 3 NSAP
481 * 4 HDLC (8-bit multidrop)
482 * 5 BBN 1822
483 * 6 802 (includes all 802 media plus Ethernet "canonical format")
484 * 7 E.163
485 * 8 E.164 (SMDS, Frame Relay, ATM)
486 * 9 F.69 (Telex)
487 * 10 X.121 (X.25, Frame Relay)
488 * 11 IPX
489 * 12 Appletalk
490 * 13 Decnet IV
491 * 14 Banyan Vines
492 * 15 E.164 with NSAP format subaddress
494 * In addition, the second byte is an "Encoding". 0 is the default
495 * encoding for the address family, and no other encodings are currently
496 * specified.
500 static int pimv2_addr_len;
502 enum pimv2_addrtype {
503 pimv2_unicast, pimv2_group, pimv2_source
506 /* 0 1 2 3
507 * 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
508 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
509 * | Addr Family | Encoding Type | Unicast Address |
510 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+++++++
511 * 0 1 2 3
512 * 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
513 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
514 * | Addr Family | Encoding Type | Reserved | Mask Len |
515 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
516 * | Group multicast Address |
517 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
518 * 0 1 2 3
519 * 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
520 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
521 * | Addr Family | Encoding Type | Rsrvd |S|W|R| Mask Len |
522 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
523 * | Source Address |
524 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
526 static int
527 pimv2_addr_print(const u_char *bp, enum pimv2_addrtype at, int silent)
529 int af;
530 int len, hdrlen;
532 TCHECK(bp[0]);
534 if (pimv2_addr_len == 0) {
535 TCHECK(bp[1]);
536 switch (bp[0]) {
537 case 1:
538 af = AF_INET;
539 len = sizeof(struct in_addr);
540 break;
541 #ifdef INET6
542 case 2:
543 af = AF_INET6;
544 len = sizeof(struct in6_addr);
545 break;
546 #endif
547 default:
548 return -1;
550 if (bp[1] != 0)
551 return -1;
552 hdrlen = 2;
553 } else {
554 switch (pimv2_addr_len) {
555 case sizeof(struct in_addr):
556 af = AF_INET;
557 break;
558 #ifdef INET6
559 case sizeof(struct in6_addr):
560 af = AF_INET6;
561 break;
562 #endif
563 default:
564 return -1;
565 break;
567 len = pimv2_addr_len;
568 hdrlen = 0;
571 bp += hdrlen;
572 switch (at) {
573 case pimv2_unicast:
574 TCHECK2(bp[0], len);
575 if (af == AF_INET) {
576 if (!silent)
577 (void)printf("%s", ipaddr_string(bp));
579 #ifdef INET6
580 else if (af == AF_INET6) {
581 if (!silent)
582 (void)printf("%s", ip6addr_string(bp));
584 #endif
585 return hdrlen + len;
586 case pimv2_group:
587 case pimv2_source:
588 TCHECK2(bp[0], len + 2);
589 if (af == AF_INET) {
590 if (!silent) {
591 (void)printf("%s", ipaddr_string(bp + 2));
592 if (bp[1] != 32)
593 (void)printf("/%u", bp[1]);
596 #ifdef INET6
597 else if (af == AF_INET6) {
598 if (!silent) {
599 (void)printf("%s", ip6addr_string(bp + 2));
600 if (bp[1] != 128)
601 (void)printf("/%u", bp[1]);
604 #endif
605 if (bp[0] && !silent) {
606 if (at == pimv2_group) {
607 (void)printf("(0x%02x)", bp[0]);
608 } else {
609 (void)printf("(%s%s%s",
610 bp[0] & 0x04 ? "S" : "",
611 bp[0] & 0x02 ? "W" : "",
612 bp[0] & 0x01 ? "R" : "");
613 if (bp[0] & 0xf8) {
614 (void) printf("+0x%02x", bp[0] & 0xf8);
616 (void)printf(")");
619 return hdrlen + 2 + len;
620 default:
621 return -1;
623 trunc:
624 return -1;
627 static void
628 pimv2_print(register const u_char *bp, register u_int len)
630 register const u_char *ep;
631 register struct pim *pim = (struct pim *)bp;
632 int advance;
634 ep = (const u_char *)snapend;
635 if (bp >= ep)
636 return;
637 if (ep > bp + len)
638 ep = bp + len;
639 TCHECK(pim->pim_rsv);
640 pimv2_addr_len = pim->pim_rsv;
641 if (pimv2_addr_len != 0)
642 (void)printf(", RFC2117-encoding");
644 printf(", cksum 0x%04x ", EXTRACT_16BITS(&pim->pim_cksum));
645 if (EXTRACT_16BITS(&pim->pim_cksum) == 0) {
646 printf("(unverified)");
647 } else {
648 printf("(%scorrect)",
649 TTEST2(bp[0], len) &&
650 in_cksum((const u_short*)bp, len, 0) ? "in" : "" );
653 switch (PIM_TYPE(pim->pim_typever)) {
654 case PIMV2_TYPE_HELLO:
656 u_int16_t otype, olen;
657 bp += 4;
658 while (bp < ep) {
659 TCHECK2(bp[0], 4);
660 otype = EXTRACT_16BITS(&bp[0]);
661 olen = EXTRACT_16BITS(&bp[2]);
662 TCHECK2(bp[0], 4 + olen);
664 printf("\n\t %s Option (%u), length %u, Value: ",
665 tok2str( pimv2_hello_option_values,"Unknown",otype),
666 otype,
667 olen);
668 bp += 4;
670 switch (otype) {
671 case PIMV2_HELLO_OPTION_HOLDTIME:
672 relts_print(EXTRACT_16BITS(bp));
673 break;
675 case PIMV2_HELLO_OPTION_LANPRUNEDELAY:
676 if (olen != 4) {
677 (void)printf("ERROR: Option Lenght != 4 Bytes (%u)", olen);
678 } else {
679 char t_bit;
680 u_int16_t lan_delay, override_interval;
681 lan_delay = EXTRACT_16BITS(bp);
682 override_interval = EXTRACT_16BITS(bp+2);
683 t_bit = (lan_delay & 0x8000)? 1 : 0;
684 lan_delay &= ~0x8000;
685 (void)printf("\n\t T-bit=%d, LAN delay %dms, Override interval %dms",
686 t_bit, lan_delay, override_interval);
688 break;
690 case PIMV2_HELLO_OPTION_DR_PRIORITY_OLD:
691 case PIMV2_HELLO_OPTION_DR_PRIORITY:
692 switch (olen) {
693 case 0:
694 printf("Bi-Directional Capability (Old)");
695 break;
696 case 4:
697 printf("%u", EXTRACT_32BITS(bp));
698 break;
699 default:
700 printf("ERROR: Option Lenght != 4 Bytes (%u)", olen);
701 break;
703 break;
705 case PIMV2_HELLO_OPTION_GENID:
706 (void)printf("0x%08x", EXTRACT_32BITS(bp));
707 break;
709 case PIMV2_HELLO_OPTION_REFRESH_CAP:
710 (void)printf("v%d", *bp);
711 if (*(bp+1) != 0) {
712 (void)printf(", interval ");
713 relts_print(*(bp+1));
715 if (EXTRACT_16BITS(bp+2) != 0) {
716 (void)printf(" ?0x%04x?", EXTRACT_16BITS(bp+2));
718 break;
720 case PIMV2_HELLO_OPTION_BIDIR_CAP:
721 break;
723 case PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD:
724 case PIMV2_HELLO_OPTION_ADDRESS_LIST:
725 if (vflag > 1) {
726 const u_char *ptr = bp;
727 while (ptr < (bp+olen)) {
728 int advance;
730 printf("\n\t ");
731 advance = pimv2_addr_print(ptr, pimv2_unicast, 0);
732 if (advance < 0) {
733 printf("...");
734 break;
736 ptr += advance;
739 break;
740 default:
741 if (vflag <= 1)
742 print_unknown_data(bp,"\n\t ",olen);
743 break;
745 /* do we want to see an additionally hexdump ? */
746 if (vflag> 1)
747 print_unknown_data(bp,"\n\t ",olen);
748 bp += olen;
750 break;
753 case PIMV2_TYPE_REGISTER:
755 struct ip *ip;
757 if (!TTEST2(*(bp+4), PIMV2_REGISTER_FLAG_LEN))
758 goto trunc;
760 printf(", Flags [ %s ]\n\t",
761 tok2str(pimv2_register_flag_values,
762 "none",
763 EXTRACT_32BITS(bp+4)));
765 bp += 8; len -= 8;
766 /* encapsulated multicast packet */
767 ip = (struct ip *)bp;
768 switch (IP_V(ip)) {
769 case 0: /* Null header */
770 (void)printf("IP-Null-header %s > %s",
771 ipaddr_string(&ip->ip_src),
772 ipaddr_string(&ip->ip_dst));
773 break;
775 case 4: /* IPv4 */
776 ip_print(gndo, bp, len);
777 break;
778 #ifdef INET6
779 case 6: /* IPv6 */
780 ip6_print(bp, len);
781 break;
782 #endif
783 default:
784 (void)printf("IP ver %d", IP_V(ip));
785 break;
787 break;
790 case PIMV2_TYPE_REGISTER_STOP:
791 bp += 4; len -= 4;
792 if (bp >= ep)
793 break;
794 (void)printf(" group=");
795 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) {
796 (void)printf("...");
797 break;
799 bp += advance; len -= advance;
800 if (bp >= ep)
801 break;
802 (void)printf(" source=");
803 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) {
804 (void)printf("...");
805 break;
807 bp += advance; len -= advance;
808 break;
810 case PIMV2_TYPE_JOIN_PRUNE:
811 case PIMV2_TYPE_GRAFT:
812 case PIMV2_TYPE_GRAFT_ACK:
816 * 0 1 2 3
817 * 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
818 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
819 * |PIM Ver| Type | Addr length | Checksum |
820 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
821 * | Unicast-Upstream Neighbor Address |
822 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
823 * | Reserved | Num groups | Holdtime |
824 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
825 * | Encoded-Multicast Group Address-1 |
826 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
827 * | Number of Joined Sources | Number of Pruned Sources |
828 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
829 * | Encoded-Joined Source Address-1 |
830 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
831 * | . |
832 * | . |
833 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
834 * | Encoded-Joined Source Address-n |
835 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
836 * | Encoded-Pruned Source Address-1 |
837 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
838 * | . |
839 * | . |
840 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
841 * | Encoded-Pruned Source Address-n |
842 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
843 * | . |
844 * | . |
845 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
846 * | Encoded-Multicast Group Address-n |
847 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
851 u_int8_t ngroup;
852 u_int16_t holdtime;
853 u_int16_t njoin;
854 u_int16_t nprune;
855 int i, j;
857 bp += 4; len -= 4;
858 if (PIM_TYPE(pim->pim_typever) != 7) { /*not for Graft-ACK*/
859 if (bp >= ep)
860 break;
861 (void)printf(", upstream-neighbor: ");
862 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) {
863 (void)printf("...");
864 break;
866 bp += advance; len -= advance;
868 if (bp + 4 > ep)
869 break;
870 ngroup = bp[1];
871 holdtime = EXTRACT_16BITS(&bp[2]);
872 (void)printf("\n\t %u group(s)", ngroup);
873 if (PIM_TYPE(pim->pim_typever) != 7) { /*not for Graft-ACK*/
874 (void)printf(", holdtime: ");
875 if (holdtime == 0xffff)
876 (void)printf("infinite");
877 else
878 relts_print(holdtime);
880 bp += 4; len -= 4;
881 for (i = 0; i < ngroup; i++) {
882 if (bp >= ep)
883 goto jp_done;
884 (void)printf("\n\t group #%u: ", i+1);
885 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) {
886 (void)printf("...)");
887 goto jp_done;
889 bp += advance; len -= advance;
890 if (bp + 4 > ep) {
891 (void)printf("...)");
892 goto jp_done;
894 njoin = EXTRACT_16BITS(&bp[0]);
895 nprune = EXTRACT_16BITS(&bp[2]);
896 (void)printf(", joined sources: %u, pruned sources: %u", njoin,nprune);
897 bp += 4; len -= 4;
898 for (j = 0; j < njoin; j++) {
899 (void)printf("\n\t joined source #%u: ",j+1);
900 if ((advance = pimv2_addr_print(bp, pimv2_source, 0)) < 0) {
901 (void)printf("...)");
902 goto jp_done;
904 bp += advance; len -= advance;
906 for (j = 0; j < nprune; j++) {
907 (void)printf("\n\t pruned source #%u: ",j+1);
908 if ((advance = pimv2_addr_print(bp, pimv2_source, 0)) < 0) {
909 (void)printf("...)");
910 goto jp_done;
912 bp += advance; len -= advance;
915 jp_done:
916 break;
919 case PIMV2_TYPE_BOOTSTRAP:
921 int i, j, frpcnt;
922 bp += 4;
924 /* Fragment Tag, Hash Mask len, and BSR-priority */
925 if (bp + sizeof(u_int16_t) >= ep) break;
926 (void)printf(" tag=%x", EXTRACT_16BITS(bp));
927 bp += sizeof(u_int16_t);
928 if (bp >= ep) break;
929 (void)printf(" hashmlen=%d", bp[0]);
930 if (bp + 1 >= ep) break;
931 (void)printf(" BSRprio=%d", bp[1]);
932 bp += 2;
934 /* Encoded-Unicast-BSR-Address */
935 if (bp >= ep) break;
936 (void)printf(" BSR=");
937 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) {
938 (void)printf("...");
939 break;
941 bp += advance;
943 for (i = 0; bp < ep; i++) {
944 /* Encoded-Group Address */
945 (void)printf(" (group%d: ", i);
946 if ((advance = pimv2_addr_print(bp, pimv2_group, 0))
947 < 0) {
948 (void)printf("...)");
949 goto bs_done;
951 bp += advance;
953 /* RP-Count, Frag RP-Cnt, and rsvd */
954 if (bp >= ep) {
955 (void)printf("...)");
956 goto bs_done;
958 (void)printf(" RPcnt=%d", bp[0]);
959 if (bp + 1 >= ep) {
960 (void)printf("...)");
961 goto bs_done;
963 (void)printf(" FRPcnt=%d", frpcnt = bp[1]);
964 bp += 4;
966 for (j = 0; j < frpcnt && bp < ep; j++) {
967 /* each RP info */
968 (void)printf(" RP%d=", j);
969 if ((advance = pimv2_addr_print(bp,
970 pimv2_unicast,
971 0)) < 0) {
972 (void)printf("...)");
973 goto bs_done;
975 bp += advance;
977 if (bp + 1 >= ep) {
978 (void)printf("...)");
979 goto bs_done;
981 (void)printf(",holdtime=");
982 relts_print(EXTRACT_16BITS(bp));
983 if (bp + 2 >= ep) {
984 (void)printf("...)");
985 goto bs_done;
987 (void)printf(",prio=%d", bp[2]);
988 bp += 4;
990 (void)printf(")");
992 bs_done:
993 break;
995 case PIMV2_TYPE_ASSERT:
996 bp += 4; len -= 4;
997 if (bp >= ep)
998 break;
999 (void)printf(" group=");
1000 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) {
1001 (void)printf("...");
1002 break;
1004 bp += advance; len -= advance;
1005 if (bp >= ep)
1006 break;
1007 (void)printf(" src=");
1008 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) {
1009 (void)printf("...");
1010 break;
1012 bp += advance; len -= advance;
1013 if (bp + 8 > ep)
1014 break;
1015 if (bp[0] & 0x80)
1016 (void)printf(" RPT");
1017 (void)printf(" pref=%u", EXTRACT_32BITS(&bp[0]) & 0x7fffffff);
1018 (void)printf(" metric=%u", EXTRACT_32BITS(&bp[4]));
1019 break;
1021 case PIMV2_TYPE_CANDIDATE_RP:
1023 int i, pfxcnt;
1024 bp += 4;
1026 /* Prefix-Cnt, Priority, and Holdtime */
1027 if (bp >= ep) break;
1028 (void)printf(" prefix-cnt=%d", bp[0]);
1029 pfxcnt = bp[0];
1030 if (bp + 1 >= ep) break;
1031 (void)printf(" prio=%d", bp[1]);
1032 if (bp + 3 >= ep) break;
1033 (void)printf(" holdtime=");
1034 relts_print(EXTRACT_16BITS(&bp[2]));
1035 bp += 4;
1037 /* Encoded-Unicast-RP-Address */
1038 if (bp >= ep) break;
1039 (void)printf(" RP=");
1040 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) {
1041 (void)printf("...");
1042 break;
1044 bp += advance;
1046 /* Encoded-Group Addresses */
1047 for (i = 0; i < pfxcnt && bp < ep; i++) {
1048 (void)printf(" Group%d=", i);
1049 if ((advance = pimv2_addr_print(bp, pimv2_group, 0))
1050 < 0) {
1051 (void)printf("...");
1052 break;
1054 bp += advance;
1056 break;
1059 case PIMV2_TYPE_PRUNE_REFRESH:
1060 (void)printf(" src=");
1061 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) {
1062 (void)printf("...");
1063 break;
1065 bp += advance;
1066 (void)printf(" grp=");
1067 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) {
1068 (void)printf("...");
1069 break;
1071 bp += advance;
1072 (void)printf(" forwarder=");
1073 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) {
1074 (void)printf("...");
1075 break;
1077 bp += advance;
1078 TCHECK2(bp[0], 2);
1079 (void)printf(" TUNR ");
1080 relts_print(EXTRACT_16BITS(bp));
1081 break;
1084 default:
1085 (void)printf(" [type %d]", PIM_TYPE(pim->pim_typever));
1086 break;
1089 return;
1091 trunc:
1092 (void)printf("[|pim]");
1096 * Local Variables:
1097 * c-style: whitesmith
1098 * c-basic-offset: 8
1099 * End: