19017Ssam #ifndef lint 2*16314Skarels static char sccsid[] = "@(#)main.c 4.9 (Berkeley) 04/09/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> 179017Ssam 189017Ssam int supplier = -1; /* process should supply updates */ 199017Ssam 209017Ssam struct rip *msg = (struct rip *)packet; 21*16314Skarels int hup(); 229017Ssam 239017Ssam main(argc, argv) 249017Ssam int argc; 259017Ssam char *argv[]; 269017Ssam { 279017Ssam int cc; 289017Ssam struct sockaddr from; 2910245Ssam u_char retry; 3010245Ssam #ifdef COMPAT 3110245Ssam int snoroute; 3210245Ssam #endif 339017Ssam 349017Ssam argv0 = argv; 359017Ssam sp = getservbyname("router", "udp"); 3610245Ssam if (sp == NULL) { 3710245Ssam fprintf(stderr, "routed: router/udp: unknown service\n"); 389017Ssam exit(1); 399017Ssam } 4010245Ssam addr.sin_family = AF_INET; 4110245Ssam addr.sin_port = sp->s_port; 4210245Ssam s = getsocket(AF_INET, SOCK_DGRAM, &addr); 4310245Ssam if (s < 0) 4410245Ssam exit(1); 4510245Ssam #ifdef COMPAT 4610245Ssam bzero(&addr, sizeof (addr)); 4710245Ssam addr.sin_family = AF_INET; 4810245Ssam addr.sin_port = htons(ntohs(sp->s_port) + 1); 4910245Ssam snoroute = getsocket(AF_INET, SOCK_DGRAM, &addr); 5010245Ssam if (snoroute < 0) 5110245Ssam exit(1); 5210245Ssam #endif 539017Ssam argv++, argc--; 549017Ssam while (argc > 0 && **argv == '-') { 5510636Ssam if (strcmp(*argv, "-s") == 0) { 569017Ssam supplier = 1; 579017Ssam argv++, argc--; 589017Ssam continue; 599017Ssam } 6010636Ssam if (strcmp(*argv, "-q") == 0) { 619017Ssam supplier = 0; 629017Ssam argv++, argc--; 639017Ssam continue; 649017Ssam } 6510636Ssam if (strcmp(*argv, "-t") == 0) { 6610636Ssam tracepackets++; 6710636Ssam argv++, argc--; 6810636Ssam continue; 6910636Ssam } 7010636Ssam fprintf(stderr, "usage: routed [ -s ] [ -q ] [ -t ]\n"); 719017Ssam exit(1); 729017Ssam } 7310636Ssam #ifndef DEBUG 7410636Ssam if (!tracepackets) { 7510636Ssam int t; 7610636Ssam 7710636Ssam if (fork()) 7810636Ssam exit(0); 7910637Ssam for (t = 0; t < 20; t++) 8010637Ssam if (t != s) 8110637Ssam #ifdef COMPAT 8212726Ssam if (t != snoroute) 8310637Ssam #endif 8410637Ssam (void) close(cc); 8510636Ssam (void) open("/", 0); 8610636Ssam (void) dup2(0, 1); 8710636Ssam (void) dup2(0, 2); 8810636Ssam t = open("/dev/tty", 2); 8910636Ssam if (t >= 0) { 9010636Ssam ioctl(t, TIOCNOTTY, (char *)0); 9110636Ssam (void) close(t); 9210636Ssam } 9310636Ssam } 9410636Ssam #endif 959017Ssam /* 9610245Ssam * Any extra argument is considered 9710245Ssam * a tracing log file. 9810245Ssam */ 9910245Ssam if (argc > 0) 10010245Ssam traceon(*argv); 10110245Ssam /* 1029017Ssam * Collect an initial view of the world by 1039017Ssam * snooping in the kernel and the gateway kludge 1049017Ssam * file. Then, send a request packet on all 1059017Ssam * directly connected networks to find out what 1069017Ssam * everyone else thinks. 1079017Ssam */ 1089017Ssam rtinit(); 1099017Ssam gwkludge(); 1109017Ssam ifinit(); 1119017Ssam if (supplier < 0) 1129017Ssam supplier = 0; 1139017Ssam msg->rip_cmd = RIPCMD_REQUEST; 11412726Ssam msg->rip_vers = RIPVERSION; 1159017Ssam msg->rip_nets[0].rip_dst.sa_family = AF_UNSPEC; 1169017Ssam msg->rip_nets[0].rip_metric = HOPCNT_INFINITY; 11712726Ssam msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC); 11812726Ssam msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY); 1199017Ssam toall(sendmsg); 12013036Ssam signal(SIGALRM, timer); 121*16314Skarels signal(SIGHUP, hup); 1229017Ssam timer(); 1239017Ssam 1249017Ssam for (;;) { 1259017Ssam int ibits; 1269017Ssam register int n; 1279017Ssam 12810245Ssam ibits = 1 << s; 12910245Ssam #ifdef COMPAT 13010245Ssam ibits |= 1 << snoroute; 13110245Ssam #endif 13210245Ssam n = select(20, &ibits, 0, 0, 0); 1339017Ssam if (n < 0) 1349017Ssam continue; 1359017Ssam if (ibits & (1 << s)) 1369017Ssam process(s); 13710245Ssam #ifdef COMPAT 1389017Ssam if (ibits & (1 << snoroute)) 1399017Ssam process(snoroute); 14010245Ssam #endif 14110245Ssam /* handle ICMP redirects */ 1429017Ssam } 1439017Ssam } 1449017Ssam 1459017Ssam process(fd) 1469017Ssam int fd; 1479017Ssam { 1489017Ssam struct sockaddr from; 14913036Ssam int fromlen = sizeof (from), cc, omask; 1509017Ssam 15110245Ssam cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen); 1529017Ssam if (cc <= 0) { 1539017Ssam if (cc < 0 && errno != EINTR) 15410245Ssam perror("recvfrom"); 1559017Ssam return; 1569017Ssam } 15710245Ssam if (fromlen != sizeof (struct sockaddr_in)) 15810245Ssam return; 15913036Ssam #define mask(s) (1<<((s)-1)) 16013036Ssam omask = sigblock(mask(SIGALRM)); 1619017Ssam rip_input(&from, cc); 16213036Ssam sigsetmask(omask); 1639017Ssam } 16410245Ssam 16510245Ssam getsocket(domain, type, sin) 16610245Ssam int domain, type; 16710245Ssam struct sockaddr_in *sin; 16810245Ssam { 16910245Ssam int retry, s; 17010245Ssam 17110245Ssam retry = 1; 17210245Ssam while ((s = socket(domain, type, 0, 0)) < 0 && retry) { 17310245Ssam perror("socket"); 17410245Ssam sleep(5 * retry); 17510245Ssam retry <<= 1; 17610245Ssam } 17710245Ssam if (retry == 0) 17810245Ssam return (-1); 17910245Ssam while (bind(s, sin, sizeof (*sin), 0) < 0 && retry) { 18010245Ssam perror("bind"); 18110245Ssam sleep(5 * retry); 18210245Ssam retry <<= 1; 18310245Ssam } 18410245Ssam if (retry == 0) 18510245Ssam return (-1); 18610245Ssam return (s); 18710245Ssam } 188