All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] ROUTE target : update to pom-ng + new version for kernel 2.6.x
@ 2004-04-21  8:16 Cedric de Launois
  2004-04-24 23:03 ` Patrick McHardy
  0 siblings, 1 reply; 6+ messages in thread
From: Cedric de Launois @ 2004-04-21  8:16 UTC (permalink / raw)
  To: Netfilter Development Mailinglist

[-- Attachment #1: Type: text/plain, Size: 252 bytes --]

Hi,

Here is a patch to convert the ROUTE target to the new pom-ng.
This patch also contains a corrected version of the ROUTE target
for kernels 2.6.x.

Other fixes for the ROUTE target will follow.

The patch is against the current cvs tree.

Cedric


[-- Attachment #2: ROUTE.pom-ng.patch --]
[-- Type: text/x-patch, Size: 64672 bytes --]

diff -Nru ROUTE.orig/info ROUTE/info
--- ROUTE.orig/info	2004-02-20 00:11:50.000000000 +0100
+++ ROUTE/info	2004-03-08 14:19:22.000000000 +0100
@@ -1,4 +1,5 @@
 Author: Cédric de Launois <delaunois@info.ucl.ac.be>
 Status: Experimental
 Repository: extra
-Requires: linux < 2.6.0
+Recompile: netfilter
+Recompile: iptables
diff -Nru ROUTE.orig/linux/Documentation/Configure.help.ladd ROUTE/linux/Documentation/Configure.help.ladd
--- ROUTE.orig/linux/Documentation/Configure.help.ladd	2004-02-19 12:30:08.000000000 +0100
+++ ROUTE/linux/Documentation/Configure.help.ladd	1970-01-01 01:00:00.000000000 +0100
@@ -1,16 +0,0 @@
-CONFIG_IP_NF_TARGET_MARK
-ROUTE target support
-CONFIG_IP_NF_TARGET_ROUTE
-  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'.
-
diff -Nru ROUTE.orig/linux/Documentation/Configure.help.ladd_2 ROUTE/linux/Documentation/Configure.help.ladd_2
--- ROUTE.orig/linux/Documentation/Configure.help.ladd_2	2004-03-05 10:30:26.000000000 +0100
+++ ROUTE/linux/Documentation/Configure.help.ladd_2	1970-01-01 01:00:00.000000000 +0100
@@ -1,12 +0,0 @@
-CONFIG_IP6_NF_TARGET_MARK
-ROUTE target support
-CONFIG_IP6_NF_TARGET_ROUTE
-  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.
-
diff -Nru ROUTE.orig/linux/include/linux/netfilter_ipv4/ipt_ROUTE.h ROUTE/linux/include/linux/netfilter_ipv4/ipt_ROUTE.h
--- ROUTE.orig/linux/include/linux/netfilter_ipv4/ipt_ROUTE.h	2003-12-18 19:47:54.000000000 +0100
+++ ROUTE/linux/include/linux/netfilter_ipv4/ipt_ROUTE.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,22 +0,0 @@
-/* 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
-
-#endif /*_IPT_ROUTE_H_target*/
diff -Nru ROUTE.orig/linux/include/linux/netfilter_ipv6/ip6t_ROUTE.h ROUTE/linux/include/linux/netfilter_ipv6/ip6t_ROUTE.h
--- ROUTE.orig/linux/include/linux/netfilter_ipv6/ip6t_ROUTE.h	2003-12-20 17:43:09.000000000 +0100
+++ ROUTE/linux/include/linux/netfilter_ipv6/ip6t_ROUTE.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,22 +0,0 @@
-/* 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
-
-#endif /*_IP6T_ROUTE_H_target*/
diff -Nru ROUTE.orig/linux/net/ipv4/netfilter/Config.in.ladd ROUTE/linux/net/ipv4/netfilter/Config.in.ladd
--- ROUTE.orig/linux/net/ipv4/netfilter/Config.in.ladd	2003-12-18 19:47:54.000000000 +0100
+++ ROUTE/linux/net/ipv4/netfilter/Config.in.ladd	1970-01-01 01:00:00.000000000 +0100
@@ -1,3 +0,0 @@
-    dep_tristate '    MARK target support' CONFIG_IP_NF_TARGET_MARK $CONFIG_IP_NF_MANGLE
-    dep_tristate '    ROUTE target support' CONFIG_IP_NF_TARGET_ROUTE $CONFIG_IP_NF_MANGLE
- 
\ Pas de fin de ligne à la fin du fichier.
diff -Nru ROUTE.orig/linux/net/ipv4/netfilter/ipt_ROUTE.c ROUTE/linux/net/ipv4/netfilter/ipt_ROUTE.c
--- ROUTE.orig/linux/net/ipv4/netfilter/ipt_ROUTE.c	2003-12-18 19:47:54.000000000 +0100
+++ ROUTE/linux/net/ipv4/netfilter/ipt_ROUTE.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,369 +0,0 @@
-/*
- * 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.8 2003/07/25
- *
- * 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/ipt_ROUTE.h>
-#include <linux/netdevice.h>
-#include <linux/route.h>
-#include <net/ip.h>
-#include <net/route.h>
-#include <net/icmp.h>
-
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
-
-/* 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 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->gw)
-		key.dst = route_info->gw;
-	
-	/* Trying to route the packet using the standard routing table. */
-	if ((err = ip_route_output_key(&rt, &key))) {
-		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;
-		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;
-
-	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 "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_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 */
-		if (net_ratelimit()) 
-			DEBUGP("ipt_ROUTE: iif interface %s not found\n", route_info->oif);
-		return NF_DROP;
-	}
-
-	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;
-
-	if (route_info->flags & IPT_ROUTE_CONTINUE)
-		return IPT_CONTINUE;
-
-	ip_direct_send(skb);
-	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;
-
-	/* 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;
-
-			if (ip_route_output(&rt, iph->saddr, iph->daddr,
-					    RT_TOS(iph->tos) | RTO_CONN,
-					    0)) {
-				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;
-		}
-
-		ip_decrease_ttl(iph);
-	}
-
-	/* 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.
-	 */
-	if (!(route_info->flags & IPT_ROUTE_CONTINUE)) {
-		nf_conntrack_put(skb->nfct);
-		skb->nfct = NULL;
-		skb->nfcache = 0;
-#ifdef CONFIG_NETFILTER_DEBUG
-		skb->nf_debug = 0;
-#endif
-	}
-
-	if (route_info->oif[0]) 
-		return route_oif(route_info, *pskb);
-	
-	if (route_info->iif[0]) 
-		return route_iif(route_info, *pskb);
-
-	if (route_info->gw) 
-		return route_gw(route_info, *pskb);
-
-	if (net_ratelimit()) 
-		DEBUGP(KERN_DEBUG "ipt_ROUTE: no parameter !\n");
-
-	return IPT_CONTINUE;
-}
-
-
-static int ipt_route_checkentry(const char *tablename,
-				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",
-		       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
-= { { NULL, NULL }, "ROUTE", ipt_route_target, ipt_route_checkentry, NULL,
-    THIS_MODULE };
-
-
-static int __init init(void)
-{
-	if (ipt_register_target(&ipt_route_reg))
-		return -EINVAL;
-
-	return 0;
-}
-
-
-static void __exit fini(void)
-{
-	ipt_unregister_target(&ipt_route_reg);
-}
-
-module_init(init);
-module_exit(fini);
-MODULE_LICENSE("GPL");
diff -Nru ROUTE.orig/linux/net/ipv4/netfilter/Kconfig.ladd ROUTE/linux/net/ipv4/netfilter/Kconfig.ladd
--- ROUTE.orig/linux/net/ipv4/netfilter/Kconfig.ladd	2003-12-21 21:09:27.000000000 +0100
+++ ROUTE/linux/net/ipv4/netfilter/Kconfig.ladd	1970-01-01 01:00:00.000000000 +0100
@@ -1,3 +0,0 @@
-config IP_NF_TARGET_ROUTE
-	tristate  'ROUTE target support'
-	depends on IP_NF_MANGLE
diff -Nru ROUTE.orig/linux/net/ipv4/netfilter/Makefile.ladd ROUTE/linux/net/ipv4/netfilter/Makefile.ladd
--- ROUTE.orig/linux/net/ipv4/netfilter/Makefile.ladd	2003-12-18 19:47:54.000000000 +0100
+++ ROUTE/linux/net/ipv4/netfilter/Makefile.ladd	1970-01-01 01:00:00.000000000 +0100
@@ -1,2 +0,0 @@
-obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
-obj-$(CONFIG_IP_NF_TARGET_ROUTE) += ipt_ROUTE.o
diff -Nru ROUTE.orig/linux/net/ipv6/netfilter/Config.in.ladd ROUTE/linux/net/ipv6/netfilter/Config.in.ladd
--- ROUTE.orig/linux/net/ipv6/netfilter/Config.in.ladd	2003-12-20 17:43:09.000000000 +0100
+++ ROUTE/linux/net/ipv6/netfilter/Config.in.ladd	1970-01-01 01:00:00.000000000 +0100
@@ -1,2 +0,0 @@
-    dep_tristate '    MARK target support' CONFIG_IP6_NF_TARGET_MARK $CONFIG_IP6_NF_MANGLE
-    dep_mbool '    ROUTE target support' CONFIG_IP6_NF_TARGET_ROUTE $CONFIG_IP6_NF_MANGLE
\ Pas de fin de ligne à la fin du fichier.
diff -Nru ROUTE.orig/linux/net/ipv6/netfilter/ip6t_ROUTE.c ROUTE/linux/net/ipv6/netfilter/ip6t_ROUTE.c
--- ROUTE.orig/linux/net/ipv6/netfilter/ip6t_ROUTE.c	2003-12-20 17:43:09.000000000 +0100
+++ ROUTE/linux/net/ipv6/netfilter/ip6t_ROUTE.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,289 +0,0 @@
-/*
- * 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.0 2003/08/05
- *
- * 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,
-		  unsigned int hooknum,
-		  const struct net_device *in,
-		  const struct net_device *out,
-		  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;
-
-	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--;
-	}
-
-
- do_it:
-	if (route_info->oif[0]) 
-		return route6_oif(route_info, *pskb);
-	
-	if (!ipv6_addr_any(gw))
-		return route6_gw(route_info, *pskb);
-
-	if (net_ratelimit()) 
-		DEBUGP(KERN_DEBUG "ip6t_ROUTE: no parameter !\n");
-
-	return IP6T_CONTINUE;
-}
-
-
-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 -Nru ROUTE.orig/linux/net/ipv6/netfilter/Kconfig.ladd ROUTE/linux/net/ipv6/netfilter/Kconfig.ladd
--- ROUTE.orig/linux/net/ipv6/netfilter/Kconfig.ladd	2003-12-23 12:41:11.000000000 +0100
+++ ROUTE/linux/net/ipv6/netfilter/Kconfig.ladd	1970-01-01 01:00:00.000000000 +0100
@@ -1,3 +0,0 @@
-config IP6_NF_TARGET_ROUTE
-	tristate '    ROUTE target support'
-	depends on IP6_NF_MANGLE
diff -Nru ROUTE.orig/linux/net/ipv6/netfilter/Makefile.ladd ROUTE/linux/net/ipv6/netfilter/Makefile.ladd
--- ROUTE.orig/linux/net/ipv6/netfilter/Makefile.ladd	2003-12-20 17:43:09.000000000 +0100
+++ ROUTE/linux/net/ipv6/netfilter/Makefile.ladd	1970-01-01 01:00:00.000000000 +0100
@@ -1,2 +0,0 @@
-obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
-obj-$(CONFIG_IP6_NF_TARGET_ROUTE) += ip6t_ROUTE.o
diff -Nru ROUTE.orig/linux-2.4/Documentation/Configure.help.ladd ROUTE/linux-2.4/Documentation/Configure.help.ladd
--- ROUTE.orig/linux-2.4/Documentation/Configure.help.ladd	1970-01-01 01:00:00.000000000 +0100
+++ ROUTE/linux-2.4/Documentation/Configure.help.ladd	2004-02-19 12:30:08.000000000 +0100
@@ -0,0 +1,16 @@
+CONFIG_IP_NF_TARGET_MARK
+ROUTE target support
+CONFIG_IP_NF_TARGET_ROUTE
+  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'.
+
diff -Nru ROUTE.orig/linux-2.4/Documentation/Configure.help.ladd_2 ROUTE/linux-2.4/Documentation/Configure.help.ladd_2
--- ROUTE.orig/linux-2.4/Documentation/Configure.help.ladd_2	1970-01-01 01:00:00.000000000 +0100
+++ ROUTE/linux-2.4/Documentation/Configure.help.ladd_2	2004-03-05 10:30:26.000000000 +0100
@@ -0,0 +1,12 @@
+CONFIG_IP6_NF_TARGET_MARK
+ROUTE target support
+CONFIG_IP6_NF_TARGET_ROUTE
+  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.
+
diff -Nru ROUTE.orig/linux-2.4/include/linux/netfilter_ipv4/ipt_ROUTE.h ROUTE/linux-2.4/include/linux/netfilter_ipv4/ipt_ROUTE.h
--- ROUTE.orig/linux-2.4/include/linux/netfilter_ipv4/ipt_ROUTE.h	1970-01-01 01:00:00.000000000 +0100
+++ ROUTE/linux-2.4/include/linux/netfilter_ipv4/ipt_ROUTE.h	2003-12-18 19:47:54.000000000 +0100
@@ -0,0 +1,22 @@
+/* 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
+
+#endif /*_IPT_ROUTE_H_target*/
diff -Nru ROUTE.orig/linux-2.4/include/linux/netfilter_ipv6/ip6t_ROUTE.h ROUTE/linux-2.4/include/linux/netfilter_ipv6/ip6t_ROUTE.h
--- ROUTE.orig/linux-2.4/include/linux/netfilter_ipv6/ip6t_ROUTE.h	1970-01-01 01:00:00.000000000 +0100
+++ ROUTE/linux-2.4/include/linux/netfilter_ipv6/ip6t_ROUTE.h	2003-12-20 17:43:09.000000000 +0100
@@ -0,0 +1,22 @@
+/* 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
+
+#endif /*_IP6T_ROUTE_H_target*/
diff -Nru ROUTE.orig/linux-2.4/net/ipv4/netfilter/Config.in.ladd ROUTE/linux-2.4/net/ipv4/netfilter/Config.in.ladd
--- ROUTE.orig/linux-2.4/net/ipv4/netfilter/Config.in.ladd	1970-01-01 01:00:00.000000000 +0100
+++ ROUTE/linux-2.4/net/ipv4/netfilter/Config.in.ladd	2003-12-18 19:47:54.000000000 +0100
@@ -0,0 +1,3 @@
+    dep_tristate '    MARK target support' CONFIG_IP_NF_TARGET_MARK $CONFIG_IP_NF_MANGLE
+    dep_tristate '    ROUTE target support' CONFIG_IP_NF_TARGET_ROUTE $CONFIG_IP_NF_MANGLE
+ 
\ Pas de fin de ligne à la fin du fichier.
diff -Nru ROUTE.orig/linux-2.4/net/ipv4/netfilter/ipt_ROUTE.c ROUTE/linux-2.4/net/ipv4/netfilter/ipt_ROUTE.c
--- ROUTE.orig/linux-2.4/net/ipv4/netfilter/ipt_ROUTE.c	1970-01-01 01:00:00.000000000 +0100
+++ ROUTE/linux-2.4/net/ipv4/netfilter/ipt_ROUTE.c	2003-12-18 19:47:54.000000000 +0100
@@ -0,0 +1,369 @@
+/*
+ * 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.8 2003/07/25
+ *
+ * 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/ipt_ROUTE.h>
+#include <linux/netdevice.h>
+#include <linux/route.h>
+#include <net/ip.h>
+#include <net/route.h>
+#include <net/icmp.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+
+/* 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 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->gw)
+		key.dst = route_info->gw;
+	
+	/* Trying to route the packet using the standard routing table. */
+	if ((err = ip_route_output_key(&rt, &key))) {
+		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;
+		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;
+
+	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 "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_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 */
+		if (net_ratelimit()) 
+			DEBUGP("ipt_ROUTE: iif interface %s not found\n", route_info->oif);
+		return NF_DROP;
+	}
+
+	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;
+
+	if (route_info->flags & IPT_ROUTE_CONTINUE)
+		return IPT_CONTINUE;
+
+	ip_direct_send(skb);
+	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;
+
+	/* 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;
+
+			if (ip_route_output(&rt, iph->saddr, iph->daddr,
+					    RT_TOS(iph->tos) | RTO_CONN,
+					    0)) {
+				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;
+		}
+
+		ip_decrease_ttl(iph);
+	}
+
+	/* 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.
+	 */
+	if (!(route_info->flags & IPT_ROUTE_CONTINUE)) {
+		nf_conntrack_put(skb->nfct);
+		skb->nfct = NULL;
+		skb->nfcache = 0;
+#ifdef CONFIG_NETFILTER_DEBUG
+		skb->nf_debug = 0;
+#endif
+	}
+
+	if (route_info->oif[0]) 
+		return route_oif(route_info, *pskb);
+	
+	if (route_info->iif[0]) 
+		return route_iif(route_info, *pskb);
+
+	if (route_info->gw) 
+		return route_gw(route_info, *pskb);
+
+	if (net_ratelimit()) 
+		DEBUGP(KERN_DEBUG "ipt_ROUTE: no parameter !\n");
+
+	return IPT_CONTINUE;
+}
+
+
+static int ipt_route_checkentry(const char *tablename,
+				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",
+		       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
+= { { NULL, NULL }, "ROUTE", ipt_route_target, ipt_route_checkentry, NULL,
+    THIS_MODULE };
+
+
+static int __init init(void)
+{
+	if (ipt_register_target(&ipt_route_reg))
+		return -EINVAL;
+
+	return 0;
+}
+
+
+static void __exit fini(void)
+{
+	ipt_unregister_target(&ipt_route_reg);
+}
+
+module_init(init);
+module_exit(fini);
+MODULE_LICENSE("GPL");
diff -Nru ROUTE.orig/linux-2.4/net/ipv4/netfilter/Makefile.ladd ROUTE/linux-2.4/net/ipv4/netfilter/Makefile.ladd
--- ROUTE.orig/linux-2.4/net/ipv4/netfilter/Makefile.ladd	1970-01-01 01:00:00.000000000 +0100
+++ ROUTE/linux-2.4/net/ipv4/netfilter/Makefile.ladd	2003-12-18 19:47:54.000000000 +0100
@@ -0,0 +1,2 @@
+obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
+obj-$(CONFIG_IP_NF_TARGET_ROUTE) += ipt_ROUTE.o
diff -Nru ROUTE.orig/linux-2.4/net/ipv6/netfilter/Config.in.ladd ROUTE/linux-2.4/net/ipv6/netfilter/Config.in.ladd
--- ROUTE.orig/linux-2.4/net/ipv6/netfilter/Config.in.ladd	1970-01-01 01:00:00.000000000 +0100
+++ ROUTE/linux-2.4/net/ipv6/netfilter/Config.in.ladd	2003-12-20 17:43:09.000000000 +0100
@@ -0,0 +1,2 @@
+    dep_tristate '    MARK target support' CONFIG_IP6_NF_TARGET_MARK $CONFIG_IP6_NF_MANGLE
+    dep_mbool '    ROUTE target support' CONFIG_IP6_NF_TARGET_ROUTE $CONFIG_IP6_NF_MANGLE
\ Pas de fin de ligne à la fin du fichier.
diff -Nru ROUTE.orig/linux-2.4/net/ipv6/netfilter/CVS/Entries ROUTE/linux-2.4/net/ipv6/netfilter/CVS/Entries
--- ROUTE.orig/linux-2.4/net/ipv6/netfilter/CVS/Entries	1970-01-01 01:00:00.000000000 +0100
+++ ROUTE/linux-2.4/net/ipv6/netfilter/CVS/Entries	2004-03-08 10:06:41.000000000 +0100
@@ -0,0 +1,5 @@
+/Config.in.ladd/1.1/Sat Dec 20 16:43:09 2003//
+/Kconfig.ladd/1.1/Tue Dec 23 11:41:11 2003//
+/Makefile.ladd/1.1/Sat Dec 20 16:43:09 2003//
+/ip6t_ROUTE.c/1.1/Sat Dec 20 16:43:09 2003//
+D
diff -Nru ROUTE.orig/linux-2.4/net/ipv6/netfilter/CVS/Repository ROUTE/linux-2.4/net/ipv6/netfilter/CVS/Repository
--- ROUTE.orig/linux-2.4/net/ipv6/netfilter/CVS/Repository	1970-01-01 01:00:00.000000000 +0100
+++ ROUTE/linux-2.4/net/ipv6/netfilter/CVS/Repository	2004-03-08 10:06:41.000000000 +0100
@@ -0,0 +1 @@
+patch-o-matic-ng/ROUTE/linux/net/ipv6/netfilter
diff -Nru ROUTE.orig/linux-2.4/net/ipv6/netfilter/CVS/Root ROUTE/linux-2.4/net/ipv6/netfilter/CVS/Root
--- ROUTE.orig/linux-2.4/net/ipv6/netfilter/CVS/Root	1970-01-01 01:00:00.000000000 +0100
+++ ROUTE/linux-2.4/net/ipv6/netfilter/CVS/Root	2004-03-08 10:06:41.000000000 +0100
@@ -0,0 +1 @@
+:pserver:cvs:cvs@pserver.netfilter.org:/cvspublic
diff -Nru ROUTE.orig/linux-2.4/net/ipv6/netfilter/ip6t_ROUTE.c ROUTE/linux-2.4/net/ipv6/netfilter/ip6t_ROUTE.c
--- ROUTE.orig/linux-2.4/net/ipv6/netfilter/ip6t_ROUTE.c	1970-01-01 01:00:00.000000000 +0100
+++ ROUTE/linux-2.4/net/ipv6/netfilter/ip6t_ROUTE.c	2003-12-20 17:43:09.000000000 +0100
@@ -0,0 +1,289 @@
+/*
+ * 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.0 2003/08/05
+ *
+ * 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,
+		  unsigned int hooknum,
+		  const struct net_device *in,
+		  const struct net_device *out,
+		  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;
+
+	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--;
+	}
+
+
+ do_it:
+	if (route_info->oif[0]) 
+		return route6_oif(route_info, *pskb);
+	
+	if (!ipv6_addr_any(gw))
+		return route6_gw(route_info, *pskb);
+
+	if (net_ratelimit()) 
+		DEBUGP(KERN_DEBUG "ip6t_ROUTE: no parameter !\n");
+
+	return IP6T_CONTINUE;
+}
+
+
+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 -Nru ROUTE.orig/linux-2.4/net/ipv6/netfilter/Makefile.ladd ROUTE/linux-2.4/net/ipv6/netfilter/Makefile.ladd
--- ROUTE.orig/linux-2.4/net/ipv6/netfilter/Makefile.ladd	1970-01-01 01:00:00.000000000 +0100
+++ ROUTE/linux-2.4/net/ipv6/netfilter/Makefile.ladd	2003-12-20 17:43:09.000000000 +0100
@@ -0,0 +1,2 @@
+obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
+obj-$(CONFIG_IP6_NF_TARGET_ROUTE) += ip6t_ROUTE.o
diff -Nru ROUTE.orig/linux-2.6/include/linux/netfilter_ipv4/ipt_ROUTE.h ROUTE/linux-2.6/include/linux/netfilter_ipv4/ipt_ROUTE.h
--- ROUTE.orig/linux-2.6/include/linux/netfilter_ipv4/ipt_ROUTE.h	1970-01-01 01:00:00.000000000 +0100
+++ ROUTE/linux-2.6/include/linux/netfilter_ipv4/ipt_ROUTE.h	2003-12-18 19:47:54.000000000 +0100
@@ -0,0 +1,22 @@
+/* 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
+
+#endif /*_IPT_ROUTE_H_target*/
diff -Nru ROUTE.orig/linux-2.6/include/linux/netfilter_ipv6/ip6t_ROUTE.h ROUTE/linux-2.6/include/linux/netfilter_ipv6/ip6t_ROUTE.h
--- ROUTE.orig/linux-2.6/include/linux/netfilter_ipv6/ip6t_ROUTE.h	1970-01-01 01:00:00.000000000 +0100
+++ ROUTE/linux-2.6/include/linux/netfilter_ipv6/ip6t_ROUTE.h	2003-12-20 17:43:09.000000000 +0100
@@ -0,0 +1,22 @@
+/* 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
+
+#endif /*_IP6T_ROUTE_H_target*/
diff -Nru ROUTE.orig/linux-2.6/net/ipv4/netfilter/ipt_ROUTE.c ROUTE/linux-2.6/net/ipv4/netfilter/ipt_ROUTE.c
--- ROUTE.orig/linux-2.6/net/ipv4/netfilter/ipt_ROUTE.c	2004-02-22 18:29:10.000000000 +0100
+++ ROUTE/linux-2.6/net/ipv4/netfilter/ipt_ROUTE.c	2004-03-08 15:19:07.000000000 +0100
@@ -19,6 +19,7 @@
 #include <net/ip.h>
 #include <net/route.h>
 #include <net/icmp.h>
+#include <net/checksum.h>
 
 #if 0
 #define DEBUGP printk
@@ -28,6 +29,7 @@
 
 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 :
@@ -53,19 +55,24 @@
 	int err;
 	struct rtable *rt;
 	struct iphdr *iph = skb->nh.iph;
-	struct rt_key key = { 
-		dst:iph->daddr,
-		src:0,
-		oif:ifindex, 
-		tos:RT_TOS(iph->tos) 
+	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)
-		key.dst = route_info->gw;
+		fl.fld_dst = route_info->gw;
 	
 	/* Trying to route the packet using the standard routing table. */
-	if ((err = ip_route_output_key(&rt, &key))) {
+	if ((err = ip_route_output_key(&rt, &fl))) {
 		if (net_ratelimit()) 
 			DEBUGP("ipt_ROUTE: couldn't route pkt (err: %i)",err);
 		return -1;
@@ -262,10 +269,21 @@
 
 		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(&rt, iph->saddr, iph->daddr,
-					    RT_TOS(iph->tos) | RTO_CONN,
-					    0)) {
+			if (ip_route_output_key(&rt, &fl)) {
 				return NF_DROP;
 			}
 
@@ -284,6 +302,7 @@
 		}
 
 		ip_decrease_ttl(iph);
+		iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
 	}
 
 	/* Tell conntrack to forget this packet since it may get confused 
diff -Nru ROUTE.orig/linux-2.6/net/ipv4/netfilter/Kconfig.ladd ROUTE/linux-2.6/net/ipv4/netfilter/Kconfig.ladd
--- ROUTE.orig/linux-2.6/net/ipv4/netfilter/Kconfig.ladd	1970-01-01 01:00:00.000000000 +0100
+++ ROUTE/linux-2.6/net/ipv4/netfilter/Kconfig.ladd	2004-03-08 14:02:45.000000000 +0100
@@ -0,0 +1,16 @@
+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'.
diff -Nru ROUTE.orig/linux-2.6/net/ipv4/netfilter/Makefile.ladd ROUTE/linux-2.6/net/ipv4/netfilter/Makefile.ladd
--- ROUTE.orig/linux-2.6/net/ipv4/netfilter/Makefile.ladd	1970-01-01 01:00:00.000000000 +0100
+++ ROUTE/linux-2.6/net/ipv4/netfilter/Makefile.ladd	2003-12-18 19:47:54.000000000 +0100
@@ -0,0 +1,2 @@
+obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
+obj-$(CONFIG_IP_NF_TARGET_ROUTE) += ipt_ROUTE.o
diff -Nru ROUTE.orig/linux-2.6/net/ipv6/netfilter/ip6t_ROUTE.c ROUTE/linux-2.6/net/ipv6/netfilter/ip6t_ROUTE.c
--- ROUTE.orig/linux-2.6/net/ipv6/netfilter/ip6t_ROUTE.c	1970-01-01 01:00:00.000000000 +0100
+++ ROUTE/linux-2.6/net/ipv6/netfilter/ip6t_ROUTE.c	2003-12-20 17:43:09.000000000 +0100
@@ -0,0 +1,289 @@
+/*
+ * 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.0 2003/08/05
+ *
+ * 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,
+		  unsigned int hooknum,
+		  const struct net_device *in,
+		  const struct net_device *out,
+		  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;
+
+	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--;
+	}
+
+
+ do_it:
+	if (route_info->oif[0]) 
+		return route6_oif(route_info, *pskb);
+	
+	if (!ipv6_addr_any(gw))
+		return route6_gw(route_info, *pskb);
+
+	if (net_ratelimit()) 
+		DEBUGP(KERN_DEBUG "ip6t_ROUTE: no parameter !\n");
+
+	return IP6T_CONTINUE;
+}
+
+
+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 -Nru ROUTE.orig/linux-2.6/net/ipv6/netfilter/Kconfig.ladd ROUTE/linux-2.6/net/ipv6/netfilter/Kconfig.ladd
--- ROUTE.orig/linux-2.6/net/ipv6/netfilter/Kconfig.ladd	1970-01-01 01:00:00.000000000 +0100
+++ ROUTE/linux-2.6/net/ipv6/netfilter/Kconfig.ladd	2004-03-08 15:06:42.000000000 +0100
@@ -0,0 +1,11 @@
+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.
+
diff -Nru ROUTE.orig/linux-2.6/net/ipv6/netfilter/Makefile.ladd ROUTE/linux-2.6/net/ipv6/netfilter/Makefile.ladd
--- ROUTE.orig/linux-2.6/net/ipv6/netfilter/Makefile.ladd	1970-01-01 01:00:00.000000000 +0100
+++ ROUTE/linux-2.6/net/ipv6/netfilter/Makefile.ladd	2003-12-20 17:43:09.000000000 +0100
@@ -0,0 +1,2 @@
+obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
+obj-$(CONFIG_IP6_NF_TARGET_ROUTE) += ip6t_ROUTE.o

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] ROUTE target : update to pom-ng + new version for kernel 2.6.x
  2004-04-21  8:16 [PATCH] ROUTE target : update to pom-ng + new version for kernel 2.6.x Cedric de Launois
@ 2004-04-24 23:03 ` Patrick McHardy
  2004-04-25  0:01   ` Esteban Ribicic
  2004-04-28 15:25   ` Cedric de Launois
  0 siblings, 2 replies; 6+ messages in thread
From: Patrick McHardy @ 2004-04-24 23:03 UTC (permalink / raw)
  To: Cedric de Launois; +Cc: Netfilter Development Mailinglist

Cedric de Launois wrote:
> Here is a patch to convert the ROUTE target to the new pom-ng.
> This patch also contains a corrected version of the ROUTE target
> for kernels 2.6.x.

Please make sure your patch doesn't contain changes to CVS directories.

Regards
Patrick

> 
> Cedric
> 
> 
> 
> diff -Nru ROUTE.orig/linux-2.4/net/ipv6/netfilter/CVS/Entries ROUTE/linux-2.4/net/ipv6/netfilter/CVS/Entries
> --- ROUTE.orig/linux-2.4/net/ipv6/netfilter/CVS/Entries	1970-01-01 01:00:00.000000000 +0100
> +++ ROUTE/linux-2.4/net/ipv6/netfilter/CVS/Entries	2004-03-08 10:06:41.000000000 +0100
> @@ -0,0 +1,5 @@
> +/Config.in.ladd/1.1/Sat Dec 20 16:43:09 2003//
> +/Kconfig.ladd/1.1/Tue Dec 23 11:41:11 2003//
> +/Makefile.ladd/1.1/Sat Dec 20 16:43:09 2003//
> +/ip6t_ROUTE.c/1.1/Sat Dec 20 16:43:09 2003//
> +D
> diff -Nru ROUTE.orig/linux-2.4/net/ipv6/netfilter/CVS/Repository ROUTE/linux-2.4/net/ipv6/netfilter/CVS/Repository
> --- ROUTE.orig/linux-2.4/net/ipv6/netfilter/CVS/Repository	1970-01-01 01:00:00.000000000 +0100
> +++ ROUTE/linux-2.4/net/ipv6/netfilter/CVS/Repository	2004-03-08 10:06:41.000000000 +0100
> @@ -0,0 +1 @@
> +patch-o-matic-ng/ROUTE/linux/net/ipv6/netfilter
> diff -Nru ROUTE.orig/linux-2.4/net/ipv6/netfilter/CVS/Root ROUTE/linux-2.4/net/ipv6/netfilter/CVS/Root
> --- ROUTE.orig/linux-2.4/net/ipv6/netfilter/CVS/Root	1970-01-01 01:00:00.000000000 +0100
> +++ ROUTE/linux-2.4/net/ipv6/netfilter/CVS/Root	2004-03-08 10:06:41.000000000 +0100
> @@ -0,0 +1 @@
> +:pserver:cvs:cvs@pserver.netfilter.org:/cvspublic

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] ROUTE target : update to pom-ng + new version for kernel 2.6.x
  2004-04-24 23:03 ` Patrick McHardy
@ 2004-04-25  0:01   ` Esteban Ribicic
  2004-04-26  4:46     ` Henrik Nordstrom
  2004-04-28 15:25   ` Cedric de Launois
  1 sibling, 1 reply; 6+ messages in thread
From: Esteban Ribicic @ 2004-04-25  0:01 UTC (permalink / raw)
  To: netfilter-devel

Content-Transfer-Encoding: 7bit

hi

im trying to match all recent ip_conntrak connections from my network
im using this algortithm:

# does not concern ESTA connections..
# udp      17 59 src=10.0.3.75 dst=62.215.85.173 sport=26097 dport=19210 src=62.215.85.173 dst=200.69.147.80 sport=19210 dport=26097 [ASSURED] use=1 mark=0

$timeout=300;
if ($_=~/\w+\s+\d+\s(\d+)\s+src=/) {
	if ($1<$timeout) {
		$counter++;
	}
}

where $timeout is the max timeout of the connection.

now, what i notice is that ESTABLISHED connections are rarely under 2000 seconds? isnt it rare?


lp:~/codigos/conntrack# cat /proc/net/ip_conntrack | grep ESTABLISHED  | awk '{print $3}' | sort -n | head -n 5
870
938
1106
1977
1990

...(the list is realy extensive)

Its obvious im thinking something woron..maybe $1 is not a timeout and less is seconds?

thanks for the help
Steve

On Sun, 25 Apr 2004 01:03:24 +0200
Patrick McHardy <kaber@trash.net> wrote:

> Cedric de Launois wrote:
> > Here is a patch to convert the ROUTE target to the new pom-ng.
> > This patch also contains a corrected version of the ROUTE target
> > for kernels 2.6.x.
> 
> Please make sure your patch doesn't contain changes to CVS directories.
> 
> Regards
> Patrick
> 
> > 
> > Cedric
> > 
> > 
> > 
> > diff -Nru ROUTE.orig/linux-2.4/net/ipv6/netfilter/CVS/Entries ROUTE/linux-2.4/net/ipv6/netfilter/CVS/Entries
> > --- ROUTE.orig/linux-2.4/net/ipv6/netfilter/CVS/Entries	1970-01-01 01:00:00.000000000 +0100
> > +++ ROUTE/linux-2.4/net/ipv6/netfilter/CVS/Entries	2004-03-08 10:06:41.000000000 +0100
> > @@ -0,0 +1,5 @@
> > +/Config.in.ladd/1.1/Sat Dec 20 16:43:09 2003//
> > +/Kconfig.ladd/1.1/Tue Dec 23 11:41:11 2003//
> > +/Makefile.ladd/1.1/Sat Dec 20 16:43:09 2003//
> > +/ip6t_ROUTE.c/1.1/Sat Dec 20 16:43:09 2003//
> > +D
> > diff -Nru ROUTE.orig/linux-2.4/net/ipv6/netfilter/CVS/Repository ROUTE/linux-2.4/net/ipv6/netfilter/CVS/Repository
> > --- ROUTE.orig/linux-2.4/net/ipv6/netfilter/CVS/Repository	1970-01-01 01:00:00.000000000 +0100
> > +++ ROUTE/linux-2.4/net/ipv6/netfilter/CVS/Repository	2004-03-08 10:06:41.000000000 +0100
> > @@ -0,0 +1 @@
> > +patch-o-matic-ng/ROUTE/linux/net/ipv6/netfilter
> > diff -Nru ROUTE.orig/linux-2.4/net/ipv6/netfilter/CVS/Root ROUTE/linux-2.4/net/ipv6/netfilter/CVS/Root
> > --- ROUTE.orig/linux-2.4/net/ipv6/netfilter/CVS/Root	1970-01-01 01:00:00.000000000 +0100
> > +++ ROUTE/linux-2.4/net/ipv6/netfilter/CVS/Root	2004-03-08 10:06:41.000000000 +0100
> > @@ -0,0 +1 @@
> > +:pserver:cvs:cvs@pserver.netfilter.org:/cvspublic
> 
> 

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] ROUTE target : update to pom-ng + new version for kernel 2.6.x
  2004-04-25  0:01   ` Esteban Ribicic
@ 2004-04-26  4:46     ` Henrik Nordstrom
  0 siblings, 0 replies; 6+ messages in thread
From: Henrik Nordstrom @ 2004-04-26  4:46 UTC (permalink / raw)
  To: Esteban Ribicic; +Cc: netfilter-devel

On Sat, 24 Apr 2004, Esteban Ribicic wrote:

> now, what i notice is that ESTABLISHED connections are rarely under 2000 seconds? isnt it rare?

The timeout of a ESTABLISHED TCP is 5 days (432000 seconds).. A
ESTABLISHED connecting with a timeout under 2000 seconds needs to have
been idle in almost 5 days..

TCP state timeouts from ip_conntrack_proto_tcp:

unsigned long ip_ct_tcp_timeout_syn_sent =      2 MINS;
unsigned long ip_ct_tcp_timeout_syn_recv =     60 SECS;
unsigned long ip_ct_tcp_timeout_established =   5 DAYS;
unsigned long ip_ct_tcp_timeout_fin_wait =      2 MINS;
unsigned long ip_ct_tcp_timeout_close_wait =   60 SECS;
unsigned long ip_ct_tcp_timeout_last_ack =     30 SECS;
unsigned long ip_ct_tcp_timeout_time_wait =     2 MINS;
unsigned long ip_ct_tcp_timeout_close =        10 SECS;


Each packet while the TCP is in the given state extends the timeout.


On UDP the timeouts is much smaller due to the stateless nature of the 
protocol

unsigned long ip_ct_udp_timeout = 30*HZ;
unsigned long ip_ct_udp_timeout_stream = 180*HZ;


30 seconds for traffic in only one direction, 180 if traffic has been 
seen in both directions.

Regards
Henrik

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] ROUTE target : update to pom-ng + new version for kernel 2.6.x
  2004-04-24 23:03 ` Patrick McHardy
  2004-04-25  0:01   ` Esteban Ribicic
@ 2004-04-28 15:25   ` Cedric de Launois
  2004-04-29 16:45     ` Patrick McHardy
  1 sibling, 1 reply; 6+ messages in thread
From: Cedric de Launois @ 2004-04-28 15:25 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: Netfilter Development Mailinglist

[-- Attachment #1: Type: text/plain, Size: 392 bytes --]

Le dim 25/04/2004 à 01:03, Patrick McHardy a écrit :
> Cedric de Launois wrote:
> > Here is a patch to convert the ROUTE target to the new pom-ng.
> > This patch also contains a corrected version of the ROUTE target
> > for kernels 2.6.x.
> 
> Please make sure your patch doesn't contain changes to CVS directories.

Oops, sorry. This patch should be better.

Regards,

Cedric


[-- Attachment #2: ROUTE.pom-ng.patch --]
[-- Type: text/x-patch, Size: 66675 bytes --]

diff -Nru ./ROUTE.orig/info ./ROUTE/info
--- ./ROUTE.orig/info	2004-02-20 00:11:50.000000000 +0100
+++ ./ROUTE/info	2004-03-08 14:19:22.000000000 +0100
@@ -1,4 +1,5 @@
 Author: Cédric de Launois <delaunois@info.ucl.ac.be>
 Status: Experimental
 Repository: extra
-Requires: linux < 2.6.0
+Recompile: netfilter
+Recompile: iptables
diff -Nru ./ROUTE.orig/linux/Documentation/Configure.help.ladd ./ROUTE/linux/Documentation/Configure.help.ladd
--- ./ROUTE.orig/linux/Documentation/Configure.help.ladd	2004-02-19 12:30:08.000000000 +0100
+++ ./ROUTE/linux/Documentation/Configure.help.ladd	1970-01-01 01:00:00.000000000 +0100
@@ -1,16 +0,0 @@
-CONFIG_IP_NF_TARGET_MARK
-ROUTE target support
-CONFIG_IP_NF_TARGET_ROUTE
-  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'.
-
diff -Nru ./ROUTE.orig/linux/Documentation/Configure.help.ladd_2 ./ROUTE/linux/Documentation/Configure.help.ladd_2
--- ./ROUTE.orig/linux/Documentation/Configure.help.ladd_2	2004-03-05 10:30:26.000000000 +0100
+++ ./ROUTE/linux/Documentation/Configure.help.ladd_2	1970-01-01 01:00:00.000000000 +0100
@@ -1,12 +0,0 @@
-CONFIG_IP6_NF_TARGET_MARK
-ROUTE target support
-CONFIG_IP6_NF_TARGET_ROUTE
-  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.
-
diff -Nru ./ROUTE.orig/linux/include/linux/netfilter_ipv4/ipt_ROUTE.h ./ROUTE/linux/include/linux/netfilter_ipv4/ipt_ROUTE.h
--- ./ROUTE.orig/linux/include/linux/netfilter_ipv4/ipt_ROUTE.h	2003-12-18 19:47:54.000000000 +0100
+++ ./ROUTE/linux/include/linux/netfilter_ipv4/ipt_ROUTE.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,22 +0,0 @@
-/* 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
-
-#endif /*_IPT_ROUTE_H_target*/
diff -Nru ./ROUTE.orig/linux/include/linux/netfilter_ipv6/ip6t_ROUTE.h ./ROUTE/linux/include/linux/netfilter_ipv6/ip6t_ROUTE.h
--- ./ROUTE.orig/linux/include/linux/netfilter_ipv6/ip6t_ROUTE.h	2003-12-20 17:43:09.000000000 +0100
+++ ./ROUTE/linux/include/linux/netfilter_ipv6/ip6t_ROUTE.h	1970-01-01 01:00:00.000000000 +0100
@@ -1,22 +0,0 @@
-/* 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
-
-#endif /*_IP6T_ROUTE_H_target*/
diff -Nru ./ROUTE.orig/linux/net/ipv4/netfilter/Config.in.ladd ./ROUTE/linux/net/ipv4/netfilter/Config.in.ladd
--- ./ROUTE.orig/linux/net/ipv4/netfilter/Config.in.ladd	2003-12-18 19:47:54.000000000 +0100
+++ ./ROUTE/linux/net/ipv4/netfilter/Config.in.ladd	1970-01-01 01:00:00.000000000 +0100
@@ -1,3 +0,0 @@
-    dep_tristate '    MARK target support' CONFIG_IP_NF_TARGET_MARK $CONFIG_IP_NF_MANGLE
-    dep_tristate '    ROUTE target support' CONFIG_IP_NF_TARGET_ROUTE $CONFIG_IP_NF_MANGLE
- 
\ Pas de fin de ligne à la fin du fichier.
diff -Nru ./ROUTE.orig/linux/net/ipv4/netfilter/ipt_ROUTE.c ./ROUTE/linux/net/ipv4/netfilter/ipt_ROUTE.c
--- ./ROUTE.orig/linux/net/ipv4/netfilter/ipt_ROUTE.c	2003-12-18 19:47:54.000000000 +0100
+++ ./ROUTE/linux/net/ipv4/netfilter/ipt_ROUTE.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,369 +0,0 @@
-/*
- * 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.8 2003/07/25
- *
- * 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/ipt_ROUTE.h>
-#include <linux/netdevice.h>
-#include <linux/route.h>
-#include <net/ip.h>
-#include <net/route.h>
-#include <net/icmp.h>
-
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
-
-/* 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 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->gw)
-		key.dst = route_info->gw;
-	
-	/* Trying to route the packet using the standard routing table. */
-	if ((err = ip_route_output_key(&rt, &key))) {
-		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;
-		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;
-
-	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 "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_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 */
-		if (net_ratelimit()) 
-			DEBUGP("ipt_ROUTE: iif interface %s not found\n", route_info->oif);
-		return NF_DROP;
-	}
-
-	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;
-
-	if (route_info->flags & IPT_ROUTE_CONTINUE)
-		return IPT_CONTINUE;
-
-	ip_direct_send(skb);
-	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;
-
-	/* 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;
-
-			if (ip_route_output(&rt, iph->saddr, iph->daddr,
-					    RT_TOS(iph->tos) | RTO_CONN,
-					    0)) {
-				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;
-		}
-
-		ip_decrease_ttl(iph);
-	}
-
-	/* 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.
-	 */
-	if (!(route_info->flags & IPT_ROUTE_CONTINUE)) {
-		nf_conntrack_put(skb->nfct);
-		skb->nfct = NULL;
-		skb->nfcache = 0;
-#ifdef CONFIG_NETFILTER_DEBUG
-		skb->nf_debug = 0;
-#endif
-	}
-
-	if (route_info->oif[0]) 
-		return route_oif(route_info, *pskb);
-	
-	if (route_info->iif[0]) 
-		return route_iif(route_info, *pskb);
-
-	if (route_info->gw) 
-		return route_gw(route_info, *pskb);
-
-	if (net_ratelimit()) 
-		DEBUGP(KERN_DEBUG "ipt_ROUTE: no parameter !\n");
-
-	return IPT_CONTINUE;
-}
-
-
-static int ipt_route_checkentry(const char *tablename,
-				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",
-		       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
-= { { NULL, NULL }, "ROUTE", ipt_route_target, ipt_route_checkentry, NULL,
-    THIS_MODULE };
-
-
-static int __init init(void)
-{
-	if (ipt_register_target(&ipt_route_reg))
-		return -EINVAL;
-
-	return 0;
-}
-
-
-static void __exit fini(void)
-{
-	ipt_unregister_target(&ipt_route_reg);
-}
-
-module_init(init);
-module_exit(fini);
-MODULE_LICENSE("GPL");
diff -Nru ./ROUTE.orig/linux/net/ipv4/netfilter/Kconfig.ladd ./ROUTE/linux/net/ipv4/netfilter/Kconfig.ladd
--- ./ROUTE.orig/linux/net/ipv4/netfilter/Kconfig.ladd	2003-12-21 21:09:27.000000000 +0100
+++ ./ROUTE/linux/net/ipv4/netfilter/Kconfig.ladd	1970-01-01 01:00:00.000000000 +0100
@@ -1,3 +0,0 @@
-config IP_NF_TARGET_ROUTE
-	tristate  'ROUTE target support'
-	depends on IP_NF_MANGLE
diff -Nru ./ROUTE.orig/linux/net/ipv4/netfilter/Makefile.ladd ./ROUTE/linux/net/ipv4/netfilter/Makefile.ladd
--- ./ROUTE.orig/linux/net/ipv4/netfilter/Makefile.ladd	2003-12-18 19:47:54.000000000 +0100
+++ ./ROUTE/linux/net/ipv4/netfilter/Makefile.ladd	1970-01-01 01:00:00.000000000 +0100
@@ -1,2 +0,0 @@
-obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
-obj-$(CONFIG_IP_NF_TARGET_ROUTE) += ipt_ROUTE.o
diff -Nru ./ROUTE.orig/linux/net/ipv6/netfilter/Config.in.ladd ./ROUTE/linux/net/ipv6/netfilter/Config.in.ladd
--- ./ROUTE.orig/linux/net/ipv6/netfilter/Config.in.ladd	2003-12-20 17:43:09.000000000 +0100
+++ ./ROUTE/linux/net/ipv6/netfilter/Config.in.ladd	1970-01-01 01:00:00.000000000 +0100
@@ -1,2 +0,0 @@
-    dep_tristate '    MARK target support' CONFIG_IP6_NF_TARGET_MARK $CONFIG_IP6_NF_MANGLE
-    dep_mbool '    ROUTE target support' CONFIG_IP6_NF_TARGET_ROUTE $CONFIG_IP6_NF_MANGLE
\ Pas de fin de ligne à la fin du fichier.
diff -Nru ./ROUTE.orig/linux/net/ipv6/netfilter/ip6t_ROUTE.c ./ROUTE/linux/net/ipv6/netfilter/ip6t_ROUTE.c
--- ./ROUTE.orig/linux/net/ipv6/netfilter/ip6t_ROUTE.c	2003-12-20 17:43:09.000000000 +0100
+++ ./ROUTE/linux/net/ipv6/netfilter/ip6t_ROUTE.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,289 +0,0 @@
-/*
- * 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.0 2003/08/05
- *
- * 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,
-		  unsigned int hooknum,
-		  const struct net_device *in,
-		  const struct net_device *out,
-		  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;
-
-	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--;
-	}
-
-
- do_it:
-	if (route_info->oif[0]) 
-		return route6_oif(route_info, *pskb);
-	
-	if (!ipv6_addr_any(gw))
-		return route6_gw(route_info, *pskb);
-
-	if (net_ratelimit()) 
-		DEBUGP(KERN_DEBUG "ip6t_ROUTE: no parameter !\n");
-
-	return IP6T_CONTINUE;
-}
-
-
-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 -Nru ./ROUTE.orig/linux/net/ipv6/netfilter/Kconfig.ladd ./ROUTE/linux/net/ipv6/netfilter/Kconfig.ladd
--- ./ROUTE.orig/linux/net/ipv6/netfilter/Kconfig.ladd	2003-12-23 12:41:11.000000000 +0100
+++ ./ROUTE/linux/net/ipv6/netfilter/Kconfig.ladd	1970-01-01 01:00:00.000000000 +0100
@@ -1,3 +0,0 @@
-config IP6_NF_TARGET_ROUTE
-	tristate '    ROUTE target support'
-	depends on IP6_NF_MANGLE
diff -Nru ./ROUTE.orig/linux/net/ipv6/netfilter/Makefile.ladd ./ROUTE/linux/net/ipv6/netfilter/Makefile.ladd
--- ./ROUTE.orig/linux/net/ipv6/netfilter/Makefile.ladd	2003-12-20 17:43:09.000000000 +0100
+++ ./ROUTE/linux/net/ipv6/netfilter/Makefile.ladd	1970-01-01 01:00:00.000000000 +0100
@@ -1,2 +0,0 @@
-obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
-obj-$(CONFIG_IP6_NF_TARGET_ROUTE) += ip6t_ROUTE.o
diff -Nru ./ROUTE.orig/linux-2.4/Documentation/Configure.help.ladd ./ROUTE/linux-2.4/Documentation/Configure.help.ladd
--- ./ROUTE.orig/linux-2.4/Documentation/Configure.help.ladd	1970-01-01 01:00:00.000000000 +0100
+++ ./ROUTE/linux-2.4/Documentation/Configure.help.ladd	2004-02-19 12:30:08.000000000 +0100
@@ -0,0 +1,16 @@
+CONFIG_IP_NF_TARGET_MARK
+ROUTE target support
+CONFIG_IP_NF_TARGET_ROUTE
+  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'.
+
diff -Nru ./ROUTE.orig/linux-2.4/Documentation/Configure.help.ladd_2 ./ROUTE/linux-2.4/Documentation/Configure.help.ladd_2
--- ./ROUTE.orig/linux-2.4/Documentation/Configure.help.ladd_2	1970-01-01 01:00:00.000000000 +0100
+++ ./ROUTE/linux-2.4/Documentation/Configure.help.ladd_2	2004-03-05 10:30:26.000000000 +0100
@@ -0,0 +1,12 @@
+CONFIG_IP6_NF_TARGET_MARK
+ROUTE target support
+CONFIG_IP6_NF_TARGET_ROUTE
+  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.
+
diff -Nru ./ROUTE.orig/linux-2.4/include/linux/netfilter_ipv4/ipt_ROUTE.h ./ROUTE/linux-2.4/include/linux/netfilter_ipv4/ipt_ROUTE.h
--- ./ROUTE.orig/linux-2.4/include/linux/netfilter_ipv4/ipt_ROUTE.h	1970-01-01 01:00:00.000000000 +0100
+++ ./ROUTE/linux-2.4/include/linux/netfilter_ipv4/ipt_ROUTE.h	2003-12-18 19:47:54.000000000 +0100
@@ -0,0 +1,22 @@
+/* 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
+
+#endif /*_IPT_ROUTE_H_target*/
diff -Nru ./ROUTE.orig/linux-2.4/include/linux/netfilter_ipv6/ip6t_ROUTE.h ./ROUTE/linux-2.4/include/linux/netfilter_ipv6/ip6t_ROUTE.h
--- ./ROUTE.orig/linux-2.4/include/linux/netfilter_ipv6/ip6t_ROUTE.h	1970-01-01 01:00:00.000000000 +0100
+++ ./ROUTE/linux-2.4/include/linux/netfilter_ipv6/ip6t_ROUTE.h	2003-12-20 17:43:09.000000000 +0100
@@ -0,0 +1,22 @@
+/* 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
+
+#endif /*_IP6T_ROUTE_H_target*/
diff -Nru ./ROUTE.orig/linux-2.4/net/ipv4/netfilter/Config.in.ladd ./ROUTE/linux-2.4/net/ipv4/netfilter/Config.in.ladd
--- ./ROUTE.orig/linux-2.4/net/ipv4/netfilter/Config.in.ladd	1970-01-01 01:00:00.000000000 +0100
+++ ./ROUTE/linux-2.4/net/ipv4/netfilter/Config.in.ladd	2003-12-18 19:47:54.000000000 +0100
@@ -0,0 +1,3 @@
+    dep_tristate '    MARK target support' CONFIG_IP_NF_TARGET_MARK $CONFIG_IP_NF_MANGLE
+    dep_tristate '    ROUTE target support' CONFIG_IP_NF_TARGET_ROUTE $CONFIG_IP_NF_MANGLE
+ 
\ Pas de fin de ligne à la fin du fichier.
diff -Nru ./ROUTE.orig/linux-2.4/net/ipv4/netfilter/ipt_ROUTE.c ./ROUTE/linux-2.4/net/ipv4/netfilter/ipt_ROUTE.c
--- ./ROUTE.orig/linux-2.4/net/ipv4/netfilter/ipt_ROUTE.c	1970-01-01 01:00:00.000000000 +0100
+++ ./ROUTE/linux-2.4/net/ipv4/netfilter/ipt_ROUTE.c	2004-04-21 09:47:08.000000000 +0200
@@ -0,0 +1,401 @@
+/*
+ * 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.10 2004/04/21
+ *
+ * This software is distributed under GNU GPL v2, 1991
+ *
+ * 30 Dec 2003: Rickard Molin <rickard.molin@businessecurity.com>
+ *      - recalculate checksum at INPUT chain after ttl is decreased
+ * 21 Apr 2004: Bill Rugolsky Jr. <brugolsky@telemetry-investments.com>
+ *      - fix missing dev_put() in route_iif()
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_ROUTE.h>
+#include <linux/netdevice.h>
+#include <linux/route.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
+
+
+/* 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 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->gw)
+		key.dst = route_info->gw;
+	
+	/* Trying to route the packet using the standard routing table. */
+	if ((err = ip_route_output_key(&rt, &key))) {
+		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;
+		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;
+
+	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 "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 void ip_tunnel_send(struct sk_buff *skb)
+{
+	memset(skb->data - 16, 0, 16);
+	skb_push(skb, skb->dev->hard_header_len);
+	dev_direct_send(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);
+
+		if (route_info->flags & IPT_ROUTE_CONTINUE)
+			return IPT_CONTINUE;
+		else
+			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) {
+			if (net_ratelimit()) 
+				DEBUGP("ipt_ROUTE: can't force the use of %s with --continue\n",
+				       route_info->oif);
+			return IPT_CONTINUE;
+		}
+
+		if (net_ratelimit()) 
+			DEBUGP("ipt_ROUTE: forcing the use of %s\n",
+			       route_info->oif);
+
+		/* 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;
+		ip_tunnel_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;
+
+	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)
+		if (!(route_info->flags & IPT_ROUTE_CONTINUE))
+			return NF_DROP;
+
+	if (route_info->flags & IPT_ROUTE_CONTINUE)
+		return IPT_CONTINUE;
+
+	ip_direct_send(skb);
+	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;
+
+	if (route_info->flags & IPT_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_IP_PRE_ROUTING ||
+	    hooknum == NF_IP_LOCAL_IN) {
+
+		struct iphdr *iph = skb->nh.iph;
+
+		if (iph->ttl <= 1) {
+			struct rtable *rt;
+
+			if (ip_route_output(&rt, iph->saddr, iph->daddr,
+					    RT_TOS(iph->tos) | RTO_CONN,
+					    0)) {
+				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);
+		}
+	}
+
+	/* 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.
+	 */
+	nf_conntrack_put(skb->nfct);
+	skb->nfct = NULL;
+	skb->nfcache = 0;
+#ifdef CONFIG_NETFILTER_DEBUG
+	skb->nf_debug = 0;
+#endif
+
+
+ do_it:
+	if (route_info->oif[0]) 
+		return route_oif(route_info, *pskb);
+	
+	if (route_info->iif[0]) 
+		return route_iif(route_info, *pskb);
+
+	if (route_info->gw) 
+		return route_gw(route_info, *pskb);
+
+	if (net_ratelimit()) 
+		DEBUGP(KERN_DEBUG "ipt_ROUTE: no parameter !\n");
+
+	return IPT_CONTINUE;
+}
+
+
+static int ipt_route_checkentry(const char *tablename,
+				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",
+		       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
+= { { NULL, NULL }, "ROUTE", ipt_route_target, ipt_route_checkentry, NULL,
+    THIS_MODULE };
+
+
+static int __init init(void)
+{
+	if (ipt_register_target(&ipt_route_reg))
+		return -EINVAL;
+
+	return 0;
+}
+
+
+static void __exit fini(void)
+{
+	ipt_unregister_target(&ipt_route_reg);
+}
+
+module_init(init);
+module_exit(fini);
+MODULE_LICENSE("GPL");
diff -Nru ./ROUTE.orig/linux-2.4/net/ipv4/netfilter/Kconfig.ladd ./ROUTE/linux-2.4/net/ipv4/netfilter/Kconfig.ladd
--- ./ROUTE.orig/linux-2.4/net/ipv4/netfilter/Kconfig.ladd	1970-01-01 01:00:00.000000000 +0100
+++ ./ROUTE/linux-2.4/net/ipv4/netfilter/Kconfig.ladd	2003-12-21 21:09:27.000000000 +0100
@@ -0,0 +1,3 @@
+config IP_NF_TARGET_ROUTE
+	tristate  'ROUTE target support'
+	depends on IP_NF_MANGLE
diff -Nru ./ROUTE.orig/linux-2.4/net/ipv4/netfilter/Makefile.ladd ./ROUTE/linux-2.4/net/ipv4/netfilter/Makefile.ladd
--- ./ROUTE.orig/linux-2.4/net/ipv4/netfilter/Makefile.ladd	1970-01-01 01:00:00.000000000 +0100
+++ ./ROUTE/linux-2.4/net/ipv4/netfilter/Makefile.ladd	2003-12-18 19:47:54.000000000 +0100
@@ -0,0 +1,2 @@
+obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
+obj-$(CONFIG_IP_NF_TARGET_ROUTE) += ipt_ROUTE.o
diff -Nru ./ROUTE.orig/linux-2.4/net/ipv6/netfilter/Config.in.ladd ./ROUTE/linux-2.4/net/ipv6/netfilter/Config.in.ladd
--- ./ROUTE.orig/linux-2.4/net/ipv6/netfilter/Config.in.ladd	1970-01-01 01:00:00.000000000 +0100
+++ ./ROUTE/linux-2.4/net/ipv6/netfilter/Config.in.ladd	2003-12-20 17:43:09.000000000 +0100
@@ -0,0 +1,2 @@
+    dep_tristate '    MARK target support' CONFIG_IP6_NF_TARGET_MARK $CONFIG_IP6_NF_MANGLE
+    dep_mbool '    ROUTE target support' CONFIG_IP6_NF_TARGET_ROUTE $CONFIG_IP6_NF_MANGLE
\ Pas de fin de ligne à la fin du fichier.
diff -Nru ./ROUTE.orig/linux-2.4/net/ipv6/netfilter/ip6t_ROUTE.c ./ROUTE/linux-2.4/net/ipv6/netfilter/ip6t_ROUTE.c
--- ./ROUTE.orig/linux-2.4/net/ipv6/netfilter/ip6t_ROUTE.c	1970-01-01 01:00:00.000000000 +0100
+++ ./ROUTE/linux-2.4/net/ipv6/netfilter/ip6t_ROUTE.c	2003-12-20 17:43:09.000000000 +0100
@@ -0,0 +1,289 @@
+/*
+ * 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.0 2003/08/05
+ *
+ * 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,
+		  unsigned int hooknum,
+		  const struct net_device *in,
+		  const struct net_device *out,
+		  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;
+
+	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--;
+	}
+
+
+ do_it:
+	if (route_info->oif[0]) 
+		return route6_oif(route_info, *pskb);
+	
+	if (!ipv6_addr_any(gw))
+		return route6_gw(route_info, *pskb);
+
+	if (net_ratelimit()) 
+		DEBUGP(KERN_DEBUG "ip6t_ROUTE: no parameter !\n");
+
+	return IP6T_CONTINUE;
+}
+
+
+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 -Nru ./ROUTE.orig/linux-2.4/net/ipv6/netfilter/Makefile.ladd ./ROUTE/linux-2.4/net/ipv6/netfilter/Makefile.ladd
--- ./ROUTE.orig/linux-2.4/net/ipv6/netfilter/Makefile.ladd	1970-01-01 01:00:00.000000000 +0100
+++ ./ROUTE/linux-2.4/net/ipv6/netfilter/Makefile.ladd	2003-12-20 17:43:09.000000000 +0100
@@ -0,0 +1,2 @@
+obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
+obj-$(CONFIG_IP6_NF_TARGET_ROUTE) += ip6t_ROUTE.o
diff -Nru ./ROUTE.orig/linux-2.6/include/linux/netfilter_ipv4/ipt_ROUTE.h ./ROUTE/linux-2.6/include/linux/netfilter_ipv4/ipt_ROUTE.h
--- ./ROUTE.orig/linux-2.6/include/linux/netfilter_ipv4/ipt_ROUTE.h	1970-01-01 01:00:00.000000000 +0100
+++ ./ROUTE/linux-2.6/include/linux/netfilter_ipv4/ipt_ROUTE.h	2003-12-18 19:47:54.000000000 +0100
@@ -0,0 +1,22 @@
+/* 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
+
+#endif /*_IPT_ROUTE_H_target*/
diff -Nru ./ROUTE.orig/linux-2.6/include/linux/netfilter_ipv6/ip6t_ROUTE.h ./ROUTE/linux-2.6/include/linux/netfilter_ipv6/ip6t_ROUTE.h
--- ./ROUTE.orig/linux-2.6/include/linux/netfilter_ipv6/ip6t_ROUTE.h	1970-01-01 01:00:00.000000000 +0100
+++ ./ROUTE/linux-2.6/include/linux/netfilter_ipv6/ip6t_ROUTE.h	2003-12-20 17:43:09.000000000 +0100
@@ -0,0 +1,22 @@
+/* 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
+
+#endif /*_IP6T_ROUTE_H_target*/
diff -Nru ./ROUTE.orig/linux-2.6/net/ipv4/netfilter/ipt_ROUTE.c ./ROUTE/linux-2.6/net/ipv4/netfilter/ipt_ROUTE.c
--- ./ROUTE.orig/linux-2.6/net/ipv4/netfilter/ipt_ROUTE.c	2004-02-22 18:29:10.000000000 +0100
+++ ./ROUTE/linux-2.6/net/ipv4/netfilter/ipt_ROUTE.c	2004-04-21 10:17:44.000000000 +0200
@@ -19,6 +19,7 @@
 #include <net/ip.h>
 #include <net/route.h>
 #include <net/icmp.h>
+#include <net/checksum.h>
 
 #if 0
 #define DEBUGP printk
@@ -28,6 +29,7 @@
 
 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 :
@@ -53,19 +55,24 @@
 	int err;
 	struct rtable *rt;
 	struct iphdr *iph = skb->nh.iph;
-	struct rt_key key = { 
-		dst:iph->daddr,
-		src:0,
-		oif:ifindex, 
-		tos:RT_TOS(iph->tos) 
+	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)
-		key.dst = route_info->gw;
+		fl.fld_dst = route_info->gw;
 	
 	/* Trying to route the packet using the standard routing table. */
-	if ((err = ip_route_output_key(&rt, &key))) {
+	if ((err = ip_route_output_key(&rt, &fl))) {
 		if (net_ratelimit()) 
 			DEBUGP("ipt_ROUTE: couldn't route pkt (err: %i)",err);
 		return -1;
@@ -205,25 +212,21 @@
 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;
+	struct net_device *dev_in = NULL;
 
-	/* 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 */
-		if (net_ratelimit()) 
-			DEBUGP("ipt_ROUTE: iif interface %s not found\n", route_info->oif);
+	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_out;
+	skb->dev = dev_in;
 	dst_release(skb->dst);
 	skb->dst = NULL;
-		
+
 	netif_rx(skb);
 
+	dev_put(dev_in);
 	return NF_STOLEN;
 }
 
@@ -252,6 +255,9 @@
 	const struct ipt_route_target_info *route_info = targinfo;
 	struct sk_buff *skb = *pskb;
 
+	if (route_info->flags & IPT_ROUTE_CONTINUE)
+		goto do_it;
+
 	/* If we are at PREROUTING or INPUT hook
 	 * the TTL isn't decreased by the IP stack
 	 */
@@ -262,10 +268,21 @@
 
 		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(&rt, iph->saddr, iph->daddr,
-					    RT_TOS(iph->tos) | RTO_CONN,
-					    0)) {
+			if (ip_route_output_key(&rt, &fl)) {
 				return NF_DROP;
 			}
 
@@ -283,7 +300,17 @@
 			return NF_DROP;
 		}
 
-		ip_decrease_ttl(iph);
+		/*
+		 * 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);
+		}
 	}
 
 	/* Tell conntrack to forget this packet since it may get confused 
@@ -299,6 +326,7 @@
 #endif
 	}
 
+ do_it:
 	if (route_info->oif[0]) 
 		return route_oif(route_info, *pskb);
 	
diff -Nru ./ROUTE.orig/linux-2.6/net/ipv4/netfilter/Kconfig.ladd ./ROUTE/linux-2.6/net/ipv4/netfilter/Kconfig.ladd
--- ./ROUTE.orig/linux-2.6/net/ipv4/netfilter/Kconfig.ladd	1970-01-01 01:00:00.000000000 +0100
+++ ./ROUTE/linux-2.6/net/ipv4/netfilter/Kconfig.ladd	2004-03-08 14:02:45.000000000 +0100
@@ -0,0 +1,16 @@
+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'.
diff -Nru ./ROUTE.orig/linux-2.6/net/ipv4/netfilter/Makefile.ladd ./ROUTE/linux-2.6/net/ipv4/netfilter/Makefile.ladd
--- ./ROUTE.orig/linux-2.6/net/ipv4/netfilter/Makefile.ladd	1970-01-01 01:00:00.000000000 +0100
+++ ./ROUTE/linux-2.6/net/ipv4/netfilter/Makefile.ladd	2003-12-18 19:47:54.000000000 +0100
@@ -0,0 +1,2 @@
+obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
+obj-$(CONFIG_IP_NF_TARGET_ROUTE) += ipt_ROUTE.o
diff -Nru ./ROUTE.orig/linux-2.6/net/ipv6/netfilter/ip6t_ROUTE.c ./ROUTE/linux-2.6/net/ipv6/netfilter/ip6t_ROUTE.c
--- ./ROUTE.orig/linux-2.6/net/ipv6/netfilter/ip6t_ROUTE.c	1970-01-01 01:00:00.000000000 +0100
+++ ./ROUTE/linux-2.6/net/ipv6/netfilter/ip6t_ROUTE.c	2003-12-20 17:43:09.000000000 +0100
@@ -0,0 +1,289 @@
+/*
+ * 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.0 2003/08/05
+ *
+ * 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,
+		  unsigned int hooknum,
+		  const struct net_device *in,
+		  const struct net_device *out,
+		  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;
+
+	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--;
+	}
+
+
+ do_it:
+	if (route_info->oif[0]) 
+		return route6_oif(route_info, *pskb);
+	
+	if (!ipv6_addr_any(gw))
+		return route6_gw(route_info, *pskb);
+
+	if (net_ratelimit()) 
+		DEBUGP(KERN_DEBUG "ip6t_ROUTE: no parameter !\n");
+
+	return IP6T_CONTINUE;
+}
+
+
+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 -Nru ./ROUTE.orig/linux-2.6/net/ipv6/netfilter/Kconfig.ladd ./ROUTE/linux-2.6/net/ipv6/netfilter/Kconfig.ladd
--- ./ROUTE.orig/linux-2.6/net/ipv6/netfilter/Kconfig.ladd	1970-01-01 01:00:00.000000000 +0100
+++ ./ROUTE/linux-2.6/net/ipv6/netfilter/Kconfig.ladd	2004-03-08 15:06:42.000000000 +0100
@@ -0,0 +1,11 @@
+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.
+
diff -Nru ./ROUTE.orig/linux-2.6/net/ipv6/netfilter/Makefile.ladd ./ROUTE/linux-2.6/net/ipv6/netfilter/Makefile.ladd
--- ./ROUTE.orig/linux-2.6/net/ipv6/netfilter/Makefile.ladd	1970-01-01 01:00:00.000000000 +0100
+++ ./ROUTE/linux-2.6/net/ipv6/netfilter/Makefile.ladd	2003-12-20 17:43:09.000000000 +0100
@@ -0,0 +1,2 @@
+obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
+obj-$(CONFIG_IP6_NF_TARGET_ROUTE) += ip6t_ROUTE.o

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] ROUTE target : update to pom-ng + new version for kernel 2.6.x
  2004-04-28 15:25   ` Cedric de Launois
@ 2004-04-29 16:45     ` Patrick McHardy
  0 siblings, 0 replies; 6+ messages in thread
From: Patrick McHardy @ 2004-04-29 16:45 UTC (permalink / raw)
  To: Cedric de Launois; +Cc: Netfilter Development Mailinglist

Cedric de Launois wrote:

>Oops, sorry. This patch should be better.
>  
>
Still can't apply, the patch contains changes to a
non-existing file, linux-2.6/net/ipv4/netfilter/ipt_ROUTE.c.

Regards
Patrick

>Regards,
>
>Cedric
>
>  
>
>diff -Nru ./ROUTE.orig/linux-2.6/net/ipv4/netfilter/ipt_ROUTE.c ./ROUTE/linux-2.6/net/ipv4/netfilter/ipt_ROUTE.c
>--- ./ROUTE.orig/linux-2.6/net/ipv4/netfilter/ipt_ROUTE.c	2004-02-22 18:29:10.000000000 +0100
>+++ ./ROUTE/linux-2.6/net/ipv4/netfilter/ipt_ROUTE.c	2004-04-21 10:17:44.000000000 +0200
>@@ -19,6 +19,7 @@
> #include <net/ip.h>
> #include <net/route.h>
> #include <net/icmp.h>
>+#include <net/checksum.h>
> 
> #if 0
> #define DEBUGP printk
>@@ -28,6 +29,7 @@
> 
>  
>

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2004-04-29 16:45 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-04-21  8:16 [PATCH] ROUTE target : update to pom-ng + new version for kernel 2.6.x Cedric de Launois
2004-04-24 23:03 ` Patrick McHardy
2004-04-25  0:01   ` Esteban Ribicic
2004-04-26  4:46     ` Henrik Nordstrom
2004-04-28 15:25   ` Cedric de Launois
2004-04-29 16:45     ` Patrick McHardy

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.