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