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: Jiri Pirko <jiri@nvidia.com> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
@@ -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,
|
|||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -1086,6 +1086,36 @@ static inline void nlmsg_free(struct sk_buff *skb)
|
|||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nlmsg_multicast_filtered - multicast a netlink message with filter function
|
||||||
|
* @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
|
||||||
|
* @filter: filter function
|
||||||
|
* @filter_data: filter function private data
|
||||||
|
*
|
||||||
|
* Return: 0 on success, negative error code for failure.
|
||||||
|
*/
|
||||||
|
static inline int nlmsg_multicast_filtered(struct sock *sk, struct sk_buff *skb,
|
||||||
|
u32 portid, unsigned int group,
|
||||||
|
gfp_t flags,
|
||||||
|
netlink_filter_fn filter,
|
||||||
|
void *filter_data)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
NETLINK_CB(skb).dst_group = group;
|
||||||
|
|
||||||
|
err = netlink_broadcast_filtered(sk, skb, portid, group, flags,
|
||||||
|
filter, filter_data);
|
||||||
|
if (err > 0)
|
||||||
|
err = 0;
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* nlmsg_multicast - multicast a netlink message
|
* nlmsg_multicast - multicast a netlink message
|
||||||
* @sk: netlink socket to spread messages to
|
* @sk: netlink socket to spread messages to
|
||||||
@@ -1097,15 +1127,8 @@ static inline void nlmsg_free(struct sk_buff *skb)
|
|||||||
static inline int nlmsg_multicast(struct sock *sk, struct sk_buff *skb,
|
static inline int nlmsg_multicast(struct sock *sk, struct sk_buff *skb,
|
||||||
u32 portid, unsigned int group, gfp_t flags)
|
u32 portid, unsigned int group, gfp_t flags)
|
||||||
{
|
{
|
||||||
int err;
|
return nlmsg_multicast_filtered(sk, skb, portid, group, flags,
|
||||||
|
NULL, NULL);
|
||||||
NETLINK_CB(skb).dst_group = group;
|
|
||||||
|
|
||||||
err = netlink_broadcast(sk, skb, portid, group, flags);
|
|
||||||
if (err > 0)
|
|
||||||
err = 0;
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user