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