Commit | Line | Data |
---|---|---|
b9b7b06a | 1 | #ifndef lint |
55d340a4 | 2 | static char sccsid[] = "@(#)tables.c 4.3 (Berkeley) %G%"; |
b9b7b06a SL |
3 | #endif |
4 | ||
5 | /* | |
6 | * Routing Table Management Daemon | |
7 | */ | |
7fe7fe74 | 8 | #include "defs.h" |
b9b7b06a SL |
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 | if (install && ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0) | |
131 | perror("SIOCADDRT"); | |
132 | } | |
133 | ||
134 | rtchange(rt, gate, metric) | |
135 | struct rt_entry *rt; | |
136 | struct sockaddr *gate; | |
137 | short metric; | |
138 | { | |
139 | int doioctl = 0, metricchanged = 0; | |
140 | struct rtentry oldroute; | |
141 | ||
142 | if (!equal(&rt->rt_router, gate)) | |
143 | doioctl++; | |
144 | if (metric != rt->rt_metric) { | |
145 | metricchanged++; | |
146 | rt->rt_metric = metric; | |
147 | } | |
148 | if (doioctl || metricchanged) { | |
149 | TRACE_ACTION(CHANGE, rt); | |
150 | rt->rt_state |= RTS_CHANGED; | |
151 | } | |
152 | if (doioctl) { | |
153 | oldroute = rt->rt_rt; | |
154 | rt->rt_router = *gate; | |
155 | if (install) { | |
156 | if (ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0) | |
157 | perror("SIOCADDRT"); | |
158 | if (ioctl(s, SIOCDELRT, (char *)&oldroute) < 0) | |
159 | perror("SIOCDELRT"); | |
160 | } | |
161 | } | |
162 | } | |
163 | ||
164 | rtdelete(rt) | |
165 | struct rt_entry *rt; | |
166 | { | |
167 | TRACE_ACTION(DELETE, rt); | |
168 | if (install && ioctl(s, SIOCDELRT, (char *)&rt->rt_rt)) | |
169 | perror("SIOCDELRT"); | |
170 | remque(rt); | |
171 | free((char *)rt); | |
172 | } | |
173 | ||
174 | rtinit() | |
175 | { | |
176 | register struct rthash *rh; | |
177 | ||
178 | for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++) | |
179 | rh->rt_forw = rh->rt_back = (struct rt_entry *)rh; | |
180 | for (rh = hosthash; rh < &hosthash[ROUTEHASHSIZ]; rh++) | |
181 | rh->rt_forw = rh->rt_back = (struct rt_entry *)rh; | |
182 | } |