|
|
1.1 root 1: /*
2: * Copyright (c) 1983 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: #ifndef lint
8: static char sccsid[] = "@(#)tables.c 5.5 (Berkeley) 5/28/86";
9: #endif not lint
10:
11: /*
12: * Routing Table Management Daemon
13: */
14: #include "defs.h"
15: #include <sys/ioctl.h>
16: #include <errno.h>
17: #include <syslog.h>
18:
19: #ifndef DEBUG
20: #define DEBUG 0
21: #endif
22:
23: int install = !DEBUG; /* if 1 call kernel */
24:
25: /*
26: * Lookup dst in the tables for an exact match.
27: */
28: struct rt_entry *
29: rtlookup(dst)
30: struct sockaddr *dst;
31: {
32: register struct rt_entry *rt;
33: register struct rthash *rh;
34: register u_int hash;
35: struct afhash h;
36: int doinghost = 1;
37:
38: if (dst->sa_family >= af_max)
39: return (0);
40: (*afswitch[dst->sa_family].af_hash)(dst, &h);
41: hash = h.afh_hosthash;
42: rh = &hosthash[hash & ROUTEHASHMASK];
43: again:
44: for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
45: if (rt->rt_hash != hash)
46: continue;
47: if (equal(&rt->rt_dst, dst))
48: return (rt);
49: }
50: if (doinghost) {
51: doinghost = 0;
52: hash = h.afh_nethash;
53: rh = &nethash[hash & ROUTEHASHMASK];
54: goto again;
55: }
56: return (0);
57: }
58:
59: /*
60: * Find a route to dst as the kernel would.
61: */
62: struct rt_entry *
63: rtfind(dst)
64: struct sockaddr *dst;
65: {
66: register struct rt_entry *rt;
67: register struct rthash *rh;
68: register u_int hash;
69: struct afhash h;
70: int af = dst->sa_family;
71: int doinghost = 1, (*match)();
72:
73: if (af >= af_max)
74: return (0);
75: (*afswitch[af].af_hash)(dst, &h);
76: hash = h.afh_hosthash;
77: rh = &hosthash[hash & ROUTEHASHMASK];
78:
79: again:
80: for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
81: if (rt->rt_hash != hash)
82: continue;
83: if (doinghost) {
84: if (equal(&rt->rt_dst, dst))
85: return (rt);
86: } else {
87: if (rt->rt_dst.sa_family == af &&
88: (*match)(&rt->rt_dst, dst))
89: return (rt);
90: }
91: }
92: if (doinghost) {
93: doinghost = 0;
94: hash = h.afh_nethash;
95: rh = &nethash[hash & ROUTEHASHMASK];
96: match = afswitch[af].af_netmatch;
97: goto again;
98: }
99: return (0);
100: }
101:
102: rtadd(dst, gate, metric, state)
103: struct sockaddr *dst, *gate;
104: int metric, state;
105: {
106: struct afhash h;
107: register struct rt_entry *rt;
108: struct rthash *rh;
109: int af = dst->sa_family, flags;
110: u_int hash;
111:
112: if (af >= af_max)
113: return;
114: (*afswitch[af].af_hash)(dst, &h);
115: flags = (*afswitch[af].af_rtflags)(dst);
116: /*
117: * Subnet flag isn't visible to kernel, move to state. XXX
118: */
119: if (flags & RTF_SUBNET) {
120: state |= RTS_SUBNET;
121: flags &= ~RTF_SUBNET;
122: }
123: if (flags & RTF_HOST) {
124: hash = h.afh_hosthash;
125: rh = &hosthash[hash & ROUTEHASHMASK];
126: } else {
127: hash = h.afh_nethash;
128: rh = &nethash[hash & ROUTEHASHMASK];
129: }
130: rt = (struct rt_entry *)malloc(sizeof (*rt));
131: if (rt == 0)
132: return;
133: rt->rt_hash = hash;
134: rt->rt_dst = *dst;
135: rt->rt_router = *gate;
136: rt->rt_metric = metric;
137: rt->rt_timer = 0;
138: rt->rt_flags = RTF_UP | flags;
139: rt->rt_state = state | RTS_CHANGED;
140: rt->rt_ifp = if_ifwithdstaddr(&rt->rt_router);
141: if (rt->rt_ifp == 0)
142: rt->rt_ifp = if_ifwithnet(&rt->rt_router);
143: if (metric)
144: rt->rt_flags |= RTF_GATEWAY;
145: insque(rt, rh);
146: TRACE_ACTION(ADD, rt);
147: /*
148: * If the ioctl fails because the gateway is unreachable
149: * from this host, discard the entry. This should only
150: * occur because of an incorrect entry in /etc/gateways.
151: */
152: if (install && (rt->rt_state & (RTS_INTERNAL | RTS_EXTERNAL)) == 0 &&
153: ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0) {
154: perror("SIOCADDRT");
155: if (errno == ENETUNREACH) {
156: TRACE_ACTION(DELETE, rt);
157: remque(rt);
158: free((char *)rt);
159: }
160: }
161: }
162:
163: rtchange(rt, gate, metric)
164: struct rt_entry *rt;
165: struct sockaddr *gate;
166: short metric;
167: {
168: int doioctl = 0, metricchanged = 0;
169: struct rtentry oldroute;
170:
171: if (!equal(&rt->rt_router, gate) && (rt->rt_state & RTS_INTERNAL) == 0)
172: doioctl++;
173: if (metric != rt->rt_metric)
174: metricchanged++;
175: if (doioctl || metricchanged) {
176: TRACE_ACTION(CHANGE FROM, rt);
177: if ((rt->rt_state & RTS_INTERFACE) && metric) {
178: rt->rt_state &= ~RTS_INTERFACE;
179: syslog(LOG_ERR,
180: "changing route from interface %s (timed out)",
181: rt->rt_ifp->int_name);
182: }
183: if (doioctl) {
184: oldroute = rt->rt_rt;
185: rt->rt_router = *gate;
186: rt->rt_ifp = if_ifwithdstaddr(&rt->rt_router);
187: if (rt->rt_ifp == 0)
188: rt->rt_ifp = if_ifwithnet(&rt->rt_router);
189: }
190: rt->rt_metric = metric;
191: if (metric)
192: rt->rt_flags |= RTF_GATEWAY;
193: else
194: rt->rt_flags &= ~RTF_GATEWAY;
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)
200: perror("SIOCADDRT");
201: if (ioctl(s, SIOCDELRT, (char *)&oldroute) < 0)
202: perror("SIOCDELRT");
203: }
204: }
205:
206: rtdelete(rt)
207: struct rt_entry *rt;
208: {
209:
210: if (rt->rt_state & RTS_INTERFACE)
211: syslog(LOG_ERR, "deleting route to interface %s (timed out)",
212: rt->rt_ifp->int_name);
213: TRACE_ACTION(DELETE, rt);
214: if (install && (rt->rt_state & (RTS_INTERNAL | RTS_EXTERNAL)) == 0 &&
215: ioctl(s, SIOCDELRT, (char *)&rt->rt_rt))
216: perror("SIOCDELRT");
217: remque(rt);
218: free((char *)rt);
219: }
220:
221: /*
222: * If we have an interface to the wide, wide world,
223: * add an entry for an Internet default route (wildcard) to the internal
224: * tables and advertise it. This route is not added to the kernel routes,
225: * but this entry prevents us from listening to other people's defaults
226: * and installing them in the kernel here.
227: */
228: rtdefault()
229: {
230: extern struct sockaddr inet_default;
231:
232: rtadd(&inet_default, &inet_default, 0,
233: RTS_CHANGED | RTS_PASSIVE | RTS_INTERNAL);
234: }
235:
236: rtinit()
237: {
238: register struct rthash *rh;
239:
240: for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++)
241: rh->rt_forw = rh->rt_back = (struct rt_entry *)rh;
242: for (rh = hosthash; rh < &hosthash[ROUTEHASHSIZ]; rh++)
243: rh->rt_forw = rh->rt_back = (struct rt_entry *)rh;
244: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.