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