Annotation of embedaddon/pimdd/debug.c, revision 1.1.1.1
1.1 misho 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.9 1998/06/02 19:46:54 kurtw 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: */
48:
49: #include "defs.h"
50:
51:
52: #ifdef __STDC__
53: #include <stdarg.h>
54: #else
55: #include <varargs.h>
56: #endif
57:
58: extern int haveterminal;
59: extern char *progname;
60:
61: int log_nmsgs = 0;
62: unsigned long debug = 0x00000000; /* If (long) is smaller than
63: * 4 bytes, then we are in
64: * trouble.
65: */
66: static char dumpfilename[] = _PATH_PIMD_DUMP;
67: static char cachefilename[] = _PATH_PIMD_CACHE; /* TODO: notused */
68:
69:
70: char *
71: packet_kind(proto, type, code)
72: u_int proto, type, code;
73: {
74: static char unknown[60];
75:
76: switch (proto) {
77: case IPPROTO_IGMP:
78: switch (type) {
79: case IGMP_MEMBERSHIP_QUERY: return "IGMP Membership Query ";
80: case IGMP_V1_MEMBERSHIP_REPORT:return "IGMP v1 Member Report ";
81: case IGMP_V2_MEMBERSHIP_REPORT:return "IGMP v2 Member Report ";
82: case IGMP_V2_LEAVE_GROUP: return "IGMP Leave message ";
83: case IGMP_DVMRP:
84: switch (code) {
85: case DVMRP_PROBE: return "DVMRP Neighbor Probe ";
86: case DVMRP_REPORT: return "DVMRP Route Report ";
87: case DVMRP_ASK_NEIGHBORS: return "DVMRP Neighbor Request ";
88: case DVMRP_NEIGHBORS: return "DVMRP Neighbor List ";
89: case DVMRP_ASK_NEIGHBORS2: return "DVMRP Neighbor request 2 ";
90: case DVMRP_NEIGHBORS2: return "DVMRP Neighbor list 2 ";
91: case DVMRP_PRUNE: return "DVMRP Prune message ";
92: case DVMRP_GRAFT: return "DVMRP Graft message ";
93: case DVMRP_GRAFT_ACK: return "DVMRP Graft message ack ";
94: case DVMRP_INFO_REQUEST: return "DVMRP Info Request ";
95: case DVMRP_INFO_REPLY: return "DVMRP Info Reply ";
96: default:
97: sprintf(unknown, "UNKNOWN DVMRP message code = %3d ", code);
98: return unknown;
99: }
100: case IGMP_PIM:
101: /* The old style (PIM v1) encapsulation of PIM messages
102: * inside IGMP messages.
103: */
104: /* PIM v1 is not implemented but we just inform that a message
105: * has arrived.
106: */
107: switch (code) {
108: case PIM_V1_QUERY: return "PIM v1 Router-Query ";
109: case PIM_V1_REGISTER: return "PIM v1 Register ";
110: case PIM_V1_REGISTER_STOP: return "PIM v1 Register-Stop ";
111: case PIM_V1_JOIN_PRUNE: return "PIM v1 Join/Prune ";
112: case PIM_V1_RP_REACHABILITY:
113: return "PIM v1 RP-Reachability ";
114: case PIM_V1_ASSERT: return "PIM v1 Assert ";
115: case PIM_V1_GRAFT: return "PIM v1 Graft ";
116: case PIM_V1_GRAFT_ACK: return "PIM v1 Graft_Ack ";
117: default:
118: sprintf(unknown, "UNKNOWN PIM v1 message type =%3d ", code);
119: return unknown;
120: }
121: case IGMP_MTRACE: return "IGMP trace query ";
122: case IGMP_MTRACE_RESP: return "IGMP trace reply ";
123: default:
124: sprintf(unknown,
125: "UNKNOWN IGMP message: type = 0x%02x, code = 0x%02x ",
126: type, code);
127: return unknown;
128: }
129: case IPPROTO_PIM: /* PIM v2 */
130: switch (type) {
131: case PIM_V2_HELLO: return "PIM v2 Hello ";
132: case PIM_V2_REGISTER: return "PIM v2 Register ";
133: case PIM_V2_REGISTER_STOP: return "PIM v2 Register_Stop ";
134: case PIM_V2_JOIN_PRUNE: return "PIM v2 Join/Prune ";
135: case PIM_V2_BOOTSTRAP: return "PIM v2 Bootstrap ";
136: case PIM_V2_ASSERT: return "PIM v2 Assert ";
137: case PIM_V2_GRAFT: return "PIM-DM v2 Graft ";
138: case PIM_V2_GRAFT_ACK: return "PIM-DM v2 Graft_Ack ";
139: case PIM_V2_CAND_RP_ADV: return "PIM v2 Cand. RP Adv. ";
140: default:
141: sprintf(unknown, "UNKNOWN PIM v2 message type =%3d ", type);
142: return unknown;
143: }
144: default:
145: sprintf(unknown, "UNKNOWN proto =%3d ", proto);
146: return unknown;
147: }
148: }
149:
150:
151: /*
152: * Used for debugging particular type of messages.
153: */
154: int
155: debug_kind(proto, type, code)
156: u_int proto, type, code;
157: {
158: switch (proto) {
159: case IPPROTO_IGMP:
160: switch (type) {
161: case IGMP_MEMBERSHIP_QUERY: return DEBUG_IGMP;
162: case IGMP_V1_MEMBERSHIP_REPORT: return DEBUG_IGMP;
163: case IGMP_V2_MEMBERSHIP_REPORT: return DEBUG_IGMP;
164: case IGMP_V2_LEAVE_GROUP: return DEBUG_IGMP;
165: case IGMP_DVMRP:
166: switch (code) {
167: case DVMRP_PROBE: return DEBUG_DVMRP_PEER;
168: case DVMRP_REPORT: return DEBUG_DVMRP_ROUTE;
169: case DVMRP_ASK_NEIGHBORS: return 0;
170: case DVMRP_NEIGHBORS: return 0;
171: case DVMRP_ASK_NEIGHBORS2: return 0;
172: case DVMRP_NEIGHBORS2: return 0;
173: case DVMRP_PRUNE: return DEBUG_DVMRP_PRUNE;
174: case DVMRP_GRAFT: return DEBUG_DVMRP_PRUNE;
175: case DVMRP_GRAFT_ACK: return DEBUG_DVMRP_PRUNE;
176: case DVMRP_INFO_REQUEST: return 0;
177: case DVMRP_INFO_REPLY: return 0;
178: default: return 0;
179: }
180: case IGMP_PIM:
181: /* PIM v1 is not implemented */
182: switch (code) {
183: case PIM_V1_QUERY: return DEBUG_PIM;
184: case PIM_V1_REGISTER: return DEBUG_PIM;
185: case PIM_V1_REGISTER_STOP: return DEBUG_PIM;
186: case PIM_V1_JOIN_PRUNE: return DEBUG_PIM;
187: case PIM_V1_RP_REACHABILITY: return DEBUG_PIM;
188: case PIM_V1_ASSERT: return DEBUG_PIM;
189: case PIM_V1_GRAFT: return DEBUG_PIM;
190: case PIM_V1_GRAFT_ACK: return DEBUG_PIM;
191: default: return DEBUG_PIM;
192: }
193: case IGMP_MTRACE: return DEBUG_TRACE;
194: case IGMP_MTRACE_RESP: return DEBUG_TRACE;
195: default: return DEBUG_IGMP;
196: }
197: case IPPROTO_PIM: /* PIM v2 */
198: /* TODO: modify? */
199: switch (type) {
200: case PIM_V2_HELLO: return DEBUG_PIM;
201: case PIM_V2_REGISTER: return DEBUG_PIM_REGISTER;
202: case PIM_V2_REGISTER_STOP: return DEBUG_PIM_REGISTER;
203: case PIM_V2_JOIN_PRUNE: return DEBUG_PIM;
204: case PIM_V2_BOOTSTRAP: return DEBUG_PIM_BOOTSTRAP;
205: case PIM_V2_ASSERT: return DEBUG_PIM;
206: case PIM_V2_GRAFT: return DEBUG_PIM;
207: case PIM_V2_GRAFT_ACK: return DEBUG_PIM;
208: case PIM_V2_CAND_RP_ADV: return DEBUG_PIM_CAND_RP;
209: default: return DEBUG_PIM;
210: }
211: default: return 0;
212: }
213: return 0;
214: }
215:
216:
217: /*
218: * Some messages are more important than others. This routine
219: * determines the logging level at which to log a send error (often
220: * "No route to host"). This is important when there is asymmetric
221: * reachability and someone is trying to, i.e., mrinfo me periodically.
222: */
223: int
224: log_level(proto, type, code)
225: u_int proto, type, code;
226: {
227: switch (proto) {
228: case IPPROTO_IGMP:
229: switch (type) {
230: case IGMP_MTRACE_RESP:
231: return LOG_INFO;
232:
233: case IGMP_DVMRP:
234: switch (code) {
235: case DVMRP_NEIGHBORS:
236: case DVMRP_NEIGHBORS2:
237: return LOG_INFO;
238: }
239: case IGMP_PIM:
240: /* PIM v1 */
241: switch (code) {
242: default:
243: return LOG_INFO;
244: }
245: default:
246: return LOG_WARNING;
247: }
248:
249: case IPPROTO_PIM:
250: /* PIM v2 */
251: switch (type) {
252: default:
253: return LOG_INFO;
254: }
255: default:
256: return LOG_WARNING;
257: }
258: return LOG_WARNING;
259: }
260:
261:
262: /*
263: * Dump internal data structures to stderr.
264: */
265: /* TODO: currently not used
266: void
267: dump(int i)
268: {
269: dump_vifs(stderr);
270: dump_pim_mrt(stderr);
271: }
272: */
273:
274: /*
275: * Dump internal data structures to a file.
276: */
277: void
278: fdump(i)
279: int i;
280: {
281: FILE *fp;
282: fp = fopen(dumpfilename, "w");
283: if (fp != NULL) {
284: dump_vifs(fp);
285: dump_pim_mrt(fp);
286: (void) fclose(fp);
287: }
288: }
289:
290: /* TODO: dummy, to be used in the future. */
291: /*
292: * Dump local cache contents to a file.
293: */
294: void
295: cdump(i)
296: int i;
297: {
298: FILE *fp;
299:
300: fp = fopen(cachefilename, "w");
301: if (fp != NULL) {
302: /* TODO: implement it:
303: dump_cache(fp);
304: */
305: (void) fclose(fp);
306: }
307: }
308:
309: void
310: dump_vifs(fp)
311: FILE *fp;
312: {
313: vifi_t vifi;
314: register struct uvif *v;
315: pim_nbr_entry_t *n;
316: int width;
317: int i;
318:
319: fprintf(fp, "\nVirtual Interface Table\n %-4s %-17s %-16s %-8s %-14s %s",
320: "Vif", "Local-Address", "Subnet", "Thresh", "Flags",
321: "Neighbors\n");
322:
323: for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
324: fprintf(fp, " %-3u %-17s ", vifi, inet_fmt(v->uv_lcl_addr, s1));
325: if (v->uv_flags & VIFF_REGISTER)
326: fprintf(fp, "%-16s ", v->uv_name);
327: else
328: fprintf(fp,"%-16.16s ", netname(v->uv_subnet, v->uv_subnetmask));
329: fprintf(fp, "%-5u ", v->uv_threshold);
330: width = 0;
331: if (v->uv_flags & VIFF_DISABLED)
332: fprintf(fp, " DISABLED");
333: if (v->uv_flags & VIFF_DOWN)
334: fprintf(fp, " DOWN");
335: if (v->uv_flags & VIFF_DR) {
336: fprintf(fp, " DR");
337: width += 3;
338: }
339: if (v->uv_flags & VIFF_PIM_NBR) {
340: fprintf(fp, " PIM");
341: width += 4;
342: }
343: if (v->uv_flags & VIFF_DVMRP_NBR) {
344: fprintf(fp, " DVMRP");
345: width += 6;
346: }
347: if (v->uv_flags & VIFF_NONBRS) {
348: fprintf(fp, " %-12s", "NO-NBR");
349: width += 6;
350: }
351:
352: if ((n = v->uv_pim_neighbors) != NULL) {
353: /* Print the first neighbor on the same line */
354: for (i = width; i <= 15; i++)
355: fprintf(fp, " ");
356: fprintf(fp, "%-12s\n", inet_fmt(n->address, s1));
357: for (n = n->next; n != NULL; n = n->next)
358: fprintf(fp, "%64s %-15s\n", "", inet_fmt(n->address, s1));
359:
360: }
361: else
362: fprintf(fp, "\n");
363: }
364: fprintf(fp, "\n");
365: }
366:
367:
368: /*
369: * Log errors and other messages to the system log daemon and to stderr,
370: * according to the severity of the message and the current debug level.
371: * For errors of severity LOG_ERR or worse, terminate the program.
372: */
373: #ifdef __STDC__
374: void
375: log(int severity, int syserr, char *format, ...)
376: {
377: va_list ap;
378: static char fmt[211] = "warning - ";
379: char *msg;
380: struct timeval now;
381: struct tm *thyme;
382:
383: va_start(ap, format);
384: #else
385: /*VARARGS3*/
386: void
387: log(severity, syserr, format, va_alist)
388: int severity, syserr;
389: char *format;
390: va_dcl
391: {
392: va_list ap;
393: static char fmt[311] = "warning - ";
394: char *msg;
395: char tbuf[20];
396: struct timeval now;
397: struct tm *thyme;
398:
399: va_start(ap);
400: #endif
401: vsprintf(&fmt[10], format, ap);
402: va_end(ap);
403: msg = (severity == LOG_WARNING) ? fmt : &fmt[10];
404:
405: /*
406: * Log to stderr if we haven't forked yet and it's a warning or worse,
407: * or if we're debugging.
408: */
409: if (haveterminal && (debug || severity <= LOG_WARNING)) {
410: gettimeofday(&now,NULL);
411: thyme = localtime(&now.tv_sec);
412: if (!debug)
413: fprintf(stderr, "%s: ", progname);
414: fprintf(stderr, "%02d:%02d:%02d.%03ld %s", thyme->tm_hour,
415: thyme->tm_min, thyme->tm_sec, now.tv_usec / 1000, msg);
416: if (syserr == 0)
417: fprintf(stderr, "\n");
418: else if (syserr < sys_nerr)
419: fprintf(stderr, ": %s\n", sys_errlist[syserr]);
420: else
421: fprintf(stderr, ": errno %d\n", syserr);
422: }
423:
424: /*
425: * Always log things that are worse than warnings, no matter what
426: * the log_nmsgs rate limiter says.
427: * Only count things worse than debugging in the rate limiter
428: * (since if you put daemon.debug in syslog.conf you probably
429: * actually want to log the debugging messages so they shouldn't
430: * be rate-limited)
431: */
432: if ((severity < LOG_WARNING) || (log_nmsgs < LOG_MAX_MSGS)) {
433: if (severity < LOG_DEBUG)
434: log_nmsgs++;
435: if (syserr != 0) {
436: errno = syserr;
437: syslog(severity, "%s: %m", msg);
438: } else
439: syslog(severity, "%s", msg);
440: }
441:
442: if (severity <= LOG_ERR) exit(-1);
443: }
444:
445: /* TODO: format the output for better readability */
446: void
447: dump_pim_mrt(fp)
448: FILE *fp;
449: {
450: grpentry_t *g;
451: register mrtentry_t *r;
452: register vifi_t vifi;
453: u_int number_of_groups = 0;
454: char oifs[(sizeof(vifbitmap_t)<<3)+1];
455: char pruned_oifs[(sizeof(vifbitmap_t)<<3)+1];
456: char leaves_oifs[(sizeof(vifbitmap_t)<<3)+1];
457: char incoming_iif[(sizeof(vifbitmap_t)<<3)+1];
458:
459: fprintf(fp, "Multicast Routing Table\n%s",
460: " Source Group Flags\n");
461:
462: /* TODO: remove the dummy 0.0.0.0 group (first in the chain) */
463: for (g = grplist->next; g != (grpentry_t *)NULL; g = g->next) {
464: number_of_groups++;
465: /* Print all (S,G) routing info */
466: for (r = g->mrtlink; r != (mrtentry_t *)NULL; r = r->grpnext) {
467: fprintf(fp, "---------------------------(S,G)----------------------------\n");
468: /* Print the routing info */
469: fprintf(fp, " %-15s", inet_fmt(r->source->address, s1));
470: fprintf(fp, " %-15s", inet_fmt(g->group, s2));
471:
472: for (vifi = 0; vifi < numvifs; vifi++) {
473: oifs[vifi] =
474: VIFM_ISSET(vifi, r->oifs) ? 'o' : '.';
475: pruned_oifs[vifi] =
476: VIFM_ISSET(vifi, r->pruned_oifs) ? 'p' : '.';
477: leaves_oifs[vifi] =
478: VIFM_ISSET(vifi, r->leaves) ? 'l' : '.';
479: incoming_iif[vifi] = '.';
480: }
481: oifs[vifi] = 0x0; /* End of string */
482: pruned_oifs[vifi] = 0x0;
483: leaves_oifs[vifi] = 0x0;
484: incoming_iif[vifi] = 0x0;
485: incoming_iif[r->incoming] = 'I';
486:
487: /* TODO: don't need some of the flags */
488: if (r->flags & MRTF_SPT) fprintf(fp, " SPT");
489: if (r->flags & MRTF_WC) fprintf(fp, " WC");
490: if (r->flags & MRTF_RP) fprintf(fp, " RP");
491: if (r->flags & MRTF_REGISTER) fprintf(fp, " REG");
492: if (r->flags & MRTF_IIF_REGISTER) fprintf(fp, " IIF_REG");
493: if (r->flags & MRTF_NULL_OIF) fprintf(fp, " NULL_OIF");
494: if (r->flags & MRTF_KERNEL_CACHE) fprintf(fp, " CACHE");
495: if (r->flags & MRTF_ASSERTED) fprintf(fp, " ASSERTED");
496: if (r->flags & MRTF_REG_SUPP) fprintf(fp, " REG_SUPP");
497: if (r->flags & MRTF_SG) fprintf(fp, " SG");
498: if (r->flags & MRTF_PMBR) fprintf(fp, " PMBR");
499: fprintf(fp, "\n");
500:
501: fprintf(fp, "Pruned oifs: %-20s\n", pruned_oifs);
502: fprintf(fp, "Leaves oifs: %-20s\n", leaves_oifs);
503: fprintf(fp, "Outgoing oifs: %-20s\n", oifs);
504: fprintf(fp, "Incoming : %-20s\n", incoming_iif);
505:
506: fprintf(fp, "Upstream nbr: %s\n",
507: r->upstream ? inet_fmt(r->upstream->address, s1) : "NONE");
508: fprintf(fp, "\nTIMERS: Entry Prune VIFS:");
509: for (vifi = 0; vifi < numvifs; vifi++)
510: fprintf(fp, " %2d", vifi);
511: fprintf(fp, "\n %3d ",
512: r->timer);
513: for (vifi = 0; vifi < numvifs; vifi++)
514: fprintf(fp, " %3d", r->prune_timers[vifi]);
515: fprintf(fp, "\n");
516: }
517: }/* for all groups */
518:
519: fprintf(fp, "Number of Groups: %u\n", number_of_groups);
520: }
521:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>