]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/pim6dd/debug.c
This commit was generated by cvs2svn to compensate for changes in r71756,
[FreeBSD/FreeBSD.git] / usr.sbin / pim6dd / 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  *  Pavlin Ivanov Radoslavov (pavlin@catarina.usc.edu)
36  *
37  *  $Id: debug.c,v 1.10 2000/10/05 22:27:07 itojun Exp $
38  */
39 /*
40  * Part of this program has been derived from mrouted.
41  * The mrouted program is covered by the license in the accompanying file
42  * named "LICENSE.mrouted".
43  *
44  * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
45  * Leland Stanford Junior University.
46  *
47  * $FreeBSD$
48  */
49
50 #include "defs.h"
51
52
53 #ifdef __STDC__
54 #include <stdarg.h>
55 #else
56 #include <varargs.h>
57 #endif
58
59 extern int haveterminal;
60 extern char *progname;
61
62 int log_nmsgs = 0;
63 unsigned long debug = 0x00000000;        /* If (long) is smaller than
64                                           * 4 bytes, then we are in
65                                           * trouble.
66                                           */
67 static char dumpfilename[] = _PATH_PIM6D_DUMP;
68 static char cachefilename[] = _PATH_PIM6D_CACHE; /* TODO: notused */
69
70 static char *sec2str __P((time_t));
71
72 static char *
73 sec2str(total)
74         time_t total;
75 {
76         static char result[256];
77         int days, hours, mins, secs;
78         int first = 1;
79         char *p = result;
80
81         days = total / 3600 / 24;
82         hours = (total / 3600) % 24;
83         mins = (total / 60) % 60;
84         secs = total % 60;
85
86         if (days) {
87                 first = 0;
88                 p += sprintf(p, "%dd", days);
89         }
90         if (!first || hours) {
91                 first = 0;
92                 p += sprintf(p, "%dh", hours);
93         }
94         if (!first || mins) {
95                 first = 0;
96                 p += sprintf(p, "%dm", mins);
97         }
98         sprintf(p, "%ds", secs);
99
100         return(result);
101 }
102
103 char *
104 packet_kind(proto, type, code)
105     u_int proto, type, code;
106 {
107     static char unknown[60];
108
109     switch (proto) {
110      case IPPROTO_ICMPV6:
111         switch (type) {
112          case MLD6_LISTENER_QUERY:      return "Multicast Listener Query    ";
113          case MLD6_LISTENER_REPORT:     return "Multicast Listener Report   ";
114          case MLD6_LISTENER_DONE:       return "Multicast Listener Done     ";
115          default:
116             sprintf(unknown,
117                     "UNKNOWN ICMPv6 message: type = 0x%02x, code = 0x%02x ",
118                     type, code);
119             return unknown;
120         }
121
122      case IPPROTO_PIM:    /* PIM v2 */
123         switch (type) {
124         case PIM_V2_HELLO:             return "PIM v2 Hello             ";
125         case PIM_V2_REGISTER:          return "PIM v2 Register          ";
126         case PIM_V2_REGISTER_STOP:     return "PIM v2 Register_Stop     ";
127         case PIM_V2_JOIN_PRUNE:        return "PIM v2 Join/Prune        ";
128         case PIM_V2_BOOTSTRAP:         return "PIM v2 Bootstrap         ";
129         case PIM_V2_ASSERT:            return "PIM v2 Assert            ";
130         case PIM_V2_GRAFT:             return "PIM-DM v2 Graft          ";
131         case PIM_V2_GRAFT_ACK:         return "PIM-DM v2 Graft_Ack      ";
132         case PIM_V2_CAND_RP_ADV:       return "PIM v2 Cand. RP Adv.     ";
133         default:
134             sprintf(unknown,      "UNKNOWN PIM v2 message type =%3d ", type);
135             return unknown;
136         }
137     default:
138         sprintf(unknown,          "UNKNOWN proto =%3d               ", proto);
139         return unknown;
140     }
141 }
142
143
144 /*
145  * Used for debugging particular type of messages.
146  */
147 int
148 debug_kind(proto, type, code)
149     u_int proto, type, code;
150 {
151     switch (proto) {
152     case IPPROTO_ICMPV6:
153         switch (type) {
154         case MLD6_LISTENER_QUERY:       return DEBUG_MLD;
155         case MLD6_LISTENER_REPORT:      return DEBUG_MLD;
156         case MLD6_LISTENER_DONE:        return DEBUG_MLD;
157         default:                           return DEBUG_MLD;
158         }
159     case IPPROTO_PIM:   /* PIM v2 */
160         /* TODO: modify? */
161         switch (type) {
162         case PIM_V2_HELLO:             return DEBUG_PIM;
163         case PIM_V2_REGISTER:          return DEBUG_PIM_REGISTER;
164         case PIM_V2_REGISTER_STOP:     return DEBUG_PIM_REGISTER;
165         case PIM_V2_JOIN_PRUNE:        return DEBUG_PIM;
166         case PIM_V2_BOOTSTRAP:         return DEBUG_PIM_BOOTSTRAP;
167         case PIM_V2_ASSERT:            return DEBUG_PIM;
168         case PIM_V2_GRAFT:             return DEBUG_PIM;
169         case PIM_V2_GRAFT_ACK:         return DEBUG_PIM;
170         case PIM_V2_CAND_RP_ADV:       return DEBUG_PIM_CAND_RP;
171         default:                       return DEBUG_PIM;
172         }
173     default:                               return 0;
174     }
175     return 0;
176 }
177
178
179 /*
180  * Some messages are more important than others.  This routine
181  * determines the logging level at which to log a send error (often
182  * "No route to host").  This is important when there is asymmetric
183  * reachability and someone is trying to, i.e., mrinfo me periodically.
184  */
185 int
186 log_level(proto, type, code)
187     u_int proto, type, code;
188 {
189     switch (proto) {
190     case IPPROTO_ICMPV6:
191         switch (type) {
192         default:
193             return LOG_WARNING;
194         }
195         
196     case IPPROTO_PIM:
197         /* PIM v2 */
198         switch (type) {
199         default:
200             return LOG_INFO;
201         }
202     default:
203         return LOG_WARNING;
204     }
205     return LOG_WARNING;
206 }
207
208
209 /*
210  * Dump internal data structures to stderr.
211  */
212 /* TODO: currently not used
213 void 
214 dump(int i)
215 {
216     dump_vifs(stderr);
217     dump_pim_mrt(stderr);
218 }       
219 */
220
221 /*
222  * Dump internal data structures to a file.
223  */
224 void 
225 fdump(i)
226     int i;
227 {
228     FILE *fp;
229     fp = fopen(dumpfilename, "w");
230     if (fp != NULL) {
231         dump_vifs(fp);
232         dump_mldqueriers(fp);
233         dump_pim_mrt(fp);
234         dump_lcl_grp(fp);
235         (void) fclose(fp);
236     }
237 }
238
239 /* TODO: dummy, to be used in the future. */
240 /*
241  * Dump local cache contents to a file.
242  */
243 void
244 cdump(i)
245     int i;
246 {
247     FILE *fp;
248     
249     fp = fopen(cachefilename, "w");
250     if (fp != NULL) {
251       /* TODO: implement it:
252          dump_cache(fp); 
253          */
254         (void) fclose(fp);
255     }
256 }
257
258 void
259 dump_vifs(fp)
260     FILE *fp;
261 {       
262     vifi_t vifi;
263     register struct uvif *v;
264     pim_nbr_entry_t *n;
265     struct phaddr *pa;
266     int width;
267     int i;
268
269     fprintf(fp, "\nMulticast Interface Table\n %-4s %-6s %-50s %-14s %s",
270             "Mif", " PhyIF", "Local-Address/Prefixlen", "Flags",
271             "Neighbors\n");
272     
273     for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
274             int firstaddr = 1;
275             for (pa = v->uv_addrs; pa; pa = pa->pa_next) {
276                     if (!firstaddr) {
277                             fprintf(fp, "  %3s %6s %-50s\n", "", "",
278                                     net6name(&pa->pa_addr.sin6_addr,
279                                              &pa->pa_subnetmask));
280                             continue;
281                     }
282
283                     firstaddr = 0;
284                     fprintf(fp, "  %-3u %6s %-50s", vifi, v->uv_name,
285                             net6name(&pa->pa_addr.sin6_addr,
286                                      &pa->pa_subnetmask));
287                     firstaddr = 0;
288 #if 0
289                     if (v->uv_flags & MIFF_REGISTER)
290                             fprintf(fp, "%-16s ", v->uv_name);
291                     else
292                             fprintf(fp,"%-16.16s ",
293                                     net6name(&v->uv_prefix.sin6_addr,
294                                              &v->uv_subnetmask));
295 #endif
296                     width = 0;
297                     if (v->uv_flags & VIFF_DISABLED)
298                             fprintf(fp, " DISABLED");
299                     if (v->uv_flags & VIFF_NOLISTENER)
300                             fprintf(fp, " NOLISTENER");
301                     if (v->uv_flags & VIFF_DOWN)
302                             fprintf(fp, " DOWN");
303                     if (v->uv_flags & VIFF_DR) {
304                             fprintf(fp, " DR");
305                             width += 3;
306                     }
307                     if (v->uv_flags & VIFF_PIM_NBR) {
308                             fprintf(fp, " PIM");
309                             width += 4;
310                     }
311 #if 0                           /* impossible */
312                     if (v->uv_flags & VIFF_DVMRP_NBR) {
313                             fprintf(fp, " DVMRP");
314                             width += 6;
315                     }
316 #endif 
317                     if (v->uv_flags & VIFF_NONBRS) {
318                             fprintf(fp, " %-12s", "NO-NBR");
319                             width += 6;
320                     }
321                     if (v->uv_flags & VIFF_QUERIER)
322                             fprintf(fp, " QRY");
323
324                     if ((n = v->uv_pim_neighbors) != NULL) {
325                             /* Print the first neighbor on the same line */
326                             for (i = width; i <= 15; i++)
327                                     fprintf(fp, " ");
328                             fprintf(fp, "%-12s\n",
329                                     inet6_fmt(&n->address.sin6_addr));
330                             for (n = n->next; n != NULL; n = n->next)
331                                     fprintf(fp, "%64s %-15s\n", "",
332                                             inet6_fmt(&n->address.sin6_addr));
333             
334                     }
335                     else
336                             fprintf(fp, "\n");
337             }
338     }
339     fprintf(fp, "\n");
340 }
341
342
343 /*
344  * Log errors and other messages to the system log daemon and to stderr,
345  * according to the severity of the message and the current debug level.
346  * For errors of severity LOG_ERR or worse, terminate the program.
347  */
348 #ifdef __STDC__
349 void
350 log(int severity, int syserr, char *format, ...)
351 {
352     va_list ap;
353     static char fmt[211] = "warning - ";
354     char *msg;
355     struct timeval now;
356     struct tm *thyme;
357     
358     va_start(ap, format);
359 #else
360 /*VARARGS3*/
361 void
362 log(severity, syserr, format, va_alist)
363     int severity, syserr;
364     char *format;
365     va_dcl
366 {
367     va_list ap;
368     static char fmt[311] = "warning - ";
369     char *msg;
370     char tbuf[20];
371     struct timeval now;
372     struct tm *thyme;
373     
374     va_start(ap);
375 #endif
376     vsprintf(&fmt[10], format, ap);
377     va_end(ap);
378     msg = (severity == LOG_WARNING) ? fmt : &fmt[10];
379     
380     /*
381      * Log to stderr if we haven't forked yet and it's a warning or worse,
382      * or if we're debugging.
383      */
384     if (haveterminal && (debug || severity <= LOG_WARNING)) {
385         time_t sectime;
386         gettimeofday(&now,NULL);
387         sectime = (time_t) now.tv_sec;
388         thyme = localtime(&sectime);
389         if (!debug)
390             fprintf(stderr, "%s: ", progname);
391         fprintf(stderr, "%02d:%02d:%02d.%03ld %s", thyme->tm_hour,
392                 thyme->tm_min, thyme->tm_sec, (long int)now.tv_usec / 1000,
393                 msg);
394         if (syserr == 0)
395             fprintf(stderr, "\n");
396         else if (syserr < sys_nerr)
397             fprintf(stderr, ": %s\n", sys_errlist[syserr]);
398         else
399             fprintf(stderr, ": errno %d\n", syserr);
400     }
401     
402     /*
403      * Always log things that are worse than warnings, no matter what
404      * the log_nmsgs rate limiter says.
405      * Only count things worse than debugging in the rate limiter
406      * (since if you put daemon.debug in syslog.conf you probably
407      * actually want to log the debugging messages so they shouldn't
408      * be rate-limited)
409      */
410     if ((severity < LOG_WARNING) || (log_nmsgs < LOG_MAX_MSGS)) {
411         if (severity < LOG_DEBUG)
412             log_nmsgs++;
413         if (syserr != 0) {
414             errno = syserr;
415             syslog(severity, "%s: %m", msg);
416         } else
417             syslog(severity, "%s", msg);
418     }
419     
420     if (severity <= LOG_ERR) exit(-1);
421 }
422
423 void
424 dump_mldqueriers(fp)
425         FILE *fp;
426 {
427         struct uvif *v;
428         vifi_t vifi;
429         time_t now;
430
431         fprintf(fp, "MLD Querier List\n");
432         fprintf(fp, " %-3s %6s %-40s %-5s %15s\n",
433                 "Mif", "PhyIF", "Address", "Timer", "Last");
434         (void)time(&now);
435
436         for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
437                 if (v->uv_querier) {
438                         fprintf(fp, " %-3u %6s", vifi,
439                                 (v->uv_flags & MIFF_REGISTER) ? "regist":
440                                 v->uv_name);
441
442                         fprintf(fp, " %-40s %5lu %15s\n",
443                                 inet6_fmt(&v->uv_querier->al_addr.sin6_addr),
444                                 (u_long)v->uv_querier->al_timer,
445                                 sec2str(now - v->uv_querier->al_ctime));
446                 }
447         }
448
449         fprintf(fp, "\n");
450
451
452 /* TODO: format the output for better readability */
453 void 
454 dump_pim_mrt(fp)
455     FILE *fp;
456 {
457     grpentry_t *g;
458     register mrtentry_t *r;
459     register vifi_t vifi;
460     u_int number_of_groups = 0;
461     char oifs[(sizeof(if_set)<<3)+1];
462     char pruned_oifs[(sizeof(if_set)<<3)+1];
463     char asserted_oifs[(sizeof(if_set)<<3)+1];
464     char leaves_oifs[(sizeof(if_set)<<3)+1];
465     char filter_oifs[(sizeof(if_set)<<3)+1];
466     char incoming_iif[(sizeof(if_set)<<3)+1];
467     
468     fprintf(fp, "Multicast Routing Table\n%s", 
469             " Source          Group           Flags\n");
470
471     /* TODO: remove the dummy 0:: group (first in the chain) */
472     for (g = grplist->next; g != (grpentry_t *)NULL; g = g->next) {
473         number_of_groups++;
474         /* Print all (S,G) routing info */
475         for (r = g->mrtlink; r != (mrtentry_t *)NULL; r = r->grpnext) {
476             fprintf(fp, "---------------------------(S,G)----------------------------\n");
477             /* Print the routing info */
478             fprintf(fp, " %-15s", inet6_fmt(&r->source->address.sin6_addr));
479             fprintf(fp, " %-15s", inet6_fmt(&g->group.sin6_addr));
480
481             for (vifi = 0; vifi < numvifs; vifi++) {
482                 oifs[vifi] =
483                     IF_ISSET(vifi, &r->oifs)          ? 'o' : '.';
484                 pruned_oifs[vifi] =
485                     IF_ISSET(vifi, &r->pruned_oifs)   ? 'p' : '.';
486                 asserted_oifs[vifi] =
487                     IF_ISSET(vifi, &r->pruned_oifs)   ? 'a' : '.';
488                 filter_oifs[vifi] =
489                     IF_ISSET(vifi, &r->filter_oifs)   ? 'f' : '.';
490                 leaves_oifs[vifi] =
491                     IF_ISSET(vifi, &r->leaves)        ? 'l' : '.';
492                 incoming_iif[vifi] = '.';
493             }
494             oifs[vifi]          = 0x0;  /* End of string */
495             pruned_oifs[vifi]   = 0x0;
496             leaves_oifs[vifi]   = 0x0;
497             filter_oifs[vifi]   = 0x0;
498             incoming_iif[vifi]  = 0x0;
499             incoming_iif[r->incoming] = 'I';
500
501             /* TODO: don't need some of the flags */
502             if (r->flags & MRTF_SPT)           fprintf(fp, " SPT");
503             if (r->flags & MRTF_WC)            fprintf(fp, " WC");
504             if (r->flags & MRTF_RP)            fprintf(fp, " RP");
505             if (r->flags & MRTF_REGISTER)      fprintf(fp, " REG");
506             if (r->flags & MRTF_IIF_REGISTER)  fprintf(fp, " IIF_REG");
507             if (r->flags & MRTF_NULL_OIF)      fprintf(fp, " NULL_OIF");
508             if (r->flags & MRTF_KERNEL_CACHE)  fprintf(fp, " CACHE");
509             if (r->flags & MRTF_ASSERTED)      fprintf(fp, " ASSERTED");
510             if (r->flags & MRTF_REG_SUPP)      fprintf(fp, " REG_SUPP");
511             if (r->flags & MRTF_SG)            fprintf(fp, " SG");
512             if (r->flags & MRTF_PMBR)          fprintf(fp, " PMBR");
513             fprintf(fp, "\n");
514             
515             fprintf(fp, "Pruned   oifs: %-20s\n", pruned_oifs);
516             fprintf(fp, "Asserted oifs: %-20s\n", pruned_oifs);
517             fprintf(fp, "Filtered oifs: %-20s\n", filter_oifs);
518             fprintf(fp, "Leaves   oifs: %-20s\n", leaves_oifs);
519             fprintf(fp, "Outgoing oifs: %-20s\n", oifs);
520             fprintf(fp, "Incoming     : %-20s\n", incoming_iif);
521
522             fprintf(fp, "Upstream nbr: %s\n", 
523                     r->upstream ? inet6_fmt(&r->upstream->address.sin6_addr) : "NONE");
524             fprintf(fp, "\nTIMERS:  Entry   Prune VIFS:");
525             for (vifi = 0; vifi < numvifs; vifi++)
526                 fprintf(fp, "  %2d", vifi);
527             fprintf(fp, "\n           %3d              ",
528                     r->timer);
529             for (vifi = 0; vifi < numvifs; vifi++)
530                 fprintf(fp, " %3d", r->prune_timers[vifi]);
531             fprintf(fp, "\n");
532         }
533     }/* for all groups */
534
535     fprintf(fp, "Number of Groups: %u\n", number_of_groups);
536 }
537
538 void
539 dump_lcl_grp(fp)
540         FILE *fp;
541 {
542         vifi_t vifi;
543         struct uvif *v;
544         struct listaddr *g;
545
546         fprintf(fp, "\nList of local listener information per interface\n");
547         for (vifi = 0, v = uvifs; vifi < numvifs; vifi++, v++) {
548                 int first = 1;
549
550                 for (g = v->uv_groups; g != NULL; g = g->al_next) {
551                         if (first) {
552                                 fprintf(fp, "  Mif %d(%s)\n", vifi, v->uv_name);
553                                 first = 0;
554                         }
555                         fprintf(fp, "    %s", inet6_fmt(&g->al_addr.sin6_addr));
556                         if (g->al_timerid)
557                                 fprintf(fp, " timeout: %d",
558                                         timer_leftTimer(g->al_timerid));
559                         if (g->al_query)
560                                 fprintf(fp, " querytimer: %d",
561                                         timer_leftTimer(g->al_timerid));
562                         fputc('\n', fp);
563                 }
564         }
565 }