diff options
Diffstat (limited to 'src/compat')
-rw-r--r-- | src/compat/compat.h | 122 |
1 files changed, 88 insertions, 34 deletions
diff --git a/src/compat/compat.h b/src/compat/compat.h index 948d3fe..5978fe9 100644 --- a/src/compat/compat.h +++ b/src/compat/compat.h @@ -932,6 +932,94 @@ static inline void skb_mark_not_on_list(struct sk_buff *skb) #define chacha20_neon zinc_chacha20_neon #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) +#include <linux/skbuff.h> +static inline int skb_ensure_writable(struct sk_buff *skb, int write_len) +{ + if (!pskb_may_pull(skb, write_len)) + return -ENOMEM; + + if (!skb_cloned(skb) || skb_clone_writable(skb, write_len)) + return 0; + + return pskb_expand_head(skb, 0, 0, GFP_ATOMIC); +} +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 6, 0) +#if IS_ENABLED(CONFIG_NF_NAT) +#include <linux/ip.h> +#include <linux/icmpv6.h> +#include <net/ipv6.h> +#include <net/icmp.h> +#include <net/netfilter/nf_conntrack.h> +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 1, 0) +#include <net/netfilter/nf_nat_core.h> +#endif +static inline 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 || !(ct->status & IPS_SRC_NAT)) { + icmp_send(skb_in, type, code, info); + return; + } + + if (skb_shared(skb_in)) + skb_in = cloned_skb = skb_clone(skb_in, GFP_ATOMIC); + + if (unlikely(!skb_in || skb_network_header(skb_in) < skb_in->head || + (skb_network_header(skb_in) + sizeof(struct iphdr)) > + skb_tail_pointer(skb_in) || skb_ensure_writable(skb_in, + skb_network_offset(skb_in) + sizeof(struct iphdr)))) + goto out; + + 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); + ip_hdr(skb_in)->saddr = orig_ip; +out: + consume_skb(cloned_skb); +} +static inline 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 || !(ct->status & IPS_SRC_NAT)) { + icmpv6_send(skb_in, type, code, info); + return; + } + + if (skb_shared(skb_in)) + skb_in = cloned_skb = skb_clone(skb_in, GFP_ATOMIC); + + if (unlikely(!skb_in || skb_network_header(skb_in) < skb_in->head || + (skb_network_header(skb_in) + sizeof(struct ipv6hdr)) > + skb_tail_pointer(skb_in) || skb_ensure_writable(skb_in, + skb_network_offset(skb_in) + sizeof(struct ipv6hdr)))) + goto out; + + 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); + ipv6_hdr(skb_in)->saddr = orig_ip; +out: + consume_skb(cloned_skb); +} +#else +#define icmp_ndo_send icmp_send +#define icmpv6_ndo_send icmpv6_send +#endif +#endif + #if defined(ISUBUNTU1604) #include <linux/siphash.h> #ifndef _WG_LINUX_SIPHASH_H @@ -956,40 +1044,6 @@ static inline void skb_mark_not_on_list(struct sk_buff *skb) #define BUILD_BUG_ON(x) #endif -/* https://lkml.kernel.org/r/20170624021727.17835-1-Jason@zx2c4.com */ -#if IS_ENABLED(CONFIG_NF_CONNTRACK) -#include <linux/ip.h> -#include <linux/icmpv6.h> -#include <net/ipv6.h> -#include <net/icmp.h> -#include <net/netfilter/nf_conntrack.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 1, 0) -#include <net/netfilter/nf_nat_core.h> -#endif -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 - /* PaX compatibility */ #ifdef CONSTIFY_PLUGIN #include <linux/cache.h> |