BSD 4_3_Tahoe release
[unix-history] / usr / src / etc / XNSrouted / tables.c
CommitLineData
4a10c08d
KS
1/*
2 * Copyright (c) 1985 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
6 */
7
8
decc7a4c 9#ifndef lint
ca67e7b4 10static char sccsid[] = "@(#)tables.c 5.6 (Berkeley) 12/30/86";
4a10c08d 11#endif not lint
decc7a4c
KS
12
13/*
14 * Routing Table Management Daemon
15 */
16#include "defs.h"
17#include <sys/ioctl.h>
18#include <errno.h>
19
20#ifndef DEBUG
21#define DEBUG 0
22#endif
23
64f255e3
MK
24extern char *xns_ntoa();
25
decc7a4c 26int install = !DEBUG; /* if 1 call kernel */
48681466 27int delete = 1;
decc7a4c
KS
28/*
29 * Lookup dst in the tables for an exact match.
30 */
31struct rt_entry *
32rtlookup(dst)
33 struct sockaddr *dst;
34{
35 register struct rt_entry *rt;
36 register struct rthash *rh;
37 register u_int hash;
38 struct afhash h;
39 int doinghost = 1;
40
41 if (dst->sa_family >= AF_MAX)
42 return (0);
43 (*afswitch[dst->sa_family].af_hash)(dst, &h);
44 hash = h.afh_hosthash;
45 rh = &hosthash[hash & ROUTEHASHMASK];
46again:
47 for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
48 if (rt->rt_hash != hash)
49 continue;
50 if (equal(&rt->rt_dst, dst))
51 return (rt);
52 }
53 if (doinghost) {
54 doinghost = 0;
55 hash = h.afh_nethash;
56 rh = &nethash[hash & ROUTEHASHMASK];
57 goto again;
58 }
59 return (0);
60}
61
62/*
63 * Find a route to dst as the kernel would.
64 */
65struct rt_entry *
66rtfind(dst)
67 struct sockaddr *dst;
68{
69 register struct rt_entry *rt;
70 register struct rthash *rh;
71 register u_int hash;
72 struct afhash h;
73 int af = dst->sa_family;
74 int doinghost = 1, (*match)();
75
76 if (af >= AF_MAX)
77 return (0);
78 (*afswitch[af].af_hash)(dst, &h);
79 hash = h.afh_hosthash;
80 rh = &hosthash[hash & ROUTEHASHMASK];
81
82again:
83 for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
84 if (rt->rt_hash != hash)
85 continue;
86 if (doinghost) {
87 if (equal(&rt->rt_dst, dst))
88 return (rt);
4a10c08d
KS
89 } else {
90 if (rt->rt_dst.sa_family == af &&
91 (*match)(&rt->rt_dst, dst))
92 return (rt);
decc7a4c
KS
93 }
94 }
95 if (doinghost) {
96 doinghost = 0;
97 hash = h.afh_nethash;
98 rh = &nethash[hash & ROUTEHASHMASK];
99 match = afswitch[af].af_netmatch;
100 goto again;
101 }
102 return (0);
103}
104
105rtadd(dst, gate, metric, state)
106 struct sockaddr *dst, *gate;
107 int metric, state;
108{
109 struct afhash h;
110 register struct rt_entry *rt;
111 struct rthash *rh;
112 int af = dst->sa_family, flags;
113 u_int hash;
114
115 if (af >= AF_MAX)
116 return;
117 (*afswitch[af].af_hash)(dst, &h);
118 flags = (*afswitch[af].af_ishost)(dst) ? RTF_HOST : 0;
119 if (flags & RTF_HOST) {
120 hash = h.afh_hosthash;
121 rh = &hosthash[hash & ROUTEHASHMASK];
122 } else {
123 hash = h.afh_nethash;
124 rh = &nethash[hash & ROUTEHASHMASK];
125 }
126 rt = (struct rt_entry *)malloc(sizeof (*rt));
127 if (rt == 0)
128 return;
129 rt->rt_hash = hash;
130 rt->rt_dst = *dst;
131 rt->rt_router = *gate;
132 rt->rt_metric = metric;
133 rt->rt_timer = 0;
134 rt->rt_flags = RTF_UP | flags;
135 rt->rt_state = state | RTS_CHANGED;
136 rt->rt_ifp = if_ifwithnet(&rt->rt_router);
137 if (metric)
138 rt->rt_flags |= RTF_GATEWAY;
139 insque(rt, rh);
140 TRACE_ACTION(ADD, rt);
141 /*
142 * If the ioctl fails because the gateway is unreachable
143 * from this host, discard the entry. This should only
144 * occur because of an incorrect entry in /etc/gateways.
145 */
146 if (install && ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0) {
64f255e3
MK
147 if (errno != EEXIST)
148 perror("SIOCADDRT");
decc7a4c
KS
149 if (errno == ENETUNREACH) {
150 TRACE_ACTION(DELETE, rt);
151 remque(rt);
152 free((char *)rt);
153 }
154 }
155}
156
157rtchange(rt, gate, metric)
158 struct rt_entry *rt;
159 struct sockaddr *gate;
160 short metric;
161{
162 int doioctl = 0, metricchanged = 0;
163 struct rtentry oldroute;
164
165 if (!equal(&rt->rt_router, gate))
166 doioctl++;
167 if (metric != rt->rt_metric)
168 metricchanged++;
169 if (doioctl || metricchanged) {
170 TRACE_ACTION(CHANGE FROM, rt);
171 if (doioctl) {
172 oldroute = rt->rt_rt;
173 rt->rt_router = *gate;
174 }
175 rt->rt_metric = metric;
84f93e8f
KS
176 if ((rt->rt_state & RTS_INTERFACE) && metric) {
177 rt->rt_state &= ~RTS_INTERFACE;
178 syslog(LOG_ERR,
179 "changing route from interface %s (timed out)",
180 rt->rt_ifp->int_name);
181 }
decc7a4c 182 if (metric)
84f93e8f
KS
183 rt->rt_flags |= RTF_GATEWAY;
184 else
185 rt->rt_flags &= ~RTF_GATEWAY;
decc7a4c
KS
186 rt->rt_state |= RTS_CHANGED;
187 TRACE_ACTION(CHANGE TO, rt);
188 }
189 if (doioctl && install) {
190 if (ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0)
64f255e3
MK
191 syslog(LOG_ERR, "SIOCADDRT dst %s, gw %s: %m",
192 xns_ntoa(&((struct sockaddr_ns *)&rt->rt_dst)->sns_addr),
193 xns_ntoa(&((struct sockaddr_ns *)&rt->rt_router)->sns_addr));
194 if (delete && ioctl(s, SIOCDELRT, (char *)&oldroute) < 0)
195 perror("SIOCDELRT");
decc7a4c
KS
196 }
197}
198
199rtdelete(rt)
200 struct rt_entry *rt;
201{
202
84f93e8f
KS
203 if (rt->rt_state & RTS_INTERFACE) {
204 syslog(LOG_ERR, "deleting route to interface %s (timed out)",
205 rt->rt_ifp->int_name);
206 }
decc7a4c 207 TRACE_ACTION(DELETE, rt);
84f93e8f
KS
208 if (install && ioctl(s, SIOCDELRT, (char *)&rt->rt_rt))
209 perror("SIOCDELRT");
decc7a4c
KS
210 remque(rt);
211 free((char *)rt);
212}
213
214rtinit()
215{
216 register struct rthash *rh;
217
218 for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++)
219 rh->rt_forw = rh->rt_back = (struct rt_entry *)rh;
220 for (rh = hosthash; rh < &hosthash[ROUTEHASHSIZ]; rh++)
221 rh->rt_forw = rh->rt_back = (struct rt_entry *)rh;
decc7a4c 222}