|
|
1.1 root 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:
9: #ifndef lint
10: static char sccsid[] = "@(#)tables.c 5.6 (Berkeley) 12/30/86";
11: #endif not lint
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:
24: extern char *xns_ntoa();
25:
26: int install = !DEBUG; /* if 1 call kernel */
27: int delete = 1;
28: /*
29: * Lookup dst in the tables for an exact match.
30: */
31: struct rt_entry *
32: rtlookup(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];
46: again:
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: */
65: struct rt_entry *
66: rtfind(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:
82: again:
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);
89: } else {
90: if (rt->rt_dst.sa_family == af &&
91: (*match)(&rt->rt_dst, dst))
92: return (rt);
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:
105: rtadd(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) {
147: if (errno != EEXIST)
148: perror("SIOCADDRT");
149: if (errno == ENETUNREACH) {
150: TRACE_ACTION(DELETE, rt);
151: remque(rt);
152: free((char *)rt);
153: }
154: }
155: }
156:
157: rtchange(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;
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: }
182: if (metric)
183: rt->rt_flags |= RTF_GATEWAY;
184: else
185: rt->rt_flags &= ~RTF_GATEWAY;
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)
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");
196: }
197: }
198:
199: rtdelete(rt)
200: struct rt_entry *rt;
201: {
202:
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: }
207: TRACE_ACTION(DELETE, rt);
208: if (install && ioctl(s, SIOCDELRT, (char *)&rt->rt_rt))
209: perror("SIOCDELRT");
210: remque(rt);
211: free((char *)rt);
212: }
213:
214: rtinit()
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;
222: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.