2005-11-10 04:25:51 +03:00
# ifndef __NET_NETLINK_H
# define __NET_NETLINK_H
# include <linux/types.h>
# include <linux/netlink.h>
2006-12-04 07:15:30 +03:00
# include <linux/jiffies.h>
2005-11-10 04:25:51 +03:00
/* ========================================================================
* Netlink Messages and Attributes Interface ( As Seen On TV )
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Messages Interface
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*
* Message Format :
* < - - - nlmsg_total_size ( payload ) - - - >
* < - - nlmsg_msg_size ( payload ) - >
* + - - - - - - - - - - + - - - + - - - - - - - - - - - - - + - - - + - - - - - - - - - -
* | nlmsghdr | Pad | Payload | Pad | nlmsghdr
* + - - - - - - - - - - + - - - + - - - - - - - - - - - - - + - - - + - - - - - - - - - -
* nlmsg_data ( nlh ) - - - ^ ^
* nlmsg_next ( nlh ) - - - - - - - - - - - - - - - - - - - - - - - +
*
* Payload Format :
* < - - - - - - - - - - - - - - - - - - - - - - nlmsg_len ( nlh ) - - - - - - - - - - - - - - - - - - - - - >
* < - - - - - - hdrlen - - - - - - > < - nlmsg_attrlen ( nlh , hdrlen ) - >
* + - - - - - - - - - - - - - - - - - - - - - - + - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
* | Family Header | Pad | Attributes |
* + - - - - - - - - - - - - - - - - - - - - - - + - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
* nlmsg_attrdata ( nlh , hdrlen ) - - - ^
*
* Data Structures :
* struct nlmsghdr netlink message header
*
* Message Construction :
* nlmsg_new ( ) create a new netlink message
* nlmsg_put ( ) add a netlink message to an skb
* nlmsg_put_answer ( ) callback based nlmsg_put ( )
* nlmsg_end ( ) finanlize netlink message
2006-08-05 10:03:05 +04:00
* nlmsg_get_pos ( ) return current position in message
* nlmsg_trim ( ) trim part of message
2005-11-10 04:25:51 +03:00
* nlmsg_cancel ( ) cancel message construction
* nlmsg_free ( ) free a netlink message
*
* Message Sending :
* nlmsg_multicast ( ) multicast message to several groups
* nlmsg_unicast ( ) unicast a message to a single socket
2006-08-15 11:31:06 +04:00
* nlmsg_notify ( ) send notification message
2005-11-10 04:25:51 +03:00
*
* Message Length Calculations :
* nlmsg_msg_size ( payload ) length of message w / o padding
* nlmsg_total_size ( payload ) length of message w / padding
* nlmsg_padlen ( payload ) length of padding at tail
*
* Message Payload Access :
* nlmsg_data ( nlh ) head of message payload
* nlmsg_len ( nlh ) length of message payload
* nlmsg_attrdata ( nlh , hdrlen ) head of attributes data
* nlmsg_attrlen ( nlh , hdrlen ) length of attributes data
*
* Message Parsing :
* nlmsg_ok ( nlh , remaining ) does nlh fit into remaining bytes ?
* nlmsg_next ( nlh , remaining ) get next netlink message
* nlmsg_parse ( ) parse attributes of a message
* nlmsg_find_attr ( ) find an attribute in a message
* nlmsg_for_each_msg ( ) loop over all messages
* nlmsg_validate ( ) validate netlink message incl . attrs
* nlmsg_for_each_attr ( ) loop over all attributes
*
2006-08-15 11:31:41 +04:00
* Misc :
* nlmsg_report ( ) report back to application ?
*
2005-11-10 04:25:51 +03:00
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Attributes Interface
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*
* Attribute Format :
* < - - - - - - - nla_total_size ( payload ) - - - - - - - >
* < - - - - nla_attr_size ( payload ) - - - - - >
* + - - - - - - - - - - + - - - + - - - - - - - - - + - - - + - - - - - - - - - -
* | Header | Pad | Payload | Pad | Header
* + - - - - - - - - - - + - - - + - - - - - - - - - + - - - + - - - - - - - - - -
* < - nla_len ( nla ) - > ^
* nla_data ( nla ) - - - - ^ |
* nla_next ( nla ) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - '
*
* Data Structures :
* struct nlattr netlink attribtue header
*
* Attribute Construction :
2006-08-05 10:03:05 +04:00
* nla_reserve ( skb , type , len ) reserve room for an attribute
* nla_reserve_nohdr ( skb , len ) reserve room for an attribute w / o hdr
2005-11-10 04:25:51 +03:00
* nla_put ( skb , type , len , data ) add attribute to skb
2006-08-05 10:03:05 +04:00
* nla_put_nohdr ( skb , len , data ) add attribute w / o hdr
2005-11-10 04:25:51 +03:00
*
* Attribute Construction for Basic Types :
* nla_put_u8 ( skb , type , value ) add u8 attribute to skb
* nla_put_u16 ( skb , type , value ) add u16 attribute to skb
* nla_put_u32 ( skb , type , value ) add u32 attribute to skb
* nla_put_u64 ( skb , type , value ) add u64 attribute to skb
* nla_put_string ( skb , type , str ) add string attribute to skb
* nla_put_flag ( skb , type ) add flag attribute to skb
* nla_put_msecs ( skb , type , jiffies ) add msecs attribute to skb
*
* Exceptions Based Attribute Construction :
* NLA_PUT ( skb , type , len , data ) add attribute to skb
* NLA_PUT_U8 ( skb , type , value ) add u8 attribute to skb
* NLA_PUT_U16 ( skb , type , value ) add u16 attribute to skb
* NLA_PUT_U32 ( skb , type , value ) add u32 attribute to skb
* NLA_PUT_U64 ( skb , type , value ) add u64 attribute to skb
* NLA_PUT_STRING ( skb , type , str ) add string attribute to skb
* NLA_PUT_FLAG ( skb , type ) add flag attribute to skb
* NLA_PUT_MSECS ( skb , type , jiffies ) add msecs attribute to skb
*
* The meaning of these functions is equal to their lower case
* variants but they jump to the label nla_put_failure in case
* of a failure .
*
* Nested Attributes Construction :
* nla_nest_start ( skb , type ) start a nested attribute
* nla_nest_end ( skb , nla ) finalize a nested attribute
* nla_nest_cancel ( skb , nla ) cancel nested attribute construction
*
* Attribute Length Calculations :
* nla_attr_size ( payload ) length of attribute w / o padding
* nla_total_size ( payload ) length of attribute w / padding
* nla_padlen ( payload ) length of padding
*
* Attribute Payload Access :
* nla_data ( nla ) head of attribute payload
* nla_len ( nla ) length of attribute payload
*
* Attribute Payload Access for Basic Types :
* nla_get_u8 ( nla ) get payload for a u8 attribute
* nla_get_u16 ( nla ) get payload for a u16 attribute
* nla_get_u32 ( nla ) get payload for a u32 attribute
* nla_get_u64 ( nla ) get payload for a u64 attribute
* nla_get_flag ( nla ) return 1 if flag is true
* nla_get_msecs ( nla ) get payload for a msecs attribute
*
* Attribute Misc :
* nla_memcpy ( dest , nla , count ) copy attribute into memory
* nla_memcmp ( nla , data , size ) compare attribute with memory area
* nla_strlcpy ( dst , nla , size ) copy attribute to a sized string
* nla_strcmp ( nla , str ) compare attribute with string
*
* Attribute Parsing :
* nla_ok ( nla , remaining ) does nla fit into remaining bytes ?
* nla_next ( nla , remaining ) get next netlink attribute
* nla_validate ( ) validate a stream of attributes
2006-09-26 02:54:03 +04:00
* nla_validate_nested ( ) validate a stream of nested attributes
2005-11-10 04:25:51 +03:00
* nla_find ( ) find attribute in stream of attributes
2006-08-05 10:03:05 +04:00
* nla_find_nested ( ) find attribute in nested attributes
2005-11-10 04:25:51 +03:00
* nla_parse ( ) parse and validate stream of attrs
* nla_parse_nested ( ) parse nested attribuets
* nla_for_each_attr ( ) loop over all attributes
2006-09-26 02:53:37 +04:00
* nla_for_each_nested ( ) loop over the nested attributes
2005-11-10 04:25:51 +03:00
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/**
* Standard attribute types to specify validation policy
*/
enum {
NLA_UNSPEC ,
NLA_U8 ,
NLA_U16 ,
NLA_U32 ,
NLA_U64 ,
NLA_STRING ,
NLA_FLAG ,
NLA_MSECS ,
NLA_NESTED ,
2006-08-27 07:11:47 +04:00
NLA_NUL_STRING ,
2005-11-10 04:25:51 +03:00
__NLA_TYPE_MAX ,
} ;
# define NLA_TYPE_MAX (__NLA_TYPE_MAX - 1)
/**
* struct nla_policy - attribute validation policy
* @ type : Type of attribute or NLA_UNSPEC
2006-08-27 07:11:47 +04:00
* @ len : Type specific length of payload
2005-11-10 04:25:51 +03:00
*
* Policies are defined as arrays of this struct , the array must be
* accessible by attribute type up to the highest identifier to be expected .
*
2006-08-27 07:11:47 +04:00
* Meaning of ` len ' field :
* NLA_STRING Maximum length of string
* NLA_NUL_STRING Maximum length of string ( excluding NUL )
* NLA_FLAG Unused
* All other Exact length of attribute payload
*
2005-11-10 04:25:51 +03:00
* Example :
* static struct nla_policy my_policy [ ATTR_MAX + 1 ] __read_mostly = {
* [ ATTR_FOO ] = { . type = NLA_U16 } ,
2006-08-27 07:11:47 +04:00
* [ ATTR_BAR ] = { . type = NLA_STRING , len = BARSIZ } ,
* [ ATTR_BAZ ] = { . len = sizeof ( struct mystruct ) } ,
2005-11-10 04:25:51 +03:00
* } ;
*/
struct nla_policy {
u16 type ;
2006-08-27 07:11:47 +04:00
u16 len ;
2005-11-10 04:25:51 +03:00
} ;
2006-08-18 05:14:52 +04:00
/**
* struct nl_info - netlink source information
* @ nlh : Netlink message header of original request
* @ pid : Netlink PID of requesting application
*/
struct nl_info {
struct nlmsghdr * nlh ;
u32 pid ;
} ;
2005-11-10 04:25:53 +03:00
extern void netlink_run_queue ( struct sock * sk , unsigned int * qlen ,
int ( * cb ) ( struct sk_buff * ,
struct nlmsghdr * , int * ) ) ;
extern void netlink_queue_skip ( struct nlmsghdr * nlh ,
struct sk_buff * skb ) ;
2006-08-15 11:31:41 +04:00
extern int nlmsg_notify ( struct sock * sk , struct sk_buff * skb ,
u32 pid , unsigned int group , int report ,
gfp_t flags ) ;
2005-11-10 04:25:53 +03:00
2005-11-10 04:25:51 +03:00
extern int nla_validate ( struct nlattr * head , int len , int maxtype ,
struct nla_policy * policy ) ;
extern int nla_parse ( struct nlattr * tb [ ] , int maxtype ,
struct nlattr * head , int len ,
struct nla_policy * policy ) ;
extern struct nlattr * nla_find ( struct nlattr * head , int len , int attrtype ) ;
extern size_t nla_strlcpy ( char * dst , const struct nlattr * nla ,
size_t dstsize ) ;
extern int nla_memcpy ( void * dest , struct nlattr * src , int count ) ;
extern int nla_memcmp ( const struct nlattr * nla , const void * data ,
size_t size ) ;
extern int nla_strcmp ( const struct nlattr * nla , const char * str ) ;
extern struct nlattr * __nla_reserve ( struct sk_buff * skb , int attrtype ,
int attrlen ) ;
2006-08-05 10:03:05 +04:00
extern void * __nla_reserve_nohdr ( struct sk_buff * skb , int attrlen ) ;
2005-11-10 04:25:51 +03:00
extern struct nlattr * nla_reserve ( struct sk_buff * skb , int attrtype ,
int attrlen ) ;
2006-08-05 10:03:05 +04:00
extern void * nla_reserve_nohdr ( struct sk_buff * skb , int attrlen ) ;
2005-11-10 04:25:51 +03:00
extern void __nla_put ( struct sk_buff * skb , int attrtype ,
int attrlen , const void * data ) ;
2006-08-05 10:03:05 +04:00
extern void __nla_put_nohdr ( struct sk_buff * skb , int attrlen ,
const void * data ) ;
2005-11-10 04:25:51 +03:00
extern int nla_put ( struct sk_buff * skb , int attrtype ,
int attrlen , const void * data ) ;
2006-08-05 10:03:05 +04:00
extern int nla_put_nohdr ( struct sk_buff * skb , int attrlen ,
const void * data ) ;
2005-11-10 04:25:51 +03:00
/**************************************************************************
* Netlink Messages
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* nlmsg_msg_size - length of netlink message not including padding
* @ payload : length of message payload
*/
static inline int nlmsg_msg_size ( int payload )
{
return NLMSG_HDRLEN + payload ;
}
/**
* nlmsg_total_size - length of netlink message including padding
* @ payload : length of message payload
*/
static inline int nlmsg_total_size ( int payload )
{
return NLMSG_ALIGN ( nlmsg_msg_size ( payload ) ) ;
}
/**
* nlmsg_padlen - length of padding at the message ' s tail
* @ payload : length of message payload
*/
static inline int nlmsg_padlen ( int payload )
{
return nlmsg_total_size ( payload ) - nlmsg_msg_size ( payload ) ;
}
/**
* nlmsg_data - head of message payload
* @ nlh : netlink messsage header
*/
static inline void * nlmsg_data ( const struct nlmsghdr * nlh )
{
return ( unsigned char * ) nlh + NLMSG_HDRLEN ;
}
/**
* nlmsg_len - length of message payload
* @ nlh : netlink message header
*/
static inline int nlmsg_len ( const struct nlmsghdr * nlh )
{
return nlh - > nlmsg_len - NLMSG_HDRLEN ;
}
/**
* nlmsg_attrdata - head of attributes data
* @ nlh : netlink message header
* @ hdrlen : length of family specific header
*/
static inline struct nlattr * nlmsg_attrdata ( const struct nlmsghdr * nlh ,
int hdrlen )
{
unsigned char * data = nlmsg_data ( nlh ) ;
return ( struct nlattr * ) ( data + NLMSG_ALIGN ( hdrlen ) ) ;
}
/**
* nlmsg_attrlen - length of attributes data
* @ nlh : netlink message header
* @ hdrlen : length of family specific header
*/
static inline int nlmsg_attrlen ( const struct nlmsghdr * nlh , int hdrlen )
{
return nlmsg_len ( nlh ) - NLMSG_ALIGN ( hdrlen ) ;
}
/**
* nlmsg_ok - check if the netlink message fits into the remaining bytes
* @ nlh : netlink message header
* @ remaining : number of bytes remaining in message stream
*/
static inline int nlmsg_ok ( const struct nlmsghdr * nlh , int remaining )
{
return ( remaining > = sizeof ( struct nlmsghdr ) & &
nlh - > nlmsg_len > = sizeof ( struct nlmsghdr ) & &
nlh - > nlmsg_len < = remaining ) ;
}
/**
* nlmsg_next - next netlink message in message stream
* @ nlh : netlink message header
* @ remaining : number of bytes remaining in message stream
*
* Returns the next netlink message in the message stream and
* decrements remaining by the size of the current message .
*/
static inline struct nlmsghdr * nlmsg_next ( struct nlmsghdr * nlh , int * remaining )
{
int totlen = NLMSG_ALIGN ( nlh - > nlmsg_len ) ;
* remaining - = totlen ;
return ( struct nlmsghdr * ) ( ( unsigned char * ) nlh + totlen ) ;
}
/**
* nlmsg_parse - parse attributes of a netlink message
* @ nlh : netlink message header
* @ hdrlen : length of family specific header
* @ tb : destination array with maxtype + 1 elements
* @ maxtype : maximum attribute type to be expected
* @ policy : validation policy
*
* See nla_parse ( )
*/
static inline int nlmsg_parse ( struct nlmsghdr * nlh , int hdrlen ,
struct nlattr * tb [ ] , int maxtype ,
struct nla_policy * policy )
{
if ( nlh - > nlmsg_len < nlmsg_msg_size ( hdrlen ) )
return - EINVAL ;
return nla_parse ( tb , maxtype , nlmsg_attrdata ( nlh , hdrlen ) ,
nlmsg_attrlen ( nlh , hdrlen ) , policy ) ;
}
/**
* nlmsg_find_attr - find a specific attribute in a netlink message
* @ nlh : netlink message header
* @ hdrlen : length of familiy specific header
* @ attrtype : type of attribute to look for
*
* Returns the first attribute which matches the specified type .
*/
static inline struct nlattr * nlmsg_find_attr ( struct nlmsghdr * nlh ,
int hdrlen , int attrtype )
{
return nla_find ( nlmsg_attrdata ( nlh , hdrlen ) ,
nlmsg_attrlen ( nlh , hdrlen ) , attrtype ) ;
}
/**
* nlmsg_validate - validate a netlink message including attributes
* @ nlh : netlinket message header
* @ hdrlen : length of familiy specific header
* @ maxtype : maximum attribute type to be expected
* @ policy : validation policy
*/
static inline int nlmsg_validate ( struct nlmsghdr * nlh , int hdrlen , int maxtype ,
struct nla_policy * policy )
{
if ( nlh - > nlmsg_len < nlmsg_msg_size ( hdrlen ) )
return - EINVAL ;
return nla_validate ( nlmsg_attrdata ( nlh , hdrlen ) ,
nlmsg_attrlen ( nlh , hdrlen ) , maxtype , policy ) ;
}
2006-08-15 11:31:41 +04:00
/**
* nlmsg_report - need to report back to application ?
* @ nlh : netlink message header
*
* Returns 1 if a report back to the application is requested .
*/
static inline int nlmsg_report ( struct nlmsghdr * nlh )
{
return ! ! ( nlh - > nlmsg_flags & NLM_F_ECHO ) ;
}
2005-11-10 04:25:51 +03:00
/**
* nlmsg_for_each_attr - iterate over a stream of attributes
* @ pos : loop counter , set to current attribute
* @ nlh : netlink message header
* @ hdrlen : length of familiy specific header
* @ rem : initialized to len , holds bytes currently remaining in stream
*/
# define nlmsg_for_each_attr(pos, nlh, hdrlen, rem) \
nla_for_each_attr ( pos , nlmsg_attrdata ( nlh , hdrlen ) , \
nlmsg_attrlen ( nlh , hdrlen ) , rem )
#if 0
/* FIXME: Enable once all users have been converted */
/**
* __nlmsg_put - Add a new netlink message to an skb
* @ skb : socket buffer to store message in
* @ pid : netlink process id
* @ seq : sequence number of message
* @ type : message type
* @ payload : length of message payload
* @ flags : message flags
*
* The caller is responsible to ensure that the skb provides enough
* tailroom for both the netlink header and payload .
*/
static inline struct nlmsghdr * __nlmsg_put ( struct sk_buff * skb , u32 pid ,
u32 seq , int type , int payload ,
int flags )
{
struct nlmsghdr * nlh ;
nlh = ( struct nlmsghdr * ) skb_put ( skb , nlmsg_total_size ( payload ) ) ;
nlh - > nlmsg_type = type ;
nlh - > nlmsg_len = nlmsg_msg_size ( payload ) ;
nlh - > nlmsg_flags = flags ;
nlh - > nlmsg_pid = pid ;
nlh - > nlmsg_seq = seq ;
memset ( ( unsigned char * ) nlmsg_data ( nlh ) + payload , 0 ,
nlmsg_padlen ( payload ) ) ;
return nlh ;
}
# endif
/**
* nlmsg_put - Add a new netlink message to an skb
* @ skb : socket buffer to store message in
* @ pid : netlink process id
* @ seq : sequence number of message
* @ type : message type
* @ payload : length of message payload
* @ flags : message flags
*
* Returns NULL if the tailroom of the skb is insufficient to store
* the message header and payload .
*/
static inline struct nlmsghdr * nlmsg_put ( struct sk_buff * skb , u32 pid , u32 seq ,
int type , int payload , int flags )
{
if ( unlikely ( skb_tailroom ( skb ) < nlmsg_total_size ( payload ) ) )
return NULL ;
return __nlmsg_put ( skb , pid , seq , type , payload , flags ) ;
}
/**
* nlmsg_put_answer - Add a new callback based netlink message to an skb
* @ skb : socket buffer to store message in
* @ cb : netlink callback
* @ type : message type
* @ payload : length of message payload
* @ flags : message flags
*
* Returns NULL if the tailroom of the skb is insufficient to store
* the message header and payload .
*/
static inline struct nlmsghdr * nlmsg_put_answer ( struct sk_buff * skb ,
struct netlink_callback * cb ,
int type , int payload ,
int flags )
{
return nlmsg_put ( skb , NETLINK_CB ( cb - > skb ) . pid , cb - > nlh - > nlmsg_seq ,
type , payload , flags ) ;
}
/**
* nlmsg_new - Allocate a new netlink message
2006-11-11 01:10:15 +03:00
* @ payload : size of the message payload
2006-08-05 10:03:05 +04:00
* @ flags : the type of memory to allocate .
2005-11-10 04:25:51 +03:00
*
2006-11-11 01:10:15 +03:00
* Use NLMSG_DEFAULT_SIZE if the size of the payload isn ' t known
* and a good default is needed .
2005-11-10 04:25:51 +03:00
*/
2006-11-11 01:10:15 +03:00
static inline struct sk_buff * nlmsg_new ( size_t payload , gfp_t flags )
2005-11-10 04:25:51 +03:00
{
2006-11-11 01:10:15 +03:00
return alloc_skb ( nlmsg_total_size ( payload ) , flags ) ;
2005-11-10 04:25:51 +03:00
}
/**
* nlmsg_end - Finalize a netlink message
* @ skb : socket buffer the message is stored in
* @ nlh : netlink message header
*
* Corrects the netlink message header to include the appeneded
* attributes . Only necessary if attributes have been added to
* the message .
*
* Returns the total data length of the skb .
*/
static inline int nlmsg_end ( struct sk_buff * skb , struct nlmsghdr * nlh )
{
nlh - > nlmsg_len = skb - > tail - ( unsigned char * ) nlh ;
return skb - > len ;
}
2006-08-05 10:03:05 +04:00
/**
* nlmsg_get_pos - return current position in netlink message
* @ skb : socket buffer the message is stored in
*
* Returns a pointer to the current tail of the message .
*/
static inline void * nlmsg_get_pos ( struct sk_buff * skb )
{
return skb - > tail ;
}
/**
* nlmsg_trim - Trim message to a mark
* @ skb : socket buffer the message is stored in
* @ mark : mark to trim to
*
* Trims the message to the provided mark . Returns - 1.
*/
static inline int nlmsg_trim ( struct sk_buff * skb , void * mark )
{
if ( mark )
skb_trim ( skb , ( unsigned char * ) mark - skb - > data ) ;
return - 1 ;
}
2005-11-10 04:25:51 +03:00
/**
* nlmsg_cancel - Cancel construction of a netlink message
* @ skb : socket buffer the message is stored in
* @ nlh : netlink message header
*
* Removes the complete netlink message including all
* attributes from the socket buffer again . Returns - 1.
*/
static inline int nlmsg_cancel ( struct sk_buff * skb , struct nlmsghdr * nlh )
{
2006-08-05 10:03:05 +04:00
return nlmsg_trim ( skb , nlh ) ;
2005-11-10 04:25:51 +03:00
}
/**
* nlmsg_free - free a netlink message
* @ skb : socket buffer of netlink message
*/
static inline void nlmsg_free ( struct sk_buff * skb )
{
kfree_skb ( skb ) ;
}
/**
* nlmsg_multicast - multicast a netlink message
* @ sk : netlink socket to spread messages to
* @ skb : netlink message as socket buffer
* @ pid : own netlink pid to avoid sending to yourself
* @ group : multicast group id
2006-08-15 11:31:06 +04:00
* @ flags : allocation flags
2005-11-10 04:25:51 +03:00
*/
static inline int nlmsg_multicast ( struct sock * sk , struct sk_buff * skb ,
2006-08-15 11:31:06 +04:00
u32 pid , unsigned int group , gfp_t flags )
2005-11-10 04:25:51 +03:00
{
int err ;
NETLINK_CB ( skb ) . dst_group = group ;
2006-08-15 11:31:06 +04:00
err = netlink_broadcast ( sk , skb , pid , group , flags ) ;
2005-11-10 04:25:51 +03:00
if ( err > 0 )
err = 0 ;
return err ;
}
/**
* nlmsg_unicast - unicast a netlink message
* @ sk : netlink socket to spread message to
* @ skb : netlink message as socket buffer
* @ pid : netlink pid of the destination socket
*/
static inline int nlmsg_unicast ( struct sock * sk , struct sk_buff * skb , u32 pid )
{
int err ;
err = netlink_unicast ( sk , skb , pid , MSG_DONTWAIT ) ;
if ( err > 0 )
err = 0 ;
return err ;
}
/**
* nlmsg_for_each_msg - iterate over a stream of messages
* @ pos : loop counter , set to current message
* @ head : head of message stream
* @ len : length of message stream
* @ rem : initialized to len , holds bytes currently remaining in stream
*/
# define nlmsg_for_each_msg(pos, head, len, rem) \
for ( pos = head , rem = len ; \
nlmsg_ok ( pos , rem ) ; \
pos = nlmsg_next ( pos , & ( rem ) ) )
/**************************************************************************
* Netlink Attributes
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* nla_attr_size - length of attribute not including padding
* @ payload : length of payload
*/
static inline int nla_attr_size ( int payload )
{
return NLA_HDRLEN + payload ;
}
/**
* nla_total_size - total length of attribute including padding
* @ payload : length of payload
*/
static inline int nla_total_size ( int payload )
{
return NLA_ALIGN ( nla_attr_size ( payload ) ) ;
}
/**
* nla_padlen - length of padding at the tail of attribute
* @ payload : length of payload
*/
static inline int nla_padlen ( int payload )
{
return nla_total_size ( payload ) - nla_attr_size ( payload ) ;
}
/**
* nla_data - head of payload
* @ nla : netlink attribute
*/
static inline void * nla_data ( const struct nlattr * nla )
{
return ( char * ) nla + NLA_HDRLEN ;
}
/**
* nla_len - length of payload
* @ nla : netlink attribute
*/
static inline int nla_len ( const struct nlattr * nla )
{
return nla - > nla_len - NLA_HDRLEN ;
}
/**
* nla_ok - check if the netlink attribute fits into the remaining bytes
* @ nla : netlink attribute
* @ remaining : number of bytes remaining in attribute stream
*/
static inline int nla_ok ( const struct nlattr * nla , int remaining )
{
return remaining > = sizeof ( * nla ) & &
nla - > nla_len > = sizeof ( * nla ) & &
nla - > nla_len < = remaining ;
}
/**
* nla_next - next netlink attribte in attribute stream
* @ nla : netlink attribute
* @ remaining : number of bytes remaining in attribute stream
*
* Returns the next netlink attribute in the attribute stream and
* decrements remaining by the size of the current attribute .
*/
static inline struct nlattr * nla_next ( const struct nlattr * nla , int * remaining )
{
int totlen = NLA_ALIGN ( nla - > nla_len ) ;
* remaining - = totlen ;
return ( struct nlattr * ) ( ( char * ) nla + totlen ) ;
}
2006-08-05 10:03:05 +04:00
/**
* nla_find_nested - find attribute in a set of nested attributes
* @ nla : attribute containing the nested attributes
* @ attrtype : type of attribute to look for
*
* Returns the first attribute which matches the specified type .
*/
static inline struct nlattr * nla_find_nested ( struct nlattr * nla , int attrtype )
{
return nla_find ( nla_data ( nla ) , nla_len ( nla ) , attrtype ) ;
}
2005-11-10 04:25:51 +03:00
/**
* nla_parse_nested - parse nested attributes
* @ tb : destination array with maxtype + 1 elements
* @ maxtype : maximum attribute type to be expected
* @ nla : attribute containing the nested attributes
* @ policy : validation policy
*
* See nla_parse ( )
*/
static inline int nla_parse_nested ( struct nlattr * tb [ ] , int maxtype ,
struct nlattr * nla ,
struct nla_policy * policy )
{
return nla_parse ( tb , maxtype , nla_data ( nla ) , nla_len ( nla ) , policy ) ;
}
/**
* nla_put_u8 - Add a u16 netlink attribute to a socket buffer
* @ skb : socket buffer to add attribute to
* @ attrtype : attribute type
* @ value : numeric value
*/
static inline int nla_put_u8 ( struct sk_buff * skb , int attrtype , u8 value )
{
return nla_put ( skb , attrtype , sizeof ( u8 ) , & value ) ;
}
/**
* nla_put_u16 - Add a u16 netlink attribute to a socket buffer
* @ skb : socket buffer to add attribute to
* @ attrtype : attribute type
* @ value : numeric value
*/
static inline int nla_put_u16 ( struct sk_buff * skb , int attrtype , u16 value )
{
return nla_put ( skb , attrtype , sizeof ( u16 ) , & value ) ;
}
/**
* nla_put_u32 - Add a u32 netlink attribute to a socket buffer
* @ skb : socket buffer to add attribute to
* @ attrtype : attribute type
* @ value : numeric value
*/
static inline int nla_put_u32 ( struct sk_buff * skb , int attrtype , u32 value )
{
return nla_put ( skb , attrtype , sizeof ( u32 ) , & value ) ;
}
/**
* nla_put_64 - Add a u64 netlink attribute to a socket buffer
* @ skb : socket buffer to add attribute to
* @ attrtype : attribute type
* @ value : numeric value
*/
static inline int nla_put_u64 ( struct sk_buff * skb , int attrtype , u64 value )
{
return nla_put ( skb , attrtype , sizeof ( u64 ) , & value ) ;
}
/**
* nla_put_string - Add a string netlink attribute to a socket buffer
* @ skb : socket buffer to add attribute to
* @ attrtype : attribute type
* @ str : NUL terminated string
*/
static inline int nla_put_string ( struct sk_buff * skb , int attrtype ,
const char * str )
{
return nla_put ( skb , attrtype , strlen ( str ) + 1 , str ) ;
}
/**
* nla_put_flag - Add a flag netlink attribute to a socket buffer
* @ skb : socket buffer to add attribute to
* @ attrtype : attribute type
*/
static inline int nla_put_flag ( struct sk_buff * skb , int attrtype )
{
return nla_put ( skb , attrtype , 0 , NULL ) ;
}
/**
* nla_put_msecs - Add a msecs netlink attribute to a socket buffer
* @ skb : socket buffer to add attribute to
* @ attrtype : attribute type
* @ jiffies : number of msecs in jiffies
*/
static inline int nla_put_msecs ( struct sk_buff * skb , int attrtype ,
unsigned long jiffies )
{
u64 tmp = jiffies_to_msecs ( jiffies ) ;
return nla_put ( skb , attrtype , sizeof ( u64 ) , & tmp ) ;
}
# define NLA_PUT(skb, attrtype, attrlen, data) \
do { \
if ( nla_put ( skb , attrtype , attrlen , data ) < 0 ) \
goto nla_put_failure ; \
} while ( 0 )
# define NLA_PUT_TYPE(skb, type, attrtype, value) \
do { \
type __tmp = value ; \
NLA_PUT ( skb , attrtype , sizeof ( type ) , & __tmp ) ; \
} while ( 0 )
# define NLA_PUT_U8(skb, attrtype, value) \
NLA_PUT_TYPE ( skb , u8 , attrtype , value )
# define NLA_PUT_U16(skb, attrtype, value) \
NLA_PUT_TYPE ( skb , u16 , attrtype , value )
2006-11-25 04:14:51 +03:00
# define NLA_PUT_LE16(skb, attrtype, value) \
NLA_PUT_TYPE ( skb , __le16 , attrtype , value )
2005-11-10 04:25:51 +03:00
# define NLA_PUT_U32(skb, attrtype, value) \
NLA_PUT_TYPE ( skb , u32 , attrtype , value )
2006-09-27 09:14:41 +04:00
# define NLA_PUT_BE32(skb, attrtype, value) \
NLA_PUT_TYPE ( skb , __be32 , attrtype , value )
2005-11-10 04:25:51 +03:00
# define NLA_PUT_U64(skb, attrtype, value) \
NLA_PUT_TYPE ( skb , u64 , attrtype , value )
# define NLA_PUT_STRING(skb, attrtype, value) \
NLA_PUT ( skb , attrtype , strlen ( value ) + 1 , value )
2006-08-27 06:17:53 +04:00
# define NLA_PUT_FLAG(skb, attrtype) \
2005-11-10 04:25:51 +03:00
NLA_PUT ( skb , attrtype , 0 , NULL )
# define NLA_PUT_MSECS(skb, attrtype, jiffies) \
NLA_PUT_U64 ( skb , attrtype , jiffies_to_msecs ( jiffies ) )
/**
* nla_get_u32 - return payload of u32 attribute
* @ nla : u32 netlink attribute
*/
static inline u32 nla_get_u32 ( struct nlattr * nla )
{
return * ( u32 * ) nla_data ( nla ) ;
}
2006-09-27 09:14:41 +04:00
/**
* nla_get_be32 - return payload of __be32 attribute
* @ nla : __be32 netlink attribute
*/
static inline __be32 nla_get_be32 ( struct nlattr * nla )
{
return * ( __be32 * ) nla_data ( nla ) ;
}
2005-11-10 04:25:51 +03:00
/**
* nla_get_u16 - return payload of u16 attribute
* @ nla : u16 netlink attribute
*/
static inline u16 nla_get_u16 ( struct nlattr * nla )
{
return * ( u16 * ) nla_data ( nla ) ;
}
2006-11-25 04:14:51 +03:00
/**
* nla_get_le16 - return payload of __le16 attribute
* @ nla : __le16 netlink attribute
*/
static inline __le16 nla_get_le16 ( struct nlattr * nla )
{
return * ( __le16 * ) nla_data ( nla ) ;
}
2005-11-10 04:25:51 +03:00
/**
* nla_get_u8 - return payload of u8 attribute
* @ nla : u8 netlink attribute
*/
static inline u8 nla_get_u8 ( struct nlattr * nla )
{
return * ( u8 * ) nla_data ( nla ) ;
}
/**
* nla_get_u64 - return payload of u64 attribute
* @ nla : u64 netlink attribute
*/
static inline u64 nla_get_u64 ( struct nlattr * nla )
{
u64 tmp ;
nla_memcpy ( & tmp , nla , sizeof ( tmp ) ) ;
return tmp ;
}
/**
* nla_get_flag - return payload of flag attribute
* @ nla : flag netlink attribute
*/
static inline int nla_get_flag ( struct nlattr * nla )
{
return ! ! nla ;
}
/**
* nla_get_msecs - return payload of msecs attribute
* @ nla : msecs netlink attribute
*
* Returns the number of milliseconds in jiffies .
*/
static inline unsigned long nla_get_msecs ( struct nlattr * nla )
{
u64 msecs = nla_get_u64 ( nla ) ;
return msecs_to_jiffies ( ( unsigned long ) msecs ) ;
}
/**
* nla_nest_start - Start a new level of nested attributes
* @ skb : socket buffer to add attributes to
* @ attrtype : attribute type of container
*
* Returns the container attribute
*/
static inline struct nlattr * nla_nest_start ( struct sk_buff * skb , int attrtype )
{
struct nlattr * start = ( struct nlattr * ) skb - > tail ;
if ( nla_put ( skb , attrtype , 0 , NULL ) < 0 )
return NULL ;
return start ;
}
/**
* nla_nest_end - Finalize nesting of attributes
* @ skb : socket buffer the attribtues are stored in
* @ start : container attribute
*
* Corrects the container attribute header to include the all
* appeneded attributes .
*
* Returns the total data length of the skb .
*/
static inline int nla_nest_end ( struct sk_buff * skb , struct nlattr * start )
{
start - > nla_len = skb - > tail - ( unsigned char * ) start ;
return skb - > len ;
}
/**
* nla_nest_cancel - Cancel nesting of attributes
* @ skb : socket buffer the message is stored in
* @ start : container attribute
*
* Removes the container attribute and including all nested
* attributes . Returns - 1.
*/
static inline int nla_nest_cancel ( struct sk_buff * skb , struct nlattr * start )
{
2006-08-05 10:03:05 +04:00
return nlmsg_trim ( skb , start ) ;
2005-11-10 04:25:51 +03:00
}
2006-09-26 02:54:03 +04:00
/**
* nla_validate_nested - Validate a stream of nested attributes
* @ start : container attribute
* @ maxtype : maximum attribute type to be expected
* @ policy : validation policy
*
* Validates all attributes in the nested attribute stream against the
* specified policy . Attributes with a type exceeding maxtype will be
* ignored . See documenation of struct nla_policy for more details .
*
* Returns 0 on success or a negative error code .
*/
static inline int nla_validate_nested ( struct nlattr * start , int maxtype ,
struct nla_policy * policy )
{
return nla_validate ( nla_data ( start ) , nla_len ( start ) , maxtype , policy ) ;
}
2005-11-10 04:25:51 +03:00
/**
* nla_for_each_attr - iterate over a stream of attributes
* @ pos : loop counter , set to current attribute
* @ head : head of attribute stream
* @ len : length of attribute stream
* @ rem : initialized to len , holds bytes currently remaining in stream
*/
# define nla_for_each_attr(pos, head, len, rem) \
for ( pos = head , rem = len ; \
nla_ok ( pos , rem ) ; \
pos = nla_next ( pos , & ( rem ) ) )
2006-08-05 10:03:05 +04:00
/**
* nla_for_each_nested - iterate over nested attributes
* @ pos : loop counter , set to current attribute
* @ nla : attribute containing the nested attributes
* @ rem : initialized to len , holds bytes currently remaining in stream
*/
# define nla_for_each_nested(pos, nla, rem) \
nla_for_each_attr ( pos , nla_data ( nla ) , nla_len ( nla ) , rem )
2005-11-10 04:25:51 +03:00
# endif