aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2013-11-30 07:21:30 -0500
committerJesse Gross <jesse@nicira.com>2014-01-06 18:51:53 -0500
commitbb9b18fb55b03477fe5bdd3e97245d6d4d3dee4f (patch)
tree02d730abd6f31752a842f8c1d9f30d62d185e0b2
parent663efa3696232300a8ad3a46bb10482fc0b861cf (diff)
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: Thomas Graf <tgraf@suug.ch> Reviewed-by: Daniel Borkmann <dborkman@redhat.com> Signed-off-by: Jesse Gross <jesse@nicira.com>
-rw-r--r--include/net/genetlink.h4
-rw-r--r--net/netlink/genetlink.c21
2 files changed, 25 insertions, 0 deletions
diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index 1b177ed803b7..93695f0e22a5 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -73,6 +73,7 @@ struct genl_family {
73 * @attrs: netlink attributes 73 * @attrs: netlink attributes
74 * @_net: network namespace 74 * @_net: network namespace
75 * @user_ptr: user pointers 75 * @user_ptr: user pointers
76 * @dst_sk: destination socket
76 */ 77 */
77struct genl_info { 78struct genl_info {
78 u32 snd_seq; 79 u32 snd_seq;
@@ -85,6 +86,7 @@ struct genl_info {
85 struct net * _net; 86 struct net * _net;
86#endif 87#endif
87 void * user_ptr[2]; 88 void * user_ptr[2];
89 struct sock * dst_sk;
88}; 90};
89 91
90static inline struct net *genl_info_net(struct genl_info *info) 92static inline struct net *genl_info_net(struct genl_info *info)
@@ -177,6 +179,8 @@ void genl_notify(struct genl_family *family,
177 struct sk_buff *skb, struct net *net, u32 portid, 179 struct sk_buff *skb, struct net *net, u32 portid,
178 u32 group, struct nlmsghdr *nlh, gfp_t flags); 180 u32 group, struct nlmsghdr *nlh, gfp_t flags);
179 181
182struct sk_buff *genlmsg_new_unicast(size_t payload, struct genl_info *info,
183 gfp_t flags);
180void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq, 184void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
181 struct genl_family *family, int flags, u8 cmd); 185 struct genl_family *family, int flags, u8 cmd);
182 186
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 4518a57aa5fe..85bf42e2a943 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -454,6 +454,26 @@ int genl_unregister_family(struct genl_family *family)
454EXPORT_SYMBOL(genl_unregister_family); 454EXPORT_SYMBOL(genl_unregister_family);
455 455
456/** 456/**
457 * genlmsg_new_unicast - Allocate generic netlink message for unicast
458 * @payload: size of the message payload
459 * @info: information on destination
460 * @flags: the type of memory to allocate
461 *
462 * Allocates a new sk_buff large enough to cover the specified payload
463 * plus required Netlink headers. Will check receiving socket for
464 * memory mapped i/o capability and use it if enabled. Will fall back
465 * to non-mapped skb if message size exceeds the frame size of the ring.
466 */
467struct sk_buff *genlmsg_new_unicast(size_t payload, struct genl_info *info,
468 gfp_t flags)
469{
470 size_t len = nlmsg_total_size(genlmsg_total_size(payload));
471
472 return netlink_alloc_skb(info->dst_sk, len, info->snd_portid, flags);
473}
474EXPORT_SYMBOL_GPL(genlmsg_new_unicast);
475
476/**
457 * genlmsg_put - Add generic netlink header to netlink message 477 * genlmsg_put - Add generic netlink header to netlink message
458 * @skb: socket buffer holding the message 478 * @skb: socket buffer holding the message
459 * @portid: netlink portid the message is addressed to 479 * @portid: netlink portid the message is addressed to
@@ -593,6 +613,7 @@ static int genl_family_rcv_msg(struct genl_family *family,
593 info.genlhdr = nlmsg_data(nlh); 613 info.genlhdr = nlmsg_data(nlh);
594 info.userhdr = nlmsg_data(nlh) + GENL_HDRLEN; 614 info.userhdr = nlmsg_data(nlh) + GENL_HDRLEN;
595 info.attrs = attrbuf; 615 info.attrs = attrbuf;
616 info.dst_sk = skb->sk;
596 genl_info_net_set(&info, net); 617 genl_info_net_set(&info, net);
597 memset(&info.user_ptr, 0, sizeof(info.user_ptr)); 618 memset(&info.user_ptr, 0, sizeof(info.user_ptr));
598 619