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