xref: /csrg-svn/sbin/routed/main.c (revision 10245)
19017Ssam #ifndef lint
2*10245Ssam static char sccsid[] = "@(#)main.c	4.2 01/11/83";
39017Ssam #endif
49017Ssam 
59017Ssam /*
69017Ssam  * Routing Table Management Daemon
79017Ssam  */
8*10245Ssam #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;
26*10245Ssam 	u_char retry;
27*10245Ssam #ifdef COMPAT
28*10245Ssam 	int snoroute;
29*10245Ssam #endif
309017Ssam 
319017Ssam 	argv0 = argv;
329017Ssam #ifndef DEBUG
339017Ssam 	if (fork())
349017Ssam 		exit(0);
359017Ssam 	for (cc = 0; cc < 10; cc++)
369017Ssam 		(void) close(cc);
379017Ssam 	(void) open("/", 0);
389017Ssam 	(void) dup2(0, 1);
399017Ssam 	(void) dup2(0, 2);
409017Ssam 	{ int t = open("/dev/tty", 2);
419017Ssam 	  if (t >= 0) {
429017Ssam 		ioctl(t, TIOCNOTTY, (char *)0);
439017Ssam 		(void) close(t);
449017Ssam 	  }
459017Ssam 	}
469017Ssam #endif
479017Ssam 	sp = getservbyname("router", "udp");
48*10245Ssam 	if (sp == NULL) {
49*10245Ssam 		fprintf(stderr, "routed: router/udp: unknown service\n");
509017Ssam 		exit(1);
519017Ssam 	}
52*10245Ssam 	addr.sin_family = AF_INET;
53*10245Ssam 	addr.sin_port = sp->s_port;
54*10245Ssam 	s = getsocket(AF_INET, SOCK_DGRAM, &addr);
55*10245Ssam 	if (s < 0)
56*10245Ssam 		exit(1);
57*10245Ssam #ifdef COMPAT
58*10245Ssam 	bzero(&addr, sizeof (addr));
59*10245Ssam 	addr.sin_family = AF_INET;
60*10245Ssam 	addr.sin_port = htons(ntohs(sp->s_port) + 1);
61*10245Ssam 	snoroute = getsocket(AF_INET, SOCK_DGRAM, &addr);
62*10245Ssam 	if (snoroute < 0)
63*10245Ssam 		exit(1);
64*10245Ssam #endif
659017Ssam 	argv++, argc--;
669017Ssam 	while (argc > 0 && **argv == '-') {
679017Ssam 		if (!strcmp(*argv, "-s") == 0) {
689017Ssam 			supplier = 1;
699017Ssam 			argv++, argc--;
709017Ssam 			continue;
719017Ssam 		}
729017Ssam 		if (!strcmp(*argv, "-q") == 0) {
739017Ssam 			supplier = 0;
749017Ssam 			argv++, argc--;
759017Ssam 			continue;
769017Ssam 		}
779017Ssam 		fprintf(stderr, "usage: routed [ -s ] [ -q ]\n");
789017Ssam 		exit(1);
799017Ssam 	}
809017Ssam 	/*
81*10245Ssam 	 * Any extra argument is considered
82*10245Ssam 	 * a tracing log file.
83*10245Ssam 	 */
84*10245Ssam 	if (argc > 0)
85*10245Ssam 		traceon(*argv);
86*10245Ssam 	/*
879017Ssam 	 * Collect an initial view of the world by
889017Ssam 	 * snooping in the kernel and the gateway kludge
899017Ssam 	 * file.  Then, send a request packet on all
909017Ssam 	 * directly connected networks to find out what
919017Ssam 	 * everyone else thinks.
929017Ssam 	 */
939017Ssam 	rtinit();
949017Ssam 	gwkludge();
959017Ssam 	ifinit();
969017Ssam 	if (supplier < 0)
979017Ssam 		supplier = 0;
989017Ssam 	msg->rip_cmd = RIPCMD_REQUEST;
999017Ssam 	msg->rip_nets[0].rip_dst.sa_family = AF_UNSPEC;
1009017Ssam 	msg->rip_nets[0].rip_metric = HOPCNT_INFINITY;
1019017Ssam 	toall(sendmsg);
1029017Ssam 	sigset(SIGALRM, timer);
1039017Ssam 	timer();
1049017Ssam 
1059017Ssam 	for (;;) {
1069017Ssam 		int ibits;
1079017Ssam 		register int n;
1089017Ssam 
109*10245Ssam 		ibits = 1 << s;
110*10245Ssam #ifdef COMPAT
111*10245Ssam 		ibits |= 1 << snoroute;
112*10245Ssam #endif
113*10245Ssam 		n = select(20, &ibits, 0, 0, 0);
1149017Ssam 		if (n < 0)
1159017Ssam 			continue;
1169017Ssam 		if (ibits & (1 << s))
1179017Ssam 			process(s);
118*10245Ssam #ifdef COMPAT
1199017Ssam 		if (ibits & (1 << snoroute))
1209017Ssam 			process(snoroute);
121*10245Ssam #endif
122*10245Ssam 		/* handle ICMP redirects */
1239017Ssam 	}
1249017Ssam }
1259017Ssam 
1269017Ssam process(fd)
1279017Ssam 	int fd;
1289017Ssam {
1299017Ssam 	struct sockaddr from;
130*10245Ssam 	int fromlen = sizeof (from), cc;
1319017Ssam 
132*10245Ssam 	cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen);
1339017Ssam 	if (cc <= 0) {
1349017Ssam 		if (cc < 0 && errno != EINTR)
135*10245Ssam 			perror("recvfrom");
1369017Ssam 		return;
1379017Ssam 	}
138*10245Ssam 	if (fromlen != sizeof (struct sockaddr_in))
139*10245Ssam 		return;
1409017Ssam 	sighold(SIGALRM);
1419017Ssam 	rip_input(&from, cc);
1429017Ssam 	sigrelse(SIGALRM);
1439017Ssam }
144*10245Ssam 
145*10245Ssam getsocket(domain, type, sin)
146*10245Ssam 	int domain, type;
147*10245Ssam 	struct sockaddr_in *sin;
148*10245Ssam {
149*10245Ssam 	int retry, s;
150*10245Ssam 
151*10245Ssam 	retry = 1;
152*10245Ssam 	while ((s = socket(domain, type, 0, 0)) < 0 && retry) {
153*10245Ssam 		perror("socket");
154*10245Ssam 		sleep(5 * retry);
155*10245Ssam 		retry <<= 1;
156*10245Ssam 	}
157*10245Ssam 	if (retry == 0)
158*10245Ssam 		return (-1);
159*10245Ssam 	while (bind(s, sin, sizeof (*sin), 0) < 0 && retry) {
160*10245Ssam 		perror("bind");
161*10245Ssam 		sleep(5 * retry);
162*10245Ssam 		retry <<= 1;
163*10245Ssam 	}
164*10245Ssam 	if (retry == 0)
165*10245Ssam 		return (-1);
166*10245Ssam 	return (s);
167*10245Ssam }
168