mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-07 22:42:04 +00:00
libnl: add more helpers to align attributes on 64-bit
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
732912d727
commit
089bf1a6a9
@ -244,13 +244,21 @@ int nla_memcpy(void *dest, const struct nlattr *src, int count);
|
|||||||
int nla_memcmp(const struct nlattr *nla, const void *data, size_t size);
|
int nla_memcmp(const struct nlattr *nla, const void *data, size_t size);
|
||||||
int nla_strcmp(const struct nlattr *nla, const char *str);
|
int nla_strcmp(const struct nlattr *nla, const char *str);
|
||||||
struct nlattr *__nla_reserve(struct sk_buff *skb, int attrtype, int attrlen);
|
struct nlattr *__nla_reserve(struct sk_buff *skb, int attrtype, int attrlen);
|
||||||
|
struct nlattr *__nla_reserve_64bit(struct sk_buff *skb, int attrtype,
|
||||||
|
int attrlen, int padattr);
|
||||||
void *__nla_reserve_nohdr(struct sk_buff *skb, int attrlen);
|
void *__nla_reserve_nohdr(struct sk_buff *skb, int attrlen);
|
||||||
struct nlattr *nla_reserve(struct sk_buff *skb, int attrtype, int attrlen);
|
struct nlattr *nla_reserve(struct sk_buff *skb, int attrtype, int attrlen);
|
||||||
|
struct nlattr *nla_reserve_64bit(struct sk_buff *skb, int attrtype,
|
||||||
|
int attrlen, int padattr);
|
||||||
void *nla_reserve_nohdr(struct sk_buff *skb, int attrlen);
|
void *nla_reserve_nohdr(struct sk_buff *skb, int attrlen);
|
||||||
void __nla_put(struct sk_buff *skb, int attrtype, int attrlen,
|
void __nla_put(struct sk_buff *skb, int attrtype, int attrlen,
|
||||||
const void *data);
|
const void *data);
|
||||||
|
void __nla_put_64bit(struct sk_buff *skb, int attrtype, int attrlen,
|
||||||
|
const void *data, int padattr);
|
||||||
void __nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data);
|
void __nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data);
|
||||||
int nla_put(struct sk_buff *skb, int attrtype, int attrlen, const void *data);
|
int nla_put(struct sk_buff *skb, int attrtype, int attrlen, const void *data);
|
||||||
|
int nla_put_64bit(struct sk_buff *skb, int attrtype, int attrlen,
|
||||||
|
const void *data, int padattr);
|
||||||
int nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data);
|
int nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data);
|
||||||
int nla_append(struct sk_buff *skb, int attrlen, const void *data);
|
int nla_append(struct sk_buff *skb, int attrlen, const void *data);
|
||||||
|
|
||||||
@ -1230,6 +1238,27 @@ static inline int nla_validate_nested(const struct nlattr *start, int maxtype,
|
|||||||
return nla_validate(nla_data(start), nla_len(start), maxtype, policy);
|
return nla_validate(nla_data(start), nla_len(start), maxtype, policy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
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
|
* nla_align_64bit - 64-bit align the nla_data() of next attribute
|
||||||
* @skb: socket buffer the message is stored in
|
* @skb: socket buffer the message is stored in
|
||||||
@ -1244,16 +1273,10 @@ static inline int nla_validate_nested(const struct nlattr *start, int maxtype,
|
|||||||
*/
|
*/
|
||||||
static inline int nla_align_64bit(struct sk_buff *skb, int padattr)
|
static inline int nla_align_64bit(struct sk_buff *skb, int padattr)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
|
if (nla_need_padding_for_64bit(skb) &&
|
||||||
/* The nlattr header is 4 bytes in size, that's why we test
|
|
||||||
* if the skb->data _is_ aligned. This 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) &&
|
|
||||||
!nla_reserve(skb, padattr, 0))
|
!nla_reserve(skb, padattr, 0))
|
||||||
return -EMSGSIZE;
|
return -EMSGSIZE;
|
||||||
#endif
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
99
lib/nlattr.c
99
lib/nlattr.c
@ -354,6 +354,29 @@ struct nlattr *__nla_reserve(struct sk_buff *skb, int attrtype, int attrlen)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(__nla_reserve);
|
EXPORT_SYMBOL(__nla_reserve);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __nla_reserve_64bit - reserve room for attribute on the skb and align it
|
||||||
|
* @skb: socket buffer to reserve room on
|
||||||
|
* @attrtype: attribute type
|
||||||
|
* @attrlen: length of attribute payload
|
||||||
|
*
|
||||||
|
* Adds a netlink attribute header to a socket buffer and reserves
|
||||||
|
* room for the payload but does not copy it. It also ensure that this
|
||||||
|
* attribute will be 64-bit aign.
|
||||||
|
*
|
||||||
|
* The caller is responsible to ensure that the skb provides enough
|
||||||
|
* tailroom for the attribute header and payload.
|
||||||
|
*/
|
||||||
|
struct nlattr *__nla_reserve_64bit(struct sk_buff *skb, int attrtype,
|
||||||
|
int attrlen, int padattr)
|
||||||
|
{
|
||||||
|
if (nla_need_padding_for_64bit(skb))
|
||||||
|
nla_align_64bit(skb, padattr);
|
||||||
|
|
||||||
|
return __nla_reserve(skb, attrtype, attrlen);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(__nla_reserve_64bit);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __nla_reserve_nohdr - reserve room for attribute without header
|
* __nla_reserve_nohdr - reserve room for attribute without header
|
||||||
* @skb: socket buffer to reserve room on
|
* @skb: socket buffer to reserve room on
|
||||||
@ -396,6 +419,35 @@ struct nlattr *nla_reserve(struct sk_buff *skb, int attrtype, int attrlen)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(nla_reserve);
|
EXPORT_SYMBOL(nla_reserve);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nla_reserve_64bit - reserve room for attribute on the skb and align it
|
||||||
|
* @skb: socket buffer to reserve room on
|
||||||
|
* @attrtype: attribute type
|
||||||
|
* @attrlen: length of attribute payload
|
||||||
|
*
|
||||||
|
* Adds a netlink attribute header to a socket buffer and reserves
|
||||||
|
* room for the payload but does not copy it. It also ensure that this
|
||||||
|
* attribute will be 64-bit aign.
|
||||||
|
*
|
||||||
|
* Returns NULL if the tailroom of the skb is insufficient to store
|
||||||
|
* the attribute header and payload.
|
||||||
|
*/
|
||||||
|
struct nlattr *nla_reserve_64bit(struct sk_buff *skb, int attrtype, int attrlen,
|
||||||
|
int padattr)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (nla_need_padding_for_64bit(skb))
|
||||||
|
len = nla_total_size_64bit(attrlen);
|
||||||
|
else
|
||||||
|
len = nla_total_size(attrlen);
|
||||||
|
if (unlikely(skb_tailroom(skb) < len))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return __nla_reserve_64bit(skb, attrtype, attrlen, padattr);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(nla_reserve_64bit);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nla_reserve_nohdr - reserve room for attribute without header
|
* nla_reserve_nohdr - reserve room for attribute without header
|
||||||
* @skb: socket buffer to reserve room on
|
* @skb: socket buffer to reserve room on
|
||||||
@ -435,6 +487,26 @@ void __nla_put(struct sk_buff *skb, int attrtype, int attrlen,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(__nla_put);
|
EXPORT_SYMBOL(__nla_put);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __nla_put_64bit - Add a netlink attribute to a socket buffer and align it
|
||||||
|
* @skb: socket buffer to add attribute to
|
||||||
|
* @attrtype: attribute type
|
||||||
|
* @attrlen: length of attribute payload
|
||||||
|
* @data: head of attribute payload
|
||||||
|
*
|
||||||
|
* The caller is responsible to ensure that the skb provides enough
|
||||||
|
* tailroom for the attribute header and payload.
|
||||||
|
*/
|
||||||
|
void __nla_put_64bit(struct sk_buff *skb, int attrtype, int attrlen,
|
||||||
|
const void *data, int padattr)
|
||||||
|
{
|
||||||
|
struct nlattr *nla;
|
||||||
|
|
||||||
|
nla = __nla_reserve_64bit(skb, attrtype, attrlen, padattr);
|
||||||
|
memcpy(nla_data(nla), data, attrlen);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(__nla_put_64bit);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __nla_put_nohdr - Add a netlink attribute without header
|
* __nla_put_nohdr - Add a netlink attribute without header
|
||||||
* @skb: socket buffer to add attribute to
|
* @skb: socket buffer to add attribute to
|
||||||
@ -473,6 +545,33 @@ int nla_put(struct sk_buff *skb, int attrtype, int attrlen, const void *data)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(nla_put);
|
EXPORT_SYMBOL(nla_put);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nla_put_64bit - Add a netlink attribute to a socket buffer and align it
|
||||||
|
* @skb: socket buffer to add attribute to
|
||||||
|
* @attrtype: attribute type
|
||||||
|
* @attrlen: length of attribute payload
|
||||||
|
* @data: head of attribute payload
|
||||||
|
*
|
||||||
|
* Returns -EMSGSIZE if the tailroom of the skb is insufficient to store
|
||||||
|
* the attribute header and payload.
|
||||||
|
*/
|
||||||
|
int nla_put_64bit(struct sk_buff *skb, int attrtype, int attrlen,
|
||||||
|
const void *data, int padattr)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (nla_need_padding_for_64bit(skb))
|
||||||
|
len = nla_total_size_64bit(attrlen);
|
||||||
|
else
|
||||||
|
len = nla_total_size(attrlen);
|
||||||
|
if (unlikely(skb_tailroom(skb) < len))
|
||||||
|
return -EMSGSIZE;
|
||||||
|
|
||||||
|
__nla_put_64bit(skb, attrtype, attrlen, data, padattr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(nla_put_64bit);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nla_put_nohdr - Add a netlink attribute without header
|
* nla_put_nohdr - Add a netlink attribute without header
|
||||||
* @skb: socket buffer to add attribute to
|
* @skb: socket buffer to add attribute to
|
||||||
|
Loading…
Reference in New Issue
Block a user