]> The Tcpdump Group git mirrors - tcpdump/blob - print-pim.c
Eliminate some unused parameters.
[tcpdump] / print-pim.c
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 #ifndef lint
23 static const char rcsid[] =
24 "@(#) $Header: /tcpdump/master/tcpdump/print-pim.c,v 1.29 2001-07-04 21:36:15 fenner Exp $ (LBL)";
25 #endif
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include <sys/param.h>
32 #include <sys/time.h>
33 #include <sys/socket.h>
34
35 #include <netinet/in.h>
36
37 /*
38 * XXX: We consider a case where IPv6 is not ready yet for portability,
39 * but PIM dependent defintions should be independent of IPv6...
40 */
41
42 struct pim {
43 u_int8_t pim_typever;
44 /* upper 4bit: PIM version number; 2 for PIMv2 */
45 /* lower 4bit: the PIM message type, currently they are:
46 * Hello, Register, Register-Stop, Join/Prune,
47 * Bootstrap, Assert, Graft (PIM-DM only),
48 * Graft-Ack (PIM-DM only), C-RP-Adv
49 */
50 #define PIM_VER(x) (((x) & 0xf0) >> 4)
51 #define PIM_TYPE(x) ((x) & 0x0f)
52 u_char pim_rsv; /* Reserved */
53 u_short pim_cksum; /* IP style check sum */
54 };
55
56
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <unistd.h>
60
61 #include "interface.h"
62 #include "addrtoname.h"
63 #include "extract.h"
64
65 #include "ip.h"
66
67 static void pimv2_print(register const u_char *bp, register u_int len);
68
69 static void
70 pimv1_join_prune_print(register const u_char *bp, register u_int len)
71 {
72 int maddrlen, addrlen, ngroups, njoin, nprune;
73 int njp;
74
75 /* If it's a single group and a single source, use 1-line output. */
76 if (TTEST2(bp[0], 30) && bp[11] == 1 &&
77 ((njoin = EXTRACT_16BITS(&bp[20])) + EXTRACT_16BITS(&bp[22])) == 1) {
78 int hold;
79
80 (void)printf(" RPF %s ", ipaddr_string(bp));
81 hold = EXTRACT_16BITS(&bp[6]);
82 if (hold != 180) {
83 (void)printf("Hold ");
84 relts_print(hold);
85 }
86 (void)printf("%s (%s/%d, %s", njoin ? "Join" : "Prune",
87 ipaddr_string(&bp[26]), bp[25] & 0x3f,
88 ipaddr_string(&bp[12]));
89 if (EXTRACT_32BITS(&bp[16]) != 0xffffffff)
90 (void)printf("/%s", ipaddr_string(&bp[16]));
91 (void)printf(") %s%s %s",
92 (bp[24] & 0x01) ? "Sparse" : "Dense",
93 (bp[25] & 0x80) ? " WC" : "",
94 (bp[25] & 0x40) ? "RP" : "SPT");
95 return;
96 }
97
98 TCHECK2(bp[0], 4);
99 if (vflag > 1)
100 (void)printf("\n");
101 (void)printf(" Upstream Nbr: %s", ipaddr_string(bp));
102 TCHECK2(bp[6], 2);
103 if (vflag > 1)
104 (void)printf("\n");
105 (void)printf(" Hold time: ");
106 relts_print(EXTRACT_16BITS(&bp[6]));
107 if (vflag < 2)
108 return;
109 bp += 8;
110 len -= 8;
111
112 TCHECK2(bp[0], 4);
113 maddrlen = bp[1];
114 addrlen = bp[2];
115 ngroups = bp[3];
116 bp += 4;
117 len -= 4;
118 while (ngroups--) {
119 TCHECK2(bp[0], 4);
120 (void)printf("\n\tGroup: %s", ipaddr_string(bp));
121 if (EXTRACT_32BITS(&bp[4]) != 0xffffffff)
122 (void)printf("/%s", ipaddr_string(&bp[4]));
123 TCHECK2(bp[8], 4);
124 njoin = EXTRACT_16BITS(&bp[8]);
125 nprune = EXTRACT_16BITS(&bp[10]);
126 (void)printf(" joined: %d pruned: %d", njoin, nprune);
127 bp += 12;
128 len -= 12;
129 for (njp = 0; njp < (njoin + nprune); njp++) {
130 char *type;
131
132 if (njp < njoin)
133 type = "Join ";
134 else
135 type = "Prune";
136 TCHECK2(bp[0], 6);
137 (void)printf("\n\t%s %s%s%s%s/%d", type,
138 (bp[0] & 0x01) ? "Sparse " : "Dense ",
139 (bp[1] & 0x80) ? "WC " : "",
140 (bp[1] & 0x40) ? "RP " : "SPT ",
141 ipaddr_string(&bp[2]), bp[1] & 0x3f);
142 bp += 6;
143 len -= 6;
144 }
145 }
146 return;
147 trunc:
148 (void)printf("[|pim]");
149 return;
150 }
151
152 void
153 pimv1_print(register const u_char *bp, register u_int len)
154 {
155 register const u_char *ep;
156 register u_char type;
157
158 ep = (const u_char *)snapend;
159 if (bp >= ep)
160 return;
161
162 type = bp[1];
163
164 switch (type) {
165 case 0:
166 (void)printf(" Query");
167 if (TTEST(bp[8])) {
168 switch (bp[8] >> 4) {
169 case 0:
170 (void)printf(" Dense-mode");
171 break;
172 case 1:
173 (void)printf(" Sparse-mode");
174 break;
175 case 2:
176 (void)printf(" Sparse-Dense-mode");
177 break;
178 default:
179 (void)printf(" mode-%d", bp[8] >> 4);
180 break;
181 }
182 }
183 if (vflag) {
184 TCHECK2(bp[10],2);
185 (void)printf(" (Hold-time ");
186 relts_print(EXTRACT_16BITS(&bp[10]));
187 (void)printf(")");
188 }
189 break;
190
191 case 1:
192 (void)printf(" Register");
193 TCHECK2(bp[8], 20); /* ip header */
194 (void)printf(" for %s > %s", ipaddr_string(&bp[20]),
195 ipaddr_string(&bp[24]));
196 break;
197 case 2:
198 (void)printf(" Register-Stop");
199 TCHECK2(bp[12], 4);
200 (void)printf(" for %s > %s", ipaddr_string(&bp[8]),
201 ipaddr_string(&bp[12]));
202 break;
203 case 3:
204 (void)printf(" Join/Prune");
205 if (vflag)
206 pimv1_join_prune_print(&bp[8], len - 8);
207 break;
208 case 4:
209 (void)printf(" RP-reachable");
210 if (vflag) {
211 TCHECK2(bp[22], 2);
212 (void)printf(" group %s",
213 ipaddr_string(&bp[8]));
214 if (EXTRACT_32BITS(&bp[12]) != 0xffffffff)
215 (void)printf("/%s", ipaddr_string(&bp[12]));
216 (void)printf(" RP %s hold ", ipaddr_string(&bp[16]));
217 relts_print(EXTRACT_16BITS(&bp[22]));
218 }
219 break;
220 case 5:
221 (void)printf(" Assert");
222 TCHECK2(bp[16], 4);
223 (void)printf(" for %s > %s", ipaddr_string(&bp[16]),
224 ipaddr_string(&bp[8]));
225 if (EXTRACT_32BITS(&bp[12]) != 0xffffffff)
226 (void)printf("/%s", ipaddr_string(&bp[12]));
227 TCHECK2(bp[24], 4);
228 (void)printf(" %s pref %d metric %d",
229 (bp[20] & 0x80) ? "RP-tree" : "SPT",
230 EXTRACT_32BITS(&bp[20]) & 0x7fffffff,
231 EXTRACT_32BITS(&bp[24]));
232 break;
233 case 6:
234 (void)printf(" Graft");
235 if (vflag)
236 pimv1_join_prune_print(&bp[8], len - 8);
237 break;
238 case 7:
239 (void)printf(" Graft-ACK");
240 if (vflag)
241 pimv1_join_prune_print(&bp[8], len - 8);
242 break;
243 case 8:
244 (void)printf(" Mode");
245 break;
246 default:
247 (void)printf(" [type %d]", type);
248 break;
249 }
250 if ((bp[4] >> 4) != 1)
251 (void)printf(" [v%d]", bp[4] >> 4);
252 return;
253
254 trunc:
255 (void)printf("[|pim]");
256 return;
257 }
258
259 /*
260 * auto-RP is a cisco protocol, documented at
261 * ftp://ftpeng.cisco.com/ipmulticast/specs/pim-autorp-spec01.txt
262 *
263 * This implements version 1+, dated Sept 9, 1998.
264 */
265 void
266 cisco_autorp_print(register const u_char *bp, register u_int len)
267 {
268 int type;
269 int numrps;
270 int hold;
271
272 TCHECK(bp[0]);
273 (void)printf(" auto-rp ");
274 type = bp[0];
275 switch (type) {
276 case 0x11:
277 (void)printf("candidate-advert");
278 break;
279 case 0x12:
280 (void)printf("mapping");
281 break;
282 default:
283 (void)printf("type-0x%02x", type);
284 break;
285 }
286
287 TCHECK(bp[1]);
288 numrps = bp[1];
289
290 TCHECK2(bp[2], 2);
291 (void)printf(" Hold ");
292 hold = EXTRACT_16BITS(&bp[2]);
293 if (hold)
294 relts_print(EXTRACT_16BITS(&bp[2]));
295 else
296 printf("FOREVER");
297
298 /* Next 4 bytes are reserved. */
299
300 bp += 8; len -= 8;
301
302 /*XXX skip unless -v? */
303
304 /*
305 * Rest of packet:
306 * numrps entries of the form:
307 * 32 bits: RP
308 * 6 bits: reserved
309 * 2 bits: PIM version supported, bit 0 is "supports v1", 1 is "v2".
310 * 8 bits: # of entries for this RP
311 * each entry: 7 bits: reserved, 1 bit: negative,
312 * 8 bits: mask 32 bits: source
313 * lather, rinse, repeat.
314 */
315 while (numrps--) {
316 int nentries;
317 char s;
318
319 TCHECK2(bp[0], 4);
320 (void)printf(" RP %s", ipaddr_string(bp));
321 TCHECK(bp[4]);
322 switch (bp[4] & 0x3) {
323 case 0: printf(" PIMv?");
324 break;
325 case 1: printf(" PIMv1");
326 break;
327 case 2: printf(" PIMv2");
328 break;
329 case 3: printf(" PIMv1+2");
330 break;
331 }
332 if (bp[4] & 0xfc)
333 (void)printf(" [rsvd=0x%02x]", bp[4] & 0xfc);
334 TCHECK(bp[5]);
335 nentries = bp[5];
336 bp += 6; len -= 6;
337 s = ' ';
338 for (; nentries; nentries--) {
339 TCHECK2(bp[0], 6);
340 (void)printf("%c%s%s/%d", s, bp[0] & 1 ? "!" : "",
341 ipaddr_string(&bp[2]), bp[1]);
342 if (bp[0] & 0xfe)
343 (void)printf("[rsvd=0x%02x]", bp[0] & 0xfe);
344 s = ',';
345 bp += 6; len -= 6;
346 }
347 }
348 return;
349
350 trunc:
351 (void)printf("[|autorp]");
352 return;
353 }
354
355 void
356 pim_print(register const u_char *bp, register u_int len)
357 {
358 register const u_char *ep;
359 register struct pim *pim = (struct pim *)bp;
360
361 ep = (const u_char *)snapend;
362 if (bp >= ep)
363 return;
364 #ifdef notyet /* currently we see only version and type */
365 TCHECK(pim->pim_rsv);
366 #endif
367
368 switch (PIM_VER(pim->pim_typever)) {
369 case 2: /* avoid hardcoding? */
370 (void)printf("pim v2");
371 pimv2_print(bp, len);
372 break;
373 default:
374 (void)printf("pim v%d", PIM_VER(pim->pim_typever));
375 break;
376 }
377 return;
378 }
379
380 /*
381 * PIMv2 uses encoded address representations.
382 *
383 * The last PIM-SM I-D before RFC2117 was published specified the
384 * following representation for unicast addresses. However, RFC2117
385 * specified no encoding for unicast addresses with the unicast
386 * address length specified in the header. Therefore, we have to
387 * guess which encoding is being used (Cisco's PIMv2 implementation
388 * uses the non-RFC encoding). RFC2117 turns a previously "Reserved"
389 * field into a 'unicast-address-length-in-bytes' field. We guess
390 * that it's the draft encoding if this reserved field is zero.
391 *
392 * RFC2362 goes back to the encoded format, and calls the addr length
393 * field "reserved" again.
394 *
395 * The first byte is the address family, from:
396 *
397 * 0 Reserved
398 * 1 IP (IP version 4)
399 * 2 IP6 (IP version 6)
400 * 3 NSAP
401 * 4 HDLC (8-bit multidrop)
402 * 5 BBN 1822
403 * 6 802 (includes all 802 media plus Ethernet "canonical format")
404 * 7 E.163
405 * 8 E.164 (SMDS, Frame Relay, ATM)
406 * 9 F.69 (Telex)
407 * 10 X.121 (X.25, Frame Relay)
408 * 11 IPX
409 * 12 Appletalk
410 * 13 Decnet IV
411 * 14 Banyan Vines
412 * 15 E.164 with NSAP format subaddress
413 *
414 * In addition, the second byte is an "Encoding". 0 is the default
415 * encoding for the address family, and no other encodings are currently
416 * specified.
417 *
418 */
419
420 static int pimv2_addr_len;
421
422 enum pimv2_addrtype {
423 pimv2_unicast, pimv2_group, pimv2_source
424 };
425
426 /* 0 1 2 3
427 * 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
428 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
429 * | Addr Family | Encoding Type | Unicast Address |
430 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+++++++
431 * 0 1 2 3
432 * 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
433 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
434 * | Addr Family | Encoding Type | Reserved | Mask Len |
435 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
436 * | Group multicast Address |
437 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
438 * 0 1 2 3
439 * 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
440 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
441 * | Addr Family | Encoding Type | Rsrvd |S|W|R| Mask Len |
442 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
443 * | Source Address |
444 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
445 */
446 static int
447 pimv2_addr_print(const u_char *bp, enum pimv2_addrtype at, int silent)
448 {
449 int af;
450 char *afstr;
451 int len, hdrlen;
452
453 TCHECK(bp[0]);
454
455 if (pimv2_addr_len == 0) {
456 TCHECK(bp[1]);
457 switch (bp[0]) {
458 case 1:
459 af = AF_INET;
460 afstr = "IPv4";
461 len = 4;
462 break;
463 #ifdef INET6
464 case 2:
465 af = AF_INET6;
466 afstr = "IPv6";
467 len = 16;
468 break;
469 #endif
470 default:
471 return -1;
472 }
473 if (bp[1] != 0)
474 return -1;
475 hdrlen = 2;
476 } else {
477 switch (pimv2_addr_len) {
478 case 4:
479 af = AF_INET;
480 afstr = "IPv4";
481 break;
482 #ifdef INET6
483 case 16:
484 af = AF_INET6;
485 afstr = "IPv6";
486 break;
487 #endif
488 default:
489 return -1;
490 break;
491 }
492 len = pimv2_addr_len;
493 hdrlen = 0;
494 }
495
496 bp += hdrlen;
497 switch (at) {
498 case pimv2_unicast:
499 TCHECK2(bp[0], len);
500 if (af == AF_INET) {
501 if (!silent)
502 (void)printf("%s", ipaddr_string(bp));
503 }
504 #ifdef INET6
505 else if (af == AF_INET6) {
506 if (!silent)
507 (void)printf("%s", ip6addr_string(bp));
508 }
509 #endif
510 return hdrlen + len;
511 case pimv2_group:
512 case pimv2_source:
513 TCHECK2(bp[0], len + 2);
514 if (af == AF_INET) {
515 if (!silent) {
516 (void)printf("%s", ipaddr_string(bp + 2));
517 if (bp[1] != 32)
518 (void)printf("/%u", bp[1]);
519 }
520 }
521 #ifdef INET6
522 else if (af == AF_INET6) {
523 if (!silent) {
524 (void)printf("%s", ip6addr_string(bp + 2));
525 if (bp[1] != 128)
526 (void)printf("/%u", bp[1]);
527 }
528 }
529 #endif
530 if (bp[0] && !silent) {
531 if (at == pimv2_group) {
532 (void)printf("(0x%02x)", bp[0]);
533 } else {
534 (void)printf("(%s%s%s",
535 bp[0] & 0x04 ? "S" : "",
536 bp[0] & 0x02 ? "W" : "",
537 bp[0] & 0x01 ? "R" : "");
538 if (bp[0] & 0xf8) {
539 (void) printf("+0x%02x", bp[0] & 0xf8);
540 }
541 (void)printf(")");
542 }
543 }
544 return hdrlen + 2 + len;
545 default:
546 return -1;
547 }
548 trunc:
549 return -1;
550 }
551
552 static void
553 pimv2_print(register const u_char *bp, register u_int len)
554 {
555 register const u_char *ep;
556 register struct pim *pim = (struct pim *)bp;
557 int advance;
558
559 ep = (const u_char *)snapend;
560 if (bp >= ep)
561 return;
562 if (ep > bp + len)
563 ep = bp + len;
564 TCHECK(pim->pim_rsv);
565 pimv2_addr_len = pim->pim_rsv;
566 if (pimv2_addr_len != 0)
567 (void)printf("[RFC2117-encoding] ");
568
569 switch (PIM_TYPE(pim->pim_typever)) {
570 case 0:
571 {
572 u_int16_t otype, olen;
573 (void)printf(" Hello");
574 bp += 4;
575 while (bp < ep) {
576 TCHECK2(bp[0], 4);
577 otype = EXTRACT_16BITS(&bp[0]);
578 olen = EXTRACT_16BITS(&bp[2]);
579 TCHECK2(bp[0], 4 + olen);
580 switch (otype) {
581 case 1: /* Hold time */
582 (void)printf(" (Hold-time ");
583 relts_print(EXTRACT_16BITS(&bp[4]));
584 (void)printf(")");
585 break;
586
587 case 19: /* DR-Priority */
588 (void)printf(" (DR-Priority: ");
589 if (olen != 4) {
590 (void)printf("!olen=%d!)", olen);
591 } else {
592 (void)printf("%d)", EXTRACT_32BITS(&bp[4]));
593 }
594 break;
595
596 case 20:
597 (void)printf(" (Genid: 0x%08x)", EXTRACT_32BITS(&bp[4]));
598 break;
599
600 case 21:
601 (void)printf(" (State Refresh Capable; v%d", bp[4]);
602 if (bp[5] != 0) {
603 (void)printf(" interval ");
604 relts_print(bp[5]);
605 }
606 if (EXTRACT_16BITS(&bp[6]) != 0) {
607 (void)printf(" ?0x%04x?", EXTRACT_16BITS(&bp[6]));
608 }
609 (void)printf(")");
610 break;
611
612 case 22: /* Bidir-Capable */
613 (void)printf(" (bidir-capable)");
614 break;
615
616 default:
617 if (vflag)
618 (void)printf(" [Hello option %d]", otype);
619 }
620 bp += 4 + olen;
621 }
622 break;
623 }
624
625 case 1:
626 {
627 struct ip *ip;
628
629 (void)printf(" Register");
630 if (vflag && bp + 8 <= ep) {
631 (void)printf(" %s%s", bp[4] & 0x80 ? "B" : "",
632 bp[4] & 0x40 ? "N" : "");
633 }
634 bp += 8; len -= 8;
635
636 /* encapsulated multicast packet */
637 if (bp >= ep)
638 break;
639 ip = (struct ip *)bp;
640 switch (IP_V(ip)) {
641 case 4: /* IPv4 */
642 printf(" ");
643 ip_print(bp, len);
644 break;
645 #ifdef INET6
646 case 6: /* IPv6 */
647 printf(" ");
648 ip6_print(bp, len);
649 break;
650 #endif
651 default:
652 (void)printf(" IP ver %d", IP_V(ip));
653 break;
654 }
655 break;
656 }
657
658 case 2:
659 (void)printf(" Register-Stop");
660 bp += 4; len -= 4;
661 if (bp >= ep)
662 break;
663 (void)printf(" group=");
664 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) {
665 (void)printf("...");
666 break;
667 }
668 bp += advance; len -= advance;
669 if (bp >= ep)
670 break;
671 (void)printf(" source=");
672 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) {
673 (void)printf("...");
674 break;
675 }
676 bp += advance; len -= advance;
677 break;
678
679 case 3:
680 case 6:
681 case 7:
682 {
683 u_int8_t ngroup;
684 u_int16_t holdtime;
685 u_int16_t njoin;
686 u_int16_t nprune;
687 int i, j;
688
689 switch (PIM_TYPE(pim->pim_typever)) {
690 case 3:
691 (void)printf(" Join/Prune");
692 break;
693 case 6:
694 (void)printf(" Graft");
695 break;
696 case 7:
697 (void)printf(" Graft-ACK");
698 break;
699 }
700 bp += 4; len -= 4;
701 if (PIM_TYPE(pim->pim_typever) != 7) { /*not for Graft-ACK*/
702 if (bp >= ep)
703 break;
704 (void)printf(" upstream-neighbor=");
705 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) {
706 (void)printf("...");
707 break;
708 }
709 bp += advance; len -= advance;
710 }
711 if (bp + 4 > ep)
712 break;
713 ngroup = bp[1];
714 holdtime = EXTRACT_16BITS(&bp[2]);
715 (void)printf(" groups=%u", ngroup);
716 if (PIM_TYPE(pim->pim_typever) != 7) { /*not for Graft-ACK*/
717 (void)printf(" holdtime=");
718 if (holdtime == 0xffff)
719 (void)printf("infty");
720 else
721 relts_print(holdtime);
722 }
723 bp += 4; len -= 4;
724 for (i = 0; i < ngroup; i++) {
725 if (bp >= ep)
726 goto jp_done;
727 (void)printf(" (group%d: ", i);
728 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) {
729 (void)printf("...)");
730 goto jp_done;
731 }
732 bp += advance; len -= advance;
733 if (bp + 4 > ep) {
734 (void)printf("...)");
735 goto jp_done;
736 }
737 njoin = EXTRACT_16BITS(&bp[0]);
738 nprune = EXTRACT_16BITS(&bp[2]);
739 (void)printf(" join=%u", njoin);
740 bp += 4; len -= 4;
741 for (j = 0; j < njoin; j++) {
742 (void)printf(" ");
743 if ((advance = pimv2_addr_print(bp, pimv2_source, 0)) < 0) {
744 (void)printf("...)");
745 goto jp_done;
746 }
747 bp += advance; len -= advance;
748 }
749 (void)printf(" prune=%u", nprune);
750 for (j = 0; j < nprune; j++) {
751 (void)printf(" ");
752 if ((advance = pimv2_addr_print(bp, pimv2_source, 0)) < 0) {
753 (void)printf("...)");
754 goto jp_done;
755 }
756 bp += advance; len -= advance;
757 }
758 (void)printf(")");
759 }
760 jp_done:
761 break;
762 }
763
764 case 4:
765 {
766 int i, j, frpcnt;
767
768 (void)printf(" Bootstrap");
769 bp += 4;
770
771 /* Fragment Tag, Hash Mask len, and BSR-priority */
772 if (bp + sizeof(u_int16_t) >= ep) break;
773 (void)printf(" tag=%x", EXTRACT_16BITS(bp));
774 bp += sizeof(u_int16_t);
775 if (bp >= ep) break;
776 (void)printf(" hashmlen=%d", bp[0]);
777 if (bp + 1 >= ep) break;
778 (void)printf(" BSRprio=%d", bp[1]);
779 bp += 2;
780
781 /* Encoded-Unicast-BSR-Address */
782 if (bp >= ep) break;
783 (void)printf(" BSR=");
784 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) {
785 (void)printf("...");
786 break;
787 }
788 bp += advance;
789
790 for (i = 0; bp < ep; i++) {
791 /* Encoded-Group Address */
792 (void)printf(" (group%d: ", i);
793 if ((advance = pimv2_addr_print(bp, pimv2_group, 0))
794 < 0) {
795 (void)printf("...)");
796 goto bs_done;
797 }
798 bp += advance;
799
800 /* RP-Count, Frag RP-Cnt, and rsvd */
801 if (bp >= ep) {
802 (void)printf("...)");
803 goto bs_done;
804 }
805 (void)printf(" RPcnt=%d", bp[0]);
806 if (bp + 1 >= ep) {
807 (void)printf("...)");
808 goto bs_done;
809 }
810 (void)printf(" FRPcnt=%d", frpcnt = bp[1]);
811 bp += 4;
812
813 for (j = 0; j < frpcnt && bp < ep; j++) {
814 /* each RP info */
815 (void)printf(" RP%d=", j);
816 if ((advance = pimv2_addr_print(bp,
817 pimv2_unicast,
818 0)) < 0) {
819 (void)printf("...)");
820 goto bs_done;
821 }
822 bp += advance;
823
824 if (bp + 1 >= ep) {
825 (void)printf("...)");
826 goto bs_done;
827 }
828 (void)printf(",holdtime=");
829 relts_print(EXTRACT_16BITS(bp));
830 if (bp + 2 >= ep) {
831 (void)printf("...)");
832 goto bs_done;
833 }
834 (void)printf(",prio=%d", bp[2]);
835 bp += 4;
836 }
837 (void)printf(")");
838 }
839 bs_done:
840 break;
841 }
842 case 5:
843 (void)printf(" Assert");
844 bp += 4; len -= 4;
845 if (bp >= ep)
846 break;
847 (void)printf(" group=");
848 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) {
849 (void)printf("...");
850 break;
851 }
852 bp += advance; len -= advance;
853 if (bp >= ep)
854 break;
855 (void)printf(" src=");
856 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) {
857 (void)printf("...");
858 break;
859 }
860 bp += advance; len -= advance;
861 if (bp + 8 > ep)
862 break;
863 if (bp[0] & 0x80)
864 (void)printf(" RPT");
865 (void)printf(" pref=%u", EXTRACT_32BITS(&bp[0]) & 0x7fffffff);
866 (void)printf(" metric=%u", EXTRACT_32BITS(&bp[4]));
867 break;
868
869 case 8:
870 {
871 int i, pfxcnt;
872
873 (void)printf(" Candidate-RP-Advertisement");
874 bp += 4;
875
876 /* Prefix-Cnt, Priority, and Holdtime */
877 if (bp >= ep) break;
878 (void)printf(" prefix-cnt=%d", bp[0]);
879 pfxcnt = bp[0];
880 if (bp + 1 >= ep) break;
881 (void)printf(" prio=%d", bp[1]);
882 if (bp + 3 >= ep) break;
883 (void)printf(" holdtime=");
884 relts_print(EXTRACT_16BITS(&bp[2]));
885 bp += 4;
886
887 /* Encoded-Unicast-RP-Address */
888 if (bp >= ep) break;
889 (void)printf(" RP=");
890 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) {
891 (void)printf("...");
892 break;
893 }
894 bp += advance;
895
896 /* Encoded-Group Addresses */
897 for (i = 0; i < pfxcnt && bp < ep; i++) {
898 (void)printf(" Group%d=", i);
899 if ((advance = pimv2_addr_print(bp, pimv2_group, 0))
900 < 0) {
901 (void)printf("...");
902 break;
903 }
904 bp += advance;
905 }
906 break;
907 }
908
909 case 9:
910 (void)printf(" Prune-Refresh");
911 (void)printf(" src=");
912 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) {
913 (void)printf("...");
914 break;
915 }
916 bp += advance;
917 (void)printf(" grp=");
918 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) {
919 (void)printf("...");
920 break;
921 }
922 bp += advance;
923 (void)printf(" forwarder=");
924 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) {
925 (void)printf("...");
926 break;
927 }
928 bp += advance;
929 TCHECK2(bp[0], 2);
930 (void)printf(" TUNR ");
931 relts_print(EXTRACT_16BITS(bp));
932 break;
933
934
935 default:
936 (void)printf(" [type %d]", PIM_TYPE(pim->pim_typever));
937 break;
938 }
939
940 return;
941
942 trunc:
943 (void)printf("[|pim]");
944 }