111820Sjulian/*
211820Sjulian * Copyright (c) 1985, 1993
311820Sjulian *	The Regents of the University of California.  All rights reserved.
411820Sjulian *
511820Sjulian * Copyright (c) 1995 John Hay.  All rights reserved.
611820Sjulian *
711820Sjulian * This file includes significant work done at Cornell University by
811820Sjulian * Bill Nesheim.  That work included by permission.
911820Sjulian *
1011820Sjulian * Redistribution and use in source and binary forms, with or without
1111820Sjulian * modification, are permitted provided that the following conditions
1211820Sjulian * are met:
1311820Sjulian * 1. Redistributions of source code must retain the above copyright
1411820Sjulian *    notice, this list of conditions and the following disclaimer.
1511820Sjulian * 2. Redistributions in binary form must reproduce the above copyright
1611820Sjulian *    notice, this list of conditions and the following disclaimer in the
1711820Sjulian *    documentation and/or other materials provided with the distribution.
1811820Sjulian * 3. All advertising materials mentioning features or use of this software
1911820Sjulian *    must display the following acknowledgement:
2011820Sjulian *	This product includes software developed by the University of
2111820Sjulian *	California, Berkeley and its contributors.
2211820Sjulian * 4. Neither the name of the University nor the names of its contributors
2311820Sjulian *    may be used to endorse or promote products derived from this software
2411820Sjulian *    without specific prior written permission.
2511820Sjulian *
2611820Sjulian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2711820Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2811820Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2911820Sjulian * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3011820Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3111820Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3211820Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3311820Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3411820Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3511820Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3611820Sjulian * SUCH DAMAGE.
3711820Sjulian *
3850479Speter * $FreeBSD$
3911820Sjulian */
4011820Sjulian
4111820Sjulian#ifndef lint
42122760Strhodesstatic const char sccsid[] = "@(#)timer.c	8.1 (Berkeley) 6/5/93";
4311820Sjulian#endif /* not lint */
4411820Sjulian
4511820Sjulian/*
4611820Sjulian * Routing Table Management Daemon
4711820Sjulian */
4811820Sjulian#include "defs.h"
4911820Sjulian#include <unistd.h>
5011820Sjulian#include <stdlib.h>
5111820Sjulian
5211820Sjulianint	timeval = -TIMER_RATE;
5311820Sjulian
5411820Sjulian/*
5511820Sjulian * Timer routine.  Performs routing information supply
5611820Sjulian * duties and manages timers on routing and SAP table entries.
5711820Sjulian */
5811820Sjulianvoid
5911820Sjuliantimer()
6011820Sjulian{
6111820Sjulian	register struct rthash *rh;
6211820Sjulian	register struct rt_entry *rt;
6311820Sjulian	register struct sap_hash *sh;
6411820Sjulian	register struct sap_entry *sap;
6511820Sjulian	struct sap_hash *sap_base = sap_head;
6627244Sjhay	int timetobroadcast, ripbroadcast, sapbroadcast;
6711820Sjulian
6811820Sjulian	timeval += TIMER_RATE;
6911820Sjulian	if (lookforinterfaces && (timeval % CHECK_INTERVAL) == 0)
7011820Sjulian		ifinit();
7111820Sjulian	timetobroadcast = supplier && (timeval % SUPPLY_INTERVAL) == 0;
7211820Sjulian	ripbroadcast = supplier && timetobroadcast &&
7311820Sjulian			(timeval % RIP_INTERVAL) == 0;
7411820Sjulian	sapbroadcast = timetobroadcast && dosap && !ripbroadcast;
7511820Sjulian
7627244Sjhay	for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++) {
7711820Sjulian		rt = rh->rt_forw;
7811820Sjulian		for (; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
7911820Sjulian			if (rt->rt_clone) {
8011820Sjulian				struct rt_entry *trt, *prt;
8111820Sjulian				/*
8211820Sjulian				 * If a clone expire free it and mark the
8311820Sjulian				 * main route RTS_CHANGED.
8411820Sjulian				 */
8511820Sjulian				prt = rt;
8611820Sjulian				trt = rt->rt_clone;
8711820Sjulian				while (trt) {
8811820Sjulian					trt->rt_timer += TIMER_RATE;
8911820Sjulian					if (trt->rt_timer >= EXPIRE_TIME) {
9011820Sjulian						prt->rt_clone = trt->rt_clone;
9111820Sjulian						free((char *)trt);
9211820Sjulian						trt = prt->rt_clone;
9311820Sjulian						rt->rt_state |= RTS_CHANGED;
9411820Sjulian					} else {
9511820Sjulian						prt = trt;
9611820Sjulian						trt = prt->rt_clone;
9711820Sjulian					}
9811820Sjulian				}
9911820Sjulian			}
10011820Sjulian			/*
10111820Sjulian			 * We don't advance time on a routing entry for
10211820Sjulian			 * a passive gateway or that for our only interface.
10311820Sjulian			 * The latter is excused because we don't act as
10411820Sjulian			 * a routing information supplier and hence would
10511820Sjulian			 * time it out.  This is fair as if it's down
10611820Sjulian			 * we're cut off from the world anyway and it's
10711820Sjulian			 * not likely we'll grow any new hardware in
10811820Sjulian			 * the mean time.
10911820Sjulian			 */
11011820Sjulian			if (!(rt->rt_state & RTS_PASSIVE) &&
11111820Sjulian			    !(rt->rt_state & RTS_INTERFACE))
11211820Sjulian				rt->rt_timer += TIMER_RATE;
11327244Sjhay			if (rt->rt_timer >= EXPIRE_TIME) {
11411820Sjulian				rt->rt_metric = HOPCNT_INFINITY;
11527244Sjhay				rt->rt_state |= RTS_CHANGED;
11627244Sjhay			}
11711820Sjulian			if (rt->rt_timer >= GARBAGE_TIME) {
11811820Sjulian				rt = rt->rt_back;
11911820Sjulian				/* Perhaps we should send a REQUEST for this route? */
12011820Sjulian				rtdelete(rt->rt_forw);
12111820Sjulian				continue;
12211820Sjulian			}
12311820Sjulian			if (rt->rt_state & RTS_CHANGED) {
12411820Sjulian				rt->rt_state &= ~RTS_CHANGED;
12511820Sjulian				/* don't send extraneous packets */
12611820Sjulian				if (!supplier || ripbroadcast)
12711820Sjulian					continue;
12827244Sjhay				if ((rt->rt_metric + 1) == HOPCNT_INFINITY)
12927244Sjhay					continue;
13011820Sjulian				msg->rip_cmd = htons(RIPCMD_RESPONSE);
13111820Sjulian				msg->rip_nets[0].rip_dst =
13211820Sjulian					(satoipx_addr(rt->rt_dst)).x_net;
13311820Sjulian				msg->rip_nets[0].rip_metric =
13411820Sjulian				   	htons(min(rt->rt_metric+1, HOPCNT_INFINITY));
13511820Sjulian				msg->rip_nets[0].rip_ticks =
13611820Sjulian					htons(rt->rt_ticks + 1);
13727244Sjhay				toall(sndmsg, rt, 0);
13811820Sjulian			}
13911820Sjulian		}
14011820Sjulian	}
14111820Sjulian	if (ripbroadcast)
14227244Sjhay		toall(supply, NULL, 0);
14311820Sjulian
14411820Sjulian	/*
14511820Sjulian	 * Now do the SAP stuff.
14611820Sjulian	 */
14711820Sjulian	for (sh = sap_base; sh < &sap_base[SAPHASHSIZ]; sh++) {
14811820Sjulian		sap = sh->forw;
14911820Sjulian		for (; sap != (struct sap_entry *)sh; sap = sap->forw) {
15011820Sjulian			if (sap->clone) {
15111820Sjulian				struct sap_entry *tsap, *psap;
15211820Sjulian				/*
15311820Sjulian				 * If a clone expire free it and mark the
15411820Sjulian				 * main sap entry RTS_CHANGED.
15511820Sjulian				 */
15611820Sjulian				psap = sap;
15711820Sjulian				tsap = sap->clone;
15811820Sjulian				while (tsap) {
15911820Sjulian					tsap->timer += TIMER_RATE;
16011820Sjulian					if (tsap->timer >= EXPIRE_TIME) {
16111820Sjulian						psap->clone = tsap->clone;
16211820Sjulian						free((char *)tsap);
16311820Sjulian						tsap = psap->clone;
16411820Sjulian						sap->state |= RTS_CHANGED;
16511820Sjulian					} else {
16611820Sjulian						psap = tsap;
16711820Sjulian						tsap = psap->clone;
16811820Sjulian					}
16911820Sjulian				}
17011820Sjulian			}
17111820Sjulian			sap->timer += TIMER_RATE;
17227244Sjhay			if (sap->timer >= EXPIRE_TIME) {
17327244Sjhay				sap->sap.hops = htons(HOPCNT_INFINITY);
17427244Sjhay				sap->state |= RTS_CHANGED;
17527244Sjhay			}
17611820Sjulian			if (sap->timer >= GARBAGE_TIME) {
17711820Sjulian				sap = sap->back;
17811820Sjulian				/* Perhaps we should send a REQUEST for this route? */
17911820Sjulian				sap_delete(sap->forw);
18011820Sjulian				continue;
18111820Sjulian			}
18211820Sjulian			/*
18311820Sjulian			 * XXX sap_sndmsg on RTS_CHANGED
18411820Sjulian			 */
18527244Sjhay			if (sap->state & RTS_CHANGED) {
18627244Sjhay				sap->state &= ~RTS_CHANGED;
18727244Sjhay#ifdef notyet
18827244Sjhay				/* don't send extraneous packets */
18927244Sjhay				if (!supplier || sapbroadcast)
19027244Sjhay					continue;
19127244Sjhay				if ((ntohs(sap->sap.hops) + 1) == HOPCNT_INFINITY)
19227244Sjhay					continue;
19327244Sjhay				sap_msg->sap_cmd = htons(SAP_RESP);
19427244Sjhay				sap_msg->sap[0] = sap->sap;
19527244Sjhay				sap_msg->sap[0].hops =
19627244Sjhay				    htons(min(sap->sap.hops+1, HOPCNT_INFINITY));
19727244Sjhay				toall(sapsndmsg, rt, 0);
19827244Sjhay#endif
19927244Sjhay			}
20011820Sjulian		}
20111820Sjulian	}
20211820Sjulian	if (sapbroadcast)
20327244Sjhay		sap_supply_toall(0);
20411820Sjulian	if (ftrace && sapbroadcast)
20511820Sjulian		dumpsaptable(ftrace, sap_head);
20611820Sjulian}
20711820Sjulian
20811820Sjulian/*
20911820Sjulian * On hangup, let everyone know we're going away.
21011820Sjulian */
21111820Sjulianvoid
21211820Sjulianhup()
21311820Sjulian{
21411820Sjulian	register struct rthash *rh;
21511820Sjulian	register struct rt_entry *rt;
21611820Sjulian	register struct sap_hash *sh;
21711820Sjulian	register struct sap_entry *sap;
21811820Sjulian
21911820Sjulian	if (supplier) {
22027244Sjhay		for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++) {
22111820Sjulian			rt = rh->rt_forw;
22211820Sjulian			for (; rt != (struct rt_entry *)rh; rt = rt->rt_forw)
22311820Sjulian				rt->rt_metric = HOPCNT_INFINITY;
22411820Sjulian		}
22527244Sjhay		toall(supply, NULL, 0);
22611820Sjulian
22711820Sjulian		/*
22811820Sjulian		 * Now for SAP.
22911820Sjulian		 */
23011820Sjulian		for (sh = sap_head; sh < &sap_head[SAPHASHSIZ]; sh++) {
23111820Sjulian			sap = sh->forw;
23211820Sjulian			for (; sap != (struct sap_entry *)sh; sap = sap->forw)
23311820Sjulian				sap->sap.hops = htons(HOPCNT_INFINITY);
23411820Sjulian		}
23511820Sjulian		if (dosap)
23627244Sjhay			sap_supply_toall(0);
23711820Sjulian	}
23811820Sjulian	exit(1);
23911820Sjulian}
240