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