Add NL80211_CMD_NAN_NDP_REQUEST event to notify userspace when the driver receives an incoming NDP request from a peer. Add the corresponding parameter structure and event function so the driver can report the request parameters to userspace for accept/reject decision. Signed-off-by: Shivani Baranwal --- include/net/cfg80211.h | 51 +++++++++++++++++++++++ include/uapi/linux/nl80211.h | 6 +++ net/wireless/nl80211.c | 79 ++++++++++++++++++++++++++++++++++++ 3 files changed, 136 insertions(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index a79098623442..b356818e135e 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -4436,6 +4436,44 @@ struct cfg80211_nan_ndp_terminate { u8 reason; }; +/** + * struct cfg80211_nan_ndp_request_params - NAN NDP request event parameters + * + * Sent to userspace when the driver receives a NDP Request frame. + * + * @peer_nmi: peer NMI address + * @ndp_id: NDP ID from the received frame + * @init_ndi: initiator NDI MAC from the received frame + * @publish_id: publisher's service instance ID + * @ssi: service-specific info (may be NULL) + * @ssi_len: length of @ssi + * @cipher_suite: initiator's cipher suite ID + * @pmkid: PMKID from the peer's SCIA (%NL80211_NAN_NDP_PMKID_LEN bytes, + * valid when @pmkid_set is true) + * @pmkid_set: if true, @pmkid is valid + * @gtk_required: if true, initiator requires GTK protection + * @ipv6_intf_id: initiator'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 + * @ndpe: if true, use NDPE attribute instead of NDP attribute + */ +struct cfg80211_nan_ndp_request_params { + const u8 *peer_nmi; + u8 ndp_id; + const u8 *init_ndi; + u8 publish_id; + const u8 *ssi; + u8 ssi_len; + u32 cipher_suite; + u8 pmkid[NL80211_NAN_NDP_PMKID_LEN]; + bool pmkid_set; + bool gtk_required; + u8 ipv6_intf_id[NL80211_NAN_NDP_IPV6_INTF_ID_LEN]; + bool ipv6_intf_id_set; + bool ndpe; +}; + /** * enum cfg80211_nan_conf_changes - indicates changed fields in NAN * configuration @@ -11314,6 +11352,19 @@ cfg80211_s1g_get_primary_sibling(struct wiphy *wiphy, } +/** + * cfg80211_nan_ndp_request - notify userspace of a received NDP request + * @wdev: the wireless device reporting the event + * @params: NDP request parameters parsed from the received frame + * @gfp: allocation flags + * + * Notify userspace that a NAN Data Path request was received from a peer. + * Only valid when %WIPHY_NAN_FLAGS_OFFLOAD_NDP is set. + */ +void cfg80211_nan_ndp_request(struct wireless_dev *wdev, + struct cfg80211_nan_ndp_request_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 c2b81e2c4366..c18580fffbd4 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -1483,6 +1483,11 @@ * Requires %WIPHY_NAN_FLAGS_OFFLOAD_NDP. Carries %NL80211_ATTR_NAN_NDP * nested with %NL80211_NAN_NDP_ATTR_ID, %NL80211_NAN_NDP_ATTR_INIT_NDI * and optionally %NL80211_NAN_NDP_ATTR_REASON. + * @NL80211_CMD_NAN_NDP_REQUEST: Notification sent to userspace when + * the driver receives a NDP Request frame from a peer. Carries + * %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_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use @@ -1769,6 +1774,7 @@ enum nl80211_commands { NL80211_CMD_NAN_NDP_INITIATE, NL80211_CMD_NAN_NDP_RESPOND, NL80211_CMD_NAN_NDP_TERMINATE, + NL80211_CMD_NAN_NDP_REQUEST, /* add new commands above here */ diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 7c2952947a84..8b133637e4e7 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -18798,6 +18798,85 @@ static int nl80211_nan_ndp_terminate(struct sk_buff *skb, return rdev_nan_ndp_terminate(rdev, wdev, ¶ms); } +void cfg80211_nan_ndp_request(struct wireless_dev *wdev, + struct cfg80211_nan_ndp_request_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; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); + if (!msg) + return; + + hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NAN_NDP_REQUEST); + 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_PUBLISH_ID, + params->publish_id)) + 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->cipher_suite && + nla_put_u32(msg, NL80211_NAN_NDP_ATTR_CIPHER_SUITE, + params->cipher_suite)) + goto nla_put_failure; + + if (params->pmkid_set && + nla_put(msg, NL80211_NAN_NDP_ATTR_PMKID, + NL80211_NAN_NDP_PMKID_LEN, params->pmkid)) + goto nla_put_failure; + + if (params->gtk_required && + nla_put_flag(msg, NL80211_NAN_NDP_ATTR_GTK_REQUIRED)) + 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; + + if (params->ndpe && + nla_put_flag(msg, NL80211_NAN_NDP_ATTR_NDPE)) + 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_request); + static bool nl80211_nan_is_sched_empty(struct cfg80211_nan_local_sched *sched) { if (!sched->n_channels) -- 2.34.1