19017Ssam #ifndef lint 2*21847Skarels static char sccsid[] = "@(#)main.c 4.13 (Berkeley) 06/03/85"; 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> 1717570Skarels #include <syslog.h> 189017Ssam 199017Ssam int supplier = -1; /* process should supply updates */ 20*21847Skarels int gateway = 0; /* 1 if we are a gateway to parts beyond */ 219017Ssam 229017Ssam struct rip *msg = (struct rip *)packet; 2316314Skarels int hup(); 249017Ssam 259017Ssam main(argc, argv) 269017Ssam int argc; 279017Ssam char *argv[]; 289017Ssam { 299017Ssam int cc; 309017Ssam struct sockaddr from; 3110245Ssam u_char retry; 329017Ssam 339017Ssam argv0 = argv; 3417570Skarels openlog("routed", LOG_PID, 0); 359017Ssam sp = getservbyname("router", "udp"); 3610245Ssam if (sp == NULL) { 3710245Ssam fprintf(stderr, "routed: router/udp: unknown service\n"); 389017Ssam exit(1); 399017Ssam } 4010245Ssam addr.sin_family = AF_INET; 4110245Ssam addr.sin_port = sp->s_port; 4210245Ssam s = getsocket(AF_INET, SOCK_DGRAM, &addr); 4310245Ssam if (s < 0) 4410245Ssam exit(1); 459017Ssam argv++, argc--; 469017Ssam while (argc > 0 && **argv == '-') { 4710636Ssam if (strcmp(*argv, "-s") == 0) { 489017Ssam supplier = 1; 499017Ssam argv++, argc--; 509017Ssam continue; 519017Ssam } 5210636Ssam if (strcmp(*argv, "-q") == 0) { 539017Ssam supplier = 0; 549017Ssam argv++, argc--; 559017Ssam continue; 569017Ssam } 5710636Ssam if (strcmp(*argv, "-t") == 0) { 5810636Ssam tracepackets++; 5910636Ssam argv++, argc--; 6010636Ssam continue; 6110636Ssam } 6216326Skarels if (strcmp(*argv, "-g") == 0) { 6316326Skarels gateway = 1; 6416326Skarels argv++, argc--; 6516326Skarels continue; 6616326Skarels } 6716326Skarels fprintf(stderr, 68*21847Skarels "usage: routed [ -s ] [ -q ] [ -t ] [ -g ]\n"); 699017Ssam exit(1); 709017Ssam } 7110636Ssam #ifndef DEBUG 7210636Ssam if (!tracepackets) { 7310636Ssam int t; 7410636Ssam 7510636Ssam if (fork()) 7610636Ssam exit(0); 7710637Ssam for (t = 0; t < 20; t++) 7810637Ssam if (t != s) 7910637Ssam (void) close(cc); 8010636Ssam (void) open("/", 0); 8110636Ssam (void) dup2(0, 1); 8210636Ssam (void) dup2(0, 2); 8310636Ssam t = open("/dev/tty", 2); 8410636Ssam if (t >= 0) { 8510636Ssam ioctl(t, TIOCNOTTY, (char *)0); 8610636Ssam (void) close(t); 8710636Ssam } 8810636Ssam } 8910636Ssam #endif 909017Ssam /* 9110245Ssam * Any extra argument is considered 9210245Ssam * a tracing log file. 9310245Ssam */ 9410245Ssam if (argc > 0) 9510245Ssam traceon(*argv); 9610245Ssam /* 979017Ssam * Collect an initial view of the world by 98*21847Skarels * checking the interface configuration and the gateway kludge 999017Ssam * file. Then, send a request packet on all 1009017Ssam * directly connected networks to find out what 1019017Ssam * everyone else thinks. 1029017Ssam */ 1039017Ssam rtinit(); 1049017Ssam gwkludge(); 1059017Ssam ifinit(); 106*21847Skarels if (gateway > 0) 107*21847Skarels rtdefault(); 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); 11713036Ssam signal(SIGALRM, timer); 11816314Skarels signal(SIGHUP, hup); 11917570Skarels signal(SIGTERM, hup); 1209017Ssam timer(); 1219017Ssam 1229017Ssam for (;;) { 1239017Ssam int ibits; 1249017Ssam register int n; 1259017Ssam 12610245Ssam ibits = 1 << s; 12710245Ssam n = select(20, &ibits, 0, 0, 0); 1289017Ssam if (n < 0) 1299017Ssam continue; 1309017Ssam if (ibits & (1 << s)) 1319017Ssam process(s); 13210245Ssam /* handle ICMP redirects */ 1339017Ssam } 1349017Ssam } 1359017Ssam 1369017Ssam process(fd) 1379017Ssam int fd; 1389017Ssam { 1399017Ssam struct sockaddr from; 14013036Ssam int fromlen = sizeof (from), cc, omask; 1419017Ssam 14210245Ssam cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen); 1439017Ssam if (cc <= 0) { 1449017Ssam if (cc < 0 && errno != EINTR) 14510245Ssam perror("recvfrom"); 1469017Ssam return; 1479017Ssam } 14810245Ssam if (fromlen != sizeof (struct sockaddr_in)) 14910245Ssam return; 15013036Ssam #define mask(s) (1<<((s)-1)) 15113036Ssam omask = sigblock(mask(SIGALRM)); 1529017Ssam rip_input(&from, cc); 15313036Ssam sigsetmask(omask); 1549017Ssam } 15510245Ssam 15610245Ssam getsocket(domain, type, sin) 15710245Ssam int domain, type; 15810245Ssam struct sockaddr_in *sin; 15910245Ssam { 16017570Skarels int retry, s, on = 1; 16110245Ssam 16210245Ssam retry = 1; 16310245Ssam while ((s = socket(domain, type, 0, 0)) < 0 && retry) { 16410245Ssam perror("socket"); 16510245Ssam sleep(5 * retry); 16610245Ssam retry <<= 1; 16710245Ssam } 16817570Skarels if (retry == 0) { 16917570Skarels syslog(LOG_ERR, "socket: %m"); 17010245Ssam return (-1); 17117570Skarels } 17217570Skarels if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) { 17317570Skarels syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m"); 17417570Skarels exit(1); 17517570Skarels } 17610245Ssam while (bind(s, sin, sizeof (*sin), 0) < 0 && retry) { 17710245Ssam perror("bind"); 17810245Ssam sleep(5 * retry); 17910245Ssam retry <<= 1; 18010245Ssam } 18117570Skarels if (retry == 0) { 18217570Skarels syslog(LOG_ERR, "bind: %m"); 18310245Ssam return (-1); 18417570Skarels } 18510245Ssam return (s); 18610245Ssam } 187