diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2017-04-09 07:02:31 +0200 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2017-04-09 07:31:00 +0200 |
commit | f687fef304b12c2868e367372dbc9a6160a54a50 (patch) | |
tree | b53f1e259fc252e204926dc5e56dccd76b461d1a /src | |
parent | 0d57d0f326777cec3f13c2b298760c6fc5edffe5 (diff) |
compat: support 3.10
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/compat/compat.h | 62 | ||||
-rw-r--r-- | src/compat/udp_tunnel/udp_tunnel.c | 45 | ||||
-rw-r--r-- | src/dkms.conf | 4 |
3 files changed, 106 insertions, 5 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, diff --git a/src/dkms.conf b/src/dkms.conf index 2e66bc9..2b854ba 100644 --- a/src/dkms.conf +++ b/src/dkms.conf @@ -5,5 +5,5 @@ AUTOINSTALL=yes BUILT_MODULE_NAME="wireguard" DEST_MODULE_LOCATION="/kernel/net" -# requires kernel 3.12 or greater: -BUILD_EXCLUSIVE_KERNEL="^(([^1230]\.)|(3\.1[23456789]))" +# requires kernel 3.10 or greater: +BUILD_EXCLUSIVE_KERNEL="^(([^1230]\.)|(3\.1[0-9]))" |