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