This source file includes following definitions.
- rt_print
- rt_del
- rt_flush
- 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 static void
67 rt_del(unsigned long dst)
68 {
69 struct rtable *r, *x, *p;
70 unsigned long flags;
71
72 DPRINTF((DBG_RT, "RT: flushing for dst %s\n", in_ntoa(dst)));
73 if ((r = rt_base) == NULL)
74 return;
75
76 save_flags(flags);
77 cli();
78 p = NULL;
79 while(r != NULL)
80 {
81 if (r->rt_dst == dst)
82 {
83 if (p == NULL)
84 rt_base = r->rt_next;
85 else
86 p->rt_next = r->rt_next;
87 x = r->rt_next;
88 kfree_s(r, sizeof(struct rtable));
89 r = x;
90 }
91 else
92 {
93 p = r;
94 r = r->rt_next;
95 }
96 }
97 restore_flags(flags);
98 }
99
100
101
102 void
103 rt_flush(struct device *dev)
104 {
105 struct rtable *r, *x, *p;
106 unsigned long flags;
107
108 DPRINTF((DBG_RT, "RT: flushing for dev 0x%08lx (%s)\n", (long)dev, dev->name));
109 if ((r = rt_base) == NULL) return;
110
111 cli();
112 save_flags(flags);
113
114 p = NULL;
115 while(r != NULL)
116 {
117 if (r->rt_dev == dev)
118 {
119 if (p == NULL)
120 rt_base = r->rt_next;
121 else
122 p->rt_next = r->rt_next;
123 x = r->rt_next;
124 kfree_s(r, sizeof(struct rtable));
125 r = x;
126 }
127 else
128 {
129 p = r;
130 r = r->rt_next;
131 }
132 }
133 restore_flags(flags);
134 }
135
136
137 void
138 rt_add(short flags, unsigned long dst, unsigned long gw, struct device *dev)
139 {
140 struct rtable *r, *r1;
141 struct rtable *rt;
142 int mask=0;
143 unsigned long cpuflags;
144
145
146 rt = (struct rtable *) kmalloc(sizeof(struct rtable), GFP_ATOMIC);
147 if (rt == NULL) {
148 DPRINTF((DBG_RT, "RT: no memory for new route!\n"));
149 return;
150 }
151
152
153 memset(rt, 0, sizeof(struct rtable));
154 rt->rt_flags = (flags | RTF_UP);
155
156
157
158
159 if (gw==dev->pa_addr || gw==dst)
160 {
161 gw=0;
162 rt->rt_flags&=~RTF_GATEWAY;
163 }
164
165 if (gw != 0)
166 rt->rt_flags |= RTF_GATEWAY;
167 rt->rt_dev = dev;
168 rt->rt_gateway = gw;
169
170
171
172
173
174
175 if (flags & RTF_DYNAMIC)
176 {
177 if (flags & RTF_HOST)
178 rt->rt_dst = dst;
179 else
180 {
181
182 rt->rt_dst = (dst & dev->pa_mask);
183 mask=dev->pa_mask;
184
185 if(rt->rt_dst == (dev->pa_addr & dev->pa_mask))
186 {
187 kfree_s(rt, sizeof(struct rtable));
188
189 return;
190 }
191 }
192 }
193 else
194 rt->rt_dst = dst;
195
196 rt_print(rt);
197
198 if (rt_base == NULL)
199 {
200 rt->rt_next = NULL;
201 rt_base = rt;
202 return;
203 }
204
205
206
207
208
209
210
211 if(mask==0)
212
213 {
214 for (mask = 0xff000000L; mask != 0xffffffffL; mask = (mask >> 8) | mask)
215 {
216 if (mask & dst)
217 {
218 mask = mask << 8;
219 break;
220 }
221 }
222 DPRINTF((DBG_RT, "RT: mask = %X\n", mask));
223 }
224
225 save_flags(cpuflags);
226 cli();
227
228 r1 = rt_base;
229
230
231 for (r = rt_base; r != NULL; r = r->rt_next)
232 {
233 if (r->rt_dst == dst)
234 {
235 if (r == rt_base)
236 {
237 rt->rt_next = r->rt_next;
238 rt_base = rt;
239 }
240 else
241 {
242 rt->rt_next = r->rt_next;
243 r1->rt_next = rt;
244 }
245 kfree_s(r, sizeof(struct rtable));
246 restore_flags(cpuflags);
247 return;
248 }
249 r1 = r;
250 }
251
252 r1 = rt_base;
253 for (r = rt_base; r != NULL; r = r->rt_next)
254 {
255
256
257 if (! (r->rt_dst & mask) && (gw==0 || r->rt_flags&RTF_GATEWAY))
258 {
259 DPRINTF((DBG_RT, "RT: adding before r=%X\n", r));
260 rt_print(r);
261 if (r == rt_base)
262 {
263 rt->rt_next = rt_base;
264 rt_base = rt;
265 restore_flags(cpuflags);
266 return;
267 }
268 rt->rt_next = r;
269 r1->rt_next = rt;
270 restore_flags(cpuflags);
271 return;
272 }
273 r1 = r;
274 }
275 DPRINTF((DBG_RT, "RT: adding after r1=%X\n", r1));
276 rt_print(r1);
277
278
279 rt->rt_next = NULL;
280 r1->rt_next = rt;
281 }
282
283
284 static int
285 rt_new(struct rtentry *r)
286 {
287 struct device *dev;
288 struct rtable *rt;
289
290 if ((r->rt_dst.sa_family != AF_INET) ||
291 (r->rt_gateway.sa_family != AF_INET)) {
292 DPRINTF((DBG_RT, "RT: We only know about AF_INET !\n"));
293 return(-EAFNOSUPPORT);
294 }
295
296
297
298
299
300
301
302
303
304
305 if (!(r->rt_flags & RTF_GATEWAY))
306 dev = dev_check(((struct sockaddr_in *) &r->rt_dst)->sin_addr.s_addr);
307 else
308 if ((rt = rt_route(((struct sockaddr_in *) &r->rt_gateway)->sin_addr.
309 s_addr,NULL)))
310 dev = rt->rt_dev;
311 else
312 dev = NULL;
313
314 DPRINTF((DBG_RT, "RT: dev for %s gw ",
315 in_ntoa((*(struct sockaddr_in *)&r->rt_dst).sin_addr.s_addr)));
316 DPRINTF((DBG_RT, "%s (0x%04X) is 0x%X (%s)\n",
317 in_ntoa((*(struct sockaddr_in *)&r->rt_gateway).sin_addr.s_addr),
318 r->rt_flags, dev, (dev == NULL) ? "NONE" : dev->name));
319
320 if (dev == NULL) return(-ENETUNREACH);
321
322 rt_add(r->rt_flags, (*(struct sockaddr_in *) &r->rt_dst).sin_addr.s_addr,
323 (*(struct sockaddr_in *) &r->rt_gateway).sin_addr.s_addr, dev);
324
325 return(0);
326 }
327
328
329 static int
330 rt_kill(struct rtentry *r)
331 {
332 struct sockaddr_in *trg;
333
334 trg = (struct sockaddr_in *) &r->rt_dst;
335 rt_del(trg->sin_addr.s_addr);
336
337 return(0);
338 }
339
340
341
342 int
343 rt_get_info(char *buffer)
344 {
345 struct rtable *r;
346 char *pos;
347
348 pos = buffer;
349
350 pos += sprintf(pos,
351 "Iface\tDestination\tGateway \tFlags\tRefCnt\tUse\tMetric\n");
352
353
354 for (r = rt_base; r != NULL; r = r->rt_next) {
355 pos += sprintf(pos, "%s\t%08lX\t%08lX\t%02X\t%d\t%lu\t%d\n",
356 r->rt_dev->name, r->rt_dst, r->rt_gateway,
357 r->rt_flags, r->rt_refcnt, r->rt_use, r->rt_metric);
358 }
359 return(pos - buffer);
360 }
361
362
363 struct rtable *
364 rt_route(unsigned long daddr, struct options *opt)
365 {
366 struct rtable *rt;
367 int type;
368
369
370
371
372 if ((type=chk_addr(daddr)) == IS_MYADDR) daddr = my_addr();
373
374
375
376
377
378
379
380 for (rt = rt_base; rt != NULL; rt = rt->rt_next)
381 if ((rt->rt_flags & RTF_HOST) && rt->rt_dst == daddr) {
382 DPRINTF((DBG_RT, "%s (%s)\n",
383 rt->rt_dev->name, in_ntoa(rt->rt_gateway)));
384 rt->rt_use++;
385 return(rt);
386 }
387 for (rt = rt_base; rt != NULL; rt = rt->rt_next) {
388 DPRINTF((DBG_RT, "RT: %s via ", in_ntoa(daddr)));
389 if (!(rt->rt_flags & RTF_HOST) && ip_addr_match(rt->rt_dst, daddr)) {
390 DPRINTF((DBG_RT, "%s (%s)\n",
391 rt->rt_dev->name, in_ntoa(rt->rt_gateway)));
392 rt->rt_use++;
393 return(rt);
394 }
395 if (type==IS_BROADCAST && (rt->rt_dev->flags & IFF_BROADCAST) &&
396 ip_addr_match(rt->rt_dev->pa_brdaddr, daddr)) {
397 DPRINTF((DBG_RT, "%s (BCAST %s)\n",
398 rt->rt_dev->name, in_ntoa(rt->rt_dev->pa_brdaddr)));
399 rt->rt_use++;
400 return(rt);
401 }
402 }
403
404 DPRINTF((DBG_RT, "NONE\n"));
405 return(NULL);
406 };
407
408
409 int
410 rt_ioctl(unsigned int cmd, void *arg)
411 {
412 struct device *dev;
413 struct rtentry rt;
414 char namebuf[32];
415 int ret;
416 int err;
417
418 switch(cmd) {
419 case DDIOCSDBG:
420 ret = dbg_ioctl(arg, DBG_RT);
421 break;
422 case SIOCADDRT:
423 case SIOCDELRT:
424 if (!suser()) return(-EPERM);
425 err=verify_area(VERIFY_READ, arg, sizeof(struct rtentry));
426 if(err)
427 return err;
428 memcpy_fromfs(&rt, arg, sizeof(struct rtentry));
429 if (rt.rt_dev) {
430 err=verify_area(VERIFY_READ, rt.rt_dev, sizeof namebuf);
431 if(err)
432 return err;
433 memcpy_fromfs(&namebuf, rt.rt_dev, sizeof namebuf);
434 dev = dev_get(namebuf);
435 rt.rt_dev = dev;
436 }
437 ret = (cmd == SIOCDELRT) ? rt_kill(&rt) : rt_new(&rt);
438 break;
439 default:
440 ret = -EINVAL;
441 }
442
443 return(ret);
444 }