* [PATCH 0/4] Updated IPSEC NAT patches for 2.6.11
@ 2005-02-17 19:08 Christophe Saout
2005-02-17 19:10 ` [PATCH 1/4] IPSEC output hooks Christophe Saout
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Christophe Saout @ 2005-02-17 19:08 UTC (permalink / raw)
To: netfilter-devel
[-- Attachment #1: Type: text/plain, Size: 552 bytes --]
Hi,
I've forward-ported Patrick McHardy's patches that make the kernel IPSEC
work with NAT.
Since there probably won't be any more big changes between 2.6.11-rc4
and the final 2.6.11 I'm posting them now.
The biggest change is in the last patch (ipsec-04-policy-checks.diff). I
needed to rewrite nf_nat_decode_session4 due to the big NAT changes. I
hope I got everything right. I couldn't find a situation where it
failed.
I also added a missing return in nat_route_key_compare that made the
kernel fail with certain compiler flags.
[-- Attachment #2: Dies ist ein digital signierter Nachrichtenteil --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/4] IPSEC output hooks
2005-02-17 19:08 [PATCH 0/4] Updated IPSEC NAT patches for 2.6.11 Christophe Saout
@ 2005-02-17 19:10 ` Christophe Saout
2005-02-17 19:11 ` [PATCH 2/4] IPSEC input hooks Christophe Saout
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Christophe Saout @ 2005-02-17 19:10 UTC (permalink / raw)
To: netfilter-devel
Updated ipsec-01-output-hooks.diff
--- linux-2.6.11-rc4/net/ipv4/xfrm4_output.c 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/net/ipv4/xfrm4_output.c 2005-02-17 18:07:38.357656232 +0100
@@ -129,6 +129,7 @@
err = -EHOSTUNREACH;
goto error_nolock;
}
+ IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
err = NET_XMIT_BYPASS;
out_exit:
--- linux-2.6.11-rc4/net/ipv4/raw.c 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/net/ipv4/raw.c 2005-02-17 18:07:21.314247224 +0100
@@ -310,7 +310,7 @@
}
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)
--- linux-2.6.11-rc4/net/ipv4/ipmr.c 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/net/ipv4/ipmr.c 2005-02-17 18:05:59.814637048 +0100
@@ -1119,7 +1119,7 @@
if (unlikely(opt->optlen))
ip_forward_options(skb);
- return dst_output(skb);
+ return ip_dst_output(skb);
}
/*
--- linux-2.6.11-rc4/net/ipv4/ip_output.c 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/net/ipv4/ip_output.c 2005-02-17 18:06:29.153176912 +0100
@@ -124,6 +124,15 @@
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.
*
@@ -166,7 +175,7 @@
/* 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)
@@ -284,7 +293,7 @@
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);
@@ -294,6 +303,16 @@
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;
@@ -374,7 +393,7 @@
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);
@@ -1189,7 +1208,7 @@
/* 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;
--- linux-2.6.11-rc4/net/ipv4/ip_forward.c 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/net/ipv4/ip_forward.c 2005-02-17 18:05:39.617707448 +0100
@@ -51,7 +51,7 @@
if (unlikely(opt->optlen))
ip_forward_options(skb);
- return dst_output(skb);
+ return ip_dst_output(skb);
}
int ip_forward(struct sk_buff *skb)
--- linux-2.6.11-rc4/net/ipv4/igmp.c 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/net/ipv4/igmp.c 2005-02-17 18:05:38.713844856 +0100
@@ -343,7 +343,7 @@
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 @@
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)
--- linux-2.6.11-rc4/include/net/ip.h 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/include/net/ip.h 2005-02-17 18:04:59.112627968 +0100
@@ -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 @@
#define IPSKB_TRANSLATED 2
#define IPSKB_FORWARDED 4
#define IPSKB_XFRM_TUNNEL_SIZE 8
+#define IPSKB_XFRM_TRANSFORMED 16
};
struct ipcm_cookie
@@ -212,6 +215,16 @@
__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.
*/
--- linux-2.6.11-rc4/include/linux/netfilter.h 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/include/linux/netfilter.h 2005-02-17 18:04:16.640084776 +0100
@@ -138,12 +138,14 @@
/* 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) \
- nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN)
+#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) \
+(!(cond) \
+ ? (okfn)(skb) \
+ : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN))
#define NF_HOOK_THRESH nf_hook_slow
#else
-#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) \
-(list_empty(&nf_hooks[(pf)][(hook)]) \
+#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) \
+(!(cond) || list_empty(&nf_hooks[(pf)][(hook)]) \
? (okfn)(skb) \
: nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN))
#define NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, thresh) \
@@ -151,6 +153,8 @@
? (okfn)(skb) \
: nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), (thresh)))
#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 *skb,
struct net_device *indev, struct net_device *outdev,
@@ -180,6 +184,7 @@
#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*/
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 2/4] IPSEC input hooks
2005-02-17 19:08 [PATCH 0/4] Updated IPSEC NAT patches for 2.6.11 Christophe Saout
2005-02-17 19:10 ` [PATCH 1/4] IPSEC output hooks Christophe Saout
@ 2005-02-17 19:11 ` Christophe Saout
2005-02-17 19:12 ` [PATCH 3/4] IPSEC policy lookups Christophe Saout
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Christophe Saout @ 2005-02-17 19:11 UTC (permalink / raw)
To: netfilter-devel
The updated ipsec-02-input-hooks.diff
--- linux-2.6.11-rc4/net/xfrm/xfrm_input.c 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/net/xfrm/xfrm_input.c 2005-02-17 18:15:38.728620048 +0100
@@ -31,6 +31,9 @@
if (!sp)
return NULL;
+#ifdef CONFIG_NETFILTER
+ sp->decap_done = 0;
+#endif
sp->len = 0;
if (src) {
int i;
--- linux-2.6.11-rc4/net/ipv4/xfrm4_tunnel.c 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/net/ipv4/xfrm4_tunnel.c 2005-02-17 18:15:39.770461664 +0100
@@ -115,6 +115,7 @@
.handler = ipip_rcv,
.err_handler = ipip_err,
.no_policy = 1,
+ .xfrm_prot = 1,
};
static int __init ipip_init(void)
--- linux-2.6.11-rc4/net/ipv4/ipip.c 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/net/ipv4/ipip.c 2005-02-17 18:15:40.466355872 +0100
@@ -476,6 +476,11 @@
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);
--- linux-2.6.11-rc4/net/ipv4/ipcomp.c 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/net/ipv4/ipcomp.c 2005-02-17 18:15:41.048267408 +0100
@@ -503,6 +503,7 @@
.handler = xfrm4_rcv,
.err_handler = ipcomp4_err,
.no_policy = 1,
+ .xfrm_prot = 1,
};
static int __init ipcomp4_init(void)
--- linux-2.6.11-rc4/net/ipv4/ip_input.c 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/net/ipv4/ip_input.c 2005-02-17 18:15:41.773157208 +0100
@@ -224,6 +224,12 @@
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 @@
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 @@
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 @@
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();
@@ -417,8 +426,8 @@
}
}
- 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);
--- linux-2.6.11-rc4/net/ipv4/esp4.c 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/net/ipv4/esp4.c 2005-02-17 18:16:06.954329088 +0100
@@ -474,6 +474,7 @@
.handler = xfrm4_rcv,
.err_handler = esp4_err,
.no_policy = 1,
+ .xfrm_prot = 1,
};
static int __init esp4_init(void)
--- linux-2.6.11-rc4/net/ipv4/ah4.c 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/net/ipv4/ah4.c 2005-02-17 18:16:06.951329544 +0100
@@ -308,6 +308,7 @@
.handler = xfrm4_rcv,
.err_handler = ah4_err,
.no_policy = 1,
+ .xfrm_prot = 1,
};
static int __init ah4_init(void)
--- linux-2.6.11-rc4/net/core/netfilter.c 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/net/core/netfilter.c 2005-02-17 18:20:27.782685304 +0100
@@ -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
@@ -675,6 +676,27 @@
}
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;
@@ -840,3 +862,4 @@
EXPORT_SYMBOL(nf_unregister_hook);
EXPORT_SYMBOL(nf_unregister_queue_handler);
EXPORT_SYMBOL(nf_unregister_sockopt);
+EXPORT_SYMBOL(nf_rcv_postxfrm_local);
--- linux-2.6.11-rc4/include/net/xfrm.h 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/include/net/xfrm.h 2005-02-17 18:21:47.995491104 +0100
@@ -531,6 +531,9 @@
{
atomic_t refcnt;
int len;
+#ifdef CONFIG_NETFILTER
+ int decap_done;
+#endif
struct sec_decap_state x[XFRM_MAX_DEPTH];
};
--- linux-2.6.11-rc4/include/net/protocol.h 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/include/net/protocol.h 2005-02-17 18:22:05.457836424 +0100
@@ -38,6 +38,7 @@
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)
--- linux-2.6.11-rc4/include/linux/netfilter_ipv4.h 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/include/linux/netfilter_ipv4.h 2005-02-17 18:22:30.163080656 +0100
@@ -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. */
@@ -85,6 +87,58 @@
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*/
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 3/4] IPSEC policy lookups
2005-02-17 19:08 [PATCH 0/4] Updated IPSEC NAT patches for 2.6.11 Christophe Saout
2005-02-17 19:10 ` [PATCH 1/4] IPSEC output hooks Christophe Saout
2005-02-17 19:11 ` [PATCH 2/4] IPSEC input hooks Christophe Saout
@ 2005-02-17 19:12 ` Christophe Saout
2005-02-17 19:13 ` [PATCH 4/4] IPSEC policy checks Christophe Saout
2005-03-03 21:10 ` [PATCH 0/4] Updated IPSEC NAT patches for 2.6.11 Tom Eastep
4 siblings, 0 replies; 6+ messages in thread
From: Christophe Saout @ 2005-02-17 19:12 UTC (permalink / raw)
To: netfilter-devel
The updated ipsec-03-policy-lookup.diff
--- linux-2.6.11-rc4/net/ipv4/netfilter/ip_nat_standalone.c 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/net/ipv4/netfilter/ip_nat_standalone.c 2005-02-17 18:28:45.623989072 +0100
@@ -172,6 +172,47 @@
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 @@
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 @@
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 @@
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 @@
|| (*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;
}
--- linux-2.6.11-rc4/net/ipv4/netfilter/ip_conntrack_standalone.c 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/net/ipv4/netfilter/ip_conntrack_standalone.c 2005-02-17 18:28:46.554847560 +0100
@@ -896,6 +896,7 @@
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);
--- linux-2.6.11-rc4/net/core/netfilter.c 2005-02-17 18:26:58.398289856 +0100
+++ linux-2.6.11-rc4-cs1/net/core/netfilter.c 2005-02-17 18:28:47.404718360 +0100
@@ -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
@@ -631,7 +632,6 @@
#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;
@@ -658,6 +658,20 @@
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) {
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 4/4] IPSEC policy checks
2005-02-17 19:08 [PATCH 0/4] Updated IPSEC NAT patches for 2.6.11 Christophe Saout
` (2 preceding siblings ...)
2005-02-17 19:12 ` [PATCH 3/4] IPSEC policy lookups Christophe Saout
@ 2005-02-17 19:13 ` Christophe Saout
2005-03-03 21:10 ` [PATCH 0/4] Updated IPSEC NAT patches for 2.6.11 Tom Eastep
4 siblings, 0 replies; 6+ messages in thread
From: Christophe Saout @ 2005-02-17 19:13 UTC (permalink / raw)
To: netfilter-devel
The updated ipsec-04-policy-checks.diff
--- linux-2.6.11-rc4/net/xfrm/xfrm_policy.c 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/net/xfrm/xfrm_policy.c 2005-02-17 19:01:20.688629416 +0100
@@ -21,6 +21,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>
@@ -43,8 +44,8 @@
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)
{
@@ -931,6 +932,7 @@
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) {
@@ -1209,7 +1211,7 @@
}
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))
@@ -1222,7 +1224,7 @@
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;
--- linux-2.6.11-rc4/net/ipv4/udp.c 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/net/ipv4/udp.c 2005-02-17 19:07:01.630927480 +0100
@@ -997,6 +997,7 @@
kfree_skb(skb);
return -1;
}
+ nf_reset(skb);
if (up->encap_type) {
/*
@@ -1162,6 +1163,7 @@
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))
--- linux-2.6.11-rc4/net/ipv4/tcp_ipv4.c 2005-02-16 00:59:44.000000000 +0100
+++ linux-2.6.11-rc4-cs1/net/ipv4/tcp_ipv4.c 2005-02-17 19:07:01.618929304 +0100
@@ -1771,6 +1771,7 @@
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;
--- linux-2.6.11-rc4/net/ipv4/raw.c 2005-02-17 18:11:39.244258088 +0100
+++ linux-2.6.11-rc4-cs1/net/ipv4/raw.c 2005-02-17 19:07:01.601931888 +0100
@@ -252,6 +252,7 @@
kfree_skb(skb);
return NET_RX_DROP;
}
+ nf_reset(skb);
skb_push(skb, skb->data - skb->nh.raw);
--- linux-2.6.11-rc4/net/ipv4/ip_input.c 2005-02-17 18:26:58.334299584 +0100
+++ linux-2.6.11-rc4-cs1/net/ipv4/ip_input.c 2005-02-17 19:07:01.587934016 +0100
@@ -206,10 +206,6 @@
__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 @@
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) {
--- linux-2.6.11-rc4/net/core/netfilter.c 2005-02-17 18:58:17.591212264 +0100
+++ linux-2.6.11-rc4-cs1/net/core/netfilter.c 2005-02-17 19:11:24.041308232 +0100
@@ -711,6 +711,47 @@
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;
+
+ statusbit = ct->status;
+ if (dir == IP_CT_DIR_REPLY)
+ statusbit ^= IPS_NAT_MASK;
+
+ if (statusbit & IPS_DST_NAT) {
+ fl->fl4_dst = t->dst.ip;
+ if (known_proto)
+ fl->fl_ip_dport = t->dst.u.tcp.port;
+ }
+
+ if (statusbit & IPS_SRC_NAT) {
+ 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;
--- linux-2.6.11-rc4/include/net/xfrm.h 2005-02-17 18:26:58.436284080 +0100
+++ linux-2.6.11-rc4-cs1/include/net/xfrm.h 2005-02-17 19:07:01.545940400 +0100
@@ -178,6 +178,8 @@
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
--- linux-2.6.11-rc4/include/linux/netfilter.h 2005-02-17 18:11:39.463224800 +0100
+++ linux-2.6.11-rc4-cs1/include/linux/netfilter.h 2005-02-17 19:07:01.542940856 +0100
@@ -188,5 +188,21 @@
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*/
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 0/4] Updated IPSEC NAT patches for 2.6.11
2005-02-17 19:08 [PATCH 0/4] Updated IPSEC NAT patches for 2.6.11 Christophe Saout
` (3 preceding siblings ...)
2005-02-17 19:13 ` [PATCH 4/4] IPSEC policy checks Christophe Saout
@ 2005-03-03 21:10 ` Tom Eastep
4 siblings, 0 replies; 6+ messages in thread
From: Tom Eastep @ 2005-03-03 21:10 UTC (permalink / raw)
To: netfilter-devel
[-- Attachment #1: Type: text/plain, Size: 929 bytes --]
Christophe Saout wrote:
> Hi,
>
> I've forward-ported Patrick McHardy's patches that make the kernel IPSEC
> work with NAT.
>
> Since there probably won't be any more big changes between 2.6.11-rc4
> and the final 2.6.11 I'm posting them now.
>
> The biggest change is in the last patch (ipsec-04-policy-checks.diff). I
> needed to rewrite nf_nat_decode_session4 due to the big NAT changes. I
> hope I got everything right. I couldn't find a situation where it
> failed.
> I also added a missing return in nat_route_key_compare that made the
> kernel fail with certain compiler flags.
>
Here's another little patch that allows iptables to compile cleanly
against a kernel tree that has the IPSEC NAT patches applied.
-Tom
--
Tom Eastep \ Off-list replies are cheerfully ignored
Shoreline, \ http://shorewall.net
Washington USA \ teastep@shorewall.net
PGP Public Key \ https://lists.shorewall.net/teastep.pgp.key
[-- Attachment #2: ipsec-05-iptablescompile.diff --]
[-- Type: text/x-patch, Size: 975 bytes --]
diff -Naur linux-2.6.11.orig/include/linux/netfilter_ipv4.h linux-2.6.11/include/linux/netfilter_ipv4.h
--- linux-2.6.11.orig/include/linux/netfilter_ipv4.h 2005-03-03 10:55:24.895484995 -0800
+++ linux-2.6.11/include/linux/netfilter_ipv4.h 2005-03-03 10:55:13.496133352 -0800
@@ -7,8 +7,10 @@
#include <linux/config.h>
#include <linux/netfilter.h>
+#ifdef __KERNEL__
#include <linux/netdevice.h>
#include <net/protocol.h>
+#endif
/* IP Cache bits. */
/* Src IP address. */
diff -Naur linux-2.6.11.orig/include/net/ip.h linux-2.6.11/include/net/ip.h
--- linux-2.6.11.orig/include/net/ip.h 2005-03-03 10:54:34.418212127 -0800
+++ linux-2.6.11/include/net/ip.h 2005-03-03 10:54:25.250342049 -0800
@@ -30,8 +30,10 @@
#include <linux/netdevice.h>
#include <linux/inetdevice.h>
#include <linux/in_route.h>
+#ifdef __KERNEL__
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
+#endif
#include <net/route.h>
#include <net/arp.h>
#include <net/snmp.h>
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2005-03-03 21:10 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-02-17 19:08 [PATCH 0/4] Updated IPSEC NAT patches for 2.6.11 Christophe Saout
2005-02-17 19:10 ` [PATCH 1/4] IPSEC output hooks Christophe Saout
2005-02-17 19:11 ` [PATCH 2/4] IPSEC input hooks Christophe Saout
2005-02-17 19:12 ` [PATCH 3/4] IPSEC policy lookups Christophe Saout
2005-02-17 19:13 ` [PATCH 4/4] IPSEC policy checks Christophe Saout
2005-03-03 21:10 ` [PATCH 0/4] Updated IPSEC NAT patches for 2.6.11 Tom Eastep
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.