Home | History | Annotate | Line # | Download | only in mrouted
main.c revision 1.12
      1  1.12  thorpej /*	$NetBSD: main.c,v 1.12 1999/06/06 03:27:06 thorpej Exp $	*/
      2   1.5  thorpej 
      3   1.1   brezak /*
      4   1.1   brezak  * The mrouted program is covered by the license in the accompanying file
      5   1.1   brezak  * named "LICENSE".  Use of the mrouted program represents acceptance of
      6   1.1   brezak  * the terms and conditions listed in that file.
      7   1.1   brezak  *
      8   1.1   brezak  * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
      9   1.1   brezak  * Leland Stanford Junior University.
     10   1.1   brezak  */
     11   1.1   brezak 
     12   1.1   brezak /*
     13   1.1   brezak  * Written by Steve Deering, Stanford University, February 1989.
     14   1.1   brezak  *
     15   1.1   brezak  * (An earlier version of DVMRP was implemented by David Waitzman of
     16   1.1   brezak  *  BBN STC by extending Berkeley's routed program.  Some of Waitzman's
     17   1.1   brezak  *  extensions have been incorporated into mrouted, but none of the
     18   1.1   brezak  *  original routed code has been adopted.)
     19   1.1   brezak  */
     20   1.1   brezak 
     21   1.1   brezak 
     22   1.1   brezak #include "defs.h"
     23   1.6  mycroft #ifdef __STDC__
     24   1.6  mycroft #include <stdarg.h>
     25   1.6  mycroft #else
     26   1.4  mycroft #include <varargs.h>
     27   1.6  mycroft #endif
     28   1.6  mycroft #include <fcntl.h>
     29   1.4  mycroft 
     30   1.4  mycroft #ifdef SNMP
     31   1.4  mycroft #include "snmp.h"
     32   1.4  mycroft #endif
     33   1.1   brezak 
     34   1.9    lukem #include <sys/cdefs.h>
     35   1.6  mycroft #ifndef lint
     36  1.12  thorpej __RCSID("@(#) $NetBSD: main.c,v 1.12 1999/06/06 03:27:06 thorpej Exp $");
     37   1.6  mycroft #endif
     38   1.6  mycroft 
     39  1.12  thorpej #include <err.h>
     40  1.12  thorpej #include <util.h>
     41  1.12  thorpej 
     42   1.1   brezak extern char *configfilename;
     43   1.6  mycroft char versionstring[100];
     44   1.1   brezak 
     45   1.1   brezak static char dumpfilename[] = _PATH_MROUTED_DUMP;
     46   1.4  mycroft static char cachefilename[] = _PATH_MROUTED_CACHE;
     47   1.4  mycroft static char genidfilename[] = _PATH_MROUTED_GENID;
     48   1.4  mycroft 
     49   1.4  mycroft int cache_lifetime 	= DEFAULT_CACHE_LIFETIME;
     50   1.4  mycroft int max_prune_lifetime 	= DEFAULT_CACHE_LIFETIME * 2;
     51   1.1   brezak 
     52   1.2   brezak int debug = 0;
     53   1.4  mycroft u_char pruning = 1;	/* Enable pruning by default */
     54   1.4  mycroft 
     55   1.6  mycroft #ifdef SNMP
     56   1.6  mycroft #define NHANDLERS	34
     57   1.6  mycroft #else
     58   1.4  mycroft #define NHANDLERS	2
     59   1.6  mycroft #endif
     60   1.1   brezak 
     61   1.4  mycroft static struct ihandler {
     62   1.4  mycroft     int fd;			/* File descriptor		 */
     63   1.6  mycroft     ihfunc_t func;		/* Function to call with &fd_set */
     64   1.4  mycroft } ihandlers[NHANDLERS];
     65   1.4  mycroft static int nhandlers = 0;
     66   1.1   brezak 
     67   1.1   brezak /*
     68   1.1   brezak  * Forward declarations.
     69   1.1   brezak  */
     70   1.6  mycroft static void fasttimer __P((int));
     71   1.6  mycroft static void done __P((int));
     72   1.6  mycroft static void dump __P((int));
     73   1.6  mycroft static void fdump __P((int));
     74   1.6  mycroft static void cdump __P((int));
     75   1.6  mycroft static void restart __P((int));
     76   1.6  mycroft static void timer __P((void));
     77   1.6  mycroft static void cleanup __P((void));
     78   1.6  mycroft static void resetlogging __P((void *));
     79   1.6  mycroft 
     80   1.6  mycroft /* To shut up gcc -Wstrict-prototypes */
     81   1.6  mycroft int main __P((int argc, char **argv));
     82   1.4  mycroft 
     83   1.4  mycroft int
     84   1.4  mycroft register_input_handler(fd, func)
     85   1.4  mycroft     int fd;
     86   1.6  mycroft     ihfunc_t func;
     87   1.4  mycroft {
     88   1.4  mycroft     if (nhandlers >= NHANDLERS)
     89   1.4  mycroft 	return -1;
     90   1.4  mycroft 
     91   1.4  mycroft     ihandlers[nhandlers].fd = fd;
     92   1.4  mycroft     ihandlers[nhandlers++].func = func;
     93   1.1   brezak 
     94   1.4  mycroft     return 0;
     95   1.4  mycroft }
     96   1.1   brezak 
     97   1.6  mycroft int
     98   1.6  mycroft main(argc, argv)
     99   1.1   brezak     int argc;
    100   1.1   brezak     char *argv[];
    101   1.1   brezak {
    102   1.1   brezak     register int recvlen;
    103   1.1   brezak     register int omask;
    104   1.1   brezak     int dummy;
    105   1.1   brezak     FILE *fp;
    106   1.4  mycroft     struct timeval tv;
    107   1.6  mycroft     u_int32_t prev_genid;
    108   1.4  mycroft     int vers;
    109   1.4  mycroft     fd_set rfds, readers;
    110   1.4  mycroft     int nfds, n, i;
    111   1.4  mycroft #ifdef SNMP
    112   1.6  mycroft     struct timeval  timeout, *tvp = &timeout;
    113   1.6  mycroft     struct timeval  sched, *svp = &sched, now, *nvp = &now;
    114   1.6  mycroft     int index, block;
    115   1.4  mycroft #endif
    116   1.1   brezak 
    117   1.1   brezak     setlinebuf(stderr);
    118   1.1   brezak 
    119   1.1   brezak     if (geteuid() != 0) {
    120   1.4  mycroft 	fprintf(stderr, "must be root\n");
    121   1.1   brezak 	exit(1);
    122   1.1   brezak     }
    123   1.1   brezak 
    124   1.1   brezak     argv++, argc--;
    125   1.1   brezak     while (argc > 0 && *argv[0] == '-') {
    126   1.1   brezak 	if (strcmp(*argv, "-d") == 0) {
    127   1.1   brezak 	    if (argc > 1 && isdigit(*(argv + 1)[0])) {
    128   1.1   brezak 		argv++, argc--;
    129   1.1   brezak 		debug = atoi(*argv);
    130   1.1   brezak 	    } else
    131   1.1   brezak 		debug = DEFAULT_DEBUG;
    132   1.1   brezak 	} else if (strcmp(*argv, "-c") == 0) {
    133   1.1   brezak 	    if (argc > 1) {
    134   1.1   brezak 		argv++, argc--;
    135   1.1   brezak 		configfilename = *argv;
    136   1.1   brezak 	    } else
    137   1.1   brezak 		goto usage;
    138   1.4  mycroft 	} else if (strcmp(*argv, "-p") == 0) {
    139   1.4  mycroft 	    pruning = 0;
    140   1.6  mycroft #ifdef SNMP
    141   1.6  mycroft    } else if (strcmp(*argv, "-P") == 0) {
    142   1.6  mycroft 	    if (argc > 1 && isdigit(*(argv + 1)[0])) {
    143   1.6  mycroft 		argv++, argc--;
    144   1.6  mycroft 		dest_port = atoi(*argv);
    145   1.6  mycroft 	    } else
    146   1.6  mycroft 		dest_port = DEFAULT_PORT;
    147   1.6  mycroft #endif
    148   1.1   brezak 	} else
    149   1.1   brezak 	    goto usage;
    150   1.1   brezak 	argv++, argc--;
    151   1.1   brezak     }
    152   1.1   brezak 
    153   1.1   brezak     if (argc > 0) {
    154   1.4  mycroft usage:	fprintf(stderr,
    155   1.4  mycroft 		"usage: mrouted [-p] [-c configfile] [-d [debug_level]]\n");
    156   1.1   brezak 	exit(1);
    157   1.1   brezak     }
    158   1.1   brezak 
    159   1.1   brezak     if (debug == 0) {
    160   1.1   brezak 	/*
    161   1.1   brezak 	 * Detach from the terminal
    162   1.1   brezak 	 */
    163  1.12  thorpej 	if (daemon(0, 0))
    164  1.12  thorpej 	    err(1, "can't fork");
    165  1.12  thorpej 	pidfile(NULL);
    166   1.1   brezak     }
    167   1.4  mycroft     else
    168   1.4  mycroft 	fprintf(stderr, "debug level %u\n", debug);
    169   1.1   brezak 
    170   1.1   brezak #ifdef LOG_DAEMON
    171   1.1   brezak     (void)openlog("mrouted", LOG_PID, LOG_DAEMON);
    172   1.1   brezak     (void)setlogmask(LOG_UPTO(LOG_NOTICE));
    173   1.1   brezak #else
    174   1.1   brezak     (void)openlog("mrouted", LOG_PID);
    175   1.1   brezak #endif
    176   1.6  mycroft     sprintf(versionstring, "mrouted version %d.%d",
    177   1.1   brezak 			PROTOCOL_VERSION, MROUTED_VERSION);
    178   1.1   brezak 
    179   1.6  mycroft     log(LOG_NOTICE, 0, "%s", versionstring);
    180   1.6  mycroft 
    181   1.4  mycroft #ifdef SYSV
    182   1.4  mycroft     srand48(time(NULL));
    183   1.4  mycroft #else
    184   1.4  mycroft     srandom(gethostid());
    185   1.4  mycroft #endif
    186   1.4  mycroft 
    187   1.4  mycroft     /*
    188   1.4  mycroft      * Get generation id
    189   1.4  mycroft      */
    190   1.4  mycroft     gettimeofday(&tv, 0);
    191   1.4  mycroft     dvmrp_genid = tv.tv_sec;
    192   1.4  mycroft 
    193   1.4  mycroft     fp = fopen(genidfilename, "r");
    194   1.4  mycroft     if (fp != NULL) {
    195   1.4  mycroft 	fscanf(fp, "%d", &prev_genid);
    196   1.4  mycroft 	if (prev_genid == dvmrp_genid)
    197   1.4  mycroft 	    dvmrp_genid++;
    198   1.4  mycroft 	(void) fclose(fp);
    199   1.4  mycroft     }
    200   1.4  mycroft 
    201   1.4  mycroft     fp = fopen(genidfilename, "w");
    202   1.1   brezak     if (fp != NULL) {
    203   1.4  mycroft 	fprintf(fp, "%d", dvmrp_genid);
    204   1.1   brezak 	(void) fclose(fp);
    205   1.1   brezak     }
    206   1.1   brezak 
    207   1.4  mycroft     callout_init();
    208   1.1   brezak     init_igmp();
    209   1.6  mycroft     init_routes();
    210   1.6  mycroft     init_ktable();
    211   1.1   brezak     k_init_dvmrp();		/* enable DVMRP routing in kernel */
    212   1.4  mycroft 
    213   1.4  mycroft #ifndef OLD_KERNEL
    214   1.4  mycroft     vers = k_get_version();
    215   1.6  mycroft     /*XXX
    216   1.6  mycroft      * This function must change whenever the kernel version changes
    217   1.6  mycroft      */
    218   1.6  mycroft     if ((((vers >> 8) & 0xff) != 3) ||
    219   1.6  mycroft 	 ((vers & 0xff) != 5))
    220   1.4  mycroft 	log(LOG_ERR, 0, "kernel (v%d.%d)/mrouted (v%d.%d) version mismatch",
    221   1.4  mycroft 		(vers >> 8) & 0xff, vers & 0xff,
    222   1.4  mycroft 		PROTOCOL_VERSION, MROUTED_VERSION);
    223   1.4  mycroft #endif
    224   1.4  mycroft 
    225   1.6  mycroft #ifdef SNMP
    226   1.6  mycroft     if (i = snmp_init())
    227   1.6  mycroft        return i;
    228   1.6  mycroft 
    229   1.6  mycroft     gettimeofday(nvp, 0);
    230   1.6  mycroft     if (nvp->tv_usec < 500000L){
    231   1.6  mycroft    svp->tv_usec = nvp->tv_usec + 500000L;
    232   1.6  mycroft    svp->tv_sec = nvp->tv_sec;
    233   1.6  mycroft     } else {
    234   1.6  mycroft    svp->tv_usec = nvp->tv_usec - 500000L;
    235   1.6  mycroft    svp->tv_sec = nvp->tv_sec + 1;
    236   1.6  mycroft     }
    237   1.6  mycroft #endif /* SNMP */
    238   1.6  mycroft 
    239   1.1   brezak     init_vifs();
    240   1.6  mycroft 
    241   1.4  mycroft #ifdef RSRR
    242   1.4  mycroft     rsrr_init();
    243   1.4  mycroft #endif /* RSRR */
    244   1.4  mycroft 
    245   1.4  mycroft #if defined(__STDC__) || defined(__GNUC__)
    246   1.6  mycroft     /*
    247   1.6  mycroft      * Allow cleanup if unexpected exit.  Apparently some architectures
    248   1.4  mycroft      * have a kernel bug where closing the socket doesn't do an
    249   1.4  mycroft      * ip_mrouter_done(), so we attempt to do it on exit.
    250   1.4  mycroft      */
    251   1.4  mycroft     atexit(cleanup);
    252   1.4  mycroft #endif
    253   1.4  mycroft 
    254   1.4  mycroft     if (debug)
    255   1.4  mycroft 	fprintf(stderr, "pruning %s\n", pruning ? "on" : "off");
    256   1.1   brezak 
    257   1.2   brezak     (void)signal(SIGALRM, fasttimer);
    258   1.4  mycroft 
    259   1.4  mycroft     (void)signal(SIGHUP,  restart);
    260   1.4  mycroft     (void)signal(SIGTERM, done);
    261   1.4  mycroft     (void)signal(SIGINT,  done);
    262   1.1   brezak     (void)signal(SIGUSR1, fdump);
    263   1.4  mycroft     (void)signal(SIGUSR2, cdump);
    264   1.1   brezak     if (debug != 0)
    265   1.1   brezak 	(void)signal(SIGQUIT, dump);
    266   1.1   brezak 
    267   1.4  mycroft     FD_ZERO(&readers);
    268   1.4  mycroft     FD_SET(igmp_socket, &readers);
    269   1.4  mycroft     nfds = igmp_socket + 1;
    270   1.4  mycroft     for (i = 0; i < nhandlers; i++) {
    271   1.4  mycroft 	FD_SET(ihandlers[i].fd, &readers);
    272   1.4  mycroft 	if (ihandlers[i].fd >= nfds)
    273   1.4  mycroft 	    nfds = ihandlers[i].fd + 1;
    274   1.4  mycroft     }
    275   1.4  mycroft 
    276   1.6  mycroft     /*
    277   1.6  mycroft      * Install the vifs in the kernel as late as possible in the
    278   1.6  mycroft      * initialization sequence.
    279   1.6  mycroft      */
    280   1.6  mycroft     init_installvifs();
    281   1.6  mycroft 
    282   1.6  mycroft     if (debug >= 2) dump(0);
    283   1.6  mycroft 
    284   1.6  mycroft     /* Start up the log rate-limiter */
    285   1.6  mycroft     resetlogging(NULL);
    286   1.6  mycroft 
    287   1.2   brezak     (void)alarm(1);	 /* schedule first timer interrupt */
    288   1.1   brezak 
    289   1.1   brezak     /*
    290   1.1   brezak      * Main receive loop.
    291   1.1   brezak      */
    292   1.1   brezak     dummy = 0;
    293   1.1   brezak     for(;;) {
    294   1.6  mycroft #ifdef SYSV
    295   1.6  mycroft 	sigset_t block, oblock;
    296   1.6  mycroft #endif
    297   1.4  mycroft 	bcopy((char *)&readers, (char *)&rfds, sizeof(rfds));
    298   1.4  mycroft #ifdef SNMP
    299   1.6  mycroft    gettimeofday(nvp, 0);
    300   1.6  mycroft    if (nvp->tv_sec > svp->tv_sec
    301   1.6  mycroft        || (nvp->tv_sec == svp->tv_sec && nvp->tv_usec > svp->tv_usec)){
    302   1.6  mycroft        alarmTimer(nvp);
    303   1.6  mycroft        eventTimer(nvp);
    304   1.6  mycroft        if (nvp->tv_usec < 500000L){
    305   1.6  mycroft       svp->tv_usec = nvp->tv_usec + 500000L;
    306   1.6  mycroft       svp->tv_sec = nvp->tv_sec;
    307   1.6  mycroft        } else {
    308   1.6  mycroft       svp->tv_usec = nvp->tv_usec - 500000L;
    309   1.6  mycroft       svp->tv_sec = nvp->tv_sec + 1;
    310   1.6  mycroft        }
    311   1.6  mycroft    }
    312   1.6  mycroft 
    313   1.6  mycroft 	tvp =  &timeout;
    314   1.6  mycroft 	tvp->tv_sec = 0;
    315   1.6  mycroft 	tvp->tv_usec = 500000L;
    316   1.6  mycroft 
    317   1.6  mycroft 	block = 0;
    318   1.6  mycroft 	snmp_select_info(&nfds, &rfds, tvp, &block);
    319   1.6  mycroft 	if (block == 1)
    320   1.6  mycroft 		tvp = NULL; /* block without timeout */
    321   1.6  mycroft 	if ((n = select(nfds, &rfds, NULL, NULL, tvp)) < 0)
    322   1.4  mycroft #else
    323   1.6  mycroft 	if ((n = select(nfds, &rfds, NULL, NULL, NULL)) < 0)
    324   1.4  mycroft #endif
    325   1.6  mycroft    {
    326   1.4  mycroft             if (errno != EINTR) /* SIGALRM is expected */
    327   1.4  mycroft                 log(LOG_WARNING, errno, "select failed");
    328   1.4  mycroft             continue;
    329   1.4  mycroft         }
    330   1.4  mycroft 
    331   1.4  mycroft 	if (FD_ISSET(igmp_socket, &rfds)) {
    332   1.4  mycroft 	    recvlen = recvfrom(igmp_socket, recv_buf, RECV_BUF_SIZE,
    333   1.4  mycroft 			       0, NULL, &dummy);
    334   1.4  mycroft 	    if (recvlen < 0) {
    335   1.4  mycroft 		if (errno != EINTR) log(LOG_ERR, errno, "recvfrom");
    336   1.4  mycroft 		continue;
    337   1.4  mycroft 	    }
    338   1.6  mycroft #ifdef SYSV
    339   1.6  mycroft 	    (void)sigemptyset(&block);
    340   1.6  mycroft 	    (void)sigaddset(&block, SIGALRM);
    341   1.6  mycroft 	    if (sigprocmask(SIG_BLOCK, &block, &oblock) < 0)
    342   1.6  mycroft 		    log(LOG_ERR, errno, "sigprocmask");
    343   1.6  mycroft #else
    344   1.4  mycroft 	    omask = sigblock(sigmask(SIGALRM));
    345   1.6  mycroft #endif
    346   1.4  mycroft 	    accept_igmp(recvlen);
    347   1.6  mycroft #ifdef SYSV
    348   1.6  mycroft 	    (void)sigprocmask(SIG_SETMASK, &oblock, (sigset_t *)NULL);
    349   1.6  mycroft #else
    350   1.4  mycroft 	    (void)sigsetmask(omask);
    351   1.6  mycroft #endif
    352   1.4  mycroft         }
    353   1.4  mycroft 
    354   1.4  mycroft 	for (i = 0; i < nhandlers; i++) {
    355   1.4  mycroft 	    if (FD_ISSET(ihandlers[i].fd, &rfds)) {
    356   1.6  mycroft 		(*ihandlers[i].func)(ihandlers[i].fd, &rfds);
    357   1.4  mycroft 	    }
    358   1.1   brezak 	}
    359   1.4  mycroft 
    360   1.4  mycroft #ifdef SNMP
    361   1.6  mycroft 	snmp_read(&rfds);
    362   1.6  mycroft 	snmp_timeout(); /* poll */
    363   1.4  mycroft #endif
    364   1.1   brezak     }
    365   1.1   brezak }
    366   1.1   brezak 
    367   1.1   brezak 
    368   1.1   brezak /*
    369   1.4  mycroft  * routine invoked every second.  Its main goal is to cycle through
    370   1.2   brezak  * the routing table and send partial updates to all neighbors at a
    371   1.2   brezak  * rate that will cause the entire table to be sent in ROUTE_REPORT_INTERVAL
    372   1.2   brezak  * seconds.  Also, every TIMER_INTERVAL seconds it calls timer() to
    373   1.2   brezak  * do all the other time-based processing.
    374   1.2   brezak  */
    375   1.4  mycroft static void
    376   1.6  mycroft fasttimer(i)
    377   1.6  mycroft     int i;
    378   1.2   brezak {
    379   1.2   brezak     static unsigned int tlast;
    380   1.2   brezak     static unsigned int nsent;
    381   1.2   brezak     register unsigned int t = tlast + 1;
    382   1.2   brezak     register int n;
    383   1.2   brezak 
    384   1.2   brezak     /*
    385   1.2   brezak      * if we're in the last second, send everything that's left.
    386   1.2   brezak      * otherwise send at least the fraction we should have sent by now.
    387   1.2   brezak      */
    388   1.2   brezak     if (t >= ROUTE_REPORT_INTERVAL) {
    389   1.2   brezak 	register int nleft = nroutes - nsent;
    390   1.2   brezak 	while (nleft > 0) {
    391   1.2   brezak 	    if ((n = report_next_chunk()) <= 0)
    392   1.2   brezak 		break;
    393   1.2   brezak 	    nleft -= n;
    394   1.2   brezak 	}
    395   1.2   brezak 	tlast = 0;
    396   1.2   brezak 	nsent = 0;
    397   1.2   brezak     } else {
    398   1.2   brezak 	register unsigned int ncum = nroutes * t / ROUTE_REPORT_INTERVAL;
    399   1.2   brezak 	while (nsent < ncum) {
    400   1.2   brezak 	    if ((n = report_next_chunk()) <= 0)
    401   1.2   brezak 		break;
    402   1.2   brezak 	    nsent += n;
    403   1.2   brezak 	}
    404   1.2   brezak 	tlast = t;
    405   1.2   brezak     }
    406   1.2   brezak     if ((t % TIMER_INTERVAL) == 0)
    407   1.2   brezak 	timer();
    408   1.2   brezak 
    409   1.4  mycroft     age_callout_queue();/* Advance the timer for the callout queue
    410   1.4  mycroft 				for groups */
    411   1.2   brezak     alarm(1);
    412   1.2   brezak }
    413   1.2   brezak 
    414   1.2   brezak /*
    415   1.1   brezak  * The 'virtual_time' variable is initialized to a value that will cause the
    416   1.1   brezak  * first invocation of timer() to send a probe or route report to all vifs
    417   1.1   brezak  * and send group membership queries to all subnets for which this router is
    418   1.1   brezak  * querier.  This first invocation occurs approximately TIMER_INTERVAL seconds
    419   1.1   brezak  * after the router starts up.   Note that probes for neighbors and queries
    420   1.1   brezak  * for group memberships are also sent at start-up time, as part of initial-
    421   1.1   brezak  * ization.  This repetition after a short interval is desirable for quickly
    422   1.1   brezak  * building up topology and membership information in the presence of possible
    423   1.1   brezak  * packet loss.
    424   1.1   brezak  *
    425   1.1   brezak  * 'virtual_time' advances at a rate that is only a crude approximation of
    426   1.1   brezak  * real time, because it does not take into account any time spent processing,
    427   1.1   brezak  * and because the timer intervals are sometimes shrunk by a random amount to
    428   1.1   brezak  * avoid unwanted synchronization with other routers.
    429   1.1   brezak  */
    430   1.1   brezak 
    431   1.1   brezak static u_long virtual_time = 0;
    432   1.1   brezak 
    433   1.1   brezak 
    434   1.1   brezak /*
    435   1.1   brezak  * Timer routine.  Performs periodic neighbor probing, route reporting, and
    436   1.1   brezak  * group querying duties, and drives various timers in routing entries and
    437   1.1   brezak  * virtual interface data structures.
    438   1.1   brezak  */
    439   1.4  mycroft static void
    440   1.4  mycroft timer()
    441   1.1   brezak {
    442   1.1   brezak     age_routes();	/* Advance the timers in the route entries     */
    443   1.4  mycroft     age_vifs();		/* Advance the timers for neighbors */
    444   1.4  mycroft     age_table_entry();	/* Advance the timers for the cache entries */
    445   1.1   brezak 
    446   1.1   brezak     if (virtual_time % GROUP_QUERY_INTERVAL == 0) {
    447   1.1   brezak 	/*
    448   1.1   brezak 	 * Time to query the local group memberships on all subnets
    449   1.1   brezak 	 * for which this router is the elected querier.
    450   1.1   brezak 	 */
    451   1.1   brezak 	query_groups();
    452   1.1   brezak     }
    453   1.1   brezak 
    454   1.1   brezak     if (virtual_time % NEIGHBOR_PROBE_INTERVAL == 0) {
    455   1.1   brezak 	/*
    456   1.1   brezak 	 * Time to send a probe on all vifs from which no neighbors have
    457   1.1   brezak 	 * been heard.  Also, check if any inoperative interfaces have now
    458   1.1   brezak 	 * come up.  (If they have, they will also be probed as part of
    459   1.1   brezak 	 * their initialization.)
    460   1.1   brezak 	 */
    461   1.1   brezak 	probe_for_neighbors();
    462   1.1   brezak 
    463   1.1   brezak 	if (vifs_down)
    464   1.1   brezak 	    check_vif_state();
    465   1.1   brezak     }
    466   1.1   brezak 
    467   1.1   brezak     delay_change_reports = FALSE;
    468   1.2   brezak     if (routes_changed) {
    469   1.1   brezak 	/*
    470   1.1   brezak 	 * Some routes have changed since the last timer interrupt, but
    471   1.1   brezak 	 * have not been reported yet.  Report the changed routes to all
    472   1.1   brezak 	 * neighbors.
    473   1.1   brezak 	 */
    474   1.1   brezak 	report_to_all_neighbors(CHANGED_ROUTES);
    475   1.1   brezak     }
    476   1.1   brezak 
    477   1.4  mycroft #ifdef SNMP
    478   1.6  mycroft     sync_timer();
    479   1.4  mycroft #endif
    480   1.4  mycroft 
    481   1.1   brezak     /*
    482   1.2   brezak      * Advance virtual time
    483   1.1   brezak      */
    484   1.1   brezak     virtual_time += TIMER_INTERVAL;
    485   1.1   brezak }
    486   1.1   brezak 
    487   1.1   brezak 
    488   1.1   brezak /*
    489   1.4  mycroft  * On termination, let everyone know we're going away.
    490   1.1   brezak  */
    491   1.4  mycroft static void
    492   1.6  mycroft done(i)
    493   1.6  mycroft     int i;
    494   1.1   brezak {
    495   1.6  mycroft     log(LOG_NOTICE, 0, "%s exiting", versionstring);
    496   1.4  mycroft     cleanup();
    497   1.4  mycroft     _exit(1);
    498   1.4  mycroft }
    499   1.4  mycroft 
    500   1.4  mycroft static void
    501   1.4  mycroft cleanup()
    502   1.4  mycroft {
    503  1.10      mrg     static int in_cleanup = 0;
    504   1.4  mycroft 
    505   1.4  mycroft     if (!in_cleanup) {
    506   1.4  mycroft 	in_cleanup++;
    507   1.4  mycroft #ifdef RSRR
    508   1.4  mycroft 	rsrr_clean();
    509   1.4  mycroft #endif /* RSRR */
    510   1.4  mycroft 	expire_all_routes();
    511   1.4  mycroft 	report_to_all_neighbors(ALL_ROUTES);
    512   1.4  mycroft 	k_stop_dvmrp();
    513   1.4  mycroft     }
    514   1.1   brezak }
    515   1.1   brezak 
    516   1.1   brezak 
    517   1.1   brezak /*
    518   1.1   brezak  * Dump internal data structures to stderr.
    519   1.1   brezak  */
    520   1.4  mycroft static void
    521   1.6  mycroft dump(i)
    522   1.6  mycroft     int i;
    523   1.1   brezak {
    524   1.1   brezak     dump_vifs(stderr);
    525   1.1   brezak     dump_routes(stderr);
    526   1.1   brezak }
    527   1.1   brezak 
    528   1.1   brezak 
    529   1.1   brezak /*
    530   1.1   brezak  * Dump internal data structures to a file.
    531   1.1   brezak  */
    532   1.4  mycroft static void
    533   1.6  mycroft fdump(i)
    534   1.6  mycroft     int i;
    535   1.1   brezak {
    536   1.1   brezak     FILE *fp;
    537   1.1   brezak 
    538   1.1   brezak     fp = fopen(dumpfilename, "w");
    539   1.1   brezak     if (fp != NULL) {
    540   1.1   brezak 	dump_vifs(fp);
    541   1.1   brezak 	dump_routes(fp);
    542   1.1   brezak 	(void) fclose(fp);
    543   1.1   brezak     }
    544   1.1   brezak }
    545   1.1   brezak 
    546   1.1   brezak 
    547   1.1   brezak /*
    548   1.4  mycroft  * Dump local cache contents to a file.
    549   1.4  mycroft  */
    550   1.4  mycroft static void
    551   1.6  mycroft cdump(i)
    552   1.6  mycroft     int i;
    553   1.4  mycroft {
    554   1.4  mycroft     FILE *fp;
    555   1.4  mycroft 
    556   1.4  mycroft     fp = fopen(cachefilename, "w");
    557   1.4  mycroft     if (fp != NULL) {
    558   1.4  mycroft 	dump_cache(fp);
    559   1.4  mycroft 	(void) fclose(fp);
    560   1.4  mycroft     }
    561   1.4  mycroft }
    562   1.4  mycroft 
    563   1.4  mycroft 
    564   1.4  mycroft /*
    565   1.4  mycroft  * Restart mrouted
    566   1.4  mycroft  */
    567   1.4  mycroft static void
    568   1.6  mycroft restart(i)
    569   1.6  mycroft     int i;
    570   1.4  mycroft {
    571   1.4  mycroft     register int omask;
    572   1.6  mycroft #ifdef SYSV
    573   1.6  mycroft     sigset_t block, oblock;
    574   1.6  mycroft #endif
    575   1.4  mycroft 
    576   1.6  mycroft     log(LOG_NOTICE, 0, "%s restart", versionstring);
    577   1.4  mycroft 
    578   1.4  mycroft     /*
    579   1.4  mycroft      * reset all the entries
    580   1.4  mycroft      */
    581   1.6  mycroft #ifdef SYSV
    582   1.6  mycroft     (void)sigemptyset(&block);
    583   1.6  mycroft     (void)sigaddset(&block, SIGALRM);
    584   1.6  mycroft     if (sigprocmask(SIG_BLOCK, &block, &oblock) < 0)
    585   1.6  mycroft 	log(LOG_ERR, errno, "sigprocmask");
    586   1.6  mycroft #else
    587   1.4  mycroft     omask = sigblock(sigmask(SIGALRM));
    588   1.6  mycroft #endif
    589   1.4  mycroft     free_all_prunes();
    590   1.4  mycroft     free_all_routes();
    591   1.4  mycroft     stop_all_vifs();
    592   1.4  mycroft     k_stop_dvmrp();
    593   1.4  mycroft     close(igmp_socket);
    594   1.4  mycroft     close(udp_socket);
    595   1.4  mycroft 
    596   1.4  mycroft     /*
    597   1.4  mycroft      * start processing again
    598   1.4  mycroft      */
    599   1.4  mycroft     dvmrp_genid++;
    600   1.4  mycroft     pruning = 1;
    601   1.4  mycroft 
    602   1.4  mycroft     init_igmp();
    603   1.4  mycroft     init_routes();
    604   1.4  mycroft     init_ktable();
    605   1.4  mycroft     init_vifs();
    606   1.6  mycroft     k_init_dvmrp();		/* enable DVMRP routing in kernel */
    607   1.6  mycroft     init_installvifs();
    608   1.4  mycroft 
    609   1.6  mycroft #ifdef SYSV
    610   1.6  mycroft     (void)sigprocmask(SIG_SETMASK, &oblock, (sigset_t *)NULL);
    611   1.6  mycroft #else
    612   1.4  mycroft     (void)sigsetmask(omask);
    613   1.6  mycroft #endif
    614   1.4  mycroft }
    615   1.4  mycroft 
    616   1.6  mycroft #define LOG_MAX_MSGS	20	/* if > 20/minute then shut up for a while */
    617   1.6  mycroft #define LOG_SHUT_UP	600	/* shut up for 10 minutes */
    618   1.6  mycroft static int log_nmsgs = 0;
    619   1.6  mycroft 
    620   1.6  mycroft static void
    621   1.6  mycroft resetlogging(arg)
    622   1.6  mycroft     void *arg;
    623   1.6  mycroft {
    624   1.6  mycroft     int nxttime = 60;
    625   1.6  mycroft     void *narg = NULL;
    626   1.6  mycroft 
    627   1.6  mycroft     if (arg == NULL && log_nmsgs > LOG_MAX_MSGS) {
    628   1.6  mycroft 	nxttime = LOG_SHUT_UP;
    629   1.6  mycroft 	narg = (void *)&log_nmsgs;	/* just need some valid void * */
    630   1.6  mycroft 	syslog(LOG_WARNING, "logging too fast, shutting up for %d minutes",
    631   1.6  mycroft 			LOG_SHUT_UP / 60);
    632   1.6  mycroft     } else {
    633   1.6  mycroft 	log_nmsgs = 0;
    634   1.6  mycroft     }
    635   1.6  mycroft 
    636   1.6  mycroft     timer_setTimer(nxttime, resetlogging, narg);
    637   1.6  mycroft }
    638   1.4  mycroft 
    639   1.4  mycroft /*
    640   1.1   brezak  * Log errors and other messages to the system log daemon and to stderr,
    641   1.1   brezak  * according to the severity of the message and the current debug level.
    642   1.1   brezak  * For errors of severity LOG_ERR or worse, terminate the program.
    643   1.1   brezak  */
    644   1.6  mycroft #ifdef __STDC__
    645   1.6  mycroft void
    646   1.6  mycroft log(int severity, int syserr, char *format, ...)
    647   1.6  mycroft {
    648   1.6  mycroft     va_list ap;
    649   1.6  mycroft     static char fmt[211] = "warning - ";
    650   1.6  mycroft     char *msg;
    651   1.6  mycroft     char tbuf[20];
    652   1.6  mycroft     struct timeval now;
    653   1.6  mycroft     struct tm *thyme;
    654   1.8      cgd     time_t t;
    655   1.6  mycroft 
    656   1.6  mycroft     va_start(ap, format);
    657   1.6  mycroft #else
    658   1.4  mycroft /*VARARGS3*/
    659   1.4  mycroft void
    660   1.4  mycroft log(severity, syserr, format, va_alist)
    661   1.1   brezak     int severity, syserr;
    662   1.1   brezak     char *format;
    663   1.4  mycroft     va_dcl
    664   1.1   brezak {
    665   1.4  mycroft     va_list ap;
    666   1.4  mycroft     static char fmt[211] = "warning - ";
    667   1.4  mycroft     char *msg;
    668   1.4  mycroft     char tbuf[20];
    669   1.4  mycroft     struct timeval now;
    670   1.4  mycroft     struct tm *thyme;
    671   1.8      cgd     time_t t;
    672   1.4  mycroft 
    673   1.4  mycroft     va_start(ap);
    674   1.6  mycroft #endif
    675   1.4  mycroft     vsprintf(&fmt[10], format, ap);
    676   1.4  mycroft     va_end(ap);
    677   1.4  mycroft     msg = (severity == LOG_WARNING) ? fmt : &fmt[10];
    678   1.1   brezak 
    679   1.1   brezak     switch (debug) {
    680   1.1   brezak 	case 0: break;
    681   1.1   brezak 	case 1: if (severity > LOG_NOTICE) break;
    682   1.1   brezak 	case 2: if (severity > LOG_INFO  ) break;
    683   1.1   brezak 	default:
    684   1.4  mycroft 	    gettimeofday(&now,NULL);
    685   1.8      cgd 	    t = now.tv_sec;
    686   1.8      cgd 	    thyme = localtime(&t);
    687   1.4  mycroft 	    strftime(tbuf, sizeof(tbuf), "%X.%%03d ", thyme);
    688   1.4  mycroft 	    fprintf(stderr, tbuf, now.tv_usec / 1000);
    689   1.4  mycroft 	    fprintf(stderr, "%s", msg);
    690   1.1   brezak 	    if (syserr == 0)
    691   1.1   brezak 		fprintf(stderr, "\n");
    692   1.1   brezak 	    else
    693  1.11   kleink 		fprintf(stderr, ": %s\n", strerror(syserr));
    694   1.1   brezak     }
    695   1.1   brezak 
    696   1.1   brezak     if (severity <= LOG_NOTICE) {
    697   1.6  mycroft 	if (log_nmsgs++ < LOG_MAX_MSGS) {
    698   1.6  mycroft 	    if (syserr != 0) {
    699   1.6  mycroft 		errno = syserr;
    700   1.6  mycroft 		syslog(severity, "%s: %m", msg);
    701   1.6  mycroft 	    } else
    702   1.6  mycroft 		syslog(severity, "%s", msg);
    703   1.6  mycroft 	}
    704   1.1   brezak 
    705   1.1   brezak 	if (severity <= LOG_ERR) exit(-1);
    706   1.1   brezak     }
    707   1.1   brezak }
    708   1.6  mycroft 
    709   1.6  mycroft #ifdef DEBUG_MFC
    710   1.6  mycroft void
    711   1.6  mycroft md_log(what, origin, mcastgrp)
    712   1.6  mycroft     int what;
    713   1.6  mycroft     u_int32_t origin, mcastgrp;
    714   1.6  mycroft {
    715   1.6  mycroft     static FILE *f = NULL;
    716   1.6  mycroft     struct timeval tv;
    717   1.6  mycroft     u_int32_t buf[4];
    718   1.6  mycroft 
    719   1.6  mycroft     if (!f) {
    720   1.6  mycroft 	if ((f = fopen("/tmp/mrouted.clog", "w")) == NULL) {
    721   1.6  mycroft 	    log(LOG_ERR, errno, "open /tmp/mrouted.clog");
    722   1.6  mycroft 	}
    723   1.6  mycroft     }
    724   1.6  mycroft 
    725   1.6  mycroft     gettimeofday(&tv, NULL);
    726   1.6  mycroft     buf[0] = tv.tv_sec;
    727   1.6  mycroft     buf[1] = what;
    728   1.6  mycroft     buf[2] = origin;
    729   1.6  mycroft     buf[3] = mcastgrp;
    730   1.6  mycroft 
    731   1.6  mycroft     fwrite(buf, sizeof(u_int32_t), 4, f);
    732   1.6  mycroft }
    733   1.6  mycroft #endif
    734