xref: /csrg-svn/sbin/routed/main.c (revision 9017)
1*9017Ssam #ifndef lint
2*9017Ssam static char sccsid[] = "@(#)main.c	4.1 11/02/82";
3*9017Ssam #endif
4*9017Ssam 
5*9017Ssam /*
6*9017Ssam  * Routing Table Management Daemon
7*9017Ssam  */
8*9017Ssam #include "router.h"
9*9017Ssam #include <sys/ioctl.h>
10*9017Ssam #include <net/if.h>
11*9017Ssam #include <errno.h>
12*9017Ssam #include <nlist.h>
13*9017Ssam #include <signal.h>
14*9017Ssam #include <time.h>
15*9017Ssam 
16*9017Ssam int	supplier = -1;		/* process should supply updates */
17*9017Ssam 
18*9017Ssam struct	rip *msg = (struct rip *)packet;
19*9017Ssam 
20*9017Ssam main(argc, argv)
21*9017Ssam 	int argc;
22*9017Ssam 	char *argv[];
23*9017Ssam {
24*9017Ssam 	int cc;
25*9017Ssam 	struct sockaddr from;
26*9017Ssam 
27*9017Ssam 	argv0 = argv;
28*9017Ssam #ifndef DEBUG
29*9017Ssam 	if (fork())
30*9017Ssam 		exit(0);
31*9017Ssam 	for (cc = 0; cc < 10; cc++)
32*9017Ssam 		(void) close(cc);
33*9017Ssam 	(void) open("/", 0);
34*9017Ssam 	(void) dup2(0, 1);
35*9017Ssam 	(void) dup2(0, 2);
36*9017Ssam 	{ int t = open("/dev/tty", 2);
37*9017Ssam 	  if (t >= 0) {
38*9017Ssam 		ioctl(t, TIOCNOTTY, (char *)0);
39*9017Ssam 		(void) close(t);
40*9017Ssam 	  }
41*9017Ssam 	}
42*9017Ssam #endif
43*9017Ssam 	if (tracing)
44*9017Ssam 		traceon("/etc/routerlog");
45*9017Ssam 
46*9017Ssam 	/*
47*9017Ssam 	 * We use two sockets.  One for which outgoing
48*9017Ssam 	 * packets are routed and for which they're not.
49*9017Ssam 	 * The latter allows us to delete routing table
50*9017Ssam 	 * entries in the kernel for network interfaces
51*9017Ssam 	 * attached to our host which we believe are down
52*9017Ssam 	 * while still polling it to see when/if it comes
53*9017Ssam 	 * back up.  With the new ipc interface we'll be
54*9017Ssam 	 * able to specify ``don't route'' as an option
55*9017Ssam 	 * to send, but until then we utilize a second port.
56*9017Ssam 	 */
57*9017Ssam 	sp = getservbyname("router", "udp");
58*9017Ssam 	if (sp == 0) {
59*9017Ssam 		fprintf(stderr, "routed: udp/router: unknown service\n");
60*9017Ssam 		exit(1);
61*9017Ssam 	}
62*9017Ssam 	routingaddr.sin_family = AF_INET;
63*9017Ssam 	routingaddr.sin_port = htons(sp->s_port);
64*9017Ssam 	noroutingaddr.sin_family = AF_INET;
65*9017Ssam 	noroutingaddr.sin_port = htons(sp->s_port + 1);
66*9017Ssam again:
67*9017Ssam 	s = socket(SOCK_DGRAM, 0, &routingaddr, 0);
68*9017Ssam 	if (s < 0) {
69*9017Ssam 		perror("socket");
70*9017Ssam 		sleep(30);
71*9017Ssam 		goto again;
72*9017Ssam 	}
73*9017Ssam again2:
74*9017Ssam 	snoroute = socket(SOCK_DGRAM, 0, &noroutingaddr, SO_DONTROUTE);
75*9017Ssam 	if (snoroute < 0) {
76*9017Ssam 		perror("socket");
77*9017Ssam 		sleep(30);
78*9017Ssam 		goto again2;
79*9017Ssam 	}
80*9017Ssam 	argv++, argc--;
81*9017Ssam 	while (argc > 0 && **argv == '-') {
82*9017Ssam 		if (!strcmp(*argv, "-s") == 0) {
83*9017Ssam 			supplier = 1;
84*9017Ssam 			argv++, argc--;
85*9017Ssam 			continue;
86*9017Ssam 		}
87*9017Ssam 		if (!strcmp(*argv, "-q") == 0) {
88*9017Ssam 			supplier = 0;
89*9017Ssam 			argv++, argc--;
90*9017Ssam 			continue;
91*9017Ssam 		}
92*9017Ssam 		goto usage;
93*9017Ssam 	}
94*9017Ssam 	if (argc > 0) {
95*9017Ssam usage:
96*9017Ssam 		fprintf(stderr, "usage: routed [ -s ] [ -q ]\n");
97*9017Ssam 		exit(1);
98*9017Ssam 	}
99*9017Ssam 	/*
100*9017Ssam 	 * Collect an initial view of the world by
101*9017Ssam 	 * snooping in the kernel and the gateway kludge
102*9017Ssam 	 * file.  Then, send a request packet on all
103*9017Ssam 	 * directly connected networks to find out what
104*9017Ssam 	 * everyone else thinks.
105*9017Ssam 	 */
106*9017Ssam 	rtinit();
107*9017Ssam 	gwkludge();
108*9017Ssam 	ifinit();
109*9017Ssam 	if (supplier < 0)
110*9017Ssam 		supplier = 0;
111*9017Ssam 	msg->rip_cmd = RIPCMD_REQUEST;
112*9017Ssam 	msg->rip_nets[0].rip_dst.sa_family = AF_UNSPEC;
113*9017Ssam 	msg->rip_nets[0].rip_metric = HOPCNT_INFINITY;
114*9017Ssam 	toall(sendmsg);
115*9017Ssam 	sigset(SIGALRM, timer);
116*9017Ssam 	timer();
117*9017Ssam 
118*9017Ssam #define	INFINITY	1000000
119*9017Ssam 	for (;;) {
120*9017Ssam 		int ibits;
121*9017Ssam 		register int n;
122*9017Ssam 
123*9017Ssam 		ibits = (1 << s) | (1 << snoroute);
124*9017Ssam 		n = select(32, &ibits, 0, INFINITY);
125*9017Ssam 		if (n < 0)
126*9017Ssam 			continue;
127*9017Ssam 		if (ibits & (1 << s))
128*9017Ssam 			process(s);
129*9017Ssam 		if (ibits & (1 << snoroute))
130*9017Ssam 			process(snoroute);
131*9017Ssam 	}
132*9017Ssam }
133*9017Ssam 
134*9017Ssam process(fd)
135*9017Ssam 	int fd;
136*9017Ssam {
137*9017Ssam 	register int cc;
138*9017Ssam 	struct sockaddr from;
139*9017Ssam 
140*9017Ssam 	cc = receive(fd, &from, packet, sizeof (packet));
141*9017Ssam 	if (cc <= 0) {
142*9017Ssam 		if (cc < 0 && errno != EINTR)
143*9017Ssam 			perror("receive");
144*9017Ssam 		return;
145*9017Ssam 	}
146*9017Ssam 	sighold(SIGALRM);
147*9017Ssam 	rip_input(&from, cc);
148*9017Ssam 	sigrelse(SIGALRM);
149*9017Ssam }
150