1*21996Sdist /* 2*21996Sdist * Copyright (c) 1983 Regents of the University of California. 3*21996Sdist * All rights reserved. The Berkeley software License Agreement 4*21996Sdist * specifies the terms and conditions for redistribution. 5*21996Sdist */ 6*21996Sdist 79017Ssam #ifndef lint 8*21996Sdist char copyright[] = 9*21996Sdist "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 10*21996Sdist All rights reserved.\n"; 11*21996Sdist #endif not lint 129017Ssam 13*21996Sdist #ifndef lint 14*21996Sdist static char sccsid[] = "@(#)main.c 5.1 (Berkeley) 06/04/85"; 15*21996Sdist #endif not lint 16*21996Sdist 179017Ssam /* 189017Ssam * Routing Table Management Daemon 199017Ssam */ 2010245Ssam #include "defs.h" 219017Ssam #include <sys/ioctl.h> 2213602Ssam #include <sys/time.h> 2313602Ssam 249017Ssam #include <net/if.h> 2513602Ssam 269017Ssam #include <errno.h> 279017Ssam #include <nlist.h> 289017Ssam #include <signal.h> 2917570Skarels #include <syslog.h> 309017Ssam 319017Ssam int supplier = -1; /* process should supply updates */ 3221847Skarels int gateway = 0; /* 1 if we are a gateway to parts beyond */ 339017Ssam 349017Ssam struct rip *msg = (struct rip *)packet; 3516314Skarels int hup(); 369017Ssam 379017Ssam main(argc, argv) 389017Ssam int argc; 399017Ssam char *argv[]; 409017Ssam { 419017Ssam int cc; 429017Ssam struct sockaddr from; 4310245Ssam u_char retry; 449017Ssam 459017Ssam argv0 = argv; 4617570Skarels openlog("routed", LOG_PID, 0); 479017Ssam sp = getservbyname("router", "udp"); 4810245Ssam if (sp == NULL) { 4910245Ssam fprintf(stderr, "routed: router/udp: unknown service\n"); 509017Ssam exit(1); 519017Ssam } 5210245Ssam addr.sin_family = AF_INET; 5310245Ssam addr.sin_port = sp->s_port; 5410245Ssam s = getsocket(AF_INET, SOCK_DGRAM, &addr); 5510245Ssam if (s < 0) 5610245Ssam exit(1); 579017Ssam argv++, argc--; 589017Ssam while (argc > 0 && **argv == '-') { 5910636Ssam if (strcmp(*argv, "-s") == 0) { 609017Ssam supplier = 1; 619017Ssam argv++, argc--; 629017Ssam continue; 639017Ssam } 6410636Ssam if (strcmp(*argv, "-q") == 0) { 659017Ssam supplier = 0; 669017Ssam argv++, argc--; 679017Ssam continue; 689017Ssam } 6910636Ssam if (strcmp(*argv, "-t") == 0) { 7010636Ssam tracepackets++; 7110636Ssam argv++, argc--; 7210636Ssam continue; 7310636Ssam } 7416326Skarels if (strcmp(*argv, "-g") == 0) { 7516326Skarels gateway = 1; 7616326Skarels argv++, argc--; 7716326Skarels continue; 7816326Skarels } 7916326Skarels fprintf(stderr, 8021847Skarels "usage: routed [ -s ] [ -q ] [ -t ] [ -g ]\n"); 819017Ssam exit(1); 829017Ssam } 8310636Ssam #ifndef DEBUG 8410636Ssam if (!tracepackets) { 8510636Ssam int t; 8610636Ssam 8710636Ssam if (fork()) 8810636Ssam exit(0); 8910637Ssam for (t = 0; t < 20; t++) 9010637Ssam if (t != s) 9110637Ssam (void) close(cc); 9210636Ssam (void) open("/", 0); 9310636Ssam (void) dup2(0, 1); 9410636Ssam (void) dup2(0, 2); 9510636Ssam t = open("/dev/tty", 2); 9610636Ssam if (t >= 0) { 9710636Ssam ioctl(t, TIOCNOTTY, (char *)0); 9810636Ssam (void) close(t); 9910636Ssam } 10010636Ssam } 10110636Ssam #endif 1029017Ssam /* 10310245Ssam * Any extra argument is considered 10410245Ssam * a tracing log file. 10510245Ssam */ 10610245Ssam if (argc > 0) 10710245Ssam traceon(*argv); 10810245Ssam /* 1099017Ssam * Collect an initial view of the world by 11021847Skarels * checking the interface configuration and the gateway kludge 1119017Ssam * file. Then, send a request packet on all 1129017Ssam * directly connected networks to find out what 1139017Ssam * everyone else thinks. 1149017Ssam */ 1159017Ssam rtinit(); 1169017Ssam gwkludge(); 1179017Ssam ifinit(); 11821847Skarels if (gateway > 0) 11921847Skarels rtdefault(); 1209017Ssam if (supplier < 0) 1219017Ssam supplier = 0; 1229017Ssam msg->rip_cmd = RIPCMD_REQUEST; 12312726Ssam msg->rip_vers = RIPVERSION; 1249017Ssam msg->rip_nets[0].rip_dst.sa_family = AF_UNSPEC; 1259017Ssam msg->rip_nets[0].rip_metric = HOPCNT_INFINITY; 12612726Ssam msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC); 12712726Ssam msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY); 1289017Ssam toall(sendmsg); 12913036Ssam signal(SIGALRM, timer); 13016314Skarels signal(SIGHUP, hup); 13117570Skarels signal(SIGTERM, hup); 1329017Ssam timer(); 1339017Ssam 1349017Ssam for (;;) { 1359017Ssam int ibits; 1369017Ssam register int n; 1379017Ssam 13810245Ssam ibits = 1 << s; 13910245Ssam n = select(20, &ibits, 0, 0, 0); 1409017Ssam if (n < 0) 1419017Ssam continue; 1429017Ssam if (ibits & (1 << s)) 1439017Ssam process(s); 14410245Ssam /* handle ICMP redirects */ 1459017Ssam } 1469017Ssam } 1479017Ssam 1489017Ssam process(fd) 1499017Ssam int fd; 1509017Ssam { 1519017Ssam struct sockaddr from; 15213036Ssam int fromlen = sizeof (from), cc, omask; 1539017Ssam 15410245Ssam cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen); 1559017Ssam if (cc <= 0) { 1569017Ssam if (cc < 0 && errno != EINTR) 15710245Ssam perror("recvfrom"); 1589017Ssam return; 1599017Ssam } 16010245Ssam if (fromlen != sizeof (struct sockaddr_in)) 16110245Ssam return; 16213036Ssam #define mask(s) (1<<((s)-1)) 16313036Ssam omask = sigblock(mask(SIGALRM)); 1649017Ssam rip_input(&from, cc); 16513036Ssam sigsetmask(omask); 1669017Ssam } 16710245Ssam 16810245Ssam getsocket(domain, type, sin) 16910245Ssam int domain, type; 17010245Ssam struct sockaddr_in *sin; 17110245Ssam { 17217570Skarels int retry, s, on = 1; 17310245Ssam 17410245Ssam retry = 1; 17510245Ssam while ((s = socket(domain, type, 0, 0)) < 0 && retry) { 17610245Ssam perror("socket"); 17710245Ssam sleep(5 * retry); 17810245Ssam retry <<= 1; 17910245Ssam } 18017570Skarels if (retry == 0) { 18117570Skarels syslog(LOG_ERR, "socket: %m"); 18210245Ssam return (-1); 18317570Skarels } 18417570Skarels if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) { 18517570Skarels syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m"); 18617570Skarels exit(1); 18717570Skarels } 18810245Ssam while (bind(s, sin, sizeof (*sin), 0) < 0 && retry) { 18910245Ssam perror("bind"); 19010245Ssam sleep(5 * retry); 19110245Ssam retry <<= 1; 19210245Ssam } 19317570Skarels if (retry == 0) { 19417570Skarels syslog(LOG_ERR, "bind: %m"); 19510245Ssam return (-1); 19617570Skarels } 19710245Ssam return (s); 19810245Ssam } 199