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