]> git.pld-linux.org Git - packages/kernel.git/blob - kernel-pom-ng-ROUTE.patch
- typo
[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 @@ -104,6 +104,7 @@ obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_EC
85  obj-$(CONFIG_IP_NF_TARGET_IMQ) += ipt_IMQ.o
86  obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.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_NETMAP) += ipt_NETMAP.o
90  obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o
91  obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.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,458 @@
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(&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->hard_header)) {
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(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(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 **pskb,
369 +                                    const struct net_device *in,
370 +                                    const struct net_device *out,
371 +                                    unsigned int hooknum,
372 +                                    const struct xt_target *target,
373 +                                    const void *targinfo
374 +                                    )
375 +{
376 +       const struct ipt_route_target_info *route_info = targinfo;
377 +       struct sk_buff *skb = *pskb;
378 +       unsigned int res;
379 +
380 +       if (skb->nfct == &route_tee_track.ct_general) {
381 +               /* Loopback - a packet we already routed, is to be
382 +                * routed another time. Avoid that, now.
383 +                */
384 +               if (net_ratelimit()) 
385 +                       DEBUGP(KERN_DEBUG "ipt_ROUTE: loopback - DROP!\n");
386 +               return NF_DROP;
387 +       }
388 +
389 +       /* If we are at PREROUTING or INPUT hook
390 +        * the TTL isn't decreased by the IP stack
391 +        */
392 +       if (hooknum == NF_IP_PRE_ROUTING ||
393 +           hooknum == NF_IP_LOCAL_IN) {
394 +
395 +               struct iphdr *iph = ip_hdr(skb);
396 +
397 +               if (iph->ttl <= 1) {
398 +                       struct rtable *rt;
399 +                       struct flowi fl = {
400 +                               .oif = 0,
401 +                               .nl_u = {
402 +                                       .ip4_u = {
403 +                                               .daddr = iph->daddr,
404 +                                               .saddr = iph->saddr,
405 +                                               .tos = RT_TOS(iph->tos),
406 +                                               .scope = ((iph->tos & RTO_ONLINK) ?
407 +                                                         RT_SCOPE_LINK :
408 +                                                         RT_SCOPE_UNIVERSE)
409 +                                       }
410 +                               } 
411 +                       };
412 +
413 +                       if (ip_route_output_key(&rt, &fl)) {
414 +                               return NF_DROP;
415 +                       }
416 +
417 +                       if (skb->dev == rt->u.dst.dev) {
418 +                               /* Drop old route. */
419 +                               dst_release(skb->dst);
420 +                               skb->dst = &rt->u.dst;
421 +
422 +                               /* this will traverse normal stack, and 
423 +                                * thus call conntrack on the icmp packet */
424 +                               icmp_send(skb, ICMP_TIME_EXCEEDED, 
425 +                                         ICMP_EXC_TTL, 0);
426 +                       }
427 +
428 +                       return NF_DROP;
429 +               }
430 +
431 +               /*
432 +                * If we are at INPUT the checksum must be recalculated since
433 +                * the length could change as the result of a defragmentation.
434 +                */
435 +               if(hooknum == NF_IP_LOCAL_IN) {
436 +                       iph->ttl = iph->ttl - 1;
437 +                       iph->check = 0;
438 +                       iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
439 +               } else {
440 +                       ip_decrease_ttl(iph);
441 +               }
442 +       }
443 +
444 +       if ((route_info->flags & IPT_ROUTE_TEE)) {
445 +               /*
446 +                * Copy the *pskb, and route the copy. Will later return
447 +                * IPT_CONTINUE for the original skb, which should continue
448 +                * on its way as if nothing happened. The copy should be
449 +                * independantly delivered to the ROUTE --gw.
450 +                */
451 +               skb = skb_copy(*pskb, GFP_ATOMIC);
452 +               if (!skb) {
453 +                       if (net_ratelimit()) 
454 +                               DEBUGP(KERN_DEBUG "ipt_ROUTE: copy failed!\n");
455 +                       return IPT_CONTINUE;
456 +               }
457 +       }
458 +
459 +       /* Tell conntrack to forget this packet since it may get confused 
460 +        * when a packet is leaving with dst address == our address.
461 +        * Good idea ? Dunno. Need advice.
462 +        *
463 +        * NEW: mark the skb with our &route_tee_track, so we avoid looping
464 +        * on any already routed packet.
465 +        */
466 +       if (!(route_info->flags & IPT_ROUTE_CONTINUE)) {
467 +               nf_conntrack_put(skb->nfct);
468 +               skb->nfct = &route_tee_track.ct_general;
469 +               skb->nfctinfo = IP_CT_NEW;
470 +               nf_conntrack_get(skb->nfct);
471 +       }
472 +
473 +       if (route_info->oif[0] != '\0') {
474 +               res = route_oif(route_info, skb);
475 +       } else if (route_info->iif[0] != '\0') {
476 +               res = route_iif(route_info, skb);
477 +       } else if (route_info->gw) {
478 +               res = route_gw(route_info, skb);
479 +       } else {
480 +               if (net_ratelimit()) 
481 +                       DEBUGP(KERN_DEBUG "ipt_ROUTE: no parameter !\n");
482 +               res = IPT_CONTINUE;
483 +       }
484 +
485 +       if ((route_info->flags & IPT_ROUTE_TEE))
486 +               res = IPT_CONTINUE;
487 +
488 +       return res;
489 +}
490 +
491 +
492 +static int ipt_route_checkentry(const char *tablename,
493 +                               const void *e,
494 +                               const struct xt_target *target,
495 +                               void *targinfo,
496 +                               
497 +                               unsigned int hook_mask)
498 +{
499 +       if (strcmp(tablename, "mangle") != 0) {
500 +               printk("ipt_ROUTE: bad table `%s', use the `mangle' table.\n",
501 +                      tablename);
502 +               return 0;
503 +       }
504 +
505 +       if (hook_mask & ~(  (1 << NF_IP_PRE_ROUTING)
506 +                           | (1 << NF_IP_LOCAL_IN)
507 +                           | (1 << NF_IP_FORWARD)
508 +                           | (1 << NF_IP_LOCAL_OUT)
509 +                           | (1 << NF_IP_POST_ROUTING))) {
510 +               printk("ipt_ROUTE: bad hook\n");
511 +               return 0;
512 +       }
513 +
514 +       
515 +
516 +
517 +
518 +       
519 +       
520 +
521 +       return 1;
522 +}
523 +
524 +
525 +static struct ipt_target ipt_route_reg = { 
526 +       .name = "ROUTE",
527 +       .target = ipt_route_target,
528 +       .targetsize = sizeof(struct ipt_route_target_info),
529 +       .checkentry = ipt_route_checkentry,
530 +       .me = THIS_MODULE,
531 +};
532 +
533 +static int __init init(void)
534 +{
535 +       /* Set up fake conntrack (stolen from raw.patch):
536 +           - to never be deleted, not in any hashes */
537 +       atomic_set(&route_tee_track.ct_general.use, 1);
538 +       /*  - and look it like as a confirmed connection */
539 +       set_bit(IPS_CONFIRMED_BIT, &route_tee_track.status);
540 +       /* Initialize fake conntrack so that NAT will skip it */
541 +       route_tee_track.status |= IPS_NAT_DONE_MASK;
542 +
543 +       return xt_register_target(&ipt_route_reg);
544 +}
545 +
546 +
547 +static void __exit fini(void)
548 +{
549 +       xt_unregister_target(&ipt_route_reg);
550 +}
551 +
552 +module_init(init);
553 +module_exit(fini);
554 diff -NurpP --minimal linux-2.6.21.a/net/ipv6/netfilter/Kconfig linux-2.6.21.b/net/ipv6/netfilter/Kconfig
555 --- linux-2.6.21.a/net/ipv6/netfilter/Kconfig   2007-05-30 11:13:04.000000000 +0200
556 +++ linux-2.6.21.b/net/ipv6/netfilter/Kconfig   2007-05-30 11:40:37.000000000 +0200
557 @@ -209,5 +209,18 @@ config IP6_NF_RAW
558           If you want to compile it as a module, say M here and read
559           <file:Documentation/modules.txt>.  If unsure, say `N'.
560  
561 +config IP6_NF_TARGET_ROUTE
562 +       tristate 'ROUTE target support'
563 +       depends on IP6_NF_MANGLE
564 +       help
565 +         This option adds a `ROUTE' target, which enables you to setup unusual
566 +         routes. The ROUTE target is also able to change the incoming interface
567 +         of a packet.
568 +       
569 +         The target can be or not a final target. It has to be used inside the 
570 +         mangle table.
571 +         
572 +         Not working as a module.
573 +
574  endmenu
575  
576 diff -NurpP --minimal linux-2.6.21.a/net/ipv6/netfilter/Makefile linux-2.6.21.b/net/ipv6/netfilter/Makefile
577 --- linux-2.6.21.a/net/ipv6/netfilter/Makefile  2007-05-30 11:13:04.000000000 +0200
578 +++ linux-2.6.21.b/net/ipv6/netfilter/Makefile  2007-05-30 11:40:37.000000000 +0200
579 @@ -21,6 +21,7 @@ obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw
580  obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
581  obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
582  obj-$(CONFIG_IP6_NF_MATCH_MH) += ip6t_mh.o
583 +obj-$(CONFIG_IP6_NF_TARGET_ROUTE) += ip6t_ROUTE.o
584  
585  # objects for l3 independent conntrack
586  nf_conntrack_ipv6-objs  :=  nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o nf_conntrack_reasm.o
587 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
588 --- linux-2.6.21.a/net/ipv6/netfilter/ip6t_ROUTE.c      1970-01-01 01:00:00.000000000 +0100
589 +++ linux-2.6.21.b/net/ipv6/netfilter/ip6t_ROUTE.c      2007-05-30 11:40:37.000000000 +0200
590 @@ -0,0 +1,308 @@
591 +/*
592 + * This implements the ROUTE v6 target, which enables you to setup unusual
593 + * routes not supported by the standard kernel routing table.
594 + *
595 + * Copyright (C) 2003 Cedric de Launois <delaunois@info.ucl.ac.be>
596 + *
597 + * v 1.1 2004/11/23
598 + *
599 + * This software is distributed under GNU GPL v2, 1991
600 + */
601 +
602 +#include <linux/module.h>
603 +#include <linux/skbuff.h>
604 +#include <linux/ipv6.h>
605 +#include <linux/netfilter/x_tables.h>
606 +#include <linux/netfilter_ipv6/ip6_tables.h>
607 +#include <linux/netfilter_ipv6/ip6t_ROUTE.h>
608 +#include <linux/netdevice.h>
609 +#include <net/ipv6.h>
610 +#include <net/ndisc.h>
611 +#include <net/ip6_route.h>
612 +#include <linux/icmpv6.h>
613 +
614 +#if 1
615 +#define DEBUGP printk
616 +#else
617 +#define DEBUGP(format, args...)
618 +#endif
619 +
620 +#define NIP6(addr) \
621 +       ntohs((addr).s6_addr16[0]), \
622 +       ntohs((addr).s6_addr16[1]), \
623 +       ntohs((addr).s6_addr16[2]), \
624 +       ntohs((addr).s6_addr16[3]), \
625 +       ntohs((addr).s6_addr16[4]), \
626 +       ntohs((addr).s6_addr16[5]), \
627 +       ntohs((addr).s6_addr16[6]), \
628 +       ntohs((addr).s6_addr16[7])
629 +
630 +/* Route the packet according to the routing keys specified in
631 + * route_info. Keys are :
632 + *  - ifindex : 
633 + *      0 if no oif preferred, 
634 + *      otherwise set to the index of the desired oif
635 + *  - route_info->gw :
636 + *      0 if no gateway specified,
637 + *      otherwise set to the next host to which the pkt must be routed
638 + * If success, skb->dev is the output device to which the packet must 
639 + * be sent and skb->dst is not NULL
640 + *
641 + * RETURN:  1 if the packet was succesfully routed to the 
642 + *            destination desired
643 + *          0 if the kernel routing table could not route the packet
644 + *            according to the keys specified
645 + */
646 +static int 
647 +route6(struct sk_buff *skb,
648 +       unsigned int ifindex,
649 +       const struct ip6t_route_target_info *route_info)
650 +{
651 +       struct rt6_info *rt = NULL;
652 +       struct ipv6hdr *ipv6h = ipv6_hdr(skb);
653 +       struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
654 +
655 +       DEBUGP("ip6t_ROUTE: called with: ");
656 +       DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr));
657 +       DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(*gw));
658 +       DEBUGP("OUT=%s\n", route_info->oif);
659 +       
660 +       if (ipv6_addr_any(gw))
661 +               rt = rt6_lookup(&ipv6h->daddr, &ipv6h->saddr, ifindex, 1);
662 +       else
663 +               rt = rt6_lookup(gw, &ipv6h->saddr, ifindex, 1);
664 +
665 +       if (!rt)
666 +               goto no_route;
667 +
668 +       DEBUGP("ip6t_ROUTE: routing gives: ");
669 +       DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_dst.addr));
670 +       DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_gateway));
671 +       DEBUGP("OUT=%s\n", rt->rt6i_dev->name);
672 +
673 +       if (ifindex && rt->rt6i_dev->ifindex!=ifindex)
674 +               goto wrong_route;
675 +       
676 +       if (!rt->rt6i_nexthop) {
677 +               DEBUGP("ip6t_ROUTE: discovering neighbour\n");
678 +               rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_dst.addr);
679 +       }
680 +
681 +       /* Drop old route. */
682 +       dst_release(skb->dst);
683 +       skb->dst = &rt->u.dst;
684 +       skb->dev = rt->rt6i_dev;
685 +       return 1;
686 +
687 + wrong_route:
688 +       dst_release(&rt->u.dst);
689 + no_route:
690 +       if (!net_ratelimit())
691 +               return 0;
692 +
693 +       printk("ip6t_ROUTE: no explicit route found ");
694 +       if (ifindex)
695 +               printk("via interface %s ", route_info->oif);
696 +       if (!ipv6_addr_any(gw))
697 +               printk("via gateway %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", NIP6(*gw));
698 +       printk("\n");
699 +       return 0;
700 +}
701 +
702 +
703 +/* Stolen from ip6_output_finish
704 + * PRE : skb->dev is set to the device we are leaving by
705 + *       skb->dst is not NULL
706 + * POST: the packet is sent with the link layer header pushed
707 + *       the packet is destroyed
708 + */
709 +static void ip_direct_send(struct sk_buff *skb)
710 +{
711 +       struct dst_entry *dst = skb->dst;
712 +       struct hh_cache *hh = dst->hh;
713 +
714 +       if (hh) {
715 +               neigh_hh_output(dst->hh, skb);
716 +       } else if (dst->neighbour)
717 +               dst->neighbour->output(skb);
718 +       else {
719 +               if (net_ratelimit())
720 +                       DEBUGP(KERN_DEBUG "ip6t_ROUTE: no hdr & no neighbour cache!\n");
721 +               kfree_skb(skb);
722 +       }
723 +}
724 +
725 +
726 +static unsigned int 
727 +route6_oif(const struct ip6t_route_target_info *route_info,
728 +          struct sk_buff *skb) 
729 +{
730 +       unsigned int ifindex = 0;
731 +       struct net_device *dev_out = NULL;
732 +
733 +       /* The user set the interface name to use.
734 +        * Getting the current interface index.
735 +        */
736 +       if ((dev_out = dev_get_by_name(route_info->oif))) {
737 +               ifindex = dev_out->ifindex;
738 +       } else {
739 +               /* Unknown interface name : packet dropped */
740 +               if (net_ratelimit()) 
741 +                       DEBUGP("ip6t_ROUTE: oif interface %s not found\n", route_info->oif);
742 +
743 +               if (route_info->flags & IP6T_ROUTE_CONTINUE)
744 +                       return IP6T_CONTINUE;
745 +               else
746 +                       return NF_DROP;
747 +       }
748 +
749 +       /* Trying the standard way of routing packets */
750 +       if (route6(skb, ifindex, route_info)) {
751 +               dev_put(dev_out);
752 +               if (route_info->flags & IP6T_ROUTE_CONTINUE)
753 +                       return IP6T_CONTINUE;
754 +               
755 +               ip_direct_send(skb);
756 +               return NF_STOLEN;
757 +       } else 
758 +               return NF_DROP;
759 +}
760 +
761 +
762 +static unsigned int 
763 +route6_gw(const struct ip6t_route_target_info *route_info,
764 +         struct sk_buff *skb) 
765 +{
766 +       if (route6(skb, 0, route_info)) {
767 +               if (route_info->flags & IP6T_ROUTE_CONTINUE)
768 +                       return IP6T_CONTINUE;
769 +
770 +               ip_direct_send(skb);
771 +               return NF_STOLEN;
772 +       } else
773 +               return NF_DROP;
774 +}
775 +
776 +
777 +static unsigned int 
778 +ip6t_route_target(struct sk_buff **pskb,
779 +                 const struct net_device *in,
780 +                 const struct net_device *out,
781 +                 unsigned int hooknum,
782 +                 const struct xt_target *target,
783 +                 const void *targinfo
784 +                 )
785 +{
786 +       const struct ip6t_route_target_info *route_info = targinfo;
787 +       struct sk_buff *skb = *pskb;
788 +       struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
789 +       unsigned int res;
790 +
791 +       if (route_info->flags & IP6T_ROUTE_CONTINUE)
792 +               goto do_it;
793 +
794 +       /* If we are at PREROUTING or INPUT hook
795 +        * the TTL isn't decreased by the IP stack
796 +        */
797 +       if (hooknum == NF_IP6_PRE_ROUTING ||
798 +           hooknum == NF_IP6_LOCAL_IN) {
799 +
800 +               struct ipv6hdr *ipv6h = ipv6_hdr(skb);
801 +
802 +               if (ipv6h->hop_limit <= 1) {
803 +                       /* Force OUTPUT device used as source address */
804 +                       skb->dev = skb->dst->dev;
805 +
806 +                       icmpv6_send(skb, ICMPV6_TIME_EXCEED, 
807 +                                   ICMPV6_EXC_HOPLIMIT, 0, skb->dev);
808 +
809 +                       return NF_DROP;
810 +               }
811 +
812 +               ipv6h->hop_limit--;
813 +       }
814 +
815 +       if ((route_info->flags & IP6T_ROUTE_TEE)) {
816 +               /*
817 +                * Copy the *pskb, and route the copy. Will later return
818 +                * IP6T_CONTINUE for the original skb, which should continue
819 +                * on its way as if nothing happened. The copy should be
820 +                * independantly delivered to the ROUTE --gw.
821 +                */
822 +               skb = skb_copy(*pskb, GFP_ATOMIC);
823 +               if (!skb) {
824 +                       if (net_ratelimit()) 
825 +                               DEBUGP(KERN_DEBUG "ip6t_ROUTE: copy failed!\n");
826 +                       return IP6T_CONTINUE;
827 +               }
828 +       }
829 +
830 +do_it:
831 +       if (route_info->oif[0]) {
832 +               res = route6_oif(route_info, skb);
833 +       } else if (!ipv6_addr_any(gw)) {
834 +               res = route6_gw(route_info, skb);
835 +       } else {
836 +               if (net_ratelimit()) 
837 +                       DEBUGP(KERN_DEBUG "ip6t_ROUTE: no parameter !\n");
838 +               res = IP6T_CONTINUE;
839 +       }
840 +
841 +       if ((route_info->flags & IP6T_ROUTE_TEE))
842 +               res = IP6T_CONTINUE;
843 +
844 +       return res;
845 +}
846 +
847 +
848 +static int 
849 +ip6t_route_checkentry(const char *tablename,
850 +                     const void *entry,
851 +                     const struct xt_target *target,
852 +                     void *targinfo,
853 +                     
854 +                     unsigned int hook_mask)
855 +{
856 +       if (strcmp(tablename, "mangle") != 0) {
857 +               printk("ip6t_ROUTE: can only be called from \"mangle\" table.\n");
858 +               return 0;
859 +       }
860 +
861 +       /* if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_route_target_info))) {
862 +               printk(KERN_WARNING "ip6t_ROUTE: targinfosize %u != %Zu\n",
863 +                      targinfosize,
864 +                      IP6T_ALIGN(sizeof(struct ip6t_route_target_info)));
865 +               return 0;
866 +       } */
867 +
868 +       return 1;
869 +}
870 +
871 +
872 +static struct ip6t_target ip6t_route_reg = {
873 +       .name       = "ROUTE",
874 +       .target     = ip6t_route_target,
875 +       .targetsize = sizeof(struct ip6t_route_target_info),
876 +       .checkentry = ip6t_route_checkentry,
877 +       .me         = THIS_MODULE
878 +};
879 +
880 +
881 +static int __init init(void)
882 +{
883 +       printk(KERN_DEBUG "registering ipv6 ROUTE target\n");
884 +       if (xt_register_target(&ip6t_route_reg))
885 +               return -EINVAL;
886 +
887 +       return 0;
888 +}
889 +
890 +
891 +static void __exit fini(void)
892 +{
893 +       xt_unregister_target(&ip6t_route_reg);
894 +}
895 +
896 +module_init(init);
897 +module_exit(fini);
898 +MODULE_LICENSE("GPL");
899 --- a/net/ipv6/ndisc.c  2007-07-09 01:32:17.000000000 +0200
900 +++ b/net/ipv6/ndisc.c  2007-08-02 13:23:26.000000000 +0200
901 @@ -154,6 +154,8 @@ struct neigh_table nd_tbl = {
902         .gc_thresh3 =   1024,
903  };
904  
905 +EXPORT_SYMBOL(nd_tbl);
906 +
907  /* ND options */
908  struct ndisc_options {
909         struct nd_opt_hdr *nd_opt_array[__ND_OPT_ARRAY_MAX];
This page took 0.091288 seconds and 3 git commands to generate.