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