2005-11-10 04:25:56 +03:00
# ifndef __NET_GENERIC_NETLINK_H
# define __NET_GENERIC_NETLINK_H
# include <linux/genetlink.h>
# include <net/netlink.h>
2009-07-10 13:51:34 +04:00
# include <net/net_namespace.h>
2005-11-10 04:25:56 +03:00
2007-07-19 02:47:52 +04:00
/**
* struct genl_multicast_group - generic netlink multicast group
* @ name : name of the multicast group , names are per - family
* @ id : multicast group ID , assigned by the core , to use with
* genlmsg_multicast ( ) .
* @ list : list entry for linking
* @ family : pointer to family , need not be set before registering
*/
2009-11-03 06:26:03 +03:00
struct genl_multicast_group {
2007-07-19 02:47:52 +04:00
struct genl_family * family ; /* private */
struct list_head list ; /* private */
char name [ GENL_NAMSIZ ] ;
u32 id ;
} ;
2010-10-04 23:14:03 +04:00
struct genl_ops ;
struct genl_info ;
2005-11-10 04:25:56 +03:00
/**
* struct genl_family - generic netlink family
* @ id : protocol family idenfitier
* @ hdrsize : length of user specific header in bytes
* @ name : name of family
* @ version : protocol version
* @ maxattr : maximum number of attributes supported
2009-07-10 13:51:34 +04:00
* @ netnsok : set to true if the family can handle network
* namespaces and should be presented in all of them
2010-10-04 23:14:03 +04:00
* @ pre_doit : called before an operation ' s doit callback , it may
* do additional , common , filtering and return an error
* @ post_doit : called after an operation ' s doit callback , it may
* undo operations done by pre_doit , for example release locks
2005-11-10 04:25:56 +03:00
* @ attrbuf : buffer to store parsed attributes
* @ ops_list : list of all assigned operations
* @ family_list : family list
2007-07-19 02:47:52 +04:00
* @ mcast_groups : multicast groups list
2005-11-10 04:25:56 +03:00
*/
2009-11-03 06:26:03 +03:00
struct genl_family {
2005-11-10 04:25:56 +03:00
unsigned int id ;
unsigned int hdrsize ;
char name [ GENL_NAMSIZ ] ;
unsigned int version ;
unsigned int maxattr ;
2009-07-10 13:51:34 +04:00
bool netnsok ;
2010-10-04 23:14:03 +04:00
int ( * pre_doit ) ( struct genl_ops * ops ,
struct sk_buff * skb ,
struct genl_info * info ) ;
void ( * post_doit ) ( struct genl_ops * ops ,
struct sk_buff * skb ,
struct genl_info * info ) ;
2005-11-10 04:25:56 +03:00
struct nlattr * * attrbuf ; /* private */
struct list_head ops_list ; /* private */
struct list_head family_list ; /* private */
2007-07-19 02:47:52 +04:00
struct list_head mcast_groups ; /* private */
2005-11-10 04:25:56 +03:00
} ;
/**
* struct genl_info - receiving information
* @ snd_seq : sending sequence number
* @ snd_pid : netlink pid of sender
* @ nlhdr : netlink message header
* @ genlhdr : generic netlink message header
* @ userhdr : user specific header
* @ attrs : netlink attributes
2010-10-04 23:14:03 +04:00
* @ _net : network namespace
* @ user_ptr : user pointers
2005-11-10 04:25:56 +03:00
*/
2009-11-03 06:26:03 +03:00
struct genl_info {
2005-11-10 04:25:56 +03:00
u32 snd_seq ;
u32 snd_pid ;
struct nlmsghdr * nlhdr ;
struct genlmsghdr * genlhdr ;
void * userhdr ;
struct nlattr * * attrs ;
2009-07-10 13:51:34 +04:00
# ifdef CONFIG_NET_NS
struct net * _net ;
# endif
2010-10-04 23:14:03 +04:00
void * user_ptr [ 2 ] ;
2005-11-10 04:25:56 +03:00
} ;
2009-07-10 13:51:34 +04:00
static inline struct net * genl_info_net ( struct genl_info * info )
{
2010-06-01 10:51:19 +04:00
return read_pnet ( & info - > _net ) ;
2009-07-10 13:51:34 +04:00
}
static inline void genl_info_net_set ( struct genl_info * info , struct net * net )
{
2010-06-01 10:51:19 +04:00
write_pnet ( & info - > _net , net ) ;
2009-07-10 13:51:34 +04:00
}
2005-11-10 04:25:56 +03:00
/**
* struct genl_ops - generic netlink operations
* @ cmd : command identifier
2010-10-04 23:14:03 +04:00
* @ internal_flags : flags used by the family
2005-11-10 04:25:56 +03:00
* @ flags : flags
* @ policy : attribute validation policy
* @ doit : standard command callback
* @ dumpit : callback for dumpers
2006-12-02 07:07:42 +03:00
* @ done : completion callback for dumps
2005-11-10 04:25:56 +03:00
* @ ops_list : operations list
*/
2009-11-03 06:26:03 +03:00
struct genl_ops {
2006-01-04 01:13:29 +03:00
u8 cmd ;
2010-10-04 23:14:03 +04:00
u8 internal_flags ;
2005-11-10 04:25:56 +03:00
unsigned int flags ;
2007-06-05 23:38:30 +04:00
const struct nla_policy * policy ;
2005-11-10 04:25:56 +03:00
int ( * doit ) ( struct sk_buff * skb ,
struct genl_info * info ) ;
int ( * dumpit ) ( struct sk_buff * skb ,
struct netlink_callback * cb ) ;
2006-12-02 07:07:42 +03:00
int ( * done ) ( struct netlink_callback * cb ) ;
2005-11-10 04:25:56 +03:00
struct list_head ops_list ;
} ;
extern int genl_register_family ( struct genl_family * family ) ;
2009-05-21 14:34:04 +04:00
extern int genl_register_family_with_ops ( struct genl_family * family ,
struct genl_ops * ops , size_t n_ops ) ;
2005-11-10 04:25:56 +03:00
extern int genl_unregister_family ( struct genl_family * family ) ;
extern int genl_register_ops ( struct genl_family * , struct genl_ops * ops ) ;
extern int genl_unregister_ops ( struct genl_family * , struct genl_ops * ops ) ;
2007-07-19 02:47:52 +04:00
extern int genl_register_mc_group ( struct genl_family * family ,
struct genl_multicast_group * grp ) ;
extern void genl_unregister_mc_group ( struct genl_family * family ,
struct genl_multicast_group * grp ) ;
2011-11-11 07:14:37 +04:00
extern void genl_notify ( struct sk_buff * skb , struct net * net , u32 pid ,
u32 group , struct nlmsghdr * nlh , gfp_t flags ) ;
2005-11-10 04:25:56 +03:00
2012-01-31 00:22:06 +04:00
void * genlmsg_put ( struct sk_buff * skb , u32 pid , u32 seq ,
struct genl_family * family , int flags , u8 cmd ) ;
2005-11-10 04:25:56 +03:00
netlink: advertise incomplete dumps
Consider the following situation:
* a dump that would show 8 entries, four in the first
round, and four in the second
* between the first and second rounds, 6 entries are
removed
* now the second round will not show any entry, and
even if there is a sequence/generation counter the
application will not know
To solve this problem, add a new flag NLM_F_DUMP_INTR
to the netlink header that indicates the dump wasn't
consistent, this flag can also be set on the MSG_DONE
message that terminates the dump, and as such above
situation can be detected.
To achieve this, add a sequence counter to the netlink
callback struct. Of course, netlink code still needs
to use this new functionality. The correct way to do
that is to always set cb->seq when a dumpit callback
is invoked and call nl_dump_check_consistent() for
each new message. The core code will also call this
function for the final MSG_DONE message.
To make it usable with generic netlink, a new function
genlmsg_nlhdr() is needed to obtain the netlink header
from the genetlink user header.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2011-06-20 15:40:46 +04:00
/**
* genlmsg_nlhdr - Obtain netlink header from user specified header
* @ user_hdr : user header as returned from genlmsg_put ( )
* @ family : generic netlink family
*
* Returns pointer to netlink header .
*/
static inline struct nlmsghdr * genlmsg_nlhdr ( void * user_hdr ,
struct genl_family * family )
{
return ( struct nlmsghdr * ) ( ( char * ) user_hdr -
family - > hdrsize -
GENL_HDRLEN -
NLMSG_HDRLEN ) ;
}
/**
* genl_dump_check_consistent - check if sequence is consistent and advertise if not
* @ cb : netlink callback structure that stores the sequence number
* @ user_hdr : user header as returned from genlmsg_put ( )
* @ family : generic netlink family
*
* Cf . nl_dump_check_consistent ( ) , this just provides a wrapper to make it
* simpler to use with generic netlink .
*/
static inline void genl_dump_check_consistent ( struct netlink_callback * cb ,
void * user_hdr ,
struct genl_family * family )
{
nl_dump_check_consistent ( cb , genlmsg_nlhdr ( user_hdr , family ) ) ;
}
2006-11-15 06:46:02 +03:00
/**
* genlmsg_put_reply - Add generic netlink header to a reply message
* @ skb : socket buffer holding the message
* @ info : receiver info
* @ family : generic netlink family
* @ flags : netlink message flags
* @ cmd : generic netlink command
*
* Returns pointer to user specific header
*/
static inline void * genlmsg_put_reply ( struct sk_buff * skb ,
struct genl_info * info ,
struct genl_family * family ,
int flags , u8 cmd )
{
return genlmsg_put ( skb , info - > snd_pid , info - > snd_seq , family ,
flags , cmd ) ;
}
2005-11-10 04:25:56 +03:00
/**
* genlmsg_end - Finalize a generic netlink message
* @ skb : socket buffer the message is stored in
* @ hdr : user specific header
*/
static inline int genlmsg_end ( struct sk_buff * skb , void * hdr )
{
return nlmsg_end ( skb , hdr - GENL_HDRLEN - NLMSG_HDRLEN ) ;
}
/**
* genlmsg_cancel - Cancel construction of a generic netlink message
* @ skb : socket buffer the message is stored in
* @ hdr : generic netlink message header
*/
2008-06-04 03:36:54 +04:00
static inline void genlmsg_cancel ( struct sk_buff * skb , void * hdr )
2005-11-10 04:25:56 +03:00
{
2011-01-28 08:43:40 +03:00
if ( hdr )
nlmsg_cancel ( skb , hdr - GENL_HDRLEN - NLMSG_HDRLEN ) ;
2005-11-10 04:25:56 +03:00
}
/**
2009-07-10 13:51:34 +04:00
* genlmsg_multicast_netns - multicast a netlink message to a specific netns
* @ net : the net namespace
* @ skb : netlink message as socket buffer
* @ pid : own netlink pid to avoid sending to yourself
* @ group : multicast group id
* @ flags : allocation flags
*/
static inline int genlmsg_multicast_netns ( struct net * net , struct sk_buff * skb ,
u32 pid , unsigned int group , gfp_t flags )
{
return nlmsg_multicast ( net - > genl_sock , skb , pid , group , flags ) ;
}
/**
* genlmsg_multicast - multicast a netlink message to the default netns
2005-11-10 04:25:56 +03:00
* @ 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:56 +03:00
*/
static inline int genlmsg_multicast ( struct sk_buff * skb , u32 pid ,
2006-08-15 11:31:06 +04:00
unsigned int group , gfp_t flags )
2005-11-10 04:25:56 +03:00
{
2009-07-10 13:51:34 +04:00
return genlmsg_multicast_netns ( & init_net , skb , pid , group , flags ) ;
2005-11-10 04:25:56 +03:00
}
2009-07-10 13:51:34 +04:00
/**
* genlmsg_multicast_allns - multicast a netlink message to all net namespaces
* @ skb : netlink message as socket buffer
* @ pid : own netlink pid to avoid sending to yourself
* @ group : multicast group id
* @ flags : allocation flags
*
* This function must hold the RTNL or rcu_read_lock ( ) .
*/
int genlmsg_multicast_allns ( struct sk_buff * skb , u32 pid ,
unsigned int group , gfp_t flags ) ;
2005-11-10 04:25:56 +03:00
/**
* genlmsg_unicast - unicast a netlink message
* @ skb : netlink message as socket buffer
* @ pid : netlink pid of the destination socket
*/
2009-07-10 13:51:34 +04:00
static inline int genlmsg_unicast ( struct net * net , struct sk_buff * skb , u32 pid )
2005-11-10 04:25:56 +03:00
{
2009-07-10 13:51:34 +04:00
return nlmsg_unicast ( net - > genl_sock , skb , pid ) ;
2005-11-10 04:25:56 +03:00
}
2006-11-15 06:45:27 +03:00
/**
* genlmsg_reply - reply to a request
* @ skb : netlink message to be sent back
* @ info : receiver information
*/
static inline int genlmsg_reply ( struct sk_buff * skb , struct genl_info * info )
{
2009-07-10 13:51:34 +04:00
return genlmsg_unicast ( genl_info_net ( info ) , skb , info - > snd_pid ) ;
2006-11-15 06:45:27 +03:00
}
2006-07-14 11:24:39 +04:00
/**
* gennlmsg_data - head of message payload
2011-05-10 12:16:21 +04:00
* @ gnlh : genetlink message header
2006-07-14 11:24:39 +04:00
*/
static inline void * genlmsg_data ( const struct genlmsghdr * gnlh )
{
return ( ( unsigned char * ) gnlh + GENL_HDRLEN ) ;
}
/**
* genlmsg_len - length of message payload
* @ gnlh : genetlink message header
*/
static inline int genlmsg_len ( const struct genlmsghdr * gnlh )
{
struct nlmsghdr * nlh = ( struct nlmsghdr * ) ( ( unsigned char * ) gnlh -
NLMSG_HDRLEN ) ;
return ( nlh - > nlmsg_len - GENL_HDRLEN - NLMSG_HDRLEN ) ;
}
2006-10-01 10:28:51 +04:00
/**
* genlmsg_msg_size - length of genetlink message not including padding
* @ payload : length of message payload
*/
static inline int genlmsg_msg_size ( int payload )
{
return GENL_HDRLEN + payload ;
}
/**
* genlmsg_total_size - length of genetlink message including padding
* @ payload : length of message payload
*/
static inline int genlmsg_total_size ( int payload )
{
return NLMSG_ALIGN ( genlmsg_msg_size ( payload ) ) ;
}
2006-11-15 06:44:52 +03:00
/**
* genlmsg_new - Allocate a new generic netlink message
* @ payload : size of the message payload
* @ flags : the type of memory to allocate .
*/
static inline struct sk_buff * genlmsg_new ( size_t payload , gfp_t flags )
{
return nlmsg_new ( genlmsg_total_size ( payload ) , flags ) ;
}
2005-11-10 04:25:56 +03:00
# endif /* __NET_GENERIC_NETLINK_H */