19017Ssam #ifndef lint 2*10637Ssam static char sccsid[] = "@(#)main.c 4.4 01/31/83"; 39017Ssam #endif 49017Ssam 59017Ssam /* 69017Ssam * Routing Table Management Daemon 79017Ssam */ 810245Ssam #include "defs.h" 99017Ssam #include <sys/ioctl.h> 109017Ssam #include <net/if.h> 119017Ssam #include <errno.h> 129017Ssam #include <nlist.h> 139017Ssam #include <signal.h> 149017Ssam #include <time.h> 159017Ssam 169017Ssam int supplier = -1; /* process should supply updates */ 179017Ssam 189017Ssam struct rip *msg = (struct rip *)packet; 199017Ssam 209017Ssam main(argc, argv) 219017Ssam int argc; 229017Ssam char *argv[]; 239017Ssam { 249017Ssam int cc; 259017Ssam struct sockaddr from; 2610245Ssam u_char retry; 2710245Ssam #ifdef COMPAT 2810245Ssam int snoroute; 2910245Ssam #endif 309017Ssam 319017Ssam argv0 = argv; 329017Ssam sp = getservbyname("router", "udp"); 3310245Ssam if (sp == NULL) { 3410245Ssam fprintf(stderr, "routed: router/udp: unknown service\n"); 359017Ssam exit(1); 369017Ssam } 3710245Ssam addr.sin_family = AF_INET; 3810245Ssam addr.sin_port = sp->s_port; 3910245Ssam s = getsocket(AF_INET, SOCK_DGRAM, &addr); 4010245Ssam if (s < 0) 4110245Ssam exit(1); 4210245Ssam #ifdef COMPAT 4310245Ssam bzero(&addr, sizeof (addr)); 4410245Ssam addr.sin_family = AF_INET; 4510245Ssam addr.sin_port = htons(ntohs(sp->s_port) + 1); 4610245Ssam snoroute = getsocket(AF_INET, SOCK_DGRAM, &addr); 4710245Ssam if (snoroute < 0) 4810245Ssam exit(1); 4910245Ssam #endif 509017Ssam argv++, argc--; 519017Ssam while (argc > 0 && **argv == '-') { 5210636Ssam if (strcmp(*argv, "-s") == 0) { 539017Ssam supplier = 1; 549017Ssam argv++, argc--; 559017Ssam continue; 569017Ssam } 5710636Ssam if (strcmp(*argv, "-q") == 0) { 589017Ssam supplier = 0; 599017Ssam argv++, argc--; 609017Ssam continue; 619017Ssam } 6210636Ssam if (strcmp(*argv, "-t") == 0) { 6310636Ssam tracepackets++; 6410636Ssam argv++, argc--; 6510636Ssam continue; 6610636Ssam } 6710636Ssam fprintf(stderr, "usage: routed [ -s ] [ -q ] [ -t ]\n"); 689017Ssam exit(1); 699017Ssam } 7010636Ssam #ifndef DEBUG 7110636Ssam if (!tracepackets) { 7210636Ssam int t; 7310636Ssam 7410636Ssam if (fork()) 7510636Ssam exit(0); 76*10637Ssam for (t = 0; t < 20; t++) 77*10637Ssam if (t != s) 78*10637Ssam #ifdef COMPAT 79*10637Ssam if (t != snoroute) 80*10637Ssam #endif 81*10637Ssam (void) close(cc); 8210636Ssam (void) open("/", 0); 8310636Ssam (void) dup2(0, 1); 8410636Ssam (void) dup2(0, 2); 8510636Ssam t = open("/dev/tty", 2); 8610636Ssam if (t >= 0) { 8710636Ssam ioctl(t, TIOCNOTTY, (char *)0); 8810636Ssam (void) close(t); 8910636Ssam } 9010636Ssam } 9110636Ssam #endif 929017Ssam /* 9310245Ssam * Any extra argument is considered 9410245Ssam * a tracing log file. 9510245Ssam */ 9610245Ssam if (argc > 0) 9710245Ssam traceon(*argv); 9810245Ssam /* 999017Ssam * Collect an initial view of the world by 1009017Ssam * snooping in the kernel and the gateway kludge 1019017Ssam * file. Then, send a request packet on all 1029017Ssam * directly connected networks to find out what 1039017Ssam * everyone else thinks. 1049017Ssam */ 1059017Ssam rtinit(); 1069017Ssam gwkludge(); 1079017Ssam ifinit(); 1089017Ssam if (supplier < 0) 1099017Ssam supplier = 0; 1109017Ssam msg->rip_cmd = RIPCMD_REQUEST; 1119017Ssam msg->rip_nets[0].rip_dst.sa_family = AF_UNSPEC; 1129017Ssam msg->rip_nets[0].rip_metric = HOPCNT_INFINITY; 1139017Ssam toall(sendmsg); 1149017Ssam sigset(SIGALRM, timer); 1159017Ssam timer(); 1169017Ssam 1179017Ssam for (;;) { 1189017Ssam int ibits; 1199017Ssam register int n; 1209017Ssam 12110245Ssam ibits = 1 << s; 12210245Ssam #ifdef COMPAT 12310245Ssam ibits |= 1 << snoroute; 12410245Ssam #endif 12510245Ssam n = select(20, &ibits, 0, 0, 0); 1269017Ssam if (n < 0) 1279017Ssam continue; 1289017Ssam if (ibits & (1 << s)) 1299017Ssam process(s); 13010245Ssam #ifdef COMPAT 1319017Ssam if (ibits & (1 << snoroute)) 1329017Ssam process(snoroute); 13310245Ssam #endif 13410245Ssam /* handle ICMP redirects */ 1359017Ssam } 1369017Ssam } 1379017Ssam 1389017Ssam process(fd) 1399017Ssam int fd; 1409017Ssam { 1419017Ssam struct sockaddr from; 14210245Ssam int fromlen = sizeof (from), cc; 1439017Ssam 14410245Ssam cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen); 1459017Ssam if (cc <= 0) { 1469017Ssam if (cc < 0 && errno != EINTR) 14710245Ssam perror("recvfrom"); 1489017Ssam return; 1499017Ssam } 15010245Ssam if (fromlen != sizeof (struct sockaddr_in)) 15110245Ssam return; 1529017Ssam sighold(SIGALRM); 1539017Ssam rip_input(&from, cc); 1549017Ssam sigrelse(SIGALRM); 1559017Ssam } 15610245Ssam 15710245Ssam getsocket(domain, type, sin) 15810245Ssam int domain, type; 15910245Ssam struct sockaddr_in *sin; 16010245Ssam { 16110245Ssam int retry, s; 16210245Ssam 16310245Ssam retry = 1; 16410245Ssam while ((s = socket(domain, type, 0, 0)) < 0 && retry) { 16510245Ssam perror("socket"); 16610245Ssam sleep(5 * retry); 16710245Ssam retry <<= 1; 16810245Ssam } 16910245Ssam if (retry == 0) 17010245Ssam return (-1); 17110245Ssam while (bind(s, sin, sizeof (*sin), 0) < 0 && retry) { 17210245Ssam perror("bind"); 17310245Ssam sleep(5 * retry); 17410245Ssam retry <<= 1; 17510245Ssam } 17610245Ssam if (retry == 0) 17710245Ssam return (-1); 17810245Ssam return (s); 17910245Ssam } 180