19017Ssam #ifndef lint 2*17570Skarels static char sccsid[] = "@(#)main.c 4.11 (Berkeley) 12/20/84"; 39017Ssam #endif 49017Ssam 59017Ssam /* 69017Ssam * Routing Table Management Daemon 79017Ssam */ 810245Ssam #include "defs.h" 99017Ssam #include <sys/ioctl.h> 1013602Ssam #include <sys/time.h> 1113602Ssam 129017Ssam #include <net/if.h> 1313602Ssam 149017Ssam #include <errno.h> 159017Ssam #include <nlist.h> 169017Ssam #include <signal.h> 17*17570Skarels #include <syslog.h> 189017Ssam 199017Ssam int supplier = -1; /* process should supply updates */ 2016326Skarels extern int gateway; 219017Ssam 229017Ssam struct rip *msg = (struct rip *)packet; 2316314Skarels int hup(); 249017Ssam 259017Ssam main(argc, argv) 269017Ssam int argc; 279017Ssam char *argv[]; 289017Ssam { 299017Ssam int cc; 309017Ssam struct sockaddr from; 3110245Ssam u_char retry; 3210245Ssam #ifdef COMPAT 3310245Ssam int snoroute; 3410245Ssam #endif 359017Ssam 369017Ssam argv0 = argv; 37*17570Skarels openlog("routed", LOG_PID, 0); 389017Ssam sp = getservbyname("router", "udp"); 3910245Ssam if (sp == NULL) { 4010245Ssam fprintf(stderr, "routed: router/udp: unknown service\n"); 419017Ssam exit(1); 429017Ssam } 4310245Ssam addr.sin_family = AF_INET; 4410245Ssam addr.sin_port = sp->s_port; 4510245Ssam s = getsocket(AF_INET, SOCK_DGRAM, &addr); 4610245Ssam if (s < 0) 4710245Ssam exit(1); 4810245Ssam #ifdef COMPAT 4910245Ssam bzero(&addr, sizeof (addr)); 5010245Ssam addr.sin_family = AF_INET; 5110245Ssam addr.sin_port = htons(ntohs(sp->s_port) + 1); 5210245Ssam snoroute = getsocket(AF_INET, SOCK_DGRAM, &addr); 5310245Ssam if (snoroute < 0) 5410245Ssam exit(1); 5510245Ssam #endif 569017Ssam argv++, argc--; 579017Ssam while (argc > 0 && **argv == '-') { 5810636Ssam if (strcmp(*argv, "-s") == 0) { 599017Ssam supplier = 1; 609017Ssam argv++, argc--; 619017Ssam continue; 629017Ssam } 6310636Ssam if (strcmp(*argv, "-q") == 0) { 649017Ssam supplier = 0; 659017Ssam argv++, argc--; 669017Ssam continue; 679017Ssam } 6810636Ssam if (strcmp(*argv, "-t") == 0) { 6910636Ssam tracepackets++; 7010636Ssam argv++, argc--; 7110636Ssam continue; 7210636Ssam } 7316326Skarels if (strcmp(*argv, "-g") == 0) { 7416326Skarels gateway = 1; 7516326Skarels argv++, argc--; 7616326Skarels continue; 7716326Skarels } 7816326Skarels if (strcmp(*argv, "-l") == 0) { 7916326Skarels gateway = -1; 8016326Skarels argv++, argc--; 8116326Skarels continue; 8216326Skarels } 8316326Skarels fprintf(stderr, 8416326Skarels "usage: routed [ -s ] [ -q ] [ -t ] [ -g ] [ -l ]\n"); 859017Ssam exit(1); 869017Ssam } 8710636Ssam #ifndef DEBUG 8810636Ssam if (!tracepackets) { 8910636Ssam int t; 9010636Ssam 9110636Ssam if (fork()) 9210636Ssam exit(0); 9310637Ssam for (t = 0; t < 20; t++) 9410637Ssam if (t != s) 9510637Ssam #ifdef COMPAT 9612726Ssam if (t != snoroute) 9710637Ssam #endif 9810637Ssam (void) close(cc); 9910636Ssam (void) open("/", 0); 10010636Ssam (void) dup2(0, 1); 10110636Ssam (void) dup2(0, 2); 10210636Ssam t = open("/dev/tty", 2); 10310636Ssam if (t >= 0) { 10410636Ssam ioctl(t, TIOCNOTTY, (char *)0); 10510636Ssam (void) close(t); 10610636Ssam } 10710636Ssam } 10810636Ssam #endif 1099017Ssam /* 11010245Ssam * Any extra argument is considered 11110245Ssam * a tracing log file. 11210245Ssam */ 11310245Ssam if (argc > 0) 11410245Ssam traceon(*argv); 11510245Ssam /* 1169017Ssam * Collect an initial view of the world by 1179017Ssam * snooping in the kernel and the gateway kludge 1189017Ssam * file. Then, send a request packet on all 1199017Ssam * directly connected networks to find out what 1209017Ssam * everyone else thinks. 1219017Ssam */ 1229017Ssam rtinit(); 1239017Ssam gwkludge(); 1249017Ssam ifinit(); 1259017Ssam if (supplier < 0) 1269017Ssam supplier = 0; 1279017Ssam msg->rip_cmd = RIPCMD_REQUEST; 12812726Ssam msg->rip_vers = RIPVERSION; 1299017Ssam msg->rip_nets[0].rip_dst.sa_family = AF_UNSPEC; 1309017Ssam msg->rip_nets[0].rip_metric = HOPCNT_INFINITY; 13112726Ssam msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC); 13212726Ssam msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY); 1339017Ssam toall(sendmsg); 13413036Ssam signal(SIGALRM, timer); 13516314Skarels signal(SIGHUP, hup); 136*17570Skarels signal(SIGTERM, hup); 1379017Ssam timer(); 1389017Ssam 1399017Ssam for (;;) { 1409017Ssam int ibits; 1419017Ssam register int n; 1429017Ssam 14310245Ssam ibits = 1 << s; 14410245Ssam #ifdef COMPAT 14510245Ssam ibits |= 1 << snoroute; 14610245Ssam #endif 14710245Ssam n = select(20, &ibits, 0, 0, 0); 1489017Ssam if (n < 0) 1499017Ssam continue; 1509017Ssam if (ibits & (1 << s)) 1519017Ssam process(s); 15210245Ssam #ifdef COMPAT 1539017Ssam if (ibits & (1 << snoroute)) 1549017Ssam process(snoroute); 15510245Ssam #endif 15610245Ssam /* handle ICMP redirects */ 1579017Ssam } 1589017Ssam } 1599017Ssam 1609017Ssam process(fd) 1619017Ssam int fd; 1629017Ssam { 1639017Ssam struct sockaddr from; 16413036Ssam int fromlen = sizeof (from), cc, omask; 1659017Ssam 16610245Ssam cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen); 1679017Ssam if (cc <= 0) { 1689017Ssam if (cc < 0 && errno != EINTR) 16910245Ssam perror("recvfrom"); 1709017Ssam return; 1719017Ssam } 17210245Ssam if (fromlen != sizeof (struct sockaddr_in)) 17310245Ssam return; 17413036Ssam #define mask(s) (1<<((s)-1)) 17513036Ssam omask = sigblock(mask(SIGALRM)); 1769017Ssam rip_input(&from, cc); 17713036Ssam sigsetmask(omask); 1789017Ssam } 17910245Ssam 18010245Ssam getsocket(domain, type, sin) 18110245Ssam int domain, type; 18210245Ssam struct sockaddr_in *sin; 18310245Ssam { 184*17570Skarels int retry, s, on = 1; 18510245Ssam 18610245Ssam retry = 1; 18710245Ssam while ((s = socket(domain, type, 0, 0)) < 0 && retry) { 18810245Ssam perror("socket"); 18910245Ssam sleep(5 * retry); 19010245Ssam retry <<= 1; 19110245Ssam } 192*17570Skarels if (retry == 0) { 193*17570Skarels syslog(LOG_ERR, "socket: %m"); 19410245Ssam return (-1); 195*17570Skarels } 196*17570Skarels if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) { 197*17570Skarels syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m"); 198*17570Skarels exit(1); 199*17570Skarels } 20010245Ssam while (bind(s, sin, sizeof (*sin), 0) < 0 && retry) { 20110245Ssam perror("bind"); 20210245Ssam sleep(5 * retry); 20310245Ssam retry <<= 1; 20410245Ssam } 205*17570Skarels if (retry == 0) { 206*17570Skarels syslog(LOG_ERR, "bind: %m"); 20710245Ssam return (-1); 208*17570Skarels } 20910245Ssam return (s); 21010245Ssam } 211