112651Skvn/*-
212651Skvn * SPDX-License-Identifier: BSD-3-Clause
312651Skvn *
412651Skvn * Copyright (c) 1983, 1988, 1993
512651Skvn *	The Regents of the University of California.  All rights reserved.
612651Skvn *
712651Skvn * Redistribution and use in source and binary forms, with or without
812651Skvn * modification, are permitted provided that the following conditions
912651Skvn * are met:
1012651Skvn * 1. Redistributions of source code must retain the above copyright
1112651Skvn *    notice, this list of conditions and the following disclaimer.
1212651Skvn * 2. Redistributions in binary form must reproduce the above copyright
1312651Skvn *    notice, this list of conditions and the following disclaimer in the
1412651Skvn *    documentation and/or other materials provided with the distribution.
1512651Skvn * 3. Neither the name of the University nor the names of its contributors
1612651Skvn *    may be used to endorse or promote products derived from this software
1712651Skvn *    without specific prior written permission.
1812651Skvn *
1912651Skvn * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2012651Skvn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2112651Skvn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2212651Skvn * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2312651Skvn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2412651Skvn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2512651Skvn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2612651Skvn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2712651Skvn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2812651Skvn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2912651Skvn * SUCH DAMAGE.
3012651Skvn */
3112651Skvn
3212651Skvn#include "defs.h"
3312651Skvn#include "pathnames.h"
3412651Skvn#include <signal.h>
3512651Skvn#include <fcntl.h>
3612651Skvn#include <sys/file.h>
3712651Skvn
3812651Skvnpid_t	mypid;
3912651Skvn
4012651Skvnnaddr	myaddr;				/* system address */
4112651Skvnstatic char myname[MAXHOSTNAMELEN+1];
4212651Skvn
4312651Skvnstatic int verbose;
4412651Skvn
4512651Skvnint	supplier;			/* supply or broadcast updates */
4612651Skvnint	supplier_set;
4712651Skvnstatic int ipforwarding = 1;		/* kernel forwarding on */
4812651Skvn
4912651Skvnstatic int default_gateway;		/* 1=advertise default */
5012651Skvnstatic int background = 1;
5112651Skvnint	ridhosts;			/* 1=reduce host routes */
5212651Skvnint	mhome;				/* 1=want multi-homed host route */
5312651Skvnint	advertise_mhome;		/* 1=must continue advertising it */
5412651Skvnint	auth_ok = 1;			/* 1=ignore auth if we do not care */
5512651Skvnint	insecure;			/* Reply to special queries or not */
5612651Skvn
5712651Skvnstruct timeval epoch;			/* when started */
5812651Skvnstruct timeval clk;
5912651Skvnstatic struct timeval prev_clk;
6012651Skvnstatic int usec_fudge;
6112651Skvnstruct timeval now;			/* current idea of time */
6212651Skvntime_t	now_stale;
6312651Skvntime_t	now_expire;
6412651Skvntime_t	now_garbage;
6512651Skvn
6612651Skvnstatic struct timeval next_bcast;	/* next general broadcast */
6712651Skvnstruct timeval no_flash = {		/* inhibit flash update */
6812651Skvn	EPOCH+SUPPLY_INTERVAL, 0
6912651Skvn};
7012651Skvn
7112651Skvnstatic struct timeval flush_kern_timer;
7212651Skvn
7312651Skvnstatic fd_set fdbits;
7412651Skvnstatic int sock_max;
7512651Skvnint	rip_sock = -1;			/* RIP socket */
7612651Skvnconst struct interface *rip_sock_mcast;	/* current multicast interface */
7712651Skvnint	rt_sock;			/* routing socket */
7812651Skvnint	rt_sock_seqno;
7912651Skvn
8012651Skvn
8112651Skvnstatic  int get_rip_sock(naddr, int);
8212651Skvnstatic void timevalsub(struct timeval *, struct timeval *, struct timeval *);
8312651Skvnstatic void sigalrm(int s UNUSED);
8412651Skvnstatic void sigterm(int sig);
8512651Skvn
8612651Skvnint
8712651Skvnmain(int argc,
8812651Skvn     char *argv[])
8912651Skvn{
9012651Skvn	int n, mib[4], off;
9112651Skvn	size_t len;
9212651Skvn	char *p, *q;
9312651Skvn	const char *cp;
9412651Skvn	struct timeval wtime, t2;
9512651Skvn	time_t dt;
9612651Skvn	fd_set ibits;
9712651Skvn	naddr p_net, p_mask;
9812651Skvn	struct interface *ifp;
9912651Skvn	struct parm parm;
10012651Skvn	char *tracename = 0;
10112651Skvn
10212651Skvn
10312651Skvn	/* Some shells are badly broken and send SIGHUP to backgrounded
10412651Skvn	 * processes.
10512651Skvn	 */
10612651Skvn	signal(SIGHUP, SIG_IGN);
10712651Skvn
10812651Skvn	openlog("routed", LOG_PID, LOG_DAEMON);
10912651Skvn	ftrace = stdout;
11012651Skvn
11112651Skvn	gettimeofday(&clk, 0);
11212651Skvn	prev_clk = clk;
11312651Skvn	epoch = clk;
11412651Skvn	epoch.tv_sec -= EPOCH;
11512651Skvn	now.tv_sec = EPOCH;
11612651Skvn	now_stale = EPOCH - STALE_TIME;
11712651Skvn	now_expire = EPOCH - EXPIRE_TIME;
11812651Skvn	now_garbage = EPOCH - GARBAGE_TIME;
11912651Skvn	wtime.tv_sec = 0;
12012651Skvn
12112651Skvn	(void)gethostname(myname, sizeof(myname)-1);
12212651Skvn	(void)gethost(myname, &myaddr);
12312651Skvn
12412651Skvn	while ((n = getopt(argc, argv, "isqdghmAtvT:F:P:")) != -1) {
12512651Skvn		switch (n) {
12612651Skvn		case 'i':
12712651Skvn			insecure++;
12812651Skvn			break;
12912651Skvn		case 's':
13012651Skvn			supplier = 1;
13112651Skvn			supplier_set = 1;
13212651Skvn			break;
13312651Skvn
13412651Skvn		case 'q':
13512651Skvn			supplier = 0;
13612651Skvn			supplier_set = 1;
13712651Skvn			break;
13812651Skvn
13912651Skvn		case 'd':
14012651Skvn			background = 0;
14112651Skvn			break;
14212651Skvn
14312651Skvn		case 'g':
14412651Skvn			memset(&parm, 0, sizeof(parm));
14512651Skvn			parm.parm_d_metric = 1;
14612651Skvn			cp = check_parms(&parm);
14712651Skvn			if (cp != 0)
14812651Skvn				msglog("bad -g: %s", cp);
14912651Skvn			else
15012651Skvn				default_gateway = 1;
15112651Skvn			break;
15212651Skvn
15312651Skvn		case 'h':		/* suppress extra host routes */
15412651Skvn			ridhosts = 1;
15512651Skvn			break;
15612651Skvn
15712651Skvn		case 'm':		/* advertise host route */
15812651Skvn			mhome = 1;	/* on multi-homed hosts */
15912651Skvn			break;
16012651Skvn
16112651Skvn		case 'A':
16212651Skvn			/* Ignore authentication if we do not care.
16312651Skvn			 * Crazy as it is, that is what RFC 1723 requires.
16412651Skvn			 */
16512651Skvn			auth_ok = 0;
16612651Skvn			break;
16712651Skvn
16812651Skvn		case 't':
16912651Skvn			new_tracelevel++;
17012651Skvn			break;
17112651Skvn
17212651Skvn		case 'T':
17312651Skvn			tracename = optarg;
17412651Skvn			break;
17512651Skvn
17612651Skvn		case 'F':		/* minimal routes for SLIP */
17712651Skvn			n = FAKE_METRIC;
17812651Skvn			p = strchr(optarg,',');
17912651Skvn			if (p && *p != '\0') {
18012651Skvn				n = (int)strtoul(p+1, &q, 0);
18112651Skvn				if (*q == '\0'
18212651Skvn				    && n <= HOPCNT_INFINITY-1
18312651Skvn				    && n >= 1)
18412651Skvn					*p = '\0';
18512651Skvn			}
18612651Skvn			if (!getnet(optarg, &p_net, &p_mask)) {
18712651Skvn				msglog("bad network; \"-F %s\"",
18812651Skvn				       optarg);
18912651Skvn				break;
19012651Skvn			}
19112651Skvn			memset(&parm, 0, sizeof(parm));
192			parm.parm_net = p_net;
193			parm.parm_mask = p_mask;
194			parm.parm_d_metric = n;
195			cp = check_parms(&parm);
196			if (cp != 0)
197				msglog("bad -F: %s", cp);
198			break;
199
200		case 'P':
201			/* handle arbitrary parameters.
202			 */
203			q = strdup(optarg);
204			cp = parse_parms(q, 0);
205			if (cp != 0)
206				msglog("%s in \"-P %s\"", cp, optarg);
207			free(q);
208			break;
209
210		case 'v':
211			/* display version */
212			verbose++;
213			msglog("version 2.31");
214			break;
215
216		default:
217			goto usage;
218		}
219	}
220	argc -= optind;
221	argv += optind;
222
223	if (tracename == 0 && argc >= 1) {
224		tracename = *argv++;
225		argc--;
226	}
227	if (tracename != 0 && tracename[0] == '\0')
228		goto usage;
229	if (argc != 0) {
230usage:
231		logbad(0, "usage: routed [-sqdghmAtv] [-T tracefile]"
232		       " [-F net[,metric]] [-P parms]");
233	}
234	if (geteuid() != 0) {
235		if (verbose)
236			exit(0);
237		logbad(0, "requires UID 0");
238	}
239
240	mib[0] = CTL_NET;
241	mib[1] = PF_INET;
242	mib[2] = IPPROTO_IP;
243	mib[3] = IPCTL_FORWARDING;
244	len = sizeof(ipforwarding);
245	if (sysctl(mib, 4, &ipforwarding, &len, 0, 0) < 0)
246		LOGERR("sysctl(IPCTL_FORWARDING)");
247
248	if (!ipforwarding) {
249		if (supplier)
250			msglog("-s incompatible with ipforwarding=0");
251		if (default_gateway) {
252			msglog("-g incompatible with ipforwarding=0");
253			default_gateway = 0;
254		}
255		supplier = 0;
256		supplier_set = 1;
257	}
258	if (default_gateway) {
259		if (supplier_set && !supplier) {
260			msglog("-g and -q incompatible");
261		} else {
262			supplier = 1;
263			supplier_set = 1;
264		}
265	}
266
267
268	signal(SIGALRM, sigalrm);
269	if (!background)
270		signal(SIGHUP, sigterm);    /* SIGHUP fatal during debugging */
271	signal(SIGTERM, sigterm);
272	signal(SIGINT, sigterm);
273	signal(SIGUSR1, sigtrace_on);
274	signal(SIGUSR2, sigtrace_off);
275
276	/* get into the background */
277	if (background && daemon(0, 1) < 0)
278		BADERR(0,"daemon()");
279
280	mypid = getpid();
281
282	/* prepare socket connected to the kernel.
283	 */
284	rt_sock = socket(AF_ROUTE, SOCK_RAW, 0);
285	if (rt_sock < 0)
286		BADERR(1,"rt_sock = socket()");
287	if (fcntl(rt_sock, F_SETFL, O_NONBLOCK) == -1)
288		logbad(1, "fcntl(rt_sock) O_NONBLOCK: %s", strerror(errno));
289	off = 0;
290	if (setsockopt(rt_sock, SOL_SOCKET,SO_USELOOPBACK,
291		       &off,sizeof(off)) < 0)
292		LOGERR("setsockopt(SO_USELOOPBACK,0)");
293
294	fix_select();
295
296
297	if (tracename != 0) {
298		strncpy(inittracename, tracename, sizeof(inittracename)-1);
299		set_tracefile(inittracename, "%s", -1);
300	} else {
301		tracelevel_msg("%s", -1);   /* turn on tracing to stdio */
302	}
303
304	bufinit();
305
306	/* initialize radix tree */
307	rtinit();
308
309	/* Pick a random part of the second for our output to minimize
310	 * collisions.
311	 *
312	 * Start broadcasting after hearing from other routers, and
313	 * at a random time so a bunch of systems do not get synchronized
314	 * after a power failure.
315	 */
316	intvl_random(&next_bcast, EPOCH+MIN_WAITTIME, EPOCH+SUPPLY_INTERVAL);
317	age_timer.tv_usec = next_bcast.tv_usec;
318	age_timer.tv_sec = EPOCH+MIN_WAITTIME;
319	rdisc_timer = next_bcast;
320	ifinit_timer.tv_usec = next_bcast.tv_usec;
321
322	/* Collect an initial view of the world by checking the interface
323	 * configuration and the kludge file.
324	 */
325	gwkludge();
326	ifinit();
327
328	/* Ask for routes */
329	rip_query();
330	rdisc_sol();
331
332	/* Now turn off stdio if not tracing */
333	if (new_tracelevel == 0)
334		trace_close(background);
335
336	/* Loop forever, listening and broadcasting.
337	 */
338	for (;;) {
339		prev_clk = clk;
340		gettimeofday(&clk, 0);
341		if (prev_clk.tv_sec == clk.tv_sec
342		    && prev_clk.tv_usec == clk.tv_usec+usec_fudge) {
343			/* Much of `routed` depends on time always advancing.
344			 * On systems that do not guarantee that gettimeofday()
345			 * produces unique timestamps even if called within
346			 * a single tick, use trickery like that in classic
347			 * BSD kernels.
348			 */
349			clk.tv_usec += ++usec_fudge;
350
351		} else {
352			usec_fudge = 0;
353
354			timevalsub(&t2, &clk, &prev_clk);
355			if (t2.tv_sec < 0
356			    || t2.tv_sec > wtime.tv_sec + 5) {
357				/* Deal with time changes before other
358				 * housekeeping to keep everything straight.
359				 */
360				dt = t2.tv_sec;
361				if (dt > 0)
362					dt -= wtime.tv_sec;
363				trace_act("time changed by %d sec", (int)dt);
364				epoch.tv_sec += dt;
365			}
366		}
367		timevalsub(&now, &clk, &epoch);
368		now_stale = now.tv_sec - STALE_TIME;
369		now_expire = now.tv_sec - EXPIRE_TIME;
370		now_garbage = now.tv_sec - GARBAGE_TIME;
371
372		/* deal with signals that should affect tracing */
373		set_tracelevel();
374
375		if (stopint != 0) {
376			rip_bcast(0);
377			rdisc_adv();
378			trace_off("exiting with signal %d", stopint);
379			exit(stopint | 128);
380		}
381
382		/* look for new or dead interfaces */
383		timevalsub(&wtime, &ifinit_timer, &now);
384		if (wtime.tv_sec <= 0) {
385			wtime.tv_sec = 0;
386			ifinit();
387			rip_query();
388			continue;
389		}
390
391		/* Check the kernel table occasionally for mysteriously
392		 * evaporated routes
393		 */
394		timevalsub(&t2, &flush_kern_timer, &now);
395		if (t2.tv_sec <= 0) {
396			flush_kern();
397			flush_kern_timer.tv_sec = (now.tv_sec
398						   + CHECK_QUIET_INTERVAL);
399			continue;
400		}
401		if (timercmp(&t2, &wtime, <))
402			wtime = t2;
403
404		/* If it is time, then broadcast our routes.
405		 */
406		if (supplier || advertise_mhome) {
407			timevalsub(&t2, &next_bcast, &now);
408			if (t2.tv_sec <= 0) {
409				/* Synchronize the aging and broadcast
410				 * timers to minimize awakenings
411				 */
412				age(0);
413
414				rip_bcast(0);
415
416				/* It is desirable to send routing updates
417				 * regularly.  So schedule the next update
418				 * 30 seconds after the previous one was
419				 * scheduled, instead of 30 seconds after
420				 * the previous update was finished.
421				 * Even if we just started after discovering
422				 * a 2nd interface or were otherwise delayed,
423				 * pick a 30-second anniversary of the
424				 * original broadcast time.
425				 */
426				n = 1 + (0-t2.tv_sec)/SUPPLY_INTERVAL;
427				next_bcast.tv_sec += n*SUPPLY_INTERVAL;
428
429				continue;
430			}
431
432			if (timercmp(&t2, &wtime, <))
433				wtime = t2;
434		}
435
436		/* If we need a flash update, either do it now or
437		 * set the delay to end when it is time.
438		 *
439		 * If we are within MIN_WAITTIME seconds of a full update,
440		 * do not bother.
441		 */
442		if (need_flash
443		    && supplier
444		    && no_flash.tv_sec+MIN_WAITTIME < next_bcast.tv_sec) {
445			/* accurate to the millisecond */
446			if (!timercmp(&no_flash, &now, >))
447				rip_bcast(1);
448			timevalsub(&t2, &no_flash, &now);
449			if (timercmp(&t2, &wtime, <))
450				wtime = t2;
451		}
452
453		/* trigger the main aging timer.
454		 */
455		timevalsub(&t2, &age_timer, &now);
456		if (t2.tv_sec <= 0) {
457			age(0);
458			continue;
459		}
460		if (timercmp(&t2, &wtime, <))
461			wtime = t2;
462
463		/* update the kernel routing table
464		 */
465		timevalsub(&t2, &need_kern, &now);
466		if (t2.tv_sec <= 0) {
467			age(0);
468			continue;
469		}
470		if (timercmp(&t2, &wtime, <))
471			wtime = t2;
472
473		/* take care of router discovery,
474		 * but do it in the correct the millisecond
475		 */
476		if (!timercmp(&rdisc_timer, &now, >)) {
477			rdisc_age(0);
478			continue;
479		}
480		timevalsub(&t2, &rdisc_timer, &now);
481		if (timercmp(&t2, &wtime, <))
482			wtime = t2;
483
484
485		/* wait for input or a timer to expire.
486		 */
487		trace_flush();
488		ibits = fdbits;
489		n = select(sock_max, &ibits, 0, 0, &wtime);
490		if (n <= 0) {
491			if (n < 0 && errno != EINTR && errno != EAGAIN)
492				BADERR(1,"select");
493			continue;
494		}
495
496		if (FD_ISSET(rt_sock, &ibits)) {
497			read_rt();
498			n--;
499		}
500		if (rdisc_sock >= 0 && FD_ISSET(rdisc_sock, &ibits)) {
501			read_d();
502			n--;
503		}
504		if (rip_sock >= 0 && FD_ISSET(rip_sock, &ibits)) {
505			read_rip(rip_sock, 0);
506			n--;
507		}
508
509		LIST_FOREACH(ifp, &ifnet, int_list) {
510			if (n <= 0)
511				break;
512			if (ifp->int_rip_sock >= 0
513			    && FD_ISSET(ifp->int_rip_sock, &ibits)) {
514				read_rip(ifp->int_rip_sock, ifp);
515				n--;
516			}
517		}
518	}
519}
520
521
522/* ARGSUSED */
523static void
524sigalrm(int s UNUSED)
525{
526	/* Historically, SIGALRM would cause the daemon to check for
527	 * new and broken interfaces.
528	 */
529	ifinit_timer.tv_sec = now.tv_sec;
530	trace_act("SIGALRM");
531}
532
533
534/* watch for fatal signals */
535static void
536sigterm(int sig)
537{
538	stopint = sig;
539	(void)signal(sig, SIG_DFL);	/* catch it only once */
540}
541
542
543void
544fix_select(void)
545{
546	struct interface *ifp;
547
548
549	FD_ZERO(&fdbits);
550	sock_max = 0;
551
552	FD_SET(rt_sock, &fdbits);
553	if (sock_max <= rt_sock)
554		sock_max = rt_sock+1;
555	if (rip_sock >= 0) {
556		FD_SET(rip_sock, &fdbits);
557		if (sock_max <= rip_sock)
558			sock_max = rip_sock+1;
559	}
560	LIST_FOREACH(ifp, &ifnet, int_list) {
561		if (ifp->int_rip_sock >= 0) {
562			FD_SET(ifp->int_rip_sock, &fdbits);
563			if (sock_max <= ifp->int_rip_sock)
564				sock_max = ifp->int_rip_sock+1;
565		}
566	}
567	if (rdisc_sock >= 0) {
568		FD_SET(rdisc_sock, &fdbits);
569		if (sock_max <= rdisc_sock)
570			sock_max = rdisc_sock+1;
571	}
572}
573
574
575void
576fix_sock(int sock,
577	 const char *name)
578{
579	int on;
580#define MIN_SOCKBUF (4*1024)
581	static int rbuf;
582
583	if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
584		logbad(1, "fcntl(%s) O_NONBLOCK: %s",
585		       name, strerror(errno));
586	on = 1;
587	if (setsockopt(sock, SOL_SOCKET,SO_BROADCAST, &on,sizeof(on)) < 0)
588		msglog("setsockopt(%s,SO_BROADCAST): %s",
589		       name, strerror(errno));
590#ifdef USE_PASSIFNAME
591	on = 1;
592	if (setsockopt(sock, SOL_SOCKET, SO_PASSIFNAME, &on,sizeof(on)) < 0)
593		msglog("setsockopt(%s,SO_PASSIFNAME): %s",
594		       name, strerror(errno));
595#endif
596
597	if (rbuf >= MIN_SOCKBUF) {
598		if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
599			       &rbuf, sizeof(rbuf)) < 0)
600			msglog("setsockopt(%s,SO_RCVBUF=%d): %s",
601			       name, rbuf, strerror(errno));
602	} else {
603		for (rbuf = 60*1024; ; rbuf -= 4096) {
604			if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
605				       &rbuf, sizeof(rbuf)) == 0) {
606				trace_act("RCVBUF=%d", rbuf);
607				break;
608			}
609			if (rbuf < MIN_SOCKBUF) {
610				msglog("setsockopt(%s,SO_RCVBUF = %d): %s",
611				       name, rbuf, strerror(errno));
612				break;
613			}
614		}
615	}
616}
617
618
619/* get a rip socket
620 */
621static int				/* <0 or file descriptor */
622get_rip_sock(naddr addr,
623	     int serious)		/* 1=failure to bind is serious */
624{
625	struct sockaddr_in rsin;
626	unsigned char ttl;
627	int s;
628
629
630	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
631		BADERR(1,"rip_sock = socket()");
632
633	memset(&rsin, 0, sizeof(rsin));
634#ifdef _HAVE_SIN_LEN
635	rsin.sin_len = sizeof(rsin);
636#endif
637	rsin.sin_family = AF_INET;
638	rsin.sin_port = htons(RIP_PORT);
639	rsin.sin_addr.s_addr = addr;
640	if (bind(s, (struct sockaddr *)&rsin, sizeof(rsin)) < 0) {
641		if (serious)
642			BADERR(errno != EADDRINUSE, "bind(rip_sock)");
643		close(s);
644		return -1;
645	}
646	fix_sock(s,"rip_sock");
647
648	ttl = 1;
649	if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL,
650		       &ttl, sizeof(ttl)) < 0)
651		DBGERR(1,"rip_sock setsockopt(IP_MULTICAST_TTL)");
652
653	return s;
654}
655
656
657/* turn off main RIP socket */
658void
659rip_off(void)
660{
661	struct interface *ifp;
662	naddr addr;
663
664
665	if (rip_sock >= 0 && !mhome) {
666		trace_act("turn off RIP");
667
668		(void)close(rip_sock);
669		rip_sock = -1;
670
671		/* get non-broadcast sockets to listen to queries.
672		 */
673		LIST_FOREACH(ifp, &ifnet, int_list) {
674			if (ifp->int_state & IS_REMOTE)
675				continue;
676			if (ifp->int_rip_sock < 0) {
677				addr = ((ifp->int_if_flags & IFF_POINTOPOINT)
678					? ifp->int_dstaddr
679					: ifp->int_addr);
680				ifp->int_rip_sock = get_rip_sock(addr, 0);
681			}
682		}
683
684		fix_select();
685
686		age(0);
687	}
688}
689
690
691/* turn on RIP multicast input via an interface
692 */
693static void
694rip_mcast_on(struct interface *ifp)
695{
696	struct group_req gr;
697	struct sockaddr_in *sin;
698
699	if (!IS_RIP_IN_OFF(ifp->int_state)
700	    && (ifp->int_if_flags & IFF_MULTICAST)
701	    && !(ifp->int_state & IS_ALIAS)) {
702		memset(&gr, 0, sizeof(gr));
703		gr.gr_interface = ifp->int_index;
704		sin = (struct sockaddr_in *)&gr.gr_group;
705		sin->sin_family = AF_INET;
706#ifdef _HAVE_SIN_LEN
707		sin->sin_len = sizeof(struct sockaddr_in);
708#endif
709		sin->sin_addr.s_addr = htonl(INADDR_RIP_GROUP);
710		if (setsockopt(rip_sock, IPPROTO_IP, MCAST_JOIN_GROUP,
711			       &gr, sizeof(gr)) < 0)
712			LOGERR("setsockopt(MCAST_JOIN_GROUP RIP)");
713	}
714}
715
716
717/* Prepare socket used for RIP.
718 */
719void
720rip_on(struct interface *ifp)
721{
722	/* If the main RIP socket is already alive, only start receiving
723	 * multicasts for this interface.
724	 */
725	if (rip_sock >= 0) {
726		if (ifp != NULL)
727			rip_mcast_on(ifp);
728		return;
729	}
730
731	/* If the main RIP socket is off and it makes sense to turn it on,
732	 * then turn it on for all of the interfaces.
733	 * It makes sense if either router discovery is off, or if
734	 * router discover is on and at most one interface is doing RIP.
735	 */
736	if (rip_interfaces > 0 && (!rdisc_ok || rip_interfaces > 1)) {
737		trace_act("turn on RIP");
738
739		/* Close all of the query sockets so that we can open
740		 * the main socket.  SO_REUSEPORT is not a solution,
741		 * since that would let two daemons bind to the broadcast
742		 * socket.
743		 */
744		LIST_FOREACH(ifp, &ifnet, int_list) {
745			if (ifp->int_rip_sock >= 0) {
746				(void)close(ifp->int_rip_sock);
747				ifp->int_rip_sock = -1;
748			}
749		}
750
751		rip_sock = get_rip_sock(INADDR_ANY, 1);
752		rip_sock_mcast = NULL;
753
754		/* Do not advertise anything until we have heard something
755		 */
756		if (next_bcast.tv_sec < now.tv_sec+MIN_WAITTIME)
757			next_bcast.tv_sec = now.tv_sec+MIN_WAITTIME;
758
759		LIST_FOREACH(ifp, &ifnet, int_list) {
760			ifp->int_query_time = NEVER;
761			rip_mcast_on(ifp);
762		}
763		ifinit_timer.tv_sec = now.tv_sec;
764
765	} else if (ifp != NULL
766		   && !(ifp->int_state & IS_REMOTE)
767		   && ifp->int_rip_sock < 0) {
768		/* RIP is off, so ensure there are sockets on which
769		 * to listen for queries.
770		 */
771		ifp->int_rip_sock = get_rip_sock(ifp->int_addr, 0);
772	}
773
774	fix_select();
775}
776
777
778/* die if malloc(3) fails
779 */
780void *
781rtmalloc(size_t size,
782	 const char *msg)
783{
784	void *p = malloc(size);
785	if (p == NULL)
786		logbad(1,"malloc(%lu) failed in %s", (u_long)size, msg);
787	return p;
788}
789
790
791/* get a random instant in an interval
792 */
793void
794intvl_random(struct timeval *tp,	/* put value here */
795	     u_long lo,			/* value is after this second */
796	     u_long hi)			/* and before this */
797{
798	tp->tv_sec = (time_t)(hi == lo
799			      ? lo
800			      : (lo + arc4random_uniform(1 + hi - lo)));
801	tp->tv_usec = arc4random_uniform(1000000);
802}
803
804
805void
806timevaladd(struct timeval *t1,
807	   struct timeval *t2)
808{
809
810	t1->tv_sec += t2->tv_sec;
811	if ((t1->tv_usec += t2->tv_usec) >= 1000000) {
812		t1->tv_sec++;
813		t1->tv_usec -= 1000000;
814	}
815}
816
817
818/* t1 = t2 - t3
819 */
820static void
821timevalsub(struct timeval *t1,
822	   struct timeval *t2,
823	   struct timeval *t3)
824{
825	t1->tv_sec = t2->tv_sec - t3->tv_sec;
826	if ((t1->tv_usec = t2->tv_usec - t3->tv_usec) < 0) {
827		t1->tv_sec--;
828		t1->tv_usec += 1000000;
829	}
830}
831
832
833/* put a message into the system log
834 */
835void
836msglog(const char *p, ...)
837{
838	va_list args;
839
840	trace_flush();
841
842	va_start(args, p);
843	vsyslog(LOG_ERR, p, args);
844	va_end(args);
845	if (ftrace != NULL) {
846		if (ftrace == stdout)
847			(void)fputs("routed: ", ftrace);
848		va_start(args, p);
849		(void)vfprintf(ftrace, p, args);
850		va_end(args);
851		(void)fputc('\n', ftrace);
852	}
853}
854
855
856/* Put a message about a bad system into the system log if
857 * we have not complained about it recently.
858 *
859 * It is desirable to complain about all bad systems, but not too often.
860 * In the worst case, it is not practical to keep track of all bad systems.
861 * For example, there can be many systems with the wrong password.
862 */
863void
864msglim(struct msg_limit *lim, naddr addr, const char *p, ...)
865{
866	va_list args;
867	int i;
868	struct msg_sub *ms1, *ms;
869	const char *p1;
870
871	/* look for the oldest slot in the table
872	 * or the slot for the bad router.
873	 */
874	ms = ms1 = lim->subs;
875	for (i = MSG_SUBJECT_N; ; i--, ms1++) {
876		if (i == 0) {
877			/* Reuse a slot at most once every 10 minutes.
878			 */
879			if (lim->reuse > now.tv_sec) {
880				ms = NULL;
881			} else {
882				ms = ms1;
883				lim->reuse = now.tv_sec + 10*60;
884			}
885			break;
886		}
887		if (ms->addr == addr) {
888			/* Repeat a complaint about a given system at
889			 * most once an hour.
890			 */
891			if (ms->until > now.tv_sec)
892				ms = NULL;
893			break;
894		}
895		if (ms->until < ms1->until)
896			ms = ms1;
897	}
898	if (ms != NULL) {
899		ms->addr = addr;
900		ms->until = now.tv_sec + 60*60;	/* 60 minutes */
901
902		trace_flush();
903		for (p1 = p; *p1 == ' '; p1++)
904			continue;
905		va_start(args, p);
906		vsyslog(LOG_ERR, p1, args);
907		va_end(args);
908	}
909
910	/* always display the message if tracing */
911	if (ftrace != NULL) {
912		va_start(args, p);
913		(void)vfprintf(ftrace, p, args);
914		va_end(args);
915		(void)fputc('\n', ftrace);
916	}
917}
918
919
920void
921logbad(int dump, const char *p, ...)
922{
923	va_list args;
924
925	trace_flush();
926
927	va_start(args, p);
928	vsyslog(LOG_ERR, p, args);
929	va_end(args);
930	(void)fputs("routed: ", stderr);
931	va_start(args, p);
932	(void)vfprintf(stderr, p, args);
933	va_end(args);
934	(void)fputs("; giving up\n",stderr);
935	(void)fflush(stderr);
936
937	if (dump)
938		abort();
939	exit(1);
940}
941