Annotation of embedaddon/pimd/debug.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (c) 1998-2001
! 3: * University of Southern California/Information Sciences Institute.
! 4: * All rights reserved.
! 5: *
! 6: * Redistribution and use in source and binary forms, with or without
! 7: * modification, are permitted provided that the following conditions
! 8: * are met:
! 9: * 1. Redistributions of source code must retain the above copyright
! 10: * notice, this list of conditions and the following disclaimer.
! 11: * 2. Redistributions in binary form must reproduce the above copyright
! 12: * notice, this list of conditions and the following disclaimer in the
! 13: * documentation and/or other materials provided with the distribution.
! 14: * 3. Neither the name of the project nor the names of its contributors
! 15: * may be used to endorse or promote products derived from this software
! 16: * without specific prior written permission.
! 17: *
! 18: * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
! 19: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 20: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 21: * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
! 22: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 23: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 24: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 25: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 26: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 27: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 28: * SUCH DAMAGE.
! 29: */
! 30: /*
! 31: * $Id: debug.c,v 1.22 2001/11/28 00:13:50 pavlin Exp $
! 32: */
! 33: /*
! 34: * Part of this program has been derived from mrouted.
! 35: * The mrouted program is covered by the license in the accompanying file
! 36: * named "LICENSE.mrouted".
! 37: *
! 38: * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
! 39: * Leland Stanford Junior University.
! 40: *
! 41: */
! 42:
! 43: #define SYSLOG_NAMES
! 44: #include "defs.h"
! 45:
! 46: #include <stdarg.h>
! 47: #include <stdio.h>
! 48:
! 49: #define MAX_MSG_SIZE 64 /* Max for dump_frame() */
! 50:
! 51: int log_nmsgs = 0;
! 52: int loglevel = LOG_NOTICE;
! 53: unsigned long debug = 0x00000000; /* If (long) is smaller than
! 54: * 4 bytes, then we are in
! 55: * trouble.
! 56: */
! 57: static char dumpfilename[] = _PATH_PIMD_DUMP;
! 58: static char cachefilename[] = _PATH_PIMD_CACHE; /* TODO: notused */
! 59:
! 60:
! 61: char *packet_kind(int proto, int type, int code)
! 62: {
! 63: static char unknown[60];
! 64:
! 65: switch (proto) {
! 66: case IPPROTO_IGMP:
! 67: switch (type) {
! 68: case IGMP_MEMBERSHIP_QUERY: return "IGMP Membership Query ";
! 69: case IGMP_V1_MEMBERSHIP_REPORT: return "IGMP v1 Membership Report";
! 70: case IGMP_V2_MEMBERSHIP_REPORT: return "IGMP v2 Membership Report";
! 71: case IGMP_V3_MEMBERSHIP_REPORT: return "IGMP v3 Membership Report";
! 72: case IGMP_V2_LEAVE_GROUP: return "IGMP Leave message ";
! 73: case IGMP_DVMRP:
! 74: switch (code) {
! 75: case DVMRP_PROBE: return "DVMRP Neighbor Probe ";
! 76: case DVMRP_REPORT: return "DVMRP Route Report ";
! 77: case DVMRP_ASK_NEIGHBORS: return "DVMRP Neighbor Request ";
! 78: case DVMRP_NEIGHBORS: return "DVMRP Neighbor List ";
! 79: case DVMRP_ASK_NEIGHBORS2: return "DVMRP Neighbor request 2 ";
! 80: case DVMRP_NEIGHBORS2: return "DVMRP Neighbor list 2 ";
! 81: case DVMRP_PRUNE: return "DVMRP Prune message ";
! 82: case DVMRP_GRAFT: return "DVMRP Graft message ";
! 83: case DVMRP_GRAFT_ACK: return "DVMRP Graft message ack ";
! 84: case DVMRP_INFO_REQUEST: return "DVMRP Info Request ";
! 85: case DVMRP_INFO_REPLY: return "DVMRP Info Reply ";
! 86: default:
! 87: snprintf(unknown, sizeof(unknown), "UNKNOWN DVMRP message code = %3d ", code);
! 88: return unknown;
! 89: }
! 90:
! 91: case IGMP_PIM:
! 92: /* The old style (PIM v1) encapsulation of PIM messages
! 93: * inside IGMP messages.
! 94: */
! 95: /* PIM v1 is not implemented but we just inform that a message
! 96: * has arrived.
! 97: */
! 98: switch (code) {
! 99: case PIM_V1_QUERY: return "PIM v1 Router-Query ";
! 100: case PIM_V1_REGISTER: return "PIM v1 Register ";
! 101: case PIM_V1_REGISTER_STOP: return "PIM v1 Register-Stop ";
! 102: case PIM_V1_JOIN_PRUNE: return "PIM v1 Join/Prune ";
! 103: case PIM_V1_RP_REACHABILITY:
! 104: return "PIM v1 RP-Reachability ";
! 105:
! 106: case PIM_V1_ASSERT: return "PIM v1 Assert ";
! 107: case PIM_V1_GRAFT: return "PIM v1 Graft ";
! 108: case PIM_V1_GRAFT_ACK: return "PIM v1 Graft_Ack ";
! 109: default:
! 110: snprintf(unknown, sizeof(unknown), "UNKNOWN PIM v1 message type =%3d ", code);
! 111: return unknown;
! 112: }
! 113:
! 114: case IGMP_MTRACE: return "IGMP trace query ";
! 115: case IGMP_MTRACE_RESP: return "IGMP trace reply ";
! 116: default:
! 117: snprintf(unknown, sizeof (unknown), "UNKNOWN IGMP message: type = 0x%02x, code = 0x%02x ", type, code);
! 118: return unknown;
! 119: }
! 120:
! 121: case IPPROTO_PIM: /* PIM v2 */
! 122: switch (type) {
! 123: case PIM_V2_HELLO: return "PIM v2 Hello ";
! 124: case PIM_V2_REGISTER: return "PIM v2 Register ";
! 125: case PIM_V2_REGISTER_STOP: return "PIM v2 Register_Stop ";
! 126: case PIM_V2_JOIN_PRUNE: return "PIM v2 Join/Prune ";
! 127: case PIM_V2_BOOTSTRAP: return "PIM v2 Bootstrap ";
! 128: case PIM_V2_ASSERT: return "PIM v2 Assert ";
! 129: case PIM_V2_GRAFT: return "PIM-DM v2 Graft ";
! 130: case PIM_V2_GRAFT_ACK: return "PIM-DM v2 Graft_Ack ";
! 131: case PIM_V2_CAND_RP_ADV: return "PIM v2 Cand. RP Adv. ";
! 132: default:
! 133: snprintf(unknown, sizeof(unknown), "UNKNOWN PIM v2 message type =%3d ", type);
! 134: return unknown;
! 135: }
! 136:
! 137: default:
! 138: snprintf(unknown, sizeof(unknown), "UNKNOWN proto =%3d ", proto);
! 139: return unknown;
! 140: }
! 141: }
! 142:
! 143:
! 144: /*
! 145: * Used for debugging particular type of messages.
! 146: */
! 147: int debug_kind(int proto, int type, int code)
! 148: {
! 149: switch (proto) {
! 150: case IPPROTO_IGMP:
! 151: switch (type) {
! 152: case IGMP_MEMBERSHIP_QUERY: return DEBUG_IGMP;
! 153: case IGMP_V1_MEMBERSHIP_REPORT: return DEBUG_IGMP;
! 154: case IGMP_V2_MEMBERSHIP_REPORT: return DEBUG_IGMP;
! 155: case IGMP_V3_MEMBERSHIP_REPORT: return DEBUG_IGMP;
! 156: case IGMP_V2_LEAVE_GROUP: return DEBUG_IGMP;
! 157: case IGMP_DVMRP:
! 158: switch (code) {
! 159: case DVMRP_PROBE: return DEBUG_DVMRP_PEER;
! 160: case DVMRP_REPORT: return DEBUG_DVMRP_ROUTE;
! 161: case DVMRP_ASK_NEIGHBORS: return 0;
! 162: case DVMRP_NEIGHBORS: return 0;
! 163: case DVMRP_ASK_NEIGHBORS2: return 0;
! 164: case DVMRP_NEIGHBORS2: return 0;
! 165: case DVMRP_PRUNE: return DEBUG_DVMRP_PRUNE;
! 166: case DVMRP_GRAFT: return DEBUG_DVMRP_PRUNE;
! 167: case DVMRP_GRAFT_ACK: return DEBUG_DVMRP_PRUNE;
! 168: case DVMRP_INFO_REQUEST: return 0;
! 169: case DVMRP_INFO_REPLY: return 0;
! 170: default: return 0;
! 171: }
! 172:
! 173: case IGMP_PIM:
! 174: /* PIM v1 is not implemented */
! 175: switch (code) {
! 176: case PIM_V1_QUERY: return DEBUG_PIM;
! 177: case PIM_V1_REGISTER: return DEBUG_PIM;
! 178: case PIM_V1_REGISTER_STOP: return DEBUG_PIM;
! 179: case PIM_V1_JOIN_PRUNE: return DEBUG_PIM;
! 180: case PIM_V1_RP_REACHABILITY: return DEBUG_PIM;
! 181: case PIM_V1_ASSERT: return DEBUG_PIM;
! 182: case PIM_V1_GRAFT: return DEBUG_PIM;
! 183: case PIM_V1_GRAFT_ACK: return DEBUG_PIM;
! 184: default: return DEBUG_PIM;
! 185: }
! 186:
! 187: case IGMP_MTRACE: return DEBUG_TRACE;
! 188: case IGMP_MTRACE_RESP: return DEBUG_TRACE;
! 189: default: return DEBUG_IGMP;
! 190: }
! 191:
! 192: case IPPROTO_PIM: /* PIM v2 */
! 193: /* TODO: modify? */
! 194: switch (type) {
! 195: case PIM_V2_HELLO: return DEBUG_PIM;
! 196: case PIM_V2_REGISTER: return DEBUG_PIM_REGISTER;
! 197: case PIM_V2_REGISTER_STOP: return DEBUG_PIM_REGISTER;
! 198: case PIM_V2_JOIN_PRUNE: return DEBUG_PIM;
! 199: case PIM_V2_BOOTSTRAP: return DEBUG_PIM_BOOTSTRAP;
! 200: case PIM_V2_ASSERT: return DEBUG_PIM;
! 201: case PIM_V2_GRAFT: return DEBUG_PIM;
! 202: case PIM_V2_GRAFT_ACK: return DEBUG_PIM;
! 203: case PIM_V2_CAND_RP_ADV: return DEBUG_PIM_CAND_RP;
! 204: default: return DEBUG_PIM;
! 205: }
! 206:
! 207: default: return 0;
! 208: }
! 209:
! 210: return 0;
! 211: }
! 212:
! 213:
! 214: /*
! 215: * Some messages are more important than others. This routine
! 216: * determines the logging level at which to log a send error (often
! 217: * "No route to host"). This is important when there is asymmetric
! 218: * reachability and someone is trying to, i.e., mrinfo me periodically.
! 219: */
! 220: int
! 221: log_level(int proto, int type, int code)
! 222: {
! 223: switch (proto) {
! 224: case IPPROTO_IGMP:
! 225: switch (type) {
! 226: case IGMP_MTRACE_RESP:
! 227: return LOG_INFO;
! 228:
! 229: case IGMP_DVMRP:
! 230: switch (code) {
! 231: case DVMRP_NEIGHBORS:
! 232: case DVMRP_NEIGHBORS2:
! 233: return LOG_INFO;
! 234: }
! 235: return LOG_WARNING;
! 236:
! 237: case IGMP_PIM:
! 238: /* PIM v1 */
! 239: switch (code) {
! 240: default:
! 241: return LOG_INFO;
! 242: }
! 243: return LOG_WARNING;
! 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: return LOG_WARNING;
! 256:
! 257: default:
! 258: return LOG_WARNING;
! 259: }
! 260: return LOG_WARNING;
! 261: }
! 262:
! 263:
! 264: /*
! 265: * Dump internal data structures to a file.
! 266: */
! 267: void fdump(int i __attribute__((unused)))
! 268: {
! 269: FILE *fp;
! 270:
! 271: fp = fopen(dumpfilename, "w");
! 272: if (fp) {
! 273: dump_vifs(fp);
! 274: dump_pim_mrt(fp);
! 275: fclose(fp);
! 276: }
! 277: }
! 278:
! 279: /* TODO: dummy, to be used in the future. */
! 280: /*
! 281: * Dump local cache contents to a file.
! 282: */
! 283: void cdump(int i __attribute__((unused)))
! 284: {
! 285: FILE *fp;
! 286:
! 287: fp = fopen(cachefilename, "w");
! 288: if (fp) {
! 289: /* XXX: TODO: implement it:
! 290: dump_cache(fp);
! 291: */
! 292: fclose(fp);
! 293: }
! 294: }
! 295:
! 296: /*
! 297: 1 2 3 4 5 6 7 8
! 298: 012345678901234567890123456789012345678901234567890123456789012345678901234567890
! 299: Virtual Interface Table
! 300: Vif Local-Address Subnet Thresh Flags Neighbors
! 301: 0 10.0.3.1 10.0.3/24 1 DR NO-NBR
! 302: 1 172.16.12.254 172.16.12/24 1 DR PIM 172.16.12.2
! 303: 172.16.12.3
! 304: 2 192.168.122.147 register_vif0 1
! 305: */
! 306: void dump_vifs(FILE *fp)
! 307: {
! 308: vifi_t vifi;
! 309: struct uvif *v;
! 310: pim_nbr_entry_t *n;
! 311: int width;
! 312: int i;
! 313: struct listaddr *group, *source;
! 314:
! 315: fprintf(fp, "Virtual Interface Table ======================================================\n");
! 316: fprintf(fp, "Vif Local Address Subnet Thresh Flags Neighbors\n");
! 317: fprintf(fp, "--- --------------- ------------------ ------ --------- -----------------\n");
! 318:
! 319: for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
! 320: int down = 0;
! 321:
! 322: fprintf(fp, "%3u %-15s ", vifi, inet_fmt(v->uv_lcl_addr, s1, sizeof(s1)));
! 323:
! 324: if (v->uv_flags & VIFF_REGISTER)
! 325: fprintf(fp, "%-18s ", v->uv_name);
! 326: else
! 327: fprintf(fp,"%-18.18s ", netname(v->uv_subnet, v->uv_subnetmask));
! 328:
! 329: fprintf(fp, "%6u ", v->uv_threshold);
! 330:
! 331: /* TODO: XXX: Print VIFF_TUNNEL? */
! 332: width = 0;
! 333: if (v->uv_flags & VIFF_DISABLED) {
! 334: fprintf(fp, " DISABLED");
! 335: down = 1;
! 336: }
! 337: if (v->uv_flags & VIFF_DOWN) {
! 338: fprintf(fp, " DOWN");
! 339: down = 1;
! 340: }
! 341:
! 342: if (v->uv_flags & VIFF_DR) {
! 343: fprintf(fp, " DR");
! 344: width += 3;
! 345: }
! 346: if (v->uv_flags & VIFF_PIM_NBR) {
! 347: fprintf(fp, " PIM");
! 348: width += 4;
! 349: }
! 350: if (v->uv_flags & VIFF_DVMRP_NBR) {
! 351: fprintf(fp, " DVMRP");
! 352: width += 6;
! 353: }
! 354: if (v->uv_flags & VIFF_NONBRS) {
! 355: fprintf(fp, " NO-NBR");
! 356: width += 6;
! 357: }
! 358:
! 359: n = v->uv_pim_neighbors;
! 360: if (!down && n) {
! 361: for (i = width; i <= 11; i++)
! 362: fprintf(fp, " ");
! 363: fprintf(fp, "%-15s\n", inet_fmt(n->address, s1, sizeof(s1)));
! 364: for (n = n->next; n; n = n->next)
! 365: fprintf(fp, "%61s%-15s\n", "", inet_fmt(n->address, s1, sizeof(s1)));
! 366: } else {
! 367: fprintf(fp, "\n");
! 368: }
! 369: }
! 370:
! 371: fprintf(fp, "\n");
! 372:
! 373: /* Dump groups and sources */
! 374: fprintf(fp, " %-3s %-15s %-20s", "Vif", "SSM Group", "Sources");
! 375: for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
! 376: for (group = v->uv_groups; group != NULL; group = group->al_next) {
! 377: if (IN_PIM_SSM_RANGE(group->al_addr)) {
! 378: fprintf(fp, "\n %3u %-15s ", vifi, inet_fmt(group->al_addr, s1, sizeof(s1)));
! 379: for (source = group->al_sources; source != NULL; source = source->al_next) {
! 380: fprintf(fp, "%s ", inet_fmt(source->al_addr, s1, sizeof(s1)));
! 381: }
! 382: }
! 383: }
! 384: }
! 385:
! 386: fprintf(fp, "\n\n");
! 387: }
! 388:
! 389: int loglvl(char *level)
! 390: {
! 391: int i;
! 392:
! 393: for (i = 0; prioritynames[i].c_name; i++) {
! 394: if (string_match(prioritynames[i].c_name, level))
! 395: return prioritynames[i].c_val;
! 396: }
! 397:
! 398: return atoi(level);
! 399: }
! 400:
! 401: /*
! 402: * Log errors and other messages to the system log daemon and to stderr,
! 403: * according to the severity of the message and the current debug level.
! 404: * For errors of severity LOG_ERR or worse, terminate the program.
! 405: */
! 406: void logit(int severity, int syserr, const char *format, ...)
! 407: {
! 408: va_list ap;
! 409: char msg[211];
! 410: struct timeval now;
! 411: struct tm *thyme;
! 412: time_t lt;
! 413:
! 414: va_start(ap, format);
! 415: vsnprintf(msg, sizeof(msg), format, ap);
! 416: va_end(ap);
! 417:
! 418: /*
! 419: * Log to stderr if we haven't forked yet and it's a warning or
! 420: * worse, or if we're debugging.
! 421: */
! 422: if (haveterminal && (debug || severity <= LOG_WARNING)) {
! 423: gettimeofday(&now, NULL);
! 424: lt = now.tv_sec;
! 425: thyme = localtime(<);
! 426:
! 427: if (!debug)
! 428: fprintf(stderr, "%s: ", __progname);
! 429:
! 430: fprintf(stderr, "%02d:%02d:%02d.%03ld %s", thyme->tm_hour, thyme->tm_min,
! 431: thyme->tm_sec, (long int)(now.tv_usec / 1000), msg);
! 432:
! 433: if (syserr) {
! 434: errno = syserr;
! 435: fprintf(stderr, ": %m");
! 436: }
! 437: fprintf(stderr, "\n");
! 438: }
! 439:
! 440: /*
! 441: * Always log things that are worse than warnings, no matter what
! 442: * the log_nmsgs rate limiter says.
! 443: *
! 444: * Only count things at the defined loglevel or worse in the rate limiter
! 445: * and exclude debugging (since if you put daemon.debug in syslog.conf
! 446: * you probably actually want to log the debugging messages so they
! 447: * shouldn't be rate-limited)
! 448: */
! 449: if ((severity < LOG_WARNING) || (log_nmsgs < LOG_MAX_MSGS)) {
! 450: if ((severity <= loglevel) && (severity != LOG_DEBUG))
! 451: log_nmsgs++;
! 452:
! 453: if (syserr) {
! 454: errno = syserr;
! 455: syslog(severity, "%s: %m", msg);
! 456: } else {
! 457: syslog(severity, "%s", msg);
! 458: }
! 459: }
! 460:
! 461: #ifndef CONTINUE_ON_ERROR
! 462: if (severity <= LOG_ERR)
! 463: exit(-1); /* Exit status: 255 */
! 464: #endif /* CONTINUE_ON_ERROR */
! 465: }
! 466:
! 467:
! 468: /*
! 469: * Hex dump a control frame to the log, MAX 64 bytes length
! 470: */
! 471: void dump_frame(char *desc, void *dump, size_t len)
! 472: {
! 473: unsigned int length, i = 0;
! 474: unsigned char *data = (unsigned char *)dump;
! 475: char buf[80] = "";
! 476: char tmp[10];
! 477:
! 478: length = len;
! 479: if (length > MAX_MSG_SIZE)
! 480: length = MAX_MSG_SIZE;
! 481:
! 482: if (desc)
! 483: logit(LOG_DEBUG, 0, "%s", desc);
! 484:
! 485: while (i < length) {
! 486: if (!(i % 16))
! 487: snprintf(buf, sizeof(buf), "%03X: ", i);
! 488:
! 489: snprintf(tmp, sizeof(tmp), "%02X ", data[i++]);
! 490: strlcat(buf, tmp, sizeof(buf));
! 491:
! 492: if (i > 0 && !(i % 16))
! 493: logit(LOG_DEBUG, 0, "%s", buf);
! 494: else if (i > 0 && !(i % 8))
! 495: strlcat(buf, ":: ", sizeof(buf));
! 496: }
! 497: logit(LOG_DEBUG, 0, "%s", buf);
! 498: }
! 499:
! 500:
! 501: static void dump_route(FILE *fp, mrtentry_t *r)
! 502: {
! 503: vifi_t vifi;
! 504: char oifs[(sizeof(vifbitmap_t)<<3)+1];
! 505: char joined_oifs[(sizeof(vifbitmap_t)<<3)+1];
! 506: char pruned_oifs[(sizeof(vifbitmap_t)<<3)+1];
! 507: char leaves_oifs[(sizeof(vifbitmap_t)<<3)+1];
! 508: char asserted_oifs[(sizeof(vifbitmap_t)<<3)+1];
! 509: char incoming_iif[(sizeof(vifbitmap_t)<<3)+1];
! 510:
! 511: for (vifi = 0; vifi < numvifs; vifi++) {
! 512: oifs[vifi] =
! 513: VIFM_ISSET(vifi, r->oifs) ? 'o' : '.';
! 514: joined_oifs[vifi] =
! 515: VIFM_ISSET(vifi, r->joined_oifs) ? 'j' : '.';
! 516: pruned_oifs[vifi] =
! 517: VIFM_ISSET(vifi, r->pruned_oifs) ? 'p' : '.';
! 518: leaves_oifs[vifi] =
! 519: VIFM_ISSET(vifi, r->leaves) ? 'l' : '.';
! 520: asserted_oifs[vifi] =
! 521: VIFM_ISSET(vifi, r->asserted_oifs) ? 'a' : '.';
! 522: incoming_iif[vifi] = '.';
! 523: }
! 524: oifs[vifi] = 0x0; /* End of string */
! 525: joined_oifs[vifi] = 0x0;
! 526: pruned_oifs[vifi] = 0x0;
! 527: leaves_oifs[vifi] = 0x0;
! 528: asserted_oifs[vifi] = 0x0;
! 529: incoming_iif[vifi] = 0x0;
! 530: incoming_iif[r->incoming] = 'I';
! 531:
! 532: /* TODO: don't need some of the flags */
! 533: if (r->flags & MRTF_SPT) fprintf(fp, " SPT");
! 534: if (r->flags & MRTF_WC) fprintf(fp, " WC");
! 535: if (r->flags & MRTF_RP) fprintf(fp, " RP");
! 536: if (r->flags & MRTF_REGISTER) fprintf(fp, " REG");
! 537: if (r->flags & MRTF_IIF_REGISTER) fprintf(fp, " IIF_REG");
! 538: if (r->flags & MRTF_NULL_OIF) fprintf(fp, " NULL_OIF");
! 539: if (r->flags & MRTF_KERNEL_CACHE) fprintf(fp, " CACHE");
! 540: if (r->flags & MRTF_ASSERTED) fprintf(fp, " ASSERTED");
! 541: if (r->flags & MRTF_REG_SUPP) fprintf(fp, " REG_SUPP");
! 542: if (r->flags & MRTF_SG) fprintf(fp, " SG");
! 543: if (r->flags & MRTF_PMBR) fprintf(fp, " PMBR");
! 544: fprintf(fp, "\n");
! 545:
! 546: fprintf(fp, "Joined oifs: %-20s\n", joined_oifs);
! 547: fprintf(fp, "Pruned oifs: %-20s\n", pruned_oifs);
! 548: fprintf(fp, "Leaves oifs: %-20s\n", leaves_oifs);
! 549: fprintf(fp, "Asserted oifs: %-20s\n", asserted_oifs);
! 550: fprintf(fp, "Outgoing oifs: %-20s\n", oifs);
! 551: fprintf(fp, "Incoming : %-20s\n", incoming_iif);
! 552:
! 553: fprintf(fp, "\nTIMERS: Entry JP RS Assert VIFS:");
! 554: for (vifi = 0; vifi < numvifs; vifi++)
! 555: fprintf(fp, " %d", vifi);
! 556: fprintf(fp, "\n %5d %4d %4d %6d ",
! 557: r->timer, r->jp_timer, r->rs_timer, r->assert_timer);
! 558: for (vifi = 0; vifi < numvifs; vifi++)
! 559: fprintf(fp, " %2d", r->vif_timers[vifi]);
! 560: fprintf(fp, "\n");
! 561: }
! 562:
! 563: void dump_pim_mrt(FILE *fp)
! 564: {
! 565: grpentry_t *g;
! 566: mrtentry_t *r;
! 567: u_int number_of_cache_mirrors = 0;
! 568: u_int number_of_groups = 0;
! 569: cand_rp_t *rp;
! 570: kernel_cache_t *kc;
! 571:
! 572: fprintf(fp, "Multicast Routing Table ======================================================\n");
! 573:
! 574: /* TODO: remove the dummy 0.0.0.0 group (first in the chain) */
! 575: for (g = grplist->next; g; g = g->next) {
! 576: number_of_groups++;
! 577:
! 578: r = g->grp_route;
! 579: if (r) {
! 580: if (r->flags & MRTF_KERNEL_CACHE) {
! 581: for (kc = r->kernel_cache; kc; kc = kc->next)
! 582: number_of_cache_mirrors++;
! 583: }
! 584:
! 585: /* Print the (*,G) routing info */
! 586: fprintf(fp, "----------------------------------- (*,G) ------------------------------------\n");
! 587: fprintf(fp, "Source Group RP Address Flags\n");
! 588: fprintf(fp, "--------------- --------------- --------------- ---------------------------\n");
! 589: fprintf(fp, "%-15s ", "INADDR_ANY");
! 590: fprintf(fp, "%-15s ", inet_fmt(g->group, s1, sizeof(s1)));
! 591: fprintf(fp, "%-15s ", IN_PIM_SSM_RANGE(g->group) ? "SSM" :
! 592: (g->active_rp_grp ? inet_fmt(g->rpaddr, s2, sizeof(s2)) : "NULL"));
! 593:
! 594: dump_route(fp, r);
! 595: }
! 596:
! 597: /* Print all (S,G) routing info */
! 598: fprintf(fp, "----------------------------------- (S,G) ------------------------------------\n");
! 599: for (r = g->mrtlink; r; r = r->grpnext) {
! 600: if (r->flags & MRTF_KERNEL_CACHE)
! 601: number_of_cache_mirrors++;
! 602:
! 603: /* Print the routing info */
! 604: fprintf(fp, "Source Group RP Address Flags\n");
! 605: fprintf(fp, "--------------- --------------- --------------- ---------------------------\n");
! 606: fprintf(fp, "%-15s ", inet_fmt(r->source->address, s1, sizeof(s1)));
! 607: fprintf(fp, "%-15s ", inet_fmt(g->group, s2, sizeof(s2)));
! 608: fprintf(fp, "%-15s ", IN_PIM_SSM_RANGE(g->group) ? "SSM" :
! 609: (g->active_rp_grp ? inet_fmt(g->rpaddr, s2, sizeof(s2)) : "NULL"));
! 610:
! 611: dump_route(fp, r);
! 612: }
! 613: }/* for all groups */
! 614:
! 615: /* Print the (*,*,R) routing entries */
! 616: fprintf(fp, "--------------------------------- (*,*,G) ------------------------------------\n");
! 617: for (rp = cand_rp_list; rp; rp = rp->next) {
! 618: r = rp->rpentry->mrtlink;
! 619: if (r) {
! 620: if (r->flags & MRTF_KERNEL_CACHE) {
! 621: for (kc = r->kernel_cache; kc; kc = kc->next)
! 622: number_of_cache_mirrors++;
! 623: }
! 624:
! 625: /* Print the (*,*,RP) routing info */
! 626: fprintf(fp, "Source Group RP Address Flags\n");
! 627: fprintf(fp, "--------------- --------------- --------------- ---------------------------\n");
! 628: fprintf(fp, "%-15s ", inet_fmt(r->source->address, s1, sizeof(s1)));
! 629: fprintf(fp, "%-15s ", "INADDR_ANY");
! 630: fprintf(fp, "%-15s ", "");
! 631:
! 632: dump_route(fp, r);
! 633: }
! 634: } /* For all (*,*,RP) */
! 635:
! 636: fprintf(fp, "Number of Groups: %u\n", number_of_groups);
! 637: fprintf(fp, "Number of Cache MIRRORs: %u\n", number_of_cache_mirrors);
! 638: fprintf(fp, "------------------------------------------------------------------------------\n\n");
! 639: }
! 640:
! 641: static void dump_rpgrp(FILE *fp, rp_grp_entry_t *rpgrp, int indent)
! 642: {
! 643: grp_mask_t *grp = rpgrp->group;
! 644:
! 645: if (indent)
! 646: fprintf(fp, " ");
! 647:
! 648: fprintf(fp, "%-18.18s %-8u %-8u\n",
! 649: netname(grp->group_addr, grp->group_mask),
! 650: rpgrp->priority, rpgrp->holdtime);
! 651: }
! 652:
! 653: /*
! 654: * Dumps the local Cand-RP-set
! 655: */
! 656: int dump_rp_set(FILE *fp)
! 657: {
! 658: cand_rp_t *rp;
! 659: rp_grp_entry_t *rpgrp;
! 660:
! 661: fprintf(fp, "Candidate Rendezvous-Point Set ===============================================\n");
! 662: fprintf(fp, "RP address Incoming Group Prefix Priority Holdtime\n");
! 663: fprintf(fp, "--------------- -------- ------------------ -------- ---------------------\n");
! 664: for (rp = cand_rp_list; rp; rp = rp->next) {
! 665: fprintf(fp, "%-15s %-8d ",
! 666: inet_fmt(rp->rpentry->address, s1, sizeof(s1)),
! 667: rp->rpentry->incoming);
! 668:
! 669: rpgrp = rp->rp_grp_next;
! 670: if (rpgrp) {
! 671: dump_rpgrp(fp, rpgrp, 0);
! 672:
! 673: for (rpgrp = rpgrp->rp_grp_next; rpgrp; rpgrp = rpgrp->rp_grp_next)
! 674: dump_rpgrp(fp, rpgrp, 1);
! 675: }
! 676: }
! 677:
! 678: fprintf(fp, "------------------------------------------------------------------------------\n");
! 679: fprintf(fp, "Current BSR address: %s\n\n", inet_fmt(curr_bsr_address, s1, sizeof(s1)));
! 680:
! 681: return TRUE;
! 682: }
! 683:
! 684: /**
! 685: * Local Variables:
! 686: * version-control: t
! 687: * indent-tabs-mode: t
! 688: * c-file-style: "ellemtel"
! 689: * c-basic-offset: 4
! 690: * End:
! 691: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>