aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ipv4/icmp.c21
-rw-r--r--net/ipv6/icmp.c21
2 files changed, 42 insertions, 0 deletions
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index c2be26b98b5f..30aa6aa79fd2 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -97,6 +97,10 @@
#include <net/inet_common.h>
#include <net/ip_fib.h>
#include <net/l3mdev.h>
+#if IS_ENABLED(CONFIG_NF_CONNTRACK)
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_nat_core.h>
+#endif
/*
* Build xmit assembly blocks
@@ -586,6 +590,10 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
u32 mark;
struct net *net;
struct sock *sk;
+#if IS_ENABLED(CONFIG_NF_CONNTRACK)
+ enum ip_conntrack_info ctinfo;
+ struct nf_conn *ct;
+#endif
if (!rt)
goto out;
@@ -604,6 +612,19 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
goto out;
/*
+ * If this function is called after the skb has already been
+ * NAT transformed, the ratelimiting will apply to the wrong
+ * saddr, and the reply will will be marked as coming from the
+ * wrong host. So, we fix it up here in case connection tracking
+ * enables that.
+ */
+#if IS_ENABLED(CONFIG_NF_CONNTRACK)
+ ct = nf_ct_get(skb_in, &ctinfo);
+ if (ct)
+ iph->saddr = ct->tuplehash[0].tuple.src.u3.ip;
+#endif
+
+ /*
* No replies to physical multicast/broadcast
*/
if (skb_in->pkt_type != PACKET_HOST)
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 8d7b113958b1..ee8a2853121e 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -69,6 +69,10 @@
#include <net/inet_common.h>
#include <net/dsfield.h>
#include <net/l3mdev.h>
+#if IS_ENABLED(CONFIG_NF_CONNTRACK)
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_nat_core.h>
+#endif
#include <linux/uaccess.h>
@@ -422,12 +426,29 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info,
int len;
int err = 0;
u32 mark = IP6_REPLY_MARK(net, skb->mark);
+#if IS_ENABLED(CONFIG_NF_CONNTRACK)
+ enum ip_conntrack_info ctinfo;
+ struct nf_conn *ct;
+#endif
if ((u8 *)hdr < skb->head ||
(skb_network_header(skb) + sizeof(*hdr)) > skb_tail_pointer(skb))
return;
/*
+ * If this function is called after the skb has already been
+ * NAT transformed, the ratelimiting will apply to the wrong
+ * saddr, and the reply will will be marked as coming from the
+ * wrong host. So, we fix it up here in case connection tracking
+ * enables that.
+ */
+#if IS_ENABLED(CONFIG_NF_CONNTRACK)
+ ct = nf_ct_get(skb, &ctinfo);
+ if (ct)
+ hdr->saddr = ct->tuplehash[0].tuple.src.u3.in6;
+#endif
+
+ /*
* Make sure we respect the rules
* i.e. RFC 1885 2.4(e)
* Rule (e.1) is enforced by not using icmp6_send