17b6ab19dSGarrett Wollman /* 27b6ab19dSGarrett Wollman * Copyright (c) 1983, 1988, 1993 37b6ab19dSGarrett Wollman * The Regents of the University of California. All rights reserved. 47b6ab19dSGarrett Wollman * 57b6ab19dSGarrett Wollman * Redistribution and use in source and binary forms, with or without 67b6ab19dSGarrett Wollman * modification, are permitted provided that the following conditions 77b6ab19dSGarrett Wollman * are met: 87b6ab19dSGarrett Wollman * 1. Redistributions of source code must retain the above copyright 97b6ab19dSGarrett Wollman * notice, this list of conditions and the following disclaimer. 107b6ab19dSGarrett Wollman * 2. Redistributions in binary form must reproduce the above copyright 117b6ab19dSGarrett Wollman * notice, this list of conditions and the following disclaimer in the 127b6ab19dSGarrett Wollman * documentation and/or other materials provided with the distribution. 137b6ab19dSGarrett Wollman * 3. All advertising materials mentioning features or use of this software 147b6ab19dSGarrett Wollman * must display the following acknowledgement: 157b6ab19dSGarrett Wollman * This product includes software developed by the University of 167b6ab19dSGarrett Wollman * California, Berkeley and its contributors. 177b6ab19dSGarrett Wollman * 4. Neither the name of the University nor the names of its contributors 187b6ab19dSGarrett Wollman * may be used to endorse or promote products derived from this software 197b6ab19dSGarrett Wollman * without specific prior written permission. 207b6ab19dSGarrett Wollman * 217b6ab19dSGarrett Wollman * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 227b6ab19dSGarrett Wollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 237b6ab19dSGarrett Wollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 247b6ab19dSGarrett Wollman * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 257b6ab19dSGarrett Wollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 267b6ab19dSGarrett Wollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 277b6ab19dSGarrett Wollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 287b6ab19dSGarrett Wollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 297b6ab19dSGarrett Wollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 307b6ab19dSGarrett Wollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 317b6ab19dSGarrett Wollman * SUCH DAMAGE. 327b6ab19dSGarrett Wollman */ 337b6ab19dSGarrett Wollman 347b6ab19dSGarrett Wollman char copyright[] = 357b6ab19dSGarrett Wollman "@(#) Copyright (c) 1983, 1988, 1993\n\ 367b6ab19dSGarrett Wollman The Regents of the University of California. All rights reserved.\n"; 377b6ab19dSGarrett Wollman #if !defined(lint) && !defined(sgi) && !defined(__NetBSD__) 387b6ab19dSGarrett Wollman static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/5/93"; 397b6ab19dSGarrett Wollman #elif defined(__NetBSD__) 407b6ab19dSGarrett Wollman static char rcsid[] = "$NetBSD$"; 417b6ab19dSGarrett Wollman #endif 427b6ab19dSGarrett Wollman #ident "$Revision: 1.17 $" 437b6ab19dSGarrett Wollman 447b6ab19dSGarrett Wollman #include "defs.h" 457b6ab19dSGarrett Wollman #include "pathnames.h" 467b6ab19dSGarrett Wollman #ifdef sgi 477b6ab19dSGarrett Wollman #include "math.h" 487b6ab19dSGarrett Wollman #endif 497b6ab19dSGarrett Wollman #include <signal.h> 507b6ab19dSGarrett Wollman #include <fcntl.h> 517b6ab19dSGarrett Wollman #include <sys/file.h> 527b6ab19dSGarrett Wollman 537b6ab19dSGarrett Wollman pid_t mypid; 547b6ab19dSGarrett Wollman 557b6ab19dSGarrett Wollman naddr myaddr; /* system address */ 567b6ab19dSGarrett Wollman char myname[MAXHOSTNAMELEN+1]; 577b6ab19dSGarrett Wollman 587b6ab19dSGarrett Wollman int supplier; /* supply or broadcast updates */ 597b6ab19dSGarrett Wollman int supplier_set; 607b6ab19dSGarrett Wollman int ipforwarding = 1; /* kernel forwarding on */ 617b6ab19dSGarrett Wollman 627b6ab19dSGarrett Wollman int default_gateway; /* 1=advertise default */ 637b6ab19dSGarrett Wollman int background = 1; 647b6ab19dSGarrett Wollman int ridhosts; /* 1=reduce host routes */ 657b6ab19dSGarrett Wollman int mhome; /* 1=want multi-homed host route */ 667b6ab19dSGarrett Wollman int advertise_mhome; /* 1=must continue adverising it */ 677b6ab19dSGarrett Wollman int auth_ok = 1; /* 1=ignore auth if we do not care */ 687b6ab19dSGarrett Wollman 697b6ab19dSGarrett Wollman struct timeval epoch; /* when started */ 707b6ab19dSGarrett Wollman struct timeval clk, prev_clk; 717b6ab19dSGarrett Wollman struct timeval now; /* current idea of time */ 727b6ab19dSGarrett Wollman time_t now_stale; 737b6ab19dSGarrett Wollman time_t now_expire; 747b6ab19dSGarrett Wollman time_t now_garbage; 757b6ab19dSGarrett Wollman 767b6ab19dSGarrett Wollman struct timeval next_bcast; /* next general broadcast */ 777b6ab19dSGarrett Wollman struct timeval no_flash = {EPOCH+SUPPLY_INTERVAL}; /* inhibit flash update */ 787b6ab19dSGarrett Wollman 797b6ab19dSGarrett Wollman fd_set fdbits; 807b6ab19dSGarrett Wollman int sock_max; 817b6ab19dSGarrett Wollman int rip_sock = -1; /* RIP socket */ 827b6ab19dSGarrett Wollman struct interface *rip_sock_mcast; /* current multicast interface */ 837b6ab19dSGarrett Wollman int rt_sock; /* routing socket */ 847b6ab19dSGarrett Wollman int rt_sock_seqno; 857b6ab19dSGarrett Wollman 867b6ab19dSGarrett Wollman 877b6ab19dSGarrett Wollman static int get_rip_sock(naddr, int); 887b6ab19dSGarrett Wollman static void timevalsub(struct timeval *, struct timeval *, struct timeval *); 897b6ab19dSGarrett Wollman 907b6ab19dSGarrett Wollman int 917b6ab19dSGarrett Wollman main(int argc, 927b6ab19dSGarrett Wollman char *argv[]) 937b6ab19dSGarrett Wollman { 947b6ab19dSGarrett Wollman int n, mib[4], off; 957b6ab19dSGarrett Wollman size_t len; 967b6ab19dSGarrett Wollman char *p, *q; 977b6ab19dSGarrett Wollman struct timeval wtime, t2; 987b6ab19dSGarrett Wollman time_t dt; 997b6ab19dSGarrett Wollman fd_set ibits; 1007b6ab19dSGarrett Wollman naddr p_addr, p_mask; 1017b6ab19dSGarrett Wollman struct interface *ifp; 1027b6ab19dSGarrett Wollman struct parm parm; 1037b6ab19dSGarrett Wollman char *tracename = 0; 1047b6ab19dSGarrett Wollman 1057b6ab19dSGarrett Wollman 1067b6ab19dSGarrett Wollman openlog("routed", LOG_PID | LOG_ODELAY, LOG_DAEMON); 1077b6ab19dSGarrett Wollman ftrace = stdout; 1087b6ab19dSGarrett Wollman 1097b6ab19dSGarrett Wollman gettimeofday(&clk, 0); 1107b6ab19dSGarrett Wollman prev_clk = clk; 1117b6ab19dSGarrett Wollman epoch = clk; 1127b6ab19dSGarrett Wollman epoch.tv_sec -= EPOCH; 1137b6ab19dSGarrett Wollman now.tv_sec = EPOCH; 1147b6ab19dSGarrett Wollman now_stale = EPOCH - STALE_TIME; 1157b6ab19dSGarrett Wollman now_expire = EPOCH - EXPIRE_TIME; 1167b6ab19dSGarrett Wollman now_garbage = EPOCH - GARBAGE_TIME; 1177b6ab19dSGarrett Wollman wtime.tv_sec = 0; 1187b6ab19dSGarrett Wollman 1197b6ab19dSGarrett Wollman (void)gethostname(myname, sizeof(myname)-1); 1207b6ab19dSGarrett Wollman (void)gethost(myname, &myaddr); 1217b6ab19dSGarrett Wollman 1227b6ab19dSGarrett Wollman while ((n = getopt(argc, argv, "sqdghmpAtT:F:P:")) != EOF) { 1237b6ab19dSGarrett Wollman switch (n) { 1247b6ab19dSGarrett Wollman case 's': 1257b6ab19dSGarrett Wollman supplier = 1; 1267b6ab19dSGarrett Wollman supplier_set = 1; 1277b6ab19dSGarrett Wollman break; 1287b6ab19dSGarrett Wollman 1297b6ab19dSGarrett Wollman case 'q': 1307b6ab19dSGarrett Wollman supplier = 0; 1317b6ab19dSGarrett Wollman supplier_set = 1; 1327b6ab19dSGarrett Wollman break; 1337b6ab19dSGarrett Wollman 1347b6ab19dSGarrett Wollman case 'd': 1357b6ab19dSGarrett Wollman background = 0; 1367b6ab19dSGarrett Wollman break; 1377b6ab19dSGarrett Wollman 1387b6ab19dSGarrett Wollman case 'g': 1397b6ab19dSGarrett Wollman bzero(&parm, sizeof(parm)); 1407b6ab19dSGarrett Wollman parm.parm_d_metric = 1; 1417b6ab19dSGarrett Wollman p = check_parms(&parm); 1427b6ab19dSGarrett Wollman if (p != 0) 1437b6ab19dSGarrett Wollman msglog("bad -g: %s", p); 1447b6ab19dSGarrett Wollman else 1457b6ab19dSGarrett Wollman default_gateway = 1; 1467b6ab19dSGarrett Wollman break; 1477b6ab19dSGarrett Wollman 1487b6ab19dSGarrett Wollman case 'h': /* suppress extra host routes */ 1497b6ab19dSGarrett Wollman ridhosts = 1; 1507b6ab19dSGarrett Wollman break; 1517b6ab19dSGarrett Wollman 1527b6ab19dSGarrett Wollman case 'm': /* advertise host route */ 1537b6ab19dSGarrett Wollman mhome = 1; /* on multi-homed hosts */ 1547b6ab19dSGarrett Wollman break; 1557b6ab19dSGarrett Wollman 1567b6ab19dSGarrett Wollman case 'A': 1577b6ab19dSGarrett Wollman /* Ignore authentication if we do not care. 1587b6ab19dSGarrett Wollman * Crazy as it is, that is what RFC 1723 requires. 1597b6ab19dSGarrett Wollman */ 1607b6ab19dSGarrett Wollman auth_ok = 0; 1617b6ab19dSGarrett Wollman break; 1627b6ab19dSGarrett Wollman 1637b6ab19dSGarrett Wollman case 't': 1647b6ab19dSGarrett Wollman new_tracelevel++; 1657b6ab19dSGarrett Wollman break; 1667b6ab19dSGarrett Wollman 1677b6ab19dSGarrett Wollman case 'T': 1687b6ab19dSGarrett Wollman tracename = optarg; 1697b6ab19dSGarrett Wollman break; 1707b6ab19dSGarrett Wollman 1717b6ab19dSGarrett Wollman case 'F': /* minimal routes for SLIP */ 1727b6ab19dSGarrett Wollman n = HOPCNT_INFINITY-2; 1737b6ab19dSGarrett Wollman p = strchr(optarg,','); 1747b6ab19dSGarrett Wollman if (p && *p != '\0') { 1757b6ab19dSGarrett Wollman n = (int)strtoul(p+1, &q, 0); 1767b6ab19dSGarrett Wollman if (*q == '\0' 1777b6ab19dSGarrett Wollman && n <= HOPCNT_INFINITY-1 1787b6ab19dSGarrett Wollman && n >= 1) 1797b6ab19dSGarrett Wollman *p = '\0'; 1807b6ab19dSGarrett Wollman } 1817b6ab19dSGarrett Wollman if (!getnet(optarg, &p_addr, &p_mask)) { 1827b6ab19dSGarrett Wollman msglog("bad network; \"-F %s\"", 1837b6ab19dSGarrett Wollman optarg); 1847b6ab19dSGarrett Wollman break; 1857b6ab19dSGarrett Wollman } 1867b6ab19dSGarrett Wollman bzero(&parm, sizeof(parm)); 1877b6ab19dSGarrett Wollman parm.parm_addr_h = ntohl(p_addr); 1887b6ab19dSGarrett Wollman parm.parm_mask = p_mask; 1897b6ab19dSGarrett Wollman parm.parm_d_metric = n; 1907b6ab19dSGarrett Wollman p = check_parms(&parm); 1917b6ab19dSGarrett Wollman if (p != 0) 1927b6ab19dSGarrett Wollman msglog("bad -F: %s", p); 1937b6ab19dSGarrett Wollman break; 1947b6ab19dSGarrett Wollman 1957b6ab19dSGarrett Wollman case 'P': 1967b6ab19dSGarrett Wollman /* handle arbirary, (usually) per-interface 1977b6ab19dSGarrett Wollman * parameters. 1987b6ab19dSGarrett Wollman */ 1997b6ab19dSGarrett Wollman p = parse_parms(optarg); 2007b6ab19dSGarrett Wollman if (p != 0) 2017b6ab19dSGarrett Wollman msglog("bad \"%s\" in \"%s\"", 2027b6ab19dSGarrett Wollman p, optarg); 2037b6ab19dSGarrett Wollman break; 2047b6ab19dSGarrett Wollman 2057b6ab19dSGarrett Wollman default: 2067b6ab19dSGarrett Wollman goto usage; 2077b6ab19dSGarrett Wollman } 2087b6ab19dSGarrett Wollman } 2097b6ab19dSGarrett Wollman argc -= optind; 2107b6ab19dSGarrett Wollman argv += optind; 2117b6ab19dSGarrett Wollman 2127b6ab19dSGarrett Wollman if (tracename == 0 && argc >= 1) { 2137b6ab19dSGarrett Wollman tracename = *argv++; 2147b6ab19dSGarrett Wollman argc--; 2157b6ab19dSGarrett Wollman } 2167b6ab19dSGarrett Wollman if (argc != 0) { 2177b6ab19dSGarrett Wollman usage: 2187b6ab19dSGarrett Wollman logbad(0, "usage: routed [-sqdghmpAt] [-T /tracefile]" 2197b6ab19dSGarrett Wollman " [-F net[,metric]] [-P parms]"); 2207b6ab19dSGarrett Wollman } 2217b6ab19dSGarrett Wollman if (geteuid() != 0) 2227b6ab19dSGarrett Wollman logbad(0, "requires UID 0"); 2237b6ab19dSGarrett Wollman 2247b6ab19dSGarrett Wollman mib[0] = CTL_NET; 2257b6ab19dSGarrett Wollman mib[1] = PF_INET; 2267b6ab19dSGarrett Wollman mib[2] = IPPROTO_IP; 2277b6ab19dSGarrett Wollman mib[3] = IPCTL_FORWARDING; 2287b6ab19dSGarrett Wollman len = sizeof(ipforwarding); 2297b6ab19dSGarrett Wollman if (sysctl(mib, 4, &ipforwarding, &len, 0, 0) < 0) 2307b6ab19dSGarrett Wollman LOGERR("sysctl(IPCTL_FORWARDING)"); 2317b6ab19dSGarrett Wollman 2327b6ab19dSGarrett Wollman if (!ipforwarding) { 2337b6ab19dSGarrett Wollman if (supplier) 2347b6ab19dSGarrett Wollman msglog("-s incompatible with ipforwarding=0"); 2357b6ab19dSGarrett Wollman if (default_gateway) { 2367b6ab19dSGarrett Wollman msglog("-g incompatible with ipforwarding=0"); 2377b6ab19dSGarrett Wollman default_gateway = 0; 2387b6ab19dSGarrett Wollman } 2397b6ab19dSGarrett Wollman supplier = 0; 2407b6ab19dSGarrett Wollman supplier_set = 1; 2417b6ab19dSGarrett Wollman } 2427b6ab19dSGarrett Wollman if (default_gateway) { 2437b6ab19dSGarrett Wollman if (supplier_set && !supplier) { 2447b6ab19dSGarrett Wollman msglog("-g and -q incompatible"); 2457b6ab19dSGarrett Wollman } else { 2467b6ab19dSGarrett Wollman supplier = 1; 2477b6ab19dSGarrett Wollman supplier_set = 1; 2487b6ab19dSGarrett Wollman } 2497b6ab19dSGarrett Wollman } 2507b6ab19dSGarrett Wollman 2517b6ab19dSGarrett Wollman 2527b6ab19dSGarrett Wollman signal(SIGALRM, sigalrm); 2537b6ab19dSGarrett Wollman if (!background) 2547b6ab19dSGarrett Wollman signal(SIGHUP, sigterm); /* SIGHUP fatal during debugging */ 2557b6ab19dSGarrett Wollman else 2567b6ab19dSGarrett Wollman signal(SIGHUP, SIG_IGN); 2577b6ab19dSGarrett Wollman signal(SIGTERM, sigterm); 2587b6ab19dSGarrett Wollman signal(SIGINT, sigterm); 2597b6ab19dSGarrett Wollman signal(SIGUSR1, sigtrace_on); 2607b6ab19dSGarrett Wollman signal(SIGUSR2, sigtrace_off); 2617b6ab19dSGarrett Wollman 2627b6ab19dSGarrett Wollman /* get into the background */ 2637b6ab19dSGarrett Wollman if (background) { 2647b6ab19dSGarrett Wollman #ifdef sgi 2657b6ab19dSGarrett Wollman if (0 > _daemonize(_DF_NOCHDIR, 2667b6ab19dSGarrett Wollman new_tracelevel == 0 ? -1 : STDOUT_FILENO, 2677b6ab19dSGarrett Wollman new_tracelevel == 0 ? -1 : STDERR_FILENO, 2687b6ab19dSGarrett Wollman -1)) 2697b6ab19dSGarrett Wollman BADERR(0, "_daemonize()"); 2707b6ab19dSGarrett Wollman #else 2717b6ab19dSGarrett Wollman if (daemon(1, 1) < 0) 2727b6ab19dSGarrett Wollman BADERR(0,"daemon()"); 2737b6ab19dSGarrett Wollman #endif 2747b6ab19dSGarrett Wollman } 2757b6ab19dSGarrett Wollman 2767b6ab19dSGarrett Wollman mypid = getpid(); 2777b6ab19dSGarrett Wollman srandom((int)(clk.tv_sec ^ clk.tv_usec ^ mypid)); 2787b6ab19dSGarrett Wollman 2797b6ab19dSGarrett Wollman /* prepare socket connected to the kernel. 2807b6ab19dSGarrett Wollman */ 2817b6ab19dSGarrett Wollman rt_sock = socket(AF_ROUTE, SOCK_RAW, 0); 2827b6ab19dSGarrett Wollman if (rt_sock < 0) 2837b6ab19dSGarrett Wollman BADERR(1,"rt_sock = socket()"); 2847b6ab19dSGarrett Wollman if (fcntl(rt_sock, F_SETFL, O_NONBLOCK) == -1) 2857b6ab19dSGarrett Wollman logbad(1, "fcntl(rt_sock) O_NONBLOCK: %s", strerror(errno)); 2867b6ab19dSGarrett Wollman off = 0; 2877b6ab19dSGarrett Wollman if (setsockopt(rt_sock, SOL_SOCKET,SO_USELOOPBACK, 2887b6ab19dSGarrett Wollman &off,sizeof(off)) < 0) 2897b6ab19dSGarrett Wollman LOGERR("setsockopt(SO_USELOOPBACK,0)"); 2907b6ab19dSGarrett Wollman 2917b6ab19dSGarrett Wollman fix_select(); 2927b6ab19dSGarrett Wollman 2937b6ab19dSGarrett Wollman 2947b6ab19dSGarrett Wollman if (background && new_tracelevel == 0) 2957b6ab19dSGarrett Wollman ftrace = 0; 2967b6ab19dSGarrett Wollman if (tracename != 0) { 2977b6ab19dSGarrett Wollman trace_on(tracename, 1); 2987b6ab19dSGarrett Wollman if (new_tracelevel == 0) /* use stdout if file is bad */ 2997b6ab19dSGarrett Wollman new_tracelevel = 1; 3007b6ab19dSGarrett Wollman } 3017b6ab19dSGarrett Wollman set_tracelevel(); 3027b6ab19dSGarrett Wollman 3037b6ab19dSGarrett Wollman /* initialize radix tree */ 3047b6ab19dSGarrett Wollman rtinit(); 3057b6ab19dSGarrett Wollman 3067b6ab19dSGarrett Wollman /* Pick a random part of the second for our output to minimize 3077b6ab19dSGarrett Wollman * collisions. 3087b6ab19dSGarrett Wollman * 3097b6ab19dSGarrett Wollman * Start broadcasting after hearing from other routers, and 3107b6ab19dSGarrett Wollman * at a random time so a bunch of systems do not get synchronized 3117b6ab19dSGarrett Wollman * after a power failure. 3127b6ab19dSGarrett Wollman */ 3137b6ab19dSGarrett Wollman intvl_random(&next_bcast, EPOCH+MIN_WAITTIME, EPOCH+SUPPLY_INTERVAL); 3147b6ab19dSGarrett Wollman age_timer.tv_usec = next_bcast.tv_usec; 3157b6ab19dSGarrett Wollman age_timer.tv_sec = EPOCH+MIN_WAITTIME; 3167b6ab19dSGarrett Wollman rdisc_timer = next_bcast; 3177b6ab19dSGarrett Wollman ifinit_timer.tv_usec = next_bcast.tv_usec; 3187b6ab19dSGarrett Wollman 3197b6ab19dSGarrett Wollman /* Collect an initial view of the world by checking the interface 3207b6ab19dSGarrett Wollman * configuration and the kludge file. 3217b6ab19dSGarrett Wollman */ 3227b6ab19dSGarrett Wollman gwkludge(); 3237b6ab19dSGarrett Wollman ifinit(); 3247b6ab19dSGarrett Wollman flush_kern(); 3257b6ab19dSGarrett Wollman 3267b6ab19dSGarrett Wollman /* Ask for routes */ 3277b6ab19dSGarrett Wollman rip_query(); 3287b6ab19dSGarrett Wollman if (!supplier) 3297b6ab19dSGarrett Wollman rdisc_sol(); 3307b6ab19dSGarrett Wollman 3317b6ab19dSGarrett Wollman /* Loop forever, listening and broadcasting. 3327b6ab19dSGarrett Wollman */ 3337b6ab19dSGarrett Wollman for (;;) { 3347b6ab19dSGarrett Wollman prev_clk = clk; 3357b6ab19dSGarrett Wollman gettimeofday(&clk, 0); 3367b6ab19dSGarrett Wollman timevalsub(&t2, &clk, &prev_clk); 3377b6ab19dSGarrett Wollman if (t2.tv_sec < 0 3387b6ab19dSGarrett Wollman || t2.tv_sec > wtime.tv_sec + 5) { 3397b6ab19dSGarrett Wollman /* Deal with time changes before other housekeeping to 3407b6ab19dSGarrett Wollman * keep everything straight. 3417b6ab19dSGarrett Wollman */ 3427b6ab19dSGarrett Wollman dt = t2.tv_sec; 3437b6ab19dSGarrett Wollman if (dt > 0) 3447b6ab19dSGarrett Wollman dt -= wtime.tv_sec; 3457b6ab19dSGarrett Wollman trace_act("time changed by %d sec\n", dt); 3467b6ab19dSGarrett Wollman epoch.tv_sec += dt; 3477b6ab19dSGarrett Wollman } 3487b6ab19dSGarrett Wollman timevalsub(&now, &clk, &epoch); 3497b6ab19dSGarrett Wollman now_stale = now.tv_sec - STALE_TIME; 3507b6ab19dSGarrett Wollman now_expire = now.tv_sec - EXPIRE_TIME; 3517b6ab19dSGarrett Wollman now_garbage = now.tv_sec - GARBAGE_TIME; 3527b6ab19dSGarrett Wollman 3537b6ab19dSGarrett Wollman /* deal with interrupts that should affect tracing */ 3547b6ab19dSGarrett Wollman set_tracelevel(); 3557b6ab19dSGarrett Wollman 3567b6ab19dSGarrett Wollman if (stopint != 0) { 3577b6ab19dSGarrett Wollman if (supplier) { 3587b6ab19dSGarrett Wollman rip_bcast(0); 3597b6ab19dSGarrett Wollman rdisc_adv(); 3607b6ab19dSGarrett Wollman } 3617b6ab19dSGarrett Wollman trace_off("exiting with signal %d\n", stopint); 3627b6ab19dSGarrett Wollman exit(stopint | 128); 3637b6ab19dSGarrett Wollman } 3647b6ab19dSGarrett Wollman 3657b6ab19dSGarrett Wollman /* look for new or dead interfaces */ 3667b6ab19dSGarrett Wollman timevalsub(&wtime, &ifinit_timer, &now); 3677b6ab19dSGarrett Wollman if (wtime.tv_sec <= 0) { 3687b6ab19dSGarrett Wollman wtime.tv_sec = 0; 3697b6ab19dSGarrett Wollman ifinit(); 3707b6ab19dSGarrett Wollman rip_query(); 3717b6ab19dSGarrett Wollman continue; 3727b6ab19dSGarrett Wollman } 3737b6ab19dSGarrett Wollman 3747b6ab19dSGarrett Wollman /* If it is time, then broadcast our routes. 3757b6ab19dSGarrett Wollman */ 3767b6ab19dSGarrett Wollman if (supplier || advertise_mhome) { 3777b6ab19dSGarrett Wollman timevalsub(&t2, &next_bcast, &now); 3787b6ab19dSGarrett Wollman if (t2.tv_sec <= 0) { 3797b6ab19dSGarrett Wollman /* Synchronize the aging and broadcast 3807b6ab19dSGarrett Wollman * timers to minimize awakenings 3817b6ab19dSGarrett Wollman */ 3827b6ab19dSGarrett Wollman age(0); 3837b6ab19dSGarrett Wollman 3847b6ab19dSGarrett Wollman rip_bcast(0); 3857b6ab19dSGarrett Wollman 3867b6ab19dSGarrett Wollman /* It is desirable to send routing updates 3877b6ab19dSGarrett Wollman * regularly. So schedule the next update 3887b6ab19dSGarrett Wollman * 30 seconds after the previous one was 3897b6ab19dSGarrett Wollman * secheduled, instead of 30 seconds after 3907b6ab19dSGarrett Wollman * the previous update was finished. 3917b6ab19dSGarrett Wollman * Even if we just started after discovering 3927b6ab19dSGarrett Wollman * a 2nd interface or were otherwise delayed, 3937b6ab19dSGarrett Wollman * pick a 30-second aniversary of the 3947b6ab19dSGarrett Wollman * original broadcast time. 3957b6ab19dSGarrett Wollman */ 3967b6ab19dSGarrett Wollman n = 1 + (0-t2.tv_sec)/SUPPLY_INTERVAL; 3977b6ab19dSGarrett Wollman next_bcast.tv_sec += n*SUPPLY_INTERVAL; 3987b6ab19dSGarrett Wollman 3997b6ab19dSGarrett Wollman continue; 4007b6ab19dSGarrett Wollman } 4017b6ab19dSGarrett Wollman 4027b6ab19dSGarrett Wollman if (timercmp(&t2, &wtime, <)) 4037b6ab19dSGarrett Wollman wtime = t2; 4047b6ab19dSGarrett Wollman } 4057b6ab19dSGarrett Wollman 4067b6ab19dSGarrett Wollman /* If we need a flash update, either do it now or 4077b6ab19dSGarrett Wollman * set the delay to end when it is time. 4087b6ab19dSGarrett Wollman * 4097b6ab19dSGarrett Wollman * If we are within MIN_WAITTIME seconds of a full update, 4107b6ab19dSGarrett Wollman * do not bother. 4117b6ab19dSGarrett Wollman */ 4127b6ab19dSGarrett Wollman if (need_flash 4137b6ab19dSGarrett Wollman && supplier 4147b6ab19dSGarrett Wollman && no_flash.tv_sec+MIN_WAITTIME < next_bcast.tv_sec) { 4157b6ab19dSGarrett Wollman /* accurate to the millisecond */ 4167b6ab19dSGarrett Wollman if (!timercmp(&no_flash, &now, >)) 4177b6ab19dSGarrett Wollman rip_bcast(1); 4187b6ab19dSGarrett Wollman timevalsub(&t2, &no_flash, &now); 4197b6ab19dSGarrett Wollman if (timercmp(&t2, &wtime, <)) 4207b6ab19dSGarrett Wollman wtime = t2; 4217b6ab19dSGarrett Wollman } 4227b6ab19dSGarrett Wollman 4237b6ab19dSGarrett Wollman /* trigger the main aging timer. 4247b6ab19dSGarrett Wollman */ 4257b6ab19dSGarrett Wollman timevalsub(&t2, &age_timer, &now); 4267b6ab19dSGarrett Wollman if (t2.tv_sec <= 0) { 4277b6ab19dSGarrett Wollman age(0); 4287b6ab19dSGarrett Wollman continue; 4297b6ab19dSGarrett Wollman } 4307b6ab19dSGarrett Wollman if (timercmp(&t2, &wtime, <)) 4317b6ab19dSGarrett Wollman wtime = t2; 4327b6ab19dSGarrett Wollman 4337b6ab19dSGarrett Wollman /* update the kernel routing table 4347b6ab19dSGarrett Wollman */ 4357b6ab19dSGarrett Wollman timevalsub(&t2, &need_kern, &now); 4367b6ab19dSGarrett Wollman if (t2.tv_sec <= 0) { 4377b6ab19dSGarrett Wollman age(0); 4387b6ab19dSGarrett Wollman continue; 4397b6ab19dSGarrett Wollman } 4407b6ab19dSGarrett Wollman if (timercmp(&t2, &wtime, <)) 4417b6ab19dSGarrett Wollman wtime = t2; 4427b6ab19dSGarrett Wollman 4437b6ab19dSGarrett Wollman /* take care of router discovery, 4447b6ab19dSGarrett Wollman * but do it to the millisecond 4457b6ab19dSGarrett Wollman */ 4467b6ab19dSGarrett Wollman if (!timercmp(&rdisc_timer, &now, >)) { 4477b6ab19dSGarrett Wollman rdisc_age(0); 4487b6ab19dSGarrett Wollman continue; 4497b6ab19dSGarrett Wollman } 4507b6ab19dSGarrett Wollman timevalsub(&t2, &rdisc_timer, &now); 4517b6ab19dSGarrett Wollman if (timercmp(&t2, &wtime, <)) 4527b6ab19dSGarrett Wollman wtime = t2; 4537b6ab19dSGarrett Wollman 4547b6ab19dSGarrett Wollman 4557b6ab19dSGarrett Wollman /* wait for input or a timer to expire. 4567b6ab19dSGarrett Wollman */ 4577b6ab19dSGarrett Wollman trace_flush(); 4587b6ab19dSGarrett Wollman ibits = fdbits; 4597b6ab19dSGarrett Wollman n = select(sock_max, &ibits, 0, 0, &wtime); 4607b6ab19dSGarrett Wollman if (n <= 0) { 4617b6ab19dSGarrett Wollman if (n < 0 && errno != EINTR && errno != EAGAIN) 4627b6ab19dSGarrett Wollman BADERR(1,"select"); 4637b6ab19dSGarrett Wollman continue; 4647b6ab19dSGarrett Wollman } 4657b6ab19dSGarrett Wollman 4667b6ab19dSGarrett Wollman if (FD_ISSET(rt_sock, &ibits)) { 4677b6ab19dSGarrett Wollman read_rt(); 4687b6ab19dSGarrett Wollman n--; 4697b6ab19dSGarrett Wollman } 4707b6ab19dSGarrett Wollman if (rdisc_sock >= 0 && FD_ISSET(rdisc_sock, &ibits)) { 4717b6ab19dSGarrett Wollman read_d(); 4727b6ab19dSGarrett Wollman n--; 4737b6ab19dSGarrett Wollman } 4747b6ab19dSGarrett Wollman if (rip_sock >= 0 && FD_ISSET(rip_sock, &ibits)) { 4757b6ab19dSGarrett Wollman read_rip(rip_sock, 0); 4767b6ab19dSGarrett Wollman n--; 4777b6ab19dSGarrett Wollman } 4787b6ab19dSGarrett Wollman 4797b6ab19dSGarrett Wollman for (ifp = ifnet; n > 0 && 0 != ifp; ifp = ifp->int_next) { 4807b6ab19dSGarrett Wollman if (ifp->int_rip_sock >= 0 4817b6ab19dSGarrett Wollman && FD_ISSET(ifp->int_rip_sock, &ibits)) { 4827b6ab19dSGarrett Wollman read_rip(ifp->int_rip_sock, ifp); 4837b6ab19dSGarrett Wollman n--; 4847b6ab19dSGarrett Wollman } 4857b6ab19dSGarrett Wollman } 4867b6ab19dSGarrett Wollman } 4877b6ab19dSGarrett Wollman } 4887b6ab19dSGarrett Wollman 4897b6ab19dSGarrett Wollman 4907b6ab19dSGarrett Wollman /* ARGSUSED */ 4917b6ab19dSGarrett Wollman void 4927b6ab19dSGarrett Wollman sigalrm(int sig) 4937b6ab19dSGarrett Wollman { 4947b6ab19dSGarrett Wollman /* Historically, SIGALRM would cause the daemon to check for 4957b6ab19dSGarrett Wollman * new and broken interfaces. 4967b6ab19dSGarrett Wollman */ 4977b6ab19dSGarrett Wollman ifinit_timer.tv_sec = now.tv_sec; 4987b6ab19dSGarrett Wollman trace_act("SIGALRM\n"); 4997b6ab19dSGarrett Wollman } 5007b6ab19dSGarrett Wollman 5017b6ab19dSGarrett Wollman 5027b6ab19dSGarrett Wollman /* watch for fatal signals */ 5037b6ab19dSGarrett Wollman void 5047b6ab19dSGarrett Wollman sigterm(int sig) 5057b6ab19dSGarrett Wollman { 5067b6ab19dSGarrett Wollman stopint = sig; 5077b6ab19dSGarrett Wollman (void)signal(sig, SIG_DFL); /* catch it only once */ 5087b6ab19dSGarrett Wollman } 5097b6ab19dSGarrett Wollman 5107b6ab19dSGarrett Wollman 5117b6ab19dSGarrett Wollman void 5127b6ab19dSGarrett Wollman fix_select(void) 5137b6ab19dSGarrett Wollman { 5147b6ab19dSGarrett Wollman struct interface *ifp; 5157b6ab19dSGarrett Wollman 5167b6ab19dSGarrett Wollman 5177b6ab19dSGarrett Wollman FD_ZERO(&fdbits); 5187b6ab19dSGarrett Wollman sock_max = 0; 5197b6ab19dSGarrett Wollman 5207b6ab19dSGarrett Wollman FD_SET(rt_sock, &fdbits); 5217b6ab19dSGarrett Wollman if (sock_max <= rt_sock) 5227b6ab19dSGarrett Wollman sock_max = rt_sock+1; 5237b6ab19dSGarrett Wollman if (rip_sock >= 0) { 5247b6ab19dSGarrett Wollman FD_SET(rip_sock, &fdbits); 5257b6ab19dSGarrett Wollman if (sock_max <= rip_sock) 5267b6ab19dSGarrett Wollman sock_max = rip_sock+1; 5277b6ab19dSGarrett Wollman } 5287b6ab19dSGarrett Wollman for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next) { 5297b6ab19dSGarrett Wollman if (ifp->int_rip_sock >= 0) { 5307b6ab19dSGarrett Wollman FD_SET(ifp->int_rip_sock, &fdbits); 5317b6ab19dSGarrett Wollman if (sock_max <= ifp->int_rip_sock) 5327b6ab19dSGarrett Wollman sock_max = ifp->int_rip_sock+1; 5337b6ab19dSGarrett Wollman } 5347b6ab19dSGarrett Wollman } 5357b6ab19dSGarrett Wollman if (rdisc_sock >= 0) { 5367b6ab19dSGarrett Wollman FD_SET(rdisc_sock, &fdbits); 5377b6ab19dSGarrett Wollman if (sock_max <= rdisc_sock) 5387b6ab19dSGarrett Wollman sock_max = rdisc_sock+1; 5397b6ab19dSGarrett Wollman } 5407b6ab19dSGarrett Wollman } 5417b6ab19dSGarrett Wollman 5427b6ab19dSGarrett Wollman 5437b6ab19dSGarrett Wollman void 5447b6ab19dSGarrett Wollman fix_sock(int sock, 5457b6ab19dSGarrett Wollman char *name) 5467b6ab19dSGarrett Wollman { 5477b6ab19dSGarrett Wollman int on; 5487b6ab19dSGarrett Wollman #define MIN_SOCKBUF (4*1024) 5497b6ab19dSGarrett Wollman static int rbuf; 5507b6ab19dSGarrett Wollman 5517b6ab19dSGarrett Wollman if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1) 5527b6ab19dSGarrett Wollman logbad(1, "fcntl(%s) O_NONBLOCK: %s", 5537b6ab19dSGarrett Wollman name, strerror(errno)); 5547b6ab19dSGarrett Wollman on = 1; 5557b6ab19dSGarrett Wollman if (setsockopt(sock, SOL_SOCKET,SO_BROADCAST, 5567b6ab19dSGarrett Wollman &on,sizeof(on)) < 0) 5577b6ab19dSGarrett Wollman msglog("setsockopt(%s,SO_BROADCAST): %s", 5587b6ab19dSGarrett Wollman name, strerror(errno)); 5597b6ab19dSGarrett Wollman if (rbuf >= MIN_SOCKBUF) { 5607b6ab19dSGarrett Wollman if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, 5617b6ab19dSGarrett Wollman &rbuf, sizeof(rbuf)) < 0) 5627b6ab19dSGarrett Wollman msglog("setsockopt(%s,SO_RCVBUF=%d): %s", 5637b6ab19dSGarrett Wollman name, rbuf, strerror(errno)); 5647b6ab19dSGarrett Wollman } else { 5657b6ab19dSGarrett Wollman for (rbuf = 60*1024; ; rbuf -= 4096) { 5667b6ab19dSGarrett Wollman if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, 5677b6ab19dSGarrett Wollman &rbuf, sizeof(rbuf)) == 0) { 5687b6ab19dSGarrett Wollman trace_act("RCVBUF=%d\n", rbuf); 5697b6ab19dSGarrett Wollman break; 5707b6ab19dSGarrett Wollman } 5717b6ab19dSGarrett Wollman if (rbuf < MIN_SOCKBUF) { 5727b6ab19dSGarrett Wollman msglog("setsockopt(%s,SO_RCVBUF = %d): %s", 5737b6ab19dSGarrett Wollman name, rbuf, strerror(errno)); 5747b6ab19dSGarrett Wollman break; 5757b6ab19dSGarrett Wollman } 5767b6ab19dSGarrett Wollman } 5777b6ab19dSGarrett Wollman } 5787b6ab19dSGarrett Wollman } 5797b6ab19dSGarrett Wollman 5807b6ab19dSGarrett Wollman 5817b6ab19dSGarrett Wollman /* get a rip socket 5827b6ab19dSGarrett Wollman */ 5837b6ab19dSGarrett Wollman static int /* <0 or file descriptor */ 5847b6ab19dSGarrett Wollman get_rip_sock(naddr addr, 5857b6ab19dSGarrett Wollman int serious) /* 1=failure to bind is serious */ 5867b6ab19dSGarrett Wollman { 5877b6ab19dSGarrett Wollman struct sockaddr_in sin; 5887b6ab19dSGarrett Wollman unsigned char ttl; 5897b6ab19dSGarrett Wollman int s; 5907b6ab19dSGarrett Wollman 5917b6ab19dSGarrett Wollman 5927b6ab19dSGarrett Wollman if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 5937b6ab19dSGarrett Wollman BADERR(1,"rip_sock = socket()"); 5947b6ab19dSGarrett Wollman 5957b6ab19dSGarrett Wollman bzero(&sin,sizeof(sin)); 5967b6ab19dSGarrett Wollman #ifdef _HAVE_SIN_LEN 5977b6ab19dSGarrett Wollman sin.sin_len = sizeof(sin); 5987b6ab19dSGarrett Wollman #endif 5997b6ab19dSGarrett Wollman sin.sin_family = AF_INET; 6007b6ab19dSGarrett Wollman sin.sin_port = htons(RIP_PORT); 6017b6ab19dSGarrett Wollman sin.sin_addr.s_addr = addr; 6027b6ab19dSGarrett Wollman if (bind(s, (struct sockaddr *)&sin,sizeof(sin)) < 0) { 6037b6ab19dSGarrett Wollman if (serious) 6047b6ab19dSGarrett Wollman BADERR(errno != EADDRINUSE, "bind(rip_sock)"); 6057b6ab19dSGarrett Wollman return -1; 6067b6ab19dSGarrett Wollman } 6077b6ab19dSGarrett Wollman fix_sock(s,"rip_sock"); 6087b6ab19dSGarrett Wollman 6097b6ab19dSGarrett Wollman ttl = 1; 6107b6ab19dSGarrett Wollman if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, 6117b6ab19dSGarrett Wollman &ttl, sizeof(ttl)) < 0) 6127b6ab19dSGarrett Wollman DBGERR(1,"rip_sock setsockopt(IP_MULTICAST_TTL)"); 6137b6ab19dSGarrett Wollman 6147b6ab19dSGarrett Wollman return s; 6157b6ab19dSGarrett Wollman } 6167b6ab19dSGarrett Wollman 6177b6ab19dSGarrett Wollman 6187b6ab19dSGarrett Wollman /* turn off main RIP socket */ 6197b6ab19dSGarrett Wollman void 6207b6ab19dSGarrett Wollman rip_off(void) 6217b6ab19dSGarrett Wollman { 6227b6ab19dSGarrett Wollman struct interface *ifp; 6237b6ab19dSGarrett Wollman register naddr addr; 6247b6ab19dSGarrett Wollman 6257b6ab19dSGarrett Wollman 6267b6ab19dSGarrett Wollman if (rip_sock >= 0 && !mhome) { 6277b6ab19dSGarrett Wollman trace_act("turn off RIP\n"); 6287b6ab19dSGarrett Wollman 6297b6ab19dSGarrett Wollman (void)close(rip_sock); 6307b6ab19dSGarrett Wollman rip_sock = -1; 6317b6ab19dSGarrett Wollman 6327b6ab19dSGarrett Wollman /* get non-broadcast sockets to listen to queries. 6337b6ab19dSGarrett Wollman */ 6347b6ab19dSGarrett Wollman for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) { 6357b6ab19dSGarrett Wollman if (ifp->int_rip_sock < 0 6367b6ab19dSGarrett Wollman && !(ifp->int_state & IS_ALIAS)) { 6377b6ab19dSGarrett Wollman addr = ((ifp->int_if_flags & IFF_POINTOPOINT) 6387b6ab19dSGarrett Wollman ? ifp->int_dstaddr 6397b6ab19dSGarrett Wollman : ifp->int_addr); 6407b6ab19dSGarrett Wollman ifp->int_rip_sock = get_rip_sock(addr, 0); 6417b6ab19dSGarrett Wollman } 6427b6ab19dSGarrett Wollman } 6437b6ab19dSGarrett Wollman 6447b6ab19dSGarrett Wollman fix_select(); 6457b6ab19dSGarrett Wollman 6467b6ab19dSGarrett Wollman age(0); 6477b6ab19dSGarrett Wollman } 6487b6ab19dSGarrett Wollman } 6497b6ab19dSGarrett Wollman 6507b6ab19dSGarrett Wollman 6517b6ab19dSGarrett Wollman /* turn on RIP multicast input via an interface 6527b6ab19dSGarrett Wollman */ 6537b6ab19dSGarrett Wollman static void 6547b6ab19dSGarrett Wollman rip_mcast_on(struct interface *ifp) 6557b6ab19dSGarrett Wollman { 6567b6ab19dSGarrett Wollman struct ip_mreq m; 6577b6ab19dSGarrett Wollman 6587b6ab19dSGarrett Wollman if (!IS_RIP_IN_OFF(ifp->int_state) 6597b6ab19dSGarrett Wollman && (ifp->int_if_flags & IFF_MULTICAST) 6607b6ab19dSGarrett Wollman #ifdef MCAST_PPP_BUG 6617b6ab19dSGarrett Wollman && !(ifp->int_if_flags & IFF_POINTOPOINT) 6627b6ab19dSGarrett Wollman #endif 6637b6ab19dSGarrett Wollman && !(ifp->int_state & IS_ALIAS)) { 6647b6ab19dSGarrett Wollman m.imr_multiaddr.s_addr = htonl(INADDR_RIP_GROUP); 6657b6ab19dSGarrett Wollman m.imr_interface.s_addr = ((ifp->int_if_flags & IFF_POINTOPOINT) 6667b6ab19dSGarrett Wollman ? ifp->int_dstaddr 6677b6ab19dSGarrett Wollman : ifp->int_addr); 6687b6ab19dSGarrett Wollman if (setsockopt(rip_sock,IPPROTO_IP, IP_ADD_MEMBERSHIP, 6697b6ab19dSGarrett Wollman &m, sizeof(m)) < 0) 6707b6ab19dSGarrett Wollman LOGERR("setsockopt(IP_ADD_MEMBERSHIP RIP)"); 6717b6ab19dSGarrett Wollman } 6727b6ab19dSGarrett Wollman } 6737b6ab19dSGarrett Wollman 6747b6ab19dSGarrett Wollman 6757b6ab19dSGarrett Wollman /* Prepare socket used for RIP. 6767b6ab19dSGarrett Wollman */ 6777b6ab19dSGarrett Wollman void 6787b6ab19dSGarrett Wollman rip_on(struct interface *ifp) 6797b6ab19dSGarrett Wollman { 6807b6ab19dSGarrett Wollman /* If the main RIP socket is already alive, only start receiving 6817b6ab19dSGarrett Wollman * multicasts for this interface. 6827b6ab19dSGarrett Wollman */ 6837b6ab19dSGarrett Wollman if (rip_sock >= 0) { 6847b6ab19dSGarrett Wollman if (ifp != 0) 6857b6ab19dSGarrett Wollman rip_mcast_on(ifp); 6867b6ab19dSGarrett Wollman return; 6877b6ab19dSGarrett Wollman } 6887b6ab19dSGarrett Wollman 6897b6ab19dSGarrett Wollman /* If the main RIP socket is off, and it makes sense to turn it on, 6907b6ab19dSGarrett Wollman * turn it on for all of the interfaces. 6917b6ab19dSGarrett Wollman */ 6927b6ab19dSGarrett Wollman if (rip_interfaces > 0 && !rdisc_ok) { 6937b6ab19dSGarrett Wollman trace_act("turn on RIP\n"); 6947b6ab19dSGarrett Wollman 6957b6ab19dSGarrett Wollman /* Close all of the query sockets so that we can open 6967b6ab19dSGarrett Wollman * the main socket. SO_REUSEPORT is not a solution, 6977b6ab19dSGarrett Wollman * since that would let two daemons bind to the broadcast 6987b6ab19dSGarrett Wollman * socket. 6997b6ab19dSGarrett Wollman */ 7007b6ab19dSGarrett Wollman for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) { 7017b6ab19dSGarrett Wollman if (ifp->int_rip_sock >= 0) { 7027b6ab19dSGarrett Wollman (void)close(ifp->int_rip_sock); 7037b6ab19dSGarrett Wollman ifp->int_rip_sock = -1; 7047b6ab19dSGarrett Wollman } 7057b6ab19dSGarrett Wollman } 7067b6ab19dSGarrett Wollman 7077b6ab19dSGarrett Wollman rip_sock = get_rip_sock(INADDR_ANY, 1); 7087b6ab19dSGarrett Wollman rip_sock_mcast = 0; 7097b6ab19dSGarrett Wollman 7107b6ab19dSGarrett Wollman /* Do not advertise anything until we have heard something 7117b6ab19dSGarrett Wollman */ 7127b6ab19dSGarrett Wollman if (next_bcast.tv_sec < now.tv_sec+MIN_WAITTIME) 7137b6ab19dSGarrett Wollman next_bcast.tv_sec = now.tv_sec+MIN_WAITTIME; 7147b6ab19dSGarrett Wollman 7157b6ab19dSGarrett Wollman for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) { 7167b6ab19dSGarrett Wollman if (!IS_RIP_IN_OFF(ifp->int_state)) 7177b6ab19dSGarrett Wollman ifp->int_state &= ~IS_RIP_QUERIED; 7187b6ab19dSGarrett Wollman rip_mcast_on(ifp); 7197b6ab19dSGarrett Wollman } 7207b6ab19dSGarrett Wollman 7217b6ab19dSGarrett Wollman ifinit_timer.tv_sec = now.tv_sec; 7227b6ab19dSGarrett Wollman 7237b6ab19dSGarrett Wollman fix_select(); 7247b6ab19dSGarrett Wollman 7257b6ab19dSGarrett Wollman } else if (ifp != 0 7267b6ab19dSGarrett Wollman && ifp->int_rip_sock < 0 7277b6ab19dSGarrett Wollman && !(ifp->int_state & IS_ALIAS)) { 7287b6ab19dSGarrett Wollman /* RIP is off, so ensure there are sockets on which 7297b6ab19dSGarrett Wollman * to listen for queries. 7307b6ab19dSGarrett Wollman */ 7317b6ab19dSGarrett Wollman ifp->int_rip_sock = get_rip_sock(ifp->int_addr, 0); 7327b6ab19dSGarrett Wollman 7337b6ab19dSGarrett Wollman fix_select(); 7347b6ab19dSGarrett Wollman } 7357b6ab19dSGarrett Wollman } 7367b6ab19dSGarrett Wollman 7377b6ab19dSGarrett Wollman 7387b6ab19dSGarrett Wollman /* die if malloc(3) fails 7397b6ab19dSGarrett Wollman */ 7407b6ab19dSGarrett Wollman void * 7417b6ab19dSGarrett Wollman rtmalloc(size_t size, 7427b6ab19dSGarrett Wollman char *msg) 7437b6ab19dSGarrett Wollman { 7447b6ab19dSGarrett Wollman void *p = malloc(size); 7457b6ab19dSGarrett Wollman if (p == 0) 7467b6ab19dSGarrett Wollman logbad(1,"malloc() failed in %s", msg); 7477b6ab19dSGarrett Wollman return p; 7487b6ab19dSGarrett Wollman } 7497b6ab19dSGarrett Wollman 7507b6ab19dSGarrett Wollman 7517b6ab19dSGarrett Wollman /* get a random instant in an interval 7527b6ab19dSGarrett Wollman */ 7537b6ab19dSGarrett Wollman void 7547b6ab19dSGarrett Wollman intvl_random(struct timeval *tp, /* put value here */ 7557b6ab19dSGarrett Wollman u_long lo, /* value is after this second */ 7567b6ab19dSGarrett Wollman u_long hi) /* and before this */ 7577b6ab19dSGarrett Wollman { 7587b6ab19dSGarrett Wollman tp->tv_sec = (time_t)(hi == lo 7597b6ab19dSGarrett Wollman ? lo 7607b6ab19dSGarrett Wollman : (lo + random() % ((hi - lo)))); 7617b6ab19dSGarrett Wollman tp->tv_usec = random() % 1000000; 7627b6ab19dSGarrett Wollman } 7637b6ab19dSGarrett Wollman 7647b6ab19dSGarrett Wollman 7657b6ab19dSGarrett Wollman void 7667b6ab19dSGarrett Wollman timevaladd(struct timeval *t1, 7677b6ab19dSGarrett Wollman struct timeval *t2) 7687b6ab19dSGarrett Wollman { 7697b6ab19dSGarrett Wollman 7707b6ab19dSGarrett Wollman t1->tv_sec += t2->tv_sec; 7717b6ab19dSGarrett Wollman if ((t1->tv_usec += t2->tv_usec) > 1000000) { 7727b6ab19dSGarrett Wollman t1->tv_sec++; 7737b6ab19dSGarrett Wollman t1->tv_usec -= 1000000; 7747b6ab19dSGarrett Wollman } 7757b6ab19dSGarrett Wollman } 7767b6ab19dSGarrett Wollman 7777b6ab19dSGarrett Wollman 7787b6ab19dSGarrett Wollman /* t1 = t2 - t3 7797b6ab19dSGarrett Wollman */ 7807b6ab19dSGarrett Wollman static void 7817b6ab19dSGarrett Wollman timevalsub(struct timeval *t1, 7827b6ab19dSGarrett Wollman struct timeval *t2, 7837b6ab19dSGarrett Wollman struct timeval *t3) 7847b6ab19dSGarrett Wollman { 7857b6ab19dSGarrett Wollman t1->tv_sec = t2->tv_sec - t3->tv_sec; 7867b6ab19dSGarrett Wollman if ((t1->tv_usec = t2->tv_usec - t3->tv_usec) < 0) { 7877b6ab19dSGarrett Wollman t1->tv_sec--; 7887b6ab19dSGarrett Wollman t1->tv_usec += 1000000; 7897b6ab19dSGarrett Wollman } 7907b6ab19dSGarrett Wollman } 7917b6ab19dSGarrett Wollman 7927b6ab19dSGarrett Wollman 7937b6ab19dSGarrett Wollman void 7947b6ab19dSGarrett Wollman msglog(char *p, ...) 7957b6ab19dSGarrett Wollman { 7967b6ab19dSGarrett Wollman va_list args; 7977b6ab19dSGarrett Wollman 7987b6ab19dSGarrett Wollman trace_flush(); 7997b6ab19dSGarrett Wollman 8007b6ab19dSGarrett Wollman va_start(args, p); 8017b6ab19dSGarrett Wollman vsyslog(LOG_ERR, p, args); 8027b6ab19dSGarrett Wollman 8037b6ab19dSGarrett Wollman if (ftrace != 0) { 8047b6ab19dSGarrett Wollman if (ftrace == stdout) 8057b6ab19dSGarrett Wollman (void)fputs("routed: ", ftrace); 8067b6ab19dSGarrett Wollman (void)vfprintf(ftrace, p, args); 8077b6ab19dSGarrett Wollman (void)fputc('\n', ftrace); 8087b6ab19dSGarrett Wollman } 8097b6ab19dSGarrett Wollman } 8107b6ab19dSGarrett Wollman 8117b6ab19dSGarrett Wollman 8127b6ab19dSGarrett Wollman void 8137b6ab19dSGarrett Wollman logbad(int dump, char *p, ...) 8147b6ab19dSGarrett Wollman { 8157b6ab19dSGarrett Wollman va_list args; 8167b6ab19dSGarrett Wollman 8177b6ab19dSGarrett Wollman trace_flush(); 8187b6ab19dSGarrett Wollman 8197b6ab19dSGarrett Wollman va_start(args, p); 8207b6ab19dSGarrett Wollman vsyslog(LOG_ERR, p, args); 8217b6ab19dSGarrett Wollman 8227b6ab19dSGarrett Wollman (void)fputs("routed: ", stderr); 8237b6ab19dSGarrett Wollman (void)vfprintf(stderr, p, args); 8247b6ab19dSGarrett Wollman (void)fputs("; giving up\n",stderr); 8257b6ab19dSGarrett Wollman (void)fflush(stderr); 8267b6ab19dSGarrett Wollman 8277b6ab19dSGarrett Wollman if (dump) 8287b6ab19dSGarrett Wollman abort(); 8297b6ab19dSGarrett Wollman exit(1); 8307b6ab19dSGarrett Wollman } 831