check for alpha release by sklower
[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 *
76e89f1d
KB
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
4a10c08d
KS
16 */
17
decc7a4c 18#ifndef lint
3470e246 19static char sccsid[] = "@(#)tables.c 5.8 (Berkeley) %G%";
76e89f1d 20#endif /* not lint */
decc7a4c
KS
21
22/*
23 * Routing Table Management Daemon
24 */
25#include "defs.h"
26#include <sys/ioctl.h>
27#include <errno.h>
28
29#ifndef DEBUG
30#define DEBUG 0
31#endif
32
64f255e3 33extern char *xns_ntoa();
3470e246 34#define FIXLEN(s) { if ((s)->sa_len == 0) (s)->sa_len = sizeof (*(s));}
64f255e3 35
decc7a4c 36int install = !DEBUG; /* if 1 call kernel */
48681466 37int delete = 1;
decc7a4c
KS
38/*
39 * Lookup dst in the tables for an exact match.
40 */
41struct rt_entry *
42rtlookup(dst)
43 struct sockaddr *dst;
44{
45 register struct rt_entry *rt;
46 register struct rthash *rh;
47 register u_int hash;
48 struct afhash h;
49 int doinghost = 1;
50
51 if (dst->sa_family >= AF_MAX)
52 return (0);
53 (*afswitch[dst->sa_family].af_hash)(dst, &h);
54 hash = h.afh_hosthash;
55 rh = &hosthash[hash & ROUTEHASHMASK];
56again:
57 for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
58 if (rt->rt_hash != hash)
59 continue;
60 if (equal(&rt->rt_dst, dst))
61 return (rt);
62 }
63 if (doinghost) {
64 doinghost = 0;
65 hash = h.afh_nethash;
66 rh = &nethash[hash & ROUTEHASHMASK];
67 goto again;
68 }
69 return (0);
70}
71
72/*
73 * Find a route to dst as the kernel would.
74 */
75struct rt_entry *
76rtfind(dst)
77 struct sockaddr *dst;
78{
79 register struct rt_entry *rt;
80 register struct rthash *rh;
81 register u_int hash;
82 struct afhash h;
83 int af = dst->sa_family;
84 int doinghost = 1, (*match)();
85
86 if (af >= AF_MAX)
87 return (0);
88 (*afswitch[af].af_hash)(dst, &h);
89 hash = h.afh_hosthash;
90 rh = &hosthash[hash & ROUTEHASHMASK];
91
92again:
93 for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
94 if (rt->rt_hash != hash)
95 continue;
96 if (doinghost) {
97 if (equal(&rt->rt_dst, dst))
98 return (rt);
4a10c08d
KS
99 } else {
100 if (rt->rt_dst.sa_family == af &&
101 (*match)(&rt->rt_dst, dst))
102 return (rt);
decc7a4c
KS
103 }
104 }
105 if (doinghost) {
106 doinghost = 0;
107 hash = h.afh_nethash;
108 rh = &nethash[hash & ROUTEHASHMASK];
109 match = afswitch[af].af_netmatch;
110 goto again;
111 }
112 return (0);
113}
114
115rtadd(dst, gate, metric, state)
116 struct sockaddr *dst, *gate;
117 int metric, state;
118{
119 struct afhash h;
120 register struct rt_entry *rt;
121 struct rthash *rh;
122 int af = dst->sa_family, flags;
123 u_int hash;
124
3470e246
MK
125 FIXLEN(dst);
126 FIXLEN(gate);
decc7a4c
KS
127 if (af >= AF_MAX)
128 return;
129 (*afswitch[af].af_hash)(dst, &h);
130 flags = (*afswitch[af].af_ishost)(dst) ? RTF_HOST : 0;
131 if (flags & RTF_HOST) {
132 hash = h.afh_hosthash;
133 rh = &hosthash[hash & ROUTEHASHMASK];
134 } else {
135 hash = h.afh_nethash;
136 rh = &nethash[hash & ROUTEHASHMASK];
137 }
138 rt = (struct rt_entry *)malloc(sizeof (*rt));
139 if (rt == 0)
140 return;
141 rt->rt_hash = hash;
142 rt->rt_dst = *dst;
143 rt->rt_router = *gate;
144 rt->rt_metric = metric;
145 rt->rt_timer = 0;
146 rt->rt_flags = RTF_UP | flags;
147 rt->rt_state = state | RTS_CHANGED;
148 rt->rt_ifp = if_ifwithnet(&rt->rt_router);
149 if (metric)
150 rt->rt_flags |= RTF_GATEWAY;
151 insque(rt, rh);
152 TRACE_ACTION(ADD, rt);
153 /*
154 * If the ioctl fails because the gateway is unreachable
155 * from this host, discard the entry. This should only
156 * occur because of an incorrect entry in /etc/gateways.
157 */
158 if (install && ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0) {
64f255e3
MK
159 if (errno != EEXIST)
160 perror("SIOCADDRT");
decc7a4c
KS
161 if (errno == ENETUNREACH) {
162 TRACE_ACTION(DELETE, rt);
163 remque(rt);
164 free((char *)rt);
165 }
166 }
167}
168
169rtchange(rt, gate, metric)
170 struct rt_entry *rt;
171 struct sockaddr *gate;
172 short metric;
173{
174 int doioctl = 0, metricchanged = 0;
175 struct rtentry oldroute;
176
3470e246 177 FIXLEN(gate);
decc7a4c
KS
178 if (!equal(&rt->rt_router, gate))
179 doioctl++;
180 if (metric != rt->rt_metric)
181 metricchanged++;
182 if (doioctl || metricchanged) {
183 TRACE_ACTION(CHANGE FROM, rt);
184 if (doioctl) {
185 oldroute = rt->rt_rt;
186 rt->rt_router = *gate;
187 }
188 rt->rt_metric = metric;
84f93e8f
KS
189 if ((rt->rt_state & RTS_INTERFACE) && metric) {
190 rt->rt_state &= ~RTS_INTERFACE;
191 syslog(LOG_ERR,
192 "changing route from interface %s (timed out)",
193 rt->rt_ifp->int_name);
194 }
decc7a4c 195 if (metric)
84f93e8f
KS
196 rt->rt_flags |= RTF_GATEWAY;
197 else
198 rt->rt_flags &= ~RTF_GATEWAY;
decc7a4c
KS
199 rt->rt_state |= RTS_CHANGED;
200 TRACE_ACTION(CHANGE TO, rt);
201 }
202 if (doioctl && install) {
3470e246 203#ifndef RTM_ADD
decc7a4c 204 if (ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0)
64f255e3
MK
205 syslog(LOG_ERR, "SIOCADDRT dst %s, gw %s: %m",
206 xns_ntoa(&((struct sockaddr_ns *)&rt->rt_dst)->sns_addr),
207 xns_ntoa(&((struct sockaddr_ns *)&rt->rt_router)->sns_addr));
208 if (delete && ioctl(s, SIOCDELRT, (char *)&oldroute) < 0)
209 perror("SIOCDELRT");
3470e246
MK
210#else
211 if (delete && ioctl(s, SIOCDELRT, (char *)&oldroute) < 0)
212 perror("SIOCDELRT");
213 if (ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0)
214 syslog(LOG_ERR, "SIOCADDRT dst %s, gw %s: %m",
215 xns_ntoa(&((struct sockaddr_ns *)&rt->rt_dst)->sns_addr),
216 xns_ntoa(&((struct sockaddr_ns *)&rt->rt_router)->sns_addr));
217#endif
decc7a4c
KS
218 }
219}
220
221rtdelete(rt)
222 struct rt_entry *rt;
223{
224
3470e246
MK
225 struct sockaddr *sa = &(rt->rt_rt.rt_gateway);
226 FIXLEN(sa);
227#undef rt_dst
228 sa = &(rt->rt_rt.rt_dst);
229 FIXLEN(sa);
84f93e8f
KS
230 if (rt->rt_state & RTS_INTERFACE) {
231 syslog(LOG_ERR, "deleting route to interface %s (timed out)",
232 rt->rt_ifp->int_name);
233 }
decc7a4c 234 TRACE_ACTION(DELETE, rt);
84f93e8f
KS
235 if (install && ioctl(s, SIOCDELRT, (char *)&rt->rt_rt))
236 perror("SIOCDELRT");
decc7a4c
KS
237 remque(rt);
238 free((char *)rt);
239}
240
241rtinit()
242{
243 register struct rthash *rh;
244
245 for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++)
246 rh->rt_forw = rh->rt_back = (struct rt_entry *)rh;
247 for (rh = hosthash; rh < &hosthash[ROUTEHASHSIZ]; rh++)
248 rh->rt_forw = rh->rt_back = (struct rt_entry *)rh;
decc7a4c 249}