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