cfg80211: allow sending vendor events unicast
Sometimes, we may want to transport higher bandwidth data through vendor events, and in that case sending it multicast is a bad idea. Allow vendor events to be unicast. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Родитель
7976b1e9e3
Коммит
55c1fdf0d6
|
@ -5854,6 +5854,7 @@ struct sk_buff *__cfg80211_alloc_event_skb(struct wiphy *wiphy,
|
||||||
struct wireless_dev *wdev,
|
struct wireless_dev *wdev,
|
||||||
enum nl80211_commands cmd,
|
enum nl80211_commands cmd,
|
||||||
enum nl80211_attrs attr,
|
enum nl80211_attrs attr,
|
||||||
|
unsigned int portid,
|
||||||
int vendor_event_idx,
|
int vendor_event_idx,
|
||||||
int approxlen, gfp_t gfp);
|
int approxlen, gfp_t gfp);
|
||||||
|
|
||||||
|
@ -5903,6 +5904,15 @@ cfg80211_vendor_cmd_alloc_reply_skb(struct wiphy *wiphy, int approxlen)
|
||||||
*/
|
*/
|
||||||
int cfg80211_vendor_cmd_reply(struct sk_buff *skb);
|
int cfg80211_vendor_cmd_reply(struct sk_buff *skb);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cfg80211_vendor_cmd_get_sender
|
||||||
|
* @wiphy: the wiphy
|
||||||
|
*
|
||||||
|
* Return the current netlink port ID in a vendor command handler.
|
||||||
|
* Valid to call only there.
|
||||||
|
*/
|
||||||
|
unsigned int cfg80211_vendor_cmd_get_sender(struct wiphy *wiphy);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cfg80211_vendor_event_alloc - allocate vendor-specific event skb
|
* cfg80211_vendor_event_alloc - allocate vendor-specific event skb
|
||||||
* @wiphy: the wiphy
|
* @wiphy: the wiphy
|
||||||
|
@ -5930,7 +5940,42 @@ cfg80211_vendor_event_alloc(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||||
{
|
{
|
||||||
return __cfg80211_alloc_event_skb(wiphy, wdev, NL80211_CMD_VENDOR,
|
return __cfg80211_alloc_event_skb(wiphy, wdev, NL80211_CMD_VENDOR,
|
||||||
NL80211_ATTR_VENDOR_DATA,
|
NL80211_ATTR_VENDOR_DATA,
|
||||||
event_idx, approxlen, gfp);
|
0, event_idx, approxlen, gfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cfg80211_vendor_event_alloc_ucast - alloc unicast vendor-specific event skb
|
||||||
|
* @wiphy: the wiphy
|
||||||
|
* @wdev: the wireless device
|
||||||
|
* @event_idx: index of the vendor event in the wiphy's vendor_events
|
||||||
|
* @portid: port ID of the receiver
|
||||||
|
* @approxlen: an upper bound of the length of the data that will
|
||||||
|
* be put into the skb
|
||||||
|
* @gfp: allocation flags
|
||||||
|
*
|
||||||
|
* This function allocates and pre-fills an skb for an event to send to
|
||||||
|
* a specific (userland) socket. This socket would previously have been
|
||||||
|
* obtained by cfg80211_vendor_cmd_get_sender(), and the caller MUST take
|
||||||
|
* care to register a netlink notifier to see when the socket closes.
|
||||||
|
*
|
||||||
|
* If wdev != NULL, both the ifindex and identifier of the specified
|
||||||
|
* wireless device are added to the event message before the vendor data
|
||||||
|
* attribute.
|
||||||
|
*
|
||||||
|
* When done filling the skb, call cfg80211_vendor_event() with the
|
||||||
|
* skb to send the event.
|
||||||
|
*
|
||||||
|
* Return: An allocated and pre-filled skb. %NULL if any errors happen.
|
||||||
|
*/
|
||||||
|
static inline struct sk_buff *
|
||||||
|
cfg80211_vendor_event_alloc_ucast(struct wiphy *wiphy,
|
||||||
|
struct wireless_dev *wdev,
|
||||||
|
unsigned int portid, int approxlen,
|
||||||
|
int event_idx, gfp_t gfp)
|
||||||
|
{
|
||||||
|
return __cfg80211_alloc_event_skb(wiphy, wdev, NL80211_CMD_VENDOR,
|
||||||
|
NL80211_ATTR_VENDOR_DATA,
|
||||||
|
portid, event_idx, approxlen, gfp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -6030,7 +6075,7 @@ static inline struct sk_buff *
|
||||||
cfg80211_testmode_alloc_event_skb(struct wiphy *wiphy, int approxlen, gfp_t gfp)
|
cfg80211_testmode_alloc_event_skb(struct wiphy *wiphy, int approxlen, gfp_t gfp)
|
||||||
{
|
{
|
||||||
return __cfg80211_alloc_event_skb(wiphy, NULL, NL80211_CMD_TESTMODE,
|
return __cfg80211_alloc_event_skb(wiphy, NULL, NL80211_CMD_TESTMODE,
|
||||||
NL80211_ATTR_TESTDATA, -1,
|
NL80211_ATTR_TESTDATA, 0, -1,
|
||||||
approxlen, gfp);
|
approxlen, gfp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
|
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
|
||||||
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
* Copyright 2013-2014 Intel Mobile Communications GmbH
|
||||||
* Copyright 2015-2017 Intel Deutschland GmbH
|
* Copyright 2015-2017 Intel Deutschland GmbH
|
||||||
* Copyright (C) 2018 Intel Corporation
|
* Copyright (C) 2018-2019 Intel Corporation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/if.h>
|
#include <linux/if.h>
|
||||||
|
@ -9306,6 +9306,7 @@ struct sk_buff *__cfg80211_alloc_event_skb(struct wiphy *wiphy,
|
||||||
struct wireless_dev *wdev,
|
struct wireless_dev *wdev,
|
||||||
enum nl80211_commands cmd,
|
enum nl80211_commands cmd,
|
||||||
enum nl80211_attrs attr,
|
enum nl80211_attrs attr,
|
||||||
|
unsigned int portid,
|
||||||
int vendor_event_idx,
|
int vendor_event_idx,
|
||||||
int approxlen, gfp_t gfp)
|
int approxlen, gfp_t gfp)
|
||||||
{
|
{
|
||||||
|
@ -9329,7 +9330,7 @@ struct sk_buff *__cfg80211_alloc_event_skb(struct wiphy *wiphy,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return __cfg80211_alloc_vendor_skb(rdev, wdev, approxlen, 0, 0,
|
return __cfg80211_alloc_vendor_skb(rdev, wdev, approxlen, portid, 0,
|
||||||
cmd, attr, info, gfp);
|
cmd, attr, info, gfp);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(__cfg80211_alloc_event_skb);
|
EXPORT_SYMBOL(__cfg80211_alloc_event_skb);
|
||||||
|
@ -9338,6 +9339,7 @@ void __cfg80211_send_event_skb(struct sk_buff *skb, gfp_t gfp)
|
||||||
{
|
{
|
||||||
struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
|
struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
|
||||||
void *hdr = ((void **)skb->cb)[1];
|
void *hdr = ((void **)skb->cb)[1];
|
||||||
|
struct nlmsghdr *nlhdr = nlmsg_hdr(skb);
|
||||||
struct nlattr *data = ((void **)skb->cb)[2];
|
struct nlattr *data = ((void **)skb->cb)[2];
|
||||||
enum nl80211_multicast_groups mcgrp = NL80211_MCGRP_TESTMODE;
|
enum nl80211_multicast_groups mcgrp = NL80211_MCGRP_TESTMODE;
|
||||||
|
|
||||||
|
@ -9347,11 +9349,16 @@ void __cfg80211_send_event_skb(struct sk_buff *skb, gfp_t gfp)
|
||||||
nla_nest_end(skb, data);
|
nla_nest_end(skb, data);
|
||||||
genlmsg_end(skb, hdr);
|
genlmsg_end(skb, hdr);
|
||||||
|
|
||||||
|
if (nlhdr->nlmsg_pid) {
|
||||||
|
genlmsg_unicast(wiphy_net(&rdev->wiphy), skb,
|
||||||
|
nlhdr->nlmsg_pid);
|
||||||
|
} else {
|
||||||
if (data->nla_type == NL80211_ATTR_VENDOR_DATA)
|
if (data->nla_type == NL80211_ATTR_VENDOR_DATA)
|
||||||
mcgrp = NL80211_MCGRP_VENDOR;
|
mcgrp = NL80211_MCGRP_VENDOR;
|
||||||
|
|
||||||
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), skb, 0,
|
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
|
||||||
mcgrp, gfp);
|
skb, 0, mcgrp, gfp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(__cfg80211_send_event_skb);
|
EXPORT_SYMBOL(__cfg80211_send_event_skb);
|
||||||
|
|
||||||
|
@ -12736,6 +12743,17 @@ int cfg80211_vendor_cmd_reply(struct sk_buff *skb)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(cfg80211_vendor_cmd_reply);
|
EXPORT_SYMBOL_GPL(cfg80211_vendor_cmd_reply);
|
||||||
|
|
||||||
|
unsigned int cfg80211_vendor_cmd_get_sender(struct wiphy *wiphy)
|
||||||
|
{
|
||||||
|
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
||||||
|
|
||||||
|
if (WARN_ON(!rdev->cur_cmd_info))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return rdev->cur_cmd_info->snd_portid;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(cfg80211_vendor_cmd_get_sender);
|
||||||
|
|
||||||
static int nl80211_set_qos_map(struct sk_buff *skb,
|
static int nl80211_set_qos_map(struct sk_buff *skb,
|
||||||
struct genl_info *info)
|
struct genl_info *info)
|
||||||
{
|
{
|
||||||
|
|
Загрузка…
Ссылка в новой задаче