19017Ssam #ifndef lint 2*10245Ssam static char sccsid[] = "@(#)main.c 4.2 01/11/83"; 39017Ssam #endif 49017Ssam 59017Ssam /* 69017Ssam * Routing Table Management Daemon 79017Ssam */ 8*10245Ssam #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; 26*10245Ssam u_char retry; 27*10245Ssam #ifdef COMPAT 28*10245Ssam int snoroute; 29*10245Ssam #endif 309017Ssam 319017Ssam argv0 = argv; 329017Ssam #ifndef DEBUG 339017Ssam if (fork()) 349017Ssam exit(0); 359017Ssam for (cc = 0; cc < 10; cc++) 369017Ssam (void) close(cc); 379017Ssam (void) open("/", 0); 389017Ssam (void) dup2(0, 1); 399017Ssam (void) dup2(0, 2); 409017Ssam { int t = open("/dev/tty", 2); 419017Ssam if (t >= 0) { 429017Ssam ioctl(t, TIOCNOTTY, (char *)0); 439017Ssam (void) close(t); 449017Ssam } 459017Ssam } 469017Ssam #endif 479017Ssam sp = getservbyname("router", "udp"); 48*10245Ssam if (sp == NULL) { 49*10245Ssam fprintf(stderr, "routed: router/udp: unknown service\n"); 509017Ssam exit(1); 519017Ssam } 52*10245Ssam addr.sin_family = AF_INET; 53*10245Ssam addr.sin_port = sp->s_port; 54*10245Ssam s = getsocket(AF_INET, SOCK_DGRAM, &addr); 55*10245Ssam if (s < 0) 56*10245Ssam exit(1); 57*10245Ssam #ifdef COMPAT 58*10245Ssam bzero(&addr, sizeof (addr)); 59*10245Ssam addr.sin_family = AF_INET; 60*10245Ssam addr.sin_port = htons(ntohs(sp->s_port) + 1); 61*10245Ssam snoroute = getsocket(AF_INET, SOCK_DGRAM, &addr); 62*10245Ssam if (snoroute < 0) 63*10245Ssam exit(1); 64*10245Ssam #endif 659017Ssam argv++, argc--; 669017Ssam while (argc > 0 && **argv == '-') { 679017Ssam if (!strcmp(*argv, "-s") == 0) { 689017Ssam supplier = 1; 699017Ssam argv++, argc--; 709017Ssam continue; 719017Ssam } 729017Ssam if (!strcmp(*argv, "-q") == 0) { 739017Ssam supplier = 0; 749017Ssam argv++, argc--; 759017Ssam continue; 769017Ssam } 779017Ssam fprintf(stderr, "usage: routed [ -s ] [ -q ]\n"); 789017Ssam exit(1); 799017Ssam } 809017Ssam /* 81*10245Ssam * Any extra argument is considered 82*10245Ssam * a tracing log file. 83*10245Ssam */ 84*10245Ssam if (argc > 0) 85*10245Ssam traceon(*argv); 86*10245Ssam /* 879017Ssam * Collect an initial view of the world by 889017Ssam * snooping in the kernel and the gateway kludge 899017Ssam * file. Then, send a request packet on all 909017Ssam * directly connected networks to find out what 919017Ssam * everyone else thinks. 929017Ssam */ 939017Ssam rtinit(); 949017Ssam gwkludge(); 959017Ssam ifinit(); 969017Ssam if (supplier < 0) 979017Ssam supplier = 0; 989017Ssam msg->rip_cmd = RIPCMD_REQUEST; 999017Ssam msg->rip_nets[0].rip_dst.sa_family = AF_UNSPEC; 1009017Ssam msg->rip_nets[0].rip_metric = HOPCNT_INFINITY; 1019017Ssam toall(sendmsg); 1029017Ssam sigset(SIGALRM, timer); 1039017Ssam timer(); 1049017Ssam 1059017Ssam for (;;) { 1069017Ssam int ibits; 1079017Ssam register int n; 1089017Ssam 109*10245Ssam ibits = 1 << s; 110*10245Ssam #ifdef COMPAT 111*10245Ssam ibits |= 1 << snoroute; 112*10245Ssam #endif 113*10245Ssam n = select(20, &ibits, 0, 0, 0); 1149017Ssam if (n < 0) 1159017Ssam continue; 1169017Ssam if (ibits & (1 << s)) 1179017Ssam process(s); 118*10245Ssam #ifdef COMPAT 1199017Ssam if (ibits & (1 << snoroute)) 1209017Ssam process(snoroute); 121*10245Ssam #endif 122*10245Ssam /* handle ICMP redirects */ 1239017Ssam } 1249017Ssam } 1259017Ssam 1269017Ssam process(fd) 1279017Ssam int fd; 1289017Ssam { 1299017Ssam struct sockaddr from; 130*10245Ssam int fromlen = sizeof (from), cc; 1319017Ssam 132*10245Ssam cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen); 1339017Ssam if (cc <= 0) { 1349017Ssam if (cc < 0 && errno != EINTR) 135*10245Ssam perror("recvfrom"); 1369017Ssam return; 1379017Ssam } 138*10245Ssam if (fromlen != sizeof (struct sockaddr_in)) 139*10245Ssam return; 1409017Ssam sighold(SIGALRM); 1419017Ssam rip_input(&from, cc); 1429017Ssam sigrelse(SIGALRM); 1439017Ssam } 144*10245Ssam 145*10245Ssam getsocket(domain, type, sin) 146*10245Ssam int domain, type; 147*10245Ssam struct sockaddr_in *sin; 148*10245Ssam { 149*10245Ssam int retry, s; 150*10245Ssam 151*10245Ssam retry = 1; 152*10245Ssam while ((s = socket(domain, type, 0, 0)) < 0 && retry) { 153*10245Ssam perror("socket"); 154*10245Ssam sleep(5 * retry); 155*10245Ssam retry <<= 1; 156*10245Ssam } 157*10245Ssam if (retry == 0) 158*10245Ssam return (-1); 159*10245Ssam while (bind(s, sin, sizeof (*sin), 0) < 0 && retry) { 160*10245Ssam perror("bind"); 161*10245Ssam sleep(5 * retry); 162*10245Ssam retry <<= 1; 163*10245Ssam } 164*10245Ssam if (retry == 0) 165*10245Ssam return (-1); 166*10245Ssam return (s); 167*10245Ssam } 168