diff options
Diffstat (limited to 'backport-include/net/netlink.h')
-rw-r--r-- | backport-include/net/netlink.h | 722 |
1 files changed, 722 insertions, 0 deletions
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 */ |