121996Sdist /* 234566Skarels * Copyright (c) 1983, 1988 Regents of the University of California. 333489Sbostic * All rights reserved. 433489Sbostic * 533489Sbostic * Redistribution and use in source and binary forms are permitted 634771Sbostic * provided that the above copyright notice and this paragraph are 734771Sbostic * duplicated in all such forms and that any documentation, 834771Sbostic * advertising materials, and other materials related to such 934771Sbostic * distribution and use acknowledge that the software was developed 1034771Sbostic * by the University of California, Berkeley. The name of the 1134771Sbostic * University may not be used to endorse or promote products derived 1234771Sbostic * from this software without specific prior written permission. 1334771Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434771Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534771Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621996Sdist */ 1721996Sdist 189017Ssam #ifndef lint 1921996Sdist char copyright[] = 2034566Skarels "@(#) Copyright (c) 1983, 1988 Regents of the University of California.\n\ 2121996Sdist All rights reserved.\n"; 2233489Sbostic #endif /* not lint */ 239017Ssam 2421996Sdist #ifndef lint 25*36831Skarels static char sccsid[] = "@(#)main.c 5.16 (Berkeley) 02/18/89"; 2633489Sbostic #endif /* not lint */ 2721996Sdist 289017Ssam /* 299017Ssam * Routing Table Management Daemon 309017Ssam */ 3110245Ssam #include "defs.h" 329017Ssam #include <sys/ioctl.h> 33*36831Skarels #include <sys/file.h> 3413602Ssam 359017Ssam #include <net/if.h> 3613602Ssam 3734566Skarels #include <sys/errno.h> 3834566Skarels #include <sys/signal.h> 3934566Skarels #include <sys/syslog.h> 409017Ssam 419017Ssam int supplier = -1; /* process should supply updates */ 4221847Skarels int gateway = 0; /* 1 if we are a gateway to parts beyond */ 4331220Skarels int debug = 0; 44*36831Skarels int bufspace = 127*1024; /* max. input buffer size to request */ 459017Ssam 469017Ssam struct rip *msg = (struct rip *)packet; 4734566Skarels int hup(), rtdeleteall(), sigtrace(); 489017Ssam 499017Ssam main(argc, argv) 509017Ssam int argc; 519017Ssam char *argv[]; 529017Ssam { 53*36831Skarels int n, cc, nfd, omask, tflags = 0; 549017Ssam struct sockaddr from; 55*36831Skarels struct timeval *tvp, waittime; 56*36831Skarels struct itimerval itval; 57*36831Skarels fd_set ibits; 5810245Ssam u_char retry; 599017Ssam 609017Ssam argv0 = argv; 6134845Skarels #if BSD >= 43 6224848Seric openlog("routed", LOG_PID | LOG_ODELAY, LOG_DAEMON); 6330930Skarels setlogmask(LOG_UPTO(LOG_WARNING)); 6434845Skarels #else 6534845Skarels openlog("routed", LOG_PID); 6634845Skarels #define LOG_UPTO(x) (x) 6734845Skarels #define setlogmask(x) (x) 6834845Skarels #endif 699017Ssam sp = getservbyname("router", "udp"); 7010245Ssam if (sp == NULL) { 7110245Ssam fprintf(stderr, "routed: router/udp: unknown service\n"); 729017Ssam exit(1); 739017Ssam } 7410245Ssam addr.sin_family = AF_INET; 7510245Ssam addr.sin_port = sp->s_port; 7610245Ssam s = getsocket(AF_INET, SOCK_DGRAM, &addr); 7710245Ssam if (s < 0) 7810245Ssam exit(1); 799017Ssam argv++, argc--; 809017Ssam while (argc > 0 && **argv == '-') { 8110636Ssam if (strcmp(*argv, "-s") == 0) { 829017Ssam supplier = 1; 839017Ssam argv++, argc--; 849017Ssam continue; 859017Ssam } 8610636Ssam if (strcmp(*argv, "-q") == 0) { 879017Ssam supplier = 0; 889017Ssam argv++, argc--; 899017Ssam continue; 909017Ssam } 9110636Ssam if (strcmp(*argv, "-t") == 0) { 92*36831Skarels tflags++; 9330930Skarels setlogmask(LOG_UPTO(LOG_DEBUG)); 9410636Ssam argv++, argc--; 9510636Ssam continue; 9610636Ssam } 9726341Skarels if (strcmp(*argv, "-d") == 0) { 9831220Skarels debug++; 9930930Skarels setlogmask(LOG_UPTO(LOG_DEBUG)); 10026341Skarels argv++, argc--; 10126341Skarels continue; 10226341Skarels } 10316326Skarels if (strcmp(*argv, "-g") == 0) { 10416326Skarels gateway = 1; 10516326Skarels argv++, argc--; 10616326Skarels continue; 10716326Skarels } 10816326Skarels fprintf(stderr, 10921847Skarels "usage: routed [ -s ] [ -q ] [ -t ] [ -g ]\n"); 1109017Ssam exit(1); 1119017Ssam } 112*36831Skarels 113*36831Skarels if (debug == 0) { 11410636Ssam int t; 11510636Ssam 11610636Ssam if (fork()) 11710636Ssam exit(0); 11810637Ssam for (t = 0; t < 20; t++) 11910637Ssam if (t != s) 12024761Ssklower (void) close(t); 12110636Ssam (void) open("/", 0); 12210636Ssam (void) dup2(0, 1); 12310636Ssam (void) dup2(0, 2); 12410636Ssam t = open("/dev/tty", 2); 12510636Ssam if (t >= 0) { 12610636Ssam ioctl(t, TIOCNOTTY, (char *)0); 12710636Ssam (void) close(t); 12810636Ssam } 12910636Ssam } 1309017Ssam /* 13110245Ssam * Any extra argument is considered 13210245Ssam * a tracing log file. 13310245Ssam */ 13410245Ssam if (argc > 0) 13510245Ssam traceon(*argv); 136*36831Skarels while (tflags-- > 0) 137*36831Skarels bumploglevel(); 138*36831Skarels 139*36831Skarels (void) gettimeofday(&now, (struct timezone *)NULL); 14010245Ssam /* 1419017Ssam * Collect an initial view of the world by 14221847Skarels * checking the interface configuration and the gateway kludge 1439017Ssam * file. Then, send a request packet on all 1449017Ssam * directly connected networks to find out what 1459017Ssam * everyone else thinks. 1469017Ssam */ 1479017Ssam rtinit(); 14830927Skarels ifinit(); 1499017Ssam gwkludge(); 15021847Skarels if (gateway > 0) 15121847Skarels rtdefault(); 1529017Ssam if (supplier < 0) 1539017Ssam supplier = 0; 1549017Ssam msg->rip_cmd = RIPCMD_REQUEST; 15512726Ssam msg->rip_vers = RIPVERSION; 156*36831Skarels if (sizeof(msg->rip_nets[0].rip_dst.sa_family) > 1) /* XXX */ 157*36831Skarels msg->rip_nets[0].rip_dst.sa_family = htons((u_short)AF_UNSPEC); 158*36831Skarels else 159*36831Skarels msg->rip_nets[0].rip_dst.sa_family = AF_UNSPEC; 160*36831Skarels msg->rip_nets[0].rip_metric = htonl((u_long)HOPCNT_INFINITY); 1619017Ssam toall(sendmsg); 16213036Ssam signal(SIGALRM, timer); 16316314Skarels signal(SIGHUP, hup); 16417570Skarels signal(SIGTERM, hup); 16531220Skarels signal(SIGINT, rtdeleteall); 16634566Skarels signal(SIGUSR1, sigtrace); 16734566Skarels signal(SIGUSR2, sigtrace); 168*36831Skarels itval.it_interval.tv_sec = TIMER_RATE; 169*36831Skarels itval.it_value.tv_sec = TIMER_RATE; 170*36831Skarels itval.it_interval.tv_usec = 0; 171*36831Skarels itval.it_value.tv_usec = 0; 172*36831Skarels srandom(getpid()); 173*36831Skarels if (setitimer(ITIMER_REAL, &itval, (struct itimerval *)NULL) < 0) 174*36831Skarels syslog(LOG_ERR, "setitimer: %m\n"); 1759017Ssam 176*36831Skarels FD_ZERO(&ibits); 177*36831Skarels nfd = s + 1; /* 1 + max(fd's) */ 1789017Ssam for (;;) { 179*36831Skarels FD_SET(s, &ibits); 180*36831Skarels /* 181*36831Skarels * If we need a dynamic update that was held off, 182*36831Skarels * needupdate will be set, and nextbcast is the time 183*36831Skarels * by which we want select to return. Compute time 184*36831Skarels * until dynamic update should be sent, and select only 185*36831Skarels * until then. If we have already passed nextbcast, 186*36831Skarels * just poll. 187*36831Skarels */ 188*36831Skarels if (needupdate) { 189*36831Skarels waittime = nextbcast; 190*36831Skarels timevalsub(&waittime, &now); 191*36831Skarels if (waittime.tv_sec < 0) { 192*36831Skarels waittime.tv_sec = 0; 193*36831Skarels waittime.tv_usec = 0; 194*36831Skarels } 195*36831Skarels if (traceactions) 196*36831Skarels fprintf(ftrace, 197*36831Skarels "select until dynamic update %d/%d sec/usec\n", 198*36831Skarels waittime.tv_sec, waittime.tv_usec); 199*36831Skarels tvp = &waittime; 200*36831Skarels } else 201*36831Skarels tvp = (struct timeval *)NULL; 202*36831Skarels n = select(nfd, &ibits, 0, 0, tvp); 203*36831Skarels if (n <= 0) { 204*36831Skarels /* 205*36831Skarels * Need delayed dynamic update if select returned 206*36831Skarels * nothing and we timed out. Otherwise, ignore 207*36831Skarels * errors (e.g. EINTR). 208*36831Skarels */ 209*36831Skarels if (n < 0) { 210*36831Skarels if (errno == EINTR) 211*36831Skarels continue; 212*36831Skarels syslog(LOG_ERR, "select: %m"); 213*36831Skarels } 214*36831Skarels omask = sigblock(sigmask(SIGALRM)); 215*36831Skarels if (n == 0 && needupdate) { 216*36831Skarels if (traceactions) 217*36831Skarels fprintf(ftrace, 218*36831Skarels "send delayed dynamic update\n"); 219*36831Skarels (void) gettimeofday(&now, 220*36831Skarels (struct timezone *)NULL); 221*36831Skarels toall(supply, RTS_CHANGED, 222*36831Skarels (struct interface *)NULL); 223*36831Skarels lastbcast = now; 224*36831Skarels needupdate = 0; 225*36831Skarels nextbcast.tv_sec = 0; 226*36831Skarels } 227*36831Skarels sigsetmask(omask); 2289017Ssam continue; 229*36831Skarels } 230*36831Skarels (void) gettimeofday(&now, (struct timezone *)NULL); 231*36831Skarels #ifdef doesntwork 232*36831Skarels /* 233*36831Skarels printf("s %d, ibits %x index %d, mod %d, sh %x, or %x &ibits %x\n", 234*36831Skarels s, 235*36831Skarels ibits.fds_bits[0], 236*36831Skarels (s)/(sizeof(fd_mask) * 8), 237*36831Skarels ((s) % (sizeof(fd_mask) * 8)), 238*36831Skarels (1 << ((s) % (sizeof(fd_mask) * 8))), 239*36831Skarels ibits.fds_bits[(s)/(sizeof(fd_mask) * 8)] & (1 << ((s) % (sizeof(fd_mask) * 8))), 240*36831Skarels &ibits 241*36831Skarels ); 242*36831Skarels */ 243*36831Skarels if (FD_ISSET(s, &ibits)) 244*36831Skarels #else 245*36831Skarels if (ibits.fds_bits[s/32] & (1 << s)) 246*36831Skarels #endif 2479017Ssam process(s); 24810245Ssam /* handle ICMP redirects */ 2499017Ssam } 2509017Ssam } 2519017Ssam 252*36831Skarels timevaladd(t1, t2) 253*36831Skarels struct timeval *t1, *t2; 254*36831Skarels { 255*36831Skarels 256*36831Skarels t1->tv_sec += t2->tv_sec; 257*36831Skarels if ((t1->tv_usec += t2->tv_usec) > 1000000) { 258*36831Skarels t1->tv_sec++; 259*36831Skarels t1->tv_usec -= 1000000; 260*36831Skarels } 261*36831Skarels } 262*36831Skarels 263*36831Skarels timevalsub(t1, t2) 264*36831Skarels struct timeval *t1, *t2; 265*36831Skarels { 266*36831Skarels 267*36831Skarels t1->tv_sec -= t2->tv_sec; 268*36831Skarels if ((t1->tv_usec -= t2->tv_usec) < 0) { 269*36831Skarels t1->tv_sec--; 270*36831Skarels t1->tv_usec += 1000000; 271*36831Skarels } 272*36831Skarels } 273*36831Skarels 2749017Ssam process(fd) 2759017Ssam int fd; 2769017Ssam { 2779017Ssam struct sockaddr from; 278*36831Skarels int fromlen, cc, omask; 2799017Ssam 280*36831Skarels for (;;) { 281*36831Skarels fromlen = sizeof (from); 282*36831Skarels cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen); 283*36831Skarels if (cc <= 0) { 284*36831Skarels if (cc < 0 && errno != EWOULDBLOCK) 285*36831Skarels perror("recvfrom"); 286*36831Skarels break; 287*36831Skarels } 288*36831Skarels if (fromlen != sizeof (struct sockaddr_in)) 289*36831Skarels break; 290*36831Skarels omask = sigblock(sigmask(SIGALRM)); 291*36831Skarels rip_input(&from, cc); 292*36831Skarels sigsetmask(omask); 2939017Ssam } 2949017Ssam } 29510245Ssam 29610245Ssam getsocket(domain, type, sin) 29710245Ssam int domain, type; 29810245Ssam struct sockaddr_in *sin; 29910245Ssam { 300*36831Skarels int sock, on = 1; 30110245Ssam 302*36831Skarels if ((sock = socket(domain, type, 0)) < 0) { 30310245Ssam perror("socket"); 30417570Skarels syslog(LOG_ERR, "socket: %m"); 30510245Ssam return (-1); 30617570Skarels } 30734845Skarels #ifdef SO_BROADCAST 308*36831Skarels if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) { 30917570Skarels syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m"); 310*36831Skarels close(sock); 31125516Skarels return (-1); 31217570Skarels } 31334845Skarels #endif 31434845Skarels #ifdef SO_RCVBUF 315*36831Skarels for (on = bufspace; ; on -= 1024) { 316*36831Skarels if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, 317*36831Skarels &on, sizeof (on)) == 0) 318*36831Skarels break; 319*36831Skarels if (on <= 8*1024) { 320*36831Skarels syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m"); 321*36831Skarels break; 322*36831Skarels } 323*36831Skarels } 324*36831Skarels if (traceactions) 325*36831Skarels fprintf(ftrace, "recv buf %d\n", on); 32634845Skarels #endif 327*36831Skarels if (bind(sock, sin, sizeof (*sin), 0) < 0) { 32810245Ssam perror("bind"); 32917570Skarels syslog(LOG_ERR, "bind: %m"); 330*36831Skarels close(sock); 33110245Ssam return (-1); 33217570Skarels } 333*36831Skarels if (fcntl(sock, F_SETFL, FNDELAY) == -1) 334*36831Skarels syslog(LOG_ERR, "fcntl FNDELAY: %m\n"); 335*36831Skarels return (sock); 33610245Ssam } 337