Annotation of embedaddon/pimdd/debug.c, revision 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>