summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2017-06-24 04:27:30 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2017-06-26 12:35:06 +0200
commit8644e1cddac2df86a67e3a407629d8416f8a3c5e (patch)
tree0fc85dbd87c028d3a253b5b32714d5d392eff12b /src
parent319b7f4a1344d826ad4e384119057ebf7e804458 (diff)
device: remove icmp conntrack hacks
This logic belongs upstream. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'src')
-rw-r--r--src/compat/compat.h31
-rw-r--r--src/device.c39
-rw-r--r--src/tests/debug.mk2
3 files changed, 37 insertions, 35 deletions
diff --git a/src/compat/compat.h b/src/compat/compat.h
index eb17c8e..159abb1 100644
--- a/src/compat/compat.h
+++ b/src/compat/compat.h
@@ -284,6 +284,37 @@ static inline u64 ktime_get_ns(void)
#define inet_confirm_addr(a,b,c,d,e) inet_confirm_addr(b,c,d,e)
#endif
+/* https://lkml.org/lkml/2017/6/23/790 */
+#if IS_ENABLED(CONFIG_NF_CONNTRACK)
+#include <linux/ip.h>
+#include <linux/icmpv6.h>
+#include <net/icmp.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_nat_core.h>
+static inline void new_icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
+{
+ enum ip_conntrack_info ctinfo;
+ struct nf_conn *ct = nf_ct_get(skb_in, &ctinfo);
+ if (skb_network_header(skb_in) < skb_in->head || (skb_network_header(skb_in) + sizeof(struct iphdr)) > skb_tail_pointer(skb_in))
+ return;
+ if (ct)
+ ip_hdr(skb_in)->saddr = ct->tuplehash[0].tuple.src.u3.ip;
+ icmp_send(skb_in, type, code, info);
+}
+static inline void new_icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
+{
+ enum ip_conntrack_info ctinfo;
+ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
+ if (skb_network_header(skb) < skb->head || (skb_network_header(skb) + sizeof(struct ipv6hdr)) > skb_tail_pointer(skb))
+ return;
+ if (ct)
+ ipv6_hdr(skb)->saddr = ct->tuplehash[0].tuple.src.u3.in6;
+ icmpv6_send(skb, type, code, info);
+}
+#define icmp_send(a,b,c,d) new_icmp_send(a,b,c,d)
+#define icmpv6_send(a,b,c,d) new_icmpv6_send(a,b,c,d)
+#endif
+
/* https://lkml.org/lkml/2015/6/12/415 */
#include <linux/netdevice.h>
static inline struct net_device *netdev_pub(void *dev)
diff --git a/src/device.c b/src/device.c
index 1b7e151..22632e5 100644
--- a/src/device.c
+++ b/src/device.c
@@ -22,10 +22,6 @@
#include <net/rtnetlink.h>
#include <net/ip_tunnels.h>
#include <net/addrconf.h>
-#if IS_ENABLED(CONFIG_NF_CONNTRACK)
-#include <net/netfilter/nf_conntrack.h>
-#include <net/netfilter/nf_nat_core.h>
-#endif
static LIST_HEAD(device_list);
@@ -110,34 +106,6 @@ static int stop(struct net_device *dev)
return 0;
}
-static void skb_unsendable(struct sk_buff *skb, struct net_device *dev)
-{
-#if IS_ENABLED(CONFIG_NF_CONNTRACK)
- /* This conntrack stuff is because the rate limiting needs to be applied
- * to the original src IP, so we have to restore saddr in the IP header.
- * It's not needed if conntracking isn't in the kernel, because in that
- * case the saddr wouldn't be NAT-transformed anyway. */
- enum ip_conntrack_info ctinfo;
- struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
-#endif
- ++dev->stats.tx_errors;
-
- if (skb->len >= sizeof(struct iphdr) && ip_hdr(skb)->version == 4) {
-#if IS_ENABLED(CONFIG_NF_CONNTRACK)
- if (ct)
- ip_hdr(skb)->saddr = ct->tuplehash[0].tuple.src.u3.ip;
-#endif
- icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0);
- } else if (skb->len >= sizeof(struct ipv6hdr) && ip_hdr(skb)->version == 6) {
-#if IS_ENABLED(CONFIG_NF_CONNTRACK)
- if (ct)
- ipv6_hdr(skb)->saddr = ct->tuplehash[0].tuple.src.u3.in6;
-#endif
- icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0);
- }
- kfree_skb(skb);
-}
-
static netdev_tx_t xmit(struct sk_buff *skb, struct net_device *dev)
{
struct wireguard_device *wg = netdev_priv(dev);
@@ -205,7 +173,12 @@ static netdev_tx_t xmit(struct sk_buff *skb, struct net_device *dev)
err_peer:
peer_put(peer);
err:
- skb_unsendable(skb, dev);
+ ++dev->stats.tx_errors;
+ if (skb->protocol == htons(ETH_P_IP))
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0);
+ else if (skb->protocol == htons(ETH_P_IPV6))
+ icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0);
+ kfree_skb(skb);
return ret;
}
diff --git a/src/tests/debug.mk b/src/tests/debug.mk
index 5078a87..5da3280 100644
--- a/src/tests/debug.mk
+++ b/src/tests/debug.mk
@@ -19,8 +19,6 @@ test: debug
-sudo modprobe ip6_udp_tunnel
-sudo modprobe udp_tunnel
-sudo modprobe ipv6
- -sudo modprobe nf_conntrack_ipv4
- -sudo modprobe nf_conntrack_ipv6
-sudo rmmod wireguard
-sudo insmod wireguard.ko
sudo PATH="$(shell pwd)/tools:$$PATH:/usr/sbin:/sbin:/usr/bin:/bin:/usr/local/sbin:/usr/local/bin" ./tests/netns.sh