le ven 21-06-2002 à 19:15, Harald Welte a écrit : > On Thu, Jun 20, 2002 at 04:12:41PM +0200, Cédric de Launois wrote: > > Hi, > > > > Here is a patch for 'ROUTE' target : > > thanks. I'd love to apply your patch, but since you have not attached > but inlined it, your mail program has wrapped the lines and thus corrupted > the patch. Please resend it. > > Please try to send patches as mime attachment to ensure no corruption > occurs.
Ok, at least, that made it possible to highlight a small problem of consistency in your rules ;) So here's the same patch in MIME format. Cédric de Launois
diff -Nru netfilter.orig/userspace/extensions/libipt_ROUTE.c netfilter/userspace/extensions/libipt_ROUTE.c --- netfilter.orig/userspace/extensions/libipt_ROUTE.c Thu Jun 13 18:12:01 2002 +++ netfilter/userspace/extensions/libipt_ROUTE.c Thu Jun 20 12:18:46 2002 @@ -6,11 +6,10 @@ #include <string.h> #include <stdlib.h> #include <getopt.h> - #include <iptables.h> +#include <net/if.h> #include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ipt_ROUTE.h> -#include <net/if.h> /* Function which prints out usage message. */ static void @@ -21,7 +20,7 @@ " --iface name Send this packet directly through iface name.\n" " --ifindex index Send this packet directly through iface index.\n" "\n", -NETFILTER_VERSION); +IPTABLES_VERSION); } static struct option opts[] = { @@ -48,8 +47,6 @@ struct ipt_route_target_info *route_info = (struct ipt_route_target_info*)(*target)->data; - unsigned int if_index; - switch (c) { char *end; case '1': @@ -57,15 +54,17 @@ exit_error(PARAMETER_PROBLEM, "Can't specify --iface or --ifindex twice"); - if (check_inverse(optarg, &invert)) + if (check_inverse(optarg, &invert, NULL, 0)) exit_error(PARAMETER_PROBLEM, "Unexpected `!' after --iface"); - if ((if_index = if_nametoindex(optarg))==0) + if (strlen(optarg) > sizeof(route_info->if_name) - 1) exit_error(PARAMETER_PROBLEM, - "Unknown interface name %s", optarg); + "Maximum interface name length %u", + sizeof(route_info->if_name) - 1); - route_info->if_index = if_index; + strcpy(route_info->if_name, optarg); + route_info->if_index = 0; *flags |= IPT_ROUTE_OPT_IF; break; @@ -74,14 +73,19 @@ exit_error(PARAMETER_PROBLEM, "Can't specify --iface or --ifindex twice"); - if (check_inverse(optarg, &invert)) + if (check_inverse(optarg, &invert, NULL, 0)) exit_error(PARAMETER_PROBLEM, "Unexpected `!' after --ifindex"); + route_info->if_name[0] = 0; route_info->if_index = strtoul(optarg, &end, 0); - if (*end != '\0' || end == optarg) - exit_error(PARAMETER_PROBLEM, "Bad ROUTE ifindex `%s'", optarg); + exit_error(PARAMETER_PROBLEM, "Bad ROUTE ifindex `%s'", + optarg); + + if (route_info->if_index == 0) + exit_error(PARAMETER_PROBLEM, + "Interface index can't be 0 !"); *flags |= IPT_ROUTE_OPT_IF; break; @@ -112,19 +116,17 @@ printf("ROUTE "); - if (route_info->if_index != 0) { - char buf[IF_NAMESIZE]; - printf("iface %s(%d) ", - if_indextoname(route_info->if_index, buf), - route_info->if_index); - } + if (route_info->if_name[0] != 0) + printf("iface %s ", route_info->if_name); + else + printf("ifindex %u ", route_info->if_index); } static struct iptables_target route = { NULL, "ROUTE", - NETFILTER_VERSION, + IPTABLES_VERSION, IPT_ALIGN(sizeof(struct ipt_route_target_info)), IPT_ALIGN(sizeof(struct ipt_route_target_info)), &help, diff -Nru netfilter.orig/userspace/patch-o-matic/extra/ROUTE.patch netfilter/userspace/patch-o-matic/extra/ROUTE.patch --- netfilter.orig/userspace/patch-o-matic/extra/ROUTE.patch Thu Jun 13 18:12:01 2002 +++ netfilter/userspace/patch-o-matic/extra/ROUTE.patch Thu Jun 20 15:29:27 2002 @@ -1,54 +1,41 @@ -diff -Nru linux/include/linux/netfilter_ipv4/ipt_ROUTE.h linux-new/include/linux/netfilter_ipv4/ipt_ROUTE.h ---- linux/include/linux/netfilter_ipv4/ipt_ROUTE.h Thu Jan 1 01:00:00 1970 -+++ linux-new/include/linux/netfilter_ipv4/ipt_ROUTE.h Mon Jun 10 09:21:41 2002 -@@ -0,0 +1,8 @@ +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 Jun 20 11:18:09 2002 +@@ -0,0 +1,17 @@ ++/* Header file for iptables ipt_ROUTE target ++ * ++ * (C) 2002 by Cédric de Launois <[EMAIL PROTECTED]> ++ * ++ * 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 { + unsigned int if_index; ++ char if_name[IPT_ROUTE_IFNAMSIZ]; +}; + +#endif /*_IPT_ROUTE_H_target*/ -diff -Nru linux/net/ipv4/netfilter/ipt_ROUTE.c linux-new/net/ipv4/netfilter/ipt_ROUTE.c ---- linux/net/ipv4/netfilter/ipt_ROUTE.c Thu Jan 1 01:00:00 1970 -+++ linux-new/net/ipv4/netfilter/ipt_ROUTE.c Mon Jun 10 10:41:30 2002 -@@ -0,0 +1,247 @@ +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 Thu Jun 20 14:22:59 2002 +@@ -0,0 +1,267 @@ +/* -+ * This is a module which is used for rerouting packets without modifying them. -+ * This module is particularly useful when the dst IP is one of our own IP -+ * addresses. Packet with those addresses are locally delivered and -+ * cannot be forwarded using the standard routing mechanisms. -+ * -+ * This module can reroute packets to the interface selected by the user. -+ * Example : -+ * -+ * iptables -A PREROUTING -i eth0 -p tcp --dport 8000:8200 -j ROUTE --iface eth1 -+ * -+ * i.e. the module reroute tcp packets coming from eth0 with dsp port 8000-8200 -+ * towards iface eth1. -+ * -+ * The rerouting is used by i.e. RSIP protocol when RSAP-IP method is -+ * selected. -+ * ++ * This is a module which is used for directly resending a received packet to ++ * an interface specified by the user. ++ * This module is particularly useful when the destination IP address is an ++ * address owned by the router itself. Packets with such addresses are locally ++ * delivered by the kernel and cannot be forwarded using the standard routing ++ * mechanisms. ++ + * Based on code from: ipt_MIRROR.c and various sources. + * + * Copyright (C) 2002 Cedric de Launois <[EMAIL PROTECTED]> + * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software Foundation, -+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA -+ * ++ * This software is distributed under GNU GPL v2, 1991 + */ + +#include <linux/module.h> @@ -61,20 +48,28 @@ +#include <net/ip.h> +#include <net/icmp.h> + ++#if 0 ++#define DEBUGP printk ++#else ++#define DEBUGP(format, args...) ++#endif ++ + +/* PRE : skb is the packet and ifindex is the interface index through which + * the packet should be rerouted -+ * POST: skb->dev is the output device towards which the packet is rerouted -+ * returns 0 if the packet could not be rerouted -+ * returns 1 and skb->dst is not NULL if a regular route has been found -+ * in the routing table -+ * returns 2 and skb->dst is NULL otherwise ++ * POST: if success, skb->dev is the output device with index 'ifindex' ++ * to which the packet must be sent and skb->dst is not NULL ++ * RETURN: -1 if an error occured ++ * 1 if the packet has been succesfully rerouted to the device with ++ * index 'ifindex', using the kernel routing table ++ * 0 if the kernel routing table didn't yield the requested ++ * interface + */ +static int route(struct sk_buff *skb, unsigned int ifindex) +{ + int err; -+ struct iphdr *iph = skb->nh.iph; + struct rtable *rt; ++ struct iphdr *iph = skb->nh.iph; + struct rt_key key = { + dst:iph->daddr, + src:0, @@ -82,23 +77,14 @@ + tos:RT_TOS(iph->tos) + }; + -+ nf_conntrack_put(skb->nfct); -+ skb->nfct = NULL; -+ + /* Trying to route the packet with the standard routing table. */ + if ((err = ip_route_output_key(&rt, &key))) { -+ printk("ipt_ROUTE couldn't route pkt (err: %i)",err); -+ return 0; -+ } -+ -+ /* Drop old device. */ -+ if (skb->dev) { -+ dev_put(skb->dev); -+ skb->dev = NULL; ++ DEBUGP("ipt_ROUTE: couldn't route pkt (err: %i)",err); ++ return -1; + } + + /* Check if the interface we are leaving by is the same as the -+ * one we requested. ++ * one we requested. + */ + if (rt->u.dst.dev->ifindex == ifindex) { + /* Drop old route. */ @@ -107,54 +93,51 @@ + 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 + * reroute such packets by forcing the device to use. -+ * This is useful i.e. to the RSIP protocol (RFC3102). + */ -+ if ((skb->dev = dev_get_by_index(ifindex)) != NULL) { -+ /* Drop old route. */ -+ dst_release(skb->dst); -+ skb->dst = NULL; -+ return 2; -+ } -+ + return 0; +} + + -+/* PRE : skb->dev is set to the device we are leaving by -+ * POST: - if skb->dst is not NULL, then the packet is sent with the -+ * link layer header pushed -+ * - if skb->dst is NULL, then the packet is directly sent to -+ * the skb->dev device, without pushing the link layer header. -+ * This should be only used for tunnel interfaces, for which -+ * link layer headers are automatically generated. ++/* 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 + */ -+static void ip_direct_send(struct sk_buff *skb) ++static inline int ip_direct_send(struct sk_buff *skb) +{ + struct dst_entry *dst = skb->dst; + struct hh_cache *hh; + -+ if (!dst) { -+ dev_queue_xmit(skb); -+ return; -+ } -+ + 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); ++ return hh->hh_output(skb); + } else if (dst->neighbour) -+ dst->neighbour->output(skb); -+ else { -+ printk(KERN_DEBUG "khm in MIRROR\n"); -+ kfree_skb(skb); -+ } ++ return dst->neighbour->output(skb); ++ ++ if (net_ratelimit()) ++ DEBUGP(KERN_DEBUG "ipt_ROUTE: no hdr & no neighbour cache!\n"); ++ kfree_skb(skb); ++ return -EINVAL; ++} ++ ++ ++/* 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. ++ * - skb has been freed !! ++ */ ++static inline int dev_direct_send(struct sk_buff *skb) ++{ ++ return dev_queue_xmit(skb); +} + + @@ -166,17 +149,26 @@ + void *userinfo) +{ + const struct ipt_route_target_info *route_info = targinfo; ++ struct net_device *dev_out = NULL; ++ struct sk_buff *skb = *pskb; ++ unsigned int index = 0; + -+ printk("RCV from IN=%s OUT=%s PROTO=%u \n", -+ in ? in->name : "", -+ out ? out->name : "", -+ (*pskb)->protocol); ++ /* raw socket (tcpdump) may have clone of incoming ++ * skb: don't disturb it ++ */ ++ if (skb_cloned(skb) && !skb->sk) { ++ struct sk_buff *nskb = skb_copy(skb, GFP_ATOMIC); ++ if (!nskb) ++ return NF_DROP; ++ kfree_skb(skb); ++ skb = nskb; ++ } + + /* If we are not at FORWARD hook + * the TTL isn't decreased by the IP stack + */ + if (hooknum != NF_IP_FORWARD) { -+ struct iphdr *iph = (*pskb)->nh.iph; ++ struct iphdr *iph = skb->nh.iph; + + if (iph->ttl <= 1) { + struct rtable *rt; @@ -187,14 +179,14 @@ + return NF_DROP; + } + -+ if ((*pskb)->dev == rt->u.dst.dev) { ++ if (skb->dev == rt->u.dst.dev) { + /* Drop old route. */ -+ dst_release((*pskb)->dst); -+ (*pskb)->dst = &rt->u.dst; ++ dst_release(skb->dst); ++ skb->dst = &rt->u.dst; + + /* this will traverse normal stack, and + * thus call conntrack on the icmp packet */ -+ icmp_send(*pskb, ICMP_TIME_EXCEEDED, ++ icmp_send(skb, ICMP_TIME_EXCEEDED, + ICMP_EXC_TTL, 0); + } + @@ -204,14 +196,52 @@ + ip_decrease_ttl(iph); + } + ++ /* This packet will not be the same as before: clear nf fields */ ++ nf_conntrack_put(skb->nfct); ++ skb->nfct = NULL; ++ skb->nfcache = 0; ++#ifdef CONFIG_NETFILTER_DEBUG ++ skb->nf_debug = 0; ++#endif ++ ++ /* Getting the actual interface index */ ++ if ((index = route_info->if_index) == 0) { ++ /* The user specified a ifname, not a ifindex */ ++ if ((dev_out = dev_get_by_name(route_info->if_name))) ++ index = dev_out->ifindex; ++ else return NF_DROP; ++ } ++ ++ /* Trying the standard way */ ++ if (route(skb, index)==1) { ++ if (dev_out) dev_put(dev_out); ++ if (ip_direct_send(skb) == -EINVAL) return NF_DROP; ++ return NF_STOLEN; ++ } ++ ++ /* Failed to correctly route. Trying the hard way */ ++ if (!dev_out) dev_out = dev_get_by_index(index); + -+ if (route(*pskb, route_info->if_index)) { ++ if (dev_out) { + -+ ip_direct_send(*pskb); ++ /* Drop old route. */ ++ dst_release(skb->dst); ++ skb->dst = NULL; ++ ++ /* 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("ipt_ROUTE: Couldn't route the packet!\n"); ++ + return NF_DROP; +} + @@ -222,14 +252,13 @@ + unsigned int targinfosize, + unsigned int hook_mask) +{ -+ /* Only working on PRE_ROUTING */ + if (hook_mask & ~(1 << NF_IP_PRE_ROUTING)) { -+ printk("ROUTE: bad hook\n"); ++ printk("ipt_ROUTE: bad hook\n"); + return 0; + } + + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_route_target_info))) { -+ printk(KERN_WARNING "ROUTE: targinfosize %u != %Zu\n", ++ DEBUGP(KERN_WARNING "ipt_ROUTE: targinfosize %u != %Zu\n", + targinfosize, + IPT_ALIGN(sizeof(struct ipt_route_target_info))); + return 0; diff -Nru netfilter.orig/userspace/patch-o-matic/extra/ROUTE.patch.configure.help netfilter/userspace/patch-o-matic/extra/ROUTE.patch.configure.help --- netfilter.orig/userspace/patch-o-matic/extra/ROUTE.patch.configure.help Thu Jun 13 18:12:01 2002 +++ netfilter/userspace/patch-o-matic/extra/ROUTE.patch.configure.help Thu Jun 20 12:33:54 2002 @@ -7,10 +7,8 @@ are locally delivered and cannot be forwarded to another computer using the standard routing mechanisms. - This target is particularly useful if you intend to use RSIP protocol - (RFC3102, RFC3103). - If you want to compile it as a module, say M here and read - Documentation/modules.txt. If unsure, say `N'. + Documentation/modules.txt. The module will be called ipt_ROUTE.o. + If unsure, say `N'. diff -Nru netfilter.orig/userspace/patch-o-matic/extra/ROUTE.patch.help netfilter/userspace/patch-o-matic/extra/ROUTE.patch.help --- netfilter.orig/userspace/patch-o-matic/extra/ROUTE.patch.help Thu Jun 13 18:12:01 2002 +++ netfilter/userspace/patch-o-matic/extra/ROUTE.patch.help Thu Jun 20 12:43:22 2002 @@ -1,13 +1,25 @@ Author: Cédric de Launois <[EMAIL PROTECTED]> Status: In Development/Works for me - This option adds a `ROUTE' target, which allows you to directly route + This option adds a `ROUTE' target, which allows you to directly resend a received packet through a specified interface, even and especially if the packet IP address is one of the router itself. Those packets are locally delivered and cannot be forwarded to another computer using the standard routing mechanisms. - This target is particularly useful if you intend to use RSIP protocol - (RFC3102, RFC3103). + ROUTE target v1.2.7 options: + --iface name Send the packet directly through iface name. + --ifindex index Send the packet directly through iface index. + + Example : + You want to install a ssh server on a computer inside your network but + you also want it to appear exactly as if it was located on the router. + A solution is to simply reroute packets with destination port 22 to the + computer having the same IP as the router and hosting the ssh service, + thanks to this ROUTE target and an ipip tunnel. + + # iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 22 -j ROUTE --iface tunl1 + # iptables -A PREROUTING -t nat -i tunl1 --j ROUTE --iface eth0 +