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