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