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