xref: /csrg-svn/sbin/routed/main.c (revision 17570)
19017Ssam #ifndef lint
2*17570Skarels static char sccsid[] = "@(#)main.c	4.11 (Berkeley) 12/20/84";
39017Ssam #endif
49017Ssam 
59017Ssam /*
69017Ssam  * Routing Table Management Daemon
79017Ssam  */
810245Ssam #include "defs.h"
99017Ssam #include <sys/ioctl.h>
1013602Ssam #include <sys/time.h>
1113602Ssam 
129017Ssam #include <net/if.h>
1313602Ssam 
149017Ssam #include <errno.h>
159017Ssam #include <nlist.h>
169017Ssam #include <signal.h>
17*17570Skarels #include <syslog.h>
189017Ssam 
199017Ssam int	supplier = -1;		/* process should supply updates */
2016326Skarels extern int gateway;
219017Ssam 
229017Ssam struct	rip *msg = (struct rip *)packet;
2316314Skarels int	hup();
249017Ssam 
259017Ssam main(argc, argv)
269017Ssam 	int argc;
279017Ssam 	char *argv[];
289017Ssam {
299017Ssam 	int cc;
309017Ssam 	struct sockaddr from;
3110245Ssam 	u_char retry;
3210245Ssam #ifdef COMPAT
3310245Ssam 	int snoroute;
3410245Ssam #endif
359017Ssam 
369017Ssam 	argv0 = argv;
37*17570Skarels 	openlog("routed", LOG_PID, 0);
389017Ssam 	sp = getservbyname("router", "udp");
3910245Ssam 	if (sp == NULL) {
4010245Ssam 		fprintf(stderr, "routed: router/udp: unknown service\n");
419017Ssam 		exit(1);
429017Ssam 	}
4310245Ssam 	addr.sin_family = AF_INET;
4410245Ssam 	addr.sin_port = sp->s_port;
4510245Ssam 	s = getsocket(AF_INET, SOCK_DGRAM, &addr);
4610245Ssam 	if (s < 0)
4710245Ssam 		exit(1);
4810245Ssam #ifdef COMPAT
4910245Ssam 	bzero(&addr, sizeof (addr));
5010245Ssam 	addr.sin_family = AF_INET;
5110245Ssam 	addr.sin_port = htons(ntohs(sp->s_port) + 1);
5210245Ssam 	snoroute = getsocket(AF_INET, SOCK_DGRAM, &addr);
5310245Ssam 	if (snoroute < 0)
5410245Ssam 		exit(1);
5510245Ssam #endif
569017Ssam 	argv++, argc--;
579017Ssam 	while (argc > 0 && **argv == '-') {
5810636Ssam 		if (strcmp(*argv, "-s") == 0) {
599017Ssam 			supplier = 1;
609017Ssam 			argv++, argc--;
619017Ssam 			continue;
629017Ssam 		}
6310636Ssam 		if (strcmp(*argv, "-q") == 0) {
649017Ssam 			supplier = 0;
659017Ssam 			argv++, argc--;
669017Ssam 			continue;
679017Ssam 		}
6810636Ssam 		if (strcmp(*argv, "-t") == 0) {
6910636Ssam 			tracepackets++;
7010636Ssam 			argv++, argc--;
7110636Ssam 			continue;
7210636Ssam 		}
7316326Skarels 		if (strcmp(*argv, "-g") == 0) {
7416326Skarels 			gateway = 1;
7516326Skarels 			argv++, argc--;
7616326Skarels 			continue;
7716326Skarels 		}
7816326Skarels 		if (strcmp(*argv, "-l") == 0) {
7916326Skarels 			gateway = -1;
8016326Skarels 			argv++, argc--;
8116326Skarels 			continue;
8216326Skarels 		}
8316326Skarels 		fprintf(stderr,
8416326Skarels 			"usage: routed [ -s ] [ -q ] [ -t ] [ -g ] [ -l ]\n");
859017Ssam 		exit(1);
869017Ssam 	}
8710636Ssam #ifndef DEBUG
8810636Ssam 	if (!tracepackets) {
8910636Ssam 		int t;
9010636Ssam 
9110636Ssam 		if (fork())
9210636Ssam 			exit(0);
9310637Ssam 		for (t = 0; t < 20; t++)
9410637Ssam 			if (t != s)
9510637Ssam #ifdef COMPAT
9612726Ssam 				if (t != snoroute)
9710637Ssam #endif
9810637Ssam 				(void) close(cc);
9910636Ssam 		(void) open("/", 0);
10010636Ssam 		(void) dup2(0, 1);
10110636Ssam 		(void) dup2(0, 2);
10210636Ssam 		t = open("/dev/tty", 2);
10310636Ssam 		if (t >= 0) {
10410636Ssam 			ioctl(t, TIOCNOTTY, (char *)0);
10510636Ssam 			(void) close(t);
10610636Ssam 		}
10710636Ssam 	}
10810636Ssam #endif
1099017Ssam 	/*
11010245Ssam 	 * Any extra argument is considered
11110245Ssam 	 * a tracing log file.
11210245Ssam 	 */
11310245Ssam 	if (argc > 0)
11410245Ssam 		traceon(*argv);
11510245Ssam 	/*
1169017Ssam 	 * Collect an initial view of the world by
1179017Ssam 	 * snooping in the kernel and the gateway kludge
1189017Ssam 	 * file.  Then, send a request packet on all
1199017Ssam 	 * directly connected networks to find out what
1209017Ssam 	 * everyone else thinks.
1219017Ssam 	 */
1229017Ssam 	rtinit();
1239017Ssam 	gwkludge();
1249017Ssam 	ifinit();
1259017Ssam 	if (supplier < 0)
1269017Ssam 		supplier = 0;
1279017Ssam 	msg->rip_cmd = RIPCMD_REQUEST;
12812726Ssam 	msg->rip_vers = RIPVERSION;
1299017Ssam 	msg->rip_nets[0].rip_dst.sa_family = AF_UNSPEC;
1309017Ssam 	msg->rip_nets[0].rip_metric = HOPCNT_INFINITY;
13112726Ssam 	msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC);
13212726Ssam 	msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY);
1339017Ssam 	toall(sendmsg);
13413036Ssam 	signal(SIGALRM, timer);
13516314Skarels 	signal(SIGHUP, hup);
136*17570Skarels 	signal(SIGTERM, hup);
1379017Ssam 	timer();
1389017Ssam 
1399017Ssam 	for (;;) {
1409017Ssam 		int ibits;
1419017Ssam 		register int n;
1429017Ssam 
14310245Ssam 		ibits = 1 << s;
14410245Ssam #ifdef COMPAT
14510245Ssam 		ibits |= 1 << snoroute;
14610245Ssam #endif
14710245Ssam 		n = select(20, &ibits, 0, 0, 0);
1489017Ssam 		if (n < 0)
1499017Ssam 			continue;
1509017Ssam 		if (ibits & (1 << s))
1519017Ssam 			process(s);
15210245Ssam #ifdef COMPAT
1539017Ssam 		if (ibits & (1 << snoroute))
1549017Ssam 			process(snoroute);
15510245Ssam #endif
15610245Ssam 		/* handle ICMP redirects */
1579017Ssam 	}
1589017Ssam }
1599017Ssam 
1609017Ssam process(fd)
1619017Ssam 	int fd;
1629017Ssam {
1639017Ssam 	struct sockaddr from;
16413036Ssam 	int fromlen = sizeof (from), cc, omask;
1659017Ssam 
16610245Ssam 	cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen);
1679017Ssam 	if (cc <= 0) {
1689017Ssam 		if (cc < 0 && errno != EINTR)
16910245Ssam 			perror("recvfrom");
1709017Ssam 		return;
1719017Ssam 	}
17210245Ssam 	if (fromlen != sizeof (struct sockaddr_in))
17310245Ssam 		return;
17413036Ssam #define	mask(s)	(1<<((s)-1))
17513036Ssam 	omask = sigblock(mask(SIGALRM));
1769017Ssam 	rip_input(&from, cc);
17713036Ssam 	sigsetmask(omask);
1789017Ssam }
17910245Ssam 
18010245Ssam getsocket(domain, type, sin)
18110245Ssam 	int domain, type;
18210245Ssam 	struct sockaddr_in *sin;
18310245Ssam {
184*17570Skarels 	int retry, s, on = 1;
18510245Ssam 
18610245Ssam 	retry = 1;
18710245Ssam 	while ((s = socket(domain, type, 0, 0)) < 0 && retry) {
18810245Ssam 		perror("socket");
18910245Ssam 		sleep(5 * retry);
19010245Ssam 		retry <<= 1;
19110245Ssam 	}
192*17570Skarels 	if (retry == 0) {
193*17570Skarels 		syslog(LOG_ERR, "socket: %m");
19410245Ssam 		return (-1);
195*17570Skarels 	}
196*17570Skarels 	if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) {
197*17570Skarels 		syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
198*17570Skarels 		exit(1);
199*17570Skarels 	}
20010245Ssam 	while (bind(s, sin, sizeof (*sin), 0) < 0 && retry) {
20110245Ssam 		perror("bind");
20210245Ssam 		sleep(5 * retry);
20310245Ssam 		retry <<= 1;
20410245Ssam 	}
205*17570Skarels 	if (retry == 0) {
206*17570Skarels 		syslog(LOG_ERR, "bind: %m");
20710245Ssam 		return (-1);
208*17570Skarels 	}
20910245Ssam 	return (s);
21010245Ssam }
211