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