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