X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/3d6886b76a47d8be1f142e9a90555921782c2426..787d3210186ed1c1d0479fd7c0cc0ca6256380ff:/usr/src/sbin/routed/main.c diff --git a/usr/src/sbin/routed/main.c b/usr/src/sbin/routed/main.c index a68a3a00d9..803b4a4517 100644 --- a/usr/src/sbin/routed/main.c +++ b/usr/src/sbin/routed/main.c @@ -1,38 +1,66 @@ +/* + * Copyright (c) 1983, 1988 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms 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 California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + #ifndef lint -static char sccsid[] = "@(#)main.c 4.11 (Berkeley) %G%"; -#endif +char copyright[] = +"@(#) Copyright (c) 1983, 1988 Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)main.c 5.17 (Berkeley) %G%"; +#endif /* not lint */ /* * Routing Table Management Daemon */ #include "defs.h" #include -#include +#include #include -#include -#include -#include +#include +#include +#include int supplier = -1; /* process should supply updates */ -extern int gateway; +int gateway = 0; /* 1 if we are a gateway to parts beyond */ +int debug = 0; +int bufspace = 127*1024; /* max. input buffer size to request */ struct rip *msg = (struct rip *)packet; -int hup(); +int hup(), rtdeleteall(), sigtrace(); main(argc, argv) int argc; char *argv[]; { - int cc; + int n, cc, nfd, omask, tflags = 0; struct sockaddr from; + struct timeval *tvp, waittime; + struct itimerval itval; + fd_set ibits; u_char retry; -#ifdef COMPAT - int snoroute; -#endif argv0 = argv; +#if BSD >= 43 + openlog("routed", LOG_PID | LOG_ODELAY, LOG_DAEMON); + setlogmask(LOG_WARNING); sp = getservbyname("router", "udp"); if (sp == NULL) { fprintf(stderr, "routed: router/udp: unknown service\n"); @@ -43,14 +71,6 @@ main(argc, argv) s = getsocket(AF_INET, SOCK_DGRAM, &addr); if (s < 0) exit(1); -#ifdef COMPAT - bzero(&addr, sizeof (addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(ntohs(sp->s_port) + 1); - snoroute = getsocket(AF_INET, SOCK_DGRAM, &addr); - if (snoroute < 0) - exit(1); -#endif argv++, argc--; while (argc > 0 && **argv == '-') { if (strcmp(*argv, "-s") == 0) { @@ -64,36 +84,35 @@ main(argc, argv) continue; } if (strcmp(*argv, "-t") == 0) { - tracepackets++; + tflags++; + setlogmask(LOG_DEBUG); argv++, argc--; continue; } - if (strcmp(*argv, "-g") == 0) { - gateway = 1; + if (strcmp(*argv, "-d") == 0) { + debug++; + setlogmask(LOG_DEBUG); argv++, argc--; continue; } - if (strcmp(*argv, "-l") == 0) { - gateway = -1; + if (strcmp(*argv, "-g") == 0) { + gateway = 1; argv++, argc--; continue; } fprintf(stderr, - "usage: routed [ -s ] [ -q ] [ -t ] [ -g ] [ -l ]\n"); + "usage: routed [ -s ] [ -q ] [ -t ] [ -g ]\n"); exit(1); } -#ifndef DEBUG - if (!tracepackets) { + + if (debug == 0) { int t; if (fork()) exit(0); for (t = 0; t < 20; t++) if (t != s) -#ifdef COMPAT - if (t != snoroute) -#endif - (void) close(cc); + (void) close(t); (void) open("/", 0); (void) dup2(0, 1); (void) dup2(0, 2); @@ -103,54 +122,149 @@ main(argc, argv) (void) close(t); } } -#endif /* * Any extra argument is considered * a tracing log file. */ if (argc > 0) traceon(*argv); + while (tflags-- > 0) + bumploglevel(); + + (void) gettimeofday(&now, (struct timezone *)NULL); /* * Collect an initial view of the world by - * snooping in the kernel and the gateway kludge + * checking the interface configuration and the gateway kludge * file. Then, send a request packet on all * directly connected networks to find out what * everyone else thinks. */ rtinit(); - gwkludge(); ifinit(); + gwkludge(); + if (gateway > 0) + rtdefault(); if (supplier < 0) supplier = 0; msg->rip_cmd = RIPCMD_REQUEST; msg->rip_vers = RIPVERSION; - msg->rip_nets[0].rip_dst.sa_family = AF_UNSPEC; - msg->rip_nets[0].rip_metric = HOPCNT_INFINITY; - msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC); - msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY); + if (sizeof(msg->rip_nets[0].rip_dst.sa_family) > 1) /* XXX */ + msg->rip_nets[0].rip_dst.sa_family = htons((u_short)AF_UNSPEC); + else + msg->rip_nets[0].rip_dst.sa_family = AF_UNSPEC; + msg->rip_nets[0].rip_metric = htonl((u_long)HOPCNT_INFINITY); toall(sendmsg); signal(SIGALRM, timer); signal(SIGHUP, hup); - timer(); + signal(SIGTERM, hup); + signal(SIGINT, rtdeleteall); + signal(SIGUSR1, sigtrace); + signal(SIGUSR2, sigtrace); + itval.it_interval.tv_sec = TIMER_RATE; + itval.it_value.tv_sec = TIMER_RATE; + itval.it_interval.tv_usec = 0; + itval.it_value.tv_usec = 0; + srandom(getpid()); + if (setitimer(ITIMER_REAL, &itval, (struct itimerval *)NULL) < 0) + syslog(LOG_ERR, "setitimer: %m\n"); + FD_ZERO(&ibits); + nfd = s + 1; /* 1 + max(fd's) */ for (;;) { - int ibits; - register int n; - - ibits = 1 << s; -#ifdef COMPAT - ibits |= 1 << snoroute; -#endif - n = select(20, &ibits, 0, 0, 0); - if (n < 0) + FD_SET(s, &ibits); + /* + * If we need a dynamic update that was held off, + * needupdate will be set, and nextbcast is the time + * by which we want select to return. Compute time + * until dynamic update should be sent, and select only + * until then. If we have already passed nextbcast, + * just poll. + */ + if (needupdate) { + waittime = nextbcast; + timevalsub(&waittime, &now); + if (waittime.tv_sec < 0) { + waittime.tv_sec = 0; + waittime.tv_usec = 0; + } + if (traceactions) + fprintf(ftrace, + "select until dynamic update %d/%d sec/usec\n", + waittime.tv_sec, waittime.tv_usec); + tvp = &waittime; + } else + tvp = (struct timeval *)NULL; + n = select(nfd, &ibits, 0, 0, tvp); + if (n <= 0) { + /* + * Need delayed dynamic update if select returned + * nothing and we timed out. Otherwise, ignore + * errors (e.g. EINTR). + */ + if (n < 0) { + if (errno == EINTR) + continue; + syslog(LOG_ERR, "select: %m"); + } + omask = sigblock(sigmask(SIGALRM)); + if (n == 0 && needupdate) { + if (traceactions) + fprintf(ftrace, + "send delayed dynamic update\n"); + (void) gettimeofday(&now, + (struct timezone *)NULL); + toall(supply, RTS_CHANGED, + (struct interface *)NULL); + lastbcast = now; + needupdate = 0; + nextbcast.tv_sec = 0; + } + sigsetmask(omask); continue; - if (ibits & (1 << s)) - process(s); -#ifdef COMPAT - if (ibits & (1 << snoroute)) - process(snoroute); + } + (void) gettimeofday(&now, (struct timezone *)NULL); + omask = sigblock(sigmask(SIGALRM)); +#ifdef doesntwork +/* +printf("s %d, ibits %x index %d, mod %d, sh %x, or %x &ibits %x\n", + s, + ibits.fds_bits[0], + (s)/(sizeof(fd_mask) * 8), + ((s) % (sizeof(fd_mask) * 8)), + (1 << ((s) % (sizeof(fd_mask) * 8))), + ibits.fds_bits[(s)/(sizeof(fd_mask) * 8)] & (1 << ((s) % (sizeof(fd_mask) * 8))), + &ibits + ); +*/ + if (FD_ISSET(s, &ibits)) +#else + if (ibits.fds_bits[s/32] & (1 << s)) #endif + process(s); /* handle ICMP redirects */ + sigsetmask(omask); + } +} + +timevaladd(t1, t2) + struct timeval *t1, *t2; +{ + + t1->tv_sec += t2->tv_sec; + if ((t1->tv_usec += t2->tv_usec) > 1000000) { + t1->tv_sec++; + t1->tv_usec -= 1000000; + } +} + +timevalsub(t1, t2) + struct timeval *t1, *t2; +{ + + t1->tv_sec -= t2->tv_sec; + if ((t1->tv_usec -= t2->tv_usec) < 0) { + t1->tv_sec--; + t1->tv_usec += 1000000; } } @@ -158,42 +272,64 @@ process(fd) int fd; { struct sockaddr from; - int fromlen = sizeof (from), cc, omask; + int fromlen, cc; + union { + char buf[MAXPACKETSIZE+1]; + struct rip rip; + } inbuf; - cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen); - if (cc <= 0) { - if (cc < 0 && errno != EINTR) - perror("recvfrom"); - return; + for (;;) { + fromlen = sizeof (from); + cc = recvfrom(fd, &inbuf, sizeof (inbuf), 0, &from, &fromlen); + if (cc <= 0) { + if (cc < 0 && errno != EWOULDBLOCK) + perror("recvfrom"); + break; + } + if (fromlen != sizeof (struct sockaddr_in)) + break; + rip_input(&from, &inbuf.rip, cc); } - if (fromlen != sizeof (struct sockaddr_in)) - return; -#define mask(s) (1<<((s)-1)) - omask = sigblock(mask(SIGALRM)); - rip_input(&from, cc); - sigsetmask(omask); } getsocket(domain, type, sin) int domain, type; struct sockaddr_in *sin; { - int retry, s; + int sock, on = 1; - retry = 1; - while ((s = socket(domain, type, 0, 0)) < 0 && retry) { + if ((sock = socket(domain, type, 0)) < 0) { perror("socket"); - sleep(5 * retry); - retry <<= 1; + syslog(LOG_ERR, "socket: %m"); + return (-1); } - if (retry == 0) +#ifdef SO_BROADCAST + if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) { + syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m"); + close(sock); return (-1); - while (bind(s, sin, sizeof (*sin), 0) < 0 && retry) { - perror("bind"); - sleep(5 * retry); - retry <<= 1; } - if (retry == 0) +#endif +#ifdef SO_RCVBUF + for (on = bufspace; ; on -= 1024) { + if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, + &on, sizeof (on)) == 0) + break; + if (on <= 8*1024) { + syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m"); + break; + } + } + if (traceactions) + fprintf(ftrace, "recv buf %d\n", on); +#endif + if (bind(sock, sin, sizeof (*sin), 0) < 0) { + perror("bind"); + syslog(LOG_ERR, "bind: %m"); + close(sock); return (-1); - return (s); + } + if (fcntl(sock, F_SETFL, FNDELAY) == -1) + syslog(LOG_ERR, "fcntl FNDELAY: %m\n"); + return (sock); }