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
2012-06-28 07:57:45 +04:00
# define GENLMSG_DEFAULT_SIZE (NLMSG_DEFAULT_SIZE - GENL_HDRLEN)
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
*/
2009-11-03 06:26:03 +03:00
struct genl_multicast_group {
2007-07-19 02:47:52 +04:00
char name [ GENL_NAMSIZ ] ;
} ;
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
2015-01-16 13:37:12 +03:00
* @ parallel_ops : operations can be called in parallel and aren ' t
* synchronized by the core genetlink code
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
2014-12-23 22:54:40 +03:00
* @ mcast_bind : a socket bound to the given multicast group ( which
* is given as the offset into the groups array )
2015-01-16 13:37:14 +03:00
* @ mcast_unbind : a socket was unbound from the given multicast group .
* Note that unbind ( ) will not be called symmetrically if the
* generic netlink family is removed while there are still open
* sockets .
2005-11-10 04:25:56 +03:00
* @ attrbuf : buffer to store parsed attributes
* @ family_list : family list
2013-11-19 18:19:39 +04:00
* @ mcgrps : multicast groups used by this family ( private )
* @ n_mcgrps : number of multicast groups ( private )
* @ mcgrp_offset : starting number of multicast group IDs in this family
2013-11-14 20:14:44 +04:00
* @ ops : the operations supported by this family ( private )
* @ n_ops : number of operations supported by this family ( private )
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 ;
2013-04-23 11:48:30 +04:00
bool parallel_ops ;
2013-11-14 20:14:45 +04:00
int ( * pre_doit ) ( const struct genl_ops * ops ,
2010-10-04 23:14:03 +04:00
struct sk_buff * skb ,
struct genl_info * info ) ;
2013-11-14 20:14:45 +04:00
void ( * post_doit ) ( const struct genl_ops * ops ,
2010-10-04 23:14:03 +04:00
struct sk_buff * skb ,
struct genl_info * info ) ;
2014-12-23 23:00:06 +03:00
int ( * mcast_bind ) ( struct net * net , int group ) ;
void ( * mcast_unbind ) ( struct net * net , int group ) ;
2005-11-10 04:25:56 +03:00
struct nlattr * * attrbuf ; /* private */
2013-11-14 20:14:45 +04:00
const struct genl_ops * ops ; /* private */
2013-11-19 18:19:39 +04:00
const struct genl_multicast_group * mcgrps ; /* private */
2013-11-14 20:14:44 +04:00
unsigned int n_ops ; /* private */
2013-11-19 18:19:39 +04:00
unsigned int n_mcgrps ; /* private */
unsigned int mcgrp_offset ; /* private */
2005-11-10 04:25:56 +03:00
struct list_head family_list ; /* private */
2013-08-23 23:45:04 +04:00
struct module * module ;
2005-11-10 04:25:56 +03:00
} ;
/**
* struct genl_info - receiving information
* @ snd_seq : sending sequence number
2012-09-08 00:12:54 +04:00
* @ snd_portid : netlink portid of sender
2005-11-10 04:25:56 +03:00
* @ 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
2013-11-30 16:21:30 +04:00
* @ dst_sk : destination socket
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 ;
2012-09-08 00:12:54 +04:00
u32 snd_portid ;
2005-11-10 04:25:56 +03:00
struct nlmsghdr * nlhdr ;
struct genlmsghdr * genlhdr ;
void * userhdr ;
struct nlattr * * attrs ;
2015-03-12 07:06:44 +03:00
possible_net_t _net ;
2010-10-04 23:14:03 +04:00
void * user_ptr [ 2 ] ;
2013-11-30 16:21:30 +04:00
struct sock * dst_sk ;
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 {
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 ) ;
2013-11-14 20:14:47 +04:00
u8 cmd ;
u8 internal_flags ;
u8 flags ;
2005-11-10 04:25:56 +03:00
} ;
2013-09-20 22:23:27 +04:00
int __genl_register_family ( struct genl_family * family ) ;
2013-08-23 23:45:04 +04:00
static inline int genl_register_family ( struct genl_family * family )
{
family - > module = THIS_MODULE ;
return __genl_register_family ( family ) ;
}
2013-11-15 17:19:08 +04:00
/**
* genl_register_family_with_ops - register a generic netlink family with ops
* @ family : generic netlink family
* @ ops : operations to be registered
* @ n_ops : number of elements to register
*
* Registers the specified family and operations from the specified table .
* Only one family may be registered with the same family name or identifier .
*
* The family id may equal GENL_ID_GENERATE causing an unique id to
* be automatically generated and assigned .
*
* Either a doit or dumpit callback must be specified for every registered
* operation or the function will fail . Only one operation structure per
* command identifier may be registered .
*
* See include / net / genetlink . h for more documenation on the operations
* structure .
*
* Return 0 on success or a negative error code .
*/
2013-11-19 18:19:39 +04:00
static inline int
_genl_register_family_with_ops_grps ( struct genl_family * family ,
const struct genl_ops * ops , size_t n_ops ,
const struct genl_multicast_group * mcgrps ,
size_t n_mcgrps )
2013-08-23 23:45:04 +04:00
{
family - > module = THIS_MODULE ;
2013-11-15 17:19:08 +04:00
family - > ops = ops ;
family - > n_ops = n_ops ;
2013-11-19 18:19:39 +04:00
family - > mcgrps = mcgrps ;
family - > n_mcgrps = n_mcgrps ;
2013-11-15 17:19:08 +04:00
return __genl_register_family ( family ) ;
2013-08-23 23:45:04 +04:00
}
2013-11-19 18:19:39 +04:00
# define genl_register_family_with_ops(family, ops) \
_genl_register_family_with_ops_grps ( ( family ) , \
( ops ) , ARRAY_SIZE ( ops ) , \
NULL , 0 )
# define genl_register_family_with_ops_groups(family, ops, grps) \
_genl_register_family_with_ops_grps ( ( family ) , \
( ops ) , ARRAY_SIZE ( ops ) , \
( grps ) , ARRAY_SIZE ( grps ) )
2013-11-19 18:19:31 +04:00
2013-09-20 22:23:27 +04:00
int genl_unregister_family ( struct genl_family * family ) ;
2013-11-19 18:19:38 +04:00
void genl_notify ( struct genl_family * family ,
struct sk_buff * skb , struct net * net , u32 portid ,
2013-09-20 22:23:27 +04:00
u32 group , struct nlmsghdr * nlh , gfp_t flags ) ;
2005-11-10 04:25:56 +03:00
2013-11-30 16:21:30 +04:00
struct sk_buff * genlmsg_new_unicast ( size_t payload , struct genl_info * info ,
gfp_t flags ) ;
2012-09-08 00:12:54 +04:00
void * genlmsg_put ( struct sk_buff * skb , u32 portid , u32 seq ,
2013-09-20 22:23:27 +04:00
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 ) ;
}
2015-01-22 03:42:51 +03:00
/**
* genlmsg_parse - parse attributes of a genetlink message
* @ nlh : netlink message header
* @ family : genetlink message family
* @ tb : destination array with maxtype + 1 elements
* @ maxtype : maximum attribute type to be expected
* @ policy : validation policy
* */
static inline int genlmsg_parse ( const struct nlmsghdr * nlh ,
const struct genl_family * family ,
struct nlattr * tb [ ] , int maxtype ,
const struct nla_policy * policy )
{
return nlmsg_parse ( nlh , family - > hdrsize + GENL_HDRLEN , tb , maxtype ,
policy ) ;
}
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
/**
* 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 )
{
2012-09-08 00:12:54 +04:00
return genlmsg_put ( skb , info - > snd_portid , info - > snd_seq , family ,
2006-11-15 06:46:02 +03:00
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
*/
2015-01-17 00:09:00 +03:00
static inline void genlmsg_end ( struct sk_buff * skb , void * hdr )
2005-11-10 04:25:56 +03:00
{
2015-01-17 00:09:00 +03:00
nlmsg_end ( skb , hdr - GENL_HDRLEN - NLMSG_HDRLEN ) ;
2005-11-10 04:25:56 +03:00
}
/**
* 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
2013-11-19 18:19:38 +04:00
* @ family : the generic netlink family
2009-07-10 13:51:34 +04:00
* @ net : the net namespace
* @ skb : netlink message as socket buffer
2012-09-08 00:12:54 +04:00
* @ portid : own netlink portid to avoid sending to yourself
2013-11-19 18:19:39 +04:00
* @ group : offset of multicast group in groups array
2009-07-10 13:51:34 +04:00
* @ flags : allocation flags
*/
2013-11-19 18:19:38 +04:00
static inline int genlmsg_multicast_netns ( struct genl_family * family ,
struct net * net , struct sk_buff * skb ,
2012-09-08 00:12:54 +04:00
u32 portid , unsigned int group , gfp_t flags )
2009-07-10 13:51:34 +04:00
{
2013-11-21 21:17:04 +04:00
if ( WARN_ON_ONCE ( group > = family - > n_mcgrps ) )
2013-11-19 18:19:39 +04:00
return - EINVAL ;
group = family - > mcgrp_offset + group ;
2012-09-08 00:12:54 +04:00
return nlmsg_multicast ( net - > genl_sock , skb , portid , group , flags ) ;
2009-07-10 13:51:34 +04:00
}
/**
* genlmsg_multicast - multicast a netlink message to the default netns
2013-11-19 18:19:38 +04:00
* @ family : the generic netlink family
2005-11-10 04:25:56 +03:00
* @ skb : netlink message as socket buffer
2012-09-08 00:12:54 +04:00
* @ portid : own netlink portid to avoid sending to yourself
2013-11-19 18:19:39 +04:00
* @ group : offset of multicast group in groups array
2006-08-15 11:31:06 +04:00
* @ flags : allocation flags
2005-11-10 04:25:56 +03:00
*/
2013-11-19 18:19:38 +04:00
static inline int genlmsg_multicast ( struct genl_family * family ,
struct sk_buff * skb , u32 portid ,
2006-08-15 11:31:06 +04:00
unsigned int group , gfp_t flags )
2005-11-10 04:25:56 +03:00
{
2013-11-19 18:19:38 +04:00
return genlmsg_multicast_netns ( family , & init_net , skb ,
portid , 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
2013-11-19 18:19:38 +04:00
* @ family : the generic netlink family
2009-07-10 13:51:34 +04:00
* @ skb : netlink message as socket buffer
2012-09-08 00:12:54 +04:00
* @ portid : own netlink portid to avoid sending to yourself
2013-11-19 18:19:39 +04:00
* @ group : offset of multicast group in groups array
2009-07-10 13:51:34 +04:00
* @ flags : allocation flags
*
* This function must hold the RTNL or rcu_read_lock ( ) .
*/
2013-11-19 18:19:38 +04:00
int genlmsg_multicast_allns ( struct genl_family * family ,
struct sk_buff * skb , u32 portid ,
2009-07-10 13:51:34 +04:00
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
2012-09-08 00:12:54 +04:00
* @ portid : netlink portid of the destination socket
2005-11-10 04:25:56 +03:00
*/
2012-09-08 00:12:54 +04:00
static inline int genlmsg_unicast ( struct net * net , struct sk_buff * skb , u32 portid )
2005-11-10 04:25:56 +03:00
{
2012-09-08 00:12:54 +04:00
return nlmsg_unicast ( net - > genl_sock , skb , portid ) ;
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 )
{
2012-09-08 00:12:54 +04:00
return genlmsg_unicast ( genl_info_net ( info ) , skb , info - > snd_portid ) ;
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 ) ;
}
2013-11-19 18:19:37 +04:00
/**
* genl_set_err - report error to genetlink broadcast listeners
2013-11-19 18:19:38 +04:00
* @ family : the generic netlink family
2013-11-19 18:19:37 +04:00
* @ net : the network namespace to report the error to
* @ portid : the PORTID of a process that we want to skip ( if any )
* @ group : the broadcast group that will notice the error
2013-11-19 18:19:39 +04:00
* ( this is the offset of the multicast group in the groups array )
2013-11-19 18:19:37 +04:00
* @ code : error code , must be negative ( as usual in kernelspace )
*
* This function returns the number of broadcast listeners that have set the
* NETLINK_RECV_NO_ENOBUFS socket option .
*/
2013-11-19 18:19:38 +04:00
static inline int genl_set_err ( struct genl_family * family , struct net * net ,
u32 portid , u32 group , int code )
2013-11-19 18:19:37 +04:00
{
2013-11-21 21:20:28 +04:00
if ( WARN_ON_ONCE ( group > = family - > n_mcgrps ) )
return - EINVAL ;
group = family - > mcgrp_offset + group ;
2013-11-19 18:19:37 +04:00
return netlink_set_err ( net - > genl_sock , portid , group , code ) ;
}
2006-11-15 06:44:52 +03:00
2014-09-18 12:31:03 +04:00
static inline int genl_has_listeners ( struct genl_family * family ,
2014-12-22 20:56:36 +03:00
struct net * net , unsigned int group )
2014-09-18 12:31:03 +04:00
{
if ( WARN_ON_ONCE ( group > = family - > n_mcgrps ) )
return - EINVAL ;
group = family - > mcgrp_offset + group ;
2014-12-22 20:56:36 +03:00
return netlink_has_listeners ( net - > genl_sock , group ) ;
2014-09-18 12:31:03 +04:00
}
2005-11-10 04:25:56 +03:00
# endif /* __NET_GENERIC_NETLINK_H */