Annotation of embedaddon/pimdd/main.c, revision 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>