|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)tables.c 4.4 (Berkeley) 9/25/83";
3: #endif
4:
5: /*
6: * Routing Table Management Daemon
7: */
8: #include "defs.h"
9: #include <sys/ioctl.h>
10: #include <errno.h>
11:
12: #ifndef DEBUG
13: #define DEBUG 0
14: #endif
15:
16: int install = !DEBUG; /* if 1 call kernel */
17:
18: /*
19: * Lookup dst in the tables for an exact match.
20: */
21: struct rt_entry *
22: rtlookup(dst)
23: struct sockaddr *dst;
24: {
25: register struct rt_entry *rt;
26: register struct rthash *rh;
27: register int hash;
28: struct afhash h;
29: int doinghost = 1;
30:
31: if (dst->sa_family >= AF_MAX)
32: return (0);
33: (*afswitch[dst->sa_family].af_hash)(dst, &h);
34: hash = h.afh_hosthash;
35: rh = &hosthash[hash % ROUTEHASHSIZ];
36: again:
37: for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
38: if (rt->rt_hash != hash)
39: continue;
40: if (equal(&rt->rt_dst, dst))
41: return (rt);
42: }
43: if (doinghost) {
44: doinghost = 0;
45: hash = h.afh_nethash;
46: rh = &nethash[hash % ROUTEHASHSIZ];
47: goto again;
48: }
49: return (0);
50: }
51:
52: /*
53: * Find a route to dst as the kernel would.
54: */
55: struct rt_entry *
56: rtfind(dst)
57: struct sockaddr *dst;
58: {
59: register struct rt_entry *rt;
60: register struct rthash *rh;
61: register int hash;
62: struct afhash h;
63: int af = dst->sa_family;
64: int doinghost = 1, (*match)();
65:
66: if (af >= AF_MAX)
67: return (0);
68: (*afswitch[af].af_hash)(dst, &h);
69: hash = h.afh_hosthash;
70: rh = &hosthash[hash % ROUTEHASHSIZ];
71:
72: again:
73: for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
74: if (rt->rt_hash != hash)
75: continue;
76: if (doinghost) {
77: if (equal(&rt->rt_dst, dst))
78: return (rt);
79: } else {
80: if (rt->rt_dst.sa_family == af &&
81: (*match)(&rt->rt_dst, dst))
82: return (rt);
83: }
84: }
85: if (doinghost) {
86: doinghost = 0;
87: hash = h.afh_nethash;
88: rh = &nethash[hash % ROUTEHASHSIZ];
89: match = afswitch[af].af_netmatch;
90: goto again;
91: }
92: return (0);
93: }
94:
95: rtadd(dst, gate, metric, state)
96: struct sockaddr *dst, *gate;
97: int metric, state;
98: {
99: struct afhash h;
100: register struct rt_entry *rt;
101: struct rthash *rh;
102: int af = dst->sa_family, flags, hash;
103:
104: if (af >= AF_MAX)
105: return;
106: (*afswitch[af].af_hash)(dst, &h);
107: flags = (*afswitch[af].af_checkhost)(dst) ? RTF_HOST : 0;
108: if (flags & RTF_HOST) {
109: hash = h.afh_hosthash;
110: rh = &hosthash[hash % ROUTEHASHSIZ];
111: } else {
112: hash = h.afh_nethash;
113: rh = &nethash[hash % ROUTEHASHSIZ];
114: }
115: rt = (struct rt_entry *)malloc(sizeof (*rt));
116: if (rt == 0)
117: return;
118: rt->rt_hash = hash;
119: rt->rt_dst = *dst;
120: rt->rt_router = *gate;
121: rt->rt_metric = metric;
122: rt->rt_timer = 0;
123: rt->rt_flags = RTF_UP | flags;
124: rt->rt_state = state | RTS_CHANGED;
125: rt->rt_ifp = if_ifwithnet(&rt->rt_router);
126: if (metric)
127: rt->rt_flags |= RTF_GATEWAY;
128: insque(rt, rh);
129: TRACE_ACTION(ADD, rt);
130: /*
131: * If the ioctl fails because the gateway is unreachable
132: * from this host, discard the entry. This should only
133: * occur because of an incorrect entry in /etc/gateways.
134: */
135: if (install && ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0) {
136: perror("SIOCADDRT");
137: if (errno == ENETUNREACH) {
138: TRACE_ACTION(DELETE, rt);
139: remque(rt);
140: free((char *)rt);
141: }
142: }
143: }
144:
145: rtchange(rt, gate, metric)
146: struct rt_entry *rt;
147: struct sockaddr *gate;
148: short metric;
149: {
150: int doioctl = 0, metricchanged = 0;
151: struct rtentry oldroute;
152:
153: if (!equal(&rt->rt_router, gate))
154: doioctl++;
155: if (metric != rt->rt_metric) {
156: metricchanged++;
157: rt->rt_metric = metric;
158: }
159: if (doioctl || metricchanged) {
160: TRACE_ACTION(CHANGE, rt);
161: rt->rt_state |= RTS_CHANGED;
162: }
163: if (doioctl) {
164: oldroute = rt->rt_rt;
165: rt->rt_router = *gate;
166: if (install) {
167: if (ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0)
168: perror("SIOCADDRT");
169: if (ioctl(s, SIOCDELRT, (char *)&oldroute) < 0)
170: perror("SIOCDELRT");
171: }
172: }
173: }
174:
175: rtdelete(rt)
176: struct rt_entry *rt;
177: {
178:
179: TRACE_ACTION(DELETE, rt);
180: if (install && ioctl(s, SIOCDELRT, (char *)&rt->rt_rt))
181: perror("SIOCDELRT");
182: remque(rt);
183: free((char *)rt);
184: }
185:
186: rtinit()
187: {
188: register struct rthash *rh;
189:
190: for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++)
191: rh->rt_forw = rh->rt_back = (struct rt_entry *)rh;
192: for (rh = hosthash; rh < &hosthash[ROUTEHASHSIZ]; rh++)
193: rh->rt_forw = rh->rt_back = (struct rt_entry *)rh;
194: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.