]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/pim6sd/debug.c
beforeinstall -> SCRIPTS.
[FreeBSD/FreeBSD.git] / usr.sbin / pim6sd / debug.c
1 /*
2  *  Copyright (c) 1998 by the University of Southern California.
3  *  All rights reserved.
4  *
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.
17  *
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
23  *  NON-INFRINGEMENT.
24  *
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.
29  *
30  *  Other copyrights might apply to parts of this software and are so
31  *  noted when applicable.
32  */
33 /*
34  *  Questions concerning this software should be directed to
35  *  Mickael Hoerdt (hoerdt@clarinet.u-strasbg.fr) LSIIT Strasbourg.
36  *
37  */
38 /*
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".
42  */
43 /*
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".
47  *
48  */
49 /*
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".
53  *
54  * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
55  * Leland Stanford Junior University.
56  *
57  * $FreeBSD$
58  */
59
60 #include <stdio.h>
61 #include <syslog.h>
62 #include <sys/param.h>
63 #include <sys/types.h>
64 #include <sys/socket.h>
65 #include <sys/time.h>
66 #include <errno.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"
73 #include "defs.h"
74 #include "pimd.h"
75 #include "debug.h"
76 #include "mrt.h"
77 #include "vif.h"
78 #include "rp.h"
79 #include "inet6.h"
80
81 #ifdef __STDC__
82 #include <stdarg.h>
83 #else
84 #include <varargs.h>
85 #endif
86
87 extern char    *progname;
88
89 int             log_nmsgs = 0;
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;
95
96 static char *sec2str __P((time_t));
97
98 static char *
99 sec2str(total)
100         time_t total;
101 {
102         static char result[256];
103         int days, hours, mins, secs;
104         int first = 1;
105         char *p = result;
106
107         days = total / 3600 / 24;
108         hours = (total / 3600) % 24;
109         mins = (total / 60) % 60;
110         secs = total % 60;
111
112         if (days) {
113                 first = 0;
114                 p += sprintf(p, "%dd", days);
115         }
116         if (!first || hours) {
117                 first = 0;
118                 p += sprintf(p, "%dh", hours);
119         }
120         if (!first || mins) {
121                 first = 0;
122                 p += sprintf(p, "%dm", mins);
123         }
124         sprintf(p, "%ds", secs);
125
126         return(result);
127 }
128
129 char           *
130 packet_kind(proto, type, code)
131     u_int           proto,
132                     type,
133                     code;
134 {
135     static char     unknown[60];
136
137     switch (proto)
138     {
139     case IPPROTO_ICMPV6:
140         switch (type)
141         {
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     ";
148         default:
149             sprintf(unknown,
150                     "UNKNOWN ICMPv6 message: type = 0x%02x, code = 0x%02x ",
151                     type, code);
152             return unknown;
153         }
154
155     case IPPROTO_PIM:           /* PIM v2 */
156         switch (type)
157         {
158         case PIM_V2_HELLO:
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         ";
168         case PIM_V2_ASSERT:
169             return "PIM v2 Assert            ";
170         case PIM_V2_GRAFT:
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.     ";
176         default:
177             sprintf(unknown, "UNKNOWN PIM v2 message type =%3d ", type);
178             return unknown;
179         }
180     default:
181         sprintf(unknown, "UNKNOWN proto =%3d               ", proto);
182         return unknown;
183     }
184 }
185
186
187 /*
188  * Used for debugging particular type of messages.
189  */
190 int
191 debug_kind(proto, type, code)
192     u_int           proto,
193                     type,
194                     code;
195 {
196     switch (proto)
197     {
198     case IPPROTO_ICMPV6:
199         switch (type)
200         {
201         case MLD6_LISTENER_QUERY:
202             return DEBUG_MLD;
203         case MLD6_LISTENER_REPORT:
204             return DEBUG_MLD;
205         case MLD6_LISTENER_DONE:
206             return DEBUG_MLD;
207         default:
208             return DEBUG_MLD;
209         }
210     case IPPROTO_PIM:           /* PIM v2 */
211         /* TODO: modify? */
212         switch (type)
213         {
214         case PIM_V2_HELLO:
215             return DEBUG_PIM;
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:
221             return DEBUG_PIM;
222         case PIM_V2_BOOTSTRAP:
223             return DEBUG_PIM_BOOTSTRAP;
224         case PIM_V2_ASSERT:
225             return DEBUG_PIM;
226         case PIM_V2_GRAFT:
227             return DEBUG_PIM;
228         case PIM_V2_GRAFT_ACK:
229             return DEBUG_PIM;
230         case PIM_V2_CAND_RP_ADV:
231             return DEBUG_PIM_CAND_RP;
232         default:
233             return DEBUG_PIM;
234         }
235     default:
236         return 0;
237     }
238     return 0;
239 }
240
241
242 /*
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.
247  */
248 int
249 log_level(proto, type, code)
250     u_int           proto,
251                     type,
252                     code;
253 {
254     switch (proto)
255     {
256     case IPPROTO_ICMPV6:
257         switch (type)
258         {
259         default:
260             return LOG_WARNING;
261         }
262
263     case IPPROTO_PIM:
264     /* PIM v2 */
265         switch (type)
266         {
267         default:
268             return LOG_INFO;
269         }
270     default:
271         return LOG_WARNING;
272     }
273
274     return LOG_WARNING;
275 }
276
277
278 /*
279  * Dump internal data structures to stderr.
280  */
281 /*
282  * TODO: currently not used void dump(int i) { dump_vifs(stderr);
283  * dump_pim_mrt(stderr); }
284  */
285
286 /*
287  * Dump internal data structures to a file.
288  */
289 void
290 fdump(i)
291     int             i;
292 {
293     FILE           *fp;
294     fp = fopen(dumpfilename, "w");
295     if (fp != NULL)
296     {
297         dump_vifs(fp);
298         dump_nbrs(fp);
299         dump_mldqueriers(fp);
300         dump_pim_mrt(fp);
301         dump_rp_set(fp);
302         (void) fclose(fp);
303     }
304 }
305
306 /* TODO: dummy, to be used in the future. */
307 /*
308  * Dump local cache contents to a file.
309  */
310 void
311 cdump(i)
312     int             i;
313 {
314     FILE           *fp;
315
316     fp = fopen(cachefilename, "w");
317     if (fp != NULL)
318     {
319         /*
320          * TODO: implement it: dump_cache(fp);
321          */
322         (void) fclose(fp);
323     }
324 }
325
326 void
327 dump_stat()
328 {
329         FILE *fp;
330         vifi_t vifi;
331         register struct uvif *v;
332
333         fp = fopen(statfilename, "w");
334         if (fp == NULL) {
335                 log(LOG_WARNING, errno, "dump_stat: can't open file(%s)",
336                     statfilename);
337                 return;
338         }
339
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)
344                         continue;
345 #endif
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);
355
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);
364
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);
371
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);
378
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);
383
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);
392         }
393
394         fprintf(fp, "\npim6sd interface independent statistics\n");
395
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);
406
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);
413
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);
418
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);
425
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);
436
437         fclose(fp);
438 }
439
440 void
441 dump_vifs(fp)
442     FILE           *fp;
443 {
444     vifi_t          vifi;
445     register struct uvif *v;
446     struct phaddr  *pa;
447
448     fprintf(fp, "\nMulticast Interface Table\n %-4s %-6s %-43s %5s %-14s\n",
449             "Mif", " PhyIF", "Local-Address/Prefixlen","Scope", "Flags");
450
451     for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v)
452     {
453         int firstaddr = 1;
454         for (pa = v->uv_addrs; pa; pa = pa->pa_next)
455         {
456             if (!firstaddr)
457             {
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);
462                 continue;
463             }
464
465             firstaddr = 0;
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);
471
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)
481                 fprintf(fp, " DR");
482             if (v->uv_flags & VIFF_PIM_NBR)
483                 fprintf(fp, " PIM");
484             if (v->uv_flags & VIFF_QUERIER)
485                 fprintf(fp, " QRY");
486 #if 0                           /* impossible */
487             if (v->uv_flags & VIFF_DVMRP_NBR)
488             {
489                 fprintf(fp, " DVMRP");
490             }
491 #endif
492             if (v->uv_flags & VIFF_NONBRS)
493                 fprintf(fp, " NO-NBR");
494
495             fprintf(fp, "\n");
496         }
497
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);
502     }
503     fprintf(fp, "\n");
504 }
505
506 void
507 dump_nbrs(fp)
508         FILE *fp;
509 {
510         struct uvif *v;
511         vifi_t vifi;
512         pim_nbr_entry_t *n;
513
514         fprintf(fp, "PIM Neighbor List\n");
515         fprintf(fp, " %-3s %6s %-40s %-5s\n",
516                 "Mif", "PhyIF", "Address", "Timer");
517
518         for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
519                 if ((n = v->uv_pim_neighbors) != NULL) {
520                         int first = 1;
521
522                         fprintf(fp, " %-3u %6s", vifi,
523                                 (v->uv_flags & MIFF_REGISTER) ? "regist":
524                                 v->uv_name);
525                         for (; n != NULL; n = n->next) {
526                                 if (first)
527                                         first = 0;
528                                 else
529                                         fprintf(fp, " %3s %6s", "", "");
530                                 fprintf(fp, " %-40s %-5u\n",
531                                         inet6_fmt(&n->address.sin6_addr),
532                                         n->timer);
533                         }
534                 }
535         }
536
537         fprintf(fp, "\n");
538 }
539
540 void
541 dump_mldqueriers(fp)
542         FILE *fp;
543 {
544         struct uvif *v;
545         vifi_t vifi;
546         time_t now;
547
548         fprintf(fp, "MLD Querier List\n");
549         fprintf(fp, " %-3s %6s %-40s %-5s %15s\n",
550                 "Mif", "PhyIF", "Address", "Timer", "Last");
551         (void)time(&now);
552
553         for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
554                 if (v->uv_querier) {
555                         fprintf(fp, " %-3u %6s", vifi,
556                                 (v->uv_flags & MIFF_REGISTER) ? "regist":
557                                 v->uv_name);
558
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));
563                 }
564         }
565
566         fprintf(fp, "\n");
567
568
569 /*
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.
573  */
574 #ifdef __STDC__
575 void
576 log(int severity, int syserr, char *format,...)
577 {
578     va_list         ap;
579     static char     fmt[211] = "warning - ";
580     char           *msg;
581     struct timeval  now;
582     struct tm      *thyme;
583
584     va_start(ap, format);
585 #else
586 /* VARARGS3 */
587 void
588 log(severity, syserr, format, va_alist)
589     int             severity,
590                     syserr;
591     char           *format;
592 va_dcl
593 {
594     va_list         ap;
595     static char     fmt[311] = "warning - ";
596     char           *msg;
597     char            tbuf[20];
598     struct timeval  now;
599     struct tm      *thyme;
600
601     va_start(ap);
602 #endif
603     vsprintf(&fmt[10], format, ap);
604     va_end(ap);
605     msg = (severity == LOG_WARNING) ? fmt : &fmt[10];
606
607     /*
608      * Log to stderr if we haven't forked yet and it's a warning or worse, or
609      * if we're debugging.
610      */
611     if (debug || severity <= LOG_WARNING)
612     {
613         time_t t;
614         FILE *fp = log_fp ? log_fp : stderr;
615
616         gettimeofday(&now, NULL);
617         t = (time_t)now.tv_sec;
618         thyme = localtime(&t);
619         if (!debug)
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,
623                 msg);
624         if (syserr == 0)
625             fprintf(fp, "\n");
626         else
627             if (syserr < sys_nerr)
628                 fprintf(fp, ": %s\n", sys_errlist[syserr]);
629             else
630                 fprintf(fp, ": errno %d\n", syserr);
631     }
632
633     /*
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
638      * be rate-limited)
639      */
640     if ((severity < LOG_WARNING) || (log_nmsgs < LOG_MAX_MSGS))
641     {
642         if (severity < LOG_DEBUG)
643             log_nmsgs++;
644         if (syserr != 0)
645         {
646             errno = syserr;
647             syslog(severity, "%s: %m", msg);
648         }
649         else
650             syslog(severity, "%s", msg);
651     }
652
653     if (severity <= LOG_ERR)
654         exit(-1);
655 }
656
657 /* TODO: format the output for better readability */
658 void
659 dump_pim_mrt(fp)
660     FILE           *fp;
661 {
662     grpentry_t     *g;
663     register mrtentry_t *r;
664     register vifi_t vifi;
665     int i;
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];
670     cand_rp_t      *rp;
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];
676
677     fprintf(fp, "Multicast Routing Table\n%s",
678             " Source          Group           RP-addr         Flags\n");
679
680     /* TODO: remove the dummy 0:: group (first in the chain) */
681     for (g = grplist->next; g != (grpentry_t *) NULL; g = g->next)
682     {
683         number_of_groups++;
684         if ((r = g->grp_route) != (mrtentry_t *) NULL)
685         {
686             if (r->flags & MRTF_KERNEL_CACHE)
687             {
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++;
692             }
693
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");
700
701             for (vifi = 0; vifi < numvifs; vifi++)
702             {
703                 oifs[vifi] =
704                     IF_ISSET(vifi, &r->oifs) ? 'o' : '.';
705                 joined_oifs[vifi] =
706                     IF_ISSET(vifi, &r->joined_oifs) ? 'j' : '.';
707                 pruned_oifs[vifi] =
708                     IF_ISSET(vifi, &r->pruned_oifs) ? 'p' : '.';
709                 leaves_oifs[vifi] =
710                     IF_ISSET(vifi, &r->leaves) ? 'l' : '.';
711                 asserted_oifs[vifi] =
712                     IF_ISSET(vifi, &r->asserted_oifs) ? 'a' : '.';
713                 incoming_iif[vifi] = '.';
714             }
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';
722
723             /* TODO: don't need some of the flags */
724             if (r->flags & MRTF_SPT)
725                 fprintf(fp, " SPT");
726             if (r->flags & MRTF_WC)
727                 fprintf(fp, " WC");
728             if (r->flags & MRTF_RP)
729                 fprintf(fp, " RP");
730             if (r->flags & MRTF_REGISTER)
731                 fprintf(fp, " REG");
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)
743                 fprintf(fp, " SG");
744             if (r->flags & MRTF_PMBR)
745                 fprintf(fp, " PMBR");
746             fprintf(fp, "\n");
747
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);
754         
755             fprintf(fp, "Upstream nbr: %s\n",
756                     r->upstream ? inet6_fmt(&r->upstream->address.sin6_addr) : "NONE");
757
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);
760
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++) {
763                     int j;
764
765                     fprintf(fp, " %4d", i);
766                     for (j = 0; j < 10 && vifi < numvifs; j++, vifi++)
767                             fprintf(fp, " %3d", r->vif_timers[vifi]);
768                     fprintf(fp, "\n");
769             }
770         }
771
772         /* Print all (S,G) routing info */
773
774         for (r = g->mrtlink; r != (mrtentry_t *) NULL; r = r->grpnext)
775         {
776             fprintf(fp, "---------------------------(S,G)----------------------------\n");
777             if (r->flags & MRTF_KERNEL_CACHE)
778                 number_of_cache_mirrors++;
779
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");
785
786             for (vifi = 0; vifi < numvifs; vifi++)
787             {
788                 oifs[vifi] =
789                 IF_ISSET(vifi, &r->oifs) ? 'o' : '.';
790                     joined_oifs[vifi] =
791                 IF_ISSET(vifi, &r->joined_oifs) ? 'j' : '.';
792                         pruned_oifs[vifi] =
793                 IF_ISSET(vifi, &r->pruned_oifs) ? 'p' : '.';
794                 leaves_oifs[vifi] =
795                 IF_ISSET(vifi, &r->leaves) ? 'l' : '.';
796                     asserted_oifs[vifi] =
797                 IF_ISSET(vifi, &r->asserted_oifs) ? 'a' : '.';
798                 incoming_iif[vifi] = '.';
799             }
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';
807
808             /* TODO: don't need some of the flags */
809             if (r->flags & MRTF_SPT)
810                 fprintf(fp, " SPT");
811             if (r->flags & MRTF_WC)
812                 fprintf(fp, " WC");
813             if (r->flags & MRTF_RP)
814                 fprintf(fp, " RP");
815             if (r->flags & MRTF_REGISTER)
816                 fprintf(fp, " REG");
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)
828                 fprintf(fp, " SG");
829             if (r->flags & MRTF_PMBR)
830                 fprintf(fp, " PMBR");
831             fprintf(fp, "\n");
832
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);
839
840             fprintf(fp, "Upstream nbr: %s\n",
841                     r->upstream ? inet6_fmt(&r->upstream->address.sin6_addr) : "NONE");
842
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);
845
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++) {
848                     int j;
849
850                     fprintf(fp, " %4d", i);
851                     for (j = 0; j < 10 && vifi < numvifs; j++, vifi++)
852                             fprintf(fp, " %3d", r->vif_timers[vifi]);
853                     fprintf(fp, "\n");
854             }
855         }
856     }                           /* for all groups */
857
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)
861     {
862         if ((r = rp->rpentry->mrtlink) != (mrtentry_t *) NULL)
863         {
864             if (r->flags & MRTF_KERNEL_CACHE)
865             {
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++;
870             }
871
872             /* Print the (*,*,RP) routing info */
873             fprintf(fp, " RP = %-15s", inet6_fmt(&r->source->address.sin6_addr));
874             fprintf(fp, " %-15s", "IN6ADDR_ANY");
875
876             for (vifi = 0; vifi < numvifs; vifi++)
877             {
878                 oifs[vifi] =
879                     IF_ISSET(vifi, &r->oifs) ? 'o' : '.';
880                 joined_oifs[vifi] =
881                     IF_ISSET(vifi, &r->joined_oifs) ? 'j' : '.';
882                 pruned_oifs[vifi] =
883                     IF_ISSET(vifi, &r->pruned_oifs) ? 'p' : '.';
884                 leaves_oifs[vifi] =
885                     IF_ISSET(vifi, &r->leaves) ? 'l' : '.';
886                 asserted_oifs[vifi] =
887                     IF_ISSET(vifi, &r->asserted_oifs) ? 'a' : '.';
888                 incoming_iif[vifi] = '.';
889             }
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';
897
898             /* TODO: don't need some of the flags */
899             if (r->flags & MRTF_SPT)
900                 fprintf(fp, " SPT");
901             if (r->flags & MRTF_WC)
902                 fprintf(fp, " WC");
903             if (r->flags & MRTF_RP)
904                 fprintf(fp, " RP");
905             if (r->flags & MRTF_REGISTER)
906                 fprintf(fp, " REG");
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)
918                 fprintf(fp, " SG");
919             if (r->flags & MRTF_PMBR)
920                 fprintf(fp, " PMBR");
921             fprintf(fp, "\n");
922
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);
929
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);
932
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++) {
935                     int j;
936
937                     fprintf(fp, " %4d", i);
938                     for (j = 0; j < 10 && vifi < numvifs; j++, vifi++)
939                             fprintf(fp, " %3d", r->vif_timers[vifi]);
940                     fprintf(fp, "\n");
941             }
942         }
943     }                           /* For all (*,*,RP) */
944
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);
947 }
948
949
950 /* TODO: modify the output for better redability */
951 /*
952  * Dumps the local Cand-RP-set
953  */
954 int
955 dump_rp_set(fp)
956     FILE           *fp;
957 {
958     cand_rp_t      *rp;
959     rp_grp_entry_t *rp_grp_entry;
960     grp_mask_t     *grp_mask;
961
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",
967             "RP-address", "IN");
968
969     for (rp = cand_rp_list; rp != (cand_rp_t *) NULL; rp = rp->next)
970     {
971
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)
976         {
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);
983
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)
987             {
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);
994             }
995         }
996     }
997     return (TRUE);
998 }