]> git.saurik.com Git - apple/network_cmds.git/blob - routed.tproj/main.c
network_cmds-176.2.1.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
67 #include <net/if.h>
68
69 #include <sys/errno.h>
70 #include <sys/signal.h>
71 #include <sys/syslog.h>
72 #include "pathnames.h"
73
74 int supplier = -1; /* process should supply updates */
75 int gateway = 0; /* 1 if we are a gateway to parts beyond */
76 int debug = 0;
77 int bufspace = 127*1024; /* max. input buffer size to request */
78
79 struct rip *msg = (struct rip *)packet;
80 void hup(), rtdeleteall(), sigtrace(), timer();
81
82 main(argc, argv)
83 int argc;
84 char *argv[];
85 {
86 int n, cc, nfd, omask, tflags = 0;
87 struct sockaddr from;
88 struct timeval *tvp, waittime;
89 struct itimerval itval;
90 register struct rip *query = msg;
91 fd_set ibits;
92 u_char retry;
93
94 argv0 = argv;
95 #if BSD >= 43
96 openlog("routed", LOG_PID | LOG_ODELAY, LOG_DAEMON);
97 setlogmask(LOG_UPTO(LOG_WARNING));
98 #else
99 openlog("routed", LOG_PID);
100 #define LOG_UPTO(x) (x)
101 #define setlogmask(x) (x)
102 #endif
103 sp = getservbyname("router", "udp");
104 if (sp == NULL) {
105 fprintf(stderr, "routed: router/udp: unknown service\n");
106 exit(1);
107 }
108 addr.sin_family = AF_INET;
109 addr.sin_port = sp->s_port;
110 r = socket(AF_ROUTE, SOCK_RAW, 0);
111 /* later, get smart about lookingforinterfaces */
112 if (r)
113 shutdown(r, 0); /* for now, don't want reponses */
114 else {
115 fprintf(stderr, "routed: no routing socket\n");
116 exit(1);
117 }
118 s = getsocket(AF_INET, SOCK_DGRAM, &addr);
119 if (s < 0)
120 exit(1);
121 argv++, argc--;
122 while (argc > 0 && **argv == '-') {
123 if (strcmp(*argv, "-s") == 0) {
124 supplier = 1;
125 argv++, argc--;
126 continue;
127 }
128 if (strcmp(*argv, "-q") == 0) {
129 supplier = 0;
130 argv++, argc--;
131 continue;
132 }
133 if (strcmp(*argv, "-t") == 0) {
134 tflags++;
135 setlogmask(LOG_UPTO(LOG_DEBUG));
136 argv++, argc--;
137 continue;
138 }
139 if (strcmp(*argv, "-d") == 0) {
140 debug++;
141 setlogmask(LOG_UPTO(LOG_DEBUG));
142 argv++, argc--;
143 continue;
144 }
145 if (strcmp(*argv, "-g") == 0) {
146 gateway = 1;
147 argv++, argc--;
148 continue;
149 }
150 fprintf(stderr,
151 "usage: routed [ -s ] [ -q ] [ -t ] [ -g ]\n");
152 exit(1);
153 }
154
155 if (debug == 0 && tflags == 0)
156 daemon(0, 0);
157 /*
158 * Any extra argument is considered
159 * a tracing log file.
160 */
161 if (argc > 0)
162 traceon(*argv);
163 while (tflags-- > 0)
164 bumploglevel();
165
166 (void) gettimeofday(&now, (struct timezone *)NULL);
167 /*
168 * Collect an initial view of the world by
169 * checking the interface configuration and the gateway kludge
170 * file. Then, send a request packet on all
171 * directly connected networks to find out what
172 * everyone else thinks.
173 */
174 rtinit();
175 ifinit();
176 gwkludge();
177 if (gateway > 0)
178 rtdefault();
179 if (supplier < 0)
180 supplier = 0;
181 query->rip_cmd = RIPCMD_REQUEST;
182 query->rip_vers = RIPVERSION;
183 if (sizeof(query->rip_nets[0].rip_dst.sa_family) > 1) /* XXX */
184 query->rip_nets[0].rip_dst.sa_family = htons((u_short)AF_UNSPEC);
185 else
186 query->rip_nets[0].rip_dst.sa_family = AF_UNSPEC;
187 query->rip_nets[0].rip_metric = htonl((u_long)HOPCNT_INFINITY);
188 toall(sndmsg);
189 signal(SIGALRM, timer);
190 signal(SIGHUP, hup);
191 signal(SIGTERM, hup);
192 signal(SIGINT, rtdeleteall);
193 signal(SIGUSR1, sigtrace);
194 signal(SIGUSR2, sigtrace);
195 itval.it_interval.tv_sec = TIMER_RATE;
196 itval.it_value.tv_sec = TIMER_RATE;
197 itval.it_interval.tv_usec = 0;
198 itval.it_value.tv_usec = 0;
199 srandom(getpid());
200 if (setitimer(ITIMER_REAL, &itval, (struct itimerval *)NULL) < 0)
201 syslog(LOG_ERR, "setitimer: %m\n");
202
203 FD_ZERO(&ibits);
204 nfd = s + 1; /* 1 + max(fd's) */
205 for (;;) {
206 FD_SET(s, &ibits);
207 /*
208 * If we need a dynamic update that was held off,
209 * needupdate will be set, and nextbcast is the time
210 * by which we want select to return. Compute time
211 * until dynamic update should be sent, and select only
212 * until then. If we have already passed nextbcast,
213 * just poll.
214 */
215 if (needupdate) {
216 waittime = nextbcast;
217 timevalsub(&waittime, &now);
218 if (waittime.tv_sec < 0) {
219 waittime.tv_sec = 0;
220 waittime.tv_usec = 0;
221 }
222 if (traceactions)
223 fprintf(ftrace,
224 "select until dynamic update %d/%d sec/usec\n",
225 waittime.tv_sec, waittime.tv_usec);
226 tvp = &waittime;
227 } else
228 tvp = (struct timeval *)NULL;
229 n = select(nfd, &ibits, 0, 0, tvp);
230 if (n <= 0) {
231 /*
232 * Need delayed dynamic update if select returned
233 * nothing and we timed out. Otherwise, ignore
234 * errors (e.g. EINTR).
235 */
236 if (n < 0) {
237 if (errno == EINTR)
238 continue;
239 syslog(LOG_ERR, "select: %m");
240 }
241 omask = sigblock(sigmask(SIGALRM));
242 if (n == 0 && needupdate) {
243 if (traceactions)
244 fprintf(ftrace,
245 "send delayed dynamic update\n");
246 (void) gettimeofday(&now,
247 (struct timezone *)NULL);
248 toall(supply, RTS_CHANGED,
249 (struct interface *)NULL);
250 lastbcast = now;
251 needupdate = 0;
252 nextbcast.tv_sec = 0;
253 }
254 sigsetmask(omask);
255 continue;
256 }
257 (void) gettimeofday(&now, (struct timezone *)NULL);
258 omask = sigblock(sigmask(SIGALRM));
259 #ifdef doesntwork
260 /*
261 printf("s %d, ibits %x index %d, mod %d, sh %x, or %x &ibits %x\n",
262 s,
263 ibits.fds_bits[0],
264 (s)/(sizeof(fd_mask) * 8),
265 ((s) % (sizeof(fd_mask) * 8)),
266 (1 << ((s) % (sizeof(fd_mask) * 8))),
267 ibits.fds_bits[(s)/(sizeof(fd_mask) * 8)] & (1 << ((s) % (sizeof(fd_mask) * 8))),
268 &ibits
269 );
270 */
271 if (FD_ISSET(s, &ibits))
272 #else
273 if (ibits.fds_bits[s/32] & (1 << s))
274 #endif
275 process(s);
276 /* handle ICMP redirects */
277 sigsetmask(omask);
278 }
279 }
280
281 timevaladd(t1, t2)
282 struct timeval *t1, *t2;
283 {
284
285 t1->tv_sec += t2->tv_sec;
286 if ((t1->tv_usec += t2->tv_usec) > 1000000) {
287 t1->tv_sec++;
288 t1->tv_usec -= 1000000;
289 }
290 }
291
292 timevalsub(t1, t2)
293 struct timeval *t1, *t2;
294 {
295
296 t1->tv_sec -= t2->tv_sec;
297 if ((t1->tv_usec -= t2->tv_usec) < 0) {
298 t1->tv_sec--;
299 t1->tv_usec += 1000000;
300 }
301 }
302
303 process(fd)
304 int fd;
305 {
306 struct sockaddr from;
307 int fromlen, cc;
308 union {
309 char buf[MAXPACKETSIZE+1];
310 struct rip rip;
311 } inbuf;
312
313 for (;;) {
314 fromlen = sizeof (from);
315 cc = recvfrom(fd, &inbuf, sizeof (inbuf), 0, &from, &fromlen);
316 if (cc <= 0) {
317 if (cc < 0 && errno != EWOULDBLOCK)
318 perror("recvfrom");
319 break;
320 }
321 if (fromlen != sizeof (struct sockaddr_in))
322 break;
323 rip_input(&from, &inbuf.rip, cc);
324 }
325 }
326
327 getsocket(domain, type, sin)
328 int domain, type;
329 struct sockaddr_in *sin;
330 {
331 int sock, on = 1;
332
333 if ((sock = socket(domain, type, 0)) < 0) {
334 perror("socket");
335 syslog(LOG_ERR, "socket: %m");
336 return (-1);
337 }
338 #ifdef SO_BROADCAST
339 if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) {
340 syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
341 close(sock);
342 return (-1);
343 }
344 #endif
345 #ifdef SO_RCVBUF
346 for (on = bufspace; ; on -= 1024) {
347 if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
348 &on, sizeof (on)) == 0)
349 break;
350 if (on <= 8*1024) {
351 syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m");
352 break;
353 }
354 }
355 if (traceactions)
356 fprintf(ftrace, "recv buf %d\n", on);
357 #endif
358 if (bind(sock, (struct sockaddr *)sin, sizeof (*sin)) < 0) {
359 perror("bind");
360 syslog(LOG_ERR, "bind: %m");
361 close(sock);
362 return (-1);
363 }
364 if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
365 syslog(LOG_ERR, "fcntl O_NONBLOCK: %m\n");
366 return (sock);
367 }