cfg80211: provide a function to report a match for NAN

Provide a function the driver can call to report a match.
This will send the event to the user space.
If the NAN instance is tied to the owner, the notifications will be
sent to the socket that started the NAN interface only.

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Ayala Beker
2016-09-20 17:31:17 +03:00
committed by Johannes Berg
parent a5a9dcf291
commit 50bcd31d99
3 changed files with 148 additions and 0 deletions

View File

@@ -56,6 +56,7 @@ enum nl80211_multicast_groups {
NL80211_MCGRP_REGULATORY,
NL80211_MCGRP_MLME,
NL80211_MCGRP_VENDOR,
NL80211_MCGRP_NAN,
NL80211_MCGRP_TESTMODE /* keep last - ifdef! */
};
@@ -65,6 +66,7 @@ static const struct genl_multicast_group nl80211_mcgrps[] = {
[NL80211_MCGRP_REGULATORY] = { .name = NL80211_MULTICAST_GROUP_REG },
[NL80211_MCGRP_MLME] = { .name = NL80211_MULTICAST_GROUP_MLME },
[NL80211_MCGRP_VENDOR] = { .name = NL80211_MULTICAST_GROUP_VENDOR },
[NL80211_MCGRP_NAN] = { .name = NL80211_MULTICAST_GROUP_NAN },
#ifdef CONFIG_NL80211_TESTMODE
[NL80211_MCGRP_TESTMODE] = { .name = NL80211_MULTICAST_GROUP_TESTMODE }
#endif
@@ -10953,6 +10955,84 @@ static int nl80211_nan_change_config(struct sk_buff *skb,
return rdev_nan_change_conf(rdev, wdev, &conf, changed);
}
void cfg80211_nan_match(struct wireless_dev *wdev,
struct cfg80211_nan_match_params *match, gfp_t gfp)
{
struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
struct nlattr *match_attr, *local_func_attr, *peer_func_attr;
struct sk_buff *msg;
void *hdr;
if (WARN_ON(!match->inst_id || !match->peer_inst_id || !match->addr))
return;
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
if (!msg)
return;
hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NAN_MATCH);
if (!hdr) {
nlmsg_free(msg);
return;
}
if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
(wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
wdev->netdev->ifindex)) ||
nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
NL80211_ATTR_PAD))
goto nla_put_failure;
if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, match->cookie,
NL80211_ATTR_PAD) ||
nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, match->addr))
goto nla_put_failure;
match_attr = nla_nest_start(msg, NL80211_ATTR_NAN_MATCH);
if (!match_attr)
goto nla_put_failure;
local_func_attr = nla_nest_start(msg, NL80211_NAN_MATCH_FUNC_LOCAL);
if (!local_func_attr)
goto nla_put_failure;
if (nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID, match->inst_id))
goto nla_put_failure;
nla_nest_end(msg, local_func_attr);
peer_func_attr = nla_nest_start(msg, NL80211_NAN_MATCH_FUNC_PEER);
if (!peer_func_attr)
goto nla_put_failure;
if (nla_put_u8(msg, NL80211_NAN_FUNC_TYPE, match->type) ||
nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID, match->peer_inst_id))
goto nla_put_failure;
if (match->info && match->info_len &&
nla_put(msg, NL80211_NAN_FUNC_SERVICE_INFO, match->info_len,
match->info))
goto nla_put_failure;
nla_nest_end(msg, peer_func_attr);
nla_nest_end(msg, match_attr);
genlmsg_end(msg, hdr);
if (!wdev->owner_nlportid)
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
msg, 0, NL80211_MCGRP_NAN, gfp);
else
genlmsg_unicast(wiphy_net(&rdev->wiphy), msg,
wdev->owner_nlportid);
return;
nla_put_failure:
nlmsg_free(msg);
}
EXPORT_SYMBOL(cfg80211_nan_match);
static int nl80211_get_protocol_features(struct sk_buff *skb,
struct genl_info *info)
{