main.c revision 1.1.1.2 1 /*
2 * Copyright (c) 1983, 1988, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #ifndef lint
35 static char copyright[] =
36 "@(#) Copyright (c) 1983, 1988, 1993\n\
37 The Regents of the University of California. All rights reserved.\n";
38 #endif /* not lint */
39
40 #ifndef lint
41 static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/5/93";
42 #endif /* not lint */
43
44 /*
45 * Routing Table Management Daemon
46 */
47 #include "defs.h"
48 #include <sys/ioctl.h>
49 #include <sys/file.h>
50
51 #include <net/if.h>
52
53 #include <sys/errno.h>
54 #include <sys/signal.h>
55 #include <sys/syslog.h>
56 #include "pathnames.h"
57
58 int supplier = -1; /* process should supply updates */
59 int gateway = 0; /* 1 if we are a gateway to parts beyond */
60 int debug = 0;
61 int bufspace = 127*1024; /* max. input buffer size to request */
62
63 struct rip *msg = (struct rip *)packet;
64 void hup(), rtdeleteall(), sigtrace(), timer();
65
66 main(argc, argv)
67 int argc;
68 char *argv[];
69 {
70 int n, cc, nfd, omask, tflags = 0;
71 struct sockaddr from;
72 struct timeval *tvp, waittime;
73 struct itimerval itval;
74 register struct rip *query = msg;
75 fd_set ibits;
76 u_char retry;
77
78 argv0 = argv;
79 #if BSD >= 43
80 openlog("routed", LOG_PID | LOG_ODELAY, LOG_DAEMON);
81 setlogmask(LOG_UPTO(LOG_WARNING));
82 #else
83 openlog("routed", LOG_PID);
84 #define LOG_UPTO(x) (x)
85 #define setlogmask(x) (x)
86 #endif
87 sp = getservbyname("router", "udp");
88 if (sp == NULL) {
89 fprintf(stderr, "routed: router/udp: unknown service\n");
90 exit(1);
91 }
92 addr.sin_family = AF_INET;
93 addr.sin_port = sp->s_port;
94 r = socket(AF_ROUTE, SOCK_RAW, 0);
95 /* later, get smart about lookingforinterfaces */
96 if (r)
97 shutdown(r, 0); /* for now, don't want reponses */
98 else {
99 fprintf(stderr, "routed: no routing socket\n");
100 exit(1);
101 }
102 s = getsocket(AF_INET, SOCK_DGRAM, &addr);
103 if (s < 0)
104 exit(1);
105 argv++, argc--;
106 while (argc > 0 && **argv == '-') {
107 if (strcmp(*argv, "-s") == 0) {
108 supplier = 1;
109 argv++, argc--;
110 continue;
111 }
112 if (strcmp(*argv, "-q") == 0) {
113 supplier = 0;
114 argv++, argc--;
115 continue;
116 }
117 if (strcmp(*argv, "-t") == 0) {
118 tflags++;
119 setlogmask(LOG_UPTO(LOG_DEBUG));
120 argv++, argc--;
121 continue;
122 }
123 if (strcmp(*argv, "-d") == 0) {
124 debug++;
125 setlogmask(LOG_UPTO(LOG_DEBUG));
126 argv++, argc--;
127 continue;
128 }
129 if (strcmp(*argv, "-g") == 0) {
130 gateway = 1;
131 argv++, argc--;
132 continue;
133 }
134 fprintf(stderr,
135 "usage: routed [ -s ] [ -q ] [ -t ] [ -g ]\n");
136 exit(1);
137 }
138
139 if (debug == 0 && tflags == 0)
140 daemon(0, 0);
141 /*
142 * Any extra argument is considered
143 * a tracing log file.
144 */
145 if (argc > 0)
146 traceon(*argv);
147 while (tflags-- > 0)
148 bumploglevel();
149
150 (void) gettimeofday(&now, (struct timezone *)NULL);
151 /*
152 * Collect an initial view of the world by
153 * checking the interface configuration and the gateway kludge
154 * file. Then, send a request packet on all
155 * directly connected networks to find out what
156 * everyone else thinks.
157 */
158 rtinit();
159 ifinit();
160 gwkludge();
161 if (gateway > 0)
162 rtdefault();
163 if (supplier < 0)
164 supplier = 0;
165 query->rip_cmd = RIPCMD_REQUEST;
166 query->rip_vers = RIPVERSION;
167 if (sizeof(query->rip_nets[0].rip_dst.sa_family) > 1) /* XXX */
168 query->rip_nets[0].rip_dst.sa_family = htons((u_short)AF_UNSPEC);
169 else
170 query->rip_nets[0].rip_dst.sa_family = AF_UNSPEC;
171 query->rip_nets[0].rip_metric = htonl((u_long)HOPCNT_INFINITY);
172 toall(sndmsg);
173 signal(SIGALRM, timer);
174 signal(SIGHUP, hup);
175 signal(SIGTERM, hup);
176 signal(SIGINT, rtdeleteall);
177 signal(SIGUSR1, sigtrace);
178 signal(SIGUSR2, sigtrace);
179 itval.it_interval.tv_sec = TIMER_RATE;
180 itval.it_value.tv_sec = TIMER_RATE;
181 itval.it_interval.tv_usec = 0;
182 itval.it_value.tv_usec = 0;
183 srandom(getpid());
184 if (setitimer(ITIMER_REAL, &itval, (struct itimerval *)NULL) < 0)
185 syslog(LOG_ERR, "setitimer: %m\n");
186
187 FD_ZERO(&ibits);
188 nfd = s + 1; /* 1 + max(fd's) */
189 for (;;) {
190 FD_SET(s, &ibits);
191 /*
192 * If we need a dynamic update that was held off,
193 * needupdate will be set, and nextbcast is the time
194 * by which we want select to return. Compute time
195 * until dynamic update should be sent, and select only
196 * until then. If we have already passed nextbcast,
197 * just poll.
198 */
199 if (needupdate) {
200 waittime = nextbcast;
201 timevalsub(&waittime, &now);
202 if (waittime.tv_sec < 0) {
203 waittime.tv_sec = 0;
204 waittime.tv_usec = 0;
205 }
206 if (traceactions)
207 fprintf(ftrace,
208 "select until dynamic update %d/%d sec/usec\n",
209 waittime.tv_sec, waittime.tv_usec);
210 tvp = &waittime;
211 } else
212 tvp = (struct timeval *)NULL;
213 n = select(nfd, &ibits, 0, 0, tvp);
214 if (n <= 0) {
215 /*
216 * Need delayed dynamic update if select returned
217 * nothing and we timed out. Otherwise, ignore
218 * errors (e.g. EINTR).
219 */
220 if (n < 0) {
221 if (errno == EINTR)
222 continue;
223 syslog(LOG_ERR, "select: %m");
224 }
225 omask = sigblock(sigmask(SIGALRM));
226 if (n == 0 && needupdate) {
227 if (traceactions)
228 fprintf(ftrace,
229 "send delayed dynamic update\n");
230 (void) gettimeofday(&now,
231 (struct timezone *)NULL);
232 toall(supply, RTS_CHANGED,
233 (struct interface *)NULL);
234 lastbcast = now;
235 needupdate = 0;
236 nextbcast.tv_sec = 0;
237 }
238 sigsetmask(omask);
239 continue;
240 }
241 (void) gettimeofday(&now, (struct timezone *)NULL);
242 omask = sigblock(sigmask(SIGALRM));
243 #ifdef doesntwork
244 /*
245 printf("s %d, ibits %x index %d, mod %d, sh %x, or %x &ibits %x\n",
246 s,
247 ibits.fds_bits[0],
248 (s)/(sizeof(fd_mask) * 8),
249 ((s) % (sizeof(fd_mask) * 8)),
250 (1 << ((s) % (sizeof(fd_mask) * 8))),
251 ibits.fds_bits[(s)/(sizeof(fd_mask) * 8)] & (1 << ((s) % (sizeof(fd_mask) * 8))),
252 &ibits
253 );
254 */
255 if (FD_ISSET(s, &ibits))
256 #else
257 if (ibits.fds_bits[s/32] & (1 << s))
258 #endif
259 process(s);
260 /* handle ICMP redirects */
261 sigsetmask(omask);
262 }
263 }
264
265 timevaladd(t1, t2)
266 struct timeval *t1, *t2;
267 {
268
269 t1->tv_sec += t2->tv_sec;
270 if ((t1->tv_usec += t2->tv_usec) > 1000000) {
271 t1->tv_sec++;
272 t1->tv_usec -= 1000000;
273 }
274 }
275
276 timevalsub(t1, t2)
277 struct timeval *t1, *t2;
278 {
279
280 t1->tv_sec -= t2->tv_sec;
281 if ((t1->tv_usec -= t2->tv_usec) < 0) {
282 t1->tv_sec--;
283 t1->tv_usec += 1000000;
284 }
285 }
286
287 process(fd)
288 int fd;
289 {
290 struct sockaddr from;
291 int fromlen, cc;
292 union {
293 char buf[MAXPACKETSIZE+1];
294 struct rip rip;
295 } inbuf;
296
297 for (;;) {
298 fromlen = sizeof (from);
299 cc = recvfrom(fd, &inbuf, sizeof (inbuf), 0, &from, &fromlen);
300 if (cc <= 0) {
301 if (cc < 0 && errno != EWOULDBLOCK)
302 perror("recvfrom");
303 break;
304 }
305 if (fromlen != sizeof (struct sockaddr_in))
306 break;
307 rip_input(&from, &inbuf.rip, cc);
308 }
309 }
310
311 getsocket(domain, type, sin)
312 int domain, type;
313 struct sockaddr_in *sin;
314 {
315 int sock, on = 1;
316
317 if ((sock = socket(domain, type, 0)) < 0) {
318 perror("socket");
319 syslog(LOG_ERR, "socket: %m");
320 return (-1);
321 }
322 #ifdef SO_BROADCAST
323 if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) {
324 syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
325 close(sock);
326 return (-1);
327 }
328 #endif
329 #ifdef SO_RCVBUF
330 for (on = bufspace; ; on -= 1024) {
331 if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
332 &on, sizeof (on)) == 0)
333 break;
334 if (on <= 8*1024) {
335 syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m");
336 break;
337 }
338 }
339 if (traceactions)
340 fprintf(ftrace, "recv buf %d\n", on);
341 #endif
342 if (bind(sock, (struct sockaddr *)sin, sizeof (*sin)) < 0) {
343 perror("bind");
344 syslog(LOG_ERR, "bind: %m");
345 close(sock);
346 return (-1);
347 }
348 if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
349 syslog(LOG_ERR, "fcntl O_NONBLOCK: %m\n");
350 return (sock);
351 }
352