private flags collided with multicast and link flags
[unix-history] / usr / src / sbin / routed / main.c
CommitLineData
5ff67f98 1/*
71d47350 2 * Copyright (c) 1983, 1988 Regents of the University of California.
0eb85d71
KB
3 * All rights reserved.
4 *
d60d530a 5 * %sccs.include.redist.c%
5ff67f98
DF
6 */
7
8#ifndef lint
9char copyright[] =
71d47350 10"@(#) Copyright (c) 1983, 1988 Regents of the University of California.\n\
5ff67f98 11 All rights reserved.\n";
0eb85d71 12#endif /* not lint */
5ff67f98 13
fdd0ed12 14#ifndef lint
ad76aa05 15static char sccsid[] = "@(#)main.c 5.24 (Berkeley) %G%";
0eb85d71 16#endif /* not lint */
fdd0ed12
SL
17
18/*
19 * Routing Table Management Daemon
20 */
7fe7fe74 21#include "defs.h"
fdd0ed12 22#include <sys/ioctl.h>
4033c8f6 23#include <sys/file.h>
e2feeea9 24
fdd0ed12 25#include <net/if.h>
e2feeea9 26
71d47350
MK
27#include <sys/errno.h>
28#include <sys/signal.h>
29#include <sys/syslog.h>
7abf8d65 30#include "pathnames.h"
fdd0ed12
SL
31
32int supplier = -1; /* process should supply updates */
d002aa8c 33int gateway = 0; /* 1 if we are a gateway to parts beyond */
7892134c 34int debug = 0;
4033c8f6 35int bufspace = 127*1024; /* max. input buffer size to request */
fdd0ed12
SL
36
37struct rip *msg = (struct rip *)packet;
49dac2b7 38void hup(), rtdeleteall(), sigtrace(), timer();
fdd0ed12
SL
39
40main(argc, argv)
41 int argc;
42 char *argv[];
43{
4033c8f6 44 int n, cc, nfd, omask, tflags = 0;
fdd0ed12 45 struct sockaddr from;
4033c8f6
MK
46 struct timeval *tvp, waittime;
47 struct itimerval itval;
314ebe0b 48 register struct rip *query = msg;
4033c8f6 49 fd_set ibits;
7fe7fe74 50 u_char retry;
fdd0ed12
SL
51
52 argv0 = argv;
265a3175 53#if BSD >= 43
a349306d 54 openlog("routed", LOG_PID | LOG_ODELAY, LOG_DAEMON);
bb3e151c 55 setlogmask(LOG_WARNING);
fdd0ed12 56 sp = getservbyname("router", "udp");
7fe7fe74
SL
57 if (sp == NULL) {
58 fprintf(stderr, "routed: router/udp: unknown service\n");
fdd0ed12
SL
59 exit(1);
60 }
7fe7fe74
SL
61 addr.sin_family = AF_INET;
62 addr.sin_port = sp->s_port;
ad76aa05
KS
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 }
7fe7fe74
SL
71 s = getsocket(AF_INET, SOCK_DGRAM, &addr);
72 if (s < 0)
73 exit(1);
fdd0ed12
SL
74 argv++, argc--;
75 while (argc > 0 && **argv == '-') {
d4b6a849 76 if (strcmp(*argv, "-s") == 0) {
fdd0ed12
SL
77 supplier = 1;
78 argv++, argc--;
79 continue;
80 }
d4b6a849 81 if (strcmp(*argv, "-q") == 0) {
fdd0ed12
SL
82 supplier = 0;
83 argv++, argc--;
84 continue;
85 }
d4b6a849 86 if (strcmp(*argv, "-t") == 0) {
4033c8f6 87 tflags++;
bb3e151c 88 setlogmask(LOG_DEBUG);
17fe297f
MK
89 argv++, argc--;
90 continue;
91 }
92 if (strcmp(*argv, "-d") == 0) {
7892134c 93 debug++;
bb3e151c 94 setlogmask(LOG_DEBUG);
d4b6a849
SL
95 argv++, argc--;
96 continue;
97 }
5562f0a3
MK
98 if (strcmp(*argv, "-g") == 0) {
99 gateway = 1;
100 argv++, argc--;
101 continue;
102 }
5562f0a3 103 fprintf(stderr,
d002aa8c 104 "usage: routed [ -s ] [ -q ] [ -t ] [ -g ]\n");
fdd0ed12
SL
105 exit(1);
106 }
4033c8f6 107
43d42ac6
MK
108 if (debug == 0)
109 daemon(0, 0);
7fe7fe74
SL
110 /*
111 * Any extra argument is considered
112 * a tracing log file.
113 */
114 if (argc > 0)
115 traceon(*argv);
4033c8f6
MK
116 while (tflags-- > 0)
117 bumploglevel();
118
119 (void) gettimeofday(&now, (struct timezone *)NULL);
fdd0ed12
SL
120 /*
121 * Collect an initial view of the world by
d002aa8c 122 * checking the interface configuration and the gateway kludge
fdd0ed12
SL
123 * file. Then, send a request packet on all
124 * directly connected networks to find out what
125 * everyone else thinks.
126 */
127 rtinit();
fdd0ed12 128 ifinit();
34894a1d 129 gwkludge();
d002aa8c
MK
130 if (gateway > 0)
131 rtdefault();
fdd0ed12
SL
132 if (supplier < 0)
133 supplier = 0;
314ebe0b
MK
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);
4033c8f6 138 else
314ebe0b
MK
139 query->rip_nets[0].rip_dst.sa_family = AF_UNSPEC;
140 query->rip_nets[0].rip_metric = htonl((u_long)HOPCNT_INFINITY);
49dac2b7 141 toall(sndmsg);
ce5e9df4 142 signal(SIGALRM, timer);
b7e4f8be 143 signal(SIGHUP, hup);
69b7ef61 144 signal(SIGTERM, hup);
7892134c 145 signal(SIGINT, rtdeleteall);
71d47350
MK
146 signal(SIGUSR1, sigtrace);
147 signal(SIGUSR2, sigtrace);
4033c8f6
MK
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");
fdd0ed12 155
4033c8f6
MK
156 FD_ZERO(&ibits);
157 nfd = s + 1; /* 1 + max(fd's) */
fdd0ed12 158 for (;;) {
4033c8f6
MK
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);
fdd0ed12 208 continue;
4033c8f6
MK
209 }
210 (void) gettimeofday(&now, (struct timezone *)NULL);
787d3210 211 omask = sigblock(sigmask(SIGALRM));
4033c8f6
MK
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
fdd0ed12 228 process(s);
7fe7fe74 229 /* handle ICMP redirects */
787d3210 230 sigsetmask(omask);
fdd0ed12
SL
231 }
232}
233
4033c8f6
MK
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
fdd0ed12
SL
256process(fd)
257 int fd;
258{
fdd0ed12 259 struct sockaddr from;
787d3210
MK
260 int fromlen, cc;
261 union {
262 char buf[MAXPACKETSIZE+1];
263 struct rip rip;
264 } inbuf;
4033c8f6
MK
265
266 for (;;) {
267 fromlen = sizeof (from);
787d3210 268 cc = recvfrom(fd, &inbuf, sizeof (inbuf), 0, &from, &fromlen);
4033c8f6
MK
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;
787d3210 276 rip_input(&from, &inbuf.rip, cc);
71d47350 277 }
fdd0ed12 278}
7fe7fe74
SL
279
280getsocket(domain, type, sin)
281 int domain, type;
282 struct sockaddr_in *sin;
283{
4033c8f6 284 int sock, on = 1;
7fe7fe74 285
4033c8f6 286 if ((sock = socket(domain, type, 0)) < 0) {
7fe7fe74 287 perror("socket");
69b7ef61 288 syslog(LOG_ERR, "socket: %m");
7fe7fe74 289 return (-1);
69b7ef61 290 }
265a3175 291#ifdef SO_BROADCAST
4033c8f6 292 if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) {
69b7ef61 293 syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
4033c8f6 294 close(sock);
3d42e160 295 return (-1);
69b7ef61 296 }
265a3175
MK
297#endif
298#ifdef SO_RCVBUF
4033c8f6
MK
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);
265a3175 310#endif
49dac2b7 311 if (bind(sock, (struct sockaddr *)sin, sizeof (*sin)) < 0) {
7fe7fe74 312 perror("bind");
69b7ef61 313 syslog(LOG_ERR, "bind: %m");
4033c8f6 314 close(sock);
7fe7fe74 315 return (-1);
69b7ef61 316 }
ca7465a6
KB
317 if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
318 syslog(LOG_ERR, "fcntl O_NONBLOCK: %m\n");
4033c8f6 319 return (sock);
7fe7fe74 320}