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