This source file includes following definitions.
- rt_print
- rt_del
- rt_flush
- default_mask
- guess_mask
- get_gw_dev
- rt_add
- bad_mask
- rt_new
- rt_kill
- rt_get_info
- rt_route
- get_old_rtent
- 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 #include <asm/segment.h>
26 #include <asm/system.h>
27 #include <linux/types.h>
28 #include <linux/kernel.h>
29 #include <linux/sched.h>
30 #include <linux/string.h>
31 #include <linux/socket.h>
32 #include <linux/sockios.h>
33 #include <linux/errno.h>
34 #include <linux/in.h>
35 #include "inet.h"
36 #include "dev.h"
37 #include "ip.h"
38 #include "protocol.h"
39 #include "route.h"
40 #include "tcp.h"
41 #include "skbuff.h"
42 #include "sock.h"
43 #include "arp.h"
44 #include "icmp.h"
45
46
47 static struct rtable *rt_base = NULL;
48 static struct rtable *rt_loopback = NULL;
49
50
51 static void
52 rt_print(struct rtable *rt)
53 {
54 if (rt == NULL || inet_debug != DBG_RT) return;
55
56 printk("RT: %06lx NXT=%06lx FLAGS=0x%02x\n",
57 (long) rt, (long) rt->rt_next, rt->rt_flags);
58 printk(" TARGET=%s ", in_ntoa(rt->rt_dst));
59 printk("GW=%s ", in_ntoa(rt->rt_gateway));
60 printk(" DEV=%s USE=%ld REF=%d\n",
61 (rt->rt_dev == NULL) ? "NONE" : rt->rt_dev->name,
62 rt->rt_use, rt->rt_refcnt);
63 }
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 DPRINTF((DBG_RT, "RT: flushing for dst %s\n", in_ntoa(dst)));
75 rp = &rt_base;
76 save_flags(flags);
77 cli();
78 while((r = *rp) != NULL) {
79 if (r->rt_dst != dst) {
80 rp = &r->rt_next;
81 continue;
82 }
83 *rp = r->rt_next;
84 if (rt_loopback == r)
85 rt_loopback = NULL;
86 kfree_s(r, sizeof(struct rtable));
87 }
88 restore_flags(flags);
89 }
90
91
92
93
94
95 void rt_flush(struct device *dev)
96 {
97 struct rtable *r;
98 struct rtable **rp;
99 unsigned long flags;
100
101 DPRINTF((DBG_RT, "RT: flushing for dev 0x%08lx (%s)\n", (long)dev, dev->name));
102 rp = &rt_base;
103 cli();
104 save_flags(flags);
105 while ((r = *rp) != NULL) {
106 if (r->rt_dev != dev) {
107 rp = &r->rt_next;
108 continue;
109 }
110 *rp = r->rt_next;
111 if (rt_loopback == r)
112 rt_loopback = NULL;
113 kfree_s(r, sizeof(struct rtable));
114 }
115 restore_flags(flags);
116 }
117
118
119
120
121
122
123
124
125 static inline unsigned long default_mask(unsigned long dst)
126 {
127 dst = ntohl(dst);
128 if (IN_CLASSA(dst))
129 return htonl(IN_CLASSA_NET);
130 if (IN_CLASSB(dst))
131 return htonl(IN_CLASSB_NET);
132 return htonl(IN_CLASSC_NET);
133 }
134
135 static unsigned long guess_mask(unsigned long dst, struct device * dev)
136 {
137 unsigned long mask;
138
139 if (!dst)
140 return 0;
141 mask = default_mask(dst);
142 if ((dst ^ dev->pa_addr) & mask)
143 return mask;
144 return dev->pa_mask;
145 }
146
147 static inline struct device * get_gw_dev(unsigned long gw)
148 {
149 struct rtable * rt;
150
151 for (rt = rt_base ; ; rt = rt->rt_next) {
152 if (!rt)
153 return NULL;
154 if ((gw ^ rt->rt_dst) & rt->rt_mask)
155 continue;
156
157 if (rt->rt_flags & RTF_GATEWAY)
158 return NULL;
159 return rt->rt_dev;
160 }
161 }
162
163
164
165
166 void rt_add(short flags, unsigned long dst, unsigned long mask,
167 unsigned long gw, struct device *dev)
168 {
169 struct rtable *r, *rt;
170 struct rtable **rp;
171 unsigned long cpuflags;
172
173 if (flags & RTF_HOST) {
174 mask = 0xffffffff;
175 } else if (!mask) {
176 if (!((dst ^ dev->pa_addr) & dev->pa_mask)) {
177 mask = dev->pa_mask;
178 flags &= ~RTF_GATEWAY;
179 if (flags & RTF_DYNAMIC) {
180
181 return;
182 }
183 } else
184 mask = guess_mask(dst, dev);
185 dst &= mask;
186 }
187 if (gw == dev->pa_addr)
188 flags &= ~RTF_GATEWAY;
189 if (flags & RTF_GATEWAY) {
190
191 if (dev != get_gw_dev(gw))
192 return;
193 flags |= RTF_GATEWAY;
194 } else
195 gw = 0;
196
197 rt = (struct rtable *) kmalloc(sizeof(struct rtable), GFP_ATOMIC);
198 if (rt == NULL) {
199 DPRINTF((DBG_RT, "RT: no memory for new route!\n"));
200 return;
201 }
202 memset(rt, 0, sizeof(struct rtable));
203 rt->rt_flags = flags | RTF_UP;
204 rt->rt_dst = dst;
205 rt->rt_dev = dev;
206 rt->rt_gateway = gw;
207 rt->rt_mask = mask;
208 rt->rt_mtu = dev->mtu;
209 rt_print(rt);
210
211
212
213
214
215 save_flags(cpuflags);
216 cli();
217
218 rp = &rt_base;
219 while ((r = *rp) != NULL) {
220 if (r->rt_dst != dst) {
221 rp = &r->rt_next;
222 continue;
223 }
224 *rp = r->rt_next;
225 if (rt_loopback == r)
226 rt_loopback = NULL;
227 kfree_s(r, sizeof(struct rtable));
228 }
229
230 rp = &rt_base;
231 while ((r = *rp) != NULL) {
232 if ((r->rt_mask & mask) != mask)
233 break;
234 rp = &r->rt_next;
235 }
236 rt->rt_next = r;
237 *rp = rt;
238 if (rt->rt_dev->flags & IFF_LOOPBACK)
239 rt_loopback = rt;
240 restore_flags(cpuflags);
241 return;
242 }
243
244 static inline int bad_mask(unsigned long mask, unsigned long addr)
245 {
246 if (addr & (mask = ~mask))
247 return 1;
248 mask = ntohl(mask);
249 if (mask & (mask+1))
250 return 1;
251 return 0;
252 }
253
254 static int rt_new(struct rtentry *r)
255 {
256 int err;
257 char * devname;
258 struct device * dev = NULL;
259 unsigned long flags, daddr, mask, gw;
260
261 if ((devname = r->rt_dev) != NULL) {
262 err = getname(devname, &devname);
263 if (err)
264 return err;
265 dev = dev_get(devname);
266 putname(devname);
267 if (!dev)
268 return -EINVAL;
269 }
270
271 if (r->rt_dst.sa_family != AF_INET)
272 return -EAFNOSUPPORT;
273
274 flags = r->rt_flags;
275 daddr = ((struct sockaddr_in *) &r->rt_dst)->sin_addr.s_addr;
276 mask = ((struct sockaddr_in *) &r->rt_genmask)->sin_addr.s_addr;
277 gw = ((struct sockaddr_in *) &r->rt_gateway)->sin_addr.s_addr;
278
279
280
281
282 if (!dev && (flags & RTF_GATEWAY)) {
283 struct device *dev2;
284 for (dev2 = dev_base ; dev2 != NULL ; dev2 = dev2->next) {
285 if ((dev2->flags & IFF_UP) && dev2->pa_addr == gw) {
286 flags &= ~RTF_GATEWAY;
287 dev = dev2;
288 break;
289 }
290 }
291 }
292
293 if (bad_mask(mask, daddr))
294 mask = 0;
295
296 if (flags & RTF_HOST)
297 mask = 0xffffffff;
298 else if (mask && r->rt_genmask.sa_family != AF_INET)
299 return -EAFNOSUPPORT;
300
301 if (flags & RTF_GATEWAY) {
302 if (r->rt_gateway.sa_family != AF_INET)
303 return -EAFNOSUPPORT;
304 if (!dev)
305 dev = get_gw_dev(gw);
306 } else if (!dev)
307 dev = dev_check(daddr);
308
309 if (dev == NULL)
310 return -ENETUNREACH;
311
312 rt_add(flags, daddr, mask, gw, dev);
313 return 0;
314 }
315
316
317 static int rt_kill(struct rtentry *r)
318 {
319 struct sockaddr_in *trg;
320
321 trg = (struct sockaddr_in *) &r->rt_dst;
322 rt_del(trg->sin_addr.s_addr);
323 return 0;
324 }
325
326
327
328 int
329 rt_get_info(char *buffer)
330 {
331 struct rtable *r;
332 char *pos;
333
334 pos = buffer;
335
336 pos += sprintf(pos,
337 "Iface\tDestination\tGateway \tFlags\tRefCnt\tUse\tMetric\tMask\n");
338
339
340 for (r = rt_base; r != NULL; r = r->rt_next) {
341 pos += sprintf(pos, "%s\t%08lX\t%08lX\t%02X\t%d\t%lu\t%d\t%08lX\n",
342 r->rt_dev->name, r->rt_dst, r->rt_gateway,
343 r->rt_flags, r->rt_refcnt, r->rt_use, r->rt_metric,
344 r->rt_mask);
345 }
346 return(pos - buffer);
347 }
348
349
350
351
352 #define early_out ({ goto no_route; 1; })
353
354 struct rtable * rt_route(unsigned long daddr, struct options *opt)
355 {
356 struct rtable *rt;
357
358 for (rt = rt_base; rt != NULL || early_out ; rt = rt->rt_next) {
359 if (!((rt->rt_dst ^ daddr) & rt->rt_mask))
360 break;
361
362 if ((rt->rt_dev->flags & IFF_BROADCAST) &&
363 rt->rt_dev->pa_brdaddr == daddr)
364 break;
365 }
366 if (daddr == rt->rt_dev->pa_addr) {
367 if ((rt = rt_loopback) == NULL)
368 goto no_route;
369 }
370 rt->rt_use++;
371 return rt;
372 no_route:
373 return NULL;
374 }
375
376 static int get_old_rtent(struct old_rtentry * src, struct rtentry * rt)
377 {
378 int err;
379 struct old_rtentry tmp;
380
381 err=verify_area(VERIFY_READ, src, sizeof(*src));
382 if (err)
383 return err;
384 memcpy_fromfs(&tmp, src, sizeof(*src));
385 memset(rt, 0, sizeof(*rt));
386 rt->rt_dst = tmp.rt_dst;
387 rt->rt_gateway = tmp.rt_gateway;
388 rt->rt_genmask.sa_family = AF_INET;
389 ((struct sockaddr_in *) &rt->rt_genmask)->sin_addr.s_addr = tmp.rt_genmask;
390 rt->rt_flags = tmp.rt_flags;
391 rt->rt_dev = tmp.rt_dev;
392 return 0;
393 }
394
395 int rt_ioctl(unsigned int cmd, void *arg)
396 {
397 int err;
398 struct rtentry rt;
399
400 switch(cmd) {
401 case DDIOCSDBG:
402 return dbg_ioctl(arg, DBG_RT);
403 case SIOCADDRTOLD:
404 case SIOCDELRTOLD:
405 if (!suser())
406 return -EPERM;
407 err = get_old_rtent((struct old_rtentry *) arg, &rt);
408 if (err)
409 return err;
410 return (cmd == SIOCDELRTOLD) ? rt_kill(&rt) : rt_new(&rt);
411 case SIOCADDRT:
412 case SIOCDELRT:
413 if (!suser())
414 return -EPERM;
415 err=verify_area(VERIFY_READ, arg, sizeof(struct rtentry));
416 if (err)
417 return err;
418 memcpy_fromfs(&rt, arg, sizeof(struct rtentry));
419 return (cmd == SIOCDELRT) ? rt_kill(&rt) : rt_new(&rt);
420 }
421
422 return -EINVAL;
423 }