2 * Copyright (c) 1998 by the University of Southern California.
5 * Permission to use, copy, modify, and distribute this software and
6 * its documentation in source and binary forms for lawful
7 * purposes and without fee is hereby granted, provided
8 * that the above copyright notice appear in all copies and that both
9 * the copyright notice and this permission notice appear in supporting
10 * documentation, and that any documentation, advertising materials,
11 * and other materials related to such distribution and use acknowledge
12 * that the software was developed by the University of Southern
13 * California and/or Information Sciences Institute.
14 * The name of the University of Southern California may not
15 * be used to endorse or promote products derived from this software
16 * without specific prior written permission.
18 * THE UNIVERSITY OF SOUTHERN CALIFORNIA DOES NOT MAKE ANY REPRESENTATIONS
19 * ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE. THIS SOFTWARE IS
20 * PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
21 * INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
22 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND
25 * IN NO EVENT SHALL USC, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
26 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT,
27 * TORT, OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH,
28 * THE USE OR PERFORMANCE OF THIS SOFTWARE.
30 * Other copyrights might apply to parts of this software and are so
31 * noted when applicable.
34 * Questions concerning this software should be directed to
35 * Mickael Hoerdt (hoerdt@clarinet.u-strasbg.fr) LSIIT Strasbourg.
39 * This program has been derived from pim6dd.
40 * The pim6dd program is covered by the license in the accompanying file
41 * named "LICENSE.pim6dd".
44 * This program has been derived from pimd.
45 * The pimd program is covered by the license in the accompanying file
46 * named "LICENSE.pimd".
50 * Part of this program has been derived from mrouted.
51 * The mrouted program is covered by the license in the accompanying file
52 * named "LICENSE.mrouted".
54 * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
55 * Leland Stanford Junior University.
62 #include <sys/param.h>
63 #include <sys/types.h>
64 #include <sys/socket.h>
67 #include <net/route.h>
68 #include <netinet/in.h>
69 #include <netinet/ip_mroute.h>
70 #include <netinet/icmp6.h>
71 #include <netinet6/pim6.h>
72 #include "pathnames.h"
87 extern char *progname;
90 unsigned long debug = 0x00000000; /* If (long) is smaller than 4 bytes,
91 * then we are in trouble. */
92 static char dumpfilename[] = _PATH_PIM6D_DUMP;
93 static char cachefilename[] = _PATH_PIM6D_CACHE; /* TODO: notused */
94 static char statfilename[] = _PATH_PIM6D_STAT;
96 static char *sec2str __P((time_t));
102 static char result[256];
103 int days, hours, mins, secs;
107 days = total / 3600 / 24;
108 hours = (total / 3600) % 24;
109 mins = (total / 60) % 60;
114 p += sprintf(p, "%dd", days);
116 if (!first || hours) {
118 p += sprintf(p, "%dh", hours);
120 if (!first || mins) {
122 p += sprintf(p, "%dm", mins);
124 sprintf(p, "%ds", secs);
130 packet_kind(proto, type, code)
135 static char unknown[60];
142 case MLD6_LISTENER_QUERY:
143 return "Multicast Listener Query ";
144 case MLD6_LISTENER_REPORT:
145 return "Multicast Listener Report ";
146 case MLD6_LISTENER_DONE:
147 return "Multicast Listener Done ";
150 "UNKNOWN ICMPv6 message: type = 0x%02x, code = 0x%02x ",
155 case IPPROTO_PIM: /* PIM v2 */
159 return "PIM v2 Hello ";
160 case PIM_V2_REGISTER:
161 return "PIM v2 Register ";
162 case PIM_V2_REGISTER_STOP:
163 return "PIM v2 Register_Stop ";
164 case PIM_V2_JOIN_PRUNE:
165 return "PIM v2 Join/Prune ";
166 case PIM_V2_BOOTSTRAP:
167 return "PIM v2 Bootstrap ";
169 return "PIM v2 Assert ";
171 return "PIM-DM v2 Graft ";
172 case PIM_V2_GRAFT_ACK:
173 return "PIM-DM v2 Graft_Ack ";
174 case PIM_V2_CAND_RP_ADV:
175 return "PIM v2 Cand. RP Adv. ";
177 sprintf(unknown, "UNKNOWN PIM v2 message type =%3d ", type);
181 sprintf(unknown, "UNKNOWN proto =%3d ", proto);
188 * Used for debugging particular type of messages.
191 debug_kind(proto, type, code)
201 case MLD6_LISTENER_QUERY:
203 case MLD6_LISTENER_REPORT:
205 case MLD6_LISTENER_DONE:
210 case IPPROTO_PIM: /* PIM v2 */
216 case PIM_V2_REGISTER:
217 return DEBUG_PIM_REGISTER;
218 case PIM_V2_REGISTER_STOP:
219 return DEBUG_PIM_REGISTER;
220 case PIM_V2_JOIN_PRUNE:
222 case PIM_V2_BOOTSTRAP:
223 return DEBUG_PIM_BOOTSTRAP;
228 case PIM_V2_GRAFT_ACK:
230 case PIM_V2_CAND_RP_ADV:
231 return DEBUG_PIM_CAND_RP;
243 * Some messages are more important than others. This routine determines the
244 * logging level at which to log a send error (often "No route to host").
245 * This is important when there is asymmetric reachability and someone is
246 * trying to, i.e., mrinfo me periodically.
249 log_level(proto, type, code)
279 * Dump internal data structures to stderr.
282 * TODO: currently not used void dump(int i) { dump_vifs(stderr);
283 * dump_pim_mrt(stderr); }
287 * Dump internal data structures to a file.
294 fp = fopen(dumpfilename, "w");
299 dump_mldqueriers(fp);
306 /* TODO: dummy, to be used in the future. */
308 * Dump local cache contents to a file.
316 fp = fopen(cachefilename, "w");
320 * TODO: implement it: dump_cache(fp);
331 register struct uvif *v;
333 fp = fopen(statfilename, "w");
335 log(LOG_WARNING, errno, "dump_stat: can't open file(%s)",
340 fprintf(fp, "pim6sd per-interface statistics\n");
341 for (vifi = 0, v = uvifs; vifi < numvifs; vifi++, v++) {
342 #if 0 /* is it better to skip them? */
343 if ((v->uv_flags & (VIFF_DISABLED|VIFF_DOWN)) != 0)
346 fprintf(fp, " Mif=%d, PhyIF=%s\n", vifi, v->uv_name);
347 fprintf(fp, "\t%qu pim6 hello received\n",
348 (unsigned long long)v->uv_in_pim6_hello);
349 fprintf(fp, "\t%qu pim6 join-prune received\n",
350 (unsigned long long)v->uv_in_pim6_join_prune);
351 fprintf(fp, "\t%qu pim6 bootstrap received\n",
352 (unsigned long long)v->uv_in_pim6_bootsrap);
353 fprintf(fp, "\t%qu pim6 assert received\n",
354 (unsigned long long)v->uv_in_pim6_assert);
356 fprintf(fp, "\t%qu pim6 hello sent\n",
357 (unsigned long long)v->uv_out_pim6_hello);
358 fprintf(fp, "\t%qu pim6 join-prune sent\n",
359 (unsigned long long)v->uv_out_pim6_join_prune);
360 fprintf(fp, "\t%qu pim6 bootstrap sent\n",
361 (unsigned long long)v->uv_out_pim6_bootsrap);
362 fprintf(fp, "\t%qu pim6 assert sent\n",
363 (unsigned long long)v->uv_out_pim6_assert);
365 fprintf(fp, "\t%qu MLD query received\n",
366 (unsigned long long)v->uv_in_mld_query);
367 fprintf(fp, "\t%qu MLD report received\n",
368 (unsigned long long)v->uv_in_mld_report);
369 fprintf(fp, "\t%qu MLD done received\n",
370 (unsigned long long)v->uv_in_mld_done);
372 fprintf(fp, "\t%qu MLD query sent\n",
373 (unsigned long long)v->uv_out_mld_query);
374 fprintf(fp, "\t%qu MLD report sent\n",
375 (unsigned long long)v->uv_out_mld_report);
376 fprintf(fp, "\t%qu MLD done sent\n",
377 (unsigned long long)v->uv_out_mld_done);
379 fprintf(fp, "\t%qu forwarding cache miss\n",
380 (unsigned long long)v->uv_cache_miss);
381 fprintf(fp, "\t%qu forwarding cache miss and not created\n",
382 (unsigned long long)v->uv_cache_notcreated);
384 fprintf(fp, "\t%qu PIM neighbor timeouts\n",
385 (unsigned long long)v->uv_pim6_nbr_timo);
386 fprintf(fp, "\t%qu MLD listener timeouts\n",
387 (unsigned long long)v->uv_listener_timo);
388 fprintf(fp, "\t%qu MLD querier timeouts\n",
389 (unsigned long long)v->uv_querier_timo);
390 fprintf(fp, "\t%qu out-I/F timeouts\n",
391 (unsigned long long)v->uv_outif_timo);
394 fprintf(fp, "\npim6sd interface independent statistics\n");
396 fprintf(fp, "\t%qu pim6 register received\n",
397 (unsigned long long)pim6dstat.in_pim6_register);
398 fprintf(fp, "\t%qu pim6 register-stop received\n",
399 (unsigned long long)pim6dstat.in_pim6_register_stop);
400 fprintf(fp, "\t%qu pim6 cand-RP received\n",
401 (unsigned long long)pim6dstat.in_pim6_cand_rp);
402 fprintf(fp, "\t%qu pim6 graft received\n",
403 (unsigned long long)pim6dstat.in_pim6_graft);
404 fprintf(fp, "\t%qu pim6 graft ack received\n",
405 (unsigned long long)pim6dstat.in_pim6_graft_ack);
407 fprintf(fp, "\t%qu pim6 register sent\n",
408 (unsigned long long)pim6dstat.out_pim6_register);
409 fprintf(fp, "\t%qu pim6 register-stop sent\n",
410 (unsigned long long)pim6dstat.out_pim6_register_stop);
411 fprintf(fp, "\t%qu pim6 cand-RP sent\n",
412 (unsigned long long)pim6dstat.out_pim6_cand_rp);
414 fprintf(fp, "\t%qu transitions of forwarder initiated SPT\n",
415 (unsigned long long)pim6dstat.pim6_trans_spt_forward);
416 fprintf(fp, "\t%qu transitions of RP initiated SPT\n",
417 (unsigned long long)pim6dstat.pim6_trans_spt_rp);
419 fprintf(fp, "\t%qu pim6 bootstrap timeouts\n",
420 (unsigned long long)pim6dstat.pim6_bootstrap_timo);
421 fprintf(fp, "\t%qu pim6 RP group entry timeouts\n",
422 (unsigned long long)pim6dstat.pim6_rpgrp_timo);
423 fprintf(fp, "\t%qu pim6 routing entry timeouts\n",
424 (unsigned long long)pim6dstat.pim6_rtentry_timo);
426 fprintf(fp, "\t%qu kernel cache additions\n",
427 (unsigned long long)pim6dstat.kern_add_cache);
428 fprintf(fp, "\t%qu kernel cache addition failures\n",
429 (unsigned long long)pim6dstat.kern_add_cache_fail);
430 fprintf(fp, "\t%qu kernel cache deletions\n",
431 (unsigned long long)pim6dstat.kern_del_cache);
432 fprintf(fp, "\t%qu kernel cache deletion failures\n",
433 (unsigned long long)pim6dstat.kern_del_cache_fail);
434 fprintf(fp, "\t%qu failures of getting kernel cache\n",
435 (unsigned long long)pim6dstat.kern_sgcnt_fail);
445 register struct uvif *v;
448 fprintf(fp, "\nMulticast Interface Table\n %-4s %-6s %-43s %5s %-14s\n",
449 "Mif", " PhyIF", "Local-Address/Prefixlen","Scope", "Flags");
451 for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v)
454 for (pa = v->uv_addrs; pa; pa = pa->pa_next)
458 fprintf(fp, " %3s %6s %-43s", "", "",
459 net6name(&pa->pa_addr.sin6_addr,
460 &pa->pa_subnetmask));
461 fprintf(fp," %-5d\n", pa->pa_addr.sin6_scope_id);
466 fprintf(fp, " %-3u %6s %-43s", vifi,
467 (v->uv_flags & MIFF_REGISTER)?"regist":v->uv_name,
468 net6name(&pa->pa_addr.sin6_addr,
469 &pa->pa_subnetmask));
470 fprintf(fp," %-5d", pa->pa_addr.sin6_scope_id);
472 if (v->uv_flags & MIFF_REGISTER)
473 fprintf(fp, " REGISTER");
474 if (v->uv_flags & VIFF_DISABLED)
475 fprintf(fp, " DISABLED");
476 if (v->uv_flags & VIFF_NOLISTENER)
477 fprintf(fp, " NOLISTENER");
478 if (v->uv_flags & VIFF_DOWN)
479 fprintf(fp, " DOWN");
480 if (v->uv_flags & VIFF_DR)
482 if (v->uv_flags & VIFF_PIM_NBR)
484 if (v->uv_flags & VIFF_QUERIER)
486 #if 0 /* impossible */
487 if (v->uv_flags & VIFF_DVMRP_NBR)
489 fprintf(fp, " DVMRP");
492 if (v->uv_flags & VIFF_NONBRS)
493 fprintf(fp, " NO-NBR");
498 fprintf(fp, " %3s %6s ", "", "");
499 fprintf(fp, "Timers: PIM hello = %d:%02d, MLD query = %d:%02d\n",
500 v->uv_pim_hello_timer / 60, v->uv_pim_hello_timer % 60,
501 v->uv_gq_timer / 60, v->uv_gq_timer % 60);
514 fprintf(fp, "PIM Neighbor List\n");
515 fprintf(fp, " %-3s %6s %-40s %-5s\n",
516 "Mif", "PhyIF", "Address", "Timer");
518 for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
519 if ((n = v->uv_pim_neighbors) != NULL) {
522 fprintf(fp, " %-3u %6s", vifi,
523 (v->uv_flags & MIFF_REGISTER) ? "regist":
525 for (; n != NULL; n = n->next) {
529 fprintf(fp, " %3s %6s", "", "");
530 fprintf(fp, " %-40s %-5u\n",
531 inet6_fmt(&n->address.sin6_addr),
548 fprintf(fp, "MLD Querier List\n");
549 fprintf(fp, " %-3s %6s %-40s %-5s %15s\n",
550 "Mif", "PhyIF", "Address", "Timer", "Last");
553 for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
555 fprintf(fp, " %-3u %6s", vifi,
556 (v->uv_flags & MIFF_REGISTER) ? "regist":
559 fprintf(fp, " %-40s %5lu %15s\n",
560 sa6_fmt(&v->uv_querier->al_addr),
561 (u_long)v->uv_querier->al_timer,
562 sec2str(now - v->uv_querier->al_ctime));
570 * Log errors and other messages to the system log daemon and to stderr,
571 * according to the severity of the message and the current debug level. For
572 * errors of severity LOG_ERR or worse, terminate the program.
576 log(int severity, int syserr, char *format,...)
579 static char fmt[211] = "warning - ";
584 va_start(ap, format);
588 log(severity, syserr, format, va_alist)
595 static char fmt[311] = "warning - ";
603 vsprintf(&fmt[10], format, ap);
605 msg = (severity == LOG_WARNING) ? fmt : &fmt[10];
608 * Log to stderr if we haven't forked yet and it's a warning or worse, or
609 * if we're debugging.
611 if (debug || severity <= LOG_WARNING)
614 FILE *fp = log_fp ? log_fp : stderr;
616 gettimeofday(&now, NULL);
617 t = (time_t)now.tv_sec;
618 thyme = localtime(&t);
620 fprintf(fp, "%s: ", progname);
621 fprintf(fp, "%02d:%02d:%02d.%03ld %s", thyme->tm_hour,
622 thyme->tm_min, thyme->tm_sec, (long int)now.tv_usec / 1000,
627 if (syserr < sys_nerr)
628 fprintf(fp, ": %s\n", sys_errlist[syserr]);
630 fprintf(fp, ": errno %d\n", syserr);
634 * Always log things that are worse than warnings, no matter what the
635 * log_nmsgs rate limiter says. Only count things worse than debugging in
636 * the rate limiter (since if you put daemon.debug in syslog.conf you
637 * probably actually want to log the debugging messages so they shouldn't
640 if ((severity < LOG_WARNING) || (log_nmsgs < LOG_MAX_MSGS))
642 if (severity < LOG_DEBUG)
647 syslog(severity, "%s: %m", msg);
650 syslog(severity, "%s", msg);
653 if (severity <= LOG_ERR)
657 /* TODO: format the output for better readability */
663 register mrtentry_t *r;
664 register vifi_t vifi;
666 u_int number_of_cache_mirrors = 0;
667 u_int number_of_groups = 0;
668 char joined_oifs[(sizeof(if_set) << 3) + 1];
669 char asserted_oifs[(sizeof(if_set) << 3) + 1];
671 kernel_cache_t *kernel_cache;
672 char oifs[(sizeof(if_set) << 3) + 1];
673 char pruned_oifs[(sizeof(if_set) << 3) + 1];
674 char leaves_oifs[(sizeof(if_set) << 3) + 1];
675 char incoming_iif[(sizeof(if_set) << 3) + 1];
677 fprintf(fp, "Multicast Routing Table\n%s",
678 " Source Group RP-addr Flags\n");
680 /* TODO: remove the dummy 0:: group (first in the chain) */
681 for (g = grplist->next; g != (grpentry_t *) NULL; g = g->next)
684 if ((r = g->grp_route) != (mrtentry_t *) NULL)
686 if (r->flags & MRTF_KERNEL_CACHE)
688 for (kernel_cache = r->kernel_cache;
689 kernel_cache != (kernel_cache_t *) NULL;
690 kernel_cache = kernel_cache->next)
691 number_of_cache_mirrors++;
694 /* Print the (*,G) routing info */
695 fprintf(fp, "---------------------------(*,G)----------------------------\n");
696 fprintf(fp, " %-15s", "IN6ADDR_ANY");
697 fprintf(fp, " %-15s", inet6_fmt(&g->group.sin6_addr));
698 fprintf(fp, " %-15s",
699 g->active_rp_grp ? inet6_fmt(&g->rpaddr.sin6_addr) : "NULL");
701 for (vifi = 0; vifi < numvifs; vifi++)
704 IF_ISSET(vifi, &r->oifs) ? 'o' : '.';
706 IF_ISSET(vifi, &r->joined_oifs) ? 'j' : '.';
708 IF_ISSET(vifi, &r->pruned_oifs) ? 'p' : '.';
710 IF_ISSET(vifi, &r->leaves) ? 'l' : '.';
711 asserted_oifs[vifi] =
712 IF_ISSET(vifi, &r->asserted_oifs) ? 'a' : '.';
713 incoming_iif[vifi] = '.';
715 oifs[vifi] = 0x0; /* End of string */
716 joined_oifs[vifi] = 0x0;
717 pruned_oifs[vifi] = 0x0;
718 leaves_oifs[vifi] = 0x0;
719 asserted_oifs[vifi] = 0x0;
720 incoming_iif[vifi] = 0x0;
721 incoming_iif[r->incoming] = 'I';
723 /* TODO: don't need some of the flags */
724 if (r->flags & MRTF_SPT)
726 if (r->flags & MRTF_WC)
728 if (r->flags & MRTF_RP)
730 if (r->flags & MRTF_REGISTER)
732 if (r->flags & MRTF_IIF_REGISTER)
733 fprintf(fp, " IIF_REG");
734 if (r->flags & MRTF_NULL_OIF)
735 fprintf(fp, " NULL_OIF");
736 if (r->flags & MRTF_KERNEL_CACHE)
737 fprintf(fp, " CACHE");
738 if (r->flags & MRTF_ASSERTED)
739 fprintf(fp, " ASSERTED");
740 if (r->flags & MRTF_REG_SUPP)
741 fprintf(fp, " REG_SUPP");
742 if (r->flags & MRTF_SG)
744 if (r->flags & MRTF_PMBR)
745 fprintf(fp, " PMBR");
748 fprintf(fp, "Joined oifs: %-20s\n", joined_oifs);
749 fprintf(fp, "Pruned oifs: %-20s\n", pruned_oifs);
750 fprintf(fp, "Leaves oifs: %-20s\n", leaves_oifs);
751 fprintf(fp, "Asserted oifs: %-20s\n", asserted_oifs);
752 fprintf(fp, "Outgoing oifs: %-20s\n", oifs);
753 fprintf(fp, "Incoming : %-20s\n", incoming_iif);
755 fprintf(fp, "Upstream nbr: %s\n",
756 r->upstream ? inet6_fmt(&r->upstream->address.sin6_addr) : "NONE");
758 fprintf(fp, "\nTIMERS: Entry=%d JP=%d RS=%d Assert=%d\n",
759 r->timer, r->jp_timer, r->rs_timer, r->assert_timer);
761 fprintf(fp, " MIF 0 1 2 3 4 5 6 7 8 9\n");
762 for (vifi = 0, i = 0; vifi < numvifs && i <= numvifs / 10; i++) {
765 fprintf(fp, " %4d", i);
766 for (j = 0; j < 10 && vifi < numvifs; j++, vifi++)
767 fprintf(fp, " %3d", r->vif_timers[vifi]);
772 /* Print all (S,G) routing info */
774 for (r = g->mrtlink; r != (mrtentry_t *) NULL; r = r->grpnext)
776 fprintf(fp, "---------------------------(S,G)----------------------------\n");
777 if (r->flags & MRTF_KERNEL_CACHE)
778 number_of_cache_mirrors++;
780 /* Print the routing info */
781 fprintf(fp, " %-15s", inet6_fmt(&r->source->address.sin6_addr));
782 fprintf(fp, " %-15s", inet6_fmt(&g->group.sin6_addr));
783 fprintf(fp, " %-15s",
784 g->active_rp_grp ? inet6_fmt(&g->rpaddr.sin6_addr) : "NULL");
786 for (vifi = 0; vifi < numvifs; vifi++)
789 IF_ISSET(vifi, &r->oifs) ? 'o' : '.';
791 IF_ISSET(vifi, &r->joined_oifs) ? 'j' : '.';
793 IF_ISSET(vifi, &r->pruned_oifs) ? 'p' : '.';
795 IF_ISSET(vifi, &r->leaves) ? 'l' : '.';
796 asserted_oifs[vifi] =
797 IF_ISSET(vifi, &r->asserted_oifs) ? 'a' : '.';
798 incoming_iif[vifi] = '.';
800 oifs[vifi] = 0x0; /* End of string */
801 joined_oifs[vifi] = 0x0;
802 pruned_oifs[vifi] = 0x0;
803 leaves_oifs[vifi] = 0x0;
804 asserted_oifs[vifi] = 0x0;
805 incoming_iif[vifi] = 0x0;
806 incoming_iif[r->incoming] = 'I';
808 /* TODO: don't need some of the flags */
809 if (r->flags & MRTF_SPT)
811 if (r->flags & MRTF_WC)
813 if (r->flags & MRTF_RP)
815 if (r->flags & MRTF_REGISTER)
817 if (r->flags & MRTF_IIF_REGISTER)
818 fprintf(fp, " IIF_REG");
819 if (r->flags & MRTF_NULL_OIF)
820 fprintf(fp, " NULL_OIF");
821 if (r->flags & MRTF_KERNEL_CACHE)
822 fprintf(fp, " CACHE");
823 if (r->flags & MRTF_ASSERTED)
824 fprintf(fp, " ASSERTED");
825 if (r->flags & MRTF_REG_SUPP)
826 fprintf(fp, " REG_SUPP");
827 if (r->flags & MRTF_SG)
829 if (r->flags & MRTF_PMBR)
830 fprintf(fp, " PMBR");
833 fprintf(fp, "Joined oifs: %-20s\n", joined_oifs);
834 fprintf(fp, "Pruned oifs: %-20s\n", pruned_oifs);
835 fprintf(fp, "Leaves oifs: %-20s\n", leaves_oifs);
836 fprintf(fp, "Asserted oifs: %-20s\n", asserted_oifs);
837 fprintf(fp, "Outgoing oifs: %-20s\n", oifs);
838 fprintf(fp, "Incoming : %-20s\n", incoming_iif);
840 fprintf(fp, "Upstream nbr: %s\n",
841 r->upstream ? inet6_fmt(&r->upstream->address.sin6_addr) : "NONE");
843 fprintf(fp, "\nTIMERS: Entry=%d JP=%d RS=%d Assert=%d\n",
844 r->timer, r->jp_timer, r->rs_timer, r->assert_timer);
846 fprintf(fp, " MIF 0 1 2 3 4 5 6 7 8 9\n");
847 for (vifi = 0, i = 0; vifi < numvifs && i <= numvifs / 10; i++) {
850 fprintf(fp, " %4d", i);
851 for (j = 0; j < 10 && vifi < numvifs; j++, vifi++)
852 fprintf(fp, " %3d", r->vif_timers[vifi]);
856 } /* for all groups */
858 /* Print the (*,*,R) routing entries */
859 fprintf(fp, "--------------------------(*,*,RP)--------------------------\n");
860 for (rp = cand_rp_list; rp != (cand_rp_t *) NULL; rp = rp->next)
862 if ((r = rp->rpentry->mrtlink) != (mrtentry_t *) NULL)
864 if (r->flags & MRTF_KERNEL_CACHE)
866 for (kernel_cache = r->kernel_cache;
867 kernel_cache != (kernel_cache_t *) NULL;
868 kernel_cache = kernel_cache->next)
869 number_of_cache_mirrors++;
872 /* Print the (*,*,RP) routing info */
873 fprintf(fp, " RP = %-15s", inet6_fmt(&r->source->address.sin6_addr));
874 fprintf(fp, " %-15s", "IN6ADDR_ANY");
876 for (vifi = 0; vifi < numvifs; vifi++)
879 IF_ISSET(vifi, &r->oifs) ? 'o' : '.';
881 IF_ISSET(vifi, &r->joined_oifs) ? 'j' : '.';
883 IF_ISSET(vifi, &r->pruned_oifs) ? 'p' : '.';
885 IF_ISSET(vifi, &r->leaves) ? 'l' : '.';
886 asserted_oifs[vifi] =
887 IF_ISSET(vifi, &r->asserted_oifs) ? 'a' : '.';
888 incoming_iif[vifi] = '.';
890 oifs[vifi] = 0x0; /* End of string */
891 joined_oifs[vifi] = 0x0;
892 pruned_oifs[vifi] = 0x0;
893 leaves_oifs[vifi] = 0x0;
894 asserted_oifs[vifi] = 0x0;
895 incoming_iif[vifi] = 0x0;
896 incoming_iif[r->incoming] = 'I';
898 /* TODO: don't need some of the flags */
899 if (r->flags & MRTF_SPT)
901 if (r->flags & MRTF_WC)
903 if (r->flags & MRTF_RP)
905 if (r->flags & MRTF_REGISTER)
907 if (r->flags & MRTF_IIF_REGISTER)
908 fprintf(fp, " IIF_REG");
909 if (r->flags & MRTF_NULL_OIF)
910 fprintf(fp, " NULL_OIF");
911 if (r->flags & MRTF_KERNEL_CACHE)
912 fprintf(fp, " CACHE");
913 if (r->flags & MRTF_ASSERTED)
914 fprintf(fp, " ASSERTED");
915 if (r->flags & MRTF_REG_SUPP)
916 fprintf(fp, " REG_SUPP");
917 if (r->flags & MRTF_SG)
919 if (r->flags & MRTF_PMBR)
920 fprintf(fp, " PMBR");
923 fprintf(fp, "Joined oifs: %-20s\n", joined_oifs);
924 fprintf(fp, "Pruned oifs: %-20s\n", pruned_oifs);
925 fprintf(fp, "Leaves oifs: %-20s\n", leaves_oifs);
926 fprintf(fp, "Asserted oifs: %-20s\n", asserted_oifs);
927 fprintf(fp, "Outgoing oifs: %-20s\n", oifs);
928 fprintf(fp, "Incoming : %-20s\n", incoming_iif);
930 fprintf(fp, "\nTIMERS: Entry=%d JP=%d RS=%d Assert=%d\n",
931 r->timer, r->jp_timer, r->rs_timer, r->assert_timer);
933 fprintf(fp, " MIF 0 1 2 3 4 5 6 7 8 9\n");
934 for (vifi = 0, i = 0; vifi < numvifs && i <= numvifs / 10; i++) {
937 fprintf(fp, " %4d", i);
938 for (j = 0; j < 10 && vifi < numvifs; j++, vifi++)
939 fprintf(fp, " %3d", r->vif_timers[vifi]);
943 } /* For all (*,*,RP) */
945 fprintf(fp, "Number of Groups: %u\n", number_of_groups);
946 fprintf(fp, "Number of Cache MIRRORs: %u\n\n", number_of_cache_mirrors);
950 /* TODO: modify the output for better redability */
952 * Dumps the local Cand-RP-set
959 rp_grp_entry_t *rp_grp_entry;
960 grp_mask_t *grp_mask;
962 fprintf(fp, "---------------------------RP-Set----------------------------\n");
963 fprintf(fp, "Current BSR address: %s Prio: %d Timeout: %d\n",
964 inet6_fmt(&curr_bsr_address.sin6_addr), curr_bsr_priority,
965 pim_bootstrap_timer);
966 fprintf(fp, "%-40s %-3s Group prefix Prio Hold Age\n",
969 for (rp = cand_rp_list; rp != (cand_rp_t *) NULL; rp = rp->next)
972 fprintf(fp, "%-40s %-3d ",
973 inet6_fmt(&rp->rpentry->address.sin6_addr),
974 rp->rpentry->incoming);
975 if ((rp_grp_entry = rp->rp_grp_next) != (rp_grp_entry_t *) NULL)
977 grp_mask = rp_grp_entry->group;
978 fprintf(fp, "%-16.16s %-4u %-4u %-3u\n",
979 net6name(&grp_mask->group_addr.sin6_addr,
980 &grp_mask->group_mask),
981 rp_grp_entry->priority, rp_grp_entry->advholdtime,
982 rp_grp_entry->holdtime);
984 for (rp_grp_entry = rp_grp_entry->rp_grp_next;
985 rp_grp_entry != (rp_grp_entry_t *) NULL;
986 rp_grp_entry = rp_grp_entry->rp_grp_next)
988 grp_mask = rp_grp_entry->group;
989 fprintf(fp, "%59.16s %-4u %-4u %-3u\n", /* XXX: hardcoding */
990 net6name(&grp_mask->group_addr.sin6_addr,
991 &grp_mask->group_mask),
992 rp_grp_entry->priority,
993 rp_grp_entry->advholdtime, rp_grp_entry->holdtime);