This source file includes following definitions.
- rt_del
- ip_rt_flush
- default_mask
- guess_mask
- get_gw_dev
- ip_rt_add
- bad_mask
- rt_new
- rt_kill
- rt_get_info
- ip_rt_route
- ip_rt_local
- ip_get_old_rtent
- ip_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
25
26
27
28
29
30
31
32
33
34 #include <asm/segment.h>
35 #include <asm/system.h>
36 #include <linux/types.h>
37 #include <linux/kernel.h>
38 #include <linux/sched.h>
39 #include <linux/mm.h>
40 #include <linux/string.h>
41 #include <linux/socket.h>
42 #include <linux/sockios.h>
43 #include <linux/errno.h>
44 #include <linux/in.h>
45 #include <linux/inet.h>
46 #include <linux/netdevice.h>
47 #include "ip.h"
48 #include "protocol.h"
49 #include "route.h"
50 #include "tcp.h"
51 #include <linux/skbuff.h>
52 #include "sock.h"
53 #include "icmp.h"
54
55
56
57
58
59 static struct rtable *rt_base = NULL;
60
61
62
63
64
65 static struct rtable *rt_loopback = NULL;
66
67
68
69
70
71 static void rt_del(unsigned long dst, char *devname)
72 {
73 struct rtable *r, **rp;
74 unsigned long flags;
75
76 rp = &rt_base;
77
78
79
80
81
82
83 save_flags(flags);
84 cli();
85 while((r = *rp) != NULL)
86 {
87
88 if ( r->rt_dst != dst ||
89 (devname != NULL && strcmp((r->rt_dev)->name,devname) != 0) )
90 {
91 rp = &r->rt_next;
92 continue;
93 }
94 *rp = r->rt_next;
95
96
97
98
99
100 if (rt_loopback == r)
101 rt_loopback = NULL;
102 kfree_s(r, sizeof(struct rtable));
103 }
104 restore_flags(flags);
105 }
106
107
108
109
110
111
112
113 void ip_rt_flush(struct device *dev)
114 {
115 struct rtable *r;
116 struct rtable **rp;
117 unsigned long flags;
118
119 rp = &rt_base;
120 save_flags(flags);
121 cli();
122 while ((r = *rp) != NULL) {
123 if (r->rt_dev != dev) {
124 rp = &r->rt_next;
125 continue;
126 }
127 *rp = r->rt_next;
128 if (rt_loopback == r)
129 rt_loopback = NULL;
130 kfree_s(r, sizeof(struct rtable));
131 }
132 restore_flags(flags);
133 }
134
135
136
137
138
139
140
141
142
143 static inline unsigned long default_mask(unsigned long dst)
144 {
145 dst = ntohl(dst);
146 if (IN_CLASSA(dst))
147 return htonl(IN_CLASSA_NET);
148 if (IN_CLASSB(dst))
149 return htonl(IN_CLASSB_NET);
150 return htonl(IN_CLASSC_NET);
151 }
152
153
154
155
156
157
158 static unsigned long guess_mask(unsigned long dst, struct device * dev)
159 {
160 unsigned long mask;
161
162 if (!dst)
163 return 0;
164 mask = default_mask(dst);
165 if ((dst ^ dev->pa_addr) & mask)
166 return mask;
167 return dev->pa_mask;
168 }
169
170
171
172
173
174
175 static inline struct device * get_gw_dev(unsigned long gw)
176 {
177 struct rtable * rt;
178
179 for (rt = rt_base ; ; rt = rt->rt_next)
180 {
181 if (!rt)
182 return NULL;
183 if ((gw ^ rt->rt_dst) & rt->rt_mask)
184 continue;
185
186
187
188
189 if (rt->rt_flags & RTF_GATEWAY)
190 return NULL;
191 return rt->rt_dev;
192 }
193 }
194
195
196
197
198
199
200
201
202
203 void ip_rt_add(short flags, unsigned long dst, unsigned long mask,
204 unsigned long gw, struct device *dev, unsigned short mtu, unsigned long window)
205 {
206 struct rtable *r, *rt;
207 struct rtable **rp;
208 unsigned long cpuflags;
209
210
211
212
213
214 if (flags & RTF_HOST)
215 {
216 mask = 0xffffffff;
217 }
218
219
220
221
222
223 else if (!mask)
224 {
225 if (!((dst ^ dev->pa_addr) & dev->pa_mask))
226 {
227 mask = dev->pa_mask;
228 flags &= ~RTF_GATEWAY;
229 if (flags & RTF_DYNAMIC)
230 {
231
232 return;
233 }
234 }
235 else
236 mask = guess_mask(dst, dev);
237 dst &= mask;
238 }
239
240
241
242
243
244 if (gw == dev->pa_addr)
245 flags &= ~RTF_GATEWAY;
246
247 if (flags & RTF_GATEWAY)
248 {
249
250
251
252
253 if (dev != get_gw_dev(gw))
254 return;
255
256 flags |= RTF_GATEWAY;
257 }
258 else
259 gw = 0;
260
261
262
263
264
265 rt = (struct rtable *) kmalloc(sizeof(struct rtable), GFP_ATOMIC);
266 if (rt == NULL)
267 {
268 return;
269 }
270 memset(rt, 0, sizeof(struct rtable));
271 rt->rt_flags = flags | RTF_UP;
272 rt->rt_dst = dst;
273 rt->rt_dev = dev;
274 rt->rt_gateway = gw;
275 rt->rt_mask = mask;
276 rt->rt_mss = dev->mtu - HEADER_SIZE;
277 rt->rt_window = 0;
278
279
280
281 if(rt->rt_flags & RTF_MSS)
282 rt->rt_mss = mtu;
283
284 if(rt->rt_flags & RTF_WINDOW)
285 rt->rt_window = window;
286
287
288
289
290
291
292
293
294 save_flags(cpuflags);
295 cli();
296
297
298
299
300
301 rp = &rt_base;
302 while ((r = *rp) != NULL)
303 {
304 if (r->rt_dst != dst ||
305 r->rt_mask != mask)
306 {
307 rp = &r->rt_next;
308 continue;
309 }
310 *rp = r->rt_next;
311 if (rt_loopback == r)
312 rt_loopback = NULL;
313 kfree_s(r, sizeof(struct rtable));
314 }
315
316
317
318
319
320 rp = &rt_base;
321 while ((r = *rp) != NULL) {
322 if ((r->rt_mask & mask) != mask)
323 break;
324 rp = &r->rt_next;
325 }
326 rt->rt_next = r;
327 *rp = rt;
328
329
330
331
332
333 if ((rt->rt_dev->flags & IFF_LOOPBACK) && !rt_loopback)
334 rt_loopback = rt;
335
336
337
338
339
340 restore_flags(cpuflags);
341 return;
342 }
343
344
345
346
347
348
349 static inline int bad_mask(unsigned long mask, unsigned long addr)
350 {
351 if (addr & (mask = ~mask))
352 return 1;
353 mask = ntohl(mask);
354 if (mask & (mask+1))
355 return 1;
356 return 0;
357 }
358
359
360
361
362
363 static int rt_new(struct rtentry *r)
364 {
365 int err;
366 char * devname;
367 struct device * dev = NULL;
368 unsigned long flags, daddr, mask, gw;
369
370
371
372
373
374 if ((devname = r->rt_dev) != NULL)
375 {
376 err = getname(devname, &devname);
377 if (err)
378 return err;
379 dev = dev_get(devname);
380 putname(devname);
381 if (!dev)
382 return -EINVAL;
383 }
384
385
386
387
388
389 if (r->rt_dst.sa_family != AF_INET)
390 return -EAFNOSUPPORT;
391
392
393
394
395
396 flags = r->rt_flags;
397 daddr = ((struct sockaddr_in *) &r->rt_dst)->sin_addr.s_addr;
398 mask = ((struct sockaddr_in *) &r->rt_genmask)->sin_addr.s_addr;
399 gw = ((struct sockaddr_in *) &r->rt_gateway)->sin_addr.s_addr;
400
401
402
403
404
405
406
407
408 if (!dev && (flags & RTF_GATEWAY))
409 {
410 struct device *dev2;
411 for (dev2 = dev_base ; dev2 != NULL ; dev2 = dev2->next)
412 {
413 if ((dev2->flags & IFF_UP) && dev2->pa_addr == gw)
414 {
415 flags &= ~RTF_GATEWAY;
416 dev = dev2;
417 break;
418 }
419 }
420 }
421
422
423
424
425
426 if (bad_mask(mask, daddr))
427 mask = 0;
428
429
430
431
432
433 if (flags & RTF_HOST)
434 mask = 0xffffffff;
435 else if (mask && r->rt_genmask.sa_family != AF_INET)
436 return -EAFNOSUPPORT;
437
438
439
440
441
442 if (flags & RTF_GATEWAY)
443 {
444 if (r->rt_gateway.sa_family != AF_INET)
445 return -EAFNOSUPPORT;
446 if (!dev)
447 dev = get_gw_dev(gw);
448 }
449 else if (!dev)
450 dev = ip_dev_check(daddr);
451
452
453
454
455
456 if (dev == NULL)
457 return -ENETUNREACH;
458
459
460
461
462
463 ip_rt_add(flags, daddr, mask, gw, dev, r->rt_mss, r->rt_window);
464 return 0;
465 }
466
467
468
469
470
471
472 static int rt_kill(struct rtentry *r)
473 {
474 struct sockaddr_in *trg;
475 char *devname;
476 int err;
477
478 trg = (struct sockaddr_in *) &r->rt_dst;
479 if ((devname = r->rt_dev) != NULL)
480 {
481 err = getname(devname, &devname);
482 if (err)
483 return err;
484 }
485 rt_del(trg->sin_addr.s_addr, devname);
486 if ( devname != NULL )
487 putname(devname);
488 return 0;
489 }
490
491
492
493
494
495
496 int rt_get_info(char *buffer, char **start, off_t offset, int length)
497 {
498 struct rtable *r;
499 int len=0;
500 off_t pos=0;
501 off_t begin=0;
502 int size;
503
504 len += sprintf(buffer,
505 "Iface\tDestination\tGateway \tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU\tWindow\n");
506 pos=len;
507
508
509
510
511
512 for (r = rt_base; r != NULL; r = r->rt_next)
513 {
514 size = sprintf(buffer+len, "%s\t%08lX\t%08lX\t%02X\t%d\t%lu\t%d\t%08lX\t%d\t%lu\n",
515 r->rt_dev->name, r->rt_dst, r->rt_gateway,
516 r->rt_flags, r->rt_refcnt, r->rt_use, r->rt_metric,
517 r->rt_mask, (int)r->rt_mss, r->rt_window);
518 len+=size;
519 pos+=size;
520 if(pos<offset)
521 {
522 len=0;
523 begin=pos;
524 }
525 if(pos>offset+length)
526 break;
527 }
528
529 *start=buffer+(offset-begin);
530 len-=(offset-begin);
531 if(len>length)
532 len=length;
533 return len;
534 }
535
536
537
538
539
540 #define early_out ({ goto no_route; 1; })
541
542
543
544
545
546
547
548
549 struct rtable * ip_rt_route(unsigned long daddr, struct options *opt, unsigned long *src_addr)
550 {
551 struct rtable *rt;
552
553 for (rt = rt_base; rt != NULL || early_out ; rt = rt->rt_next)
554 {
555 if (!((rt->rt_dst ^ daddr) & rt->rt_mask))
556 break;
557
558
559
560 if (rt->rt_flags & RTF_GATEWAY)
561 continue;
562 if ((rt->rt_dev->flags & IFF_BROADCAST) &&
563 (rt->rt_dev->pa_brdaddr == daddr))
564 break;
565 }
566
567 if(src_addr!=NULL)
568 *src_addr= rt->rt_dev->pa_addr;
569
570 if (daddr == rt->rt_dev->pa_addr) {
571 if ((rt = rt_loopback) == NULL)
572 goto no_route;
573 }
574 rt->rt_use++;
575 return rt;
576 no_route:
577 return NULL;
578 }
579
580 struct rtable * ip_rt_local(unsigned long daddr, struct options *opt, unsigned long *src_addr)
581 {
582 struct rtable *rt;
583
584 for (rt = rt_base; rt != NULL || early_out ; rt = rt->rt_next)
585 {
586
587
588
589 if (rt->rt_flags&RTF_GATEWAY)
590 continue;
591
592 if (!((rt->rt_dst ^ daddr) & rt->rt_mask))
593 break;
594
595
596
597
598 if ((rt->rt_dev->flags & IFF_BROADCAST) &&
599 rt->rt_dev->pa_brdaddr == daddr)
600 break;
601 }
602
603 if(src_addr!=NULL)
604 *src_addr= rt->rt_dev->pa_addr;
605
606 if (daddr == rt->rt_dev->pa_addr) {
607 if ((rt = rt_loopback) == NULL)
608 goto no_route;
609 }
610 rt->rt_use++;
611 return rt;
612 no_route:
613 return NULL;
614 }
615
616
617
618
619
620 static int ip_get_old_rtent(struct old_rtentry * src, struct rtentry * rt)
621 {
622 int err;
623 struct old_rtentry tmp;
624
625 err=verify_area(VERIFY_READ, src, sizeof(*src));
626 if (err)
627 return err;
628 memcpy_fromfs(&tmp, src, sizeof(*src));
629 memset(rt, 0, sizeof(*rt));
630 rt->rt_dst = tmp.rt_dst;
631 rt->rt_gateway = tmp.rt_gateway;
632 rt->rt_genmask.sa_family = AF_INET;
633 ((struct sockaddr_in *) &rt->rt_genmask)->sin_addr.s_addr = tmp.rt_genmask;
634 rt->rt_flags = tmp.rt_flags;
635 rt->rt_dev = tmp.rt_dev;
636 printk("Warning: obsolete routing request made.\n");
637 return 0;
638 }
639
640
641
642
643
644 int ip_rt_ioctl(unsigned int cmd, void *arg)
645 {
646 int err;
647 struct rtentry rt;
648
649 switch(cmd)
650 {
651 case SIOCADDRTOLD:
652 case SIOCDELRTOLD:
653 if (!suser())
654 return -EPERM;
655 err = ip_get_old_rtent((struct old_rtentry *) arg, &rt);
656 if (err)
657 return err;
658 return (cmd == SIOCDELRTOLD) ? rt_kill(&rt) : rt_new(&rt);
659
660 case SIOCADDRT:
661 case SIOCDELRT:
662 if (!suser())
663 return -EPERM;
664 err=verify_area(VERIFY_READ, arg, sizeof(struct rtentry));
665 if (err)
666 return err;
667 memcpy_fromfs(&rt, arg, sizeof(struct rtentry));
668 return (cmd == SIOCDELRT) ? rt_kill(&rt) : rt_new(&rt);
669 }
670
671 return -EINVAL;
672 }