19017Ssam #ifndef lint 2*13036Ssam static char sccsid[] = "@(#)main.c 4.7 (Berkeley) 06/12/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); 7610637Ssam for (t = 0; t < 20; t++) 7710637Ssam if (t != s) 7810637Ssam #ifdef COMPAT 7912726Ssam if (t != snoroute) 8010637Ssam #endif 8110637Ssam (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; 11112726Ssam msg->rip_vers = RIPVERSION; 1129017Ssam msg->rip_nets[0].rip_dst.sa_family = AF_UNSPEC; 1139017Ssam msg->rip_nets[0].rip_metric = HOPCNT_INFINITY; 11412726Ssam msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC); 11512726Ssam msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY); 1169017Ssam toall(sendmsg); 117*13036Ssam signal(SIGALRM, timer); 1189017Ssam timer(); 1199017Ssam 1209017Ssam for (;;) { 1219017Ssam int ibits; 1229017Ssam register int n; 1239017Ssam 12410245Ssam ibits = 1 << s; 12510245Ssam #ifdef COMPAT 12610245Ssam ibits |= 1 << snoroute; 12710245Ssam #endif 12810245Ssam n = select(20, &ibits, 0, 0, 0); 1299017Ssam if (n < 0) 1309017Ssam continue; 1319017Ssam if (ibits & (1 << s)) 1329017Ssam process(s); 13310245Ssam #ifdef COMPAT 1349017Ssam if (ibits & (1 << snoroute)) 1359017Ssam process(snoroute); 13610245Ssam #endif 13710245Ssam /* handle ICMP redirects */ 1389017Ssam } 1399017Ssam } 1409017Ssam 1419017Ssam process(fd) 1429017Ssam int fd; 1439017Ssam { 1449017Ssam struct sockaddr from; 145*13036Ssam int fromlen = sizeof (from), cc, omask; 1469017Ssam 14710245Ssam cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen); 1489017Ssam if (cc <= 0) { 1499017Ssam if (cc < 0 && errno != EINTR) 15010245Ssam perror("recvfrom"); 1519017Ssam return; 1529017Ssam } 15310245Ssam if (fromlen != sizeof (struct sockaddr_in)) 15410245Ssam return; 155*13036Ssam #define mask(s) (1<<((s)-1)) 156*13036Ssam omask = sigblock(mask(SIGALRM)); 1579017Ssam rip_input(&from, cc); 158*13036Ssam sigsetmask(omask); 1599017Ssam } 16010245Ssam 16110245Ssam getsocket(domain, type, sin) 16210245Ssam int domain, type; 16310245Ssam struct sockaddr_in *sin; 16410245Ssam { 16510245Ssam int retry, s; 16610245Ssam 16710245Ssam retry = 1; 16810245Ssam while ((s = socket(domain, type, 0, 0)) < 0 && retry) { 16910245Ssam perror("socket"); 17010245Ssam sleep(5 * retry); 17110245Ssam retry <<= 1; 17210245Ssam } 17310245Ssam if (retry == 0) 17410245Ssam return (-1); 17510245Ssam while (bind(s, sin, sizeof (*sin), 0) < 0 && retry) { 17610245Ssam perror("bind"); 17710245Ssam sleep(5 * retry); 17810245Ssam retry <<= 1; 17910245Ssam } 18010245Ssam if (retry == 0) 18110245Ssam return (-1); 18210245Ssam return (s); 18310245Ssam } 184