19017Ssam #ifndef lint 2*16326Skarels static char sccsid[] = "@(#)main.c 4.10 (Berkeley) 04/10/84"; 39017Ssam #endif 49017Ssam 59017Ssam /* 69017Ssam * Routing Table Management Daemon 79017Ssam */ 810245Ssam #include "defs.h" 99017Ssam #include <sys/ioctl.h> 1013602Ssam #include <sys/time.h> 1113602Ssam 129017Ssam #include <net/if.h> 1313602Ssam 149017Ssam #include <errno.h> 159017Ssam #include <nlist.h> 169017Ssam #include <signal.h> 179017Ssam 189017Ssam int supplier = -1; /* process should supply updates */ 19*16326Skarels extern int gateway; 209017Ssam 219017Ssam struct rip *msg = (struct rip *)packet; 2216314Skarels int hup(); 239017Ssam 249017Ssam main(argc, argv) 259017Ssam int argc; 269017Ssam char *argv[]; 279017Ssam { 289017Ssam int cc; 299017Ssam struct sockaddr from; 3010245Ssam u_char retry; 3110245Ssam #ifdef COMPAT 3210245Ssam int snoroute; 3310245Ssam #endif 349017Ssam 359017Ssam argv0 = argv; 369017Ssam sp = getservbyname("router", "udp"); 3710245Ssam if (sp == NULL) { 3810245Ssam fprintf(stderr, "routed: router/udp: unknown service\n"); 399017Ssam exit(1); 409017Ssam } 4110245Ssam addr.sin_family = AF_INET; 4210245Ssam addr.sin_port = sp->s_port; 4310245Ssam s = getsocket(AF_INET, SOCK_DGRAM, &addr); 4410245Ssam if (s < 0) 4510245Ssam exit(1); 4610245Ssam #ifdef COMPAT 4710245Ssam bzero(&addr, sizeof (addr)); 4810245Ssam addr.sin_family = AF_INET; 4910245Ssam addr.sin_port = htons(ntohs(sp->s_port) + 1); 5010245Ssam snoroute = getsocket(AF_INET, SOCK_DGRAM, &addr); 5110245Ssam if (snoroute < 0) 5210245Ssam exit(1); 5310245Ssam #endif 549017Ssam argv++, argc--; 559017Ssam while (argc > 0 && **argv == '-') { 5610636Ssam if (strcmp(*argv, "-s") == 0) { 579017Ssam supplier = 1; 589017Ssam argv++, argc--; 599017Ssam continue; 609017Ssam } 6110636Ssam if (strcmp(*argv, "-q") == 0) { 629017Ssam supplier = 0; 639017Ssam argv++, argc--; 649017Ssam continue; 659017Ssam } 6610636Ssam if (strcmp(*argv, "-t") == 0) { 6710636Ssam tracepackets++; 6810636Ssam argv++, argc--; 6910636Ssam continue; 7010636Ssam } 71*16326Skarels if (strcmp(*argv, "-g") == 0) { 72*16326Skarels gateway = 1; 73*16326Skarels argv++, argc--; 74*16326Skarels continue; 75*16326Skarels } 76*16326Skarels if (strcmp(*argv, "-l") == 0) { 77*16326Skarels gateway = -1; 78*16326Skarels argv++, argc--; 79*16326Skarels continue; 80*16326Skarels } 81*16326Skarels fprintf(stderr, 82*16326Skarels "usage: routed [ -s ] [ -q ] [ -t ] [ -g ] [ -l ]\n"); 839017Ssam exit(1); 849017Ssam } 8510636Ssam #ifndef DEBUG 8610636Ssam if (!tracepackets) { 8710636Ssam int t; 8810636Ssam 8910636Ssam if (fork()) 9010636Ssam exit(0); 9110637Ssam for (t = 0; t < 20; t++) 9210637Ssam if (t != s) 9310637Ssam #ifdef COMPAT 9412726Ssam if (t != snoroute) 9510637Ssam #endif 9610637Ssam (void) close(cc); 9710636Ssam (void) open("/", 0); 9810636Ssam (void) dup2(0, 1); 9910636Ssam (void) dup2(0, 2); 10010636Ssam t = open("/dev/tty", 2); 10110636Ssam if (t >= 0) { 10210636Ssam ioctl(t, TIOCNOTTY, (char *)0); 10310636Ssam (void) close(t); 10410636Ssam } 10510636Ssam } 10610636Ssam #endif 1079017Ssam /* 10810245Ssam * Any extra argument is considered 10910245Ssam * a tracing log file. 11010245Ssam */ 11110245Ssam if (argc > 0) 11210245Ssam traceon(*argv); 11310245Ssam /* 1149017Ssam * Collect an initial view of the world by 1159017Ssam * snooping in the kernel and the gateway kludge 1169017Ssam * file. Then, send a request packet on all 1179017Ssam * directly connected networks to find out what 1189017Ssam * everyone else thinks. 1199017Ssam */ 1209017Ssam rtinit(); 1219017Ssam gwkludge(); 1229017Ssam ifinit(); 1239017Ssam if (supplier < 0) 1249017Ssam supplier = 0; 1259017Ssam msg->rip_cmd = RIPCMD_REQUEST; 12612726Ssam msg->rip_vers = RIPVERSION; 1279017Ssam msg->rip_nets[0].rip_dst.sa_family = AF_UNSPEC; 1289017Ssam msg->rip_nets[0].rip_metric = HOPCNT_INFINITY; 12912726Ssam msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC); 13012726Ssam msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY); 1319017Ssam toall(sendmsg); 13213036Ssam signal(SIGALRM, timer); 13316314Skarels signal(SIGHUP, hup); 1349017Ssam timer(); 1359017Ssam 1369017Ssam for (;;) { 1379017Ssam int ibits; 1389017Ssam register int n; 1399017Ssam 14010245Ssam ibits = 1 << s; 14110245Ssam #ifdef COMPAT 14210245Ssam ibits |= 1 << snoroute; 14310245Ssam #endif 14410245Ssam n = select(20, &ibits, 0, 0, 0); 1459017Ssam if (n < 0) 1469017Ssam continue; 1479017Ssam if (ibits & (1 << s)) 1489017Ssam process(s); 14910245Ssam #ifdef COMPAT 1509017Ssam if (ibits & (1 << snoroute)) 1519017Ssam process(snoroute); 15210245Ssam #endif 15310245Ssam /* handle ICMP redirects */ 1549017Ssam } 1559017Ssam } 1569017Ssam 1579017Ssam process(fd) 1589017Ssam int fd; 1599017Ssam { 1609017Ssam struct sockaddr from; 16113036Ssam int fromlen = sizeof (from), cc, omask; 1629017Ssam 16310245Ssam cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen); 1649017Ssam if (cc <= 0) { 1659017Ssam if (cc < 0 && errno != EINTR) 16610245Ssam perror("recvfrom"); 1679017Ssam return; 1689017Ssam } 16910245Ssam if (fromlen != sizeof (struct sockaddr_in)) 17010245Ssam return; 17113036Ssam #define mask(s) (1<<((s)-1)) 17213036Ssam omask = sigblock(mask(SIGALRM)); 1739017Ssam rip_input(&from, cc); 17413036Ssam sigsetmask(omask); 1759017Ssam } 17610245Ssam 17710245Ssam getsocket(domain, type, sin) 17810245Ssam int domain, type; 17910245Ssam struct sockaddr_in *sin; 18010245Ssam { 18110245Ssam int retry, s; 18210245Ssam 18310245Ssam retry = 1; 18410245Ssam while ((s = socket(domain, type, 0, 0)) < 0 && retry) { 18510245Ssam perror("socket"); 18610245Ssam sleep(5 * retry); 18710245Ssam retry <<= 1; 18810245Ssam } 18910245Ssam if (retry == 0) 19010245Ssam return (-1); 19110245Ssam while (bind(s, sin, sizeof (*sin), 0) < 0 && retry) { 19210245Ssam perror("bind"); 19310245Ssam sleep(5 * retry); 19410245Ssam retry <<= 1; 19510245Ssam } 19610245Ssam if (retry == 0) 19710245Ssam return (-1); 19810245Ssam return (s); 19910245Ssam } 200