summaryrefslogtreecommitdiffstats
path: root/usr.sbin/pim6dd/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/pim6dd/main.c')
-rw-r--r--usr.sbin/pim6dd/main.c719
1 files changed, 719 insertions, 0 deletions
diff --git a/usr.sbin/pim6dd/main.c b/usr.sbin/pim6dd/main.c
new file mode 100644
index 0000000..7efc30e
--- /dev/null
+++ b/usr.sbin/pim6dd/main.c
@@ -0,0 +1,719 @@
+/*
+ * Copyright (c) 1998 by the University of Oregon.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation in source and binary forms for lawful
+ * purposes and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both
+ * the copyright notice and this permission notice appear in supporting
+ * documentation, and that any documentation, advertising materials,
+ * and other materials related to such distribution and use acknowledge
+ * that the software was developed by the University of Oregon.
+ * The name of the University of Oregon may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THE UNIVERSITY OF OREGON DOES NOT MAKE ANY REPRESENTATIONS
+ * ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE. THIS SOFTWARE IS
+ * PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND
+ * NON-INFRINGEMENT.
+ *
+ * IN NO EVENT SHALL UO, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT,
+ * TORT, OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH,
+ * THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Other copyrights might apply to parts of this software and are so
+ * noted when applicable.
+ */
+/*
+ * Questions concerning this software should be directed to
+ * Kurt Windisch (kurtw@antc.uoregon.edu)
+ *
+ * $Id: main.c,v 1.2 1999/08/13 09:20:13 jinmei Exp $
+ */
+/*
+ * Part of this program has been derived from PIM sparse-mode pimd.
+ * The pimd program is covered by the license in the accompanying file
+ * named "LICENSE.pimd".
+ *
+ * The pimd program is COPYRIGHT 1998 by University of Southern California.
+ *
+ * Part of this program has been derived from mrouted.
+ * The mrouted program is covered by the license in the accompanying file
+ * named "LICENSE.mrouted".
+ *
+ * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
+ * Leland Stanford Junior University.
+ *
+ * $FreeBSD$
+ */
+
+#include "defs.h"
+
+#ifdef SNMP
+#include "snmp.h"
+#endif
+
+char configfilename[256] = _PATH_PIM6D_CONF;
+char versionstring[100];
+
+static char pidfilename[] = _PATH_PIM6D_PID;
+/* TODO: not used
+static char genidfilename[] = _PATH_PIM6D_GENID;
+*/
+
+int haveterminal = 1;
+char *progname;
+
+static int sighandled = 0;
+#define GOT_SIGINT 0x01
+#define GOT_SIGHUP 0x02
+#define GOT_SIGUSR1 0x04
+#define GOT_SIGUSR2 0x08
+#define GOT_SIGALRM 0x10
+
+
+#ifdef SNMP
+#define NHANDLERS 34
+#else
+#define NHANDLERS 3
+#endif
+
+static struct ihandler {
+ int fd; /* File descriptor */
+ ihfunc_t func; /* Function to call with &fd_set */
+} ihandlers[NHANDLERS];
+static int nhandlers = 0;
+
+static struct debugname {
+ char *name;
+ int level;
+ int nchars;
+} debugnames[] = {
+#if 0
+ { "dvmrp_detail", DEBUG_DVMRP_DETAIL, 5 },
+ { "dvmrp_prunes", DEBUG_DVMRP_PRUNE, 8 },
+ { "dvmrp_pruning", DEBUG_DVMRP_PRUNE, 8 },
+ { "dvmrp_mrt", DEBUG_DVMRP_ROUTE, 7 },
+ { "dvmrp_routes", DEBUG_DVMRP_ROUTE, 7 },
+ { "dvmrp_routing", DEBUG_DVMRP_ROUTE, 7 },
+ { "dvmrp_neighbors", DEBUG_DVMRP_PEER, 7 },
+ { "dvmrp_peers", DEBUG_DVMRP_PEER, 8 },
+ { "dvmrp_hello", DEBUG_DVMRP_PEER, 7 },
+ { "dvmrp_timers", DEBUG_DVMRP_TIMER, 7 },
+ { "dvmrp", DEBUG_DVMRP, 1 },
+ { "igmp_proto", DEBUG_IGMP_PROTO, 6 },
+ { "igmp_timers", DEBUG_IGMP_TIMER, 6 },
+ { "igmp_members", DEBUG_IGMP_MEMBER, 6 },
+ { "groups", DEBUG_MEMBER, 1 },
+ { "membership", DEBUG_MEMBER, 2 },
+ { "igmp", DEBUG_IGMP, 1 },
+#endif
+ { "trace", DEBUG_TRACE, 2 },
+ { "mtrace", DEBUG_TRACE, 2 },
+ { "traceroute", DEBUG_TRACE, 2 },
+ { "timeout", DEBUG_TIMEOUT, 2 },
+ { "callout", DEBUG_TIMEOUT, 3 },
+ { "pkt", DEBUG_PKT, 2 },
+ { "packets", DEBUG_PKT, 2 },
+ { "interfaces", DEBUG_IF, 2 },
+ { "vif", DEBUG_IF, 1 },
+ { "kernel", DEBUG_KERN, 2 },
+ { "cache", DEBUG_MFC, 1 },
+ { "mfc", DEBUG_MFC, 2 },
+ { "k_cache", DEBUG_MFC, 2 },
+ { "k_mfc", DEBUG_MFC, 2 },
+ { "rsrr", DEBUG_RSRR, 2 },
+ { "pim_detail", DEBUG_PIM_DETAIL, 5 },
+ { "pim_hello", DEBUG_PIM_HELLO, 5 },
+ { "pim_neighbors", DEBUG_PIM_HELLO, 5 },
+ { "pim_register", DEBUG_PIM_REGISTER, 5 },
+ { "registers", DEBUG_PIM_REGISTER, 2 },
+ { "pim_join_prune", DEBUG_PIM_JOIN_PRUNE, 5 },
+ { "pim_j_p", DEBUG_PIM_JOIN_PRUNE, 5 },
+ { "pim_jp", DEBUG_PIM_JOIN_PRUNE, 5 },
+ { "pim_graft", DEBUG_PIM_GRAFT, 5 },
+ { "pim_bootstrap", DEBUG_PIM_BOOTSTRAP, 5 },
+ { "pim_bsr", DEBUG_PIM_BOOTSTRAP, 5 },
+ { "bsr", DEBUG_PIM_BOOTSTRAP, 1 },
+ { "bootstrap", DEBUG_PIM_BOOTSTRAP, 1 },
+ { "pim_asserts", DEBUG_PIM_ASSERT, 5 },
+ { "pim_cand_rp", DEBUG_PIM_CAND_RP, 5 },
+ { "pim_c_rp", DEBUG_PIM_CAND_RP, 5 },
+ { "pim_rp", DEBUG_PIM_CAND_RP, 6 },
+ { "rp", DEBUG_PIM_CAND_RP, 2 },
+ { "pim_routes", DEBUG_PIM_MRT, 6 },
+ { "pim_routing", DEBUG_PIM_MRT, 6 },
+ { "pim_mrt", DEBUG_PIM_MRT, 5 },
+ { "pim_timers", DEBUG_PIM_TIMER, 5 },
+ { "pim_rpf", DEBUG_PIM_RPF, 6 },
+ { "rpf", DEBUG_RPF, 3 },
+ { "pim", DEBUG_PIM, 1 },
+ { "routes", DEBUG_MRT, 1 },
+ { "routing", DEBUG_MRT, 1 },
+ { "mrt", DEBUG_MRT, 1 },
+ { "routers", DEBUG_NEIGHBORS, 6 },
+ { "mrouters", DEBUG_NEIGHBORS, 7 },
+ { "neighbors", DEBUG_NEIGHBORS, 1 },
+ { "timers", DEBUG_TIMER, 1 },
+ { "asserts", DEBUG_ASSERT, 1 },
+ { "all", DEBUG_ALL, 2 },
+ { "3", 0xffffffff, 1 } /* compat. */
+};
+
+/*
+ * Forward declarations.
+ */
+static void handler __P((int));
+static void timer __P((void *));
+static void cleanup __P((void));
+static void restart __P((int));
+static void cleanup __P((void));
+static void resetlogging __P((void *));
+
+
+/* To shut up gcc -Wstrict-prototypes */
+int main __P((int argc, char **argv));
+
+int
+register_input_handler(fd, func)
+ int fd;
+ ihfunc_t func;
+{
+ if (nhandlers >= NHANDLERS)
+ return -1;
+
+ ihandlers[nhandlers].fd = fd;
+ ihandlers[nhandlers++].func = func;
+
+ return 0;
+}
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int dummy, dummysigalrm;
+ FILE *fp;
+ struct timeval tv, difftime, curtime, lasttime, *timeout;
+ fd_set rfds, readers;
+ int nfds, n, i, secs;
+ extern char todaysversion[];
+ struct sigaction sa;
+ struct debugname *d;
+ char c;
+ int tmpd;
+
+
+ setlinebuf(stderr);
+
+ if (geteuid() != 0) {
+ fprintf(stderr, "pim6dd: 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 && *(argv + 1)[0] != '-') {
+ char *p,*q;
+ int i, len;
+ struct debugname *d;
+
+ argv++;
+ argc--;
+ 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 = DEBUG_DEFAULT;
+ }
+ else if (strcmp(*argv, "-c") == 0) {
+ if (argc > 1) {
+ argv++; argc--;
+ strcpy(configfilename, *argv);
+ }
+ else
+ goto usage;
+/* TODO: not implemented */
+#ifdef SNMP
+ }
+ else if (strcmp(*argv, "-P") == 0) {
+ if (argc > 1 && isdigit(*(argv + 1)[0])) {
+ argv++, argc--;
+ dest_port = atoi(*argv);
+ }
+ else
+ dest_port = DEFAULT_PORT;
+#endif
+ }
+ else
+ goto usage;
+ argv++; argc--;
+ }
+
+ if (argc > 0) {
+ usage:
+ tmpd = 0xffffffff;
+ fprintf(stderr, "usage: pim6dd [-c configfile] [-d [debug_level][,debug_level]]\n");
+
+ fprintf(stderr, "debug levels: ");
+ 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 = ',';
+ }
+ }
+ fprintf(stderr, ")\n");
+ exit(1);
+ }
+
+ if (debug != 0) {
+ tmpd = debug;
+ fprintf(stderr, "debug level 0x%lx ", 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 = ',';
+ }
+ }
+ fprintf(stderr, ")\n");
+ }
+
+#ifdef LOG_DAEMON
+ (void)openlog("pim6dd", LOG_PID, LOG_DAEMON);
+ (void)setlogmask(LOG_UPTO(LOG_NOTICE));
+#else
+ (void)openlog("pim6dd", LOG_PID);
+#endif /* LOG_DAEMON */
+ sprintf(versionstring, "pim6dd version %s", todaysversion);
+
+ log(LOG_DEBUG, 0, "%s starting", versionstring);
+
+/* TODO: XXX: use a combination of time and hostid to initialize the random
+ * generator.
+ */
+#ifdef SYSV
+ srand48(time(NULL));
+#else
+ {
+ struct timeval tm;
+ gettimeofday(&tm, NULL);
+ srandom(tm.tv_usec + gethostid());
+ }
+#endif
+
+ callout_init();
+
+ /* Start up the log rate-limiter */
+ resetlogging(NULL);
+
+ init_mld6();
+#if 0
+ k_stop_pim(mld6_socket);
+ exit(0); /* XXX */
+#endif
+ init_pim6();
+
+ init_pim6_mrt();
+ init_timers();
+
+ /* TODO: check the kernel DVMRP/MROUTED/PIM support version */
+
+#ifdef SNMP
+ if (i = snmp_init())
+ return i;
+#endif /* SNMP */
+ init_vifs();
+
+#ifdef RSRR
+ rsrr_init();
+#endif /* RSRR */
+
+ sa.sa_handler = handler;
+ sa.sa_flags = 0; /* Interrupt system calls */
+ sigemptyset(&sa.sa_mask);
+ sigaction(SIGALRM, &sa, NULL);
+ 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(mld6_socket, &readers);
+ nfds = mld6_socket + 1;
+ for (i = 0; i < nhandlers; i++) {
+ FD_SET(ihandlers[i].fd, &readers);
+ if (ihandlers[i].fd >= nfds)
+ nfds = ihandlers[i].fd + 1;
+ }
+
+ IF_DEBUG(DEBUG_IF)
+ dump_vifs(stderr);
+ IF_DEBUG(DEBUG_PIM_MRT)
+ dump_pim_mrt(stderr);
+
+ /* schedule first timer interrupt */
+ timer_setTimer(TIMER_INTERVAL, timer, NULL);
+
+ if (debug == 0) {
+ /* Detach from the terminal */
+#ifdef TIOCNOTTY
+ int t;
+#endif /* TIOCNOTTY */
+
+ 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 /* TIOCNOTTY */
+#endif /* SYSV */
+ } /* End of child process code */
+
+#ifdef HAVE_ROUTING_SOCKETS
+ init_routesock();
+#endif /* HAVE_ROUTING_SOCKETS */
+
+ fp = fopen(pidfilename, "w");
+ if (fp != NULL) {
+ fprintf(fp, "%d\n", (int)getpid());
+ (void) fclose(fp);
+ }
+
+ /*
+ * Main receive loop.
+ */
+ dummy = 0;
+ dummysigalrm = SIGALRM;
+ difftime.tv_usec = 0;
+ gettimeofday(&curtime, NULL);
+ lasttime = curtime;
+ for(;;) {
+ 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;
+ }
+
+ if (sighandled) {
+ if (sighandled & GOT_SIGINT) {
+ sighandled &= ~GOT_SIGINT;
+ break;
+ }
+ if (sighandled & GOT_SIGHUP) {
+ sighandled &= ~GOT_SIGHUP;
+ restart(SIGHUP);
+ }
+ if (sighandled & GOT_SIGUSR1) {
+ sighandled &= ~GOT_SIGUSR1;
+ fdump(SIGUSR1);
+ }
+ if (sighandled & GOT_SIGUSR2) {
+ sighandled &= ~GOT_SIGUSR2;
+ cdump(SIGUSR2);
+ }
+ if (sighandled & GOT_SIGALRM) {
+ sighandled &= ~GOT_SIGALRM;
+ timer(&dummysigalrm);
+ }
+ }
+ if ((n = select(nfds, &rfds, NULL, NULL, timeout)) < 0) {
+ if (errno != EINTR) /* SIGALRM is expected */
+ log(LOG_WARNING, errno, "select failed");
+ continue;
+ }
+
+ /*
+ * 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;
+#ifdef TIMERDEBUG
+ IF_DEBUG(DEBUG_TIMEOUT)
+ log(LOG_DEBUG, 0, "TIMEOUT: secs %d, diff secs %d, diff usecs %d", secs, difftime.tv_sec, difftime.tv_usec );
+#endif
+ 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) {
+#ifdef TIMERDEBUG
+ IF_DEBUG(DEBUG_TIMEOUT)
+ log(LOG_DEBUG, 0, "\taging callouts: secs %d, diff secs %d, diff usecs %d", secs, difftime.tv_sec, difftime.tv_usec );
+#endif
+ age_callout_queue(difftime.tv_sec);
+ }
+ secs = -1;
+ } while (difftime.tv_sec > 0);
+
+ /* Handle sockets */
+ if (n > 0) {
+ /* TODO: shall check first mld6_socket for better performance? */
+ for (i = 0; i < nhandlers; i++) {
+ if (FD_ISSET(ihandlers[i].fd, &rfds)) {
+ (*ihandlers[i].func)(ihandlers[i].fd, &rfds);
+ }
+ }
+ }
+
+ } /* Main loop */
+
+ log(LOG_NOTICE, 0, "%s exiting", versionstring);
+ cleanup();
+ exit(0);
+}
+
+/*
+ * The 'virtual_time' variable is initialized to a value that will cause the
+ * first invocation of timer() to send a probe or route report to all vifs
+ * and send group membership queries to all subnets for which this router is
+ * querier. This first invocation occurs approximately TIMER_INTERVAL seconds
+ * after the router starts up. Note that probes for neighbors and queries
+ * for group memberships are also sent at start-up time, as part of initial-
+ * ization. This repetition after a short interval is desirable for quickly
+ * building up topology and membership information in the presence of possible
+ * packet loss.
+ *
+ * 'virtual_time' advances at a rate that is only a crude approximation of
+ * real time, because it does not take into account any time spent processing,
+ * and because the timer intervals are sometimes shrunk by a random amount to
+ * avoid unwanted synchronization with other routers.
+ */
+
+u_long virtual_time = 0;
+
+/*
+ * Timer routine. Performs all perodic functions:
+ * aging interfaces, quering neighbors and members, etc... The granularity
+ * is equal to TIMER_INTERVAL.
+ */
+static void
+timer(i)
+ void *i;
+{
+ age_vifs(); /* Timeout neighbors and groups */
+ age_routes(); /* Timeout routing entries */
+
+ virtual_time += TIMER_INTERVAL;
+ timer_setTimer(TIMER_INTERVAL, timer, NULL);
+}
+
+/*
+ * Performs all necessary functions to quit gracefully
+ */
+/* TODO: implement all necessary stuff */
+static void
+cleanup()
+{
+
+#ifdef RSRR
+ rsrr_clean();
+#endif /* RSRR */
+
+ k_stop_pim(mld6_socket);
+
+ /* TODO: XXX (not in the spec)
+ */
+}
+
+
+/*
+ * 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 SIGALRM:
+ sighandled |= GOT_SIGALRM;
+ 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;
+ }
+}
+
+
+/* TODO: not verified */
+/* PIMDM TODO */
+/*
+ * Restart the daemon
+ */
+static void
+restart(i)
+ int i;
+{
+#ifdef SNMP
+ int s;
+#endif /* SNMP */
+
+ log(LOG_NOTICE, 0, "% restart", versionstring);
+
+ /*
+ * reset all the entries
+ */
+ /*
+ * TODO: delete?
+ * free_all_routes();
+ */
+ free_all_callouts();
+ stop_all_vifs();
+ nhandlers=0;
+ k_stop_pim(mld6_socket);
+ close(mld6_socket);
+ close(pim6_socket);
+ close(udp_socket);
+
+ /*
+ * start processing again
+ */
+ init_mld6();
+ init_pim6();
+#ifdef HAVE_ROUTING_SOCKETS
+ init_routesock();
+#endif /* HAVE_ROUTING_SOCKETS */
+ init_pim6_mrt();
+#ifdef SNMP
+ if ( s = snmp_init())
+ exit(s);
+#endif /* SNMP */
+ init_vifs();
+
+#ifdef RSRR
+ rsrr_init();
+#endif /* RSRR */
+
+ /* schedule timer interrupts */
+ timer_setTimer(TIMER_INTERVAL, timer, NULL);
+}
+
+
+static void
+resetlogging(arg)
+ void *arg;
+{
+ int nxttime = 60;
+ void *narg = NULL;
+
+ if (arg == NULL && log_nmsgs > LOG_MAX_MSGS) {
+ nxttime = LOG_SHUT_UP;
+ narg = (void *)&log_nmsgs; /* just need some valid void * */
+ syslog(LOG_WARNING, "logging too fast, shutting up for %d minutes",
+ LOG_SHUT_UP / 60);
+ } else {
+ log_nmsgs = 0;
+ }
+
+ timer_setTimer(nxttime, resetlogging, narg);
+}
OpenPOWER on IntegriCloud