mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02: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
					
				
					 2 changed files with 130 additions and 8 deletions
				
			
		| 
						 | 
				
			
			@ -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_strcmp(const struct nlattr *nla, const char *str);
 | 
			
		||||
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);
 | 
			
		||||
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_put(struct sk_buff *skb, int attrtype, int attrlen,
 | 
			
		||||
	       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);
 | 
			
		||||
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_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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 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
 | 
			
		||||
 * @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)
 | 
			
		||||
{
 | 
			
		||||
#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.  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) &&
 | 
			
		||||
	if (nla_need_padding_for_64bit(skb) &&
 | 
			
		||||
	    !nla_reserve(skb, padattr, 0))
 | 
			
		||||
		return -EMSGSIZE;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	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);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * __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
 | 
			
		||||
 * @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);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 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
 | 
			
		||||
 * @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);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * __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
 | 
			
		||||
 * @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);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 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
 | 
			
		||||
 * @skb: socket buffer to add attribute to
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue