Commit 971b4ad8 authored by Jiri Pirko's avatar Jiri Pirko Committed by Paolo Abeni

genetlink: introduce helpers to do filtered multicast

Currently it is possible for netlink kernel user to pass custom
filter function to broadcast send function netlink_broadcast_filtered().
However, this is not exposed to multicast send and to generic
netlink users.

Extend the api and introduce a netlink helper nlmsg_multicast_filtered()
and a generic netlink helper genlmsg_multicast_netns_filtered()
to allow generic netlink families to specify filter function
while sending multicast messages.
Signed-off-by: default avatarJiri Pirko <jiri@nvidia.com>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 403863e9
...@@ -448,6 +448,35 @@ static inline void genlmsg_cancel(struct sk_buff *skb, void *hdr) ...@@ -448,6 +448,35 @@ static inline void genlmsg_cancel(struct sk_buff *skb, void *hdr)
nlmsg_cancel(skb, hdr - GENL_HDRLEN - NLMSG_HDRLEN); nlmsg_cancel(skb, hdr - GENL_HDRLEN - NLMSG_HDRLEN);
} }
/**
* genlmsg_multicast_netns_filtered - multicast a netlink message
* to a specific netns with filter
* function
* @family: the generic netlink family
* @net: the net namespace
* @skb: netlink message as socket buffer
* @portid: own netlink portid to avoid sending to yourself
* @group: offset of multicast group in groups array
* @flags: allocation flags
* @filter: filter function
* @filter_data: filter function private data
*
* Return: 0 on success, negative error code for failure.
*/
static inline int
genlmsg_multicast_netns_filtered(const struct genl_family *family,
struct net *net, struct sk_buff *skb,
u32 portid, unsigned int group, gfp_t flags,
netlink_filter_fn filter,
void *filter_data)
{
if (WARN_ON_ONCE(group >= family->n_mcgrps))
return -EINVAL;
group = family->mcgrp_offset + group;
return nlmsg_multicast_filtered(net->genl_sock, skb, portid, group,
flags, filter, filter_data);
}
/** /**
* genlmsg_multicast_netns - multicast a netlink message to a specific netns * genlmsg_multicast_netns - multicast a netlink message to a specific netns
* @family: the generic netlink family * @family: the generic netlink family
...@@ -461,10 +490,8 @@ static inline int genlmsg_multicast_netns(const struct genl_family *family, ...@@ -461,10 +490,8 @@ static inline int genlmsg_multicast_netns(const struct genl_family *family,
struct net *net, struct sk_buff *skb, struct net *net, struct sk_buff *skb,
u32 portid, unsigned int group, gfp_t flags) u32 portid, unsigned int group, gfp_t flags)
{ {
if (WARN_ON_ONCE(group >= family->n_mcgrps)) return genlmsg_multicast_netns_filtered(family, net, skb, portid,
return -EINVAL; group, flags, NULL, NULL);
group = family->mcgrp_offset + group;
return nlmsg_multicast(net->genl_sock, skb, portid, group, flags);
} }
/** /**
......
...@@ -1087,27 +1087,50 @@ static inline void nlmsg_free(struct sk_buff *skb) ...@@ -1087,27 +1087,50 @@ static inline void nlmsg_free(struct sk_buff *skb)
} }
/** /**
* nlmsg_multicast - multicast a netlink message * nlmsg_multicast_filtered - multicast a netlink message with filter function
* @sk: netlink socket to spread messages to * @sk: netlink socket to spread messages to
* @skb: netlink message as socket buffer * @skb: netlink message as socket buffer
* @portid: own netlink portid to avoid sending to yourself * @portid: own netlink portid to avoid sending to yourself
* @group: multicast group id * @group: multicast group id
* @flags: allocation flags * @flags: allocation flags
* @filter: filter function
* @filter_data: filter function private data
*
* Return: 0 on success, negative error code for failure.
*/ */
static inline int nlmsg_multicast(struct sock *sk, struct sk_buff *skb, static inline int nlmsg_multicast_filtered(struct sock *sk, struct sk_buff *skb,
u32 portid, unsigned int group, gfp_t flags) u32 portid, unsigned int group,
gfp_t flags,
netlink_filter_fn filter,
void *filter_data)
{ {
int err; int err;
NETLINK_CB(skb).dst_group = group; NETLINK_CB(skb).dst_group = group;
err = netlink_broadcast(sk, skb, portid, group, flags); err = netlink_broadcast_filtered(sk, skb, portid, group, flags,
filter, filter_data);
if (err > 0) if (err > 0)
err = 0; err = 0;
return err; return err;
} }
/**
* nlmsg_multicast - multicast a netlink message
* @sk: netlink socket to spread messages to
* @skb: netlink message as socket buffer
* @portid: own netlink portid to avoid sending to yourself
* @group: multicast group id
* @flags: allocation flags
*/
static inline int nlmsg_multicast(struct sock *sk, struct sk_buff *skb,
u32 portid, unsigned int group, gfp_t flags)
{
return nlmsg_multicast_filtered(sk, skb, portid, group, flags,
NULL, NULL);
}
/** /**
* nlmsg_unicast - unicast a netlink message * nlmsg_unicast - unicast a netlink message
* @sk: netlink socket to spread message to * @sk: netlink socket to spread message to
......
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