xref: /csrg-svn/sbin/routed/main.c (revision 13036)
19017Ssam #ifndef lint
2*13036Ssam static char sccsid[] = "@(#)main.c	4.7 (Berkeley) 06/12/83";
39017Ssam #endif
49017Ssam 
59017Ssam /*
69017Ssam  * Routing Table Management Daemon
79017Ssam  */
810245Ssam #include "defs.h"
99017Ssam #include <sys/ioctl.h>
109017Ssam #include <net/if.h>
119017Ssam #include <errno.h>
129017Ssam #include <nlist.h>
139017Ssam #include <signal.h>
149017Ssam #include <time.h>
159017Ssam 
169017Ssam int	supplier = -1;		/* process should supply updates */
179017Ssam 
189017Ssam struct	rip *msg = (struct rip *)packet;
199017Ssam 
209017Ssam main(argc, argv)
219017Ssam 	int argc;
229017Ssam 	char *argv[];
239017Ssam {
249017Ssam 	int cc;
259017Ssam 	struct sockaddr from;
2610245Ssam 	u_char retry;
2710245Ssam #ifdef COMPAT
2810245Ssam 	int snoroute;
2910245Ssam #endif
309017Ssam 
319017Ssam 	argv0 = argv;
329017Ssam 	sp = getservbyname("router", "udp");
3310245Ssam 	if (sp == NULL) {
3410245Ssam 		fprintf(stderr, "routed: router/udp: unknown service\n");
359017Ssam 		exit(1);
369017Ssam 	}
3710245Ssam 	addr.sin_family = AF_INET;
3810245Ssam 	addr.sin_port = sp->s_port;
3910245Ssam 	s = getsocket(AF_INET, SOCK_DGRAM, &addr);
4010245Ssam 	if (s < 0)
4110245Ssam 		exit(1);
4210245Ssam #ifdef COMPAT
4310245Ssam 	bzero(&addr, sizeof (addr));
4410245Ssam 	addr.sin_family = AF_INET;
4510245Ssam 	addr.sin_port = htons(ntohs(sp->s_port) + 1);
4610245Ssam 	snoroute = getsocket(AF_INET, SOCK_DGRAM, &addr);
4710245Ssam 	if (snoroute < 0)
4810245Ssam 		exit(1);
4910245Ssam #endif
509017Ssam 	argv++, argc--;
519017Ssam 	while (argc > 0 && **argv == '-') {
5210636Ssam 		if (strcmp(*argv, "-s") == 0) {
539017Ssam 			supplier = 1;
549017Ssam 			argv++, argc--;
559017Ssam 			continue;
569017Ssam 		}
5710636Ssam 		if (strcmp(*argv, "-q") == 0) {
589017Ssam 			supplier = 0;
599017Ssam 			argv++, argc--;
609017Ssam 			continue;
619017Ssam 		}
6210636Ssam 		if (strcmp(*argv, "-t") == 0) {
6310636Ssam 			tracepackets++;
6410636Ssam 			argv++, argc--;
6510636Ssam 			continue;
6610636Ssam 		}
6710636Ssam 		fprintf(stderr, "usage: routed [ -s ] [ -q ] [ -t ]\n");
689017Ssam 		exit(1);
699017Ssam 	}
7010636Ssam #ifndef DEBUG
7110636Ssam 	if (!tracepackets) {
7210636Ssam 		int t;
7310636Ssam 
7410636Ssam 		if (fork())
7510636Ssam 			exit(0);
7610637Ssam 		for (t = 0; t < 20; t++)
7710637Ssam 			if (t != s)
7810637Ssam #ifdef COMPAT
7912726Ssam 				if (t != snoroute)
8010637Ssam #endif
8110637Ssam 				(void) close(cc);
8210636Ssam 		(void) open("/", 0);
8310636Ssam 		(void) dup2(0, 1);
8410636Ssam 		(void) dup2(0, 2);
8510636Ssam 		t = open("/dev/tty", 2);
8610636Ssam 		if (t >= 0) {
8710636Ssam 			ioctl(t, TIOCNOTTY, (char *)0);
8810636Ssam 			(void) close(t);
8910636Ssam 		}
9010636Ssam 	}
9110636Ssam #endif
929017Ssam 	/*
9310245Ssam 	 * Any extra argument is considered
9410245Ssam 	 * a tracing log file.
9510245Ssam 	 */
9610245Ssam 	if (argc > 0)
9710245Ssam 		traceon(*argv);
9810245Ssam 	/*
999017Ssam 	 * Collect an initial view of the world by
1009017Ssam 	 * snooping in the kernel and the gateway kludge
1019017Ssam 	 * file.  Then, send a request packet on all
1029017Ssam 	 * directly connected networks to find out what
1039017Ssam 	 * everyone else thinks.
1049017Ssam 	 */
1059017Ssam 	rtinit();
1069017Ssam 	gwkludge();
1079017Ssam 	ifinit();
1089017Ssam 	if (supplier < 0)
1099017Ssam 		supplier = 0;
1109017Ssam 	msg->rip_cmd = RIPCMD_REQUEST;
11112726Ssam 	msg->rip_vers = RIPVERSION;
1129017Ssam 	msg->rip_nets[0].rip_dst.sa_family = AF_UNSPEC;
1139017Ssam 	msg->rip_nets[0].rip_metric = HOPCNT_INFINITY;
11412726Ssam 	msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC);
11512726Ssam 	msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY);
1169017Ssam 	toall(sendmsg);
117*13036Ssam 	signal(SIGALRM, timer);
1189017Ssam 	timer();
1199017Ssam 
1209017Ssam 	for (;;) {
1219017Ssam 		int ibits;
1229017Ssam 		register int n;
1239017Ssam 
12410245Ssam 		ibits = 1 << s;
12510245Ssam #ifdef COMPAT
12610245Ssam 		ibits |= 1 << snoroute;
12710245Ssam #endif
12810245Ssam 		n = select(20, &ibits, 0, 0, 0);
1299017Ssam 		if (n < 0)
1309017Ssam 			continue;
1319017Ssam 		if (ibits & (1 << s))
1329017Ssam 			process(s);
13310245Ssam #ifdef COMPAT
1349017Ssam 		if (ibits & (1 << snoroute))
1359017Ssam 			process(snoroute);
13610245Ssam #endif
13710245Ssam 		/* handle ICMP redirects */
1389017Ssam 	}
1399017Ssam }
1409017Ssam 
1419017Ssam process(fd)
1429017Ssam 	int fd;
1439017Ssam {
1449017Ssam 	struct sockaddr from;
145*13036Ssam 	int fromlen = sizeof (from), cc, omask;
1469017Ssam 
14710245Ssam 	cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen);
1489017Ssam 	if (cc <= 0) {
1499017Ssam 		if (cc < 0 && errno != EINTR)
15010245Ssam 			perror("recvfrom");
1519017Ssam 		return;
1529017Ssam 	}
15310245Ssam 	if (fromlen != sizeof (struct sockaddr_in))
15410245Ssam 		return;
155*13036Ssam #define	mask(s)	(1<<((s)-1))
156*13036Ssam 	omask = sigblock(mask(SIGALRM));
1579017Ssam 	rip_input(&from, cc);
158*13036Ssam 	sigsetmask(omask);
1599017Ssam }
16010245Ssam 
16110245Ssam getsocket(domain, type, sin)
16210245Ssam 	int domain, type;
16310245Ssam 	struct sockaddr_in *sin;
16410245Ssam {
16510245Ssam 	int retry, s;
16610245Ssam 
16710245Ssam 	retry = 1;
16810245Ssam 	while ((s = socket(domain, type, 0, 0)) < 0 && retry) {
16910245Ssam 		perror("socket");
17010245Ssam 		sleep(5 * retry);
17110245Ssam 		retry <<= 1;
17210245Ssam 	}
17310245Ssam 	if (retry == 0)
17410245Ssam 		return (-1);
17510245Ssam 	while (bind(s, sin, sizeof (*sin), 0) < 0 && retry) {
17610245Ssam 		perror("bind");
17710245Ssam 		sleep(5 * retry);
17810245Ssam 		retry <<= 1;
17910245Ssam 	}
18010245Ssam 	if (retry == 0)
18110245Ssam 		return (-1);
18210245Ssam 	return (s);
18310245Ssam }
184