121996Sdist /* 221996Sdist * Copyright (c) 1983 Regents of the University of California. 321996Sdist * All rights reserved. The Berkeley software License Agreement 421996Sdist * specifies the terms and conditions for redistribution. 521996Sdist */ 621996Sdist 79017Ssam #ifndef lint 821996Sdist char copyright[] = 921996Sdist "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 1021996Sdist All rights reserved.\n"; 1121996Sdist #endif not lint 129017Ssam 1321996Sdist #ifndef lint 14*25516Skarels static char sccsid[] = "@(#)main.c 5.4 (Berkeley) 11/21/85"; 1521996Sdist #endif not lint 1621996Sdist 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; 4624848Seric openlog("routed", LOG_PID | LOG_ODELAY, LOG_DAEMON); 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) 9124761Ssklower (void) close(t); 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; 16224761Ssklower omask = sigblock(sigmask(SIGALRM)); 1639017Ssam rip_input(&from, cc); 16413036Ssam sigsetmask(omask); 1659017Ssam } 16610245Ssam 16710245Ssam getsocket(domain, type, sin) 16810245Ssam int domain, type; 16910245Ssam struct sockaddr_in *sin; 17010245Ssam { 171*25516Skarels int s, on = 1; 17210245Ssam 173*25516Skarels if (s = socket(domain, type, 0)) { 17410245Ssam perror("socket"); 17517570Skarels syslog(LOG_ERR, "socket: %m"); 17610245Ssam return (-1); 17717570Skarels } 17817570Skarels if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) { 17917570Skarels syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m"); 180*25516Skarels close(s); 181*25516Skarels return (-1); 18217570Skarels } 183*25516Skarels if (bind(s, sin, sizeof (*sin), 0) < 0) { 18410245Ssam perror("bind"); 18517570Skarels syslog(LOG_ERR, "bind: %m"); 186*25516Skarels close(s); 18710245Ssam return (-1); 18817570Skarels } 18910245Ssam return (s); 19010245Ssam } 191