timer.c revision 11820
1/*
2 * Copyright (c) 1985, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Copyright (c) 1995 John Hay.  All rights reserved.
6 *
7 * This file includes significant work done at Cornell University by
8 * Bill Nesheim.  That work included by permission.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 *    must display the following acknowledgement:
20 *	This product includes software developed by the University of
21 *	California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 *    may be used to endorse or promote products derived from this software
24 *    without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 *	$Id: timer.c,v 1.8 1995/10/11 18:57:32 jhay Exp $
39 */
40
41#ifndef lint
42static char sccsid[] = "@(#)timer.c	8.1 (Berkeley) 6/5/93";
43#endif /* not lint */
44
45/*
46 * Routing Table Management Daemon
47 */
48#include "defs.h"
49#include <unistd.h>
50#include <stdlib.h>
51
52int	timeval = -TIMER_RATE;
53
54/*
55 * Timer routine.  Performs routing information supply
56 * duties and manages timers on routing and SAP table entries.
57 */
58void
59timer()
60{
61	register struct rthash *rh;
62	register struct rt_entry *rt;
63	struct rthash *base = hosthash;
64	register struct sap_hash *sh;
65	register struct sap_entry *sap;
66	struct sap_hash *sap_base = sap_head;
67	int doinghost = 1, timetobroadcast, ripbroadcast, sapbroadcast;
68
69	timeval += TIMER_RATE;
70	if (lookforinterfaces && (timeval % CHECK_INTERVAL) == 0)
71		ifinit();
72	timetobroadcast = supplier && (timeval % SUPPLY_INTERVAL) == 0;
73	ripbroadcast = supplier && timetobroadcast &&
74			(timeval % RIP_INTERVAL) == 0;
75	sapbroadcast = timetobroadcast && dosap && !ripbroadcast;
76
77again:
78	for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) {
79		rt = rh->rt_forw;
80		for (; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
81			if (rt->rt_clone) {
82				struct rt_entry *trt, *prt;
83				/*
84				 * If a clone expire free it and mark the
85				 * main route RTS_CHANGED.
86				 */
87				prt = rt;
88				trt = rt->rt_clone;
89				while (trt) {
90					trt->rt_timer += TIMER_RATE;
91					if (trt->rt_timer >= EXPIRE_TIME) {
92						prt->rt_clone = trt->rt_clone;
93						free((char *)trt);
94						trt = prt->rt_clone;
95						rt->rt_state |= RTS_CHANGED;
96					} else {
97						prt = trt;
98						trt = prt->rt_clone;
99					}
100				}
101			}
102			/*
103			 * We don't advance time on a routing entry for
104			 * a passive gateway or that for our only interface.
105			 * The latter is excused because we don't act as
106			 * a routing information supplier and hence would
107			 * time it out.  This is fair as if it's down
108			 * we're cut off from the world anyway and it's
109			 * not likely we'll grow any new hardware in
110			 * the mean time.
111			 */
112			if (!(rt->rt_state & RTS_PASSIVE) &&
113			    !(rt->rt_state & RTS_INTERFACE))
114				rt->rt_timer += TIMER_RATE;
115			if (rt->rt_timer >= EXPIRE_TIME)
116				rt->rt_metric = HOPCNT_INFINITY;
117			if (rt->rt_timer >= GARBAGE_TIME) {
118				rt = rt->rt_back;
119				/* Perhaps we should send a REQUEST for this route? */
120				rtdelete(rt->rt_forw);
121				continue;
122			}
123			if (rt->rt_state & RTS_CHANGED) {
124				rt->rt_state &= ~RTS_CHANGED;
125				/* don't send extraneous packets */
126				if (!supplier || ripbroadcast)
127					continue;
128				msg->rip_cmd = htons(RIPCMD_RESPONSE);
129				msg->rip_nets[0].rip_dst =
130					(satoipx_addr(rt->rt_dst)).x_net;
131				msg->rip_nets[0].rip_metric =
132				   	htons(min(rt->rt_metric+1, HOPCNT_INFINITY));
133				msg->rip_nets[0].rip_ticks =
134					htons(rt->rt_ticks + 1);
135				toall(sndmsg, rt);
136			}
137		}
138	}
139	if (doinghost) {
140		doinghost = 0;
141		base = nethash;
142		goto again;
143	}
144	if (ripbroadcast)
145		toall(supply, NULL);
146
147	/*
148	 * Now do the SAP stuff.
149	 */
150	for (sh = sap_base; sh < &sap_base[SAPHASHSIZ]; sh++) {
151		sap = sh->forw;
152		for (; sap != (struct sap_entry *)sh; sap = sap->forw) {
153			if (sap->clone) {
154				struct sap_entry *tsap, *psap;
155				/*
156				 * If a clone expire free it and mark the
157				 * main sap entry RTS_CHANGED.
158				 */
159				psap = sap;
160				tsap = sap->clone;
161				while (tsap) {
162					tsap->timer += TIMER_RATE;
163					if (tsap->timer >= EXPIRE_TIME) {
164						psap->clone = tsap->clone;
165						free((char *)tsap);
166						tsap = psap->clone;
167						sap->state |= RTS_CHANGED;
168					} else {
169						psap = tsap;
170						tsap = psap->clone;
171					}
172				}
173			}
174			sap->timer += TIMER_RATE;
175			if (sap->timer >= EXPIRE_TIME)
176				sap->metric = HOPCNT_INFINITY;
177			if (sap->timer >= GARBAGE_TIME) {
178				sap = sap->back;
179				/* Perhaps we should send a REQUEST for this route? */
180				sap_delete(sap->forw);
181				continue;
182			}
183			/*
184			 * XXX sap_sndmsg on RTS_CHANGED
185			 */
186		}
187	}
188	if (sapbroadcast)
189		sap_supply_toall();
190	if (ftrace && sapbroadcast)
191		dumpsaptable(ftrace, sap_head);
192	alarm(TIMER_RATE);
193}
194
195/*
196 * On hangup, let everyone know we're going away.
197 */
198void
199hup()
200{
201	register struct rthash *rh;
202	register struct rt_entry *rt;
203	struct rthash *base = hosthash;
204	register struct sap_hash *sh;
205	register struct sap_entry *sap;
206	int doinghost = 1;
207
208	if (supplier) {
209again:
210		for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) {
211			rt = rh->rt_forw;
212			for (; rt != (struct rt_entry *)rh; rt = rt->rt_forw)
213				rt->rt_metric = HOPCNT_INFINITY;
214		}
215		if (doinghost) {
216			doinghost = 0;
217			base = nethash;
218			goto again;
219		}
220		toall(supply, NULL);
221
222		/*
223		 * Now for SAP.
224		 */
225		for (sh = sap_head; sh < &sap_head[SAPHASHSIZ]; sh++) {
226			sap = sh->forw;
227			for (; sap != (struct sap_entry *)sh; sap = sap->forw)
228				sap->sap.hops = htons(HOPCNT_INFINITY);
229		}
230		if (dosap)
231			sap_supply_toall();
232	}
233	exit(1);
234}
235