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
- 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_print(rt);
209
210
211
212
213
214 save_flags(cpuflags);
215 cli();
216
217 rp = &rt_base;
218 while ((r = *rp) != NULL) {
219 if (r->rt_dst != dst) {
220 rp = &r->rt_next;
221 continue;
222 }
223 *rp = r->rt_next;
224 if (rt_loopback == r)
225 rt_loopback = NULL;
226 kfree_s(r, sizeof(struct rtable));
227 }
228
229 rp = &rt_base;
230 while ((r = *rp) != NULL) {
231 if ((r->rt_mask & mask) != mask)
232 break;
233 rp = &r->rt_next;
234 }
235 rt->rt_next = r;
236 *rp = rt;
237 if (rt->rt_dev->flags & IFF_LOOPBACK)
238 rt_loopback = rt;
239 restore_flags(cpuflags);
240 return;
241 }
242
243 static inline int bad_mask(unsigned long mask, unsigned long addr)
244 {
245 if (addr & (mask = ~mask))
246 return 1;
247 mask = ntohl(mask);
248 if (mask & (mask+1))
249 return 1;
250 return 0;
251 }
252
253 static int rt_new(struct rtentry *r)
254 {
255 struct device *dev;
256 unsigned long flags, daddr, mask, gw;
257
258 if (r->rt_dst.sa_family != AF_INET)
259 return -EAFNOSUPPORT;
260
261 flags = r->rt_flags;
262 daddr = ((struct sockaddr_in *) &r->rt_dst)->sin_addr.s_addr;
263 mask = r->rt_genmask;
264 gw = ((struct sockaddr_in *) &r->rt_gateway)->sin_addr.s_addr;
265 dev = (struct device *) r->rt_dev;
266
267 if (flags & RTF_GATEWAY) {
268 if (r->rt_gateway.sa_family != AF_INET)
269 return -EAFNOSUPPORT;
270 if (!dev)
271 dev = get_gw_dev(gw);
272 } else if (!dev)
273 dev = dev_check(daddr);
274
275 if (dev == NULL)
276 return -ENETUNREACH;
277
278 if (bad_mask(mask, daddr))
279 mask = 0;
280
281 rt_add(flags, daddr, mask, gw, dev);
282 return 0;
283 }
284
285
286 static int rt_kill(struct rtentry *r)
287 {
288 struct sockaddr_in *trg;
289
290 trg = (struct sockaddr_in *) &r->rt_dst;
291 rt_del(trg->sin_addr.s_addr);
292 return 0;
293 }
294
295
296
297 int
298 rt_get_info(char *buffer)
299 {
300 struct rtable *r;
301 char *pos;
302
303 pos = buffer;
304
305 pos += sprintf(pos,
306 "Iface\tDestination\tGateway \tFlags\tRefCnt\tUse\tMetric\tMask\n");
307
308
309 for (r = rt_base; r != NULL; r = r->rt_next) {
310 pos += sprintf(pos, "%s\t%08lX\t%08lX\t%02X\t%d\t%lu\t%d\t%08lX\n",
311 r->rt_dev->name, r->rt_dst, r->rt_gateway,
312 r->rt_flags, r->rt_refcnt, r->rt_use, r->rt_metric,
313 r->rt_mask);
314 }
315 return(pos - buffer);
316 }
317
318
319
320
321 #define early_out ({ goto no_route; 1; })
322
323 struct rtable * rt_route(unsigned long daddr, struct options *opt)
324 {
325 struct rtable *rt;
326
327 for (rt = rt_base; rt != NULL || early_out ; rt = rt->rt_next) {
328 if (!((rt->rt_dst ^ daddr) & rt->rt_mask))
329 break;
330
331 if ((rt->rt_dev->flags & IFF_BROADCAST) &&
332 rt->rt_dev->pa_brdaddr == daddr)
333 break;
334 }
335 if (daddr == rt->rt_dev->pa_addr) {
336 if ((rt = rt_loopback) == NULL)
337 goto no_route;
338 }
339 rt->rt_use++;
340 return rt;
341 no_route:
342 return NULL;
343 }
344
345
346 int rt_ioctl(unsigned int cmd, void *arg)
347 {
348 struct device *dev;
349 struct rtentry rt;
350 char *devname;
351 int ret;
352 int err;
353
354 switch(cmd) {
355 case DDIOCSDBG:
356 ret = dbg_ioctl(arg, DBG_RT);
357 break;
358 case SIOCADDRT:
359 case SIOCDELRT:
360 if (!suser())
361 return -EPERM;
362 err=verify_area(VERIFY_READ, arg, sizeof(struct rtentry));
363 if (err)
364 return err;
365 memcpy_fromfs(&rt, arg, sizeof(struct rtentry));
366 if ((devname = (char *) rt.rt_dev) != NULL) {
367 err = getname(devname, &devname);
368 if (err)
369 return err;
370 dev = dev_get(devname);
371 putname(devname);
372 if (!dev)
373 return -EINVAL;
374 rt.rt_dev = dev;
375 }
376 ret = (cmd == SIOCDELRT) ? rt_kill(&rt) : rt_new(&rt);
377 break;
378 default:
379 ret = -EINVAL;
380 }
381
382 return ret;
383 }