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