* 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