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