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*31220Skarels static char sccsid[] = "@(#)main.c 5.11 (Berkeley) 05/28/87"; 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 <signal.h> 2817570Skarels #include <syslog.h> 299017Ssam 309017Ssam int supplier = -1; /* process should supply updates */ 3121847Skarels int gateway = 0; /* 1 if we are a gateway to parts beyond */ 32*31220Skarels int debug = 0; 339017Ssam 349017Ssam struct rip *msg = (struct rip *)packet; 35*31220Skarels int hup(), rtdeleteall(); 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); 4730930Skarels setlogmask(LOG_UPTO(LOG_WARNING)); 489017Ssam sp = getservbyname("router", "udp"); 4910245Ssam if (sp == NULL) { 5010245Ssam fprintf(stderr, "routed: router/udp: unknown service\n"); 519017Ssam exit(1); 529017Ssam } 5310245Ssam addr.sin_family = AF_INET; 5410245Ssam addr.sin_port = sp->s_port; 5510245Ssam s = getsocket(AF_INET, SOCK_DGRAM, &addr); 5610245Ssam if (s < 0) 5710245Ssam exit(1); 589017Ssam argv++, argc--; 599017Ssam while (argc > 0 && **argv == '-') { 6010636Ssam if (strcmp(*argv, "-s") == 0) { 619017Ssam supplier = 1; 629017Ssam argv++, argc--; 639017Ssam continue; 649017Ssam } 6510636Ssam if (strcmp(*argv, "-q") == 0) { 669017Ssam supplier = 0; 679017Ssam argv++, argc--; 689017Ssam continue; 699017Ssam } 7010636Ssam if (strcmp(*argv, "-t") == 0) { 7110636Ssam tracepackets++; 7230930Skarels setlogmask(LOG_UPTO(LOG_DEBUG)); 7310636Ssam argv++, argc--; 7410636Ssam continue; 7510636Ssam } 7626341Skarels if (strcmp(*argv, "-d") == 0) { 77*31220Skarels debug++; 7830930Skarels setlogmask(LOG_UPTO(LOG_DEBUG)); 7926341Skarels argv++, argc--; 8026341Skarels continue; 8126341Skarels } 8216326Skarels if (strcmp(*argv, "-g") == 0) { 8316326Skarels gateway = 1; 8416326Skarels argv++, argc--; 8516326Skarels continue; 8616326Skarels } 8716326Skarels fprintf(stderr, 8821847Skarels "usage: routed [ -s ] [ -q ] [ -t ] [ -g ]\n"); 899017Ssam exit(1); 909017Ssam } 91*31220Skarels if (tracepackets == 0 && debug == 0) { 9210636Ssam int t; 9310636Ssam 9410636Ssam if (fork()) 9510636Ssam exit(0); 9610637Ssam for (t = 0; t < 20; t++) 9710637Ssam if (t != s) 9824761Ssklower (void) close(t); 9910636Ssam (void) open("/", 0); 10010636Ssam (void) dup2(0, 1); 10110636Ssam (void) dup2(0, 2); 10210636Ssam t = open("/dev/tty", 2); 10310636Ssam if (t >= 0) { 10410636Ssam ioctl(t, TIOCNOTTY, (char *)0); 10510636Ssam (void) close(t); 10610636Ssam } 10710636Ssam } 1089017Ssam /* 10910245Ssam * Any extra argument is considered 11010245Ssam * a tracing log file. 11110245Ssam */ 11210245Ssam if (argc > 0) 11310245Ssam traceon(*argv); 11410245Ssam /* 1159017Ssam * Collect an initial view of the world by 11621847Skarels * checking the interface configuration and the gateway kludge 1179017Ssam * file. Then, send a request packet on all 1189017Ssam * directly connected networks to find out what 1199017Ssam * everyone else thinks. 1209017Ssam */ 1219017Ssam rtinit(); 12230927Skarels ifinit(); 1239017Ssam gwkludge(); 12421847Skarels if (gateway > 0) 12521847Skarels rtdefault(); 1269017Ssam if (supplier < 0) 1279017Ssam supplier = 0; 1289017Ssam msg->rip_cmd = RIPCMD_REQUEST; 12912726Ssam msg->rip_vers = RIPVERSION; 1309017Ssam msg->rip_nets[0].rip_dst.sa_family = AF_UNSPEC; 1319017Ssam msg->rip_nets[0].rip_metric = HOPCNT_INFINITY; 13212726Ssam msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC); 13312726Ssam msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY); 1349017Ssam toall(sendmsg); 13513036Ssam signal(SIGALRM, timer); 13616314Skarels signal(SIGHUP, hup); 13717570Skarels signal(SIGTERM, hup); 138*31220Skarels signal(SIGINT, rtdeleteall); 1399017Ssam timer(); 1409017Ssam 1419017Ssam for (;;) { 1429017Ssam int ibits; 1439017Ssam register int n; 1449017Ssam 14510245Ssam ibits = 1 << s; 14610245Ssam n = select(20, &ibits, 0, 0, 0); 1479017Ssam if (n < 0) 1489017Ssam continue; 1499017Ssam if (ibits & (1 << s)) 1509017Ssam process(s); 15110245Ssam /* handle ICMP redirects */ 1529017Ssam } 1539017Ssam } 1549017Ssam 1559017Ssam process(fd) 1569017Ssam int fd; 1579017Ssam { 1589017Ssam struct sockaddr from; 15913036Ssam int fromlen = sizeof (from), cc, omask; 1609017Ssam 16110245Ssam cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen); 1629017Ssam if (cc <= 0) { 1639017Ssam if (cc < 0 && errno != EINTR) 16410245Ssam perror("recvfrom"); 1659017Ssam return; 1669017Ssam } 16710245Ssam if (fromlen != sizeof (struct sockaddr_in)) 16810245Ssam return; 16924761Ssklower omask = sigblock(sigmask(SIGALRM)); 1709017Ssam rip_input(&from, cc); 17113036Ssam sigsetmask(omask); 1729017Ssam } 17310245Ssam 17410245Ssam getsocket(domain, type, sin) 17510245Ssam int domain, type; 17610245Ssam struct sockaddr_in *sin; 17710245Ssam { 17825516Skarels int s, on = 1; 17910245Ssam 18025702Smckusick if ((s = socket(domain, type, 0)) < 0) { 18110245Ssam perror("socket"); 18217570Skarels syslog(LOG_ERR, "socket: %m"); 18310245Ssam return (-1); 18417570Skarels } 18517570Skarels if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) { 18617570Skarels syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m"); 18725516Skarels close(s); 18825516Skarels return (-1); 18917570Skarels } 19030927Skarels on = 48*1024; 19130927Skarels if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &on, sizeof (on)) < 0) 19230927Skarels syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m"); 19325516Skarels if (bind(s, sin, sizeof (*sin), 0) < 0) { 19410245Ssam perror("bind"); 19517570Skarels syslog(LOG_ERR, "bind: %m"); 19625516Skarels close(s); 19710245Ssam return (-1); 19817570Skarels } 19910245Ssam return (s); 20010245Ssam } 201