xref: /original-bsd/sbin/routed/main.c (revision e591299d)
1 #ifndef lint
2 static char sccsid[] = "@(#)main.c	4.12 (Berkeley) 02/25/85";
3 #endif
4 
5 /*
6  * Routing Table Management Daemon
7  */
8 #include "defs.h"
9 #include <sys/ioctl.h>
10 #include <sys/time.h>
11 
12 #include <net/if.h>
13 
14 #include <errno.h>
15 #include <nlist.h>
16 #include <signal.h>
17 #include <syslog.h>
18 
19 int	supplier = -1;		/* process should supply updates */
20 extern int gateway;
21 
22 struct	rip *msg = (struct rip *)packet;
23 int	hup();
24 
25 main(argc, argv)
26 	int argc;
27 	char *argv[];
28 {
29 	int cc;
30 	struct sockaddr from;
31 	u_char retry;
32 
33 	argv0 = argv;
34 	openlog("routed", LOG_PID, 0);
35 	sp = getservbyname("router", "udp");
36 	if (sp == NULL) {
37 		fprintf(stderr, "routed: router/udp: unknown service\n");
38 		exit(1);
39 	}
40 	addr.sin_family = AF_INET;
41 	addr.sin_port = sp->s_port;
42 	s = getsocket(AF_INET, SOCK_DGRAM, &addr);
43 	if (s < 0)
44 		exit(1);
45 	argv++, argc--;
46 	while (argc > 0 && **argv == '-') {
47 		if (strcmp(*argv, "-s") == 0) {
48 			supplier = 1;
49 			argv++, argc--;
50 			continue;
51 		}
52 		if (strcmp(*argv, "-q") == 0) {
53 			supplier = 0;
54 			argv++, argc--;
55 			continue;
56 		}
57 		if (strcmp(*argv, "-t") == 0) {
58 			tracepackets++;
59 			argv++, argc--;
60 			continue;
61 		}
62 		if (strcmp(*argv, "-g") == 0) {
63 			gateway = 1;
64 			argv++, argc--;
65 			continue;
66 		}
67 		if (strcmp(*argv, "-l") == 0) {
68 			gateway = -1;
69 			argv++, argc--;
70 			continue;
71 		}
72 		fprintf(stderr,
73 			"usage: routed [ -s ] [ -q ] [ -t ] [ -g ] [ -l ]\n");
74 		exit(1);
75 	}
76 #ifndef DEBUG
77 	if (!tracepackets) {
78 		int t;
79 
80 		if (fork())
81 			exit(0);
82 		for (t = 0; t < 20; t++)
83 			if (t != s)
84 				(void) close(cc);
85 		(void) open("/", 0);
86 		(void) dup2(0, 1);
87 		(void) dup2(0, 2);
88 		t = open("/dev/tty", 2);
89 		if (t >= 0) {
90 			ioctl(t, TIOCNOTTY, (char *)0);
91 			(void) close(t);
92 		}
93 	}
94 #endif
95 	/*
96 	 * Any extra argument is considered
97 	 * a tracing log file.
98 	 */
99 	if (argc > 0)
100 		traceon(*argv);
101 	/*
102 	 * Collect an initial view of the world by
103 	 * snooping in the kernel and the gateway kludge
104 	 * file.  Then, send a request packet on all
105 	 * directly connected networks to find out what
106 	 * everyone else thinks.
107 	 */
108 	rtinit();
109 	gwkludge();
110 	ifinit();
111 	if (supplier < 0)
112 		supplier = 0;
113 	msg->rip_cmd = RIPCMD_REQUEST;
114 	msg->rip_vers = RIPVERSION;
115 	msg->rip_nets[0].rip_dst.sa_family = AF_UNSPEC;
116 	msg->rip_nets[0].rip_metric = HOPCNT_INFINITY;
117 	msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC);
118 	msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY);
119 	toall(sendmsg);
120 	signal(SIGALRM, timer);
121 	signal(SIGHUP, hup);
122 	signal(SIGTERM, hup);
123 	timer();
124 
125 	for (;;) {
126 		int ibits;
127 		register int n;
128 
129 		ibits = 1 << s;
130 		n = select(20, &ibits, 0, 0, 0);
131 		if (n < 0)
132 			continue;
133 		if (ibits & (1 << s))
134 			process(s);
135 		/* handle ICMP redirects */
136 	}
137 }
138 
139 process(fd)
140 	int fd;
141 {
142 	struct sockaddr from;
143 	int fromlen = sizeof (from), cc, omask;
144 
145 	cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen);
146 	if (cc <= 0) {
147 		if (cc < 0 && errno != EINTR)
148 			perror("recvfrom");
149 		return;
150 	}
151 	if (fromlen != sizeof (struct sockaddr_in))
152 		return;
153 #define	mask(s)	(1<<((s)-1))
154 	omask = sigblock(mask(SIGALRM));
155 	rip_input(&from, cc);
156 	sigsetmask(omask);
157 }
158 
159 getsocket(domain, type, sin)
160 	int domain, type;
161 	struct sockaddr_in *sin;
162 {
163 	int retry, s, on = 1;
164 
165 	retry = 1;
166 	while ((s = socket(domain, type, 0, 0)) < 0 && retry) {
167 		perror("socket");
168 		sleep(5 * retry);
169 		retry <<= 1;
170 	}
171 	if (retry == 0) {
172 		syslog(LOG_ERR, "socket: %m");
173 		return (-1);
174 	}
175 	if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) {
176 		syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
177 		exit(1);
178 	}
179 	while (bind(s, sin, sizeof (*sin), 0) < 0 && retry) {
180 		perror("bind");
181 		sleep(5 * retry);
182 		retry <<= 1;
183 	}
184 	if (retry == 0) {
185 		syslog(LOG_ERR, "bind: %m");
186 		return (-1);
187 	}
188 	return (s);
189 }
190