Commit bb9b18fb authored by Thomas Graf's avatar Thomas Graf Committed by Jesse Gross

genl: Add genlmsg_new_unicast() for unicast message allocation

Allocates a new sk_buff large enough to cover the specified payload
plus required Netlink headers. Will check receiving socket for
memory mapped i/o capability and use it if enabled. Will fall back
to non-mapped skb if message size exceeds the frame size of the ring.
Signed-of-by: default avatarThomas Graf <tgraf@suug.ch>
Reviewed-by: default avatarDaniel Borkmann <dborkman@redhat.com>
Signed-off-by: default avatarJesse Gross <jesse@nicira.com>
parent 663efa36
...@@ -73,6 +73,7 @@ struct genl_family { ...@@ -73,6 +73,7 @@ struct genl_family {
* @attrs: netlink attributes * @attrs: netlink attributes
* @_net: network namespace * @_net: network namespace
* @user_ptr: user pointers * @user_ptr: user pointers
* @dst_sk: destination socket
*/ */
struct genl_info { struct genl_info {
u32 snd_seq; u32 snd_seq;
...@@ -85,6 +86,7 @@ struct genl_info { ...@@ -85,6 +86,7 @@ struct genl_info {
struct net * _net; struct net * _net;
#endif #endif
void * user_ptr[2]; void * user_ptr[2];
struct sock * dst_sk;
}; };
static inline struct net *genl_info_net(struct genl_info *info) static inline struct net *genl_info_net(struct genl_info *info)
...@@ -177,6 +179,8 @@ void genl_notify(struct genl_family *family, ...@@ -177,6 +179,8 @@ void genl_notify(struct genl_family *family,
struct sk_buff *skb, struct net *net, u32 portid, struct sk_buff *skb, struct net *net, u32 portid,
u32 group, struct nlmsghdr *nlh, gfp_t flags); u32 group, struct nlmsghdr *nlh, gfp_t flags);
struct sk_buff *genlmsg_new_unicast(size_t payload, struct genl_info *info,
gfp_t flags);
void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq, void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
struct genl_family *family, int flags, u8 cmd); struct genl_family *family, int flags, u8 cmd);
......
...@@ -453,6 +453,26 @@ int genl_unregister_family(struct genl_family *family) ...@@ -453,6 +453,26 @@ int genl_unregister_family(struct genl_family *family)
} }
EXPORT_SYMBOL(genl_unregister_family); EXPORT_SYMBOL(genl_unregister_family);
/**
* genlmsg_new_unicast - Allocate generic netlink message for unicast
* @payload: size of the message payload
* @info: information on destination
* @flags: the type of memory to allocate
*
* Allocates a new sk_buff large enough to cover the specified payload
* plus required Netlink headers. Will check receiving socket for
* memory mapped i/o capability and use it if enabled. Will fall back
* to non-mapped skb if message size exceeds the frame size of the ring.
*/
struct sk_buff *genlmsg_new_unicast(size_t payload, struct genl_info *info,
gfp_t flags)
{
size_t len = nlmsg_total_size(genlmsg_total_size(payload));
return netlink_alloc_skb(info->dst_sk, len, info->snd_portid, flags);
}
EXPORT_SYMBOL_GPL(genlmsg_new_unicast);
/** /**
* genlmsg_put - Add generic netlink header to netlink message * genlmsg_put - Add generic netlink header to netlink message
* @skb: socket buffer holding the message * @skb: socket buffer holding the message
...@@ -593,6 +613,7 @@ static int genl_family_rcv_msg(struct genl_family *family, ...@@ -593,6 +613,7 @@ static int genl_family_rcv_msg(struct genl_family *family,
info.genlhdr = nlmsg_data(nlh); info.genlhdr = nlmsg_data(nlh);
info.userhdr = nlmsg_data(nlh) + GENL_HDRLEN; info.userhdr = nlmsg_data(nlh) + GENL_HDRLEN;
info.attrs = attrbuf; info.attrs = attrbuf;
info.dst_sk = skb->sk;
genl_info_net_set(&info, net); genl_info_net_set(&info, net);
memset(&info.user_ptr, 0, sizeof(info.user_ptr)); memset(&info.user_ptr, 0, sizeof(info.user_ptr));
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment