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>