Add NL80211_CMD_NAN_NDP_CONFIRM event to notify userspace when NDP setup completes. Add the corresponding parameter structure and event function so the driver can report the accept/reject status and, if accepted, the responder NDI address. Signed-off-by: Shivani Baranwal --- include/net/cfg80211.h | 45 ++++++++++++++++++++++ include/uapi/linux/nl80211.h | 24 ++++++++++++ net/wireless/nl80211.c | 75 ++++++++++++++++++++++++++++++++++++ 3 files changed, 144 insertions(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index b356818e135e..e3d3dccfa06e 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -4474,6 +4474,37 @@ struct cfg80211_nan_ndp_request_params { bool ndpe; }; +/** + * struct cfg80211_nan_ndp_confirm_params - NAN NDP confirm event parameters + * + * Sent to userspace after the driver completes NDP setup. + * + * @peer_nmi: peer NMI address + * @ndp_id: NDP ID + * @init_ndi: initiator NDI MAC address + * @resp_ndi: responder NDI MAC address (valid when @accepted is true) + * @accepted: if true, NDP was accepted; if false, rejected + * @reason: rejection reason (valid when @accepted is false) + * @ssi: response service-specific info (may be NULL) + * @ssi_len: length of @ssi + * @ipv6_intf_id: peer's IPv6 link-local interface identifier + * (%NL80211_NAN_NDP_IPV6_INTF_ID_LEN bytes, + * valid when @ipv6_intf_id_set is true) + * @ipv6_intf_id_set: if true, @ipv6_intf_id is valid + */ +struct cfg80211_nan_ndp_confirm_params { + const u8 *peer_nmi; + u8 ndp_id; + const u8 *init_ndi; + const u8 *resp_ndi; + bool accepted; + u8 reason; + const u8 *ssi; + u8 ssi_len; + u8 ipv6_intf_id[NL80211_NAN_NDP_IPV6_INTF_ID_LEN]; + bool ipv6_intf_id_set; +}; + /** * enum cfg80211_nan_conf_changes - indicates changed fields in NAN * configuration @@ -11365,6 +11396,20 @@ void cfg80211_nan_ndp_request(struct wireless_dev *wdev, struct cfg80211_nan_ndp_request_params *params, gfp_t gfp); +/** + * cfg80211_nan_ndp_confirm - notify userspace that NDP setup is complete + * @wdev: the wireless device reporting the event + * @params: NDP confirm parameters + * @gfp: allocation flags + * + * Notify userspace that NAN Data Path setup is complete. Includes the + * accept/reject status and, if accepted, the responder NDI. Only valid + * when %WIPHY_NAN_FLAGS_OFFLOAD_NDP is set. + */ +void cfg80211_nan_ndp_confirm(struct wireless_dev *wdev, + struct cfg80211_nan_ndp_confirm_params *params, + gfp_t gfp); + /** * cfg80211_incumbent_signal_notify - Notify userspace of incumbent signal detection * @wiphy: the wiphy to use diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index c18580fffbd4..58127fbd5738 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -1488,6 +1488,12 @@ * %NL80211_ATTR_MAC (peer NMI) and %NL80211_ATTR_NAN_NDP nested with * all parsed NDP request parameters. Userspace must ensure the NDI * interface is ready before calling %NL80211_CMD_NAN_NDP_RESPOND. + * @NL80211_CMD_NAN_NDP_CONFIRM: Notification sent to userspace after + * the driver completes NDP setup and installs data path keys. Carries + * %NL80211_ATTR_MAC (peer NMI) and %NL80211_ATTR_NAN_NDP nested with + * the NDP confirm parameters including %NL80211_NAN_NDP_ATTR_RESP_NDI. + * Userspace should call %NL80211_CMD_NEW_STATION on the NDI interface + * to add the peer NDI station. * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use @@ -1775,6 +1781,7 @@ enum nl80211_commands { NL80211_CMD_NAN_NDP_RESPOND, NL80211_CMD_NAN_NDP_TERMINATE, NL80211_CMD_NAN_NDP_REQUEST, + NL80211_CMD_NAN_NDP_CONFIRM, /* add new commands above here */ @@ -8127,6 +8134,8 @@ enum nl80211_nan_conf_attributes { * rejected. * @NL80211_NAN_NDP_ATTR_REASON: (u8) Termination or rejection reason * code (enum nan_reason from the Wi-Fi Aware Specification). + * @NL80211_NAN_NDP_ATTR_STATUS: (u8) NDP status in + * %NL80211_CMD_NAN_NDP_CONFIRM, see &enum nl80211_nan_ndp_status. * @__NL80211_NAN_NDP_ATTR_LAST: Internal. * @NL80211_NAN_NDP_ATTR_MAX: Highest NDP attribute. */ @@ -8148,12 +8157,27 @@ enum nl80211_nan_ndp_attributes { NL80211_NAN_NDP_ATTR_NDPE, NL80211_NAN_NDP_ATTR_ACCEPT, NL80211_NAN_NDP_ATTR_REASON, + NL80211_NAN_NDP_ATTR_STATUS, /* keep last */ __NL80211_NAN_NDP_ATTR_LAST, NL80211_NAN_NDP_ATTR_MAX = __NL80211_NAN_NDP_ATTR_LAST - 1, }; +/** + * enum nl80211_nan_ndp_status - NAN Data Path setup status + * + * Values for %NL80211_NAN_NDP_ATTR_STATUS reported in + * %NL80211_CMD_NAN_NDP_CONFIRM. + * + * @NL80211_NAN_NDP_STATUS_ACCEPTED: NDP setup was accepted by the peer. + * @NL80211_NAN_NDP_STATUS_REJECTED: NDP setup was rejected by the peer. + */ +enum nl80211_nan_ndp_status { + NL80211_NAN_NDP_STATUS_ACCEPTED, + NL80211_NAN_NDP_STATUS_REJECTED, +}; + /** * enum nl80211_external_auth_action - Action to perform with external * authentication request. Used by NL80211_ATTR_EXTERNAL_AUTH_ACTION. diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 8b133637e4e7..ef7071501915 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -796,6 +796,7 @@ nl80211_nan_ndp_policy[NL80211_NAN_NDP_ATTR_MAX + 1] = { [NL80211_NAN_NDP_ATTR_NDPE] = { .type = NLA_FLAG }, [NL80211_NAN_NDP_ATTR_ACCEPT] = { .type = NLA_FLAG }, [NL80211_NAN_NDP_ATTR_REASON] = { .type = NLA_U8 }, + [NL80211_NAN_NDP_ATTR_STATUS] = { .type = NLA_U8 }, }; static const struct nla_policy @@ -18877,6 +18878,80 @@ void cfg80211_nan_ndp_request(struct wireless_dev *wdev, } EXPORT_SYMBOL(cfg80211_nan_ndp_request); +void cfg80211_nan_ndp_confirm(struct wireless_dev *wdev, + struct cfg80211_nan_ndp_confirm_params *params, + gfp_t gfp) +{ + struct wiphy *wiphy = wdev->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); + struct nlattr *ndp_attr; + struct sk_buff *msg; + void *hdr; + + if (WARN_ON(!(wiphy->nan_capa.flags & WIPHY_NAN_FLAGS_OFFLOAD_NDP))) + return; + + if (!wdev->owner_nlportid) + return; + + if (WARN_ON_ONCE(params->accepted && !params->resp_ndi)) + return; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); + if (!msg) + return; + + hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NAN_NDP_CONFIRM); + if (!hdr) + goto nla_put_failure; + + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || + nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev), + NL80211_ATTR_PAD) || + nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, params->peer_nmi)) + goto nla_put_failure; + + ndp_attr = nla_nest_start(msg, NL80211_ATTR_NAN_NDP); + if (!ndp_attr) + goto nla_put_failure; + + if (nla_put_u8(msg, NL80211_NAN_NDP_ATTR_ID, params->ndp_id) || + nla_put(msg, NL80211_NAN_NDP_ATTR_INIT_NDI, ETH_ALEN, + params->init_ndi) || + nla_put_u8(msg, NL80211_NAN_NDP_ATTR_STATUS, + params->accepted ? NL80211_NAN_NDP_STATUS_ACCEPTED : + NL80211_NAN_NDP_STATUS_REJECTED)) + goto nla_put_failure; + + if (params->accepted && params->resp_ndi && + nla_put(msg, NL80211_NAN_NDP_ATTR_RESP_NDI, ETH_ALEN, + params->resp_ndi)) + goto nla_put_failure; + + if (!params->accepted && + nla_put_u8(msg, NL80211_NAN_NDP_ATTR_REASON, params->reason)) + goto nla_put_failure; + + if (params->ssi && params->ssi_len && + nla_put(msg, NL80211_NAN_NDP_ATTR_SSI, params->ssi_len, + params->ssi)) + goto nla_put_failure; + + if (params->ipv6_intf_id_set && + nla_put(msg, NL80211_NAN_NDP_ATTR_IPV6_INTF_ID, + NL80211_NAN_NDP_IPV6_INTF_ID_LEN, params->ipv6_intf_id)) + goto nla_put_failure; + + nla_nest_end(msg, ndp_attr); + genlmsg_end(msg, hdr); + genlmsg_unicast(wiphy_net(wiphy), msg, wdev->owner_nlportid); + return; + +nla_put_failure: + nlmsg_free(msg); +} +EXPORT_SYMBOL(cfg80211_nan_ndp_confirm); + static bool nl80211_nan_is_sched_empty(struct cfg80211_nan_local_sched *sched) { if (!sched->n_channels) -- 2.34.1