diff -Nru netfilter.orig/patch-o-matic/extra/ROUTE.patch netfilter/patch-o-matic/extra/ROUTE.patch --- netfilter.orig/patch-o-matic/extra/ROUTE.patch Thu Dec 5 21:44:38 2002 +++ netfilter/patch-o-matic/extra/ROUTE.patch Wed Dec 18 12:53:02 2002 @@ -1,7 +1,7 @@ diff -Nru linux.orig/include/linux/netfilter_ipv4/ipt_ROUTE.h linux/include/linux/netfilter_ipv4/ipt_ROUTE.h --- linux.orig/include/linux/netfilter_ipv4/ipt_ROUTE.h Thu Jan 1 01:00:00 1970 -+++ linux/include/linux/netfilter_ipv4/ipt_ROUTE.h Thu Nov 21 10:36:35 2002 -@@ -0,0 +1,17 @@ ++++ linux/include/linux/netfilter_ipv4/ipt_ROUTE.h Tue Dec 17 16:49:04 2002 +@@ -0,0 +1,18 @@ +/* Header file for iptables ipt_ROUTE target + * + * (C) 2002 by Cédric de Launois @@ -14,22 +14,19 @@ +#define IPT_ROUTE_IFNAMSIZ 16 + +struct ipt_route_target_info { -+ char ifname[IPT_ROUTE_IFNAMSIZ]; -+ unsigned int ipto; ++ char oif[IPT_ROUTE_IFNAMSIZ]; ++ char iif[IPT_ROUTE_IFNAMSIZ]; ++ unsigned int gw; +}; + +#endif /*_IPT_ROUTE_H_target*/ diff -Nru linux.orig/net/ipv4/netfilter/ipt_ROUTE.c linux/net/ipv4/netfilter/ipt_ROUTE.c --- linux.orig/net/ipv4/netfilter/ipt_ROUTE.c Thu Jan 1 01:00:00 1970 -+++ linux/net/ipv4/netfilter/ipt_ROUTE.c Fri Nov 22 14:53:06 2002 -@@ -0,0 +1,317 @@ ++++ linux/net/ipv4/netfilter/ipt_ROUTE.c Wed Dec 18 12:40:26 2002 +@@ -0,0 +1,365 @@ +/* -+ * This is a module which is used for directly sending a received packet to -+ * an interface or a host specified by the user. This target NEVER modifies -+ * packets but allows a different routing scheme than the one provided by -+ * the standard kernel routing table. -+ * -+ * Based on code from: ipt_MIRROR.c and various sources. ++ * 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 + * @@ -44,6 +41,7 @@ +#include +#include +#include ++#include +#include + +#if 0 @@ -58,7 +56,7 @@ + * - ifindex : + * 0 if no oif prefered, + * otherwise set to the index of the desired oif -+ * - route_info->ipto : ++ * - 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 @@ -76,24 +74,24 @@ +{ + int err; + struct rtable *rt; -+ struct iphdr *iph = skb->nh.iph; ++ struct iphdr *iph = skb->nh.iph; + struct rt_key key = { + dst:iph->daddr, + src:0, + oif:ifindex, + tos:RT_TOS(iph->tos) + }; -+ ++ + /* The destination address may be overloaded by the target */ -+ if (route_info->ipto) -+ key.dst = route_info->ipto; -+ ++ if (route_info->gw) ++ key.dst = route_info->gw; ++ + /* Trying to route the packet with the standard routing table. */ + if ((err = ip_route_output_key(&rt, &key))) { + DEBUGP("ipt_ROUTE: couldn't route pkt (err: %i)",err); + return -1; + } -+ ++ + /* Success if no oif specified or if the oif correspond to the + * one desired */ + if (!ifindex || rt->u.dst.dev->ifindex == ifindex) { @@ -103,7 +101,7 @@ + skb->dev = skb->dst->dev; + 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. This module makes it possible to @@ -111,7 +109,7 @@ + */ + DEBUGP("ipt_ROUTE: failed to route as desired (oif: %i)", + rt->u.dst.dev->ifindex); -+ ++ + return 0; +} + @@ -154,22 +152,120 @@ +} + + -+static unsigned int ipt_route_target(struct sk_buff **pskb, -+ unsigned int hooknum, -+ const struct net_device *in, -+ const struct net_device *out, -+ const void *targinfo, -+ void *userinfo) ++static unsigned int route_oif(const struct ipt_route_target_info *route_info, ++ struct sk_buff *skb) +{ -+ const struct ipt_route_target_info *route_info = targinfo; + struct net_device *dev_out = NULL; -+ struct sk_buff *skb = *pskb; + unsigned int ifindex = 0; + -+ if (!route_info->ipto && !route_info->ifname[0]) { -+ DEBUGP(KERN_DEBUG "ipt_ROUTE: missing argument!\n"); -+ return NF_ACCEPT; ++ /* 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 */ ++ return NF_DROP; ++ ++ DEBUGP(KERN_DEBUG "oif index of %s is %i\n", route_info->oif, ifindex); ++ ++ ++ /* Trying the standard way of routing packets */ ++ if (route(skb, ifindex, route_info)==1) { ++ DEBUGP(KERN_DEBUG "ROUTE oif ok, skb->dev->index=%i\n", ++ skb->dev->ifindex); ++ ++ dev_put(dev_out); ++ if (ip_direct_send(skb) == -EINVAL) ++ return NF_DROP; ++ else ++ return NF_STOLEN; ++ } ++ ++ /* Failed to send to oif. Trying the hard way */ ++ ++ DEBUGP(KERN_DEBUG "HARD ROUTING\n"); ++ ++ /* Drop old route. */ ++ dst_release(skb->dst); ++ skb->dst = NULL; ++ ++ /* 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)) { ++ 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; ++} ++ ++ ++static unsigned int route_iif(const struct ipt_route_target_info *route_info, ++ struct sk_buff *skb) ++{ ++ struct net_device *dev_out = NULL; ++ unsigned int ifindex = 0; ++ ++ /* Getting the current interface index. */ ++ if ((dev_out = dev_get_by_name(route_info->iif))) ++ ifindex = dev_out->ifindex; ++ else ++ /* Unknown interface name : packet dropped */ ++ return NF_DROP; ++ ++ DEBUGP(KERN_DEBUG "iif index of %s is %i\n", route_info->iif, ifindex); ++ ++ skb->dev = dev_out; ++ dst_release(skb->dst); ++ skb->dst = NULL; ++ ++ netif_rx(skb); ++ ++ 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; ++ ++ DEBUGP(KERN_DEBUG "ROUTE gw ok, skb->dev->index=%i\n", ++ skb->dev->ifindex); ++ ++ if (ip_direct_send(skb) == -EINVAL) ++ return NF_DROP; ++ ++ return NF_STOLEN; ++} ++ ++ ++static unsigned int ipt_route_target(struct sk_buff **pskb, ++ unsigned int hooknum, ++ const struct net_device *in, ++ const struct net_device *out, ++ const void *targinfo, ++ void *userinfo) ++{ ++ const struct ipt_route_target_info *route_info = targinfo; ++ struct sk_buff *skb = *pskb; + + /* raw socket (tcpdump) may have clone of incoming + * skb: don't disturb it @@ -225,74 +321,25 @@ + skb->nf_debug = 0; +#endif + -+ if (route_info->ifname[0]) { -+ /* The user set the interface name to use. -+ * Getting the current interface index. -+ */ -+ if ((dev_out = dev_get_by_name(route_info->ifname))) -+ ifindex = dev_out->ifindex; -+ else -+ /* Unknown interface name : packet dropped */ -+ return NF_DROP; -+ -+ } -+ -+ DEBUGP(KERN_DEBUG "Index of %s is %i\n", route_info->ifname, ifindex); -+ -+ /* Trying the standard way of routing packets */ -+ if (route(skb, ifindex, route_info)==1) { -+ DEBUGP(KERN_DEBUG "ROUTE ok, skb->dev->index=%i\n", -+ skb->dev->ifindex); -+ -+ if (dev_out) dev_put(dev_out); -+ if (ip_direct_send(skb) == -EINVAL) return NF_DROP; -+ return NF_STOLEN; -+ } -+ -+ if (!route_info->ifname[0]) { -+ if (dev_out) dev_put(dev_out); -+ return NF_DROP; -+ } -+ -+ /* Failed to correctly route. Trying the hard way */ -+ -+ DEBUGP(KERN_DEBUG "HARD ROUTING\n"); ++ if (route_info->oif[0]) ++ return route_oif(route_info, skb); ++ ++ if (route_info->iif[0]) ++ return route_iif(route_info, skb); + -+ /* Drop old route. */ -+ dst_release(skb->dst); -+ skb->dst = NULL; ++ if (route_info->gw) ++ return route_gw(route_info, skb); + -+ /* 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)) { -+ 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; ++ DEBUGP(KERN_DEBUG "ipt_ROUTE: no parameter !\n"); ++ return NF_ACCEPT; +} + + +static int ipt_route_checkentry(const char *tablename, -+ const struct ipt_entry *e, -+ void *targinfo, -+ unsigned int targinfosize, -+ unsigned int hook_mask) ++ const struct ipt_entry *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", @@ -301,8 +348,10 @@ + } + + if (hook_mask & ~( (1 << NF_IP_PRE_ROUTING) -+ | (1 << NF_IP_FORWARD) -+ | (1 << NF_IP_POST_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; + } diff -Nru netfilter.orig/patch-o-matic/extra/ROUTE.patch.configure.help netfilter/patch-o-matic/extra/ROUTE.patch.configure.help --- netfilter.orig/patch-o-matic/extra/ROUTE.patch.configure.help Thu Dec 5 21:44:38 2002 +++ netfilter/patch-o-matic/extra/ROUTE.patch.configure.help Wed Dec 18 12:19:19 2002 @@ -1,14 +1,18 @@ CONFIG_IP_NF_TARGET_LOG ROUTE target support CONFIG_IP_NF_TARGET_ROUTE - This option adds a `ROUTE' target, which allows you to directly route - a received packet through a specified interface or towards a host, even - if the regular destination of the packet is the router itself. - This target never modifies packets but allows a different routing scheme - than the one provided by the standard kernel routing table. + This option adds a `ROUTE' target, which enables you to setup unusual + routes not supported by the standard kernel routing table. + For example, the ROUTE lets you directly 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. + + This target does never modify the packet and is 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'. - diff -Nru netfilter.orig/patch-o-matic/extra/ROUTE.patch.help netfilter/patch-o-matic/extra/ROUTE.patch.help --- netfilter.orig/patch-o-matic/extra/ROUTE.patch.help Thu Dec 5 21:44:38 2002 +++ netfilter/patch-o-matic/extra/ROUTE.patch.help Wed Dec 18 12:51:37 2002 @@ -1,28 +1,32 @@ Author: Cédric de Launois Status: In Development/Works for me - This option adds a `ROUTE' target, which allows you to directly route - a received packet through a specified interface or towards a host, even - if the regular destination of the packet is the router itself. - This target never modifies packets but allows a different routing scheme - than the one provided by the standard kernel routing table. - - This target is to be used inside the mangle table, in the PREROUTING, - POSTROUTING or FORWARD hooks. + This option adds a `ROUTE' target, which enables you to setup unusual + routes not supported by the standard kernel routing table. + For example, the ROUTE lets you directly 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. + + This target does never modify the packet and is a final target. + It has to be used inside the mangle table. ROUTE target options: - --iface name Send the packet directly through this interface. - --to ip Route the packet as if its destination address was ip. + --oif ifname Send the packet out using `ifname' network interface. + --iif ifname Change the packet's incoming interface to `ifname'. + --gw ip Route the packet via this gateway. Examples : To redirect all outgoing icmp packet to the eth1 interface : - # iptables -A POSTROUTING -t mangle -p icmp -j ROUTE --iface eth1 + # iptables -A POSTROUTING -t mangle -p icmp -j ROUTE --oif eth1 - To tunnel all incoming http packets - # iptables -A PREROUTING -t mangle -p tcp --dport 80 -j ROUTE --iface tunl1 + To tunnel all incoming http packets : + # iptables -A PREROUTING -t mangle -p tcp --dport 80 -j ROUTE --oif tunl1 - To force the next-hop used for ssh packets - # iptables -A PREROUTING -t mangle -p tcp --dport 22 -j ROUTE --to w.x.y.z + To force the next-hop used for ssh packets : + # iptables -A PREROUTING -t mangle -p tcp --dport 22 -j ROUTE --gw w.x.y.z + To change the incoming network interface from eth0 to eth1 for icmp packets : + # iptables -A PREROUTING -t mangle -p icmp -i eth0 -j ROUTE --iif eth1 diff -Nru netfilter.orig/userspace/extensions/libipt_ROUTE.c netfilter/userspace/extensions/libipt_ROUTE.c --- netfilter.orig/userspace/extensions/libipt_ROUTE.c Thu Dec 5 21:44:38 2002 +++ netfilter/userspace/extensions/libipt_ROUTE.c Wed Dec 18 12:26:37 2002 @@ -20,15 +20,17 @@ { printf( "ROUTE target v%s options:\n" -" --iface name Send the packet directly through this interface.\n" -" --to ip Route the packet as if its destination address was ip.\n" +" --oif \tifname \t\tSend the packet out using `ifname' network interface\n" +" --iif \tifname \t\tChange the packet's incoming interface to `ifname'\n" +" --gw \tip \t\tRoute the packet via this gateway\n" "\n", IPTABLES_VERSION); } static struct option opts[] = { - { "iface", 1, 0, '1' }, - { "to", 1, 0, '2' }, + { "oif", 1, 0, '1' }, + { "iif", 1, 0, '2' }, + { "gw", 1, 0, '3' }, { 0 } }; @@ -39,12 +41,14 @@ struct ipt_route_target_info *route_info = (struct ipt_route_target_info*)t->data; - route_info->ifname[0] = '\0'; - route_info->ipto = 0; + route_info->oif[0] = '\0'; + route_info->iif[0] = '\0'; + route_info->gw = 0; } -#define IPT_ROUTE_OPT_IF 0x01 -#define IPT_ROUTE_OPT_TO 0x02 + +#define IPT_ROUTE_OPT_IF 0x01 +#define IPT_ROUTE_OPT_GW 0x02 /* Function which parses command options; returns true if it ate an option */ @@ -60,33 +64,51 @@ case '1': if (*flags & IPT_ROUTE_OPT_IF) exit_error(PARAMETER_PROBLEM, - "Can't specify --iface twice"); + "Can't specify --oif twice or --oif with --iif"); if (check_inverse(optarg, &invert, NULL, 0)) exit_error(PARAMETER_PROBLEM, - "Unexpected `!' after --iface"); + "Unexpected `!' after --oif"); - if (strlen(optarg) > sizeof(route_info->ifname) - 1) + if (strlen(optarg) > sizeof(route_info->oif) - 1) exit_error(PARAMETER_PROBLEM, "Maximum interface name length %u", - sizeof(route_info->ifname) - 1); + sizeof(route_info->oif) - 1); - strcpy(route_info->ifname, optarg); + strcpy(route_info->oif, optarg); *flags |= IPT_ROUTE_OPT_IF; break; case '2': - if (*flags & IPT_ROUTE_OPT_TO) + if (*flags & IPT_ROUTE_OPT_IF) + exit_error(PARAMETER_PROBLEM, + "Can't specify --iif twice or --iif with --oif"); + + if (check_inverse(optarg, &invert, NULL, 0)) + exit_error(PARAMETER_PROBLEM, + "Unexpected `!' after --iif"); + + if (strlen(optarg) > sizeof(route_info->iif) - 1) exit_error(PARAMETER_PROBLEM, - "Can't specify --to twice"); + "Maximum interface name length %u", + sizeof(route_info->iif) - 1); + + strcpy(route_info->iif, optarg); + *flags |= IPT_ROUTE_OPT_IF; + break; - if (!inet_aton(optarg, (struct in_addr*)&route_info->ipto)) { + case '3': + if (*flags & IPT_ROUTE_OPT_GW) + exit_error(PARAMETER_PROBLEM, + "Can't specify --gw twice"); + + if (!inet_aton(optarg, (struct in_addr*)&route_info->gw)) { exit_error(PARAMETER_PROBLEM, "Invalid IP address %s", optarg); } - *flags |= IPT_ROUTE_OPT_TO; + *flags |= IPT_ROUTE_OPT_GW; break; default: @@ -96,14 +118,16 @@ return 1; } + static void final_check(unsigned int flags) { if (!flags) exit_error(PARAMETER_PROBLEM, - "ROUTE target: minimum 1 parameter is required"); + "ROUTE target: one parameter is required"); } + /* Prints out the targinfo. */ static void print(const struct ipt_ip *ip, @@ -115,15 +139,38 @@ printf("ROUTE "); - if (route_info->ifname[0]) - printf("iface %s ", route_info->ifname); + if (route_info->oif[0]) + printf("oif %s ", route_info->oif); + + if (route_info->iif[0]) + printf("iif %s ", route_info->iif); - if (route_info->ipto) { - struct in_addr ip = { route_info->ipto }; - printf("to %s ", inet_ntoa(ip)); + if (route_info->gw) { + struct in_addr ip = { route_info->gw }; + printf("gw %s ", inet_ntoa(ip)); } } + +static void save(const struct ipt_ip *ip, + const struct ipt_entry_target *target) +{ + const struct ipt_route_target_info *route_info + = (const struct ipt_route_target_info *)target->data; + + if (route_info->oif[0]) + printf("--oif %s ", route_info->oif); + + if (route_info->iif[0]) + printf("--iif %s ", route_info->iif); + + if (route_info->gw) { + struct in_addr ip = { route_info->gw }; + printf("--gw %s ", inet_ntoa(ip)); + } +} + + static struct iptables_target route = { NULL, @@ -136,7 +183,7 @@ &parse, &final_check, &print, - NULL, /* save */ + &save, opts };