diff options
| -rw-r--r-- | target/linux/au1000-2.6/config | 2 | ||||
| -rw-r--r-- | target/linux/brcm-2.6/config | 4 | ||||
| -rw-r--r-- | target/linux/brcm63xx-2.6/config | 2 | ||||
| -rw-r--r-- | target/linux/generic-2.6/patches/108-netfilter_route.patch | 914 | ||||
| -rw-r--r-- | target/linux/rb532-2.6/config | 2 | ||||
| -rw-r--r-- | target/linux/sibyte-2.6/config | 2 | ||||
| -rw-r--r-- | target/linux/uml-2.6/config | 2 | ||||
| -rw-r--r-- | target/linux/x86-2.6/config | 2 | ||||
| -rw-r--r-- | target/linux/xscale-2.6/config | 2 | 
9 files changed, 931 insertions, 1 deletions
| diff --git a/target/linux/au1000-2.6/config b/target/linux/au1000-2.6/config index b86c699a1..9c498efd1 100644 --- a/target/linux/au1000-2.6/config +++ b/target/linux/au1000-2.6/config @@ -415,6 +415,7 @@ CONFIG_IP_NF_NAT=y  CONFIG_IP_NF_NAT_NEEDED=y  CONFIG_IP_NF_TARGET_MASQUERADE=y  CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_TARGET_ROUTE=m  # CONFIG_IP_NF_TARGET_NETMAP is not set  # CONFIG_IP_NF_TARGET_SAME is not set  # CONFIG_IP_NF_NAT_SNMP_BASIC is not set @@ -462,6 +463,7 @@ CONFIG_IP6_NF_FILTER=m  CONFIG_IP6_NF_TARGET_IMQ=m  # CONFIG_IP6_NF_TARGET_LOG is not set  CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_TARGET_ROUTE=m  CONFIG_IP6_NF_MANGLE=m  # CONFIG_IP6_NF_TARGET_HL is not set  # CONFIG_IP6_NF_RAW is not set diff --git a/target/linux/brcm-2.6/config b/target/linux/brcm-2.6/config index 180a45f58..75e9a1921 100644 --- a/target/linux/brcm-2.6/config +++ b/target/linux/brcm-2.6/config @@ -1,7 +1,7 @@  #  # Automatically generated make config: don't edit  # Linux kernel version: 2.6.17 -# Fri Jun 23 19:00:36 2006 +# Tue Aug 22 11:48:58 2006  #  CONFIG_MIPS=y @@ -386,6 +386,7 @@ CONFIG_IP_NF_NAT=y  CONFIG_IP_NF_NAT_NEEDED=y  CONFIG_IP_NF_TARGET_MASQUERADE=y  CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_TARGET_ROUTE=m  # CONFIG_IP_NF_TARGET_NETMAP is not set  # CONFIG_IP_NF_TARGET_SAME is not set  # CONFIG_IP_NF_NAT_SNMP_BASIC is not set @@ -433,6 +434,7 @@ CONFIG_IP6_NF_FILTER=m  CONFIG_IP6_NF_TARGET_IMQ=m  # CONFIG_IP6_NF_TARGET_LOG is not set  CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_TARGET_ROUTE=m  CONFIG_IP6_NF_MANGLE=m  # CONFIG_IP6_NF_TARGET_HL is not set  # CONFIG_IP6_NF_RAW is not set diff --git a/target/linux/brcm63xx-2.6/config b/target/linux/brcm63xx-2.6/config index c5f8d58bf..f7c7c0b0d 100644 --- a/target/linux/brcm63xx-2.6/config +++ b/target/linux/brcm63xx-2.6/config @@ -418,6 +418,7 @@ CONFIG_IP_NF_NAT=y  CONFIG_IP_NF_NAT_NEEDED=y  CONFIG_IP_NF_TARGET_MASQUERADE=y  CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_TARGET_ROUTE=m  # CONFIG_IP_NF_TARGET_NETMAP is not set  # CONFIG_IP_NF_TARGET_SAME is not set  # CONFIG_IP_NF_NAT_SNMP_BASIC is not set @@ -464,6 +465,7 @@ CONFIG_IP6_NF_FILTER=m  CONFIG_IP6_NF_TARGET_IMQ=m  # CONFIG_IP6_NF_TARGET_LOG is not set  CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_TARGET_ROUTE=m  CONFIG_IP6_NF_MANGLE=m  # CONFIG_IP6_NF_TARGET_HL is not set  # CONFIG_IP6_NF_RAW is not set diff --git a/target/linux/generic-2.6/patches/108-netfilter_route.patch b/target/linux/generic-2.6/patches/108-netfilter_route.patch new file mode 100644 index 000000000..571d6a381 --- /dev/null +++ b/target/linux/generic-2.6/patches/108-netfilter_route.patch @@ -0,0 +1,914 @@ +diff -u'rNF^function' linux-2.6.16.7/include/linux/netfilter_ipv4/ipt_ROUTE.h linux-2.6.16.7-ROUTE/include/linux/netfilter_ipv4/ipt_ROUTE.h +--- linux-2.6.16.7/include/linux/netfilter_ipv4/ipt_ROUTE.h     1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.7-ROUTE/include/linux/netfilter_ipv4/ipt_ROUTE.h       2006-06-14 16:40:49.000000000 +0200 +@@ -0,0 +1,23 @@ ++/* Header file for iptables ipt_ROUTE target ++ * ++ * (C) 2002 by Cédric de Launois <delaunois@info.ucl.ac.be> ++ * ++ * This software is distributed under GNU GPL v2, 1991 ++ */ ++#ifndef _IPT_ROUTE_H_target ++#define _IPT_ROUTE_H_target ++ ++#define IPT_ROUTE_IFNAMSIZ 16 ++ ++struct ipt_route_target_info { ++       char      oif[IPT_ROUTE_IFNAMSIZ];      /* Output Interface Name */ ++       char      iif[IPT_ROUTE_IFNAMSIZ];      /* Input Interface Name  */ ++       u_int32_t gw;                           /* IP address of gateway */ ++       u_int8_t  flags; ++}; ++ ++/* Values for "flags" field */ ++#define IPT_ROUTE_CONTINUE        0x01 ++#define IPT_ROUTE_TEE             0x02 ++ ++#endif /*_IPT_ROUTE_H_target*/ +diff -u'rNF^function' linux-2.6.16.7/include/linux/netfilter_ipv6/ip6t_ROUTE.h linux-2.6.16.7-ROUTE/include/linux/netfilter_ipv6/ip6t_ROUTE.h +--- linux-2.6.16.7/include/linux/netfilter_ipv6/ip6t_ROUTE.h    1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.7-ROUTE/include/linux/netfilter_ipv6/ip6t_ROUTE.h      2006-06-14 16:41:08.000000000 +0200 +@@ -0,0 +1,23 @@ ++/* Header file for iptables ip6t_ROUTE target ++ * ++ * (C) 2003 by Cédric de Launois <delaunois@info.ucl.ac.be> ++ * ++ * This software is distributed under GNU GPL v2, 1991 ++ */ ++#ifndef _IPT_ROUTE_H_target ++#define _IPT_ROUTE_H_target ++ ++#define IP6T_ROUTE_IFNAMSIZ 16 ++ ++struct ip6t_route_target_info { ++       char      oif[IP6T_ROUTE_IFNAMSIZ];     /* Output Interface Name */ ++       char      iif[IP6T_ROUTE_IFNAMSIZ];     /* Input Interface Name  */ ++       u_int32_t gw[4];                        /* IPv6 address of gateway */ ++       u_int8_t  flags; ++}; ++ ++/* Values for "flags" field */ ++#define IP6T_ROUTE_CONTINUE        0x01 ++#define IP6T_ROUTE_TEE             0x02 ++ ++#endif /*_IP6T_ROUTE_H_target*/ +diff -u'rNF^function' linux-2.6.16.7/net/ipv4/netfilter/Kconfig linux-2.6.16.7-ROUTE/net/ipv4/netfilter/Kconfig +--- linux-2.6.16.7/net/ipv4/netfilter/Kconfig   2006-06-14 16:05:44.000000000 +0200 ++++ linux-2.6.16.7-ROUTE/net/ipv4/netfilter/Kconfig     2006-06-14 16:46:40.000000000 +0200 +@@ -491,6 +491,23 @@ + +          To compile it as a module, choose M here.  If unsure, say N. + ++config IP_NF_TARGET_ROUTE ++        tristate  'ROUTE target support' ++        depends on IP_NF_MANGLE ++        help ++          This option adds a `ROUTE' target, which enables you to setup unusual ++          routes. For example, the ROUTE lets you route a received packet through ++          an interface or towards a host, even if the regular destination of the ++          packet is the router itself. The ROUTE target is also able to change the ++          incoming interface of a packet. ++ ++          The target can be or not a final target. It has to be used inside the ++          mangle table. ++ ++          If you want to compile it as a module, say M here and read ++          Documentation/modules.txt.  The module will be called ipt_ROUTE.o. ++          If unsure, say `N'. ++ + config IP_NF_TARGET_NETMAP +        tristate "NETMAP target support" +        depends on IP_NF_NAT +diff -u'rNF^function' linux-2.6.16.7/net/ipv4/netfilter/Makefile linux-2.6.16.7-ROUTE/net/ipv4/netfilter/Makefile +--- linux-2.6.16.7/net/ipv4/netfilter/Makefile  2006-06-14 16:05:44.000000000 +0200 ++++ linux-2.6.16.7-ROUTE/net/ipv4/netfilter/Makefile    2006-06-14 16:44:02.000000000 +0200 +@@ -74,6 +74,7 @@ + obj-$(CONFIG_IP_NF_TARGET_IMQ) += ipt_IMQ.o + obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o + obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o ++obj-$(CONFIG_IP_NF_TARGET_ROUTE) += ipt_ROUTE.o + obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o + obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o + obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o +diff -u'rNF^function' linux-2.6.16.7/net/ipv4/netfilter/ipt_ROUTE.c linux-2.6.16.7-ROUTE/net/ipv4/netfilter/ipt_ROUTE.c +--- linux-2.6.16.7/net/ipv4/netfilter/ipt_ROUTE.c       1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.7-ROUTE/net/ipv4/netfilter/ipt_ROUTE.c 2006-06-14 16:42:23.000000000 +0200 +@@ -0,0 +1,461 @@ ++/* ++ * This implements the ROUTE target, which enables you to setup unusual ++ * routes not supported by the standard kernel routing table. ++ * ++ * Copyright (C) 2002 Cedric de Launois <delaunois@info.ucl.ac.be> ++ * ++ * v 1.11 2004/11/23 ++ * ++ * This software is distributed under GNU GPL v2, 1991 ++ */ ++ ++#include <linux/module.h> ++#include <linux/skbuff.h> ++#include <linux/ip.h> ++#include <linux/netfilter_ipv4/ip_tables.h> ++#include <linux/netfilter_ipv4/ip_conntrack.h> ++#include <linux/netfilter_ipv4/ipt_ROUTE.h> ++#include <linux/netdevice.h> ++#include <linux/route.h> ++#include <linux/if_arp.h> ++#include <net/ip.h> ++#include <net/route.h> ++#include <net/icmp.h> ++#include <net/checksum.h> ++ ++#if 0 ++#define DEBUGP printk ++#else ++#define DEBUGP(format, args...) ++#endif ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Cedric de Launois <delaunois@info.ucl.ac.be>"); ++MODULE_DESCRIPTION("iptables ROUTE target module"); ++ ++/* Try to route the packet according to the routing keys specified in ++ * route_info. Keys are : ++ *  - ifindex : ++ *      0 if no oif preferred, ++ *      otherwise set to the index of the desired oif ++ *  - route_info->gw : ++ *      0 if no gateway specified, ++ *      otherwise set to the next host to which the pkt must be routed ++ * If success, skb->dev is the output device to which the packet must ++ * be sent and skb->dst is not NULL ++ * ++ * RETURN: -1 if an error occured ++ *          1 if the packet was succesfully routed to the ++ *            destination desired ++ *          0 if the kernel routing table could not route the packet ++ *            according to the keys specified ++ */ ++static int route(struct sk_buff *skb, ++                unsigned int ifindex, ++                const struct ipt_route_target_info *route_info) ++{ ++       int err; ++       struct rtable *rt; ++       struct iphdr *iph = skb->nh.iph; ++       struct flowi fl = { ++               .oif = ifindex, ++               .nl_u = { ++                       .ip4_u = { ++                               .daddr = iph->daddr, ++                               .saddr = 0, ++                               .tos = RT_TOS(iph->tos), ++                               .scope = RT_SCOPE_UNIVERSE, ++                       } ++               } ++       }; ++ ++       /* The destination address may be overloaded by the target */ ++       if (route_info->gw) ++               fl.fl4_dst = route_info->gw; ++ ++       /* Trying to route the packet using the standard routing table. */ ++       if ((err = ip_route_output_key(&rt, &fl))) { ++               if (net_ratelimit()) ++                       DEBUGP("ipt_ROUTE: couldn't route pkt (err: %i)",err); ++               return -1; ++       } ++ ++       /* Drop old route. */ ++       dst_release(skb->dst); ++       skb->dst = NULL; ++ ++       /* Success if no oif specified or if the oif correspond to the ++        * one desired */ ++       if (!ifindex || rt->u.dst.dev->ifindex == ifindex) { ++               skb->dst = &rt->u.dst; ++               skb->dev = skb->dst->dev; ++               skb->protocol = htons(ETH_P_IP); ++               return 1; ++       } ++ ++       /* The interface selected by the routing table is not the one ++        * specified by the user. This may happen because the dst address ++        * is one of our own addresses. ++        */ ++       if (net_ratelimit()) ++               DEBUGP("ipt_ROUTE: failed to route as desired gw=%u.%u.%u.%u oif=%i (got oif=%i)\n", ++                      NIPQUAD(route_info->gw), ifindex, rt->u.dst.dev->ifindex); ++ ++       return 0; ++} ++ ++ ++/* Stolen from ip_finish_output2 ++ * PRE : skb->dev is set to the device we are leaving by ++ *       skb->dst is not NULL ++ * POST: the packet is sent with the link layer header pushed ++ *       the packet is destroyed ++ */ ++static void ip_direct_send(struct sk_buff *skb) ++{ ++       struct dst_entry *dst = skb->dst; ++       struct hh_cache *hh = dst->hh; ++       struct net_device *dev = dst->dev; ++       int hh_len = LL_RESERVED_SPACE(dev); ++ ++       /* Be paranoid, rather than too clever. */ ++       if (unlikely(skb_headroom(skb) < hh_len && dev->hard_header)) { ++               struct sk_buff *skb2; ++ ++               skb2 = skb_realloc_headroom(skb, LL_RESERVED_SPACE(dev)); ++               if (skb2 == NULL) { ++                       kfree_skb(skb); ++                       return; ++               } ++               if (skb->sk) ++                       skb_set_owner_w(skb2, skb->sk); ++               kfree_skb(skb); ++               skb = skb2; ++       } ++ ++       if (hh) { ++               int hh_alen; ++ ++               read_lock_bh(&hh->hh_lock); ++               hh_alen = HH_DATA_ALIGN(hh->hh_len); ++               memcpy(skb->data - hh_alen, hh->hh_data, hh_alen); ++               read_unlock_bh(&hh->hh_lock); ++               skb_push(skb, hh->hh_len); ++               hh->hh_output(skb); ++       } else if (dst->neighbour) ++               dst->neighbour->output(skb); ++       else { ++               if (net_ratelimit()) ++                       DEBUGP(KERN_DEBUG "ipt_ROUTE: no hdr & no neighbour cache!\n"); ++               kfree_skb(skb); ++       } ++} ++ ++ ++/* PRE : skb->dev is set to the device we are leaving by ++ * POST: - the packet is directly sent to the skb->dev device, without ++ *         pushing the link layer header. ++ *       - the packet is destroyed ++ */ ++static inline int dev_direct_send(struct sk_buff *skb) ++{ ++       return dev_queue_xmit(skb); ++} ++ ++ ++static unsigned int route_oif(const struct ipt_route_target_info *route_info, ++                             struct sk_buff *skb) ++{ ++       unsigned int ifindex = 0; ++       struct net_device *dev_out = NULL; ++ ++       /* The user set the interface name to use. ++        * Getting the current interface index. ++        */ ++       if ((dev_out = dev_get_by_name(route_info->oif))) { ++               ifindex = dev_out->ifindex; ++       } else { ++               /* Unknown interface name : packet dropped */ ++               if (net_ratelimit()) ++                       DEBUGP("ipt_ROUTE: oif interface %s not found\n", route_info->oif); ++               return NF_DROP; ++       } ++ ++       /* Trying the standard way of routing packets */ ++       switch (route(skb, ifindex, route_info)) { ++       case 1: ++               dev_put(dev_out); ++               if (route_info->flags & IPT_ROUTE_CONTINUE) ++                       return IPT_CONTINUE; ++ ++               ip_direct_send(skb); ++               return NF_STOLEN; ++ ++       case 0: ++               /* Failed to send to oif. Trying the hard way */ ++               if (route_info->flags & IPT_ROUTE_CONTINUE) ++                       return NF_DROP; ++ ++               if (net_ratelimit()) ++                       DEBUGP("ipt_ROUTE: forcing the use of %i\n", ++                              ifindex); ++ ++               /* We have to force the use of an interface. ++                * This interface must be a tunnel interface since ++                * otherwise we can't guess the hw address for ++                * the packet. For a tunnel interface, no hw address ++                * is needed. ++                */ ++               if ((dev_out->type != ARPHRD_TUNNEL) ++                   && (dev_out->type != ARPHRD_IPGRE)) { ++                       if (net_ratelimit()) ++                               DEBUGP("ipt_ROUTE: can't guess the hw addr !\n"); ++                       dev_put(dev_out); ++                       return NF_DROP; ++               } ++ ++               /* Send the packet. This will also free skb ++                * Do not go through the POST_ROUTING hook because ++                * skb->dst is not set and because it will probably ++                * get confused by the destination IP address. ++                */ ++               skb->dev = dev_out; ++               dev_direct_send(skb); ++               dev_put(dev_out); ++               return NF_STOLEN; ++ ++       default: ++               /* Unexpected error */ ++               dev_put(dev_out); ++               return NF_DROP; ++       } ++} ++ ++ ++static unsigned int route_iif(const struct ipt_route_target_info *route_info, ++                             struct sk_buff *skb) ++{ ++       struct net_device *dev_in = NULL; ++ ++       /* Getting the current interface index. */ ++       if (!(dev_in = dev_get_by_name(route_info->iif))) { ++               if (net_ratelimit()) ++                       DEBUGP("ipt_ROUTE: iif interface %s not found\n", route_info->iif); ++               return NF_DROP; ++       } ++ ++       skb->dev = dev_in; ++       dst_release(skb->dst); ++       skb->dst = NULL; ++ ++       netif_rx(skb); ++       dev_put(dev_in); ++       return NF_STOLEN; ++} ++ ++ ++static unsigned int route_gw(const struct ipt_route_target_info *route_info, ++                            struct sk_buff *skb) ++{ ++       if (route(skb, 0, route_info)!=1) ++               return NF_DROP; ++ ++       if (route_info->flags & IPT_ROUTE_CONTINUE) ++               return IPT_CONTINUE; ++ ++       ip_direct_send(skb); ++       return NF_STOLEN; ++} ++ ++ ++/* To detect and deter routed packet loopback when using the --tee option, ++ * we take a page out of the raw.patch book: on the copied skb, we set up ++ * a fake ->nfct entry, pointing to the local &route_tee_track. We skip ++ * routing packets when we see they already have that ->nfct. ++ */ ++ ++static struct ip_conntrack route_tee_track; ++ ++static unsigned int ipt_route_target(struct sk_buff **pskb, ++                                    const struct net_device *in, ++                                    const struct net_device *out, ++                                    unsigned int hooknum, ++                                    const void *targinfo, ++                                    void *userinfo) ++{ ++       const struct ipt_route_target_info *route_info = targinfo; ++       struct sk_buff *skb = *pskb; ++       unsigned int res; ++ ++       if (skb->nfct == &route_tee_track.ct_general) { ++               /* Loopback - a packet we already routed, is to be ++                * routed another time. Avoid that, now. ++                */ ++               if (net_ratelimit()) ++                       DEBUGP(KERN_DEBUG "ipt_ROUTE: loopback - DROP!\n"); ++               return NF_DROP; ++       } ++ ++       /* If we are at PREROUTING or INPUT hook ++        * the TTL isn't decreased by the IP stack ++        */ ++       if (hooknum == NF_IP_PRE_ROUTING || ++           hooknum == NF_IP_LOCAL_IN) { ++ ++               struct iphdr *iph = skb->nh.iph; ++ ++               if (iph->ttl <= 1) { ++                       struct rtable *rt; ++                       struct flowi fl = { ++                               .oif = 0, ++                               .nl_u = { ++                                       .ip4_u = { ++                                               .daddr = iph->daddr, ++                                               .saddr = iph->saddr, ++                                               .tos = RT_TOS(iph->tos), ++                                               .scope = ((iph->tos & RTO_ONLINK) ? ++                                                         RT_SCOPE_LINK : ++                                                         RT_SCOPE_UNIVERSE) ++                                       } ++                               } ++                       }; ++ ++                       if (ip_route_output_key(&rt, &fl)) { ++                               return NF_DROP; ++                       } ++ ++                       if (skb->dev == rt->u.dst.dev) { ++                               /* Drop old route. */ ++                               dst_release(skb->dst); ++                               skb->dst = &rt->u.dst; ++ ++                               /* this will traverse normal stack, and ++                                * thus call conntrack on the icmp packet */ ++                               icmp_send(skb, ICMP_TIME_EXCEEDED, ++                                         ICMP_EXC_TTL, 0); ++                       } ++ ++                       return NF_DROP; ++               } ++ ++               /* ++                * If we are at INPUT the checksum must be recalculated since ++                * the length could change as the result of a defragmentation. ++                */ ++               if(hooknum == NF_IP_LOCAL_IN) { ++                       iph->ttl = iph->ttl - 1; ++                       iph->check = 0; ++                       iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); ++               } else { ++                       ip_decrease_ttl(iph); ++               } ++       } ++ ++       if ((route_info->flags & IPT_ROUTE_TEE)) { ++               /* ++                * Copy the *pskb, and route the copy. Will later return ++                * IPT_CONTINUE for the original skb, which should continue ++                * on its way as if nothing happened. The copy should be ++                * independantly delivered to the ROUTE --gw. ++                */ ++               skb = skb_copy(*pskb, GFP_ATOMIC); ++               if (!skb) { ++                       if (net_ratelimit()) ++                               DEBUGP(KERN_DEBUG "ipt_ROUTE: copy failed!\n"); ++                       return IPT_CONTINUE; ++               } ++       } ++ ++       /* Tell conntrack to forget this packet since it may get confused ++        * when a packet is leaving with dst address == our address. ++        * Good idea ? Dunno. Need advice. ++        * ++        * NEW: mark the skb with our &route_tee_track, so we avoid looping ++        * on any already routed packet. ++        */ ++       if (!(route_info->flags & IPT_ROUTE_CONTINUE)) { ++               nf_conntrack_put(skb->nfct); ++               skb->nfct = &route_tee_track.ct_general; ++               skb->nfctinfo = IP_CT_NEW; ++               nf_conntrack_get(skb->nfct); ++       } ++ ++       if (route_info->oif[0] != '\0') { ++               res = route_oif(route_info, skb); ++       } else if (route_info->iif[0] != '\0') { ++               res = route_iif(route_info, skb); ++       } else if (route_info->gw) { ++               res = route_gw(route_info, skb); ++       } else { ++               if (net_ratelimit()) ++                       DEBUGP(KERN_DEBUG "ipt_ROUTE: no parameter !\n"); ++               res = IPT_CONTINUE; ++       } ++ ++       if ((route_info->flags & IPT_ROUTE_TEE)) ++               res = IPT_CONTINUE; ++ ++       return res; ++} ++ ++ ++static int ipt_route_checkentry(const char *tablename, ++                               const void *e, ++                               void *targinfo, ++                               unsigned int targinfosize, ++                               unsigned int hook_mask) ++{ ++       if (strcmp(tablename, "mangle") != 0) { ++               printk("ipt_ROUTE: bad table `%s', use the `mangle' table.\n", ++                      tablename); ++               return 0; ++       } ++ ++       if (hook_mask & ~(  (1 << NF_IP_PRE_ROUTING) ++                           | (1 << NF_IP_LOCAL_IN) ++                           | (1 << NF_IP_FORWARD) ++                           | (1 << NF_IP_LOCAL_OUT) ++                           | (1 << NF_IP_POST_ROUTING))) { ++               printk("ipt_ROUTE: bad hook\n"); ++               return 0; ++       } ++ ++       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_route_target_info))) { ++               printk(KERN_WARNING "ipt_ROUTE: targinfosize %u != %Zu\n", ++                      targinfosize, ++                      IPT_ALIGN(sizeof(struct ipt_route_target_info))); ++               return 0; ++       } ++ ++       return 1; ++} ++ ++ ++static struct ipt_target ipt_route_reg = { ++       .name = "ROUTE", ++       .target = ipt_route_target, ++       .checkentry = ipt_route_checkentry, ++       .me = THIS_MODULE, ++}; ++ ++static int __init init(void) ++{ ++       /* Set up fake conntrack (stolen from raw.patch): ++           - to never be deleted, not in any hashes */ ++       atomic_set(&route_tee_track.ct_general.use, 1); ++       /*  - and look it like as a confirmed connection */ ++       set_bit(IPS_CONFIRMED_BIT, &route_tee_track.status); ++       /* Initialize fake conntrack so that NAT will skip it */ ++       route_tee_track.status |= IPS_NAT_DONE_MASK; ++ ++       return ipt_register_target(&ipt_route_reg); ++} ++ ++ ++static void __exit fini(void) ++{ ++       ipt_unregister_target(&ipt_route_reg); ++} ++ ++module_init(init); ++module_exit(fini); +diff -u'rNF^function' linux-2.6.16.7/net/ipv6/ipv6_syms.c linux-2.6.16.7-ROUTE/net/ipv6/ipv6_syms.c +--- linux-2.6.16.7/net/ipv6/ipv6_syms.c 2006-04-17 23:53:25.000000000 +0200 ++++ linux-2.6.16.7-ROUTE/net/ipv6/ipv6_syms.c   2006-06-14 17:02:32.000000000 +0200 +@@ -12,6 +12,7 @@ + EXPORT_SYMBOL(icmpv6_statistics); + EXPORT_SYMBOL(icmpv6_err_convert); + EXPORT_SYMBOL(ndisc_mc_map); ++EXPORT_SYMBOL(nd_tbl); + EXPORT_SYMBOL(register_inet6addr_notifier); + EXPORT_SYMBOL(unregister_inet6addr_notifier); + EXPORT_SYMBOL(ip6_route_output); +diff -u'rNF^function' linux-2.6.16.7/net/ipv6/netfilter/Kconfig linux-2.6.16.7-ROUTE/net/ipv6/netfilter/Kconfig +--- linux-2.6.16.7/net/ipv6/netfilter/Kconfig   2006-06-14 16:05:44.000000000 +0200 ++++ linux-2.6.16.7-ROUTE/net/ipv6/netfilter/Kconfig     2006-06-14 16:45:45.000000000 +0200 +@@ -182,6 +182,19 @@ + +          To compile it as a module, choose M here.  If unsure, say N. + ++config IP6_NF_TARGET_ROUTE ++        tristate '    ROUTE target support' ++        depends on IP6_NF_MANGLE ++        help ++          This option adds a `ROUTE' target, which enables you to setup unusual ++          routes. The ROUTE target is also able to change the incoming interface ++          of a packet. ++ ++          The target can be or not a final target. It has to be used inside the ++          mangle table. ++ ++          Not working as a module. ++ + config IP6_NF_MANGLE +        tristate "Packet mangling" +        depends on IP6_NF_IPTABLES +diff -u'rNF^function' linux-2.6.16.7/net/ipv6/netfilter/Makefile linux-2.6.16.7-ROUTE/net/ipv6/netfilter/Makefile +--- linux-2.6.16.7/net/ipv6/netfilter/Makefile  2006-06-14 16:05:44.000000000 +0200 ++++ linux-2.6.16.7-ROUTE/net/ipv6/netfilter/Makefile    2006-06-14 16:45:00.000000000 +0200 +@@ -22,6 +22,7 @@ + obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o + obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o + obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o ++obj-$(CONFIG_IP6_NF_TARGET_ROUTE) += ip6t_ROUTE.o + + # objects for l3 independent conntrack + nf_conntrack_ipv6-objs  :=  nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o nf_conntrack_reasm.o +diff -u'rNF^function' linux-2.6.16.7/net/ipv6/netfilter/ip6t_ROUTE.c linux-2.6.16.7-ROUTE/net/ipv6/netfilter/ip6t_ROUTE.c +--- linux-2.6.16.7/net/ipv6/netfilter/ip6t_ROUTE.c      1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.16.7-ROUTE/net/ipv6/netfilter/ip6t_ROUTE.c        2006-06-14 16:42:44.000000000 +0200 +@@ -0,0 +1,308 @@ ++/* ++ * This implements the ROUTE v6 target, which enables you to setup unusual ++ * routes not supported by the standard kernel routing table. ++ * ++ * Copyright (C) 2003 Cedric de Launois <delaunois@info.ucl.ac.be> ++ * ++ * v 1.1 2004/11/23 ++ * ++ * This software is distributed under GNU GPL v2, 1991 ++ */ ++ ++#include <linux/module.h> ++#include <linux/skbuff.h> ++#include <linux/ipv6.h> ++#include <linux/netfilter_ipv6/ip6_tables.h> ++#include <linux/netfilter_ipv6/ip6t_ROUTE.h> ++#include <linux/netdevice.h> ++#include <net/ipv6.h> ++#include <net/ndisc.h> ++#include <net/ip6_route.h> ++#include <linux/icmpv6.h> ++ ++#if 1 ++#define DEBUGP printk ++#else ++#define DEBUGP(format, args...) ++#endif ++ ++#define NIP6(addr) \ ++       ntohs((addr).s6_addr16[0]), \ ++       ntohs((addr).s6_addr16[1]), \ ++       ntohs((addr).s6_addr16[2]), \ ++       ntohs((addr).s6_addr16[3]), \ ++       ntohs((addr).s6_addr16[4]), \ ++       ntohs((addr).s6_addr16[5]), \ ++       ntohs((addr).s6_addr16[6]), \ ++       ntohs((addr).s6_addr16[7]) ++ ++/* Route the packet according to the routing keys specified in ++ * route_info. Keys are : ++ *  - ifindex : ++ *      0 if no oif preferred, ++ *      otherwise set to the index of the desired oif ++ *  - route_info->gw : ++ *      0 if no gateway specified, ++ *      otherwise set to the next host to which the pkt must be routed ++ * If success, skb->dev is the output device to which the packet must ++ * be sent and skb->dst is not NULL ++ * ++ * RETURN:  1 if the packet was succesfully routed to the ++ *            destination desired ++ *          0 if the kernel routing table could not route the packet ++ *            according to the keys specified ++ */ ++static int ++route6(struct sk_buff *skb, ++       unsigned int ifindex, ++       const struct ip6t_route_target_info *route_info) ++{ ++       struct rt6_info *rt = NULL; ++       struct ipv6hdr *ipv6h = skb->nh.ipv6h; ++       struct in6_addr *gw = (struct in6_addr*)&route_info->gw; ++ ++       DEBUGP("ip6t_ROUTE: called with: "); ++       DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr)); ++       DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(*gw)); ++       DEBUGP("OUT=%s\n", route_info->oif); ++ ++       if (ipv6_addr_any(gw)) ++               rt = rt6_lookup(&ipv6h->daddr, &ipv6h->saddr, ifindex, 1); ++       else ++               rt = rt6_lookup(gw, &ipv6h->saddr, ifindex, 1); ++ ++       if (!rt) ++               goto no_route; ++ ++       DEBUGP("ip6t_ROUTE: routing gives: "); ++       DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_dst.addr)); ++       DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_gateway)); ++       DEBUGP("OUT=%s\n", rt->rt6i_dev->name); ++ ++       if (ifindex && rt->rt6i_dev->ifindex!=ifindex) ++               goto wrong_route; ++ ++       if (!rt->rt6i_nexthop) { ++               DEBUGP("ip6t_ROUTE: discovering neighbour\n"); ++               rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_dst.addr); ++       } ++ ++       /* Drop old route. */ ++       dst_release(skb->dst); ++       skb->dst = &rt->u.dst; ++       skb->dev = rt->rt6i_dev; ++       return 1; ++ ++ wrong_route: ++       dst_release(&rt->u.dst); ++ no_route: ++       if (!net_ratelimit()) ++               return 0; ++ ++       printk("ip6t_ROUTE: no explicit route found "); ++       if (ifindex) ++               printk("via interface %s ", route_info->oif); ++       if (!ipv6_addr_any(gw)) ++               printk("via gateway %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", NIP6(*gw)); ++       printk("\n"); ++       return 0; ++} ++ ++ ++/* Stolen from ip6_output_finish ++ * PRE : skb->dev is set to the device we are leaving by ++ *       skb->dst is not NULL ++ * POST: the packet is sent with the link layer header pushed ++ *       the packet is destroyed ++ */ ++static void ip_direct_send(struct sk_buff *skb) ++{ ++       struct dst_entry *dst = skb->dst; ++       struct hh_cache *hh = dst->hh; ++ ++       if (hh) { ++               read_lock_bh(&hh->hh_lock); ++               memcpy(skb->data - 16, hh->hh_data, 16); ++               read_unlock_bh(&hh->hh_lock); ++               skb_push(skb, hh->hh_len); ++               hh->hh_output(skb); ++       } else if (dst->neighbour) ++               dst->neighbour->output(skb); ++       else { ++               if (net_ratelimit()) ++                       DEBUGP(KERN_DEBUG "ip6t_ROUTE: no hdr & no neighbour cache!\n"); ++               kfree_skb(skb); ++       } ++} ++ ++ ++static unsigned int ++route6_oif(const struct ip6t_route_target_info *route_info, ++          struct sk_buff *skb) ++{ ++       unsigned int ifindex = 0; ++       struct net_device *dev_out = NULL; ++ ++       /* The user set the interface name to use. ++        * Getting the current interface index. ++        */ ++       if ((dev_out = dev_get_by_name(route_info->oif))) { ++               ifindex = dev_out->ifindex; ++       } else { ++               /* Unknown interface name : packet dropped */ ++               if (net_ratelimit()) ++                       DEBUGP("ip6t_ROUTE: oif interface %s not found\n", route_info->oif); ++ ++               if (route_info->flags & IP6T_ROUTE_CONTINUE) ++                       return IP6T_CONTINUE; ++               else ++                       return NF_DROP; ++       } ++ ++       /* Trying the standard way of routing packets */ ++       if (route6(skb, ifindex, route_info)) { ++               dev_put(dev_out); ++               if (route_info->flags & IP6T_ROUTE_CONTINUE) ++                       return IP6T_CONTINUE; ++ ++               ip_direct_send(skb); ++               return NF_STOLEN; ++       } else ++               return NF_DROP; ++} ++ ++ ++static unsigned int ++route6_gw(const struct ip6t_route_target_info *route_info, ++         struct sk_buff *skb) ++{ ++       if (route6(skb, 0, route_info)) { ++               if (route_info->flags & IP6T_ROUTE_CONTINUE) ++                       return IP6T_CONTINUE; ++ ++               ip_direct_send(skb); ++               return NF_STOLEN; ++       } else ++               return NF_DROP; ++} ++ ++ ++static unsigned int ++ip6t_route_target(struct sk_buff **pskb, ++                 const struct net_device *in, ++                 const struct net_device *out, ++                 unsigned int hooknum, ++                 const void *targinfo, ++                 void *userinfo) ++{ ++       const struct ip6t_route_target_info *route_info = targinfo; ++       struct sk_buff *skb = *pskb; ++       struct in6_addr *gw = (struct in6_addr*)&route_info->gw; ++       unsigned int res; ++ ++       if (route_info->flags & IP6T_ROUTE_CONTINUE) ++               goto do_it; ++ ++       /* If we are at PREROUTING or INPUT hook ++        * the TTL isn't decreased by the IP stack ++        */ ++       if (hooknum == NF_IP6_PRE_ROUTING || ++           hooknum == NF_IP6_LOCAL_IN) { ++ ++               struct ipv6hdr *ipv6h = skb->nh.ipv6h; ++ ++               if (ipv6h->hop_limit <= 1) { ++                       /* Force OUTPUT device used as source address */ ++                       skb->dev = skb->dst->dev; ++ ++                       icmpv6_send(skb, ICMPV6_TIME_EXCEED, ++                                   ICMPV6_EXC_HOPLIMIT, 0, skb->dev); ++ ++                       return NF_DROP; ++               } ++ ++               ipv6h->hop_limit--; ++       } ++ ++       if ((route_info->flags & IP6T_ROUTE_TEE)) { ++               /* ++                * Copy the *pskb, and route the copy. Will later return ++                * IP6T_CONTINUE for the original skb, which should continue ++                * on its way as if nothing happened. The copy should be ++                * independantly delivered to the ROUTE --gw. ++                */ ++               skb = skb_copy(*pskb, GFP_ATOMIC); ++               if (!skb) { ++                       if (net_ratelimit()) ++                               DEBUGP(KERN_DEBUG "ip6t_ROUTE: copy failed!\n"); ++                       return IP6T_CONTINUE; ++               } ++       } ++ ++do_it: ++       if (route_info->oif[0]) { ++               res = route6_oif(route_info, skb); ++       } else if (!ipv6_addr_any(gw)) { ++               res = route6_gw(route_info, skb); ++       } else { ++               if (net_ratelimit()) ++                       DEBUGP(KERN_DEBUG "ip6t_ROUTE: no parameter !\n"); ++               res = IP6T_CONTINUE; ++       } ++ ++       if ((route_info->flags & IP6T_ROUTE_TEE)) ++               res = IP6T_CONTINUE; ++ ++       return res; ++} ++ ++ ++static int ++ip6t_route_checkentry(const char *tablename, ++                     const struct ip6t_entry *e, ++                     void *targinfo, ++                     unsigned int targinfosize, ++                     unsigned int hook_mask) ++{ ++       if (strcmp(tablename, "mangle") != 0) { ++               printk("ip6t_ROUTE: can only be called from \"mangle\" table.\n"); ++               return 0; ++       } ++ ++       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_route_target_info))) { ++               printk(KERN_WARNING "ip6t_ROUTE: targinfosize %u != %Zu\n", ++                      targinfosize, ++                      IP6T_ALIGN(sizeof(struct ip6t_route_target_info))); ++               return 0; ++       } ++ ++       return 1; ++} ++ ++ ++static struct ip6t_target ip6t_route_reg = { ++       .name       = "ROUTE", ++       .target     = ip6t_route_target, ++       .checkentry = ip6t_route_checkentry, ++       .me         = THIS_MODULE ++}; ++ ++ ++static int __init init(void) ++{ ++       printk(KERN_DEBUG "registering ipv6 ROUTE target\n"); ++       if (ip6t_register_target(&ip6t_route_reg)) ++               return -EINVAL; ++ ++       return 0; ++} ++ ++ ++static void __exit fini(void) ++{ ++       ip6t_unregister_target(&ip6t_route_reg); ++} ++ ++module_init(init); ++module_exit(fini); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/rb532-2.6/config b/target/linux/rb532-2.6/config index 6921ad5a4..eaa3771d1 100644 --- a/target/linux/rb532-2.6/config +++ b/target/linux/rb532-2.6/config @@ -381,6 +381,7 @@ CONFIG_IP_NF_NAT=y  CONFIG_IP_NF_NAT_NEEDED=y  CONFIG_IP_NF_TARGET_MASQUERADE=y  CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_TARGET_ROUTE=m  # CONFIG_IP_NF_TARGET_NETMAP is not set  # CONFIG_IP_NF_TARGET_SAME is not set  # CONFIG_IP_NF_NAT_SNMP_BASIC is not set @@ -428,6 +429,7 @@ CONFIG_IP6_NF_FILTER=m  CONFIG_IP6_NF_TARGET_IMQ=m  # CONFIG_IP6_NF_TARGET_LOG is not set  CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_TARGET_ROUTE=m  CONFIG_IP6_NF_MANGLE=m  # CONFIG_IP6_NF_TARGET_HL is not set  # CONFIG_IP6_NF_RAW is not set diff --git a/target/linux/sibyte-2.6/config b/target/linux/sibyte-2.6/config index 5e055acaf..79c4c72f0 100644 --- a/target/linux/sibyte-2.6/config +++ b/target/linux/sibyte-2.6/config @@ -394,6 +394,7 @@ CONFIG_IP_NF_NAT=y  CONFIG_IP_NF_NAT_NEEDED=y  CONFIG_IP_NF_TARGET_MASQUERADE=y  CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_TARGET_ROUTE=m  # CONFIG_IP_NF_TARGET_NETMAP is not set  # CONFIG_IP_NF_TARGET_SAME is not set  # CONFIG_IP_NF_NAT_SNMP_BASIC is not set @@ -442,6 +443,7 @@ CONFIG_IP6_NF_FILTER=m  CONFIG_IP6_NF_TARGET_IMQ=m  # CONFIG_IP6_NF_TARGET_LOG is not set  CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_TARGET_ROUTE=m  CONFIG_IP6_NF_MANGLE=m  # CONFIG_IP6_NF_TARGET_HL is not set  # CONFIG_IP6_NF_RAW is not set diff --git a/target/linux/uml-2.6/config b/target/linux/uml-2.6/config index 0e675c1e0..4480a0120 100644 --- a/target/linux/uml-2.6/config +++ b/target/linux/uml-2.6/config @@ -357,6 +357,7 @@ CONFIG_IP_NF_NAT=y  CONFIG_IP_NF_NAT_NEEDED=y  CONFIG_IP_NF_TARGET_MASQUERADE=m  CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_ROUTE=m  CONFIG_IP_NF_TARGET_NETMAP=m  CONFIG_IP_NF_TARGET_SAME=m  CONFIG_IP_NF_NAT_SNMP_BASIC=m @@ -406,6 +407,7 @@ CONFIG_IP6_NF_FILTER=m  CONFIG_IP6_NF_TARGET_IMQ=m  CONFIG_IP6_NF_TARGET_LOG=m  CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_TARGET_ROUTE=m  CONFIG_IP6_NF_MANGLE=m  CONFIG_IP6_NF_TARGET_HL=m  CONFIG_IP6_NF_RAW=m diff --git a/target/linux/x86-2.6/config b/target/linux/x86-2.6/config index 626716c0c..fee9c7534 100644 --- a/target/linux/x86-2.6/config +++ b/target/linux/x86-2.6/config @@ -423,6 +423,7 @@ CONFIG_IP_NF_NAT=m  CONFIG_IP_NF_NAT_NEEDED=y  CONFIG_IP_NF_TARGET_MASQUERADE=m  CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_ROUTE=m  CONFIG_IP_NF_TARGET_NETMAP=m  CONFIG_IP_NF_TARGET_SAME=m  # CONFIG_IP_NF_NAT_SNMP_BASIC is not set @@ -472,6 +473,7 @@ CONFIG_IP6_NF_FILTER=m  CONFIG_IP6_NF_TARGET_IMQ=m  CONFIG_IP6_NF_TARGET_LOG=m  CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_TARGET_ROUTE=m  CONFIG_IP6_NF_MANGLE=m  CONFIG_IP6_NF_TARGET_HL=m  CONFIG_IP6_NF_RAW=m diff --git a/target/linux/xscale-2.6/config b/target/linux/xscale-2.6/config index 4eac5f9b2..74a56554b 100644 --- a/target/linux/xscale-2.6/config +++ b/target/linux/xscale-2.6/config @@ -348,6 +348,7 @@ CONFIG_IP_NF_NAT=y  CONFIG_IP_NF_NAT_NEEDED=y  CONFIG_IP_NF_TARGET_MASQUERADE=y  CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_ROUTE=m  # CONFIG_IP_NF_TARGET_NETMAP is not set  # CONFIG_IP_NF_TARGET_SAME is not set  # CONFIG_IP_NF_NAT_SNMP_BASIC is not set @@ -381,6 +382,7 @@ CONFIG_IP6_NF_MATCH_AH=m  CONFIG_IP6_NF_FILTER=m  # CONFIG_IP6_NF_TARGET_LOG is not set  CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_TARGET_ROUTE=m  # CONFIG_IP6_NF_MANGLE is not set  # CONFIG_IP6_NF_RAW is not set | 
