[netfilter-cvslog] r4006 - in trunk/patch-o-matic-ng: ipsec-01-output-hooks ipsec-02-input-hooks ipsec-03-policy-lookup ipsec-04-policy-checks

laforge at netfilter.org laforge at netfilter.org
Mon Jun 27 10:26:21 CEST 2005


Author: laforge at netfilter.org
Date: 2005-06-27 10:26:20 +0200 (Mon, 27 Jun 2005)
New Revision: 4006

Added:
   trunk/patch-o-matic-ng/ipsec-01-output-hooks/linux-2.6.12.patch
   trunk/patch-o-matic-ng/ipsec-02-input-hooks/linux-2.6.12.patch
   trunk/patch-o-matic-ng/ipsec-03-policy-lookup/linux-2.6.12.patch
   trunk/patch-o-matic-ng/ipsec-04-policy-checks/linux-2.6.12.patch
Log:
add 2.6.12 port by Christophe Saout <christophe at saout.de>


Added: trunk/patch-o-matic-ng/ipsec-01-output-hooks/linux-2.6.12.patch
===================================================================
--- trunk/patch-o-matic-ng/ipsec-01-output-hooks/linux-2.6.12.patch	2005-06-26 12:50:26 UTC (rev 4005)
+++ trunk/patch-o-matic-ng/ipsec-01-output-hooks/linux-2.6.12.patch	2005-06-27 08:26:20 UTC (rev 4006)
@@ -0,0 +1,222 @@
+diff -Nurp linux-2.6.12.orig/include/linux/netfilter.h linux-2.6.12/include/linux/netfilter.h
+--- linux-2.6.12.orig/include/linux/netfilter.h	2005-06-17 21:48:29.000000000 +0200
++++ linux-2.6.12/include/linux/netfilter.h	2005-06-19 18:12:33.000000000 +0200
+@@ -139,9 +139,10 @@ void nf_log_packet(int pf,
+ /* This is gross, but inline doesn't cut it for avoiding the function
+    call in fast path: gcc doesn't inline (needs value tracking?). --RR */
+ #ifdef CONFIG_NETFILTER_DEBUG
+-#define NF_HOOK(pf, hook, skb, indev, outdev, okfn)			       \
++#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond)		       \
+ ({int __ret;								       \
+-if ((__ret=nf_hook_slow(pf, hook, &(skb), indev, outdev, okfn, INT_MIN)) == 1) \
++if (!(cond) ||								       \
++    (__ret=nf_hook_slow(pf, hook, &(skb), indev, outdev, okfn, INT_MIN)) == 1) \
+ 	__ret = (okfn)(skb);						       \
+ __ret;})
+ #define NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, thresh)	       \
+@@ -150,9 +151,9 @@ if ((__ret=nf_hook_slow(pf, hook, &(skb)
+ 	__ret = (okfn)(skb);						       \
+ __ret;})
+ #else
+-#define NF_HOOK(pf, hook, skb, indev, outdev, okfn)			       \
++#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond)		       \
+ ({int __ret;								       \
+-if (list_empty(&nf_hooks[pf][hook]) ||					       \
++if (!(cond) || list_empty(&nf_hooks[pf][hook]) ||					       \
+     (__ret=nf_hook_slow(pf, hook, &(skb), indev, outdev, okfn, INT_MIN)) == 1) \
+ 	__ret = (okfn)(skb);						       \
+ __ret;})
+@@ -163,6 +164,8 @@ if (list_empty(&nf_hooks[pf][hook]) ||		
+ 	__ret = (okfn)(skb);						       \
+ __ret;})
+ #endif
++#define NF_HOOK(pf, hook, skb, indev, outdev, okfn)			\
++ NF_HOOK_COND((pf), (hook), (skb), (indev), (outdev), (okfn), 1)
+ 
+ int nf_hook_slow(int pf, unsigned int hook, struct sk_buff **pskb,
+ 		 struct net_device *indev, struct net_device *outdev,
+@@ -192,6 +195,7 @@ extern void nf_invalidate_cache(int pf);
+ 
+ #else /* !CONFIG_NETFILTER */
+ #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
++#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb)
+ static inline void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) {}
+ #endif /*CONFIG_NETFILTER*/
+ 
+diff -Nurp linux-2.6.12.orig/include/net/ip.h linux-2.6.12/include/net/ip.h
+--- linux-2.6.12.orig/include/net/ip.h	2005-06-17 21:48:29.000000000 +0200
++++ linux-2.6.12/include/net/ip.h	2005-06-19 18:12:33.000000000 +0200
+@@ -30,6 +30,8 @@
+ #include <linux/netdevice.h>
+ #include <linux/inetdevice.h>
+ #include <linux/in_route.h>
++#include <linux/netfilter.h>
++#include <linux/netfilter_ipv4.h>
+ #include <net/route.h>
+ #include <net/arp.h>
+ #include <net/snmp.h>
+@@ -45,6 +47,7 @@ struct inet_skb_parm
+ #define IPSKB_TRANSLATED	2
+ #define IPSKB_FORWARDED		4
+ #define IPSKB_XFRM_TUNNEL_SIZE	8
++#define IPSKB_XFRM_TRANSFORMED	16
+ };
+ 
+ struct ipcm_cookie
+@@ -213,6 +216,16 @@ static inline void ip_select_ident_more(
+ 		__ip_select_ident(iph, dst, more);
+ }
+ 
++#ifdef CONFIG_NETFILTER
++extern int ip_dst_output(struct sk_buff *skb);
++#else
++static inline int ip_dst_output(struct sk_buff *skb)
++{
++	return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
++	                    skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
++}
++#endif
++
+ /*
+  *	Map a multicast IP onto multicast MAC for type ethernet.
+  */
+diff -Nurp linux-2.6.12.orig/net/ipv4/igmp.c linux-2.6.12/net/ipv4/igmp.c
+--- linux-2.6.12.orig/net/ipv4/igmp.c	2005-06-17 21:48:29.000000000 +0200
++++ linux-2.6.12/net/ipv4/igmp.c	2005-06-19 18:12:33.000000000 +0200
+@@ -343,7 +343,7 @@ static int igmpv3_sendpack(struct sk_buf
+ 	pig->csum = ip_compute_csum((void *)skb->h.igmph, igmplen);
+ 
+ 	return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, skb->dev,
+-		       dst_output);
++	               ip_dst_output);
+ }
+ 
+ static int grec_size(struct ip_mc_list *pmc, int type, int gdel, int sdel)
+@@ -674,7 +674,7 @@ static int igmp_send_report(struct in_de
+ 	ih->csum=ip_compute_csum((void *)ih, sizeof(struct igmphdr));
+ 
+ 	return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
+-		       dst_output);
++	               ip_dst_output);
+ }
+ 
+ static void igmp_gq_timer_expire(unsigned long data)
+diff -Nurp linux-2.6.12.orig/net/ipv4/ip_forward.c linux-2.6.12/net/ipv4/ip_forward.c
+--- linux-2.6.12.orig/net/ipv4/ip_forward.c	2005-06-17 21:48:29.000000000 +0200
++++ linux-2.6.12/net/ipv4/ip_forward.c	2005-06-19 18:12:33.000000000 +0200
+@@ -51,7 +51,7 @@ static inline int ip_forward_finish(stru
+ 	if (unlikely(opt->optlen))
+ 		ip_forward_options(skb);
+ 
+-	return dst_output(skb);
++	return ip_dst_output(skb);
+ }
+ 
+ int ip_forward(struct sk_buff *skb)
+diff -Nurp linux-2.6.12.orig/net/ipv4/ipmr.c linux-2.6.12/net/ipv4/ipmr.c
+--- linux-2.6.12.orig/net/ipv4/ipmr.c	2005-06-17 21:48:29.000000000 +0200
++++ linux-2.6.12/net/ipv4/ipmr.c	2005-06-19 18:12:32.000000000 +0200
+@@ -1119,7 +1119,7 @@ static inline int ipmr_forward_finish(st
+ 	if (unlikely(opt->optlen))
+ 		ip_forward_options(skb);
+ 
+-	return dst_output(skb);
++	return ip_dst_output(skb);
+ }
+ 
+ /*
+diff -Nurp linux-2.6.12.orig/net/ipv4/ip_output.c linux-2.6.12/net/ipv4/ip_output.c
+--- linux-2.6.12.orig/net/ipv4/ip_output.c	2005-06-17 21:48:29.000000000 +0200
++++ linux-2.6.12/net/ipv4/ip_output.c	2005-06-19 18:12:33.000000000 +0200
+@@ -125,6 +125,15 @@ static inline int ip_select_ttl(struct i
+ 	return ttl;
+ }
+ 
++#ifdef CONFIG_NETFILTER
++/* out-of-line copy is only required with netfilter */
++int ip_dst_output(struct sk_buff *skb)
++{
++	return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
++	                    skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
++}
++#endif
++
+ /* 
+  *		Add an ip header to a skbuff and send it out.
+  *
+@@ -167,7 +176,7 @@ int ip_build_and_send_pkt(struct sk_buff
+ 
+ 	/* Send it out. */
+ 	return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
+-		       dst_output);
++		       ip_dst_output);
+ }
+ 
+ static inline int ip_finish_output2(struct sk_buff *skb)
+@@ -287,7 +296,7 @@ int ip_mc_output(struct sk_buff *skb)
+ 		return ip_finish_output(skb);
+ }
+ 
+-int ip_output(struct sk_buff *skb)
++static inline int ip_output2(struct sk_buff *skb)
+ {
+ 	IP_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
+ 
+@@ -297,6 +306,16 @@ int ip_output(struct sk_buff *skb)
+ 		return ip_finish_output(skb);
+ }
+ 
++int ip_output(struct sk_buff *skb)
++{
++	int transformed = IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED;
++
++	if (transformed)
++		nf_reset(skb);
++	return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
++	                    skb->dst->dev, ip_output2, transformed);
++}
++
+ int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
+ {
+ 	struct sock *sk = skb->sk;
+@@ -377,7 +396,7 @@ packet_routed:
+ 	skb->priority = sk->sk_priority;
+ 
+ 	return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
+-		       dst_output);
++		       ip_dst_output);
+ 
+ no_route:
+ 	IP_INC_STATS(IPSTATS_MIB_OUTNOROUTES);
+@@ -1201,7 +1220,7 @@ int ip_push_pending_frames(struct sock *
+ 
+ 	/* Netfilter gets whole the not fragmented skb. */
+ 	err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, 
+-		      skb->dst->dev, dst_output);
++		      skb->dst->dev, ip_dst_output);
+ 	if (err) {
+ 		if (err > 0)
+ 			err = inet->recverr ? net_xmit_errno(err) : 0;
+diff -Nurp linux-2.6.12.orig/net/ipv4/raw.c linux-2.6.12/net/ipv4/raw.c
+--- linux-2.6.12.orig/net/ipv4/raw.c	2005-06-17 21:48:29.000000000 +0200
++++ linux-2.6.12/net/ipv4/raw.c	2005-06-19 18:12:32.000000000 +0200
+@@ -310,7 +310,7 @@ static int raw_send_hdrinc(struct sock *
+ 	}
+ 
+ 	err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
+-		      dst_output);
++	              ip_dst_output);
+ 	if (err > 0)
+ 		err = inet->recverr ? net_xmit_errno(err) : 0;
+ 	if (err)
+diff -Nurp linux-2.6.12.orig/net/ipv4/xfrm4_output.c linux-2.6.12/net/ipv4/xfrm4_output.c
+--- linux-2.6.12.orig/net/ipv4/xfrm4_output.c	2005-06-17 21:48:29.000000000 +0200
++++ linux-2.6.12/net/ipv4/xfrm4_output.c	2005-06-19 18:12:32.000000000 +0200
+@@ -129,6 +129,7 @@ int xfrm4_output(struct sk_buff *skb)
+ 		err = -EHOSTUNREACH;
+ 		goto error_nolock;
+ 	}
++	IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
+ 	err = NET_XMIT_BYPASS;
+ 
+ out_exit:

Added: trunk/patch-o-matic-ng/ipsec-02-input-hooks/linux-2.6.12.patch
===================================================================
--- trunk/patch-o-matic-ng/ipsec-02-input-hooks/linux-2.6.12.patch	2005-06-26 12:50:26 UTC (rev 4005)
+++ trunk/patch-o-matic-ng/ipsec-02-input-hooks/linux-2.6.12.patch	2005-06-27 08:26:20 UTC (rev 4006)
@@ -0,0 +1,268 @@
+diff -Nurp linux-2.6.12.orig/include/linux/netfilter_ipv4.h linux-2.6.12/include/linux/netfilter_ipv4.h
+--- linux-2.6.12.orig/include/linux/netfilter_ipv4.h	2005-06-17 21:48:29.000000000 +0200
++++ linux-2.6.12/include/linux/netfilter_ipv4.h	2005-06-19 18:17:34.000000000 +0200
+@@ -7,6 +7,8 @@
+ 
+ #include <linux/config.h>
+ #include <linux/netfilter.h>
++#include <linux/netdevice.h>
++#include <net/protocol.h>
+ 
+ /* IP Cache bits. */
+ /* Src IP address. */
+@@ -88,6 +90,58 @@ extern int ip_route_me_harder(struct sk_
+    Returns true or false. */
+ extern int skb_ip_make_writable(struct sk_buff **pskb,
+ 				unsigned int writable_len);
++
++#if defined(CONFIG_XFRM) && defined(CONFIG_NETFILTER)
++#include <net/route.h>
++#include <net/xfrm.h>
++
++static inline int nf_hook_input_cond(struct sk_buff *skb)
++{
++	return !skb->sp || skb->sp->decap_done;
++}
++
++static inline int
++nf_xfrm_local_done(struct sk_buff *skb, struct net_protocol *ipprot)
++{
++	return skb->sp && !skb->sp->decap_done
++	       && (!ipprot || !ipprot->xfrm_prot);
++}
++
++static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
++{
++	return skb->sp && !skb->sp->decap_done
++	       && !(((struct rtable *)skb->dst)->rt_flags & RTCF_LOCAL);
++}
++
++extern int nf_rcv_postxfrm_local(struct sk_buff *skb);
++extern int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb);
++#else /* CONFIG_XFRM */
++static inline int nf_hook_input_cond(struct sk_buff *skb)
++{
++	return 1;
++}
++
++static inline int
++nf_xfrm_local_done(struct sk_buff *skb, struct net_protocol *ipprot)
++{
++	return 0;
++}
++
++static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
++{
++	return 0;
++}
++
++static inline int nf_rcv_postxfrm_local(struct sk_buff *skb)
++{
++	return 0;
++}
++
++static inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
++{
++	return 0; 
++}
++#endif /* CONFIG_XFRM */
+ #endif /*__KERNEL__*/
+ 
+ #endif /*__LINUX_IP_NETFILTER_H*/
+diff -Nurp linux-2.6.12.orig/include/net/protocol.h linux-2.6.12/include/net/protocol.h
+--- linux-2.6.12.orig/include/net/protocol.h	2005-06-17 21:48:29.000000000 +0200
++++ linux-2.6.12/include/net/protocol.h	2005-06-19 18:17:34.000000000 +0200
+@@ -38,6 +38,7 @@ struct net_protocol {
+ 	int			(*handler)(struct sk_buff *skb);
+ 	void			(*err_handler)(struct sk_buff *skb, u32 info);
+ 	int			no_policy;
++	int			xfrm_prot;
+ };
+ 
+ #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+diff -Nurp linux-2.6.12.orig/include/net/xfrm.h linux-2.6.12/include/net/xfrm.h
+--- linux-2.6.12.orig/include/net/xfrm.h	2005-06-17 21:48:29.000000000 +0200
++++ linux-2.6.12/include/net/xfrm.h	2005-06-19 18:17:34.000000000 +0200
+@@ -546,6 +546,9 @@ struct sec_path
+ {
+ 	atomic_t		refcnt;
+ 	int			len;
++#ifdef CONFIG_NETFILTER
++	int			decap_done;
++#endif
+ 	struct sec_decap_state	x[XFRM_MAX_DEPTH];
+ };
+ 
+diff -Nurp linux-2.6.12.orig/net/core/netfilter.c linux-2.6.12/net/core/netfilter.c
+--- linux-2.6.12.orig/net/core/netfilter.c	2005-06-17 21:48:29.000000000 +0200
++++ linux-2.6.12/net/core/netfilter.c	2005-06-19 18:17:34.000000000 +0200
+@@ -27,6 +27,7 @@
+ #include <linux/icmp.h>
+ #include <net/sock.h>
+ #include <net/route.h>
++#include <net/xfrm.h>
+ #include <linux/ip.h>
+ 
+ /* In this code, we can be waiting indefinitely for userspace to
+@@ -651,6 +652,27 @@ int ip_route_me_harder(struct sk_buff **
+ }
+ EXPORT_SYMBOL(ip_route_me_harder);
+ 
++#ifdef CONFIG_XFRM
++inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
++{
++	skb->sp->decap_done = 1;
++	dst_release(skb->dst);
++	skb->dst = NULL;
++	nf_reset(skb);
++	return netif_rx(skb);
++}
++
++int nf_rcv_postxfrm_local(struct sk_buff *skb)
++{
++	__skb_push(skb, skb->data - skb->nh.raw);
++	/* Fix header len and checksum if last xfrm was transport mode */
++	if (!skb->sp->x[skb->sp->len - 1].xvec->props.mode) {
++		skb->nh.iph->tot_len = htons(skb->len);
++		ip_send_check(skb->nh.iph);
++	}
++	return nf_rcv_postxfrm_nonlocal(skb);
++}
++ 
+ int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len)
+ {
+ 	struct sk_buff *nskb;
+@@ -784,3 +806,4 @@ EXPORT_SYMBOL(nf_setsockopt);
+ EXPORT_SYMBOL(nf_unregister_hook);
+ EXPORT_SYMBOL(nf_unregister_queue_handler);
+ EXPORT_SYMBOL(nf_unregister_sockopt);
++EXPORT_SYMBOL(nf_rcv_postxfrm_local);
+diff -Nurp linux-2.6.12.orig/net/ipv4/ah4.c linux-2.6.12/net/ipv4/ah4.c
+--- linux-2.6.12.orig/net/ipv4/ah4.c	2005-06-17 21:48:29.000000000 +0200
++++ linux-2.6.12/net/ipv4/ah4.c	2005-06-19 18:17:34.000000000 +0200
+@@ -306,6 +306,7 @@ static struct net_protocol ah4_protocol 
+ 	.handler	=	xfrm4_rcv,
+ 	.err_handler	=	ah4_err,
+ 	.no_policy	=	1,
++	.xfrm_prot	=	1,
+ };
+ 
+ static int __init ah4_init(void)
+diff -Nurp linux-2.6.12.orig/net/ipv4/esp4.c linux-2.6.12/net/ipv4/esp4.c
+--- linux-2.6.12.orig/net/ipv4/esp4.c	2005-06-17 21:48:29.000000000 +0200
++++ linux-2.6.12/net/ipv4/esp4.c	2005-06-19 18:17:34.000000000 +0200
+@@ -472,6 +472,7 @@ static struct net_protocol esp4_protocol
+ 	.handler	=	xfrm4_rcv,
+ 	.err_handler	=	esp4_err,
+ 	.no_policy	=	1,
++	.xfrm_prot	=	1,
+ };
+ 
+ static int __init esp4_init(void)
+diff -Nurp linux-2.6.12.orig/net/ipv4/ipcomp.c linux-2.6.12/net/ipv4/ipcomp.c
+--- linux-2.6.12.orig/net/ipv4/ipcomp.c	2005-06-17 21:48:29.000000000 +0200
++++ linux-2.6.12/net/ipv4/ipcomp.c	2005-06-19 18:17:34.000000000 +0200
+@@ -491,6 +491,7 @@ static struct net_protocol ipcomp4_proto
+ 	.handler	=	xfrm4_rcv,
+ 	.err_handler	=	ipcomp4_err,
+ 	.no_policy	=	1,
++	.xfrm_prot	=	1,
+ };
+ 
+ static int __init ipcomp4_init(void)
+diff -Nurp linux-2.6.12.orig/net/ipv4/ip_input.c linux-2.6.12/net/ipv4/ip_input.c
+--- linux-2.6.12.orig/net/ipv4/ip_input.c	2005-06-17 21:48:29.000000000 +0200
++++ linux-2.6.12/net/ipv4/ip_input.c	2005-06-19 18:17:34.000000000 +0200
+@@ -224,6 +224,12 @@ static inline int ip_local_deliver_finis
+ 	resubmit:
+ 		hash = protocol & (MAX_INET_PROTOS - 1);
+ 		raw_sk = sk_head(&raw_v4_htable[hash]);
++		ipprot = rcu_dereference(inet_protos[hash]);
++
++		if (nf_xfrm_local_done(skb, ipprot)) {
++			nf_rcv_postxfrm_local(skb);
++			goto out;
++		}
+ 
+ 		/* If there maybe a raw socket we must check - if not we
+ 		 * don't care less
+@@ -231,7 +237,7 @@ static inline int ip_local_deliver_finis
+ 		if (raw_sk)
+ 			raw_v4_input(skb, skb->nh.iph, hash);
+ 
+-		if ((ipprot = rcu_dereference(inet_protos[hash])) != NULL) {
++		if (ipprot != NULL) {
+ 			int ret;
+ 
+ 			if (!ipprot->no_policy &&
+@@ -278,8 +284,8 @@ int ip_local_deliver(struct sk_buff *skb
+ 			return 0;
+ 	}
+ 
+-	return NF_HOOK(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
+-		       ip_local_deliver_finish);
++	return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
++	                    ip_local_deliver_finish, nf_hook_input_cond(skb));
+ }
+ 
+ static inline int ip_rcv_finish(struct sk_buff *skb)
+@@ -296,6 +302,9 @@ static inline int ip_rcv_finish(struct s
+ 			goto drop; 
+ 	}
+ 
++	if (nf_xfrm_nonlocal_done(skb))
++		return nf_rcv_postxfrm_nonlocal(skb);
++
+ #ifdef CONFIG_NET_CLS_ROUTE
+ 	if (skb->dst->tclassid) {
+ 		struct ip_rt_acct *st = ip_rt_acct + 256*smp_processor_id();
+@@ -416,8 +425,8 @@ int ip_rcv(struct sk_buff *skb, struct n
+ 		}
+ 	}
+ 
+-	return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
+-		       ip_rcv_finish);
++	return NF_HOOK_COND(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
++	                    ip_rcv_finish, nf_hook_input_cond(skb));
+ 
+ inhdr_error:
+ 	IP_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+diff -Nurp linux-2.6.12.orig/net/ipv4/ipip.c linux-2.6.12/net/ipv4/ipip.c
+--- linux-2.6.12.orig/net/ipv4/ipip.c	2005-06-17 21:48:29.000000000 +0200
++++ linux-2.6.12/net/ipv4/ipip.c	2005-06-19 18:17:34.000000000 +0200
+@@ -476,6 +476,11 @@ static int ipip_rcv(struct sk_buff *skb)
+ 
+ 	read_lock(&ipip_lock);
+ 	if ((tunnel = ipip_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) {
++		/* IPIP packets decapsulated by IPsec missed netfilter hooks */
++		if (nf_xfrm_local_done(skb, NULL)) {
++			nf_rcv_postxfrm_local(skb);
++			return 0;
++		}
+ 		if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
+ 			read_unlock(&ipip_lock);
+ 			kfree_skb(skb);
+diff -Nurp linux-2.6.12.orig/net/ipv4/xfrm4_tunnel.c linux-2.6.12/net/ipv4/xfrm4_tunnel.c
+--- linux-2.6.12.orig/net/ipv4/xfrm4_tunnel.c	2005-06-17 21:48:29.000000000 +0200
++++ linux-2.6.12/net/ipv4/xfrm4_tunnel.c	2005-06-19 18:17:34.000000000 +0200
+@@ -115,6 +115,7 @@ static struct net_protocol ipip_protocol
+ 	.handler	=	ipip_rcv,
+ 	.err_handler	=	ipip_err,
+ 	.no_policy	=	1,
++	.xfrm_prot	=	1,
+ };
+ 
+ static int __init ipip_init(void)
+diff -Nurp linux-2.6.12.orig/net/xfrm/xfrm_input.c linux-2.6.12/net/xfrm/xfrm_input.c
+--- linux-2.6.12.orig/net/xfrm/xfrm_input.c	2005-06-17 21:48:29.000000000 +0200
++++ linux-2.6.12/net/xfrm/xfrm_input.c	2005-06-19 18:17:34.000000000 +0200
+@@ -31,6 +31,9 @@ struct sec_path *secpath_dup(struct sec_
+ 	if (!sp)
+ 		return NULL;
+ 
++#ifdef CONFIG_NETFILTER
++	sp->decap_done = 0;
++#endif
+ 	sp->len = 0;
+ 	if (src) {
+ 		int i;

Added: trunk/patch-o-matic-ng/ipsec-03-policy-lookup/linux-2.6.12.patch
===================================================================
--- trunk/patch-o-matic-ng/ipsec-03-policy-lookup/linux-2.6.12.patch	2005-06-26 12:50:26 UTC (rev 4005)
+++ trunk/patch-o-matic-ng/ipsec-03-policy-lookup/linux-2.6.12.patch	2005-06-27 08:26:20 UTC (rev 4006)
@@ -0,0 +1,173 @@
+diff -Nurp linux-2.6.12.orig/net/core/netfilter.c linux-2.6.12/net/core/netfilter.c
+--- linux-2.6.12.orig/net/core/netfilter.c	2005-06-19 18:22:57.000000000 +0200
++++ linux-2.6.12/net/core/netfilter.c	2005-06-19 18:23:03.000000000 +0200
+@@ -28,6 +28,7 @@
+ #include <net/sock.h>
+ #include <net/route.h>
+ #include <net/xfrm.h>
++#include <net/ip.h>
+ #include <linux/ip.h>
+ 
+ /* In this code, we can be waiting indefinitely for userspace to
+@@ -607,7 +608,6 @@ int ip_route_me_harder(struct sk_buff **
+ #ifdef CONFIG_IP_ROUTE_FWMARK
+ 		fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark;
+ #endif
+-		fl.proto = iph->protocol;
+ 		if (ip_route_output_key(&rt, &fl) != 0)
+ 			return -1;
+ 
+@@ -634,6 +634,20 @@ int ip_route_me_harder(struct sk_buff **
+ 	if ((*pskb)->dst->error)
+ 		return -1;
+ 
++#ifdef CONFIG_XFRM
++	if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED)) {
++		struct xfrm_policy_afinfo *afinfo;
++
++		afinfo = xfrm_policy_get_afinfo(AF_INET);
++		if (afinfo != NULL) {
++			afinfo->decode_session(*pskb, &fl);
++			xfrm_policy_put_afinfo(afinfo);
++			if (xfrm_lookup(&(*pskb)->dst, &fl, (*pskb)->sk, 0) != 0)
++				return -1;
++		}
++	}
++#endif
++
+ 	/* Change in oif may mean change in hh_len. */
+ 	hh_len = (*pskb)->dst->dev->hard_header_len;
+ 	if (skb_headroom(*pskb) < hh_len) {
+diff -Nurp linux-2.6.12.orig/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.6.12/net/ipv4/netfilter/ip_conntrack_standalone.c
+--- linux-2.6.12.orig/net/ipv4/netfilter/ip_conntrack_standalone.c	2005-06-17 21:48:29.000000000 +0200
++++ linux-2.6.12/net/ipv4/netfilter/ip_conntrack_standalone.c	2005-06-19 18:23:03.000000000 +0200
+@@ -970,6 +970,7 @@ EXPORT_SYMBOL(ip_ct_get_tuple);
+ EXPORT_SYMBOL(invert_tuplepr);
+ EXPORT_SYMBOL(ip_conntrack_alter_reply);
+ EXPORT_SYMBOL(ip_conntrack_destroyed);
++EXPORT_SYMBOL(__ip_conntrack_confirm);
+ EXPORT_SYMBOL(need_ip_conntrack);
+ EXPORT_SYMBOL(ip_conntrack_helper_register);
+ EXPORT_SYMBOL(ip_conntrack_helper_unregister);
+diff -Nurp linux-2.6.12.orig/net/ipv4/netfilter/ip_nat_standalone.c linux-2.6.12/net/ipv4/netfilter/ip_nat_standalone.c
+--- linux-2.6.12.orig/net/ipv4/netfilter/ip_nat_standalone.c	2005-06-17 21:48:29.000000000 +0200
++++ linux-2.6.12/net/ipv4/netfilter/ip_nat_standalone.c	2005-06-19 18:23:03.000000000 +0200
+@@ -172,6 +172,47 @@ ip_nat_in(unsigned int hooknum,
+ 	return ret;
+ }
+ 
++struct nat_route_key
++{
++	u_int32_t addr;
++#ifdef CONFIG_XFRM
++	u_int16_t port;
++#endif
++};
++
++static inline void
++nat_route_key_get(struct sk_buff *skb, struct nat_route_key *key, int which)
++{
++	struct iphdr *iph = skb->nh.iph;
++
++	key->addr = which ? iph->daddr : iph->saddr;
++#ifdef CONFIG_XFRM
++	key->port = 0;
++	if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) {
++		u_int16_t *ports = (u_int16_t *)(skb->nh.raw + iph->ihl*4);
++		key->port = ports[which];
++	}
++#endif
++}
++
++static inline int
++nat_route_key_compare(struct sk_buff *skb, struct nat_route_key *key, int which)
++{
++	struct iphdr *iph = skb->nh.iph;
++
++	if (key->addr != (which ? iph->daddr : iph->saddr))
++		return 1;
++#ifdef CONFIG_XFRM
++	if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) {
++		u_int16_t *ports = (u_int16_t *)(skb->nh.raw + iph->ihl*4);
++		if (key->port != ports[which])
++			return 1;
++	}
++#endif
++
++	return 0;
++}
++
+ static unsigned int
+ ip_nat_out(unsigned int hooknum,
+ 	   struct sk_buff **pskb,
+@@ -179,6 +220,9 @@ ip_nat_out(unsigned int hooknum,
+ 	   const struct net_device *out,
+ 	   int (*okfn)(struct sk_buff *))
+ {
++	struct nat_route_key key;
++	unsigned int ret;
++
+ 	/* root is playing with raw sockets. */
+ 	if ((*pskb)->len < sizeof(struct iphdr)
+ 	    || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
+@@ -201,7 +245,29 @@ ip_nat_out(unsigned int hooknum,
+ 			return NF_STOLEN;
+ 	}
+ 
+-	return ip_nat_fn(hooknum, pskb, in, out, okfn);
++	nat_route_key_get(*pskb, &key, 0);
++	ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
++
++	if (ret != NF_DROP && ret != NF_STOLEN
++	    && nat_route_key_compare(*pskb, &key, 0)) {
++		if (ip_route_me_harder(pskb) != 0)
++			ret = NF_DROP;
++#ifdef CONFIG_XFRM
++		/*
++		 * POST_ROUTING hook is called with fixed outfn, we need
++		 * to manually confirm the packet and direct it to the
++		 * transformers if a policy matches.
++		 */
++		else if ((*pskb)->dst->xfrm != NULL) {
++			ret = ip_conntrack_confirm(pskb);
++			if (ret != NF_DROP) {
++				dst_output(*pskb);
++				ret = NF_STOLEN;
++			}
++		}
++#endif
++	}
++	return ret;
+ }
+ 
+ static unsigned int
+@@ -211,7 +277,7 @@ ip_nat_local_fn(unsigned int hooknum,
+ 		const struct net_device *out,
+ 		int (*okfn)(struct sk_buff *))
+ {
+-	u_int32_t saddr, daddr;
++	struct nat_route_key key;
+ 	unsigned int ret;
+ 
+ 	/* root is playing with raw sockets. */
+@@ -219,14 +285,14 @@ ip_nat_local_fn(unsigned int hooknum,
+ 	    || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
+ 		return NF_ACCEPT;
+ 
+-	saddr = (*pskb)->nh.iph->saddr;
+-	daddr = (*pskb)->nh.iph->daddr;
+-
++	nat_route_key_get(*pskb, &key, 1);
+ 	ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
++
+ 	if (ret != NF_DROP && ret != NF_STOLEN
+-	    && ((*pskb)->nh.iph->saddr != saddr
+-		|| (*pskb)->nh.iph->daddr != daddr))
+-		return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
++	    && nat_route_key_compare(*pskb, &key, 1)) {
++		if (ip_route_me_harder(pskb) != 0)
++			ret = NF_DROP;
++	}
+ 	return ret;
+ }
+ 

Added: trunk/patch-o-matic-ng/ipsec-04-policy-checks/linux-2.6.12.patch
===================================================================
--- trunk/patch-o-matic-ng/ipsec-04-policy-checks/linux-2.6.12.patch	2005-06-26 12:50:26 UTC (rev 4005)
+++ trunk/patch-o-matic-ng/ipsec-04-policy-checks/linux-2.6.12.patch	2005-06-27 08:26:20 UTC (rev 4006)
@@ -0,0 +1,209 @@
+diff -Nurp linux-2.6.12.orig/include/linux/netfilter.h linux-2.6.12/include/linux/netfilter.h
+--- linux-2.6.12.orig/include/linux/netfilter.h	2005-06-19 18:17:27.000000000 +0200
++++ linux-2.6.12/include/linux/netfilter.h	2005-06-19 18:28:33.000000000 +0200
+@@ -199,5 +199,21 @@ extern void nf_invalidate_cache(int pf);
+ static inline void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) {}
+ #endif /*CONFIG_NETFILTER*/
+ 
++#ifdef CONFIG_XFRM
++#ifdef CONFIG_IP_NF_NAT_NEEDED
++struct flowi;
++extern void nf_nat_decode_session4(struct sk_buff *skb, struct flowi *fl);
++
++static inline void
++nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, int family)
++{
++	if (family == AF_INET)
++		nf_nat_decode_session4(skb, fl);
++}
++#else /* CONFIG_IP_NF_NAT_NEEDED */
++#define nf_nat_decode_session(skb,fl,family)
++#endif /* CONFIG_IP_NF_NAT_NEEDED */
++#endif /* CONFIG_XFRM */
++
+ #endif /*__KERNEL__*/
+ #endif /*__LINUX_NETFILTER_H*/
+diff -Nurp linux-2.6.12.orig/include/net/xfrm.h linux-2.6.12/include/net/xfrm.h
+--- linux-2.6.12.orig/include/net/xfrm.h	2005-06-19 18:22:57.000000000 +0200
++++ linux-2.6.12/include/net/xfrm.h	2005-06-19 18:28:33.000000000 +0200
+@@ -179,6 +179,8 @@ struct xfrm_policy_afinfo {
+ 
+ extern int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo);
+ extern int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo);
++extern struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family);
++extern void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo);
+ 
+ #define XFRM_ACQ_EXPIRES	30
+ 
+diff -Nurp linux-2.6.12.orig/net/core/netfilter.c linux-2.6.12/net/core/netfilter.c
+--- linux-2.6.12.orig/net/core/netfilter.c	2005-06-19 18:28:27.000000000 +0200
++++ linux-2.6.12/net/core/netfilter.c	2005-06-19 18:28:33.000000000 +0200
+@@ -687,6 +687,48 @@ int nf_rcv_postxfrm_local(struct sk_buff
+ 	return nf_rcv_postxfrm_nonlocal(skb);
+ }
+  
++#ifdef CONFIG_IP_NF_NAT_NEEDED
++#include <linux/netfilter_ipv4/ip_conntrack.h>
++#include <linux/netfilter_ipv4/ip_nat.h>
++
++void nf_nat_decode_session4(struct sk_buff *skb, struct flowi *fl)
++{
++	struct ip_conntrack *ct;
++	struct ip_conntrack_tuple *t;
++	enum ip_conntrack_info ctinfo;
++	enum ip_conntrack_dir dir;
++	int known_proto;
++	int statusbit;
++
++	ct = ip_conntrack_get(skb, &ctinfo);
++	if (ct == NULL || !(ct->status & IPS_NAT_MASK))
++		return;
++
++	dir = CTINFO2DIR(ctinfo);
++	t = &ct->tuplehash[dir].tuple;
++	known_proto = t->dst.protonum == IPPROTO_TCP ||
++	              t->dst.protonum == IPPROTO_UDP;
++
++	if (dir == IP_CT_DIR_REPLY)
++		statusbit = IPS_SRC_NAT;
++	else
++		statusbit = IPS_DST_NAT;
++	if (ct->status & statusbit) {
++		fl->fl4_dst = t->dst.ip;
++		if (known_proto)
++			fl->fl_ip_dport = t->dst.u.tcp.port;
++	}
++
++	statusbit ^= IPS_NAT_MASK;
++	if (ct->status & statusbit) {
++		fl->fl4_src = t->src.ip;
++		if (known_proto)
++			fl->fl_ip_sport = t->src.u.tcp.port;
++	}
++}
++#endif /* CONFIG_IP_NF_NAT_NEEDED */
++#endif
++
+ int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len)
+ {
+ 	struct sk_buff *nskb;
+diff -Nurp linux-2.6.12.orig/net/ipv4/ip_input.c linux-2.6.12/net/ipv4/ip_input.c
+--- linux-2.6.12.orig/net/ipv4/ip_input.c	2005-06-19 18:22:57.000000000 +0200
++++ linux-2.6.12/net/ipv4/ip_input.c	2005-06-19 18:28:33.000000000 +0200
+@@ -206,10 +206,6 @@ static inline int ip_local_deliver_finis
+ 
+ 	__skb_pull(skb, ihl);
+ 
+-	/* Free reference early: we don't need it any more, and it may
+-           hold ip_conntrack module loaded indefinitely. */
+-	nf_reset(skb);
+-
+         /* Point into the IP datagram, just past the header. */
+         skb->h.raw = skb->data;
+ 
+@@ -240,10 +236,12 @@ static inline int ip_local_deliver_finis
+ 		if (ipprot != NULL) {
+ 			int ret;
+ 
+-			if (!ipprot->no_policy &&
+-			    !xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
+-				kfree_skb(skb);
+-				goto out;
++			if (!ipprot->no_policy) {
++				if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
++					kfree_skb(skb);
++					goto out;
++				}
++				nf_reset(skb);
+ 			}
+ 			ret = ipprot->handler(skb);
+ 			if (ret < 0) {
+diff -Nurp linux-2.6.12.orig/net/ipv4/raw.c linux-2.6.12/net/ipv4/raw.c
+--- linux-2.6.12.orig/net/ipv4/raw.c	2005-06-19 18:17:27.000000000 +0200
++++ linux-2.6.12/net/ipv4/raw.c	2005-06-19 18:28:33.000000000 +0200
+@@ -252,6 +252,7 @@ int raw_rcv(struct sock *sk, struct sk_b
+ 		kfree_skb(skb);
+ 		return NET_RX_DROP;
+ 	}
++	nf_reset(skb);
+ 
+ 	skb_push(skb, skb->data - skb->nh.raw);
+ 
+diff -Nurp linux-2.6.12.orig/net/ipv4/tcp_ipv4.c linux-2.6.12/net/ipv4/tcp_ipv4.c
+--- linux-2.6.12.orig/net/ipv4/tcp_ipv4.c	2005-06-17 21:48:29.000000000 +0200
++++ linux-2.6.12/net/ipv4/tcp_ipv4.c	2005-06-19 18:28:33.000000000 +0200
+@@ -1772,6 +1772,7 @@ process:
+ 
+ 	if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
+ 		goto discard_and_relse;
++	nf_reset(skb);
+ 
+ 	if (sk_filter(sk, skb, 0))
+ 		goto discard_and_relse;
+diff -Nurp linux-2.6.12.orig/net/ipv4/udp.c linux-2.6.12/net/ipv4/udp.c
+--- linux-2.6.12.orig/net/ipv4/udp.c	2005-06-17 21:48:29.000000000 +0200
++++ linux-2.6.12/net/ipv4/udp.c	2005-06-19 18:28:33.000000000 +0200
+@@ -1000,6 +1000,7 @@ static int udp_queue_rcv_skb(struct sock
+ 		kfree_skb(skb);
+ 		return -1;
+ 	}
++	nf_reset(skb);
+ 
+ 	if (up->encap_type) {
+ 		/*
+@@ -1165,6 +1166,7 @@ int udp_rcv(struct sk_buff *skb)
+ 
+ 	if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
+ 		goto drop;
++	nf_reset(skb);
+ 
+ 	/* No socket. Drop packet silently, if checksum is wrong */
+ 	if (udp_checksum_complete(skb))
+diff -Nurp linux-2.6.12.orig/net/xfrm/xfrm_policy.c linux-2.6.12/net/xfrm/xfrm_policy.c
+--- linux-2.6.12.orig/net/xfrm/xfrm_policy.c	2005-06-17 21:48:29.000000000 +0200
++++ linux-2.6.12/net/xfrm/xfrm_policy.c	2005-06-19 18:28:33.000000000 +0200
+@@ -22,6 +22,7 @@
+ #include <linux/workqueue.h>
+ #include <linux/notifier.h>
+ #include <linux/netdevice.h>
++#include <linux/netfilter.h>
+ #include <linux/module.h>
+ #include <net/xfrm.h>
+ #include <net/ip.h>
+@@ -44,8 +45,8 @@ static struct list_head xfrm_policy_gc_l
+ 	LIST_HEAD_INIT(xfrm_policy_gc_list);
+ static DEFINE_SPINLOCK(xfrm_policy_gc_lock);
+ 
+-static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family);
+-static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo);
++struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family);
++void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo);
+ 
+ int xfrm_register_type(struct xfrm_type *type, unsigned short family)
+ {
+@@ -936,6 +937,7 @@ int __xfrm_policy_check(struct sock *sk,
+ 
+ 	if (_decode_session(skb, &fl, family) < 0)
+ 		return 0;
++	nf_nat_decode_session(skb, &fl, family);
+ 
+ 	/* First, check used SA against their selectors. */
+ 	if (skb->sp) {
+@@ -1289,7 +1291,7 @@ int xfrm_policy_unregister_afinfo(struct
+ }
+ EXPORT_SYMBOL(xfrm_policy_unregister_afinfo);
+ 
+-static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family)
++struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family)
+ {
+ 	struct xfrm_policy_afinfo *afinfo;
+ 	if (unlikely(family >= NPROTO))
+@@ -1302,7 +1304,7 @@ static struct xfrm_policy_afinfo *xfrm_p
+ 	return afinfo;
+ }
+ 
+-static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo)
++void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo)
+ {
+ 	if (unlikely(afinfo == NULL))
+ 		return;




More information about the netfilter-cvslog mailing list