File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / pimdd / debug.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jun 12 07:58:55 2017 UTC (7 years ago) by misho
Branches: pimdd, MAIN
CVS tags: v0_2_1p0, v0_2_1, HEAD
pimdd-dense 0.2.1.0_2

    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.1.1.1 2017/06/12 07:58:55 misho 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>