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

    1: /*
    2:  *  Copyright (c) 1998 by the University of Oregon.
    3:  *  All rights reserved.
    4:  *
    5:  *  Permission to use, copy, modify, and distribute this software and
    6:  *  its documentation in source and binary forms for lawful
    7:  *  purposes and without fee is hereby granted, provided
    8:  *  that the above copyright notice appear in all copies and that both
    9:  *  the copyright notice and this permission notice appear in supporting
   10:  *  documentation, and that any documentation, advertising materials,
   11:  *  and other materials related to such distribution and use acknowledge
   12:  *  that the software was developed by the University of Oregon.
   13:  *  The name of the University of Oregon may not be used to endorse or 
   14:  *  promote products derived from this software without specific prior 
   15:  *  written permission.
   16:  *
   17:  *  THE UNIVERSITY OF OREGON DOES NOT MAKE ANY REPRESENTATIONS
   18:  *  ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE.  THIS SOFTWARE IS
   19:  *  PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
   20:  *  INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
   21:  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND 
   22:  *  NON-INFRINGEMENT.
   23:  *
   24:  *  IN NO EVENT SHALL UO, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
   25:  *  SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT,
   26:  *  TORT, OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH,
   27:  *  THE USE OR PERFORMANCE OF THIS SOFTWARE.
   28:  *
   29:  *  Other copyrights might apply to parts of this software and are so
   30:  *  noted when applicable.
   31:  */
   32: /*
   33:  *  Questions concerning this software should be directed to 
   34:  *  Kurt Windisch (kurtw@antc.uoregon.edu)
   35:  *
   36:  *  $Id: main.c,v 1.1.1.1 2017/06/12 07:58:55 misho Exp $
   37:  */
   38: /*
   39:  * Part of this program has been derived from PIM sparse-mode pimd.
   40:  * The pimd program is covered by the license in the accompanying file
   41:  * named "LICENSE.pimd".
   42:  *  
   43:  * The pimd program is COPYRIGHT 1998 by University of Southern California.
   44:  *
   45:  * Part of this program has been derived from mrouted.
   46:  * The mrouted program is covered by the license in the accompanying file
   47:  * named "LICENSE.mrouted".
   48:  * 
   49:  * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
   50:  * Leland Stanford Junior University.
   51:  *
   52:  */
   53: 
   54: #include "defs.h"
   55: 
   56: #ifdef SNMP
   57: #include "snmp.h"
   58: #endif
   59: 
   60: char configfilename[256] = _PATH_PIMD_CONF;
   61: char versionstring[100];
   62: 
   63: static char pidfilename[]  = _PATH_PIMD_PID;
   64: /* TODO: not used
   65: static char genidfilename[] = _PATH_PIMD_GENID;
   66: */
   67: 
   68: int haveterminal = 1;
   69: char *progname;
   70: 
   71: static int sighandled = 0;
   72: #define GOT_SIGINT      0x01
   73: #define GOT_SIGHUP      0x02
   74: #define GOT_SIGUSR1     0x04
   75: #define GOT_SIGUSR2     0x08
   76: #define GOT_SIGALRM     0x10
   77: 
   78: 
   79: #ifdef SNMP
   80: #define NHANDLERS       34
   81: #else
   82: #define NHANDLERS       3
   83: #endif
   84: 
   85: static struct ihandler {
   86:     int fd;			/* File descriptor               */
   87:     ihfunc_t func;		/* Function to call with &fd_set */
   88: } ihandlers[NHANDLERS];
   89: static int nhandlers = 0;
   90: 
   91: static struct debugname {
   92:     char *name;
   93:     int	 level;
   94:     int	 nchars;
   95: } debugnames[] = {
   96:     {   "dvmrp_detail",	    DEBUG_DVMRP_DETAIL,   5	    },
   97:     {   "dvmrp_prunes",	    DEBUG_DVMRP_PRUNE,    8	    },
   98:     {   "dvmrp_pruning",    DEBUG_DVMRP_PRUNE,    8	    },
   99:     {   "dvmrp_mrt",        DEBUG_DVMRP_ROUTE,    7	    },
  100:     {   "dvmrp_routes",	    DEBUG_DVMRP_ROUTE,    7	    },
  101:     {   "dvmrp_routing",    DEBUG_DVMRP_ROUTE,    7	    },
  102:     {   "dvmrp_neighbors",  DEBUG_DVMRP_PEER,     7	    },
  103:     {   "dvmrp_peers",	    DEBUG_DVMRP_PEER,     8	    },
  104:     {   "dvmrp_hello",      DEBUG_DVMRP_PEER,     7	    },
  105:     {   "dvmrp_timers",	    DEBUG_DVMRP_TIMER,    7	    },
  106:     {   "dvmrp",	    DEBUG_DVMRP,          1	    },
  107:     {   "igmp_proto",	    DEBUG_IGMP_PROTO,     6	    },
  108:     {   "igmp_timers",	    DEBUG_IGMP_TIMER,     6	    },
  109:     {   "igmp_members",	    DEBUG_IGMP_MEMBER,    6	    },
  110:     {   "groups",	    DEBUG_MEMBER,         1	    },
  111:     {   "membership",       DEBUG_MEMBER,         2	    },
  112:     {   "igmp",	            DEBUG_IGMP, 	  1	    },
  113:     {   "trace",	    DEBUG_TRACE,          2	    },
  114:     {   "mtrace",	    DEBUG_TRACE,          2	    },
  115:     {   "traceroute",       DEBUG_TRACE,          2	    },
  116:     {   "timeout",	    DEBUG_TIMEOUT,        2	    },
  117:     {   "callout",	    DEBUG_TIMEOUT,        3	    },
  118:     {   "pkt",	            DEBUG_PKT,  	  2	    },
  119:     {   "packets",	    DEBUG_PKT,  	  2	    },
  120:     {   "interfaces",       DEBUG_IF,   	  2	    },
  121:     {   "vif",	            DEBUG_IF,   	  1	    },
  122:     {   "kernel",           DEBUG_KERN,           2	    },
  123:     {   "cache",            DEBUG_MFC,   	  1	    },
  124:     {   "mfc",              DEBUG_MFC,  	  2	    },
  125:     {   "k_cache",          DEBUG_MFC,  	  2	    },
  126:     {   "k_mfc",            DEBUG_MFC,  	  2	    },
  127:     {   "rsrr",	            DEBUG_RSRR, 	  2	    },
  128:     {   "pim_detail",       DEBUG_PIM_DETAIL,     5	    },
  129:     {   "pim_hello",        DEBUG_PIM_HELLO,      5	    },
  130:     {   "pim_neighbors",    DEBUG_PIM_HELLO,      5	    },
  131:     {   "pim_register",     DEBUG_PIM_REGISTER,   5	    },
  132:     {   "registers",        DEBUG_PIM_REGISTER,   2	    },
  133:     {   "pim_join_prune",   DEBUG_PIM_JOIN_PRUNE, 5	    },
  134:     {   "pim_j_p",          DEBUG_PIM_JOIN_PRUNE, 5	    },
  135:     {   "pim_jp",           DEBUG_PIM_JOIN_PRUNE, 5	    },
  136:     {   "pim_graft",        DEBUG_PIM_GRAFT,      5         },
  137:     {   "pim_bootstrap",    DEBUG_PIM_BOOTSTRAP,  5	    },
  138:     {   "pim_bsr",          DEBUG_PIM_BOOTSTRAP,  5	    },
  139:     {   "bsr",	            DEBUG_PIM_BOOTSTRAP,  1	    },
  140:     {   "bootstrap",        DEBUG_PIM_BOOTSTRAP,  1	    },
  141:     {   "pim_asserts",      DEBUG_PIM_ASSERT,     5	    },
  142:     {   "pim_cand_rp",      DEBUG_PIM_CAND_RP,    5	    },
  143:     {   "pim_c_rp",         DEBUG_PIM_CAND_RP,    5	    },
  144:     {   "pim_rp",           DEBUG_PIM_CAND_RP,    6	    },
  145:     {   "rp",	            DEBUG_PIM_CAND_RP,    2	    },
  146:     {   "pim_routes",       DEBUG_PIM_MRT,        6	    },
  147:     {   "pim_routing",      DEBUG_PIM_MRT,        6	    },
  148:     {   "pim_mrt",          DEBUG_PIM_MRT,        5	    },
  149:     {   "pim_timers",       DEBUG_PIM_TIMER,      5	    },
  150:     {   "pim_rpf",          DEBUG_PIM_RPF,        6	    },
  151:     {   "rpf",              DEBUG_RPF,            3	    },
  152:     {   "pim",              DEBUG_PIM,  	  1	    },
  153:     {   "routes",	    DEBUG_MRT,            1	    },
  154:     {   "routing",	    DEBUG_MRT,            1	    },
  155:     {   "mrt",  	    DEBUG_MRT,            1	    },
  156:     {   "routers",          DEBUG_NEIGHBORS,      6	    },
  157:     {   "mrouters",         DEBUG_NEIGHBORS,      7	    },
  158:     {   "neighbors",        DEBUG_NEIGHBORS,      1	    },
  159:     {   "timers",           DEBUG_TIMER,          1	    },
  160:     {   "asserts",          DEBUG_ASSERT,         1	    },
  161:     {   "all",              DEBUG_ALL,            2         },
  162:     {   "3",	            0xffffffff,           1	    }    /* compat. */
  163: };
  164: 
  165: /*
  166:  * Forward declarations.
  167:  */
  168: static void handler __P((int));
  169: static void timer __P((void *));
  170: static void cleanup __P((void));
  171: static void restart __P((int));
  172: static void cleanup __P((void));
  173: static void resetlogging __P((void *));
  174: 
  175: 
  176: /* To shut up gcc -Wstrict-prototypes */
  177: int main __P((int argc, char **argv));
  178: 
  179: int
  180: register_input_handler(fd, func)
  181:     int fd;
  182: ihfunc_t func;
  183: {
  184:     if (nhandlers >= NHANDLERS)
  185: 	return -1;
  186:     
  187:     ihandlers[nhandlers].fd = fd;
  188:     ihandlers[nhandlers++].func = func;
  189:     
  190:     return 0;
  191: }
  192: 
  193: int
  194: main(argc, argv)
  195:     int argc;
  196:     char *argv[];
  197: {	
  198:     int dummy, dummysigalrm;
  199:     FILE *fp;
  200:     struct timeval tv, difftime, curtime, lasttime, *timeout;
  201:     fd_set rfds, readers;
  202:     int nfds, n, i, secs;
  203:     extern char todaysversion[];
  204:     struct sigaction sa;
  205:     struct debugname *d;
  206:     char c;
  207:     int tmpd;
  208: 
  209:     
  210:     setlinebuf(stderr);
  211: 	
  212:     if (geteuid() != 0) {
  213: 	fprintf(stderr, "pimdd: must be root\n");
  214: 	exit(1);
  215:     }
  216:     
  217:     progname = strrchr(argv[0], '/');
  218:     if (progname)
  219: 	progname++;
  220:     else
  221: 	progname = argv[0];
  222:     
  223:     argv++;
  224:     argc--;
  225:     while (argc > 0 && *argv[0] == '-') {
  226: 	if (strcmp(*argv, "-d") == 0) {
  227: 	    if (argc > 1 && *(argv + 1)[0] != '-') { 
  228: 		char *p,*q;
  229: 		int i, len;
  230: 		struct debugname *d;
  231: 		
  232: 		argv++;
  233: 		argc--;
  234: 		debug = 0;
  235: 		p = *argv; q = NULL;
  236: 		while (p) {
  237: 		    q = strchr(p, ',');
  238: 		    if (q)
  239: 			*q++ = '\0';
  240: 		    len = strlen(p);
  241: 		    for (i = 0, d = debugnames;
  242: 			 i < sizeof(debugnames) / sizeof(debugnames[0]);
  243: 			 i++, d++)
  244: 			if (len >= d->nchars && strncmp(d->name, p, len) == 0)
  245: 			    break;
  246: 		    if (i == sizeof(debugnames) / sizeof(debugnames[0])) {
  247: 			int j = 0xffffffff;
  248: 			int k = 0;
  249: 			fprintf(stderr, "Valid debug levels: ");
  250: 			for (i = 0, d = debugnames;
  251: 			     i < sizeof(debugnames) / sizeof(debugnames[0]);
  252: 			     i++, d++) {
  253: 			    if ((j & d->level) == d->level) {
  254: 				if (k++)
  255: 				    putc(',', stderr);
  256: 				fputs(d->name, stderr);
  257: 				j &= ~d->level;
  258: 			    }
  259: 			}
  260: 			putc('\n', stderr);
  261: 			goto usage;
  262: 		    }
  263: 		    debug |= d->level;
  264: 		    p = q;
  265: 		}
  266: 	    }
  267: 	    else
  268: 		debug = DEBUG_DEFAULT;
  269: 	}
  270: 	else if (strcmp(*argv, "-c") == 0) {
  271: 	    if (argc > 1) {
  272: 		argv++; argc--;
  273: 		strcpy(configfilename, *argv);
  274: 	    }
  275: 	    else
  276: 		goto usage;
  277: /* TODO: not implemented */
  278: #ifdef SNMP
  279: 	}
  280: 	else if (strcmp(*argv, "-P") == 0) {
  281: 	    if (argc > 1 && isdigit(*(argv + 1)[0])) {
  282: 		argv++, argc--;
  283: 		dest_port = atoi(*argv);
  284: 	    }
  285: 	    else
  286: 		dest_port = DEFAULT_PORT;
  287: #endif
  288: 	}
  289: 	else
  290: 	    goto usage;
  291: 	argv++; argc--;
  292:     }
  293: 
  294:     if (argc > 0) {
  295:     usage:
  296: 	tmpd = 0xffffffff;
  297: 	fprintf(stderr, "usage: pimdd [-c configfile] [-d [debug_level][,debug_level]]\n");
  298: 	
  299: 	fprintf(stderr, "debug levels: ");
  300:     c = '(';
  301:     for (d = debugnames; d < debugnames +
  302: 	     sizeof(debugnames) / sizeof(debugnames[0]); d++) {
  303: 	if ((tmpd & d->level) == d->level) {
  304: 	    tmpd &= ~d->level;
  305: 	    fprintf(stderr, "%c%s", c, d->name);
  306: 	    c = ',';
  307: 	}
  308:     }
  309:     fprintf(stderr, ")\n");
  310:     exit(1);
  311:     }	
  312:     
  313:     if (debug != 0) {
  314: 	tmpd = debug;
  315: 	fprintf(stderr, "debug level 0x%lx ", debug);
  316: 	c = '(';
  317: 	for (d = debugnames; d < debugnames +
  318: 		 sizeof(debugnames) / sizeof(debugnames[0]); d++) {
  319: 	    if ((tmpd & d->level) == d->level) {
  320: 		tmpd &= ~d->level;
  321: 		fprintf(stderr, "%c%s", c, d->name);
  322: 		c = ',';
  323: 	    }
  324: 	}
  325: 	fprintf(stderr, ")\n");
  326:     }
  327:     
  328: #ifdef LOG_DAEMON
  329:     (void)openlog("pimdd", LOG_PID, LOG_DAEMON);
  330:     (void)setlogmask(LOG_UPTO(LOG_NOTICE));
  331: #else
  332:     (void)openlog("pimdd", LOG_PID);
  333: #endif /* LOG_DAEMON */
  334:     sprintf(versionstring, "pimdd version %s", todaysversion);
  335:     
  336:     log(LOG_DEBUG, 0, "%s starting", versionstring);
  337:     
  338: /* TODO: XXX: use a combination of time and hostid to initialize the random
  339:  * generator.
  340:  */
  341: #ifdef SYSV
  342:     srand48(time(NULL));
  343: #else
  344:     srandom(gethostid());
  345: #endif
  346:     
  347:     /* Start up the log rate-limiter */
  348:     resetlogging(NULL);
  349: 
  350:     callout_init();
  351:     init_igmp();
  352:     init_pim();
  353: #ifdef HAVE_ROUTING_SOCKETS
  354:     init_routesock();
  355: #endif /* HAVE_ROUTING_SOCKETS */
  356:     init_pim_mrt();
  357:     init_timers();
  358:     
  359:     /* TODO: check the kernel DVMRP/MROUTED/PIM support version */
  360:     
  361: #ifdef SNMP
  362:     if (i = snmp_init())
  363: 	return i;
  364: #endif /* SNMP */
  365:     init_vifs();
  366:     
  367: #ifdef RSRR
  368:     rsrr_init();
  369: #endif /* RSRR */
  370: 
  371:     sa.sa_handler = handler;
  372:     sa.sa_flags = 0;	/* Interrupt system calls */
  373:     sigemptyset(&sa.sa_mask);
  374:     sigaction(SIGALRM, &sa, NULL);
  375:     sigaction(SIGHUP, &sa, NULL);
  376:     sigaction(SIGTERM, &sa, NULL);
  377:     sigaction(SIGINT, &sa, NULL);
  378:     sigaction(SIGUSR1, &sa, NULL);
  379:     sigaction(SIGUSR2, &sa, NULL);
  380:     
  381:     FD_ZERO(&readers);
  382:     FD_SET(igmp_socket, &readers);
  383:     nfds = igmp_socket + 1;
  384:     for (i = 0; i < nhandlers; i++) {
  385: 	FD_SET(ihandlers[i].fd, &readers);
  386: 	if (ihandlers[i].fd >= nfds)
  387: 	    nfds = ihandlers[i].fd + 1;
  388:     }
  389:     
  390:     IF_DEBUG(DEBUG_IF)
  391: 	dump_vifs(stderr);
  392:     IF_DEBUG(DEBUG_PIM_MRT)
  393: 	dump_pim_mrt(stderr);
  394:     
  395:     /* schedule first timer interrupt */
  396:     timer_setTimer(TIMER_INTERVAL, timer, NULL);
  397:     
  398:     if (debug == 0) {
  399: 	/* Detach from the terminal */
  400: #ifdef TIOCNOTTY
  401:       int t;
  402: #endif /* TIOCNOTTY */
  403:       
  404: 	haveterminal = 0;
  405: 	if (fork())
  406: 	    exit(0);
  407: 	(void)close(0);
  408: 	(void)close(1);
  409: 	(void)close(2);
  410: 	(void)open("/", 0);
  411: 	(void)dup2(0, 1);
  412: 	(void)dup2(0, 2);
  413: #if defined(SYSV) || defined(linux)
  414: 	(void)setpgrp();
  415: #else 
  416: #ifdef TIOCNOTTY
  417: 	t = open("/dev/tty", 2);
  418: 	if (t >= 0) {
  419: 	    (void)ioctl(t, TIOCNOTTY, (char *)0);
  420: 	    (void)close(t);
  421: 	}
  422: #else
  423: 	if (setsid() < 0)
  424: 	    perror("setsid");
  425: #endif /* TIOCNOTTY */
  426: #endif /* SYSV */
  427:     } /* End of child process code */
  428:     
  429:     fp = fopen(pidfilename, "w");
  430:     if (fp != NULL) {
  431: 	fprintf(fp, "%d\n", (int)getpid());
  432: 	(void) fclose(fp);
  433:     }
  434:     
  435:     /*
  436:      * Main receive loop.
  437:      */
  438:     dummy = 0;
  439:     dummysigalrm = SIGALRM;
  440:     difftime.tv_usec = 0;
  441:     gettimeofday(&curtime, NULL);
  442:     lasttime = curtime;
  443:     for(;;) {
  444: 	bcopy((char *)&readers, (char *)&rfds, sizeof(rfds));
  445: 	secs = timer_nextTimer();
  446: 	if (secs == -1)
  447: 	    timeout = NULL;
  448: 	else {
  449: 	   timeout = &tv;
  450: 	   timeout->tv_sec = secs;
  451: 	   timeout->tv_usec = 0;
  452:         }
  453: 	
  454: 	if (sighandled) {
  455: 	    if (sighandled & GOT_SIGINT) {
  456: 		sighandled &= ~GOT_SIGINT;
  457: 		break;
  458: 	    }
  459: 	    if (sighandled & GOT_SIGHUP) {
  460: 		sighandled &= ~GOT_SIGHUP;
  461: 		restart(SIGHUP);
  462: 	    }
  463: 	    if (sighandled & GOT_SIGUSR1) {
  464: 		sighandled &= ~GOT_SIGUSR1;
  465: 		fdump(SIGUSR1);
  466: 	    }
  467: 	    if (sighandled & GOT_SIGUSR2) {
  468: 		sighandled &= ~GOT_SIGUSR2;
  469: 		cdump(SIGUSR2);
  470: 	    }
  471: 	    if (sighandled & GOT_SIGALRM) {
  472: 		sighandled &= ~GOT_SIGALRM;
  473: 		timer(&dummysigalrm);
  474: 	    }
  475: 	}
  476: 	if ((n = select(nfds, &rfds, NULL, NULL, timeout)) < 0) {
  477: 	    if (errno != EINTR) /* SIGALRM is expected */
  478: 		log(LOG_WARNING, errno, "select failed");
  479: 	    continue;
  480: 	}
  481: 
  482: 	/*
  483: 	 * Handle timeout queue.
  484: 	 *
  485: 	 * If select + packet processing took more than 1 second,
  486: 	 * or if there is a timeout pending, age the timeout queue.
  487: 	 *
  488: 	 * If not, collect usec in difftime to make sure that the
  489: 	 * time doesn't drift too badly.
  490: 	 *
  491: 	 * If the timeout handlers took more than 1 second,
  492: 	 * age the timeout queue again.  XXX This introduces the
  493: 	 * potential for infinite loops!
  494: 	 */
  495: 	do {
  496: 	    /*
  497: 	     * If the select timed out, then there's no other
  498: 	     * activity to account for and we don't need to
  499: 	     * call gettimeofday.
  500: 	     */
  501: 	    if (n == 0) {
  502: 		curtime.tv_sec = lasttime.tv_sec + secs;
  503: 		curtime.tv_usec = lasttime.tv_usec;
  504: 		n = -1;	/* don't do this next time through the loop */
  505: 	    } else
  506: 		gettimeofday(&curtime, NULL);
  507: 	    difftime.tv_sec = curtime.tv_sec - lasttime.tv_sec;
  508: 	    difftime.tv_usec += curtime.tv_usec - lasttime.tv_usec;
  509: #ifdef TIMERDEBUG
  510: 	    IF_DEBUG(DEBUG_TIMEOUT)
  511: 		log(LOG_DEBUG, 0, "TIMEOUT: secs %d, diff secs %d, diff usecs %d", secs, difftime.tv_sec, difftime.tv_usec );
  512: #endif
  513: 	    while (difftime.tv_usec > 1000000) {
  514: 		difftime.tv_sec++;
  515: 		difftime.tv_usec -= 1000000;
  516: 	    }
  517: 	    if (difftime.tv_usec < 0) {
  518: 		difftime.tv_sec--;
  519: 		difftime.tv_usec += 1000000;
  520: 	    }
  521: 	    lasttime = curtime;
  522: 	    if (secs == 0 || difftime.tv_sec > 0) {
  523: #ifdef TIMERDEBUG
  524: 		IF_DEBUG(DEBUG_TIMEOUT)
  525: 		    log(LOG_DEBUG, 0, "\taging callouts: secs %d, diff secs %d, diff usecs %d", secs, difftime.tv_sec, difftime.tv_usec );
  526: #endif
  527: 		age_callout_queue(difftime.tv_sec);
  528: 	    }
  529: 	    secs = -1;
  530: 	} while (difftime.tv_sec > 0);
  531: 
  532: 	/* Handle sockets */
  533: 	if (n > 0) {
  534: 	    /* TODO: shall check first igmp_socket for better performance? */
  535: 	    for (i = 0; i < nhandlers; i++) {
  536: 		if (FD_ISSET(ihandlers[i].fd, &rfds)) {
  537: 		    (*ihandlers[i].func)(ihandlers[i].fd, &rfds);
  538: 		}
  539: 	    }
  540: 	}
  541:     
  542:     } /* Main loop */
  543: 
  544:     log(LOG_NOTICE, 0, "%s exiting", versionstring);
  545:     cleanup();
  546:     exit(0);
  547: }
  548: 
  549: /*
  550:  * The 'virtual_time' variable is initialized to a value that will cause the
  551:  * first invocation of timer() to send a probe or route report to all vifs
  552:  * and send group membership queries to all subnets for which this router is
  553:  * querier.  This first invocation occurs approximately TIMER_INTERVAL seconds
  554:  * after the router starts up.   Note that probes for neighbors and queries
  555:  * for group memberships are also sent at start-up time, as part of initial-
  556:  * ization.  This repetition after a short interval is desirable for quickly
  557:  * building up topology and membership information in the presence of possible
  558:  * packet loss.
  559:  *
  560:  * 'virtual_time' advances at a rate that is only a crude approximation of
  561:  * real time, because it does not take into account any time spent processing,
  562:  * and because the timer intervals are sometimes shrunk by a random amount to
  563:  * avoid unwanted synchronization with other routers.
  564:  */
  565: 
  566: u_long virtual_time = 0;
  567: 
  568: /*
  569:  * Timer routine. Performs all perodic functions:
  570:  * aging interfaces, quering neighbors and members, etc... The granularity
  571:  * is equal to TIMER_INTERVAL.
  572:  */
  573: static void 
  574: timer(i)
  575:     void *i;
  576: {
  577:     age_vifs();	        /* Timeout neighbors and groups         */
  578:     age_routes();  	/* Timeout routing entries              */
  579:     
  580:     virtual_time += TIMER_INTERVAL;
  581:     timer_setTimer(TIMER_INTERVAL, timer, NULL);
  582: }	
  583: 
  584: /*
  585:  * Performs all necessary functions to quit gracefully
  586:  */
  587: /* TODO: implement all necessary stuff */
  588: static void
  589: cleanup()
  590: {
  591: 
  592: #ifdef RSRR
  593:     rsrr_clean();
  594: #endif /* RSRR */
  595:     
  596:     /* TODO: XXX (not in the spec)
  597:      */
  598: }
  599: 
  600: 
  601: /*
  602:  * Signal handler.  Take note of the fact that the signal arrived
  603:  * so that the main loop can take care of it.
  604:  */
  605: static void
  606: handler(sig)
  607:     int sig;
  608: {
  609:     switch (sig) {
  610:     case SIGALRM:
  611: 	sighandled |= GOT_SIGALRM;
  612:     case SIGINT:
  613:     case SIGTERM:
  614: 	sighandled |= GOT_SIGINT;
  615: 	break;
  616: 	
  617:     case SIGHUP:
  618: 	sighandled |= GOT_SIGHUP;
  619: 	break;
  620: 	
  621:     case SIGUSR1:
  622: 	sighandled |= GOT_SIGUSR1;
  623: 	break;
  624: 	
  625:     case SIGUSR2:
  626: 	sighandled |= GOT_SIGUSR2;
  627: 	break;
  628:     }
  629: }
  630: 
  631: 
  632: /* TODO: not verified */
  633: /* PIMDM TODO */
  634: /*
  635:  * Restart the daemon
  636:  */
  637: static void
  638: restart(i)
  639:     int i;
  640: {
  641: #ifdef SNMP
  642:     int s;
  643: #endif /* SNMP */
  644:     
  645:     log(LOG_NOTICE, 0, "% restart", versionstring);
  646:     
  647:     /*
  648:      * reset all the entries
  649:      */
  650:     /* TODO: delete?
  651:        free_all_routes();
  652:        */
  653:     free_all_callouts();
  654:     stop_all_vifs();
  655:     k_stop_pim(igmp_socket);
  656:     close(igmp_socket);
  657:     close(pim_socket);
  658:     close(udp_socket);
  659:     
  660:     /*
  661:      * start processing again
  662:      */
  663:     
  664:     init_igmp();
  665:     init_pim();
  666: #ifdef HAVE_ROUTING_SOCKETS
  667:     init_routesock();
  668: #endif /* HAVE_ROUTING_SOCKETS */
  669:     init_pim_mrt();
  670: #ifdef SNMP
  671:     if ( s = snmp_init())
  672: 	exit(s);
  673: #endif /* SNMP */
  674:     init_vifs();
  675: 
  676: #ifdef RSRR
  677:     rsrr_init();
  678: #endif /* RSRR */
  679: 
  680:     /* schedule timer interrupts */
  681:     timer_setTimer(TIMER_INTERVAL, timer, NULL);
  682: }
  683: 
  684: 
  685: static void
  686: resetlogging(arg)
  687:     void *arg;
  688: {
  689:     int nxttime = 60;
  690:     void *narg = NULL;
  691:     
  692:     if (arg == NULL && log_nmsgs > LOG_MAX_MSGS) {
  693: 	nxttime = LOG_SHUT_UP;
  694: 	narg = (void *)&log_nmsgs;	/* just need some valid void * */
  695: 	syslog(LOG_WARNING, "logging too fast, shutting up for %d minutes",
  696: 	       LOG_SHUT_UP / 60);
  697:     } else {
  698: 	log_nmsgs = 0;
  699:     }
  700:     
  701:     timer_setTimer(nxttime, resetlogging, narg);
  702: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>