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