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