From: Patrick McHardy <kaber@trash.net>
To: "David S. Miller" <davem@redhat.com>
Cc: herbert@gondor.apana.org.au, netdev@oss.sgi.com,
netfilter-devel@lists.netfilter.org
Subject: [RFC, PATCH 3/5]: netfilter+ipsec - input hooks
Date: Thu, 18 Mar 2004 17:32:14 +0100 [thread overview]
Message-ID: <4059CF0E.3050708@trash.net> (raw)
In-Reply-To: <20040308115858.75cdddca.davem@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 1151 bytes --]
This patch adds new hooks for input, it is the worst of all patches.
Packets should traverse PRE_ROUTING+LOCAL_IN before decryption and
PRE_ROUTING+LOCAL_IN/FORWARD afterwards. This is tricky because I
didn't find an elegant way to determine when decapsulation is done.
Currently, packets reposted into the stack don't traverse the hooks
at the normal positions but at a later time when we know decapsulation
if done:
- if a reposted packet has a non-local destination after input routing
decapsulation must be done, it then traverses the PRE_ROUTING hook.
- otherwise, it continues until ip_local_deliver_finish but also
skips the LOCAL_IN hook. All xfrm protocol-handlers are marked with
xfrm_prot. If the protocol handler of a packet with a secpath
pointer is a non-xfrm-protocol the packet was handled by ipsec and
is done now, it traverses the PRE_ROUTING and LOCAL_IN hooks then.
This catches packets from both tunnel-mode and transport-mode SAs.
Because the hooks are traversed at a later time than usual several
not-so-nice things have to be done in the nf_postxfrm_* functions.
I don't see a better way currently, but I'm sure you do ;)
[-- Attachment #2: 03-input-hooks.diff --]
[-- Type: text/x-patch, Size: 7170 bytes --]
# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
# 2004/03/18 16:41:37+01:00 kaber@trash.net
# [NETFILTER]: post-ipsec input hooks
#
# net/ipv4/xfrm4_tunnel.c
# 2004/03/18 16:41:31+01:00 kaber@trash.net +1 -0
# [NETFILTER]: post-ipsec input hooks
#
# net/ipv4/ipcomp.c
# 2004/03/18 16:41:31+01:00 kaber@trash.net +1 -0
# [NETFILTER]: post-ipsec input hooks
#
# net/ipv4/ip_input.c
# 2004/03/18 16:41:31+01:00 kaber@trash.net +15 -6
# [NETFILTER]: post-ipsec input hooks
#
# net/ipv4/esp4.c
# 2004/03/18 16:41:31+01:00 kaber@trash.net +1 -0
# [NETFILTER]: post-ipsec input hooks
#
# net/ipv4/ah4.c
# 2004/03/18 16:41:31+01:00 kaber@trash.net +1 -0
# [NETFILTER]: post-ipsec input hooks
#
# net/core/netfilter.c
# 2004/03/18 16:41:31+01:00 kaber@trash.net +50 -3
# [NETFILTER]: post-ipsec input hooks
#
# include/net/protocol.h
# 2004/03/18 16:41:31+01:00 kaber@trash.net +1 -0
# [NETFILTER]: post-ipsec input hooks
#
# include/linux/netfilter_ipv4.h
# 2004/03/18 16:41:31+01:00 kaber@trash.net +15 -0
# [NETFILTER]: post-ipsec input hooks
#
diff -Nru a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h
--- a/include/linux/netfilter_ipv4.h Thu Mar 18 16:45:35 2004
+++ b/include/linux/netfilter_ipv4.h Thu Mar 18 16:45:35 2004
@@ -83,6 +83,21 @@
Returns true or false. */
extern int skb_ip_make_writable(struct sk_buff **pskb,
unsigned int writable_len);
+
+#ifdef CONFIG_XFRM
+extern int nf_postxfrm_input(struct sk_buff *skb);
+extern int nf_postxfrm_nonlocal(struct sk_buff *skb);
+#else /* CONFIG_XFRM */
+static inline int nf_postxfrm_input(struct sk_buff *skb)
+{
+ return 0;
+}
+
+static inline int nf_postxfrm_nonlocal(struct sk_buff *skb)
+{
+ return 0;
+}
+#endif /* CONFIG_XFRM */
#endif /*__KERNEL__*/
#endif /*__LINUX_IP_NETFILTER_H*/
diff -Nru a/include/net/protocol.h b/include/net/protocol.h
--- a/include/net/protocol.h Thu Mar 18 16:45:35 2004
+++ b/include/net/protocol.h Thu Mar 18 16:45:35 2004
@@ -39,6 +39,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)
diff -Nru a/net/core/netfilter.c b/net/core/netfilter.c
--- a/net/core/netfilter.c Thu Mar 18 16:45:35 2004
+++ b/net/core/netfilter.c Thu Mar 18 16:45:35 2004
@@ -11,6 +11,7 @@
*/
#include <linux/config.h>
#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
#include <net/protocol.h>
#include <linux/init.h>
#include <linux/skbuff.h>
@@ -25,6 +26,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
@@ -625,9 +627,6 @@
struct dst_entry *odst;
unsigned int hh_len;
- /* some non-standard hacks like ipt_REJECT.c:send_reset() can cause
- * packets with foreign saddr to appear on the NF_IP_LOCAL_OUT hook.
- */
if (inet_addr_type(iph->saddr) == RTN_LOCAL) {
fl.nl_u.ip4_u.daddr = iph->daddr;
fl.nl_u.ip4_u.saddr = iph->saddr;
@@ -679,6 +678,54 @@
return 0;
}
+
+#ifdef CONFIG_XFRM
+static inline int nf_postxfrm_done(struct sk_buff *skb)
+{
+ return 0;
+}
+
+static inline int nf_postxfrm_input2(struct sk_buff *skb)
+{
+ if (inet_addr_type(skb->nh.iph->daddr) != RTN_LOCAL) {
+ if (ip_route_me_harder(&skb) == 0)
+ dst_input(skb);
+ else
+ kfree_skb(skb);
+ return -1;
+ }
+
+ return NF_HOOK(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
+ nf_postxfrm_done);
+}
+
+int nf_postxfrm_input(struct sk_buff *skb)
+{
+ int off = skb->data - skb->nh.raw;
+
+ __skb_push(skb, off);
+ /* 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);
+ }
+
+ nf_reset(skb);
+ if (NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL,
+ nf_postxfrm_input2) != 0)
+ return -1;
+
+ __skb_pull(skb, off);
+ return 0;
+}
+
+int nf_postxfrm_nonlocal(struct sk_buff *skb)
+{
+ nf_reset(skb);
+ return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL,
+ nf_postxfrm_done);
+}
+#endif /* CONFIG_XFRM */
int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len)
{
diff -Nru a/net/ipv4/ah4.c b/net/ipv4/ah4.c
--- a/net/ipv4/ah4.c Thu Mar 18 16:45:35 2004
+++ b/net/ipv4/ah4.c Thu Mar 18 16:45:35 2004
@@ -344,6 +344,7 @@
.handler = xfrm4_rcv,
.err_handler = ah4_err,
.no_policy = 1,
+ .xfrm_prot = 1,
};
static int __init ah4_init(void)
diff -Nru a/net/ipv4/esp4.c b/net/ipv4/esp4.c
--- a/net/ipv4/esp4.c Thu Mar 18 16:45:35 2004
+++ b/net/ipv4/esp4.c Thu Mar 18 16:45:35 2004
@@ -577,6 +577,7 @@
.handler = xfrm4_rcv,
.err_handler = esp4_err,
.no_policy = 1,
+ .xfrm_prot = 1,
};
static int __init esp4_init(void)
diff -Nru a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
--- a/net/ipv4/ip_input.c Thu Mar 18 16:45:35 2004
+++ b/net/ipv4/ip_input.c Thu Mar 18 16:45:35 2004
@@ -224,6 +224,12 @@
resubmit:
hash = protocol & (MAX_INET_PROTOS - 1);
raw_sk = sk_head(&raw_v4_htable[hash]);
+ ipprot = inet_protos[hash];
+ smp_read_barrier_depends();
+
+ if (skb->sp && !ipprot->xfrm_prot)
+ if (nf_postxfrm_input(skb))
+ goto out;
/* If there maybe a raw socket we must check - if not we
* don't care less
@@ -231,10 +237,9 @@
if (raw_sk)
raw_v4_input(skb, skb->nh.iph, hash);
- if ((ipprot = inet_protos[hash]) != NULL) {
+ if (ipprot != NULL) {
int ret;
- smp_read_barrier_depends();
if (!ipprot->no_policy &&
!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
kfree_skb(skb);
@@ -279,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, !skb->sp);
}
static inline int ip_rcv_finish(struct sk_buff *skb)
@@ -346,6 +351,10 @@
}
}
+ if (skb->sp && !(((struct rtable *)skb->dst)->rt_flags&RTCF_LOCAL))
+ if (nf_postxfrm_nonlocal(skb))
+ goto drop;
+
return dst_input(skb);
inhdr_error:
@@ -418,8 +427,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, !skb->sp);
inhdr_error:
IP_INC_STATS_BH(IpInHdrErrors);
diff -Nru a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
--- a/net/ipv4/ipcomp.c Thu Mar 18 16:45:35 2004
+++ b/net/ipv4/ipcomp.c Thu Mar 18 16:45:35 2004
@@ -408,6 +408,7 @@
.handler = xfrm4_rcv,
.err_handler = ipcomp4_err,
.no_policy = 1,
+ .xfrm_prot = 1,
};
static int __init ipcomp4_init(void)
diff -Nru a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
--- a/net/ipv4/xfrm4_tunnel.c Thu Mar 18 16:45:35 2004
+++ b/net/ipv4/xfrm4_tunnel.c Thu Mar 18 16:45:35 2004
@@ -171,6 +171,7 @@
.handler = ipip_rcv,
.err_handler = ipip_err,
.no_policy = 1,
+ .xfrm_prot = 1,
};
static int __init ipip_init(void)
next prev parent reply other threads:[~2004-03-18 16:32 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-03-08 11:03 ip_route_me_harder -> xfrm_lookup Herbert Xu
2004-03-08 14:46 ` Patrick McHardy
2004-03-08 19:58 ` David S. Miller
2004-03-18 16:31 ` Patrick McHardy
2004-03-18 16:31 ` [RFC, PATCH 1/5]: netfilter+ipsec - nf_reset Patrick McHardy
2004-03-19 6:08 ` David S. Miller
2004-03-18 16:31 ` [RFC, PATCH 2/5]: netfilter+ipsec - output hooks Patrick McHardy
2004-03-19 6:09 ` David S. Miller
2004-03-19 10:59 ` Herbert Xu
2004-03-18 16:32 ` Patrick McHardy [this message]
2004-03-19 6:15 ` [RFC, PATCH 3/5]: netfilter+ipsec - input hooks David S. Miller
2004-03-19 11:47 ` Herbert Xu
2004-03-19 16:17 ` Patrick McHardy
2004-03-19 21:05 ` Herbert Xu
2004-03-19 11:07 ` Herbert Xu
2004-03-19 11:46 ` Herbert Xu
2004-03-19 16:29 ` Patrick McHardy
2004-03-18 16:32 ` [RFC, PATCH 4/5]: netfilter+ipsec - policy lookup Patrick McHardy
2004-03-19 6:16 ` David S. Miller
2004-03-19 15:30 ` Patrick McHardy
2004-03-19 11:51 ` Herbert Xu
2004-03-19 16:34 ` Patrick McHardy
2004-03-19 21:05 ` Herbert Xu
2004-03-20 14:01 ` Patrick McHardy
2004-03-21 6:35 ` Herbert Xu
2004-03-21 22:16 ` Herbert Xu
2004-03-21 23:34 ` Patrick McHardy
2004-03-22 2:03 ` Herbert Xu
2004-03-22 2:29 ` Patrick McHardy
2004-03-24 2:15 ` Alexander Samad
2004-03-24 2:39 ` Patrick McHardy
2004-03-24 3:33 ` Alexander Samad
2004-03-18 16:32 ` [RFC, PATCH 5/5]: netfilter+ipsec - policy checks Patrick McHardy
2004-03-19 6:19 ` David S. Miller
2004-03-19 16:24 ` Patrick McHardy
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4059CF0E.3050708@trash.net \
--to=kaber@trash.net \
--cc=davem@redhat.com \
--cc=herbert@gondor.apana.org.au \
--cc=netdev@oss.sgi.com \
--cc=netfilter-devel@lists.netfilter.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).