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