19017Ssam #ifndef lint 2*10636Ssam static char sccsid[] = "@(#)main.c 4.3 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 == '-') { 52*10636Ssam if (strcmp(*argv, "-s") == 0) { 539017Ssam supplier = 1; 549017Ssam argv++, argc--; 559017Ssam continue; 569017Ssam } 57*10636Ssam if (strcmp(*argv, "-q") == 0) { 589017Ssam supplier = 0; 599017Ssam argv++, argc--; 609017Ssam continue; 619017Ssam } 62*10636Ssam if (strcmp(*argv, "-t") == 0) { 63*10636Ssam tracepackets++; 64*10636Ssam argv++, argc--; 65*10636Ssam continue; 66*10636Ssam } 67*10636Ssam fprintf(stderr, "usage: routed [ -s ] [ -q ] [ -t ]\n"); 689017Ssam exit(1); 699017Ssam } 70*10636Ssam #ifndef DEBUG 71*10636Ssam if (!tracepackets) { 72*10636Ssam int t; 73*10636Ssam 74*10636Ssam if (fork()) 75*10636Ssam exit(0); 76*10636Ssam for (cc = 0; cc < 10; cc++) 77*10636Ssam (void) close(cc); 78*10636Ssam (void) open("/", 0); 79*10636Ssam (void) dup2(0, 1); 80*10636Ssam (void) dup2(0, 2); 81*10636Ssam t = open("/dev/tty", 2); 82*10636Ssam if (t >= 0) { 83*10636Ssam ioctl(t, TIOCNOTTY, (char *)0); 84*10636Ssam (void) close(t); 85*10636Ssam } 86*10636Ssam } 87*10636Ssam #endif 889017Ssam /* 8910245Ssam * Any extra argument is considered 9010245Ssam * a tracing log file. 9110245Ssam */ 9210245Ssam if (argc > 0) 9310245Ssam traceon(*argv); 9410245Ssam /* 959017Ssam * Collect an initial view of the world by 969017Ssam * snooping in the kernel and the gateway kludge 979017Ssam * file. Then, send a request packet on all 989017Ssam * directly connected networks to find out what 999017Ssam * everyone else thinks. 1009017Ssam */ 1019017Ssam rtinit(); 1029017Ssam gwkludge(); 1039017Ssam ifinit(); 1049017Ssam if (supplier < 0) 1059017Ssam supplier = 0; 1069017Ssam msg->rip_cmd = RIPCMD_REQUEST; 1079017Ssam msg->rip_nets[0].rip_dst.sa_family = AF_UNSPEC; 1089017Ssam msg->rip_nets[0].rip_metric = HOPCNT_INFINITY; 1099017Ssam toall(sendmsg); 1109017Ssam sigset(SIGALRM, timer); 1119017Ssam timer(); 1129017Ssam 1139017Ssam for (;;) { 1149017Ssam int ibits; 1159017Ssam register int n; 1169017Ssam 11710245Ssam ibits = 1 << s; 11810245Ssam #ifdef COMPAT 11910245Ssam ibits |= 1 << snoroute; 12010245Ssam #endif 12110245Ssam n = select(20, &ibits, 0, 0, 0); 1229017Ssam if (n < 0) 1239017Ssam continue; 1249017Ssam if (ibits & (1 << s)) 1259017Ssam process(s); 12610245Ssam #ifdef COMPAT 1279017Ssam if (ibits & (1 << snoroute)) 1289017Ssam process(snoroute); 12910245Ssam #endif 13010245Ssam /* handle ICMP redirects */ 1319017Ssam } 1329017Ssam } 1339017Ssam 1349017Ssam process(fd) 1359017Ssam int fd; 1369017Ssam { 1379017Ssam struct sockaddr from; 13810245Ssam int fromlen = sizeof (from), cc; 1399017Ssam 14010245Ssam cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen); 1419017Ssam if (cc <= 0) { 1429017Ssam if (cc < 0 && errno != EINTR) 14310245Ssam perror("recvfrom"); 1449017Ssam return; 1459017Ssam } 14610245Ssam if (fromlen != sizeof (struct sockaddr_in)) 14710245Ssam return; 1489017Ssam sighold(SIGALRM); 1499017Ssam rip_input(&from, cc); 1509017Ssam sigrelse(SIGALRM); 1519017Ssam } 15210245Ssam 15310245Ssam getsocket(domain, type, sin) 15410245Ssam int domain, type; 15510245Ssam struct sockaddr_in *sin; 15610245Ssam { 15710245Ssam int retry, s; 15810245Ssam 15910245Ssam retry = 1; 16010245Ssam while ((s = socket(domain, type, 0, 0)) < 0 && retry) { 16110245Ssam perror("socket"); 16210245Ssam sleep(5 * retry); 16310245Ssam retry <<= 1; 16410245Ssam } 16510245Ssam if (retry == 0) 16610245Ssam return (-1); 16710245Ssam while (bind(s, sin, sizeof (*sin), 0) < 0 && retry) { 16810245Ssam perror("bind"); 16910245Ssam sleep(5 * retry); 17010245Ssam retry <<= 1; 17110245Ssam } 17210245Ssam if (retry == 0) 17310245Ssam return (-1); 17410245Ssam return (s); 17510245Ssam } 176