genl: Add genlmsg_new_unicast() for unicast message allocation
authorThomas Graf <tgraf@suug.ch>
Sat, 30 Nov 2013 12:21:30 +0000 (13:21 +0100)
committerJesse Gross <jesse@nicira.com>
Mon, 6 Jan 2014 23:51:53 +0000 (15:51 -0800)
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: Thomas Graf <tgraf@suug.ch>
Reviewed-by: Daniel Borkmann <dborkman@redhat.com>
Signed-off-by: Jesse Gross <jesse@nicira.com>
include/net/genetlink.h
net/netlink/genetlink.c

index 1b177ed803b7aa99045fec46e6449b29b76ac323..93695f0e22a54a7e4fa16f6934b1e085e75e1a7b 100644 (file)
@@ -73,6 +73,7 @@ struct genl_family {
  * @attrs: netlink attributes
  * @_net: network namespace
  * @user_ptr: user pointers
+ * @dst_sk: destination socket
  */
 struct genl_info {
        u32                     snd_seq;
@@ -85,6 +86,7 @@ struct genl_info {
        struct net *            _net;
 #endif
        void *                  user_ptr[2];
+       struct sock *           dst_sk;
 };
 
 static inline struct net *genl_info_net(struct genl_info *info)
@@ -177,6 +179,8 @@ void genl_notify(struct genl_family *family,
                 struct sk_buff *skb, struct net *net, u32 portid,
                 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,
                  struct genl_family *family, int flags, u8 cmd);
 
index 4518a57aa5febb14db1c1d750f217102dd8fd2a9..85bf42e2a9438318a476d429d02d6e4b6c402692 100644 (file)
@@ -453,6 +453,26 @@ int genl_unregister_family(struct genl_family *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
  * @skb: socket buffer holding the message
@@ -593,6 +613,7 @@ static int genl_family_rcv_msg(struct genl_family *family,
        info.genlhdr = nlmsg_data(nlh);
        info.userhdr = nlmsg_data(nlh) + GENL_HDRLEN;
        info.attrs = attrbuf;
+       info.dst_sk = skb->sk;
        genl_info_net_set(&info, net);
        memset(&info.user_ptr, 0, sizeof(info.user_ptr));