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

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
Loading
Loading
Loading
Loading
+31 −4
Original line number Diff line number Diff line
@@ -449,22 +449,49 @@ static inline void genlmsg_cancel(struct sk_buff *skb, void *hdr)
}

/**
 * genlmsg_multicast_netns - multicast a netlink message to a specific netns
 * 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(const struct genl_family *family,
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)
				 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(net->genl_sock, skb, portid, group, flags);
	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
 * @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
 */
static inline int genlmsg_multicast_netns(const struct genl_family *family,
					  struct net *net, struct sk_buff *skb,
					  u32 portid, unsigned int group, gfp_t flags)
{
	return genlmsg_multicast_netns_filtered(family, net, skb, portid,
						group, flags, NULL, NULL);
}

/**
+27 −4
Original line number Diff line number Diff line
@@ -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
 * @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(struct sock *sk, struct sk_buff *skb,
				  u32 portid, unsigned int group, gfp_t flags)
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(sk, skb, portid, group, flags);
	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
 * @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
 * @sk: netlink socket to spread message to