From: "Jason A. Donenfeld" <Jason@zx2c4.com>
To: netdev@vger.kernel.org, davem@davemloft.net
Cc: "Jason A. Donenfeld" <Jason@zx2c4.com>, Florian Westphal <fw@strlen.de>
Subject: [PATCH v2 net 1/5] icmp: introduce helper for NAT'd source address in network device context
Date: Mon, 10 Feb 2020 15:14:19 +0100 [thread overview]
Message-ID: <20200210141423.173790-2-Jason@zx2c4.com> (raw)
In-Reply-To: <20200210141423.173790-1-Jason@zx2c4.com>
This introduces a helper function to be called only by network drivers
that wraps calls to icmp[v6]_send in a conntrack transformation, in case
NAT has been used. The transformation happens only on a non-shared skb,
and the skb is fixed back up to its original state after, in case the
calling code continues to use it.
We don't want to pollute the non-driver path, though, so we introduce
this as a helper to be called by places that actually make use of
this, as suggested by Florian.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Cc: Florian Westphal <fw@strlen.de>
---
include/linux/icmpv6.h | 6 ++++++
include/net/icmp.h | 6 ++++++
net/ipv4/icmp.c | 29 +++++++++++++++++++++++++++++
net/ipv6/ip6_icmp.c | 30 ++++++++++++++++++++++++++++++
4 files changed, 71 insertions(+)
diff --git a/include/linux/icmpv6.h b/include/linux/icmpv6.h
index ef1cbb5f454f..93338fd54af8 100644
--- a/include/linux/icmpv6.h
+++ b/include/linux/icmpv6.h
@@ -31,6 +31,12 @@ static inline void icmpv6_send(struct sk_buff *skb,
}
#endif
+#if IS_ENABLED(CONFIG_NF_NAT)
+void icmpv6_ndo_send(struct sk_buff *skb_in, u8 type, u8 code, __u32 info);
+#else
+#define icmpv6_ndo_send icmpv6_send
+#endif
+
extern int icmpv6_init(void);
extern int icmpv6_err_convert(u8 type, u8 code,
int *err);
diff --git a/include/net/icmp.h b/include/net/icmp.h
index 5d4bfdba9adf..9ac2d2672a93 100644
--- a/include/net/icmp.h
+++ b/include/net/icmp.h
@@ -43,6 +43,12 @@ static inline void icmp_send(struct sk_buff *skb_in, int type, int code, __be32
__icmp_send(skb_in, type, code, info, &IPCB(skb_in)->opt);
}
+#if IS_ENABLED(CONFIG_NF_NAT)
+void icmp_ndo_send(struct sk_buff *skb_in, int type, int code, __be32 info);
+#else
+#define icmp_ndo_send icmp_send
+#endif
+
int icmp_rcv(struct sk_buff *skb);
int icmp_err(struct sk_buff *skb, u32 info);
int icmp_init(void);
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 18068ed42f25..5ca36181d4f4 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -748,6 +748,35 @@ out:;
}
EXPORT_SYMBOL(__icmp_send);
+#if IS_ENABLED(CONFIG_NF_NAT)
+#include <net/netfilter/nf_conntrack.h>
+void icmp_ndo_send(struct sk_buff *skb_in, int type, int code, __be32 info)
+{
+ struct sk_buff *cloned_skb = NULL;
+ enum ip_conntrack_info ctinfo;
+ struct nf_conn *ct;
+ __be32 orig_ip;
+
+ ct = nf_ct_get(skb_in, &ctinfo);
+ if (ct) {
+ if (skb_shared(skb_in)) {
+ skb_in = cloned_skb = skb_clone(skb_in, GFP_ATOMIC);
+ if (unlikely(!skb_in))
+ return;
+ }
+ orig_ip = ip_hdr(skb_in)->saddr;
+ ip_hdr(skb_in)->saddr = ct->tuplehash[0].tuple.src.u3.ip;
+ }
+ icmp_send(skb_in, type, code, info);
+ if (ct) {
+ if (cloned_skb)
+ consume_skb(cloned_skb);
+ else
+ ip_hdr(skb_in)->saddr = orig_ip;
+ }
+}
+EXPORT_SYMBOL(icmp_ndo_send);
+#endif
static void icmp_socket_deliver(struct sk_buff *skb, u32 info)
{
diff --git a/net/ipv6/ip6_icmp.c b/net/ipv6/ip6_icmp.c
index 02045494c24c..ee364d61b789 100644
--- a/net/ipv6/ip6_icmp.c
+++ b/net/ipv6/ip6_icmp.c
@@ -45,4 +45,34 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
rcu_read_unlock();
}
EXPORT_SYMBOL(icmpv6_send);
+
+#if IS_ENABLED(CONFIG_NF_NAT)
+#include <net/netfilter/nf_conntrack.h>
+void icmpv6_ndo_send(struct sk_buff *skb_in, u8 type, u8 code, __u32 info)
+{
+ struct sk_buff *cloned_skb = NULL;
+ enum ip_conntrack_info ctinfo;
+ struct in6_addr orig_ip;
+ struct nf_conn *ct;
+
+ ct = nf_ct_get(skb_in, &ctinfo);
+ if (ct) {
+ if (skb_shared(skb_in)) {
+ skb_in = cloned_skb = skb_clone(skb_in, GFP_ATOMIC);
+ if (unlikely(!skb_in))
+ return;
+ }
+ orig_ip = ipv6_hdr(skb_in)->saddr;
+ ipv6_hdr(skb_in)->saddr = ct->tuplehash[0].tuple.src.u3.in6;
+ }
+ icmpv6_send(skb_in, type, code, info);
+ if (ct) {
+ if (cloned_skb)
+ consume_skb(cloned_skb);
+ else
+ ipv6_hdr(skb_in)->saddr = orig_ip;
+ }
+}
+EXPORT_SYMBOL(icmpv6_ndo_send);
+#endif
#endif
--
2.25.0
next prev parent reply other threads:[~2020-02-10 14:15 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-02-10 14:14 [PATCH v2 net 0/5] icmp: account for NAT when sending icmps from ndo layer Jason A. Donenfeld
2020-02-10 14:14 ` Jason A. Donenfeld [this message]
2020-02-10 19:48 ` [PATCH v2 net 1/5] icmp: introduce helper for NAT'd source address in network device context Jason A. Donenfeld
2020-02-10 21:32 ` Florian Westphal
2020-02-10 21:59 ` Jason A. Donenfeld
2020-02-10 22:26 ` Florian Westphal
2020-02-11 9:59 ` Jason A. Donenfeld
2020-02-11 12:25 ` Jason A. Donenfeld
2020-02-11 15:00 ` [PATCH v3 net 0/9] icmp: account for NAT when sending icmps from ndo layer Jason A. Donenfeld
2020-02-11 15:00 ` [PATCH v3 net 1/9] icmp: introduce helper for nat'd source address in network device context Jason A. Donenfeld
2020-02-11 15:00 ` [PATCH v3 net 2/9] gtp: use icmp_ndo_send helper Jason A. Donenfeld
2020-02-11 15:00 ` [PATCH v3 net 3/9] sunvnet: " Jason A. Donenfeld
2020-02-11 15:00 ` [PATCH v3 net 4/9] xfrm: interface: " Jason A. Donenfeld
2020-02-11 15:00 ` [PATCH v3 net 5/9] wireguard: device: use icmp_ndo_send helper and remove skb_share_check Jason A. Donenfeld
2020-02-11 15:00 ` [PATCH v3 net 6/9] firewire: remove skb_share_check from xmit path Jason A. Donenfeld
2020-02-11 15:00 ` [PATCH v3 net 7/9] ipvlan: " Jason A. Donenfeld
2020-02-11 17:39 ` Eric Dumazet
2020-02-11 17:44 ` Jason A. Donenfeld
2020-02-11 18:50 ` Eric Dumazet
2020-02-11 18:54 ` Jason A. Donenfeld
2020-02-11 15:00 ` [PATCH v3 net 8/9] fm10k: " Jason A. Donenfeld
2020-02-11 15:00 ` [PATCH v3 net 9/9] benet: " Jason A. Donenfeld
2020-02-10 14:14 ` [PATCH v2 net 2/5] gtp: use icmp_ndo_send helper Jason A. Donenfeld
2020-02-10 14:14 ` [PATCH v2 net 3/5] sunvnet: " Jason A. Donenfeld
2020-02-10 14:14 ` [PATCH v2 net 4/5] wireguard: " Jason A. Donenfeld
2020-02-10 14:14 ` [PATCH v2 net 5/5] xfrm: interface: " Jason A. Donenfeld
2020-02-10 19:30 ` [PATCH v2 net 6/5] wireguard: selftests: ensure that icmp src address is correct with NAT Jason A. Donenfeld
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=20200210141423.173790-2-Jason@zx2c4.com \
--to=jason@zx2c4.com \
--cc=davem@davemloft.net \
--cc=fw@strlen.de \
--cc=netdev@vger.kernel.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).