1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27/*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
28/*	  All Rights Reserved  	*/
29
30/*
31 * Portions of this source code were derived from Berkeley 4.3 BSD
32 * under license from the Regents of the University of California.
33 */
34
35#pragma ident	"%Z%%M%	%I%	%E% SMI"
36
37/*
38 * Routing Table Management Daemon
39 */
40#include "defs.h"
41
42int supplyinterval;			/* current supply interval */
43
44/*
45 * Timer routine.  Performs routing information supply
46 * duties and manages timers on routing table entries.
47 * Management of the RTS_CHANGED bit assumes that we multicast
48 * each time called.
49 */
50void
51timer(void)
52{
53	struct rthash *rh;
54	struct rt_entry *rt;
55	boolean_t timetomulticast = _B_FALSE;
56	int i;
57	static int iftime;		/* interface timer */
58	static int mtime;		/* periodic mcast supply timer */
59	static int alarmtime = 0;	/* time elapsed since last call */
60	int mintime;			/* tracks when next timer will expire */
61
62	/*
63	 * On the initial call to timer(), the various times that are kept track
64	 * of need to be initialized.  After initializing everything, "remember"
65	 * (via a static) how long until the next timer expires.
66	 */
67	if (alarmtime == 0) {
68		supplyinterval = GET_RANDOM(MIN_SUPPLY_TIME, MAX_SUPPLY_TIME);
69		iftime = 0;
70		mtime = supplyinterval;
71		alarmtime = supplyinterval;
72		(void) alarm(alarmtime);
73		return;
74	}
75
76	/*
77	 * Initialize mintime to a suitable "large" value and then compare it to
78	 * other times in the future to determine which event will occur next.
79	 */
80	mintime = INT_MAX;
81	(void) sighold(SIGHUP);
82	(void) sighold(SIGUSR1);
83	(void) sighold(SIGUSR2);
84
85	iftime += alarmtime;
86	if (iftime >= CHECK_INTERVAL) {
87		initifs();
88		iftime = 0;
89	}
90	mintime = min(mintime, CHECK_INTERVAL - iftime);
91
92	mtime += alarmtime;
93	if (mtime >= supplyinterval) {
94		if (supplier)
95			timetomulticast = _B_TRUE;
96		mtime = 0;
97		supplyinterval = GET_RANDOM(MIN_SUPPLY_TIME, MAX_SUPPLY_TIME);
98	}
99	mintime = min(mintime, supplyinterval - mtime);
100
101	for (i = IPV6_ABITS; i >= 0; i--) {
102		if (net_hashes[i] == NULL)
103			continue;
104
105		for (rh = net_hashes[i];
106		    rh < &net_hashes[i][ROUTEHASHSIZ]; rh++) {
107			for (rt = rh->rt_forw; rt != (struct rt_entry *)rh;
108			    rt = rt->rt_forw) {
109				/*
110				 * We don't advance time on a routing entry for
111				 * an interface because we catch
112				 * interfaces going up and down in initifs.
113				 */
114				rt->rt_state &= ~RTS_CHANGED;
115				if ((rt->rt_state & RTS_INTERFACE) != 0)
116					continue;
117				rt->rt_timer += alarmtime;
118				if (rt->rt_timer >= GARBAGE_TIME) {
119					rt = rt->rt_back;
120					rtdelete(rt->rt_forw);
121					continue;
122				}
123				if (rt->rt_timer >= EXPIRE_TIME) {
124					rtdown(rt);
125					mintime = min(mintime,
126					    GARBAGE_TIME - rt->rt_timer);
127				} else {
128					mintime = min(mintime,
129					    EXPIRE_TIME - rt->rt_timer);
130				}
131			}
132		}
133	}
134
135	if (timetomulticast) {
136		supplyall(&allrouters, 0, (struct interface *)NULL, _B_TRUE);
137		(void) gettimeofday(&now, (struct timezone *)NULL);
138		lastmcast = now;
139		lastfullupdate = now;
140		needupdate = _B_FALSE;	/* cancel any pending dynamic update */
141		nextmcast.tv_sec = 0;
142	}
143	(void) sigrelse(SIGUSR2);
144	(void) sigrelse(SIGUSR1);
145	(void) sigrelse(SIGHUP);
146
147	/*
148	 * "Remember" (via a static) how long until the next timer expires.
149	 */
150	alarmtime = mintime;
151	(void) alarm(alarmtime);
152}
153
154/*
155 * On SIGTERM, let everyone know we're going away.
156 */
157void
158term(void)
159{
160	struct rthash *rh;
161	struct rt_entry *rt;
162	int i;
163
164	if (!supplier)
165		exit(EXIT_SUCCESS);
166	for (i = IPV6_ABITS; i >= 0; i--) {
167		if (net_hashes[i] == NULL)
168			continue;
169
170		for (rh = net_hashes[i]; rh < &net_hashes[i][ROUTEHASHSIZ];
171		    rh++) {
172			for (rt = rh->rt_forw; rt != (struct rt_entry *)rh;
173			    rt = rt->rt_forw) {
174				rt->rt_metric = HOPCNT_INFINITY;
175			}
176		}
177	}
178	supplyall(&allrouters, 0, (struct interface *)NULL, _B_TRUE);
179	(void) unlink(PATH_PID);
180	exit(EXIT_SUCCESS);
181}
182