aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin/mrouted/main.c
diff options
context:
space:
mode:
authorBill Fenner <fenner@FreeBSD.org>1999-01-20 07:44:18 +0000
committerBill Fenner <fenner@FreeBSD.org>1999-01-20 07:44:18 +0000
commit1f25327484733d0bec3b33044da7bd5d82ad007f (patch)
tree19c94eeb7ba2b59b0ad53ae0864ebf06723a8afa /usr.sbin/mrouted/main.c
parentce595def0708b60ce4dde9002ac206fae20be240 (diff)
Import mrouted version 3.9-beta3+IOS12 . This is a version of 3.9-beta3vendor/mrouted
with minor changes to work around a bug in Cisco's IOS version 12.0 . 3.9-beta3 is much improved over 3.8, and is only labelled "beta" because of missing features, as opposed to instability or known bugs.
Notes
Notes: svn path=/cvs2svn/branches/XEROX/; revision=42888
Diffstat (limited to 'usr.sbin/mrouted/main.c')
-rw-r--r--usr.sbin/mrouted/main.c694
1 files changed, 495 insertions, 199 deletions
diff --git a/usr.sbin/mrouted/main.c b/usr.sbin/mrouted/main.c
index b5ef723bcb73..1bd147705f9e 100644
--- a/usr.sbin/mrouted/main.c
+++ b/usr.sbin/mrouted/main.c
@@ -7,7 +7,7 @@
* Leland Stanford Junior University.
*
*
- * $Id: main.c,v 3.8 1995/11/29 22:36:34 fenner Rel $
+ * main.c,v 3.8.4.29 1998/03/01 01:49:00 fenner Exp
*/
/*
@@ -33,8 +33,8 @@
#endif
#ifndef lint
-static char rcsid[] =
- "@(#) $Id: main.c,v 3.8 1995/11/29 22:36:34 fenner Rel $";
+static char rcsid[] = "@(#) $Id: \
+main.c,v 3.8.4.29 1998/03/01 01:49:00 fenner Exp $";
#endif
extern char *configfilename;
@@ -45,11 +45,21 @@ static char dumpfilename[] = _PATH_MROUTED_DUMP;
static char cachefilename[] = _PATH_MROUTED_CACHE;
static char genidfilename[] = _PATH_MROUTED_GENID;
+static int haveterminal = 1;
+int did_final_init = 0;
+
+static int sighandled = 0;
+#define GOT_SIGINT 0x01
+#define GOT_SIGHUP 0x02
+#define GOT_SIGUSR1 0x04
+#define GOT_SIGUSR2 0x08
+
int cache_lifetime = DEFAULT_CACHE_LIFETIME;
-int max_prune_lifetime = DEFAULT_CACHE_LIFETIME * 2;
+int prune_lifetime = AVERAGE_PRUNE_LIFETIME;
int debug = 0;
-u_char pruning = 1; /* Enable pruning by default */
+char *progname;
+time_t mrouted_init_time;
#ifdef SNMP
#define NHANDLERS 34
@@ -63,16 +73,48 @@ static struct ihandler {
} ihandlers[NHANDLERS];
static int nhandlers = 0;
+static struct debugname {
+ char *name;
+ int level;
+ int nchars;
+} debugnames[] = {
+ { "packet", DEBUG_PKT, 2 },
+ { "pkt", DEBUG_PKT, 3 },
+ { "pruning", DEBUG_PRUNE, 1 },
+ { "prunes", DEBUG_PRUNE, 1 },
+ { "routing", DEBUG_ROUTE, 1 },
+ { "routes", DEBUG_ROUTE, 1 },
+ { "route_detail", DEBUG_RTDETAIL, 6 },
+ { "rtdetail", DEBUG_RTDETAIL, 2 },
+ { "peers", DEBUG_PEER, 2 },
+ { "neighbors", DEBUG_PEER, 1 },
+ { "cache", DEBUG_CACHE, 1 },
+ { "timeout", DEBUG_TIMEOUT, 1 },
+ { "callout", DEBUG_TIMEOUT, 2 },
+ { "interface", DEBUG_IF, 2 },
+ { "vif", DEBUG_IF, 1 },
+ { "membership", DEBUG_MEMBER, 1 },
+ { "groups", DEBUG_MEMBER, 1 },
+ { "traceroute", DEBUG_TRACE, 2 },
+ { "mtrace", DEBUG_TRACE, 2 },
+ { "igmp", DEBUG_IGMP, 1 },
+ { "icmp", DEBUG_ICMP, 2 },
+ { "rsrr", DEBUG_RSRR, 2 },
+ { "3", 0xffffffff, 1 } /* compat. */
+};
+
/*
* Forward declarations.
*/
-static void fasttimer __P((int));
-static void done __P((int));
-static void dump __P((int));
-static void fdump __P((int));
-static void cdump __P((int));
-static void restart __P((int));
-static void timer __P((void));
+static void final_init __P((void *));
+static void fasttimer __P((void *));
+static void timer __P((void *));
+static void dump __P((void));
+static void dump_version __P((FILE *));
+static void fdump __P((void));
+static void cdump __P((void));
+static void restart __P((void));
+static void handler __P((int));
static void cleanup __P((void));
static void resetlogging __P((void *));
@@ -99,14 +141,15 @@ main(argc, argv)
char *argv[];
{
register int recvlen;
- register int omask;
int dummy;
FILE *fp;
- struct timeval tv;
+ struct timeval tv, difftime, curtime, lasttime, *timeout;
u_int32 prev_genid;
int vers;
fd_set rfds, readers;
- int nfds, n, i;
+ int nfds, n, i, secs;
+ extern char todaysversion[];
+ struct sigaction sa;
#ifdef SNMP
struct timeval timeout, *tvp = &timeout;
struct timeval sched, *svp = &sched, now, *nvp = &now;
@@ -116,16 +159,57 @@ main(argc, argv)
setlinebuf(stderr);
if (geteuid() != 0) {
- fprintf(stderr, "must be root\n");
+ fprintf(stderr, "mrouted: must be root\n");
exit(1);
}
+ progname = strrchr(argv[0], '/');
+ if (progname)
+ progname++;
+ else
+ progname = argv[0];
+
argv++, argc--;
while (argc > 0 && *argv[0] == '-') {
if (strcmp(*argv, "-d") == 0) {
- if (argc > 1 && isdigit(*(argv + 1)[0])) {
+ if (argc > 1 && *(argv + 1)[0] != '-') {
+ char *p,*q;
+ int i, len;
+ struct debugname *d;
+
argv++, argc--;
- debug = atoi(*argv);
+ debug = 0;
+ p = *argv; q = NULL;
+ while (p) {
+ q = strchr(p, ',');
+ if (q)
+ *q++ = '\0';
+ len = strlen(p);
+ for (i = 0, d = debugnames;
+ i < sizeof(debugnames) / sizeof(debugnames[0]);
+ i++, d++)
+ if (len >= d->nchars && strncmp(d->name, p, len) == 0)
+ break;
+ if (i == sizeof(debugnames) / sizeof(debugnames[0])) {
+ int j = 0xffffffff;
+ int k = 0;
+ fprintf(stderr, "Valid debug levels: ");
+ for (i = 0, d = debugnames;
+ i < sizeof(debugnames) / sizeof(debugnames[0]);
+ i++, d++) {
+ if ((j & d->level) == d->level) {
+ if (k++)
+ putc(',', stderr);
+ fputs(d->name, stderr);
+ j &= ~d->level;
+ }
+ }
+ putc('\n', stderr);
+ goto usage;
+ }
+ debug |= d->level;
+ p = q;
+ }
} else
debug = DEFAULT_DEBUG;
} else if (strcmp(*argv, "-c") == 0) {
@@ -135,7 +219,7 @@ main(argc, argv)
} else
goto usage;
} else if (strcmp(*argv, "-p") == 0) {
- pruning = 0;
+ log(LOG_WARNING, 0, "disabling pruning is no longer supported");
#ifdef SNMP
} else if (strcmp(*argv, "-P") == 0) {
if (argc > 1 && isdigit(*(argv + 1)[0])) {
@@ -151,40 +235,27 @@ main(argc, argv)
if (argc > 0) {
usage: fprintf(stderr,
- "usage: mrouted [-p] [-c configfile] [-d [debug_level]]\n");
+ "usage: mrouted [-p] [-c configfile] [-d [debug_level][,debug_level...]]\n");
exit(1);
}
- if (debug == 0) {
- /*
- * Detach from the terminal
- */
- int t;
-
- if (fork()) exit(0);
- (void)close(0);
- (void)close(1);
- (void)close(2);
- (void)open("/", 0);
- (void)dup2(0, 1);
- (void)dup2(0, 2);
-#ifdef SYSV
- (void)setpgrp();
-#else
-#ifdef TIOCNOTTY
- t = open("/dev/tty", 2);
- if (t >= 0) {
- (void)ioctl(t, TIOCNOTTY, (char *)0);
- (void)close(t);
+ if (debug != 0) {
+ struct debugname *d;
+ char c;
+ int tmpd = debug;
+
+ fprintf(stderr, "debug level 0x%x ", debug);
+ c = '(';
+ for (d = debugnames; d < debugnames +
+ sizeof(debugnames) / sizeof(debugnames[0]); d++) {
+ if ((tmpd & d->level) == d->level) {
+ tmpd &= ~d->level;
+ fprintf(stderr, "%c%s", c, d->name);
+ c = ',';
+ }
}
-#else
- if (setsid() < 0)
- perror("setsid");
-#endif
-#endif
+ fprintf(stderr, ")\n");
}
- else
- fprintf(stderr, "debug level %u\n", debug);
#ifdef LOG_DAEMON
(void)openlog("mrouted", LOG_PID, LOG_DAEMON);
@@ -192,10 +263,9 @@ usage: fprintf(stderr,
#else
(void)openlog("mrouted", LOG_PID);
#endif
- sprintf(versionstring, "mrouted version %d.%d",
- PROTOCOL_VERSION, MROUTED_VERSION);
+ sprintf(versionstring, "mrouted version %s", todaysversion);
- log(LOG_NOTICE, 0, "%s", versionstring);
+ log(LOG_DEBUG, 0, "%s starting", versionstring);
#ifdef SYSV
srand48(time(NULL));
@@ -223,14 +293,27 @@ usage: fprintf(stderr,
(void) fclose(fp);
}
+ /* Start up the log rate-limiter */
+ resetlogging(NULL);
+
callout_init();
init_igmp();
+ init_icmp();
+ init_ipip();
init_routes();
init_ktable();
- k_init_dvmrp(); /* enable DVMRP routing in kernel */
-
#ifndef OLD_KERNEL
+ /*
+ * Unfortunately, you can't k_get_version() unless you've
+ * k_init_dvmrp()'d. Now that we want to move the
+ * k_init_dvmrp() to later in the initialization sequence,
+ * we have to do the disgusting hack of initializing,
+ * getting the version, then stopping the kernel multicast
+ * forwarding.
+ */
+ k_init_dvmrp();
vers = k_get_version();
+ k_stop_dvmrp();
/*XXX
* This function must change whenever the kernel version changes
*/
@@ -261,33 +344,14 @@ usage: fprintf(stderr,
rsrr_init();
#endif /* RSRR */
-#if defined(__STDC__) || defined(__GNUC__)
- /*
- * Allow cleanup if unexpected exit. Apparently some architectures
- * have a kernel bug where closing the socket doesn't do an
- * ip_mrouter_done(), so we attempt to do it on exit.
- */
- atexit(cleanup);
-#endif
-
- if (debug)
- fprintf(stderr, "pruning %s\n", pruning ? "on" : "off");
-
- fp = fopen(pidfilename, "w");
- if (fp != NULL) {
- fprintf(fp, "%d\n", (int)getpid());
- (void) fclose(fp);
- }
-
- (void)signal(SIGALRM, fasttimer);
-
- (void)signal(SIGHUP, restart);
- (void)signal(SIGTERM, done);
- (void)signal(SIGINT, done);
- (void)signal(SIGUSR1, fdump);
- (void)signal(SIGUSR2, cdump);
- if (debug != 0)
- (void)signal(SIGQUIT, dump);
+ sa.sa_handler = handler;
+ sa.sa_flags = 0; /* Interrupt system calls */
+ sigemptyset(&sa.sa_mask);
+ sigaction(SIGHUP, &sa, NULL);
+ sigaction(SIGTERM, &sa, NULL);
+ sigaction(SIGINT, &sa, NULL);
+ sigaction(SIGUSR1, &sa, NULL);
+ sigaction(SIGUSR2, &sa, NULL);
FD_ZERO(&readers);
FD_SET(igmp_socket, &readers);
@@ -298,30 +362,82 @@ usage: fprintf(stderr,
nfds = ihandlers[i].fd + 1;
}
- /*
- * Install the vifs in the kernel as late as possible in the
- * initialization sequence.
- */
- init_installvifs();
+ IF_DEBUG(DEBUG_IF)
+ dump_vifs(stderr);
+ IF_DEBUG(DEBUG_ROUTE)
+ dump_routes(stderr);
- if (debug >= 2) dump(0);
+ /* schedule first timer interrupt */
+ timer_setTimer(1, fasttimer, NULL);
+ timer_setTimer(TIMER_INTERVAL, timer, NULL);
- /* Start up the log rate-limiter */
- resetlogging(NULL);
+ if (debug == 0) {
+ /*
+ * Detach from the terminal
+ */
+ int t;
- (void)alarm(1); /* schedule first timer interrupt */
+ haveterminal = 0;
+ if (fork()) exit(0);
+ (void)close(0);
+ (void)close(1);
+ (void)close(2);
+ (void)open("/", 0);
+ (void)dup2(0, 1);
+ (void)dup2(0, 2);
+#if defined(SYSV) || defined(linux)
+ (void)setpgrp();
+#else
+#ifdef TIOCNOTTY
+ t = open("/dev/tty", 2);
+ if (t >= 0) {
+ (void)ioctl(t, TIOCNOTTY, (char *)0);
+ (void)close(t);
+ }
+#else
+ if (setsid() < 0)
+ perror("setsid");
+#endif
+#endif
+ }
+
+ fp = fopen(pidfilename, "w");
+ if (fp != NULL) {
+ fprintf(fp, "%d\n", (int)getpid());
+ (void) fclose(fp);
+ }
+
+ /* XXX HACK
+ * This will cause black holes for the first few seconds after startup,
+ * since we are exchanging routes but not actually forwarding.
+ * However, it eliminates much of the startup transient.
+ *
+ * It's possible that we can set a flag which says not to report any
+ * routes (just accept reports) until this timer fires, and then
+ * do a report_to_all_neighbors(ALL_ROUTES) immediately before
+ * turning on DVMRP.
+ */
+ timer_setTimer(10, final_init, NULL);
/*
* Main receive loop.
*/
dummy = 0;
+ difftime.tv_usec = 0;
+ gettimeofday(&curtime, NULL);
+ lasttime = curtime;
for(;;) {
-#ifdef SYSV
- sigset_t block, oblock;
-#endif
bcopy((char *)&readers, (char *)&rfds, sizeof(rfds));
+ secs = timer_nextTimer();
+ if (secs == -1)
+ timeout = NULL;
+ else {
+ timeout = &tv;
+ timeout->tv_sec = secs;
+ timeout->tv_usec = 0;
+ }
#ifdef SNMP
- gettimeofday(nvp, 0);
+ THIS IS BROKEN
if (nvp->tv_sec > svp->tv_sec
|| (nvp->tv_sec == svp->tv_sec && nvp->tv_usec > svp->tv_usec)){
alarmTimer(nvp);
@@ -344,51 +460,121 @@ usage: fprintf(stderr,
if (block == 1)
tvp = NULL; /* block without timeout */
if ((n = select(nfds, &rfds, NULL, NULL, tvp)) < 0)
-#else
- if ((n = select(nfds, &rfds, NULL, NULL, NULL)) < 0)
#endif
- {
- if (errno != EINTR) /* SIGALRM is expected */
+ if (sighandled) {
+ if (sighandled & GOT_SIGINT) {
+ sighandled &= ~GOT_SIGINT;
+ break;
+ }
+ if (sighandled & GOT_SIGHUP) {
+ sighandled &= ~GOT_SIGHUP;
+ restart();
+ }
+ if (sighandled & GOT_SIGUSR1) {
+ sighandled &= ~GOT_SIGUSR1;
+ fdump();
+ }
+ if (sighandled & GOT_SIGUSR2) {
+ sighandled &= ~GOT_SIGUSR2;
+ cdump();
+ }
+ }
+ if ((n = select(nfds, &rfds, NULL, NULL, timeout)) < 0) {
+ if (errno != EINTR)
log(LOG_WARNING, errno, "select failed");
continue;
}
- if (FD_ISSET(igmp_socket, &rfds)) {
- recvlen = recvfrom(igmp_socket, recv_buf, RECV_BUF_SIZE,
- 0, NULL, &dummy);
- if (recvlen < 0) {
- if (errno != EINTR) log(LOG_ERR, errno, "recvfrom");
- continue;
+ if (n > 0) {
+ if (FD_ISSET(igmp_socket, &rfds)) {
+ recvlen = recvfrom(igmp_socket, recv_buf, RECV_BUF_SIZE,
+ 0, NULL, &dummy);
+ if (recvlen < 0) {
+ if (errno != EINTR) log(LOG_ERR, errno, "recvfrom");
+ continue;
+ }
+ accept_igmp(recvlen);
}
-#ifdef SYSV
- (void)sigemptyset(&block);
- (void)sigaddset(&block, SIGALRM);
- if (sigprocmask(SIG_BLOCK, &block, &oblock) < 0)
- log(LOG_ERR, errno, "sigprocmask");
-#else
- omask = sigblock(sigmask(SIGALRM));
-#endif
- accept_igmp(recvlen);
-#ifdef SYSV
- (void)sigprocmask(SIG_SETMASK, &oblock, (sigset_t *)NULL);
-#else
- (void)sigsetmask(omask);
-#endif
- }
- for (i = 0; i < nhandlers; i++) {
- if (FD_ISSET(ihandlers[i].fd, &rfds)) {
- (*ihandlers[i].func)(ihandlers[i].fd, &rfds);
+ for (i = 0; i < nhandlers; i++) {
+ if (FD_ISSET(ihandlers[i].fd, &rfds)) {
+ (*ihandlers[i].func)(ihandlers[i].fd, &rfds);
+ }
}
}
#ifdef SNMP
+ THIS IS BROKEN
snmp_read(&rfds);
snmp_timeout(); /* poll */
#endif
+ /*
+ * Handle timeout queue.
+ *
+ * If select + packet processing took more than 1 second,
+ * or if there is a timeout pending, age the timeout queue.
+ *
+ * If not, collect usec in difftime to make sure that the
+ * time doesn't drift too badly.
+ *
+ * If the timeout handlers took more than 1 second,
+ * age the timeout queue again. XXX This introduces the
+ * potential for infinite loops!
+ */
+ do {
+ /*
+ * If the select timed out, then there's no other
+ * activity to account for and we don't need to
+ * call gettimeofday.
+ */
+ if (n == 0) {
+ curtime.tv_sec = lasttime.tv_sec + secs;
+ curtime.tv_usec = lasttime.tv_usec;
+ n = -1; /* don't do this next time through the loop */
+ } else
+ gettimeofday(&curtime, NULL);
+ difftime.tv_sec = curtime.tv_sec - lasttime.tv_sec;
+ difftime.tv_usec += curtime.tv_usec - lasttime.tv_usec;
+ while (difftime.tv_usec > 1000000) {
+ difftime.tv_sec++;
+ difftime.tv_usec -= 1000000;
+ }
+ if (difftime.tv_usec < 0) {
+ difftime.tv_sec--;
+ difftime.tv_usec += 1000000;
+ }
+ lasttime = curtime;
+ if (secs == 0 || difftime.tv_sec > 0)
+ age_callout_queue(difftime.tv_sec);
+ secs = -1;
+ } while (difftime.tv_sec > 0);
}
+ log(LOG_NOTICE, 0, "%s exiting", versionstring);
+ cleanup();
+ exit(0);
}
+static void
+final_init(i)
+ void *i;
+{
+ char *s = (char *)i;
+
+ log(LOG_NOTICE, 0, "%s%s", versionstring, s ? s : "");
+ if (s)
+ free(s);
+
+ k_init_dvmrp(); /* enable DVMRP routing in kernel */
+
+ /*
+ * Install the vifs in the kernel as late as possible in the
+ * initialization sequence.
+ */
+ init_installvifs();
+
+ time(&mrouted_init_time);
+ did_final_init = 1;
+}
/*
* routine invoked every second. Its main goal is to cycle through
@@ -399,7 +585,7 @@ usage: fprintf(stderr,
*/
static void
fasttimer(i)
- int i;
+ void *i;
{
static unsigned int tlast;
static unsigned int nsent;
@@ -428,12 +614,8 @@ fasttimer(i)
}
tlast = t;
}
- if ((t % TIMER_INTERVAL) == 0)
- timer();
- age_callout_queue();/* Advance the timer for the callout queue
- for groups */
- alarm(1);
+ timer_setTimer(1, fasttimer, NULL);
}
/*
@@ -453,7 +635,7 @@ fasttimer(i)
* avoid unwanted synchronization with other routers.
*/
-static u_long virtual_time = 0;
+u_long virtual_time = 0;
/*
@@ -462,13 +644,14 @@ static u_long virtual_time = 0;
* virtual interface data structures.
*/
static void
-timer()
+timer(i)
+ void *i;
{
age_routes(); /* Advance the timers in the route entries */
age_vifs(); /* Advance the timers for neighbors */
age_table_entry(); /* Advance the timers for the cache entries */
- if (virtual_time % GROUP_QUERY_INTERVAL == 0) {
+ if (virtual_time % IGMP_QUERY_INTERVAL == 0) {
/*
* Time to query the local group memberships on all subnets
* for which this router is the elected querier.
@@ -507,21 +690,10 @@ timer()
* Advance virtual time
*/
virtual_time += TIMER_INTERVAL;
+ timer_setTimer(TIMER_INTERVAL, timer, NULL);
}
-/*
- * On termination, let everyone know we're going away.
- */
-static void
-done(i)
- int i;
-{
- log(LOG_NOTICE, 0, "%s exiting", versionstring);
- cleanup();
- _exit(1);
-}
-
static void
cleanup()
{
@@ -534,7 +706,36 @@ cleanup()
#endif /* RSRR */
expire_all_routes();
report_to_all_neighbors(ALL_ROUTES);
- k_stop_dvmrp();
+ if (did_final_init)
+ k_stop_dvmrp();
+ }
+}
+
+/*
+ * Signal handler. Take note of the fact that the signal arrived
+ * so that the main loop can take care of it.
+ */
+static void
+handler(sig)
+ int sig;
+{
+ switch (sig) {
+ case SIGINT:
+ case SIGTERM:
+ sighandled |= GOT_SIGINT;
+ break;
+
+ case SIGHUP:
+ sighandled |= GOT_SIGHUP;
+ break;
+
+ case SIGUSR1:
+ sighandled |= GOT_SIGUSR1;
+ break;
+
+ case SIGUSR2:
+ sighandled |= GOT_SIGUSR2;
+ break;
}
}
@@ -543,25 +744,39 @@ cleanup()
* Dump internal data structures to stderr.
*/
static void
-dump(i)
- int i;
+dump()
{
dump_vifs(stderr);
dump_routes(stderr);
}
+static void
+dump_version(fp)
+ FILE *fp;
+{
+ time_t t;
+
+ time(&t);
+ fprintf(fp, "%s ", versionstring);
+ if (did_final_init)
+ fprintf(fp, "up %s",
+ scaletime(t - mrouted_init_time));
+ else
+ fprintf(fp, "(not yet initialized)");
+ fprintf(fp, " %s\n", ctime(&t));
+}
/*
* Dump internal data structures to a file.
*/
static void
-fdump(i)
- int i;
+fdump()
{
FILE *fp;
fp = fopen(dumpfilename, "w");
if (fp != NULL) {
+ dump_version(fp);
dump_vifs(fp);
dump_routes(fp);
(void) fclose(fp);
@@ -573,13 +788,13 @@ fdump(i)
* Dump local cache contents to a file.
*/
static void
-cdump(i)
- int i;
+cdump()
{
FILE *fp;
fp = fopen(cachefilename, "w");
if (fp != NULL) {
+ dump_version(fp);
dump_cache(fp);
(void) fclose(fp);
}
@@ -590,52 +805,42 @@ cdump(i)
* Restart mrouted
*/
static void
-restart(i)
- int i;
+restart()
{
- register int omask;
-#ifdef SYSV
- sigset_t block, oblock;
-#endif
+ char *s;
- log(LOG_NOTICE, 0, "%s restart", versionstring);
+ s = (char *)malloc(sizeof(" restart"));
+ if (s == NULL)
+ log(LOG_ERR, 0, "out of memory");
+ strcpy(s, " restart");
/*
* reset all the entries
*/
-#ifdef SYSV
- (void)sigemptyset(&block);
- (void)sigaddset(&block, SIGALRM);
- if (sigprocmask(SIG_BLOCK, &block, &oblock) < 0)
- log(LOG_ERR, errno, "sigprocmask");
-#else
- omask = sigblock(sigmask(SIGALRM));
-#endif
free_all_prunes();
free_all_routes();
+ free_all_callouts();
stop_all_vifs();
k_stop_dvmrp();
close(igmp_socket);
close(udp_socket);
+ did_final_init = 0;
/*
* start processing again
*/
dvmrp_genid++;
- pruning = 1;
init_igmp();
init_routes();
init_ktable();
init_vifs();
- k_init_dvmrp(); /* enable DVMRP routing in kernel */
- init_installvifs();
+ /*XXX Schedule final_init() as main does? */
+ final_init(s);
-#ifdef SYSV
- (void)sigprocmask(SIG_SETMASK, &oblock, (sigset_t *)NULL);
-#else
- (void)sigsetmask(omask);
-#endif
+ /* schedule timer interrupts */
+ timer_setTimer(1, fasttimer, NULL);
+ timer_setTimer(TIMER_INTERVAL, timer, NULL);
}
#define LOG_MAX_MSGS 20 /* if > 20/minute then shut up for a while */
@@ -661,6 +866,61 @@ resetlogging(arg)
timer_setTimer(nxttime, resetlogging, narg);
}
+char *
+scaletime(t)
+ u_long t;
+{
+#define SCALETIMEBUFLEN 20
+ static char buf1[20];
+ static char buf2[20];
+ static char *buf = buf1;
+ char *p;
+
+ p = buf;
+ if (buf == buf1)
+ buf = buf2;
+ else
+ buf = buf1;
+
+ /* XXX snprintf */
+ sprintf(p, "%2ld:%02ld:%02ld", t / 3600, (t % 3600) / 60, t % 60);
+ p[SCALETIMEBUFLEN - 1] = '\0';
+ return p;
+}
+
+#ifdef RINGBUFFER
+#define NLOGMSGS 10000
+#define LOGMSGSIZE 200
+char *logmsg[NLOGMSGS];
+static int logmsgno = 0;
+
+void
+printringbuf()
+{
+ FILE *f;
+ int i;
+
+ f = fopen("/var/tmp/mrouted.log", "a");
+ if (f == NULL) {
+ log(LOG_ERR, errno, "can't open /var/tmp/mrouted.log");
+ /*NOTREACHED*/
+ }
+ fprintf(f, "--------------------------------------------\n");
+
+ i = (logmsgno + 1) % NLOGMSGS;
+
+ while (i != logmsgno) {
+ if (*logmsg[i]) {
+ fprintf(f, "%s\n", logmsg[i]);
+ *logmsg[i] = '\0';
+ }
+ i = (i + 1) % NLOGMSGS;
+ }
+
+ fclose(f);
+}
+#endif
+
/*
* Log errors and other messages to the system log daemon and to stderr,
* according to the severity of the message and the current debug level.
@@ -673,9 +933,11 @@ log(int severity, int syserr, char *format, ...)
va_list ap;
static char fmt[211] = "warning - ";
char *msg;
- char tbuf[20];
struct timeval now;
struct tm *thyme;
+#ifdef RINGBUFFER
+ static int ringbufinit = 0;
+#endif
va_start(ap, format);
#else
@@ -687,11 +949,14 @@ log(severity, syserr, format, va_alist)
va_dcl
{
va_list ap;
- static char fmt[211] = "warning - ";
+ static char fmt[311] = "warning - ";
char *msg;
char tbuf[20];
struct timeval now;
struct tm *thyme;
+#ifdef RINGBUFFER
+ static int ringbufinit = 0;
+#endif
va_start(ap);
#endif
@@ -699,35 +964,66 @@ log(severity, syserr, format, va_alist)
va_end(ap);
msg = (severity == LOG_WARNING) ? fmt : &fmt[10];
- switch (debug) {
- case 0: break;
- case 1: if (severity > LOG_NOTICE) break;
- case 2: if (severity > LOG_INFO ) break;
- default:
- gettimeofday(&now,NULL);
- thyme = localtime(&now.tv_sec);
- strftime(tbuf, sizeof(tbuf), "%X.%%03d ", thyme);
- fprintf(stderr, tbuf, now.tv_usec / 1000);
- fprintf(stderr, "%s", msg);
- if (syserr == 0)
- fprintf(stderr, "\n");
- else if (syserr < sys_nerr)
- fprintf(stderr, ": %s\n", sys_errlist[syserr]);
- else
- fprintf(stderr, ": errno %d\n", syserr);
- }
+#ifdef RINGBUFFER
+ if (!ringbufinit) {
+ int i;
- if (severity <= LOG_NOTICE) {
- if (log_nmsgs++ < LOG_MAX_MSGS) {
- if (syserr != 0) {
- errno = syserr;
- syslog(severity, "%s: %m", msg);
- } else
- syslog(severity, "%s", msg);
+ for (i = 0; i < NLOGMSGS; i++) {
+ logmsg[i] = malloc(LOGMSGSIZE);
+ if (logmsg[i] == 0) {
+ syslog(LOG_ERR, "out of memory");
+ exit(-1);
+ }
+ *logmsg[i] = 0;
}
+ ringbufinit = 1;
+ }
+ gettimeofday(&now,NULL);
+ thyme = localtime(&now.tv_sec);
+ sprintf(logmsg[logmsgno++], "%02d:%02d:%02d.%03ld %s err %d",
+ thyme->tm_hour, thyme->tm_min, thyme->tm_sec,
+ now.tv_usec / 1000, msg, syserr);
+ logmsgno %= NLOGMSGS;
+ if (severity <= LOG_NOTICE)
+#endif
+ /*
+ * Log to stderr if we haven't forked yet and it's a warning or worse,
+ * or if we're debugging.
+ */
+ if (haveterminal && (debug || severity <= LOG_WARNING)) {
+ gettimeofday(&now,NULL);
+ thyme = localtime(&now.tv_sec);
+ if (!debug)
+ fprintf(stderr, "%s: ", progname);
+ fprintf(stderr, "%02d:%02d:%02d.%03ld %s", thyme->tm_hour,
+ thyme->tm_min, thyme->tm_sec, now.tv_usec / 1000, msg);
+ if (syserr == 0)
+ fprintf(stderr, "\n");
+ else if (syserr < sys_nerr)
+ fprintf(stderr, ": %s\n", sys_errlist[syserr]);
+ else
+ fprintf(stderr, ": errno %d\n", syserr);
+ }
- if (severity <= LOG_ERR) exit(-1);
+ /*
+ * Always log things that are worse than warnings, no matter what
+ * the log_nmsgs rate limiter says.
+ * Only count things worse than debugging in the rate limiter
+ * (since if you put daemon.debug in syslog.conf you probably
+ * actually want to log the debugging messages so they shouldn't
+ * be rate-limited)
+ */
+ if ((severity < LOG_WARNING) || (log_nmsgs < LOG_MAX_MSGS)) {
+ if (severity < LOG_DEBUG)
+ log_nmsgs++;
+ if (syserr != 0) {
+ errno = syserr;
+ syslog(severity, "%s: %m", msg);
+ } else
+ syslog(severity, "%s", msg);
}
+
+ if (severity <= LOG_ERR) exit(-1);
}
#ifdef DEBUG_MFC