All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Cédric de Launois" <delaunoi@info.ucl.ac.be>
To: netfilter-devel@lists.samba.org
Subject: [PATCH] ROUTE target : bug fixes
Date: 20 Jun 2002 16:12:41 +0200	[thread overview]
Message-ID: <1024582362.2418.30.camel@descartes> (raw)

Hi,

Here is a patch for 'ROUTE' target :

1) The ipt_ROUTE.c code has been reworked. This patch fixes a bug
   in the previous version : a dev_put() was missing after the call 
   to dev_get_by_index().

2) libipt_ROUTE.c now allows the user to specify the name of an
   interface that currently does not exist, like for the -i and -o
   options.

3) The 'ROUTE.patch.help' and 'ROUTE.patch.configure.help' were
   slightly modified.

This patch is against the current (june 20th) cvs tree, so this patch
is to apply INSTEAD of the last ROUTE patch (june 17th, yet not applied
on the cvs).

Doing
   patch -p0 < ROUTE.cvs.patch
in the same directory as netfilter/ should apply the patch correctly.

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 <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 {
 +	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 <delaunois@info.ucl.ac.be>
 + *
-+ * 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 <delaunois@info.ucl.ac.be>
 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
+
 
  

             reply	other threads:[~2002-06-20 14:12 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-06-20 14:12 Cédric de Launois [this message]
2002-06-21 17:15 ` [PATCH] ROUTE target : bug fixes Harald Welte
2002-06-21 17:56   ` MIME Patches (was [PATCH] ROUTE target : bug fixes) Ben Reser
2002-06-22 16:41     ` Harald Welte
2002-06-24  7:43   ` [PATCH] ROUTE target : bug fixes MIME format Cédric de Launois
2002-06-24 10:20     ` Harald Welte

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1024582362.2418.30.camel@descartes \
    --to=delaunoi@info.ucl.ac.be \
    --cc=netfilter-devel@lists.samba.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.