summaryrefslogtreecommitdiff
path: root/backport-include/net
diff options
context:
space:
mode:
Diffstat (limited to 'backport-include/net')
-rw-r--r--backport-include/net/addrconf.h25
-rw-r--r--backport-include/net/flow_keys.h21
-rw-r--r--backport-include/net/genetlink.h254
-rw-r--r--backport-include/net/ip.h14
-rw-r--r--backport-include/net/ip6_fib.h26
-rw-r--r--backport-include/net/ipv6.h60
-rw-r--r--backport-include/net/ipv6_stubs.h13
-rw-r--r--backport-include/net/iw_handler.h40
-rw-r--r--backport-include/net/net_namespace.h44
-rw-r--r--backport-include/net/netlink.h722
-rw-r--r--backport-include/net/sch_generic.h20
-rw-r--r--backport-include/net/sock.h78
-rw-r--r--backport-include/net/tso.h33
-rw-r--r--backport-include/net/xfrm.h14
14 files changed, 1364 insertions, 0 deletions
diff --git a/backport-include/net/addrconf.h b/backport-include/net/addrconf.h
new file mode 100644
index 0000000..f1e8e62
--- /dev/null
+++ b/backport-include/net/addrconf.h
@@ -0,0 +1,25 @@
+#ifndef _BACKPORT_NET_ADDRCONF_H
+#define _BACKPORT_NET_ADDRCONF_H 1
+
+#include_next <net/addrconf.h>
+
+#include <linux/version.h>
+
+#if LINUX_VERSION_IS_LESS(3,9,0)
+static inline bool ipv6_addr_is_solict_mult(const struct in6_addr *addr)
+{
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
+ __u64 *p = (__u64 *)addr;
+ return ((p[0] ^ cpu_to_be64(0xff02000000000000UL)) |
+ ((p[1] ^ cpu_to_be64(0x00000001ff000000UL)) &
+ cpu_to_be64(0xffffffffff000000UL))) == 0UL;
+#else
+ return ((addr->s6_addr32[0] ^ htonl(0xff020000)) |
+ addr->s6_addr32[1] |
+ (addr->s6_addr32[2] ^ htonl(0x00000001)) |
+ (addr->s6_addr[12] ^ 0xff)) == 0;
+#endif
+}
+#endif /* LINUX_VERSION_IS_LESS(3,9,0) */
+
+#endif /* _BACKPORT_NET_ADDRCONF_H */
diff --git a/backport-include/net/flow_keys.h b/backport-include/net/flow_keys.h
new file mode 100644
index 0000000..093bc80
--- /dev/null
+++ b/backport-include/net/flow_keys.h
@@ -0,0 +1,21 @@
+#if LINUX_VERSION_IS_GEQ(3,3,0)
+#include_next <net/flow_keys.h>
+#else
+
+#ifndef _NET_FLOW_KEYS_H
+#define _NET_FLOW_KEYS_H
+
+struct flow_keys {
+ /* (src,dst) must be grouped, in the same way than in IP header */
+ __be32 src;
+ __be32 dst;
+ union {
+ __be32 ports;
+ __be16 port16[2];
+ };
+ u8 ip_proto;
+};
+
+extern bool skb_flow_dissect(const struct sk_buff *skb, struct flow_keys *flow);
+#endif
+#endif
diff --git a/backport-include/net/genetlink.h b/backport-include/net/genetlink.h
new file mode 100644
index 0000000..747b6da
--- /dev/null
+++ b/backport-include/net/genetlink.h
@@ -0,0 +1,254 @@
+#ifndef __BACKPORT_NET_GENETLINK_H
+#define __BACKPORT_NET_GENETLINK_H
+#include_next <net/genetlink.h>
+#include <linux/version.h>
+
+static inline void __bp_genl_info_userhdr_set(struct genl_info *info,
+ void *userhdr)
+{
+ info->userhdr = userhdr;
+}
+
+static inline void *__bp_genl_info_userhdr(struct genl_info *info)
+{
+ return info->userhdr;
+}
+
+#if LINUX_VERSION_IS_LESS(4,12,0)
+#define GENL_SET_ERR_MSG(info, msg) NL_SET_ERR_MSG(genl_info_extack(info), msg)
+
+static inline int genl_err_attr(struct genl_info *info, int err,
+ struct nlattr *attr)
+{
+ return err;
+}
+#endif /* < 4.12 */
+
+/* this is for patches we apply */
+static inline struct netlink_ext_ack *genl_info_extack(struct genl_info *info)
+{
+#if LINUX_VERSION_IS_GEQ(4,12,0)
+ return info->extack;
+#else
+ return info->userhdr;
+#endif
+}
+
+/* this is for patches we apply */
+static inline struct netlink_ext_ack *genl_callback_extack(struct netlink_callback *cb)
+{
+#if LINUX_VERSION_IS_GEQ(4,20,0)
+ return cb->extack;
+#else
+ return NULL;
+#endif
+}
+
+/* this gets put in place of info->userhdr, since we use that above */
+static inline void *genl_info_userhdr(struct genl_info *info)
+{
+ return (u8 *)info->genlhdr + GENL_HDRLEN;
+}
+
+/* this is for patches we apply */
+#if LINUX_VERSION_IS_LESS(3,7,0)
+#define genl_info_snd_portid(__genl_info) (__genl_info->snd_pid)
+#else
+#define genl_info_snd_portid(__genl_info) (__genl_info->snd_portid)
+#endif
+
+#if LINUX_VERSION_IS_LESS(3,13,0)
+#define __genl_const
+#else /* < 3.13 */
+#define __genl_const const
+#endif /* < 3.13 */
+
+#ifndef GENLMSG_DEFAULT_SIZE
+#define GENLMSG_DEFAULT_SIZE (NLMSG_DEFAULT_SIZE - GENL_HDRLEN)
+#endif
+
+#if LINUX_VERSION_IS_LESS(3,1,0)
+#define genl_dump_check_consistent(cb, user_hdr) do { } while (0)
+#endif
+
+#if LINUX_VERSION_IS_LESS(4,10,0)
+#define __genl_ro_after_init
+#else
+#define __genl_ro_after_init __ro_after_init
+#endif
+
+#if LINUX_VERSION_IS_LESS(4,15,0)
+#define genlmsg_nlhdr LINUX_BACKPORT(genlmsg_nlhdr)
+static inline struct nlmsghdr *genlmsg_nlhdr(void *user_hdr)
+{
+ return (struct nlmsghdr *)((char *)user_hdr -
+ GENL_HDRLEN -
+ NLMSG_HDRLEN);
+}
+
+#ifndef genl_dump_check_consistent
+static inline
+void backport_genl_dump_check_consistent(struct netlink_callback *cb,
+ void *user_hdr)
+{
+ struct genl_family dummy_family = {
+ .hdrsize = 0,
+ };
+
+ genl_dump_check_consistent(cb, user_hdr, &dummy_family);
+}
+#define genl_dump_check_consistent LINUX_BACKPORT(genl_dump_check_consistent)
+#endif
+#endif /* LINUX_VERSION_IS_LESS(4,15,0) */
+
+#if LINUX_VERSION_IS_LESS(5,2,0)
+enum genl_validate_flags {
+ GENL_DONT_VALIDATE_STRICT = BIT(0),
+ GENL_DONT_VALIDATE_DUMP = BIT(1),
+ GENL_DONT_VALIDATE_DUMP_STRICT = BIT(2),
+};
+
+#if LINUX_VERSION_IS_GEQ(3,13,0)
+struct backport_genl_ops {
+ void *__dummy_was_policy_must_be_null;
+ int (*doit)(struct sk_buff *skb,
+ struct genl_info *info);
+#if LINUX_VERSION_IS_GEQ(4,5,0) || \
+ LINUX_VERSION_IN_RANGE(4,4,104, 4,5,0) || \
+ LINUX_VERSION_IN_RANGE(4,1,48, 4,2,0) || \
+ LINUX_VERSION_IN_RANGE(3,18,86, 3,19,0)
+ int (*start)(struct netlink_callback *cb);
+#endif
+ int (*dumpit)(struct sk_buff *skb,
+ struct netlink_callback *cb);
+ int (*done)(struct netlink_callback *cb);
+ u8 cmd;
+ u8 internal_flags;
+ u8 flags;
+ u8 validate;
+};
+#else
+struct backport_genl_ops {
+ u8 cmd;
+ u8 internal_flags;
+ unsigned int flags;
+ void *__dummy_was_policy_must_be_null;
+ int (*doit)(struct sk_buff *skb,
+ struct genl_info *info);
+ int (*dumpit)(struct sk_buff *skb,
+ struct netlink_callback *cb);
+ int (*done)(struct netlink_callback *cb);
+ struct list_head ops_list;
+ u8 validate;
+};
+#endif
+
+static inline int
+__real_backport_genl_register_family(struct genl_family *family)
+{
+#define OPS_VALIDATE(f) \
+ BUILD_BUG_ON(offsetof(struct genl_ops, f) != \
+ offsetof(struct backport_genl_ops, f))
+ OPS_VALIDATE(doit);
+#if LINUX_VERSION_IS_GEQ(4,5,0) || \
+ LINUX_VERSION_IN_RANGE(4,4,104, 4,5,0) || \
+ LINUX_VERSION_IN_RANGE(4,1,48, 4,2,0) || \
+ LINUX_VERSION_IN_RANGE(3,18,86, 3,19,0)
+ OPS_VALIDATE(start);
+#endif
+ OPS_VALIDATE(dumpit);
+ OPS_VALIDATE(done);
+ OPS_VALIDATE(cmd);
+ OPS_VALIDATE(internal_flags);
+ OPS_VALIDATE(flags);
+
+ return genl_register_family(family);
+}
+#define genl_ops backport_genl_ops
+
+static inline int
+__real_backport_genl_unregister_family(struct genl_family *family)
+{
+ return genl_unregister_family(family);
+}
+
+struct backport_genl_family {
+ struct genl_family family;
+ const struct genl_ops * copy_ops;
+
+ /* copied */
+ int id; /* private */
+ unsigned int hdrsize;
+ char name[GENL_NAMSIZ];
+ unsigned int version;
+ unsigned int maxattr;
+ bool netnsok;
+ bool parallel_ops;
+ const struct nla_policy *policy;
+ int (*pre_doit)(__genl_const struct genl_ops *ops,
+ struct sk_buff *skb,
+ struct genl_info *info);
+ void (*post_doit)(__genl_const struct genl_ops *ops,
+ struct sk_buff *skb,
+ struct genl_info *info);
+/*
+ * unsupported!
+ int (*mcast_bind)(struct net *net, int group);
+ void (*mcast_unbind)(struct net *net, int group);
+ */
+ struct nlattr ** attrbuf; /* private */
+ __genl_const struct genl_ops * ops;
+ __genl_const struct genl_multicast_group *mcgrps;
+ unsigned int n_ops;
+ unsigned int n_mcgrps;
+ struct module *module;
+};
+#undef genl_family
+#define genl_family backport_genl_family
+
+#define genl_register_family backport_genl_register_family
+int genl_register_family(struct genl_family *family);
+
+#define genl_unregister_family backport_genl_unregister_family
+int backport_genl_unregister_family(struct genl_family *family);
+
+#define genl_notify LINUX_BACKPORT(genl_notify)
+void genl_notify(const struct genl_family *family, struct sk_buff *skb,
+ struct genl_info *info, u32 group, gfp_t flags);
+
+#define genlmsg_put LINUX_BACKPORT(genlmsg_put)
+void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
+ const struct genl_family *family, int flags, u8 cmd);
+
+#define genlmsg_put_reply LINUX_BACKPORT(genlmsg_put_reply)
+void *genlmsg_put_reply(struct sk_buff *skb,
+ struct genl_info *info,
+ const struct genl_family *family,
+ int flags, u8 cmd);
+
+#define genlmsg_multicast_netns LINUX_BACKPORT(genlmsg_multicast_netns)
+int genlmsg_multicast_netns(const struct genl_family *family,
+ struct net *net, struct sk_buff *skb,
+ u32 portid, unsigned int group,
+ gfp_t flags);
+
+#define genlmsg_multicast LINUX_BACKPORT(genlmsg_multicast)
+int genlmsg_multicast(const struct genl_family *family,
+ struct sk_buff *skb, u32 portid,
+ unsigned int group, gfp_t flags);
+
+#define genlmsg_multicast_allns LINUX_BACKPORT(genlmsg_multicast_allns)
+int backport_genlmsg_multicast_allns(const struct genl_family *family,
+ struct sk_buff *skb, u32 portid,
+ unsigned int group, gfp_t flags);
+
+#define genl_family_attrbuf LINUX_BACKPORT(genl_family_attrbuf)
+static inline struct nlattr **genl_family_attrbuf(struct genl_family *family)
+{
+ WARN_ON(family->parallel_ops);
+
+ return family->attrbuf;
+}
+#endif /* LINUX_VERSION_IS_LESS(4,20,0) */
+
+#endif /* __BACKPORT_NET_GENETLINK_H */
diff --git a/backport-include/net/ip.h b/backport-include/net/ip.h
new file mode 100644
index 0000000..6893ba5
--- /dev/null
+++ b/backport-include/net/ip.h
@@ -0,0 +1,14 @@
+#ifndef __BACKPORT_NET_IP_H
+#define __BACKPORT_NET_IP_H
+#include_next <net/ip.h>
+#include <linux/version.h>
+
+#if LINUX_VERSION_IS_LESS(3,1,0)
+/* Backports 56f8a75c */
+static inline bool ip_is_fragment(const struct iphdr *iph)
+{
+ return (iph->frag_off & htons(IP_MF | IP_OFFSET)) != 0;
+}
+#endif
+
+#endif /* __BACKPORT_NET_IP_H */
diff --git a/backport-include/net/ip6_fib.h b/backport-include/net/ip6_fib.h
new file mode 100644
index 0000000..2f21163
--- /dev/null
+++ b/backport-include/net/ip6_fib.h
@@ -0,0 +1,26 @@
+#ifndef __BACKPORT_NET_IP6_ROUTE_H
+#define __BACKPORT_NET_IP6_ROUTE_H
+#include_next <net/ip6_fib.h>
+#include <net/ip6_route.h>
+#include <linux/route.h>
+#include <linux/version.h>
+
+/*
+ * This function is avaliable with one argument since kernel 3.10, but the
+ * secound one was added in 4.2.
+ */
+#if LINUX_VERSION_IS_LESS(4,2,0)
+#define rt6_nexthop LINUX_BACKPORT(rt6_nexthop)
+static inline struct in6_addr *rt6_nexthop(struct rt6_info *rt,
+ struct in6_addr *daddr)
+{
+ if (rt->rt6i_flags & RTF_GATEWAY)
+ return &rt->rt6i_gateway;
+ else if (rt->rt6i_flags & RTF_CACHE)
+ return &rt->rt6i_dst.addr;
+ else
+ return daddr;
+}
+#endif /* LINUX_VERSION_IS_LESS(4,2,0) */
+
+#endif /* __BACKPORT_NET_IP6_ROUTE_H */
diff --git a/backport-include/net/ipv6.h b/backport-include/net/ipv6.h
new file mode 100644
index 0000000..7416d6b
--- /dev/null
+++ b/backport-include/net/ipv6.h
@@ -0,0 +1,60 @@
+#ifndef __BACKPORT_NET_IPV6_H
+#define __BACKPORT_NET_IPV6_H
+#include_next <net/ipv6.h>
+#include <linux/version.h>
+#include <net/addrconf.h>
+#include <net/inet_frag.h>
+
+#if LINUX_VERSION_IS_LESS(3,7,0)
+/*
+ * Equivalent of ipv4 struct ip
+ */
+struct frag_queue {
+ struct inet_frag_queue q;
+
+ __be32 id; /* fragment id */
+ u32 user;
+ struct in6_addr saddr;
+ struct in6_addr daddr;
+
+ int iif;
+ unsigned int csum;
+ __u16 nhoffset;
+};
+#endif /* LINUX_VERSION_IS_LESS(3,7,0) */
+
+#if LINUX_VERSION_IS_LESS(3,6,0)
+#define ipv6_addr_hash LINUX_BACKPORT(ipv6_addr_hash)
+static inline u32 ipv6_addr_hash(const struct in6_addr *a)
+{
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
+ const unsigned long *ul = (const unsigned long *)a;
+ unsigned long x = ul[0] ^ ul[1];
+
+ return (u32)(x ^ (x >> 32));
+#else
+ return (__force u32)(a->s6_addr32[0] ^ a->s6_addr32[1] ^
+ a->s6_addr32[2] ^ a->s6_addr32[3]);
+#endif
+}
+#endif
+
+#if LINUX_VERSION_IS_LESS(4,5,0)
+#define ipv6_addr_prefix_copy LINUX_BACKPORT(ipv6_addr_prefix_copy)
+static inline void ipv6_addr_prefix_copy(struct in6_addr *addr,
+ const struct in6_addr *pfx,
+ int plen)
+{
+ /* caller must guarantee 0 <= plen <= 128 */
+ int o = plen >> 3,
+ b = plen & 0x7;
+
+ memcpy(addr->s6_addr, pfx, o);
+ if (b != 0) {
+ addr->s6_addr[o] &= ~(0xff00 >> b);
+ addr->s6_addr[o] |= (pfx->s6_addr[o] & (0xff00 >> b));
+ }
+}
+#endif
+
+#endif /* __BACKPORT_NET_IPV6_H */
diff --git a/backport-include/net/ipv6_stubs.h b/backport-include/net/ipv6_stubs.h
new file mode 100644
index 0000000..7d9a522
--- /dev/null
+++ b/backport-include/net/ipv6_stubs.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _BACKPORT_IPV6_STUBS_H
+#define _BACKPORT_IPV6_STUBS_H
+
+#if LINUX_VERSION_IS_LESS(5,2,0)
+
+#include <net/addrconf.h>
+
+#else
+#include_next <net/ipv6_stubs.h>
+#endif
+
+#endif /* _BACKPORT_IPV6_STUBS_H */
diff --git a/backport-include/net/iw_handler.h b/backport-include/net/iw_handler.h
new file mode 100644
index 0000000..84d63b3
--- /dev/null
+++ b/backport-include/net/iw_handler.h
@@ -0,0 +1,40 @@
+#ifndef __BACKPORT_IW_HANDLER_H
+#define __BACKPORT_IW_HANDLER_H
+#include_next <net/iw_handler.h>
+
+#if LINUX_VERSION_IS_LESS(4,1,0)
+static inline char *
+iwe_stream_add_event_check(struct iw_request_info *info, char *stream,
+ char *ends, struct iw_event *iwe, int event_len)
+{
+ char *res = iwe_stream_add_event(info, stream, ends, iwe, event_len);
+
+ if (res == stream)
+ return ERR_PTR(-E2BIG);
+ return res;
+}
+
+static inline char *
+iwe_stream_add_point_check(struct iw_request_info *info, char *stream,
+ char *ends, struct iw_event *iwe, char *extra)
+{
+ char *res = iwe_stream_add_point(info, stream, ends, iwe, extra);
+
+ if (res == stream)
+ return ERR_PTR(-E2BIG);
+ return res;
+}
+#endif /* LINUX_VERSION_IS_LESS(4,1,0) */
+
+/* this was added in v3.2.79, v3.18.30, v4.1.21, v4.4.6 and 4.5 */
+#if !(LINUX_VERSION_IS_GEQ(4,4,6) || \
+ (LINUX_VERSION_IS_GEQ(4,1,21) && \
+ LINUX_VERSION_IS_LESS(4,2,0)) || \
+ (LINUX_VERSION_IS_GEQ(3,18,30) && \
+ LINUX_VERSION_IS_LESS(3,19,0)) || \
+ (LINUX_VERSION_IS_GEQ(3,2,79) && \
+ LINUX_VERSION_IS_LESS(3,3,0)))
+#define wireless_nlevent_flush LINUX_BACKPORT(wireless_nlevent_flush)
+static inline void wireless_nlevent_flush(void) {}
+#endif
+#endif /* __BACKPORT_IW_HANDLER_H */
diff --git a/backport-include/net/net_namespace.h b/backport-include/net/net_namespace.h
new file mode 100644
index 0000000..1e84297
--- /dev/null
+++ b/backport-include/net/net_namespace.h
@@ -0,0 +1,44 @@
+#ifndef _COMPAT_NET_NET_NAMESPACE_H
+#define _COMPAT_NET_NET_NAMESPACE_H 1
+
+#include_next <net/net_namespace.h>
+
+#if LINUX_VERSION_IS_LESS(3,20,0)
+/*
+ * In older kernels we simply fail this function.
+ */
+#define get_net_ns_by_fd LINUX_BACKPORT(get_net_ns_by_fd)
+static inline struct net *get_net_ns_by_fd(int fd)
+{
+ return ERR_PTR(-EINVAL);
+}
+#endif
+
+#if LINUX_VERSION_IS_LESS(4,1,0)
+typedef struct {
+#ifdef CONFIG_NET_NS
+ struct net *net;
+#endif
+} possible_net_t;
+
+static inline void possible_write_pnet(possible_net_t *pnet, struct net *net)
+{
+#ifdef CONFIG_NET_NS
+ pnet->net = net;
+#endif
+}
+
+static inline struct net *possible_read_pnet(const possible_net_t *pnet)
+{
+#ifdef CONFIG_NET_NS
+ return pnet->net;
+#else
+ return &init_net;
+#endif
+}
+#else
+#define possible_write_pnet(pnet, net) write_pnet(pnet, net)
+#define possible_read_pnet(pnet) read_pnet(pnet)
+#endif /* LINUX_VERSION_IS_LESS(4,1,0) */
+
+#endif /* _COMPAT_NET_NET_NAMESPACE_H */
diff --git a/backport-include/net/netlink.h b/backport-include/net/netlink.h
new file mode 100644
index 0000000..b2045e4
--- /dev/null
+++ b/backport-include/net/netlink.h
@@ -0,0 +1,722 @@
+#ifndef __BACKPORT_NET_NETLINK_H
+#define __BACKPORT_NET_NETLINK_H
+#include_next <net/netlink.h>
+#include <linux/version.h>
+#include <linux/in6.h>
+
+#if LINUX_VERSION_IS_LESS(5,2,0)
+/* can't backport using the enum - need to override */
+#define NLA_UNSPEC 0
+#define NLA_U8 1
+#define NLA_U16 2
+#define NLA_U32 3
+#define NLA_U64 4
+#define NLA_STRING 5
+#define NLA_FLAG 6
+#define NLA_MSECS 7
+#define NLA_NESTED 8
+#define NLA_NESTED_ARRAY 9
+#define NLA_NUL_STRING 10
+#define NLA_BINARY 11
+#define NLA_S8 12
+#define NLA_S16 13
+#define NLA_S32 14
+#define NLA_S64 15
+#define NLA_BITFIELD32 16
+#define NLA_REJECT 17
+#define NLA_EXACT_LEN 18
+#define NLA_EXACT_LEN_WARN 19
+#define NLA_MIN_LEN 20
+#define __NLA_TYPE_MAX 21
+#define NLA_TYPE_MAX (__NLA_TYPE_MAX - 1)
+
+struct backport_nla_policy {
+ u8 type;
+ u8 validation_type;
+ u16 len;
+ union {
+ const void *validation_data;
+ struct {
+ s16 min, max;
+ };
+ int (*validate)(const struct nlattr *attr,
+ struct netlink_ext_ack *extack);
+ u16 strict_start_type;
+ };
+};
+#define nla_policy backport_nla_policy
+
+#define nla_nest_start_noflag LINUX_BACKPORT(nla_nest_start_noflag)
+static inline struct nlattr *nla_nest_start_noflag(struct sk_buff *skb,
+ int attrtype)
+{
+ struct nlattr *start = (struct nlattr *)skb_tail_pointer(skb);
+
+ if (nla_put(skb, attrtype, 0, NULL) < 0)
+ return NULL;
+
+ return start;
+}
+
+#define nla_nest_start LINUX_BACKPORT(nla_nest_start)
+static inline struct nlattr *nla_nest_start(struct sk_buff *skb, int attrtype)
+{
+ return nla_nest_start_noflag(skb, attrtype | NLA_F_NESTED);
+}
+
+enum netlink_validation {
+ NL_VALIDATE_LIBERAL = 0,
+ NL_VALIDATE_TRAILING = BIT(0),
+ NL_VALIDATE_MAXTYPE = BIT(1),
+ NL_VALIDATE_UNSPEC = BIT(2),
+ NL_VALIDATE_STRICT_ATTRS = BIT(3),
+ NL_VALIDATE_NESTED = BIT(4),
+};
+
+#define NL_VALIDATE_DEPRECATED_STRICT (NL_VALIDATE_TRAILING |\
+ NL_VALIDATE_MAXTYPE)
+#define NL_VALIDATE_STRICT (NL_VALIDATE_TRAILING |\
+ NL_VALIDATE_MAXTYPE |\
+ NL_VALIDATE_UNSPEC |\
+ NL_VALIDATE_STRICT_ATTRS |\
+ NL_VALIDATE_NESTED)
+
+#define __nla_validate LINUX_BACKPORT(__nla_validate)
+int __nla_validate(const struct nlattr *head, int len, int maxtype,
+ const struct nla_policy *policy, unsigned int validate,
+ struct netlink_ext_ack *extack);
+#define __nla_parse LINUX_BACKPORT(__nla_parse)
+int __nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head,
+ int len, const struct nla_policy *policy, unsigned int validate,
+ struct netlink_ext_ack *extack);
+
+#define nla_policy_len LINUX_BACKPORT(nla_policy_len)
+int nla_policy_len(const struct nla_policy *, int);
+
+#define nla_parse LINUX_BACKPORT(nla_parse)
+static inline int nla_parse(struct nlattr **tb, int maxtype,
+ const struct nlattr *head, int len,
+ const struct nla_policy *policy,
+ struct netlink_ext_ack *extack)
+{
+ return __nla_parse(tb, maxtype, head, len, policy,
+ NL_VALIDATE_STRICT, extack);
+}
+
+#define nla_parse_deprecated LINUX_BACKPORT(nla_parse_deprecated)
+static inline int nla_parse_deprecated(struct nlattr **tb, int maxtype,
+ const struct nlattr *head, int len,
+ const struct nla_policy *policy,
+ struct netlink_ext_ack *extack)
+{
+ return __nla_parse(tb, maxtype, head, len, policy,
+ NL_VALIDATE_LIBERAL, extack);
+}
+
+#define nla_parse_deprecated_strict LINUX_BACKPORT(nla_parse_deprecated_strict)
+static inline int nla_parse_deprecated_strict(struct nlattr **tb, int maxtype,
+ const struct nlattr *head,
+ int len,
+ const struct nla_policy *policy,
+ struct netlink_ext_ack *extack)
+{
+ return __nla_parse(tb, maxtype, head, len, policy,
+ NL_VALIDATE_DEPRECATED_STRICT, extack);
+}
+
+#define __nlmsg_parse LINUX_BACKPORT(__nlmsg_parse)
+static inline int __nlmsg_parse(const struct nlmsghdr *nlh, int hdrlen,
+ struct nlattr *tb[], int maxtype,
+ const struct nla_policy *policy,
+ unsigned int validate,
+ struct netlink_ext_ack *extack)
+{
+ if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen)) {
+ NL_SET_ERR_MSG(extack, "Invalid header length");
+ return -EINVAL;
+ }
+
+ return __nla_parse(tb, maxtype, nlmsg_attrdata(nlh, hdrlen),
+ nlmsg_attrlen(nlh, hdrlen), policy, validate,
+ extack);
+}
+
+#define nlmsg_parse LINUX_BACKPORT(nlmsg_parse)
+static inline int nlmsg_parse(const struct nlmsghdr *nlh, int hdrlen,
+ struct nlattr *tb[], int maxtype,
+ const struct nla_policy *policy,
+ struct netlink_ext_ack *extack)
+{
+ return __nla_parse(tb, maxtype, nlmsg_attrdata(nlh, hdrlen),
+ nlmsg_attrlen(nlh, hdrlen), policy,
+ NL_VALIDATE_STRICT, extack);
+}
+
+#define nlmsg_parse_deprecated LINUX_BACKPORT(nlmsg_parse_deprecated)
+static inline int nlmsg_parse_deprecated(const struct nlmsghdr *nlh, int hdrlen,
+ struct nlattr *tb[], int maxtype,
+ const struct nla_policy *policy,
+ struct netlink_ext_ack *extack)
+{
+ return __nlmsg_parse(nlh, hdrlen, tb, maxtype, policy,
+ NL_VALIDATE_LIBERAL, extack);
+}
+
+#define nlmsg_parse_deprecated_strict LINUX_BACKPORT(nlmsg_parse_deprecated_strict)
+static inline int
+nlmsg_parse_deprecated_strict(const struct nlmsghdr *nlh, int hdrlen,
+ struct nlattr *tb[], int maxtype,
+ const struct nla_policy *policy,
+ struct netlink_ext_ack *extack)
+{
+ return __nlmsg_parse(nlh, hdrlen, tb, maxtype, policy,
+ NL_VALIDATE_DEPRECATED_STRICT, extack);
+}
+
+#define nla_validate_deprecated LINUX_BACKPORT(nla_validate_deprecated)
+static inline int nla_validate_deprecated(const struct nlattr *head, int len,
+ int maxtype,
+ const struct nla_policy *policy,
+ struct netlink_ext_ack *extack)
+{
+ return __nla_validate(head, len, maxtype, policy, NL_VALIDATE_LIBERAL,
+ extack);
+}
+
+#define nla_validate LINUX_BACKPORT(nla_validate)
+static inline int nla_validate(const struct nlattr *head, int len, int maxtype,
+ const struct nla_policy *policy,
+ struct netlink_ext_ack *extack)
+{
+ return __nla_validate(head, len, maxtype, policy, NL_VALIDATE_STRICT,
+ extack);
+}
+
+#define nlmsg_validate_deprecated LINUX_BACKPORT(nlmsg_validate_deprecated)
+static inline int nlmsg_validate_deprecated(const struct nlmsghdr *nlh,
+ int hdrlen, int maxtype,
+ const struct nla_policy *policy,
+ struct netlink_ext_ack *extack)
+{
+ if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
+ return -EINVAL;
+
+ return __nla_validate(nlmsg_attrdata(nlh, hdrlen),
+ nlmsg_attrlen(nlh, hdrlen), maxtype,
+ policy, NL_VALIDATE_LIBERAL, extack);
+}
+
+#define nlmsg_validate LINUX_BACKPORT(nlmsg_validate)
+static inline int nlmsg_validate(const struct nlmsghdr *nlh,
+ int hdrlen, int maxtype,
+ const struct nla_policy *policy,
+ struct netlink_ext_ack *extack)
+{
+ if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
+ return -EINVAL;
+
+ return __nla_validate(nlmsg_attrdata(nlh, hdrlen),
+ nlmsg_attrlen(nlh, hdrlen), maxtype,
+ policy, NL_VALIDATE_STRICT, extack);
+}
+
+#define nla_parse_nested LINUX_BACKPORT(nla_parse_nested)
+static inline int nla_parse_nested(struct nlattr *tb[], int maxtype,
+ const struct nlattr *nla,
+ const struct nla_policy *policy,
+ struct netlink_ext_ack *extack)
+{
+ if (!(nla->nla_type & NLA_F_NESTED)) {
+ NL_SET_ERR_MSG_ATTR(extack, nla, "NLA_F_NESTED is missing");
+ return -EINVAL;
+ }
+
+ return __nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy,
+ NL_VALIDATE_STRICT, extack);
+}
+
+#define nla_parse_nested_deprecated LINUX_BACKPORT(nla_parse_nested_deprecated)
+static inline int nla_parse_nested_deprecated(struct nlattr *tb[], int maxtype,
+ const struct nlattr *nla,
+ const struct nla_policy *policy,
+ struct netlink_ext_ack *extack)
+{
+ return __nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy,
+ NL_VALIDATE_LIBERAL, extack);
+}
+
+#define __nla_validate_nested LINUX_BACKPORT(__nla_validate_nested)
+static inline int __nla_validate_nested(const struct nlattr *start, int maxtype,
+ const struct nla_policy *policy,
+ unsigned int validate,
+ struct netlink_ext_ack *extack)
+{
+ return __nla_validate(nla_data(start), nla_len(start), maxtype, policy,
+ validate, extack);
+}
+
+#define nla_validate_nested_deprecated LINUX_BACKPORT(nla_validate_nested_deprecated)
+static inline int
+nla_validate_nested_deprecated(const struct nlattr *start, int maxtype,
+ const struct nla_policy *policy,
+ struct netlink_ext_ack *extack)
+{
+ return __nla_validate_nested(start, maxtype, policy,
+ NL_VALIDATE_LIBERAL, extack);
+}
+#endif /* < 5.2 */
+
+#if LINUX_VERSION_IS_LESS(5,3,0)
+#define nl80211_validate_nested LINUX_BACKPORT(nl80211_validate_nested)
+static inline int
+nl80211_validate_nested(const struct nlattr *start, int maxtype,
+ const struct nla_policy *policy,
+ struct netlink_ext_ack *extack)
+{
+ return __nla_validate_nested(start, maxtype, policy,
+ NL_VALIDATE_STRICT, extack);
+}
+#endif /* < 5.3 */
+
+#if LINUX_VERSION_IS_LESS(5,1,0)
+#undef NLA_POLICY_NESTED
+#undef NLA_POLICY_NESTED_ARRAY
+#define _NLA_POLICY_NESTED(maxattr, policy) \
+ { .type = NLA_NESTED, .validation_data = policy, .len = maxattr }
+#define _NLA_POLICY_NESTED_ARRAY(maxattr, policy) \
+ { .type = NLA_NESTED_ARRAY, .validation_data = policy, .len = maxattr }
+#define NLA_POLICY_NESTED(policy) \
+ _NLA_POLICY_NESTED(ARRAY_SIZE(policy) - 1, policy)
+#define NLA_POLICY_NESTED_ARRAY(policy) \
+ _NLA_POLICY_NESTED_ARRAY(ARRAY_SIZE(policy) - 1, policy)
+#endif /* < 5.1 */
+
+#if LINUX_VERSION_IS_LESS(4,20,0)
+enum nla_policy_validation {
+ NLA_VALIDATE_NONE,
+ NLA_VALIDATE_RANGE,
+ NLA_VALIDATE_MIN,
+ NLA_VALIDATE_MAX,
+ NLA_VALIDATE_FUNCTION,
+};
+
+#define NLA_POLICY_EXACT_LEN(_len) { .type = NLA_EXACT_LEN, .len = _len }
+#define NLA_POLICY_EXACT_LEN_WARN(_len) { .type = NLA_EXACT_LEN_WARN, \
+ .len = _len }
+
+#define NLA_POLICY_ETH_ADDR NLA_POLICY_EXACT_LEN(ETH_ALEN)
+#define NLA_POLICY_ETH_ADDR_COMPAT NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN)
+
+#define __NLA_ENSURE(condition) (sizeof(char[1 - 2*!(condition)]) - 1)
+#define NLA_ENSURE_INT_TYPE(tp) \
+ (__NLA_ENSURE(tp == NLA_S8 || tp == NLA_U8 || \
+ tp == NLA_S16 || tp == NLA_U16 || \
+ tp == NLA_S32 || tp == NLA_U32 || \
+ tp == NLA_S64 || tp == NLA_U64) + tp)
+#define NLA_ENSURE_NO_VALIDATION_PTR(tp) \
+ (__NLA_ENSURE(tp != NLA_BITFIELD32 && \
+ tp != NLA_REJECT && \
+ tp != NLA_NESTED && \
+ tp != NLA_NESTED_ARRAY) + tp)
+
+#define NLA_POLICY_RANGE(tp, _min, _max) { \
+ .type = NLA_ENSURE_INT_TYPE(tp), \
+ .validation_type = NLA_VALIDATE_RANGE, \
+ .min = _min, \
+ .max = _max \
+}
+
+#define NLA_POLICY_MIN(tp, _min) { \
+ .type = NLA_ENSURE_INT_TYPE(tp), \
+ .validation_type = NLA_VALIDATE_MIN, \
+ .min = _min, \
+}
+
+#define NLA_POLICY_MAX(tp, _max) { \
+ .type = NLA_ENSURE_INT_TYPE(tp), \
+ .validation_type = NLA_VALIDATE_MAX, \
+ .max = _max, \
+}
+
+#define NLA_POLICY_VALIDATE_FN(tp, fn, ...) { \
+ .type = NLA_ENSURE_NO_VALIDATION_PTR(tp), \
+ .validation_type = NLA_VALIDATE_FUNCTION, \
+ .validate = fn, \
+ .len = __VA_ARGS__ + 0, \
+}
+#endif /* < 4.20 */
+
+#if LINUX_VERSION_IS_LESS(4,12,0)
+#include <backport/magic.h>
+
+static inline int _nla_validate5(const struct nlattr *head,
+ int len, int maxtype,
+ const struct nla_policy *policy,
+ struct netlink_ext_ack *extack)
+{
+ return nla_validate(head, len, maxtype, policy, extack);
+}
+static inline int _nla_validate4(const struct nlattr *head,
+ int len, int maxtype,
+ const struct nla_policy *policy)
+{
+ return nla_validate(head, len, maxtype, policy, NULL);
+}
+#undef nla_validate
+#define nla_validate(...) \
+ macro_dispatcher(_nla_validate, __VA_ARGS__)(__VA_ARGS__)
+
+static inline int _nla_parse6(struct nlattr **tb, int maxtype,
+ const struct nlattr *head,
+ int len, const struct nla_policy *policy,
+ struct netlink_ext_ack *extack)
+{
+ return nla_parse(tb, maxtype, head, len, policy, extack);
+}
+static inline int _nla_parse5(struct nlattr **tb, int maxtype,
+ const struct nlattr *head,
+ int len, const struct nla_policy *policy)
+{
+ return nla_parse(tb, maxtype, head, len, policy, NULL);
+}
+#undef nla_parse
+#define nla_parse(...) \
+ macro_dispatcher(_nla_parse, __VA_ARGS__)(__VA_ARGS__)
+
+static inline int _nlmsg_parse6(const struct nlmsghdr *nlh, int hdrlen,
+ struct nlattr *tb[], int maxtype,
+ const struct nla_policy *policy,
+ struct netlink_ext_ack *extack)
+{
+ return nlmsg_parse(nlh, hdrlen, tb, maxtype, policy, extack);
+}
+static inline int _nlmsg_parse5(const struct nlmsghdr *nlh, int hdrlen,
+ struct nlattr *tb[], int maxtype,
+ const struct nla_policy *policy)
+{
+ return nlmsg_parse(nlh, hdrlen, tb, maxtype, policy, NULL);
+}
+#undef nlmsg_parse
+#define nlmsg_parse(...) \
+ macro_dispatcher(_nlmsg_parse, __VA_ARGS__)(__VA_ARGS__)
+
+static inline int _nlmsg_validate5(const struct nlmsghdr *nlh,
+ int hdrlen, int maxtype,
+ const struct nla_policy *policy,
+ struct netlink_ext_ack *extack)
+{
+ return nlmsg_validate(nlh, hdrlen, maxtype, policy, extack);
+}
+static inline int _nlmsg_validate4(const struct nlmsghdr *nlh,
+ int hdrlen, int maxtype,
+ const struct nla_policy *policy)
+{
+ return nlmsg_validate(nlh, hdrlen, maxtype, policy, NULL);
+}
+#undef nlmsg_validate
+#define nlmsg_validate(...) \
+ macro_dispatcher(_nlmsg_validate, __VA_ARGS__)(__VA_ARGS__)
+
+static inline int _nla_parse_nested5(struct nlattr *tb[], int maxtype,
+ const struct nlattr *nla,
+ const struct nla_policy *policy,
+ struct netlink_ext_ack *extack)
+{
+ return nla_parse_nested(tb, maxtype, nla, policy, extack);
+}
+static inline int _nla_parse_nested4(struct nlattr *tb[], int maxtype,
+ const struct nlattr *nla,
+ const struct nla_policy *policy)
+{
+ return nla_parse_nested(tb, maxtype, nla, policy, NULL);
+}
+#undef nla_parse_nested
+#define nla_parse_nested(...) \
+ macro_dispatcher(_nla_parse_nested, __VA_ARGS__)(__VA_ARGS__)
+#endif /* LINUX_VERSION_IS_LESS(4,12,0) */
+
+#if LINUX_VERSION_IS_LESS(3,7,0)
+/**
+ * nla_put_s8 - Add a s8 netlink attribute to a socket buffer
+ * @skb: socket buffer to add attribute to
+ * @attrtype: attribute type
+ * @value: numeric value
+ */
+#define nla_put_s8 LINUX_BACKPORT(nla_put_s8)
+static inline int nla_put_s8(struct sk_buff *skb, int attrtype, s8 value)
+{
+ return nla_put(skb, attrtype, sizeof(s8), &value);
+}
+
+/**
+ * nla_put_s16 - Add a s16 netlink attribute to a socket buffer
+ * @skb: socket buffer to add attribute to
+ * @attrtype: attribute type
+ * @value: numeric value
+ */
+#define nla_put_s16 LINUX_BACKPORT(nla_put_s16)
+static inline int nla_put_s16(struct sk_buff *skb, int attrtype, s16 value)
+{
+ return nla_put(skb, attrtype, sizeof(s16), &value);
+}
+
+/**
+ * nla_put_s32 - Add a s32 netlink attribute to a socket buffer
+ * @skb: socket buffer to add attribute to
+ * @attrtype: attribute type
+ * @value: numeric value
+ */
+#define nla_put_s32 LINUX_BACKPORT(nla_put_s32)
+static inline int nla_put_s32(struct sk_buff *skb, int attrtype, s32 value)
+{
+ return nla_put(skb, attrtype, sizeof(s32), &value);
+}
+
+/**
+ * nla_get_s32 - return payload of s32 attribute
+ * @nla: s32 netlink attribute
+ */
+#define nla_get_s32 LINUX_BACKPORT(nla_get_s32)
+static inline s32 nla_get_s32(const struct nlattr *nla)
+{
+ return *(s32 *) nla_data(nla);
+}
+
+/**
+ * nla_get_s16 - return payload of s16 attribute
+ * @nla: s16 netlink attribute
+ */
+#define nla_get_s16 LINUX_BACKPORT(nla_get_s16)
+static inline s16 nla_get_s16(const struct nlattr *nla)
+{
+ return *(s16 *) nla_data(nla);
+}
+
+/**
+ * nla_get_s8 - return payload of s8 attribute
+ * @nla: s8 netlink attribute
+ */
+#define nla_get_s8 LINUX_BACKPORT(nla_get_s8)
+static inline s8 nla_get_s8(const struct nlattr *nla)
+{
+ return *(s8 *) nla_data(nla);
+}
+
+/**
+ * nla_get_s64 - return payload of s64 attribute
+ * @nla: s64 netlink attribute
+ */
+#define nla_get_s64 LINUX_BACKPORT(nla_get_s64)
+static inline s64 nla_get_s64(const struct nlattr *nla)
+{
+ s64 tmp;
+
+ nla_memcpy(&tmp, nla, sizeof(tmp));
+
+ return tmp;
+}
+#endif /* < 3.7.0 */
+
+#if LINUX_VERSION_IS_LESS(3,5,0)
+/*
+ * This backports:
+ * commit 569a8fc38367dfafd87454f27ac646c8e6b54bca
+ * Author: David S. Miller <davem@davemloft.net>
+ * Date: Thu Mar 29 23:18:53 2012 -0400
+ *
+ * netlink: Add nla_put_be{16,32,64}() helpers.
+ */
+
+#define nla_put_be16 LINUX_BACKPORT(nla_put_be16)
+static inline int nla_put_be16(struct sk_buff *skb, int attrtype, __be16 value)
+{
+ return nla_put(skb, attrtype, sizeof(__be16), &value);
+}
+
+#define nla_put_be32 LINUX_BACKPORT(nla_put_be32)
+static inline int nla_put_be32(struct sk_buff *skb, int attrtype, __be32 value)
+{
+ return nla_put(skb, attrtype, sizeof(__be32), &value);
+}
+
+#define nla_put_be64 LINUX_BACKPORT(nla_put_be64)
+static inline int nla_put_be64(struct sk_buff *skb, int attrtype, __be64 value)
+{
+ return nla_put(skb, attrtype, sizeof(__be64), &value);
+}
+#endif /* < 3.5 */
+
+#if LINUX_VERSION_IS_LESS(3,7,0)
+#define NLA_S8 (NLA_BINARY + 1)
+#define NLA_S16 (NLA_BINARY + 2)
+#define NLA_S32 (NLA_BINARY + 3)
+#define NLA_S64 (NLA_BINARY + 4)
+#define __NLA_TYPE_MAX (NLA_BINARY + 5)
+
+#undef NLA_TYPE_MAX
+#define NLA_TYPE_MAX (__NLA_TYPE_MAX - 1)
+#endif
+
+#if LINUX_VERSION_IS_LESS(4,1,0)
+#define nla_put_in_addr LINUX_BACKPORT(nla_put_in_addr)
+static inline int nla_put_in_addr(struct sk_buff *skb, int attrtype,
+ __be32 addr)
+{
+ return nla_put_be32(skb, attrtype, addr);
+}
+
+#define nla_put_in6_addr LINUX_BACKPORT(nla_put_in6_addr)
+static inline int nla_put_in6_addr(struct sk_buff *skb, int attrtype,
+ const struct in6_addr *addr)
+{
+ return nla_put(skb, attrtype, sizeof(*addr), addr);
+}
+
+static inline __be32 nla_get_in_addr(const struct nlattr *nla)
+{
+ return *(__be32 *) nla_data(nla);
+}
+
+static inline struct in6_addr nla_get_in6_addr(const struct nlattr *nla)
+{
+ struct in6_addr tmp;
+
+ nla_memcpy(&tmp, nla, sizeof(tmp));
+ return tmp;
+}
+#endif /* < 4.1 */
+
+#if LINUX_VERSION_IS_LESS(4,4,0)
+/**
+ * nla_get_le32 - return payload of __le32 attribute
+ * @nla: __le32 netlink attribute
+ */
+#define nla_get_le32 LINUX_BACKPORT(nla_get_le32)
+static inline __le32 nla_get_le32(const struct nlattr *nla)
+{
+ return *(__le32 *) nla_data(nla);
+}
+
+/**
+ * nla_get_le64 - return payload of __le64 attribute
+ * @nla: __le64 netlink attribute
+ */
+#define nla_get_le64 LINUX_BACKPORT(nla_get_le64)
+static inline __le64 nla_get_le64(const struct nlattr *nla)
+{
+ return *(__le64 *) nla_data(nla);
+}
+#endif /* < 4.4 */
+
+#if LINUX_VERSION_IS_LESS(4,7,0)
+/**
+ * nla_need_padding_for_64bit - test 64-bit alignment of the next attribute
+ * @skb: socket buffer the message is stored in
+ *
+ * Return true if padding is needed to align the next attribute (nla_data()) to
+ * a 64-bit aligned area.
+ */
+#define nla_need_padding_for_64bit LINUX_BACKPORT(nla_need_padding_for_64bit)
+static inline bool nla_need_padding_for_64bit(struct sk_buff *skb)
+{
+#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+ /* The nlattr header is 4 bytes in size, that's why we test
+ * if the skb->data _is_ aligned. A NOP attribute, plus
+ * nlattr header for next attribute, will make nla_data()
+ * 8-byte aligned.
+ */
+ if (IS_ALIGNED((unsigned long)skb_tail_pointer(skb), 8))
+ return true;
+#endif
+ return false;
+}
+/**
+ * nla_align_64bit - 64-bit align the nla_data() of next attribute
+ * @skb: socket buffer the message is stored in
+ * @padattr: attribute type for the padding
+ *
+ * Conditionally emit a padding netlink attribute in order to make
+ * the next attribute we emit have a 64-bit aligned nla_data() area.
+ * This will only be done in architectures which do not have
+ * HAVE_EFFICIENT_UNALIGNED_ACCESS defined.
+ *
+ * Returns zero on success or a negative error code.
+ */
+#define nla_align_64bit LINUX_BACKPORT(nla_align_64bit)
+static inline int nla_align_64bit(struct sk_buff *skb, int padattr)
+{
+ if (nla_need_padding_for_64bit(skb) &&
+ !nla_reserve(skb, padattr, 0))
+ return -EMSGSIZE;
+ return 0;
+}
+
+/**
+ * nla_total_size_64bit - total length of attribute including padding
+ * @payload: length of payload
+ */
+#define nla_total_size_64bit LINUX_BACKPORT(nla_total_size_64bit)
+static inline int nla_total_size_64bit(int payload)
+{
+ return NLA_ALIGN(nla_attr_size(payload))
+#ifndef HAVE_EFFICIENT_UNALIGNED_ACCESS
+ + NLA_ALIGN(nla_attr_size(0))
+#endif
+ ;
+}
+#define __nla_reserve_64bit LINUX_BACKPORT(__nla_reserve_64bit)
+struct nlattr *__nla_reserve_64bit(struct sk_buff *skb, int attrtype,
+ int attrlen, int padattr);
+#define nla_reserve_64bit LINUX_BACKPORT(nla_reserve_64bit)
+struct nlattr *nla_reserve_64bit(struct sk_buff *skb, int attrtype,
+ int attrlen, int padattr);
+#define __nla_put_64bit LINUX_BACKPORT(__nla_put_64bit)
+void __nla_put_64bit(struct sk_buff *skb, int attrtype, int attrlen,
+ const void *data, int padattr);
+#define nla_put_64bit LINUX_BACKPORT(nla_put_64bit)
+int nla_put_64bit(struct sk_buff *skb, int attrtype, int attrlen,
+ const void *data, int padattr);
+/**
+ * nla_put_u64_64bit - Add a u64 netlink attribute to a skb and align it
+ * @skb: socket buffer to add attribute to
+ * @attrtype: attribute type
+ * @value: numeric value
+ * @padattr: attribute type for the padding
+ */
+#define nla_put_u64_64bit LINUX_BACKPORT(nla_put_u64_64bit)
+static inline int nla_put_u64_64bit(struct sk_buff *skb, int attrtype,
+ u64 value, int padattr)
+{
+ return nla_put_64bit(skb, attrtype, sizeof(u64), &value, padattr);
+}
+
+
+/**
+ * nla_put_s64 - Add a s64 netlink attribute to a socket buffer and align it
+ * @skb: socket buffer to add attribute to
+ * @attrtype: attribute type
+ * @value: numeric value
+ * @padattr: attribute type for the padding
+ */
+#define nla_put_s64 LINUX_BACKPORT(nla_put_s64)
+static inline int nla_put_s64(struct sk_buff *skb, int attrtype, s64 value,
+ int padattr)
+{
+ return nla_put_64bit(skb, attrtype, sizeof(s64), &value, padattr);
+}
+#endif /* < 4.7 */
+
+#if LINUX_VERSION_IS_LESS(4,10,0)
+/**
+ * nla_memdup - duplicate attribute memory (kmemdup)
+ * @src: netlink attribute to duplicate from
+ * @gfp: GFP mask
+ */
+#define nla_memdump LINUX_BACKPORT(nla_memdup)
+static inline void *nla_memdup(const struct nlattr *src, gfp_t gfp)
+{
+ return kmemdup(nla_data(src), nla_len(src), gfp);
+}
+#endif /* < 4.9 */
+
+#endif /* __BACKPORT_NET_NETLINK_H */
diff --git a/backport-include/net/sch_generic.h b/backport-include/net/sch_generic.h
new file mode 100644
index 0000000..cabc601
--- /dev/null
+++ b/backport-include/net/sch_generic.h
@@ -0,0 +1,20 @@
+#ifndef __BACKPORT_NET_SCH_GENERIC_H
+#define __BACKPORT_NET_SCH_GENERIC_H
+#include_next <net/sch_generic.h>
+
+#if LINUX_VERSION_IS_LESS(3,3,0)
+#if !((LINUX_VERSION_IS_GEQ(3,2,9) && LINUX_VERSION_IS_LESS(3,3,0)) || (LINUX_VERSION_IS_GEQ(3,0,23) && LINUX_VERSION_IS_LESS(3,1,0)))
+/* mask qdisc_cb_private_validate as RHEL6 backports this */
+#define qdisc_cb_private_validate(a,b) compat_qdisc_cb_private_validate(a,b)
+static inline void qdisc_cb_private_validate(const struct sk_buff *skb, int sz)
+{
+ BUILD_BUG_ON(sizeof(skb->cb) < sizeof(struct qdisc_skb_cb) + sz);
+}
+#endif
+#endif /* LINUX_VERSION_IS_LESS(3,3,0) */
+
+#ifndef TCQ_F_CAN_BYPASS
+#define TCQ_F_CAN_BYPASS 4
+#endif
+
+#endif /* __BACKPORT_NET_SCH_GENERIC_H */
diff --git a/backport-include/net/sock.h b/backport-include/net/sock.h
new file mode 100644
index 0000000..39bf008
--- /dev/null
+++ b/backport-include/net/sock.h
@@ -0,0 +1,78 @@
+#ifndef __BACKPORT_NET_SOCK_H
+#define __BACKPORT_NET_SOCK_H
+#include_next <net/sock.h>
+#include <linux/version.h>
+
+#if LINUX_VERSION_IS_LESS(3,9,0)
+#include <backport/magic.h>
+
+#define sk_for_each3(__sk, node, list) \
+ hlist_for_each_entry(__sk, node, list, sk_node)
+
+#define sk_for_each_safe4(__sk, node, tmp, list) \
+ hlist_for_each_entry_safe(__sk, node, tmp, list, sk_node)
+
+#define sk_for_each2(__sk, list) \
+ hlist_for_each_entry(__sk, list, sk_node)
+
+#define sk_for_each_safe3(__sk, tmp, list) \
+ hlist_for_each_entry_safe(__sk, tmp, list, sk_node)
+
+#undef sk_for_each
+#define sk_for_each(...) \
+ macro_dispatcher(sk_for_each, __VA_ARGS__)(__VA_ARGS__)
+#undef sk_for_each_safe
+#define sk_for_each_safe(...) \
+ macro_dispatcher(sk_for_each_safe, __VA_ARGS__)(__VA_ARGS__)
+
+#endif
+
+#if LINUX_VERSION_IS_LESS(3,10,0)
+/*
+ * backport SOCK_SELECT_ERR_QUEUE -- see commit
+ * "net: add option to enable error queue packets waking select"
+ *
+ * Adding 14 to SOCK_QUEUE_SHRUNK will reach a bet that can't be
+ * set on older kernels, so sock_flag() will always return false.
+ */
+#define SOCK_SELECT_ERR_QUEUE (SOCK_QUEUE_SHRUNK + 14)
+#endif
+
+#ifndef sock_skb_cb_check_size
+#define sock_skb_cb_check_size(size) \
+ BUILD_BUG_ON((size) > FIELD_SIZEOF(struct sk_buff, cb))
+#endif
+
+#if LINUX_VERSION_IS_LESS(4,2,0)
+#define sk_alloc(net, family, priority, prot, kern) sk_alloc(net, family, priority, prot)
+#endif
+
+#if LINUX_VERSION_IS_LESS(4,5,0)
+#define sk_set_bit LINUX_BACKPORT(sk_set_bit)
+static inline void sk_set_bit(int nr, struct sock *sk)
+{
+ set_bit(nr, &sk->sk_socket->flags);
+}
+#endif /* < 4.5 */
+
+#if LINUX_VERSION_IS_LESS(4,5,0)
+#define sk_clear_bit LINUX_BACKPORT(sk_clear_bit)
+static inline void sk_clear_bit(int nr, struct sock *sk)
+{
+ clear_bit(nr, &sk->sk_socket->flags);
+}
+#endif /* < 4.5 */
+
+#if LINUX_VERSION_IS_LESS(4,16,0)
+#define sk_pacing_shift_update LINUX_BACKPORT(sk_pacing_shift_update)
+static inline void sk_pacing_shift_update(struct sock *sk, int val)
+{
+#if LINUX_VERSION_IS_GEQ(4,15,0)
+ if (!sk || !sk_fullsock(sk) || sk->sk_pacing_shift == val)
+ return;
+ sk->sk_pacing_shift = val;
+#endif /* >= 4.15 */
+}
+#endif /* < 4.16 */
+
+#endif /* __BACKPORT_NET_SOCK_H */
diff --git a/backport-include/net/tso.h b/backport-include/net/tso.h
new file mode 100644
index 0000000..3a3f50b
--- /dev/null
+++ b/backport-include/net/tso.h
@@ -0,0 +1,33 @@
+#ifndef BACKPORT_TSO_H
+#define BACKPORT_TSO_H
+
+#include <net/ip.h>
+
+#if LINUX_VERSION_IS_LESS(4,4,0)
+
+#define tso_t LINUX_BACKPORT(tso_t)
+struct tso_t {
+ int next_frag_idx;
+ void *data;
+ size_t size;
+ u16 ip_id;
+ bool ipv6;
+ u32 tcp_seq;
+};
+
+#define tso_count_descs LINUX_BACKPORT(tso_count_descs)
+int tso_count_descs(struct sk_buff *skb);
+
+#define tso_build_hdr LINUX_BACKPORT(tso_build_hdr)
+void tso_build_hdr(struct sk_buff *skb, char *hdr, struct tso_t *tso,
+ int size, bool is_last);
+#define tso_build_data LINUX_BACKPORT(tso_build_data)
+void tso_build_data(struct sk_buff *skb, struct tso_t *tso, int size);
+#define tso_start LINUX_BACKPORT(tso_start)
+void tso_start(struct sk_buff *skb, struct tso_t *tso);
+
+#else
+#include_next <net/tso.h>
+#endif
+
+#endif /* BACKPORT_TSO_H */
diff --git a/backport-include/net/xfrm.h b/backport-include/net/xfrm.h
new file mode 100644
index 0000000..7e55984
--- /dev/null
+++ b/backport-include/net/xfrm.h
@@ -0,0 +1,14 @@
+#ifndef __BACKPORT_NET_XFRM_H
+#define __BACKPORT_NET_XFRM_H
+#include_next <net/xfrm.h>
+#include <linux/version.h>
+
+#if LINUX_VERSION_IS_LESS(5,4,0)
+#define skb_ext_reset LINUX_BACKPORT(skb_ext_reset)
+static inline void skb_ext_reset(struct sk_buff *skb)
+{
+ secpath_reset(skb);
+}
+#endif
+
+#endif /* __BACKPORT_NET_XFRM_H */