Home | History | Annotate | Line # | Download | only in routed
main.c revision 1.11
      1  1.11  mycroft /*	$NetBSD: main.c,v 1.11 1995/03/23 00:02:49 mycroft Exp $	*/
      2   1.7      cgd 
      3   1.1      cgd /*
      4   1.5  mycroft  * Copyright (c) 1983, 1988, 1993
      5   1.5  mycroft  *	The Regents of the University of California.  All rights reserved.
      6   1.1      cgd  *
      7   1.1      cgd  * Redistribution and use in source and binary forms, with or without
      8   1.1      cgd  * modification, are permitted provided that the following conditions
      9   1.1      cgd  * are met:
     10   1.1      cgd  * 1. Redistributions of source code must retain the above copyright
     11   1.1      cgd  *    notice, this list of conditions and the following disclaimer.
     12   1.1      cgd  * 2. Redistributions in binary form must reproduce the above copyright
     13   1.1      cgd  *    notice, this list of conditions and the following disclaimer in the
     14   1.1      cgd  *    documentation and/or other materials provided with the distribution.
     15   1.1      cgd  * 3. All advertising materials mentioning features or use of this software
     16   1.1      cgd  *    must display the following acknowledgement:
     17   1.1      cgd  *	This product includes software developed by the University of
     18   1.1      cgd  *	California, Berkeley and its contributors.
     19   1.1      cgd  * 4. Neither the name of the University nor the names of its contributors
     20   1.1      cgd  *    may be used to endorse or promote products derived from this software
     21   1.1      cgd  *    without specific prior written permission.
     22   1.1      cgd  *
     23   1.1      cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24   1.1      cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25   1.1      cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26   1.1      cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27   1.1      cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28   1.1      cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29   1.1      cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30   1.1      cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31   1.1      cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32   1.1      cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33   1.1      cgd  * SUCH DAMAGE.
     34   1.1      cgd  */
     35   1.1      cgd 
     36   1.1      cgd #ifndef lint
     37   1.5  mycroft static char copyright[] =
     38   1.5  mycroft "@(#) Copyright (c) 1983, 1988, 1993\n\
     39   1.5  mycroft 	The Regents of the University of California.  All rights reserved.\n";
     40   1.1      cgd #endif /* not lint */
     41   1.1      cgd 
     42   1.1      cgd #ifndef lint
     43   1.7      cgd #if 0
     44   1.7      cgd static char sccsid[] = "@(#)main.c	8.1 (Berkeley) 6/5/93";
     45   1.7      cgd #else
     46  1.11  mycroft static char rcsid[] = "$NetBSD: main.c,v 1.11 1995/03/23 00:02:49 mycroft Exp $";
     47   1.7      cgd #endif
     48   1.1      cgd #endif /* not lint */
     49   1.1      cgd 
     50   1.1      cgd /*
     51   1.1      cgd  * Routing Table Management Daemon
     52   1.1      cgd  */
     53   1.1      cgd #include "defs.h"
     54   1.1      cgd #include <sys/ioctl.h>
     55   1.1      cgd #include <sys/file.h>
     56   1.1      cgd 
     57   1.1      cgd #include <net/if.h>
     58   1.1      cgd 
     59   1.1      cgd #include <sys/errno.h>
     60   1.1      cgd #include <sys/signal.h>
     61   1.1      cgd #include <sys/syslog.h>
     62   1.1      cgd #include "pathnames.h"
     63   1.1      cgd 
     64   1.1      cgd int	supplier = -1;		/* process should supply updates */
     65   1.1      cgd int	gateway = 0;		/* 1 if we are a gateway to parts beyond */
     66   1.1      cgd int	debug = 0;
     67   1.1      cgd int	bufspace = 127*1024;	/* max. input buffer size to request */
     68   1.6      cgd struct	rip *msg = (struct rip *)packet;
     69   1.1      cgd 
     70   1.6      cgd int getsocket __P((int, int, struct sockaddr_in *));
     71   1.6      cgd void process __P((int));
     72   1.1      cgd 
     73   1.6      cgd int
     74   1.1      cgd main(argc, argv)
     75   1.1      cgd 	int argc;
     76   1.1      cgd 	char *argv[];
     77   1.1      cgd {
     78  1.11  mycroft 	int n, nfd, tflags = 0;
     79   1.1      cgd 	struct timeval *tvp, waittime;
     80   1.1      cgd 	struct itimerval itval;
     81   1.1      cgd 	register struct rip *query = msg;
     82   1.1      cgd 	fd_set ibits;
     83  1.10  mycroft 	sigset_t sigset, osigset;
     84   1.1      cgd 
     85   1.1      cgd 	argv0 = argv;
     86   1.1      cgd #if BSD >= 43
     87   1.1      cgd 	openlog("routed", LOG_PID | LOG_ODELAY, LOG_DAEMON);
     88   1.1      cgd 	setlogmask(LOG_UPTO(LOG_WARNING));
     89   1.1      cgd #else
     90   1.1      cgd 	openlog("routed", LOG_PID);
     91   1.1      cgd #define LOG_UPTO(x) (x)
     92   1.1      cgd #define setlogmask(x) (x)
     93   1.1      cgd #endif
     94   1.1      cgd 	sp = getservbyname("router", "udp");
     95   1.1      cgd 	if (sp == NULL) {
     96   1.1      cgd 		fprintf(stderr, "routed: router/udp: unknown service\n");
     97   1.1      cgd 		exit(1);
     98   1.1      cgd 	}
     99   1.1      cgd 	addr.sin_family = AF_INET;
    100   1.1      cgd 	addr.sin_port = sp->s_port;
    101   1.5  mycroft 	r = socket(AF_ROUTE, SOCK_RAW, 0);
    102   1.5  mycroft 	/* later, get smart about lookingforinterfaces */
    103   1.5  mycroft 	if (r)
    104   1.5  mycroft 		shutdown(r, 0); /* for now, don't want reponses */
    105   1.5  mycroft 	else {
    106   1.5  mycroft 		fprintf(stderr, "routed: no routing socket\n");
    107   1.5  mycroft 		exit(1);
    108   1.5  mycroft 	}
    109   1.1      cgd 	s = getsocket(AF_INET, SOCK_DGRAM, &addr);
    110   1.1      cgd 	if (s < 0)
    111   1.1      cgd 		exit(1);
    112   1.1      cgd 	argv++, argc--;
    113   1.1      cgd 	while (argc > 0 && **argv == '-') {
    114   1.1      cgd 		if (strcmp(*argv, "-s") == 0) {
    115   1.1      cgd 			supplier = 1;
    116   1.1      cgd 			argv++, argc--;
    117   1.1      cgd 			continue;
    118   1.1      cgd 		}
    119   1.1      cgd 		if (strcmp(*argv, "-q") == 0) {
    120   1.1      cgd 			supplier = 0;
    121   1.1      cgd 			argv++, argc--;
    122   1.1      cgd 			continue;
    123   1.1      cgd 		}
    124   1.1      cgd 		if (strcmp(*argv, "-t") == 0) {
    125   1.1      cgd 			tflags++;
    126   1.1      cgd 			setlogmask(LOG_UPTO(LOG_DEBUG));
    127   1.1      cgd 			argv++, argc--;
    128   1.1      cgd 			continue;
    129   1.1      cgd 		}
    130   1.1      cgd 		if (strcmp(*argv, "-d") == 0) {
    131   1.1      cgd 			debug++;
    132   1.1      cgd 			setlogmask(LOG_UPTO(LOG_DEBUG));
    133   1.1      cgd 			argv++, argc--;
    134   1.1      cgd 			continue;
    135   1.1      cgd 		}
    136   1.1      cgd 		if (strcmp(*argv, "-g") == 0) {
    137   1.1      cgd 			gateway = 1;
    138   1.1      cgd 			argv++, argc--;
    139   1.1      cgd 			continue;
    140   1.1      cgd 		}
    141   1.1      cgd 		fprintf(stderr,
    142   1.1      cgd 			"usage: routed [ -s ] [ -q ] [ -t ] [ -g ]\n");
    143   1.1      cgd 		exit(1);
    144   1.1      cgd 	}
    145   1.1      cgd 
    146   1.5  mycroft 	if (debug == 0 && tflags == 0)
    147   1.1      cgd 		daemon(0, 0);
    148   1.1      cgd 	/*
    149   1.1      cgd 	 * Any extra argument is considered
    150   1.1      cgd 	 * a tracing log file.
    151   1.1      cgd 	 */
    152   1.1      cgd 	if (argc > 0)
    153   1.1      cgd 		traceon(*argv);
    154   1.1      cgd 	while (tflags-- > 0)
    155   1.1      cgd 		bumploglevel();
    156   1.1      cgd 
    157   1.1      cgd 	(void) gettimeofday(&now, (struct timezone *)NULL);
    158   1.1      cgd 	/*
    159   1.1      cgd 	 * Collect an initial view of the world by
    160   1.1      cgd 	 * checking the interface configuration and the gateway kludge
    161   1.1      cgd 	 * file.  Then, send a request packet on all
    162   1.1      cgd 	 * directly connected networks to find out what
    163   1.1      cgd 	 * everyone else thinks.
    164   1.1      cgd 	 */
    165   1.1      cgd 	rtinit();
    166   1.1      cgd 	ifinit();
    167   1.1      cgd 	gwkludge();
    168   1.1      cgd 	if (gateway > 0)
    169   1.1      cgd 		rtdefault();
    170   1.1      cgd 	if (supplier < 0)
    171   1.1      cgd 		supplier = 0;
    172   1.1      cgd 	query->rip_cmd = RIPCMD_REQUEST;
    173   1.1      cgd 	query->rip_vers = RIPVERSION;
    174   1.1      cgd 	if (sizeof(query->rip_nets[0].rip_dst.sa_family) > 1)	/* XXX */
    175   1.1      cgd 		query->rip_nets[0].rip_dst.sa_family = htons((u_short)AF_UNSPEC);
    176   1.1      cgd 	else
    177   1.1      cgd 		query->rip_nets[0].rip_dst.sa_family = AF_UNSPEC;
    178   1.1      cgd 	query->rip_nets[0].rip_metric = htonl((u_long)HOPCNT_INFINITY);
    179   1.6      cgd 	toall(sndmsg, 0, NULL);
    180   1.1      cgd 	signal(SIGALRM, timer);
    181   1.1      cgd 	signal(SIGHUP, hup);
    182   1.1      cgd 	signal(SIGTERM, hup);
    183   1.1      cgd 	signal(SIGINT, rtdeleteall);
    184   1.1      cgd 	signal(SIGUSR1, sigtrace);
    185   1.1      cgd 	signal(SIGUSR2, sigtrace);
    186   1.1      cgd 	itval.it_interval.tv_sec = TIMER_RATE;
    187   1.1      cgd 	itval.it_value.tv_sec = TIMER_RATE;
    188   1.1      cgd 	itval.it_interval.tv_usec = 0;
    189   1.1      cgd 	itval.it_value.tv_usec = 0;
    190   1.1      cgd 	srandom(getpid());
    191   1.1      cgd 	if (setitimer(ITIMER_REAL, &itval, (struct itimerval *)NULL) < 0)
    192   1.1      cgd 		syslog(LOG_ERR, "setitimer: %m\n");
    193   1.1      cgd 
    194   1.1      cgd 	FD_ZERO(&ibits);
    195   1.1      cgd 	nfd = s + 1;			/* 1 + max(fd's) */
    196   1.1      cgd 	for (;;) {
    197   1.1      cgd 		FD_SET(s, &ibits);
    198   1.1      cgd 		/*
    199   1.1      cgd 		 * If we need a dynamic update that was held off,
    200   1.1      cgd 		 * needupdate will be set, and nextbcast is the time
    201   1.1      cgd 		 * by which we want select to return.  Compute time
    202   1.1      cgd 		 * until dynamic update should be sent, and select only
    203   1.1      cgd 		 * until then.  If we have already passed nextbcast,
    204   1.1      cgd 		 * just poll.
    205   1.1      cgd 		 */
    206   1.1      cgd 		if (needupdate) {
    207   1.9  mycroft 			timersub(&nextbcast, &now, &waittime);
    208   1.1      cgd 			if (waittime.tv_sec < 0) {
    209   1.1      cgd 				waittime.tv_sec = 0;
    210   1.1      cgd 				waittime.tv_usec = 0;
    211   1.1      cgd 			}
    212   1.1      cgd 			if (traceactions)
    213   1.1      cgd 				fprintf(ftrace,
    214   1.1      cgd 				 "select until dynamic update %d/%d sec/usec\n",
    215   1.1      cgd 				    waittime.tv_sec, waittime.tv_usec);
    216   1.1      cgd 			tvp = &waittime;
    217   1.1      cgd 		} else
    218   1.1      cgd 			tvp = (struct timeval *)NULL;
    219   1.1      cgd 		n = select(nfd, &ibits, 0, 0, tvp);
    220   1.1      cgd 		if (n <= 0) {
    221   1.1      cgd 			/*
    222   1.1      cgd 			 * Need delayed dynamic update if select returned
    223   1.1      cgd 			 * nothing and we timed out.  Otherwise, ignore
    224   1.1      cgd 			 * errors (e.g. EINTR).
    225   1.1      cgd 			 */
    226   1.1      cgd 			if (n < 0) {
    227   1.1      cgd 				if (errno == EINTR)
    228   1.1      cgd 					continue;
    229   1.1      cgd 				syslog(LOG_ERR, "select: %m");
    230   1.1      cgd 			}
    231  1.10  mycroft 			sigemptyset(&sigset);
    232  1.10  mycroft 			sigaddset(&sigset, SIGALRM);
    233  1.10  mycroft 			sigprocmask(SIG_BLOCK, &sigset, &osigset);
    234   1.1      cgd 			if (n == 0 && needupdate) {
    235   1.1      cgd 				if (traceactions)
    236   1.1      cgd 					fprintf(ftrace,
    237   1.1      cgd 					    "send delayed dynamic update\n");
    238   1.1      cgd 				(void) gettimeofday(&now,
    239   1.1      cgd 					    (struct timezone *)NULL);
    240   1.1      cgd 				toall(supply, RTS_CHANGED,
    241   1.1      cgd 				    (struct interface *)NULL);
    242   1.1      cgd 				lastbcast = now;
    243   1.1      cgd 				needupdate = 0;
    244   1.1      cgd 				nextbcast.tv_sec = 0;
    245   1.1      cgd 			}
    246  1.10  mycroft 			sigprocmask(SIG_SETMASK, &osigset, NULL);
    247   1.1      cgd 			continue;
    248   1.1      cgd 		}
    249   1.1      cgd 		(void) gettimeofday(&now, (struct timezone *)NULL);
    250  1.10  mycroft 		sigemptyset(&sigset);
    251  1.10  mycroft 		sigaddset(&sigset, SIGALRM);
    252  1.10  mycroft 		sigprocmask(SIG_BLOCK, &sigset, &osigset);
    253   1.1      cgd #ifdef doesntwork
    254   1.1      cgd /*
    255   1.1      cgd printf("s %d, ibits %x index %d, mod %d, sh %x, or %x &ibits %x\n",
    256   1.1      cgd 	s,
    257   1.1      cgd 	ibits.fds_bits[0],
    258   1.1      cgd 	(s)/(sizeof(fd_mask) * 8),
    259   1.1      cgd 	((s) % (sizeof(fd_mask) * 8)),
    260   1.1      cgd 	(1 << ((s) % (sizeof(fd_mask) * 8))),
    261   1.1      cgd 	ibits.fds_bits[(s)/(sizeof(fd_mask) * 8)] & (1 << ((s) % (sizeof(fd_mask) * 8))),
    262   1.1      cgd 	&ibits
    263   1.1      cgd 	);
    264   1.1      cgd */
    265   1.1      cgd 		if (FD_ISSET(s, &ibits))
    266   1.1      cgd #else
    267   1.1      cgd 		if (ibits.fds_bits[s/32] & (1 << s))
    268   1.1      cgd #endif
    269   1.1      cgd 			process(s);
    270   1.1      cgd 		/* handle ICMP redirects */
    271  1.10  mycroft 		sigprocmask(SIG_SETMASK, &osigset, NULL);
    272   1.1      cgd 	}
    273   1.1      cgd }
    274   1.1      cgd 
    275   1.6      cgd void
    276   1.1      cgd process(fd)
    277   1.1      cgd 	int fd;
    278   1.1      cgd {
    279   1.1      cgd 	struct sockaddr from;
    280   1.1      cgd 	int fromlen, cc;
    281   1.1      cgd 	union {
    282   1.1      cgd 		char	buf[MAXPACKETSIZE+1];
    283   1.1      cgd 		struct	rip rip;
    284   1.1      cgd 	} inbuf;
    285   1.1      cgd 
    286   1.1      cgd 	for (;;) {
    287   1.1      cgd 		fromlen = sizeof (from);
    288   1.1      cgd 		cc = recvfrom(fd, &inbuf, sizeof (inbuf), 0, &from, &fromlen);
    289   1.1      cgd 		if (cc <= 0) {
    290   1.1      cgd 			if (cc < 0 && errno != EWOULDBLOCK)
    291   1.1      cgd 				perror("recvfrom");
    292   1.1      cgd 			break;
    293   1.1      cgd 		}
    294   1.1      cgd 		if (fromlen != sizeof (struct sockaddr_in))
    295   1.1      cgd 			break;
    296   1.1      cgd 		rip_input(&from, &inbuf.rip, cc);
    297   1.1      cgd 	}
    298   1.1      cgd }
    299   1.1      cgd 
    300   1.6      cgd int
    301   1.1      cgd getsocket(domain, type, sin)
    302   1.1      cgd 	int domain, type;
    303   1.1      cgd 	struct sockaddr_in *sin;
    304   1.1      cgd {
    305   1.1      cgd 	int sock, on = 1;
    306   1.1      cgd 
    307   1.1      cgd 	if ((sock = socket(domain, type, 0)) < 0) {
    308   1.1      cgd 		perror("socket");
    309   1.1      cgd 		syslog(LOG_ERR, "socket: %m");
    310   1.1      cgd 		return (-1);
    311   1.1      cgd 	}
    312   1.1      cgd #ifdef SO_BROADCAST
    313   1.1      cgd 	if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) {
    314   1.1      cgd 		syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
    315   1.1      cgd 		close(sock);
    316   1.1      cgd 		return (-1);
    317   1.1      cgd 	}
    318   1.1      cgd #endif
    319   1.1      cgd #ifdef SO_RCVBUF
    320   1.1      cgd 	for (on = bufspace; ; on -= 1024) {
    321   1.1      cgd 		if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
    322   1.1      cgd 		    &on, sizeof (on)) == 0)
    323   1.1      cgd 			break;
    324   1.1      cgd 		if (on <= 8*1024) {
    325   1.1      cgd 			syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m");
    326   1.1      cgd 			break;
    327   1.1      cgd 		}
    328   1.1      cgd 	}
    329   1.1      cgd 	if (traceactions)
    330   1.1      cgd 		fprintf(ftrace, "recv buf %d\n", on);
    331   1.1      cgd #endif
    332   1.1      cgd 	if (bind(sock, (struct sockaddr *)sin, sizeof (*sin)) < 0) {
    333   1.1      cgd 		perror("bind");
    334   1.1      cgd 		syslog(LOG_ERR, "bind: %m");
    335   1.1      cgd 		close(sock);
    336   1.1      cgd 		return (-1);
    337   1.1      cgd 	}
    338   1.1      cgd 	if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
    339   1.1      cgd 		syslog(LOG_ERR, "fcntl O_NONBLOCK: %m\n");
    340   1.1      cgd 	return (sock);
    341   1.1      cgd }
    342