This source file includes following definitions.
- rt_print
- rt_del
- rt_flush
- guess_mask
- rt_add
- rt_new
- rt_kill
- rt_get_info
- rt_route
- rt_ioctl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 #include <asm/segment.h>
25 #include <asm/system.h>
26 #include <linux/types.h>
27 #include <linux/kernel.h>
28 #include <linux/sched.h>
29 #include <linux/string.h>
30 #include <linux/socket.h>
31 #include <linux/sockios.h>
32 #include <linux/errno.h>
33 #include <linux/in.h>
34 #include "inet.h"
35 #include "dev.h"
36 #include "ip.h"
37 #include "protocol.h"
38 #include "route.h"
39 #include "tcp.h"
40 #include "skbuff.h"
41 #include "sock.h"
42 #include "arp.h"
43 #include "icmp.h"
44
45
46 static struct rtable *rt_base = NULL;
47
48
49
50 static void
51 rt_print(struct rtable *rt)
52 {
53 if (rt == NULL || inet_debug != DBG_RT) return;
54
55 printk("RT: %06lx NXT=%06lx FLAGS=0x%02x\n",
56 (long) rt, (long) rt->rt_next, rt->rt_flags);
57 printk(" TARGET=%s ", in_ntoa(rt->rt_dst));
58 printk("GW=%s ", in_ntoa(rt->rt_gateway));
59 printk(" DEV=%s USE=%ld REF=%d\n",
60 (rt->rt_dev == NULL) ? "NONE" : rt->rt_dev->name,
61 rt->rt_use, rt->rt_refcnt);
62 }
63
64
65
66
67
68 static void rt_del(unsigned long dst)
69 {
70 struct rtable *r, **rp;
71 unsigned long flags;
72
73 DPRINTF((DBG_RT, "RT: flushing for dst %s\n", in_ntoa(dst)));
74 rp = &rt_base;
75 save_flags(flags);
76 cli();
77 while((r = *rp) != NULL) {
78 if (r->rt_dst != dst) {
79 rp = &r->rt_next;
80 continue;
81 }
82 *rp = r->rt_next;
83 kfree_s(r, sizeof(struct rtable));
84 }
85 restore_flags(flags);
86 }
87
88
89
90
91
92 void rt_flush(struct device *dev)
93 {
94 struct rtable *r;
95 struct rtable **rp;
96 unsigned long flags;
97
98 DPRINTF((DBG_RT, "RT: flushing for dev 0x%08lx (%s)\n", (long)dev, dev->name));
99 rp = &rt_base;
100 cli();
101 save_flags(flags);
102 while ((r = *rp) != NULL) {
103 if (r->rt_dev != dev) {
104 rp = &r->rt_next;
105 continue;
106 }
107 *rp = r->rt_next;
108 kfree_s(r, sizeof(struct rtable));
109 }
110 restore_flags(flags);
111 }
112
113
114
115
116 static unsigned long guess_mask(unsigned long dst)
117 {
118 unsigned long mask = 0xffffffff;
119
120 while (mask & dst)
121 mask <<= 8;
122 return ~mask;
123 }
124
125
126
127
128 void
129 rt_add(short flags, unsigned long dst, unsigned long gw, struct device *dev)
130 {
131 struct rtable *r, *rt;
132 struct rtable **rp;
133 unsigned long mask;
134 unsigned long cpuflags;
135
136
137 rt = (struct rtable *) kmalloc(sizeof(struct rtable), GFP_ATOMIC);
138 if (rt == NULL) {
139 DPRINTF((DBG_RT, "RT: no memory for new route!\n"));
140 return;
141 }
142
143 memset(rt, 0, sizeof(struct rtable));
144 rt->rt_flags = (flags | RTF_UP);
145
146
147
148 if (gw == dev->pa_addr || gw == dst) {
149 gw=0;
150 rt->rt_flags&=~RTF_GATEWAY;
151 }
152 if (gw != 0)
153 rt->rt_flags |= RTF_GATEWAY;
154 rt->rt_dev = dev;
155 rt->rt_gateway = gw;
156 if (flags & RTF_HOST) {
157 mask = 0xffffffff;
158 rt->rt_dst = dst;
159 } else {
160 if (!((dst ^ dev->pa_addr) & dev->pa_mask)) {
161 mask = dev->pa_mask;
162 dst &= mask;
163 if (flags & RTF_DYNAMIC) {
164 kfree_s(rt, sizeof(struct rtable));
165
166 return;
167 }
168 } else
169 mask = guess_mask(dst);
170 rt->rt_dst = dst;
171 }
172 rt->rt_mask = mask;
173 rt_print(rt);
174
175
176
177
178
179 save_flags(cpuflags);
180 cli();
181
182 rp = &rt_base;
183 while ((r = *rp) != NULL) {
184 if (r->rt_dst != dst) {
185 rp = &r->rt_next;
186 continue;
187 }
188 *rp = r->rt_next;
189 kfree_s(r, sizeof(struct rtable));
190 }
191
192 rp = &rt_base;
193 while ((r = *rp) != NULL) {
194 if ((r->rt_mask & mask) != mask)
195 break;
196 rp = &r->rt_next;
197 }
198 rt->rt_next = r;
199 *rp = rt;
200 restore_flags(cpuflags);
201 return;
202 }
203
204
205 static int
206 rt_new(struct rtentry *r)
207 {
208 struct device *dev;
209 struct rtable *rt;
210
211 if ((r->rt_dst.sa_family != AF_INET) ||
212 (r->rt_gateway.sa_family != AF_INET)) {
213 DPRINTF((DBG_RT, "RT: We only know about AF_INET !\n"));
214 return(-EAFNOSUPPORT);
215 }
216
217
218
219
220
221
222
223
224
225
226 if (!(r->rt_flags & RTF_GATEWAY))
227 dev = dev_check(((struct sockaddr_in *) &r->rt_dst)->sin_addr.s_addr);
228 else
229 if ((rt = rt_route(((struct sockaddr_in *) &r->rt_gateway)->sin_addr.
230 s_addr,NULL)))
231 dev = rt->rt_dev;
232 else
233 dev = NULL;
234
235 DPRINTF((DBG_RT, "RT: dev for %s gw ",
236 in_ntoa((*(struct sockaddr_in *)&r->rt_dst).sin_addr.s_addr)));
237 DPRINTF((DBG_RT, "%s (0x%04X) is 0x%X (%s)\n",
238 in_ntoa((*(struct sockaddr_in *)&r->rt_gateway).sin_addr.s_addr),
239 r->rt_flags, dev, (dev == NULL) ? "NONE" : dev->name));
240
241 if (dev == NULL) return(-ENETUNREACH);
242
243 rt_add(r->rt_flags, (*(struct sockaddr_in *) &r->rt_dst).sin_addr.s_addr,
244 (*(struct sockaddr_in *) &r->rt_gateway).sin_addr.s_addr, dev);
245
246 return(0);
247 }
248
249
250 static int
251 rt_kill(struct rtentry *r)
252 {
253 struct sockaddr_in *trg;
254
255 trg = (struct sockaddr_in *) &r->rt_dst;
256 rt_del(trg->sin_addr.s_addr);
257
258 return(0);
259 }
260
261
262
263 int
264 rt_get_info(char *buffer)
265 {
266 struct rtable *r;
267 char *pos;
268
269 pos = buffer;
270
271 pos += sprintf(pos,
272 "Iface\tDestination\tGateway \tFlags\tRefCnt\tUse\tMetric\n");
273
274
275 for (r = rt_base; r != NULL; r = r->rt_next) {
276 pos += sprintf(pos, "%s\t%08lX\t%08lX\t%02X\t%d\t%lu\t%d\n",
277 r->rt_dev->name, r->rt_dst, r->rt_gateway,
278 r->rt_flags, r->rt_refcnt, r->rt_use, r->rt_metric);
279 }
280 return(pos - buffer);
281 }
282
283
284
285
286
287 struct rtable * rt_route(unsigned long daddr, struct options *opt)
288 {
289 struct rtable *rt;
290 int type;
291
292
293
294
295 if ((type=chk_addr(daddr)) == IS_MYADDR) daddr = my_addr();
296
297
298
299
300
301
302
303
304
305
306 for (rt = rt_base; rt != NULL; rt = rt->rt_next) {
307 if (!((rt->rt_dst ^ daddr) & rt->rt_mask)) {
308 rt->rt_use++;
309 return rt;
310 }
311
312 if ((rt->rt_dev->flags & IFF_BROADCAST) &&
313 rt->rt_dev->pa_brdaddr == daddr) {
314 rt->rt_use++;
315 return(rt);
316 }
317 }
318 return NULL;
319 }
320
321
322 int
323 rt_ioctl(unsigned int cmd, void *arg)
324 {
325 struct device *dev;
326 struct rtentry rt;
327 char namebuf[32];
328 int ret;
329 int err;
330
331 switch(cmd) {
332 case DDIOCSDBG:
333 ret = dbg_ioctl(arg, DBG_RT);
334 break;
335 case SIOCADDRT:
336 case SIOCDELRT:
337 if (!suser()) return(-EPERM);
338 err=verify_area(VERIFY_READ, arg, sizeof(struct rtentry));
339 if(err)
340 return err;
341 memcpy_fromfs(&rt, arg, sizeof(struct rtentry));
342 if (rt.rt_dev) {
343 err=verify_area(VERIFY_READ, rt.rt_dev, sizeof namebuf);
344 if(err)
345 return err;
346 memcpy_fromfs(&namebuf, rt.rt_dev, sizeof namebuf);
347 dev = dev_get(namebuf);
348 rt.rt_dev = dev;
349 }
350 ret = (cmd == SIOCDELRT) ? rt_kill(&rt) : rt_new(&rt);
351 break;
352 default:
353 ret = -EINVAL;
354 }
355
356 return(ret);
357 }