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