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