BSD 4_3_Net_2 release
[unix-history] / usr / src / sbin / XNSrouted / tables.c
CommitLineData
4a10c08d 1/*
76e89f1d
KB
2 * Copyright (c) 1985 The Regents of the University of California.
3 * All rights reserved.
4a10c08d 4 *
af359dea
C
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
4a10c08d
KS
32 */
33
decc7a4c 34#ifndef lint
1c15e888 35static char sccsid[] = "@(#)tables.c 5.9 (Berkeley) 6/1/90";
76e89f1d 36#endif /* not lint */
decc7a4c
KS
37
38/*
39 * Routing Table Management Daemon
40 */
41#include "defs.h"
42#include <sys/ioctl.h>
43#include <errno.h>
44
45#ifndef DEBUG
46#define DEBUG 0
47#endif
48
64f255e3 49extern char *xns_ntoa();
3470e246 50#define FIXLEN(s) { if ((s)->sa_len == 0) (s)->sa_len = sizeof (*(s));}
64f255e3 51
decc7a4c 52int install = !DEBUG; /* if 1 call kernel */
48681466 53int delete = 1;
decc7a4c
KS
54/*
55 * Lookup dst in the tables for an exact match.
56 */
57struct rt_entry *
58rtlookup(dst)
59 struct sockaddr *dst;
60{
61 register struct rt_entry *rt;
62 register struct rthash *rh;
63 register u_int hash;
64 struct afhash h;
65 int doinghost = 1;
66
67 if (dst->sa_family >= AF_MAX)
68 return (0);
69 (*afswitch[dst->sa_family].af_hash)(dst, &h);
70 hash = h.afh_hosthash;
71 rh = &hosthash[hash & ROUTEHASHMASK];
72again:
73 for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
74 if (rt->rt_hash != hash)
75 continue;
76 if (equal(&rt->rt_dst, dst))
77 return (rt);
78 }
79 if (doinghost) {
80 doinghost = 0;
81 hash = h.afh_nethash;
82 rh = &nethash[hash & ROUTEHASHMASK];
83 goto again;
84 }
85 return (0);
86}
87
88/*
89 * Find a route to dst as the kernel would.
90 */
91struct rt_entry *
92rtfind(dst)
93 struct sockaddr *dst;
94{
95 register struct rt_entry *rt;
96 register struct rthash *rh;
97 register u_int hash;
98 struct afhash h;
99 int af = dst->sa_family;
100 int doinghost = 1, (*match)();
101
102 if (af >= AF_MAX)
103 return (0);
104 (*afswitch[af].af_hash)(dst, &h);
105 hash = h.afh_hosthash;
106 rh = &hosthash[hash & ROUTEHASHMASK];
107
108again:
109 for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
110 if (rt->rt_hash != hash)
111 continue;
112 if (doinghost) {
113 if (equal(&rt->rt_dst, dst))
114 return (rt);
4a10c08d
KS
115 } else {
116 if (rt->rt_dst.sa_family == af &&
117 (*match)(&rt->rt_dst, dst))
118 return (rt);
decc7a4c
KS
119 }
120 }
121 if (doinghost) {
122 doinghost = 0;
123 hash = h.afh_nethash;
124 rh = &nethash[hash & ROUTEHASHMASK];
125 match = afswitch[af].af_netmatch;
126 goto again;
127 }
128 return (0);
129}
130
131rtadd(dst, gate, metric, state)
132 struct sockaddr *dst, *gate;
133 int metric, state;
134{
135 struct afhash h;
136 register struct rt_entry *rt;
137 struct rthash *rh;
138 int af = dst->sa_family, flags;
139 u_int hash;
140
3470e246
MK
141 FIXLEN(dst);
142 FIXLEN(gate);
decc7a4c
KS
143 if (af >= AF_MAX)
144 return;
145 (*afswitch[af].af_hash)(dst, &h);
146 flags = (*afswitch[af].af_ishost)(dst) ? RTF_HOST : 0;
147 if (flags & RTF_HOST) {
148 hash = h.afh_hosthash;
149 rh = &hosthash[hash & ROUTEHASHMASK];
150 } else {
151 hash = h.afh_nethash;
152 rh = &nethash[hash & ROUTEHASHMASK];
153 }
154 rt = (struct rt_entry *)malloc(sizeof (*rt));
155 if (rt == 0)
156 return;
157 rt->rt_hash = hash;
158 rt->rt_dst = *dst;
159 rt->rt_router = *gate;
160 rt->rt_metric = metric;
161 rt->rt_timer = 0;
162 rt->rt_flags = RTF_UP | flags;
163 rt->rt_state = state | RTS_CHANGED;
164 rt->rt_ifp = if_ifwithnet(&rt->rt_router);
165 if (metric)
166 rt->rt_flags |= RTF_GATEWAY;
167 insque(rt, rh);
168 TRACE_ACTION(ADD, rt);
169 /*
170 * If the ioctl fails because the gateway is unreachable
171 * from this host, discard the entry. This should only
172 * occur because of an incorrect entry in /etc/gateways.
173 */
174 if (install && ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0) {
64f255e3
MK
175 if (errno != EEXIST)
176 perror("SIOCADDRT");
decc7a4c
KS
177 if (errno == ENETUNREACH) {
178 TRACE_ACTION(DELETE, rt);
179 remque(rt);
180 free((char *)rt);
181 }
182 }
183}
184
185rtchange(rt, gate, metric)
186 struct rt_entry *rt;
187 struct sockaddr *gate;
188 short metric;
189{
190 int doioctl = 0, metricchanged = 0;
191 struct rtentry oldroute;
192
3470e246 193 FIXLEN(gate);
decc7a4c
KS
194 if (!equal(&rt->rt_router, gate))
195 doioctl++;
196 if (metric != rt->rt_metric)
197 metricchanged++;
198 if (doioctl || metricchanged) {
199 TRACE_ACTION(CHANGE FROM, rt);
200 if (doioctl) {
201 oldroute = rt->rt_rt;
202 rt->rt_router = *gate;
203 }
204 rt->rt_metric = metric;
84f93e8f
KS
205 if ((rt->rt_state & RTS_INTERFACE) && metric) {
206 rt->rt_state &= ~RTS_INTERFACE;
207 syslog(LOG_ERR,
208 "changing route from interface %s (timed out)",
209 rt->rt_ifp->int_name);
210 }
decc7a4c 211 if (metric)
84f93e8f
KS
212 rt->rt_flags |= RTF_GATEWAY;
213 else
214 rt->rt_flags &= ~RTF_GATEWAY;
decc7a4c
KS
215 rt->rt_state |= RTS_CHANGED;
216 TRACE_ACTION(CHANGE TO, rt);
217 }
218 if (doioctl && install) {
3470e246 219#ifndef RTM_ADD
decc7a4c 220 if (ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0)
64f255e3
MK
221 syslog(LOG_ERR, "SIOCADDRT dst %s, gw %s: %m",
222 xns_ntoa(&((struct sockaddr_ns *)&rt->rt_dst)->sns_addr),
223 xns_ntoa(&((struct sockaddr_ns *)&rt->rt_router)->sns_addr));
224 if (delete && ioctl(s, SIOCDELRT, (char *)&oldroute) < 0)
225 perror("SIOCDELRT");
3470e246
MK
226#else
227 if (delete && ioctl(s, SIOCDELRT, (char *)&oldroute) < 0)
228 perror("SIOCDELRT");
229 if (ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0)
230 syslog(LOG_ERR, "SIOCADDRT dst %s, gw %s: %m",
231 xns_ntoa(&((struct sockaddr_ns *)&rt->rt_dst)->sns_addr),
232 xns_ntoa(&((struct sockaddr_ns *)&rt->rt_router)->sns_addr));
233#endif
decc7a4c
KS
234 }
235}
236
237rtdelete(rt)
238 struct rt_entry *rt;
239{
240
3470e246
MK
241 struct sockaddr *sa = &(rt->rt_rt.rt_gateway);
242 FIXLEN(sa);
243#undef rt_dst
244 sa = &(rt->rt_rt.rt_dst);
245 FIXLEN(sa);
84f93e8f
KS
246 if (rt->rt_state & RTS_INTERFACE) {
247 syslog(LOG_ERR, "deleting route to interface %s (timed out)",
248 rt->rt_ifp->int_name);
249 }
decc7a4c 250 TRACE_ACTION(DELETE, rt);
84f93e8f
KS
251 if (install && ioctl(s, SIOCDELRT, (char *)&rt->rt_rt))
252 perror("SIOCDELRT");
decc7a4c
KS
253 remque(rt);
254 free((char *)rt);
255}
256
257rtinit()
258{
259 register struct rthash *rh;
260
261 for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++)
262 rh->rt_forw = rh->rt_back = (struct rt_entry *)rh;
263 for (rh = hosthash; rh < &hosthash[ROUTEHASHSIZ]; rh++)
264 rh->rt_forw = rh->rt_back = (struct rt_entry *)rh;
decc7a4c 265}