]> git.pld-linux.org Git - packages/kernel.git/blob - kernel-pom-ng-ROUTE.patch
- new
[packages/kernel.git] / kernel-pom-ng-ROUTE.patch
1 diff -NurpP --minimal linux-2.6.21.a/include/linux/netfilter_ipv4/ipt_ROUTE.h linux-2.6.21.b/include/linux/netfilter_ipv4/ipt_ROUTE.h
2 --- linux-2.6.21.a/include/linux/netfilter_ipv4/ipt_ROUTE.h     1970-01-01 01:00:00.000000000 +0100
3 +++ linux-2.6.21.b/include/linux/netfilter_ipv4/ipt_ROUTE.h     2007-05-30 11:40:37.000000000 +0200
4 @@ -0,0 +1,23 @@
5 +/* Header file for iptables ipt_ROUTE target
6 + *
7 + * (C) 2002 by Cédric de Launois <delaunois@info.ucl.ac.be>
8 + *
9 + * This software is distributed under GNU GPL v2, 1991
10 + */
11 +#ifndef _IPT_ROUTE_H_target
12 +#define _IPT_ROUTE_H_target
13 +
14 +#define IPT_ROUTE_IFNAMSIZ 16
15 +
16 +struct ipt_route_target_info {
17 +       char      oif[IPT_ROUTE_IFNAMSIZ];      /* Output Interface Name */
18 +       char      iif[IPT_ROUTE_IFNAMSIZ];      /* Input Interface Name  */
19 +       u_int32_t gw;                           /* IP address of gateway */
20 +       u_int8_t  flags;
21 +};
22 +
23 +/* Values for "flags" field */
24 +#define IPT_ROUTE_CONTINUE        0x01
25 +#define IPT_ROUTE_TEE             0x02
26 +
27 +#endif /*_IPT_ROUTE_H_target*/
28 diff -NurpP --minimal linux-2.6.21.a/include/linux/netfilter_ipv6/ip6t_ROUTE.h linux-2.6.21.b/include/linux/netfilter_ipv6/ip6t_ROUTE.h
29 --- linux-2.6.21.a/include/linux/netfilter_ipv6/ip6t_ROUTE.h    1970-01-01 01:00:00.000000000 +0100
30 +++ linux-2.6.21.b/include/linux/netfilter_ipv6/ip6t_ROUTE.h    2007-05-30 11:40:37.000000000 +0200
31 @@ -0,0 +1,23 @@
32 +/* Header file for iptables ip6t_ROUTE target
33 + *
34 + * (C) 2003 by Cédric de Launois <delaunois@info.ucl.ac.be>
35 + *
36 + * This software is distributed under GNU GPL v2, 1991
37 + */
38 +#ifndef _IPT_ROUTE_H_target
39 +#define _IPT_ROUTE_H_target
40 +
41 +#define IP6T_ROUTE_IFNAMSIZ 16
42 +
43 +struct ip6t_route_target_info {
44 +       char      oif[IP6T_ROUTE_IFNAMSIZ];     /* Output Interface Name */
45 +       char      iif[IP6T_ROUTE_IFNAMSIZ];     /* Input Interface Name  */
46 +       u_int32_t gw[4];                        /* IPv6 address of gateway */
47 +       u_int8_t  flags;
48 +};
49 +
50 +/* Values for "flags" field */
51 +#define IP6T_ROUTE_CONTINUE        0x01
52 +#define IP6T_ROUTE_TEE             0x02
53 +
54 +#endif /*_IP6T_ROUTE_H_target*/
55 diff -NurpP --minimal linux-2.6.21.a/net/ipv4/netfilter/Kconfig linux-2.6.21.b/net/ipv4/netfilter/Kconfig
56 --- linux-2.6.21.a/net/ipv4/netfilter/Kconfig   2007-05-30 11:39:28.000000000 +0200
57 +++ linux-2.6.21.b/net/ipv4/netfilter/Kconfig   2007-05-30 11:40:37.000000000 +0200
58 @@ -813,5 +813,22 @@ config IP_NF_MATCH_U32
59         
60           Details and examples are in the kernel module source.
61  
62 +config IP_NF_TARGET_ROUTE
63 +       tristate  'ROUTE target support'
64 +       depends on IP_NF_MANGLE
65 +       help
66 +         This option adds a `ROUTE' target, which enables you to setup unusual
67 +         routes. For example, the ROUTE lets you route a received packet through 
68 +         an interface or towards a host, even if the regular destination of the 
69 +         packet is the router itself. The ROUTE target is also able to change the 
70 +         incoming interface of a packet.
71 +       
72 +         The target can be or not a final target. It has to be used inside the 
73 +         mangle table.
74 +         
75 +         If you want to compile it as a module, say M here and read
76 +         Documentation/modules.txt.  The module will be called ipt_ROUTE.o.
77 +         If unsure, say `N'.
78 +
79  endmenu
80  
81 diff -NurpP --minimal linux-2.6.21.a/net/ipv4/netfilter/Makefile linux-2.6.21.b/net/ipv4/netfilter/Makefile
82 --- linux-2.6.21.a/net/ipv4/netfilter/Makefile  2007-05-30 11:39:28.000000000 +0200
83 +++ linux-2.6.21.b/net/ipv4/netfilter/Makefile  2007-05-30 11:40:37.000000000 +0200
84 @@ -74,6 +74,7 @@
85  obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
86  obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
87  obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
88 +obj-$(CONFIG_IP_NF_TARGET_ROUTE) += ipt_ROUTE.o
89  obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
90  obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o
91  obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o
92 diff -NurpP --minimal linux-2.6.21.a/net/ipv4/netfilter/ipt_ROUTE.c linux-2.6.21.b/net/ipv4/netfilter/ipt_ROUTE.c
93 --- linux-2.6.21.a/net/ipv4/netfilter/ipt_ROUTE.c       1970-01-01 01:00:00.000000000 +0100
94 +++ linux-2.6.21.b/net/ipv4/netfilter/ipt_ROUTE.c       2007-05-30 11:40:37.000000000 +0200
95 @@ -0,0 +1,450 @@
96 +/*
97 + * This implements the ROUTE target, which enables you to setup unusual
98 + * routes not supported by the standard kernel routing table.
99 + *
100 + * Copyright (C) 2002 Cedric de Launois <delaunois@info.ucl.ac.be>
101 + *
102 + * v 1.11 2004/11/23
103 + *
104 + * This software is distributed under GNU GPL v2, 1991
105 + */
106 +
107 +#include <linux/module.h>
108 +#include <linux/skbuff.h>
109 +#include <linux/ip.h>
110 +#include <linux/netfilter/x_tables.h>
111 +#include <linux/netfilter_ipv4/ip_tables.h>
112 +#include <net/netfilter/nf_conntrack.h>
113 +#include <linux/netfilter_ipv4/ipt_ROUTE.h>
114 +#include <linux/netdevice.h>
115 +#include <linux/route.h>
116 +#include <linux/if_arp.h>
117 +#include <net/ip.h>
118 +#include <net/route.h>
119 +#include <net/icmp.h>
120 +#include <net/checksum.h>
121 +
122 +#if 0
123 +#define DEBUGP printk
124 +#else
125 +#define DEBUGP(format, args...)
126 +#endif
127 +
128 +MODULE_LICENSE("GPL");
129 +MODULE_AUTHOR("Cedric de Launois <delaunois@info.ucl.ac.be>");
130 +MODULE_DESCRIPTION("iptables ROUTE target module");
131 +
132 +/* Try to route the packet according to the routing keys specified in
133 + * route_info. Keys are :
134 + *  - ifindex : 
135 + *      0 if no oif preferred, 
136 + *      otherwise set to the index of the desired oif
137 + *  - route_info->gw :
138 + *      0 if no gateway specified,
139 + *      otherwise set to the next host to which the pkt must be routed
140 + * If success, skb->dev is the output device to which the packet must 
141 + * be sent and skb->dst is not NULL
142 + *
143 + * RETURN: -1 if an error occured
144 + *          1 if the packet was succesfully routed to the 
145 + *            destination desired
146 + *          0 if the kernel routing table could not route the packet
147 + *            according to the keys specified
148 + */
149 +static int route(struct sk_buff *skb,
150 +                unsigned int ifindex,
151 +                const struct ipt_route_target_info *route_info)
152 +{
153 +       int err;
154 +       struct rtable *rt;
155 +       struct iphdr *iph = ip_hdr(skb);
156 +       struct flowi fl = {
157 +               .oif = ifindex,
158 +               .nl_u = {
159 +                       .ip4_u = {
160 +                               .daddr = iph->daddr,
161 +                               .saddr = 0,
162 +                               .tos = RT_TOS(iph->tos),
163 +                               .scope = RT_SCOPE_UNIVERSE,
164 +                       }
165 +               } 
166 +       };
167 +       
168 +       /* The destination address may be overloaded by the target */
169 +       if (route_info->gw)
170 +               fl.fl4_dst = route_info->gw;
171 +       
172 +       /* Trying to route the packet using the standard routing table. */
173 +       if ((err = ip_route_output_key(&init_net, &rt, &fl))) {
174 +               if (net_ratelimit()) 
175 +                       DEBUGP("ipt_ROUTE: couldn't route pkt (err: %i)",err);
176 +               return -1;
177 +       }
178 +       
179 +       /* Drop old route. */
180 +       dst_release(skb->dst);
181 +       skb->dst = NULL;
182 +
183 +       /* Success if no oif specified or if the oif correspond to the 
184 +        * one desired */
185 +       if (!ifindex || rt->u.dst.dev->ifindex == ifindex) {
186 +               skb->dst = &rt->u.dst;
187 +               skb->dev = skb->dst->dev;
188 +               skb->protocol = htons(ETH_P_IP);
189 +               return 1;
190 +       }
191 +       
192 +       /* The interface selected by the routing table is not the one
193 +        * specified by the user. This may happen because the dst address
194 +        * is one of our own addresses.
195 +        */
196 +       if (net_ratelimit()) 
197 +               DEBUGP("ipt_ROUTE: failed to route as desired gw=%u.%u.%u.%u oif=%i (got oif=%i)\n", 
198 +                      NIPQUAD(route_info->gw), ifindex, rt->u.dst.dev->ifindex);
199 +       
200 +       return 0;
201 +}
202 +
203 +
204 +/* Stolen from ip_finish_output2
205 + * PRE : skb->dev is set to the device we are leaving by
206 + *       skb->dst is not NULL
207 + * POST: the packet is sent with the link layer header pushed
208 + *       the packet is destroyed
209 + */
210 +static void ip_direct_send(struct sk_buff *skb)
211 +{
212 +       struct dst_entry *dst = skb->dst;
213 +       struct hh_cache *hh = dst->hh;
214 +       struct net_device *dev = dst->dev;
215 +       int hh_len = LL_RESERVED_SPACE(dev);
216 +
217 +       /* Be paranoid, rather than too clever. */
218 +       if (unlikely(skb_headroom(skb) < hh_len && dev->header_ops)) {
219 +               struct sk_buff *skb2;
220 +
221 +               skb2 = skb_realloc_headroom(skb, LL_RESERVED_SPACE(dev));
222 +               if (skb2 == NULL) {
223 +                       kfree_skb(skb);
224 +                       return;
225 +               }
226 +               if (skb->sk)
227 +                       skb_set_owner_w(skb2, skb->sk);
228 +               kfree_skb(skb);
229 +               skb = skb2;
230 +       }
231 +
232 +       if (hh) {
233 +               neigh_hh_output(dst->hh, skb);
234 +       } else if (dst->neighbour)
235 +               dst->neighbour->output(skb);
236 +       else {
237 +               if (net_ratelimit())
238 +                       DEBUGP(KERN_DEBUG "ipt_ROUTE: no hdr & no neighbour cache!\n");
239 +               kfree_skb(skb);
240 +       }
241 +}
242 +
243 +
244 +/* PRE : skb->dev is set to the device we are leaving by
245 + * POST: - the packet is directly sent to the skb->dev device, without 
246 + *         pushing the link layer header.
247 + *       - the packet is destroyed
248 + */
249 +static inline int dev_direct_send(struct sk_buff *skb)
250 +{
251 +       return dev_queue_xmit(skb);
252 +}
253 +
254 +
255 +static unsigned int route_oif(const struct ipt_route_target_info *route_info,
256 +                             struct sk_buff *skb) 
257 +{
258 +       unsigned int ifindex = 0;
259 +       struct net_device *dev_out = NULL;
260 +
261 +       /* The user set the interface name to use.
262 +        * Getting the current interface index.
263 +        */
264 +       if ((dev_out = dev_get_by_name(&init_net, route_info->oif))) {
265 +               ifindex = dev_out->ifindex;
266 +       } else {
267 +               /* Unknown interface name : packet dropped */
268 +               if (net_ratelimit()) 
269 +                       DEBUGP("ipt_ROUTE: oif interface %s not found\n", route_info->oif);
270 +               return NF_DROP;
271 +       }
272 +
273 +       /* Trying the standard way of routing packets */
274 +       switch (route(skb, ifindex, route_info)) {
275 +       case 1:
276 +               dev_put(dev_out);
277 +               if (route_info->flags & IPT_ROUTE_CONTINUE)
278 +                       return IPT_CONTINUE;
279 +
280 +               ip_direct_send(skb);
281 +               return NF_STOLEN;
282 +
283 +       case 0:
284 +               /* Failed to send to oif. Trying the hard way */
285 +               if (route_info->flags & IPT_ROUTE_CONTINUE)
286 +                       return NF_DROP;
287 +
288 +               if (net_ratelimit()) 
289 +                       DEBUGP("ipt_ROUTE: forcing the use of %i\n",
290 +                              ifindex);
291 +
292 +               /* We have to force the use of an interface.
293 +                * This interface must be a tunnel interface since
294 +                * otherwise we can't guess the hw address for
295 +                * the packet. For a tunnel interface, no hw address
296 +                * is needed.
297 +                */
298 +               if ((dev_out->type != ARPHRD_TUNNEL)
299 +                   && (dev_out->type != ARPHRD_IPGRE)) {
300 +                       if (net_ratelimit()) 
301 +                               DEBUGP("ipt_ROUTE: can't guess the hw addr !\n");
302 +                       dev_put(dev_out);
303 +                       return NF_DROP;
304 +               }
305 +       
306 +               /* Send the packet. This will also free skb
307 +                * Do not go through the POST_ROUTING hook because 
308 +                * skb->dst is not set and because it will probably
309 +                * get confused by the destination IP address.
310 +                */
311 +               skb->dev = dev_out;
312 +               dev_direct_send(skb);
313 +               dev_put(dev_out);
314 +               return NF_STOLEN;
315 +               
316 +       default:
317 +               /* Unexpected error */
318 +               dev_put(dev_out);
319 +               return NF_DROP;
320 +       }
321 +}
322 +
323 +
324 +static unsigned int route_iif(const struct ipt_route_target_info *route_info,
325 +                             struct sk_buff *skb) 
326 +{
327 +       struct net_device *dev_in = NULL;
328 +
329 +       /* Getting the current interface index. */
330 +       if (!(dev_in = dev_get_by_name(&init_net, route_info->iif))) {
331 +               if (net_ratelimit()) 
332 +                       DEBUGP("ipt_ROUTE: iif interface %s not found\n", route_info->iif);
333 +               return NF_DROP;
334 +       }
335 +
336 +       skb->dev = dev_in;
337 +       dst_release(skb->dst);
338 +       skb->dst = NULL;
339 +
340 +       netif_rx(skb);
341 +       dev_put(dev_in);
342 +       return NF_STOLEN;
343 +}
344 +
345 +
346 +static unsigned int route_gw(const struct ipt_route_target_info *route_info,
347 +                            struct sk_buff *skb) 
348 +{
349 +       if (route(skb, 0, route_info)!=1)
350 +               return NF_DROP;
351 +
352 +       if (route_info->flags & IPT_ROUTE_CONTINUE)
353 +               return IPT_CONTINUE;
354 +
355 +       ip_direct_send(skb);
356 +       return NF_STOLEN;
357 +}
358 +
359 +
360 +/* To detect and deter routed packet loopback when using the --tee option,
361 + * we take a page out of the raw.patch book: on the copied skb, we set up
362 + * a fake ->nfct entry, pointing to the local &route_tee_track. We skip
363 + * routing packets when we see they already have that ->nfct.
364 + */
365 +
366 +static struct nf_conn route_tee_track;
367 +
368 +static unsigned int ipt_route_target(struct sk_buff *skb, const struct xt_target_param *par)
369 +{
370 +       const struct ipt_route_target_info *route_info = par->targinfo;
371 +       //struct sk_buff *skb = *pskb;
372 +       unsigned int res;
373 +
374 +       if (skb->nfct == &route_tee_track.ct_general) {
375 +               /* Loopback - a packet we already routed, is to be
376 +                * routed another time. Avoid that, now.
377 +                */
378 +               if (net_ratelimit()) 
379 +                       DEBUGP(KERN_DEBUG "ipt_ROUTE: loopback - DROP!\n");
380 +               return NF_DROP;
381 +       }
382 +
383 +       /* If we are at PREROUTING or INPUT hook
384 +        * the TTL isn't decreased by the IP stack
385 +        */
386 +       if (par->hooknum == NF_INET_PRE_ROUTING ||
387 +           par->hooknum == NF_INET_LOCAL_IN) {
388 +
389 +               struct iphdr *iph = ip_hdr(skb);
390 +
391 +               if (iph->ttl <= 1) {
392 +                       struct rtable *rt;
393 +                       struct flowi fl = {
394 +                               .oif = 0,
395 +                               .nl_u = {
396 +                                       .ip4_u = {
397 +                                               .daddr = iph->daddr,
398 +                                               .saddr = iph->saddr,
399 +                                               .tos = RT_TOS(iph->tos),
400 +                                               .scope = ((iph->tos & RTO_ONLINK) ?
401 +                                                         RT_SCOPE_LINK :
402 +                                                         RT_SCOPE_UNIVERSE)
403 +                                       }
404 +                               } 
405 +                       };
406 +
407 +                       if (ip_route_output_key(&init_net, &rt, &fl)) {
408 +                               return NF_DROP;
409 +                       }
410 +
411 +                       if (skb->dev == rt->u.dst.dev) {
412 +                               /* Drop old route. */
413 +                               dst_release(skb->dst);
414 +                               skb->dst = &rt->u.dst;
415 +
416 +                               /* this will traverse normal stack, and 
417 +                                * thus call conntrack on the icmp packet */
418 +                               icmp_send(skb, ICMP_TIME_EXCEEDED, 
419 +                                         ICMP_EXC_TTL, 0);
420 +                       }
421 +
422 +                       return NF_DROP;
423 +               }
424 +
425 +               /*
426 +                * If we are at INPUT the checksum must be recalculated since
427 +                * the length could change as the result of a defragmentation.
428 +                */
429 +               if(par->hooknum == NF_INET_LOCAL_IN) {
430 +                       iph->ttl = iph->ttl - 1;
431 +                       iph->check = 0;
432 +                       iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
433 +               } else {
434 +                       ip_decrease_ttl(iph);
435 +               }
436 +       }
437 +
438 +       if ((route_info->flags & IPT_ROUTE_TEE)) {
439 +               /*
440 +                * Copy the *pskb, and route the copy. Will later return
441 +                * IPT_CONTINUE for the original skb, which should continue
442 +                * on its way as if nothing happened. The copy should be
443 +                * independantly delivered to the ROUTE --gw.
444 +                */
445 +               skb = skb_copy(skb, GFP_ATOMIC);
446 +               if (!skb) {
447 +                       if (net_ratelimit()) 
448 +                               DEBUGP(KERN_DEBUG "ipt_ROUTE: copy failed!\n");
449 +                       nf_conntrack_put(skb->nfct);
450 +                       skb->nfct = &route_tee_track.ct_general;
451 +                       skb->nfctinfo = IP_CT_NEW;
452 +                       nf_conntrack_get(skb->nfct);
453 +                       return IPT_CONTINUE;
454 +               }
455 +       }
456 +
457 +       /* Tell conntrack to forget this packet since it may get confused 
458 +        * when a packet is leaving with dst address == our address.
459 +        * Good idea ? Dunno. Need advice.
460 +        *
461 +        * NEW: mark the skb with our &route_tee_track, so we avoid looping
462 +        * on any already routed packet.
463 +        */
464 +       if (!(route_info->flags & IPT_ROUTE_CONTINUE)) {
465 +               nf_conntrack_put(skb->nfct);
466 +               skb->nfct = &route_tee_track.ct_general;
467 +               skb->nfctinfo = IP_CT_NEW;
468 +               nf_conntrack_get(skb->nfct);
469 +       }
470 +
471 +       if (route_info->oif[0] != '\0') {
472 +               res = route_oif(route_info, skb);
473 +       } else if (route_info->iif[0] != '\0') {
474 +               res = route_iif(route_info, skb);
475 +       } else if (route_info->gw) {
476 +               res = route_gw(route_info, skb);
477 +       } else {
478 +               if (net_ratelimit()) 
479 +                       DEBUGP(KERN_DEBUG "ipt_ROUTE: no parameter !\n");
480 +               res = IPT_CONTINUE;
481 +       }
482 +
483 +       if ((route_info->flags & IPT_ROUTE_TEE))
484 +               res = IPT_CONTINUE;
485 +
486 +       return res;
487 +}
488 +
489 +static bool ipt_route_checkentry(const struct xt_tgchk_param *par)
490 +/*static bool ipt_route_checkentry(const char *tablename,
491 +                               const void *e,
492 +                               const struct xt_target *target,
493 +                               void *targinfo,
494 +                               
495 +                               unsigned int hook_mask) */
496 +{
497 +/*     if (strcmp(par->tablename, "mangle") != 0) {
498 +               printk("ipt_ROUTE: bad table `%s', use the `mangle' table.\n",
499 +                      par->tablename);
500 +               return 0;
501 +       }
502 +*/
503 +       if (par->hook_mask & ~(  (1 << NF_INET_PRE_ROUTING)
504 +                           | (1 << NF_INET_LOCAL_IN)
505 +                           | (1 << NF_INET_FORWARD)
506 +                           | (1 << NF_INET_LOCAL_OUT)
507 +                           | (1 << NF_INET_POST_ROUTING))) {
508 +               printk("ipt_ROUTE: bad hook\n");
509 +               return 0;
510 +       }
511 +
512 +       return 1;
513 +}
514 +
515 +static struct xt_target ipt_route_reg __read_mostly = {
516 +       .name = "ROUTE",
517 +       .family         = AF_INET,
518 +       .target = ipt_route_target,
519 +       .targetsize = sizeof(struct ipt_route_target_info),
520 +       .table          = "mangle",
521 +       .checkentry = ipt_route_checkentry,
522 +       .me = THIS_MODULE,
523 +};
524 +
525 +static int __init init(void)
526 +{
527 +       /* Set up fake conntrack (stolen from raw.patch):
528 +           - to never be deleted, not in any hashes */
529 +       atomic_set(&route_tee_track.ct_general.use, 1);
530 +       /*  - and look it like as a confirmed connection */
531 +       set_bit(IPS_CONFIRMED_BIT, &route_tee_track.status);
532 +       /* Initialize fake conntrack so that NAT will skip it */
533 +       route_tee_track.status |= IPS_NAT_DONE_MASK;
534 +
535 +       return xt_register_target(&ipt_route_reg);
536 +}
537 +
538 +
539 +static void __exit fini(void)
540 +{
541 +       xt_unregister_target(&ipt_route_reg);
542 +}
543 +
544 +module_init(init);
545 +module_exit(fini);
546 diff -NurpP --minimal linux-2.6.21.a/net/ipv6/netfilter/Kconfig linux-2.6.21.b/net/ipv6/netfilter/Kconfig
547 --- linux-2.6.21.a/net/ipv6/netfilter/Kconfig   2007-05-30 11:13:04.000000000 +0200
548 +++ linux-2.6.21.b/net/ipv6/netfilter/Kconfig   2007-05-30 11:40:37.000000000 +0200
549 @@ -209,5 +209,18 @@ config IP6_NF_RAW
550           If you want to compile it as a module, say M here and read
551           <file:Documentation/modules.txt>.  If unsure, say `N'.
552  
553 +config IP6_NF_TARGET_ROUTE
554 +       tristate 'ROUTE target support'
555 +       depends on IP6_NF_MANGLE
556 +       help
557 +         This option adds a `ROUTE' target, which enables you to setup unusual
558 +         routes. The ROUTE target is also able to change the incoming interface
559 +         of a packet.
560 +       
561 +         The target can be or not a final target. It has to be used inside the 
562 +         mangle table.
563 +         
564 +         Not working as a module.
565 +
566  endmenu
567  
568 diff -NurpP --minimal linux-2.6.21.a/net/ipv6/netfilter/Makefile linux-2.6.21.b/net/ipv6/netfilter/Makefile
569 --- linux-2.6.21.a/net/ipv6/netfilter/Makefile  2007-05-30 11:13:04.000000000 +0200
570 +++ linux-2.6.21.b/net/ipv6/netfilter/Makefile  2007-05-30 11:40:37.000000000 +0200
571 @@ -30,3 +30,4 @@
572  obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
573  obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
574  obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
575 +obj-$(CONFIG_IP6_NF_TARGET_ROUTE) += ip6t_ROUTE.o
576 diff -NurpP --minimal linux-2.6.21.a/net/ipv6/netfilter/ip6t_ROUTE.c linux-2.6.21.b/net/ipv6/netfilter/ip6t_ROUTE.c
577 --- linux-2.6.21.a/net/ipv6/netfilter/ip6t_ROUTE.c      1970-01-01 01:00:00.000000000 +0100
578 +++ linux-2.6.21.b/net/ipv6/netfilter/ip6t_ROUTE.c      2007-05-30 11:40:37.000000000 +0200
579 @@ -0,0 +1,293 @@
580 +/*
581 + * This implements the ROUTE v6 target, which enables you to setup unusual
582 + * routes not supported by the standard kernel routing table.
583 + *
584 + * Copyright (C) 2003 Cedric de Launois <delaunois@info.ucl.ac.be>
585 + *
586 + * v 1.1 2004/11/23
587 + *
588 + * This software is distributed under GNU GPL v2, 1991
589 + */
590 +
591 +#include <linux/module.h>
592 +#include <linux/skbuff.h>
593 +#include <linux/ipv6.h>
594 +#include <linux/netfilter/x_tables.h>
595 +#include <linux/netfilter_ipv6/ip6_tables.h>
596 +#include <linux/netfilter_ipv6/ip6t_ROUTE.h>
597 +#include <linux/netdevice.h>
598 +#include <net/ipv6.h>
599 +#include <net/ndisc.h>
600 +#include <net/ip6_route.h>
601 +#include <linux/icmpv6.h>
602 +
603 +#if 1
604 +#define DEBUGP printk
605 +#else
606 +#define DEBUGP(format, args...)
607 +#endif
608 +
609 +#define NIP6(addr) \
610 +       ntohs((addr).s6_addr16[0]), \
611 +       ntohs((addr).s6_addr16[1]), \
612 +       ntohs((addr).s6_addr16[2]), \
613 +       ntohs((addr).s6_addr16[3]), \
614 +       ntohs((addr).s6_addr16[4]), \
615 +       ntohs((addr).s6_addr16[5]), \
616 +       ntohs((addr).s6_addr16[6]), \
617 +       ntohs((addr).s6_addr16[7])
618 +
619 +/* Route the packet according to the routing keys specified in
620 + * route_info. Keys are :
621 + *  - ifindex : 
622 + *      0 if no oif preferred, 
623 + *      otherwise set to the index of the desired oif
624 + *  - route_info->gw :
625 + *      0 if no gateway specified,
626 + *      otherwise set to the next host to which the pkt must be routed
627 + * If success, skb->dev is the output device to which the packet must 
628 + * be sent and skb->dst is not NULL
629 + *
630 + * RETURN:  1 if the packet was succesfully routed to the 
631 + *            destination desired
632 + *          0 if the kernel routing table could not route the packet
633 + *            according to the keys specified
634 + */
635 +static int 
636 +route6(struct sk_buff *skb,
637 +       unsigned int ifindex,
638 +       const struct ip6t_route_target_info *route_info)
639 +{
640 +       struct rt6_info *rt = NULL;
641 +       struct ipv6hdr *ipv6h = ipv6_hdr(skb);
642 +       struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
643 +
644 +       DEBUGP("ip6t_ROUTE: called with: ");
645 +       DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr));
646 +       DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(*gw));
647 +       DEBUGP("OUT=%s\n", route_info->oif);
648 +       
649 +       if (ipv6_addr_any(gw))
650 +               rt = rt6_lookup(dev_net(skb->dev), &ipv6h->daddr, &ipv6h->saddr, ifindex, 1);
651 +       else
652 +               rt = rt6_lookup(dev_net(skb->dev), gw, &ipv6h->saddr, ifindex, 1);
653 +
654 +       if (!rt)
655 +               goto no_route;
656 +
657 +       DEBUGP("ip6t_ROUTE: routing gives: ");
658 +       DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_dst.addr));
659 +       DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_gateway));
660 +       DEBUGP("OUT=%s\n", rt->rt6i_dev->name);
661 +
662 +       if (ifindex && rt->rt6i_dev->ifindex!=ifindex)
663 +               goto wrong_route;
664 +       
665 +       if (!rt->rt6i_nexthop) {
666 +               DEBUGP("ip6t_ROUTE: discovering neighbour\n");
667 +               rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_dst.addr);
668 +       }
669 +
670 +       /* Drop old route. */
671 +       dst_release(skb->dst);
672 +       skb->dst = &rt->u.dst;
673 +       skb->dev = rt->rt6i_dev;
674 +       return 1;
675 +
676 + wrong_route:
677 +       dst_release(&rt->u.dst);
678 + no_route:
679 +       if (!net_ratelimit())
680 +               return 0;
681 +
682 +       printk("ip6t_ROUTE: no explicit route found ");
683 +       if (ifindex)
684 +               printk("via interface %s ", route_info->oif);
685 +       if (!ipv6_addr_any(gw))
686 +               printk("via gateway %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", NIP6(*gw));
687 +       printk("\n");
688 +       return 0;
689 +}
690 +
691 +
692 +/* Stolen from ip6_output_finish
693 + * PRE : skb->dev is set to the device we are leaving by
694 + *       skb->dst is not NULL
695 + * POST: the packet is sent with the link layer header pushed
696 + *       the packet is destroyed
697 + */
698 +static void ip_direct_send(struct sk_buff *skb)
699 +{
700 +       struct dst_entry *dst = skb->dst;
701 +       struct hh_cache *hh = dst->hh;
702 +
703 +       if (hh) {
704 +               neigh_hh_output(dst->hh, skb);
705 +       } else if (dst->neighbour)
706 +               dst->neighbour->output(skb);
707 +       else {
708 +               if (net_ratelimit())
709 +                       DEBUGP(KERN_DEBUG "ip6t_ROUTE: no hdr & no neighbour cache!\n");
710 +               kfree_skb(skb);
711 +       }
712 +}
713 +
714 +
715 +static unsigned int 
716 +route6_oif(const struct ip6t_route_target_info *route_info,
717 +          struct sk_buff *skb) 
718 +{
719 +       unsigned int ifindex = 0;
720 +       struct net_device *dev_out = NULL;
721 +
722 +       /* The user set the interface name to use.
723 +        * Getting the current interface index.
724 +        */
725 +       if ((dev_out = dev_get_by_name(&init_net, route_info->oif))) {
726 +               ifindex = dev_out->ifindex;
727 +       } else {
728 +               /* Unknown interface name : packet dropped */
729 +               if (net_ratelimit()) 
730 +                       DEBUGP("ip6t_ROUTE: oif interface %s not found\n", route_info->oif);
731 +
732 +               if (route_info->flags & IP6T_ROUTE_CONTINUE)
733 +                       return IP6T_CONTINUE;
734 +               else
735 +                       return NF_DROP;
736 +       }
737 +
738 +       /* Trying the standard way of routing packets */
739 +       if (route6(skb, ifindex, route_info)) {
740 +               dev_put(dev_out);
741 +               if (route_info->flags & IP6T_ROUTE_CONTINUE)
742 +                       return IP6T_CONTINUE;
743 +               
744 +               ip_direct_send(skb);
745 +               return NF_STOLEN;
746 +       } else 
747 +               return NF_DROP;
748 +}
749 +
750 +
751 +static unsigned int 
752 +route6_gw(const struct ip6t_route_target_info *route_info,
753 +         struct sk_buff *skb) 
754 +{
755 +       if (route6(skb, 0, route_info)) {
756 +               if (route_info->flags & IP6T_ROUTE_CONTINUE)
757 +                       return IP6T_CONTINUE;
758 +
759 +               ip_direct_send(skb);
760 +               return NF_STOLEN;
761 +       } else
762 +               return NF_DROP;
763 +}
764 +
765 +
766 +static unsigned int 
767 +ip6t_route_target(struct sk_buff *skb, const struct xt_target_param *par)
768 +{
769 +       const struct ip6t_route_target_info *route_info = par->targinfo;
770 +       struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
771 +       unsigned int res;
772 +
773 +       if (route_info->flags & IP6T_ROUTE_CONTINUE)
774 +               goto do_it;
775 +
776 +       /* If we are at PREROUTING or INPUT hook
777 +        * the TTL isn't decreased by the IP stack
778 +        */
779 +       if (par->hooknum == NF_INET_PRE_ROUTING ||
780 +           par->hooknum == NF_INET_LOCAL_IN) {
781 +
782 +               struct ipv6hdr *ipv6h = ipv6_hdr(skb);
783 +
784 +               if (ipv6h->hop_limit <= 1) {
785 +                       /* Force OUTPUT device used as source address */
786 +                       skb->dev = skb->dst->dev;
787 +
788 +                       icmpv6_send(skb, ICMPV6_TIME_EXCEED, 
789 +                                   ICMPV6_EXC_HOPLIMIT, 0, skb->dev);
790 +
791 +                       return NF_DROP;
792 +               }
793 +
794 +               ipv6h->hop_limit--;
795 +       }
796 +
797 +       if ((route_info->flags & IP6T_ROUTE_TEE)) {
798 +               /*
799 +                * Copy the *pskb, and route the copy. Will later return
800 +                * IP6T_CONTINUE for the original skb, which should continue
801 +                * on its way as if nothing happened. The copy should be
802 +                * independantly delivered to the ROUTE --gw.
803 +                */
804 +               skb = skb_copy(skb, GFP_ATOMIC);
805 +               if (!skb) {
806 +                       if (net_ratelimit()) 
807 +                               DEBUGP(KERN_DEBUG "ip6t_ROUTE: copy failed!\n");
808 +                       return IP6T_CONTINUE;
809 +               }
810 +       }
811 +
812 +do_it:
813 +       if (route_info->oif[0]) {
814 +               res = route6_oif(route_info, skb);
815 +       } else if (!ipv6_addr_any(gw)) {
816 +               res = route6_gw(route_info, skb);
817 +       } else {
818 +               if (net_ratelimit()) 
819 +                       DEBUGP(KERN_DEBUG "ip6t_ROUTE: no parameter !\n");
820 +               res = IP6T_CONTINUE;
821 +       }
822 +
823 +       if ((route_info->flags & IP6T_ROUTE_TEE))
824 +               res = IP6T_CONTINUE;
825 +
826 +       return res;
827 +}
828 +
829 +
830 +static bool
831 +ip6t_route_checkentry(const struct xt_tgchk_param *par)
832 +{
833 +       /* if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_route_target_info))) {
834 +               printk(KERN_WARNING "ip6t_ROUTE: targinfosize %u != %Zu\n",
835 +                      targinfosize,
836 +                      IP6T_ALIGN(sizeof(struct ip6t_route_target_info)));
837 +               return 0;
838 +       } */
839 +
840 +       return 1;
841 +}
842 +
843 +
844 +static struct xt_target ip6t_route_reg __read_mostly = {
845 +       .name       = "ROUTE",
846 +       .family     = NFPROTO_IPV6,
847 +       .target     = ip6t_route_target,
848 +       .targetsize = sizeof(struct ip6t_route_target_info),
849 +       .table      = "mangle",
850 +       .checkentry = ip6t_route_checkentry,
851 +       .me         = THIS_MODULE
852 +};
853 +
854 +
855 +static int __init init(void)
856 +{
857 +       printk(KERN_DEBUG "registering ipv6 ROUTE target\n");
858 +       if (xt_register_target(&ip6t_route_reg))
859 +               return -EINVAL;
860 +
861 +       return 0;
862 +}
863 +
864 +
865 +static void __exit fini(void)
866 +{
867 +       xt_unregister_target(&ip6t_route_reg);
868 +}
869 +
870 +module_init(init);
871 +module_exit(fini);
872 +MODULE_LICENSE("GPL");
873 --- a/net/ipv6/ndisc.c  2007-07-09 01:32:17.000000000 +0200
874 +++ b/net/ipv6/ndisc.c  2007-08-02 13:23:26.000000000 +0200
875 @@ -154,6 +154,8 @@ struct neigh_table nd_tbl = {
876         .gc_thresh3 =   1024,
877  };
878  
879 +EXPORT_SYMBOL(nd_tbl);
880 +
881  /* ND options */
882  struct ndisc_options {
883         struct nd_opt_hdr *nd_opt_array[__ND_OPT_ARRAY_MAX];
This page took 0.097667 seconds and 3 git commands to generate.