summaryrefslogtreecommitdiffstatshomepage
path: root/src/compat
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2017-04-09 07:02:31 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2017-04-09 07:31:00 +0200
commite7e20169af313e5b1f7e1850889dada8c960ce13 (patch)
treec580fbd24e0e53635bb929b991a083abc2a27a67 /src/compat
parentcompat: support 3.12 (diff)
downloadwireguard-monolithic-historical-e7e20169af313e5b1f7e1850889dada8c960ce13.tar.xz
wireguard-monolithic-historical-e7e20169af313e5b1f7e1850889dada8c960ce13.zip
compat: support 3.10
Diffstat (limited to 'src/compat')
-rw-r--r--src/compat/compat.h62
-rw-r--r--src/compat/udp_tunnel/udp_tunnel.c45
2 files changed, 104 insertions, 3 deletions
diff --git a/src/compat/compat.h b/src/compat/compat.h
index a586b93..d936582 100644
--- a/src/compat/compat.h
+++ b/src/compat/compat.h
@@ -7,8 +7,8 @@
#include <linux/version.h>
#include <linux/types.h>
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0)
-#error "WireGuard requires Linux >= 3.12"
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+#error "WireGuard requires Linux >= 3.10"
#endif
/* These conditionals can't be enforced by an out of tree module very easily,
@@ -53,7 +53,9 @@
(LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 17) && LINUX_VERSION_CODE > KERNEL_VERSION(3, 19, 0)) || \
(LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 27) && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || \
(LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 8) && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)) || \
- (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 40) && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
+ (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 40) && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) || \
+ (LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 54))
+
#include <linux/if.h>
#include <net/ip_tunnels.h>
#define IP6_ECN_set_ce(a, b) IP6_ECN_set_ce(b)
@@ -66,6 +68,20 @@
#define time_is_after_eq_jiffies64(a) time_before_eq64(get_jiffies_64(), a)
#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) && IS_ENABLED(CONFIG_IPV6)
+#include <net/ipv6.h>
+struct ipv6_stub_type {
+ void *udpv6_encap_enable;
+ int (*ipv6_dst_lookup)(struct sock *sk, struct dst_entry **dst, struct flowi6 *fl6);
+};
+static const struct ipv6_stub_type ipv6_stub_impl = {
+ .udpv6_encap_enable = (void *)1,
+ .ipv6_dst_lookup = ip6_dst_lookup
+};
+static const struct ipv6_stub_type *ipv6_stub = &ipv6_stub_impl;
+#endif
+
+
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0) && IS_ENABLED(CONFIG_IPV6)
#include <net/addrconf.h>
static inline bool ipv6_mod_enabled(void)
@@ -142,6 +158,46 @@ static inline void *our_pskb_put(struct sk_buff *skb, struct sk_buff *tail, int
#define pskb_put our_pskb_put
#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0)
+#include <net/xfrm.h>
+static inline void skb_scrub_packet(struct sk_buff *skb, bool xnet)
+{
+ skb->tstamp.tv64 = 0;
+ skb->pkt_type = PACKET_HOST;
+ skb->skb_iif = 0;
+ skb_dst_drop(skb);
+ secpath_reset(skb);
+ nf_reset(skb);
+ nf_reset_trace(skb);
+ if (!xnet)
+ return;
+ skb_orphan(skb);
+ skb->mark = 0;
+}
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0)
+#include <linux/random.h>
+static inline u32 prandom_u32_max(u32 ep_ro)
+{
+ return (u32)(((u64) prandom_u32() * ep_ro) >> 32);
+}
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 59)
+static inline int crypto_memneq(const void *a, const void *b, size_t size)
+{
+ unsigned long neq = 0;
+ while (size > 0) {
+ neq |= *(unsigned char *)a ^ *(unsigned char *)b;
+ a += 1;
+ b += 1;
+ size -= 1;
+ }
+ return neq != 0UL ? 1 : 0;
+}
+#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/compat/udp_tunnel/udp_tunnel.c b/src/compat/udp_tunnel/udp_tunnel.c
index 58ac61c..2c60681 100644
--- a/src/compat/udp_tunnel/udp_tunnel.c
+++ b/src/compat/udp_tunnel/udp_tunnel.c
@@ -9,6 +9,12 @@
#include <net/udp.h>
#include <net/udp_tunnel.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0)
+#define __sk_user_data(sk) ((*((void __rcu **)&(sk)->sk_user_data)))
+#define rcu_dereference_sk_user_data(sk) rcu_dereference(__sk_user_data((sk)))
+#define rcu_assign_sk_user_data(sk, ptr) rcu_assign_pointer(__sk_user_data((sk)), ptr)
+#endif
+
/* This is global so, uh, only one real call site... This is the kind of horrific hack you'd expect to see in compat code. */
static udp_tunnel_encap_rcv_t encap_rcv = NULL;
static void our_sk_data_ready(struct sock *sk
@@ -129,6 +135,45 @@ static void fake_destructor(struct sk_buff *skb)
{
}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0)
+static int our_iptunnel_xmit(struct rtable *rt, struct sk_buff *skb,
+ __be32 src, __be32 dst, __u8 proto,
+ __u8 tos, __u8 ttl, __be16 df, bool xnet)
+{
+ int pkt_len = skb->len;
+ struct iphdr *iph;
+ int err;
+
+ skb_scrub_packet(skb, xnet);
+
+ skb->rxhash = 0;
+ skb_dst_set(skb, &rt->dst);
+ memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
+
+ /* Push down and install the IP header. */
+ skb_push(skb, sizeof(struct iphdr));
+ skb_reset_network_header(skb);
+
+ iph = ip_hdr(skb);
+
+ iph->version = 4;
+ iph->ihl = sizeof(struct iphdr) >> 2;
+ iph->frag_off = df;
+ iph->protocol = proto;
+ iph->tos = tos;
+ iph->daddr = dst;
+ iph->saddr = src;
+ iph->ttl = ttl;
+ __ip_select_ident(iph, skb_shinfo(skb)->gso_segs ?: 1);
+
+ err = ip_local_out(skb);
+ if (unlikely(net_xmit_eval(err)))
+ pkt_len = 0;
+ return pkt_len;
+}
+#define iptunnel_xmit our_iptunnel_xmit
+#endif
+
void udp_tunnel_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *skb,
__be32 src, __be32 dst, __u8 tos, __u8 ttl,
__be16 df, __be16 src_port, __be16 dst_port,