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