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