19017Ssam #ifndef lint 2*13602Ssam static char sccsid[] = "@(#)main.c 4.8 (Berkeley) 07/01/83"; 39017Ssam #endif 49017Ssam 59017Ssam /* 69017Ssam * Routing Table Management Daemon 79017Ssam */ 810245Ssam #include "defs.h" 99017Ssam #include <sys/ioctl.h> 10*13602Ssam #include <sys/time.h> 11*13602Ssam 129017Ssam #include <net/if.h> 13*13602Ssam 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; 219017Ssam 229017Ssam main(argc, argv) 239017Ssam int argc; 249017Ssam char *argv[]; 259017Ssam { 269017Ssam int cc; 279017Ssam struct sockaddr from; 2810245Ssam u_char retry; 2910245Ssam #ifdef COMPAT 3010245Ssam int snoroute; 3110245Ssam #endif 329017Ssam 339017Ssam argv0 = argv; 349017Ssam sp = getservbyname("router", "udp"); 3510245Ssam if (sp == NULL) { 3610245Ssam fprintf(stderr, "routed: router/udp: unknown service\n"); 379017Ssam exit(1); 389017Ssam } 3910245Ssam addr.sin_family = AF_INET; 4010245Ssam addr.sin_port = sp->s_port; 4110245Ssam s = getsocket(AF_INET, SOCK_DGRAM, &addr); 4210245Ssam if (s < 0) 4310245Ssam exit(1); 4410245Ssam #ifdef COMPAT 4510245Ssam bzero(&addr, sizeof (addr)); 4610245Ssam addr.sin_family = AF_INET; 4710245Ssam addr.sin_port = htons(ntohs(sp->s_port) + 1); 4810245Ssam snoroute = getsocket(AF_INET, SOCK_DGRAM, &addr); 4910245Ssam if (snoroute < 0) 5010245Ssam exit(1); 5110245Ssam #endif 529017Ssam argv++, argc--; 539017Ssam while (argc > 0 && **argv == '-') { 5410636Ssam if (strcmp(*argv, "-s") == 0) { 559017Ssam supplier = 1; 569017Ssam argv++, argc--; 579017Ssam continue; 589017Ssam } 5910636Ssam if (strcmp(*argv, "-q") == 0) { 609017Ssam supplier = 0; 619017Ssam argv++, argc--; 629017Ssam continue; 639017Ssam } 6410636Ssam if (strcmp(*argv, "-t") == 0) { 6510636Ssam tracepackets++; 6610636Ssam argv++, argc--; 6710636Ssam continue; 6810636Ssam } 6910636Ssam fprintf(stderr, "usage: routed [ -s ] [ -q ] [ -t ]\n"); 709017Ssam exit(1); 719017Ssam } 7210636Ssam #ifndef DEBUG 7310636Ssam if (!tracepackets) { 7410636Ssam int t; 7510636Ssam 7610636Ssam if (fork()) 7710636Ssam exit(0); 7810637Ssam for (t = 0; t < 20; t++) 7910637Ssam if (t != s) 8010637Ssam #ifdef COMPAT 8112726Ssam if (t != snoroute) 8210637Ssam #endif 8310637Ssam (void) close(cc); 8410636Ssam (void) open("/", 0); 8510636Ssam (void) dup2(0, 1); 8610636Ssam (void) dup2(0, 2); 8710636Ssam t = open("/dev/tty", 2); 8810636Ssam if (t >= 0) { 8910636Ssam ioctl(t, TIOCNOTTY, (char *)0); 9010636Ssam (void) close(t); 9110636Ssam } 9210636Ssam } 9310636Ssam #endif 949017Ssam /* 9510245Ssam * Any extra argument is considered 9610245Ssam * a tracing log file. 9710245Ssam */ 9810245Ssam if (argc > 0) 9910245Ssam traceon(*argv); 10010245Ssam /* 1019017Ssam * Collect an initial view of the world by 1029017Ssam * snooping in the kernel and the gateway kludge 1039017Ssam * file. Then, send a request packet on all 1049017Ssam * directly connected networks to find out what 1059017Ssam * everyone else thinks. 1069017Ssam */ 1079017Ssam rtinit(); 1089017Ssam gwkludge(); 1099017Ssam ifinit(); 1109017Ssam if (supplier < 0) 1119017Ssam supplier = 0; 1129017Ssam msg->rip_cmd = RIPCMD_REQUEST; 11312726Ssam msg->rip_vers = RIPVERSION; 1149017Ssam msg->rip_nets[0].rip_dst.sa_family = AF_UNSPEC; 1159017Ssam msg->rip_nets[0].rip_metric = HOPCNT_INFINITY; 11612726Ssam msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC); 11712726Ssam msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY); 1189017Ssam toall(sendmsg); 11913036Ssam signal(SIGALRM, timer); 1209017Ssam timer(); 1219017Ssam 1229017Ssam for (;;) { 1239017Ssam int ibits; 1249017Ssam register int n; 1259017Ssam 12610245Ssam ibits = 1 << s; 12710245Ssam #ifdef COMPAT 12810245Ssam ibits |= 1 << snoroute; 12910245Ssam #endif 13010245Ssam n = select(20, &ibits, 0, 0, 0); 1319017Ssam if (n < 0) 1329017Ssam continue; 1339017Ssam if (ibits & (1 << s)) 1349017Ssam process(s); 13510245Ssam #ifdef COMPAT 1369017Ssam if (ibits & (1 << snoroute)) 1379017Ssam process(snoroute); 13810245Ssam #endif 13910245Ssam /* handle ICMP redirects */ 1409017Ssam } 1419017Ssam } 1429017Ssam 1439017Ssam process(fd) 1449017Ssam int fd; 1459017Ssam { 1469017Ssam struct sockaddr from; 14713036Ssam int fromlen = sizeof (from), cc, omask; 1489017Ssam 14910245Ssam cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen); 1509017Ssam if (cc <= 0) { 1519017Ssam if (cc < 0 && errno != EINTR) 15210245Ssam perror("recvfrom"); 1539017Ssam return; 1549017Ssam } 15510245Ssam if (fromlen != sizeof (struct sockaddr_in)) 15610245Ssam return; 15713036Ssam #define mask(s) (1<<((s)-1)) 15813036Ssam omask = sigblock(mask(SIGALRM)); 1599017Ssam rip_input(&from, cc); 16013036Ssam sigsetmask(omask); 1619017Ssam } 16210245Ssam 16310245Ssam getsocket(domain, type, sin) 16410245Ssam int domain, type; 16510245Ssam struct sockaddr_in *sin; 16610245Ssam { 16710245Ssam int retry, s; 16810245Ssam 16910245Ssam retry = 1; 17010245Ssam while ((s = socket(domain, type, 0, 0)) < 0 && retry) { 17110245Ssam perror("socket"); 17210245Ssam sleep(5 * retry); 17310245Ssam retry <<= 1; 17410245Ssam } 17510245Ssam if (retry == 0) 17610245Ssam return (-1); 17710245Ssam while (bind(s, sin, sizeof (*sin), 0) < 0 && retry) { 17810245Ssam perror("bind"); 17910245Ssam sleep(5 * retry); 18010245Ssam retry <<= 1; 18110245Ssam } 18210245Ssam if (retry == 0) 18310245Ssam return (-1); 18410245Ssam return (s); 18510245Ssam } 186