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