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 {
306 rp = &r->rt_next;
307 continue;
308 }
309 *rp = r->rt_next;
310 if (rt_loopback == r)
311 rt_loopback = NULL;
312 kfree_s(r, sizeof(struct rtable));
313 }
314
315
316
317
318
319 rp = &rt_base;
320 while ((r = *rp) != NULL) {
321 if ((r->rt_mask & mask) != mask)
322 break;
323 rp = &r->rt_next;
324 }
325 rt->rt_next = r;
326 *rp = rt;
327
328
329
330
331
332 if ((rt->rt_dev->flags & IFF_LOOPBACK) && !rt_loopback)
333 rt_loopback = rt;
334
335
336
337
338
339 restore_flags(cpuflags);
340 return;
341 }
342
343
344
345
346
347
348 static inline int bad_mask(unsigned long mask, unsigned long addr)
349 {
350 if (addr & (mask = ~mask))
351 return 1;
352 mask = ntohl(mask);
353 if (mask & (mask+1))
354 return 1;
355 return 0;
356 }
357
358
359
360
361
362 static int rt_new(struct rtentry *r)
363 {
364 int err;
365 char * devname;
366 struct device * dev = NULL;
367 unsigned long flags, daddr, mask, gw;
368
369
370
371
372
373 if ((devname = r->rt_dev) != NULL)
374 {
375 err = getname(devname, &devname);
376 if (err)
377 return err;
378 dev = dev_get(devname);
379 putname(devname);
380 if (!dev)
381 return -EINVAL;
382 }
383
384
385
386
387
388 if (r->rt_dst.sa_family != AF_INET)
389 return -EAFNOSUPPORT;
390
391
392
393
394
395 flags = r->rt_flags;
396 daddr = ((struct sockaddr_in *) &r->rt_dst)->sin_addr.s_addr;
397 mask = ((struct sockaddr_in *) &r->rt_genmask)->sin_addr.s_addr;
398 gw = ((struct sockaddr_in *) &r->rt_gateway)->sin_addr.s_addr;
399
400
401
402
403
404
405
406
407 if (!dev && (flags & RTF_GATEWAY))
408 {
409 struct device *dev2;
410 for (dev2 = dev_base ; dev2 != NULL ; dev2 = dev2->next)
411 {
412 if ((dev2->flags & IFF_UP) && dev2->pa_addr == gw)
413 {
414 flags &= ~RTF_GATEWAY;
415 dev = dev2;
416 break;
417 }
418 }
419 }
420
421
422
423
424
425 if (bad_mask(mask, daddr))
426 mask = 0;
427
428
429
430
431
432 if (flags & RTF_HOST)
433 mask = 0xffffffff;
434 else if (mask && r->rt_genmask.sa_family != AF_INET)
435 return -EAFNOSUPPORT;
436
437
438
439
440
441 if (flags & RTF_GATEWAY)
442 {
443 if (r->rt_gateway.sa_family != AF_INET)
444 return -EAFNOSUPPORT;
445 if (!dev)
446 dev = get_gw_dev(gw);
447 }
448 else if (!dev)
449 dev = ip_dev_check(daddr);
450
451
452
453
454
455 if (dev == NULL)
456 return -ENETUNREACH;
457
458
459
460
461
462 ip_rt_add(flags, daddr, mask, gw, dev, r->rt_mss, r->rt_window);
463 return 0;
464 }
465
466
467
468
469
470
471 static int rt_kill(struct rtentry *r)
472 {
473 struct sockaddr_in *trg;
474 char *devname;
475 int err;
476
477 trg = (struct sockaddr_in *) &r->rt_dst;
478 if ((devname = r->rt_dev) != NULL)
479 {
480 err = getname(devname, &devname);
481 if (err)
482 return err;
483 }
484 rt_del(trg->sin_addr.s_addr, devname);
485 if ( devname != NULL )
486 putname(devname);
487 return 0;
488 }
489
490
491
492
493
494
495 int rt_get_info(char *buffer, char **start, off_t offset, int length)
496 {
497 struct rtable *r;
498 int len=0;
499 off_t pos=0;
500 off_t begin=0;
501 int size;
502
503 len += sprintf(buffer,
504 "Iface\tDestination\tGateway \tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU\tWindow\n");
505 pos=len;
506
507
508
509
510
511 for (r = rt_base; r != NULL; r = r->rt_next)
512 {
513 size = sprintf(buffer+len, "%s\t%08lX\t%08lX\t%02X\t%d\t%lu\t%d\t%08lX\t%d\t%lu\n",
514 r->rt_dev->name, r->rt_dst, r->rt_gateway,
515 r->rt_flags, r->rt_refcnt, r->rt_use, r->rt_metric,
516 r->rt_mask, (int)r->rt_mss, r->rt_window);
517 len+=size;
518 pos+=size;
519 if(pos<offset)
520 {
521 len=0;
522 begin=pos;
523 }
524 if(pos>offset+length)
525 break;
526 }
527
528 *start=buffer+(offset-begin);
529 len-=(offset-begin);
530 if(len>length)
531 len=length;
532 return len;
533 }
534
535
536
537
538
539 #define early_out ({ goto no_route; 1; })
540
541
542
543
544
545
546
547
548 struct rtable * ip_rt_route(unsigned long daddr, struct options *opt, unsigned long *src_addr)
549 {
550 struct rtable *rt;
551
552 for (rt = rt_base; rt != NULL || early_out ; rt = rt->rt_next)
553 {
554 if (!((rt->rt_dst ^ daddr) & rt->rt_mask))
555 break;
556
557
558
559 if (rt->rt_flags & RTF_GATEWAY)
560 continue;
561 if ((rt->rt_dev->flags & IFF_BROADCAST) &&
562 (rt->rt_dev->pa_brdaddr == daddr))
563 break;
564 }
565
566 if(src_addr!=NULL)
567 *src_addr= rt->rt_dev->pa_addr;
568
569 if (daddr == rt->rt_dev->pa_addr) {
570 if ((rt = rt_loopback) == NULL)
571 goto no_route;
572 }
573 rt->rt_use++;
574 return rt;
575 no_route:
576 return NULL;
577 }
578
579 struct rtable * ip_rt_local(unsigned long daddr, struct options *opt, unsigned long *src_addr)
580 {
581 struct rtable *rt;
582
583 for (rt = rt_base; rt != NULL || early_out ; rt = rt->rt_next)
584 {
585
586
587
588 if (rt->rt_flags&RTF_GATEWAY)
589 continue;
590
591 if (!((rt->rt_dst ^ daddr) & rt->rt_mask))
592 break;
593
594
595
596
597 if ((rt->rt_dev->flags & IFF_BROADCAST) &&
598 rt->rt_dev->pa_brdaddr == daddr)
599 break;
600 }
601
602 if(src_addr!=NULL)
603 *src_addr= rt->rt_dev->pa_addr;
604
605 if (daddr == rt->rt_dev->pa_addr) {
606 if ((rt = rt_loopback) == NULL)
607 goto no_route;
608 }
609 rt->rt_use++;
610 return rt;
611 no_route:
612 return NULL;
613 }
614
615
616
617
618
619 static int ip_get_old_rtent(struct old_rtentry * src, struct rtentry * rt)
620 {
621 int err;
622 struct old_rtentry tmp;
623
624 err=verify_area(VERIFY_READ, src, sizeof(*src));
625 if (err)
626 return err;
627 memcpy_fromfs(&tmp, src, sizeof(*src));
628 memset(rt, 0, sizeof(*rt));
629 rt->rt_dst = tmp.rt_dst;
630 rt->rt_gateway = tmp.rt_gateway;
631 rt->rt_genmask.sa_family = AF_INET;
632 ((struct sockaddr_in *) &rt->rt_genmask)->sin_addr.s_addr = tmp.rt_genmask;
633 rt->rt_flags = tmp.rt_flags;
634 rt->rt_dev = tmp.rt_dev;
635 printk("Warning: obsolete routing request made.\n");
636 return 0;
637 }
638
639
640
641
642
643 int ip_rt_ioctl(unsigned int cmd, void *arg)
644 {
645 int err;
646 struct rtentry rt;
647
648 switch(cmd)
649 {
650 case SIOCADDRTOLD:
651 case SIOCDELRTOLD:
652 if (!suser())
653 return -EPERM;
654 err = ip_get_old_rtent((struct old_rtentry *) arg, &rt);
655 if (err)
656 return err;
657 return (cmd == SIOCDELRTOLD) ? rt_kill(&rt) : rt_new(&rt);
658
659 case SIOCADDRT:
660 case SIOCDELRT:
661 if (!suser())
662 return -EPERM;
663 err=verify_area(VERIFY_READ, arg, sizeof(struct rtentry));
664 if (err)
665 return err;
666 memcpy_fromfs(&rt, arg, sizeof(struct rtentry));
667 return (cmd == SIOCDELRT) ? rt_kill(&rt) : rt_new(&rt);
668 }
669
670 return -EINVAL;
671 }