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