Annotation of embedaddon/pimdd/main.c, revision 1.1.1.1

1.1       misho       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.13 1998/06/01 15:25:46 kurtw 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>