From dcfe1516104019774390d0c0ab3ddf195401bcf6 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 31 May 2016 00:16:50 +0300 Subject: [PATCH 1/4] cfg80211: Allow cfg80211_connect_result() errors to be distinguished Previously, the status parameter to cfg80211_connect_result() was documented as using WLAN_STATUS_UNSPECIFIED_FAILURE (1) when the real status code for the failure is not known. This value can be used by an AP (and often is) and as such, user space cannot distinguish between explicitly rejected authentication/association and not being able to even try to associate or not receiving a response from the AP. Add a new inline function, cfg80211_connect_timeout(), to be used when the driver knows that the connection attempt failed due to a reason where connection could not be attempt or no response was received from the AP. The internal functions now allow a negative status value (-1) to be used as an indication of this special case. This results in the NL80211_ATTR_TIMED_OUT to be added to the NL80211_CMD_CONNECT event to allow user space to determine this case was hit. For backwards compatibility, NL80211_STATUS_CODE with the value WLAN_STATUS_UNSPECIFIED_FAILURE is still indicated in the event in such a case. Signed-off-by: Jouni Malinen [johannes: fix cfg80211_connect_bss() prototype to use int for status, add cfg80211_connect_timeout() to docbook, fix docbook] Signed-off-by: Johannes Berg Git-commit: bf1ecd210541ef5f3a110e88e8ca5d33b4aa5c23 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git CRs-Fixed: 2004380 Change-Id: I43e2a7d588ee86a8470cf72ac0a95daaae569fa0 Signed-off-by: Purushottam Kushwaha --- Documentation/DocBook/80211.tmpl | 1 + include/net/cfg80211.h | 45 +++++++++++++++++++++++++++++--- include/uapi/linux/nl80211.h | 7 ++++- net/wireless/core.h | 4 +-- net/wireless/nl80211.c | 7 +++-- net/wireless/nl80211.h | 2 +- net/wireless/sme.c | 8 +++--- 7 files changed, 59 insertions(+), 15 deletions(-) diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl index 02431aeca15f..eaadf60f4692 100644 --- a/Documentation/DocBook/80211.tmpl +++ b/Documentation/DocBook/80211.tmpl @@ -137,6 +137,7 @@ !Finclude/net/cfg80211.h cfg80211_ibss_joined !Finclude/net/cfg80211.h cfg80211_connect_result !Finclude/net/cfg80211.h cfg80211_connect_bss +!Finclude/net/cfg80211.h cfg80211_connect_timeout !Finclude/net/cfg80211.h cfg80211_roamed !Finclude/net/cfg80211.h cfg80211_disconnected !Finclude/net/cfg80211.h cfg80211_ready_on_channel diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 1ce3ea1fd917..cb10d2c2a712 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -2437,9 +2437,23 @@ struct cfg80211_qos_map { * (invoked with the wireless_dev mutex held) * * @connect: Connect to the ESS with the specified parameters. When connected, - * call cfg80211_connect_result() with status code %WLAN_STATUS_SUCCESS. - * If the connection fails for some reason, call cfg80211_connect_result() - * with the status from the AP. + * call cfg80211_connect_result()/cfg80211_connect_bss() with status code + * %WLAN_STATUS_SUCCESS. If the connection fails for some reason, call + * cfg80211_connect_result()/cfg80211_connect_bss() with the status code + * from the AP or cfg80211_connect_timeout() if no frame with status code + * was received. + * The driver is allowed to roam to other BSSes within the ESS when the + * other BSS matches the connect parameters. When such roaming is initiated + * by the driver, the driver is expected to verify that the target matches + * the configured security parameters and to use Reassociation Request + * frame instead of Association Request frame. + * The connect function can also be used to request the driver to perform a + * specific roam when connected to an ESS. In that case, the prev_bssid + * parameter is set to the BSSID of the currently associated BSS as an + * indication of requesting reassociation. + * In both the driver-initiated and new connect() call initiated roaming + * cases, the result of roaming is indicated with a call to + * cfg80211_roamed() or cfg80211_roamed_bss(). * (invoked with the wireless_dev mutex held) * @update_connect_params: Update the connect parameters while connected to a * BSS. The updated parameters can be used by driver/firmware for @@ -4813,7 +4827,7 @@ static inline void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp) void cfg80211_connect_bss(struct net_device *dev, const u8 *bssid, struct cfg80211_bss *bss, const u8 *req_ie, size_t req_ie_len, const u8 *resp_ie, - size_t resp_ie_len, u16 status, gfp_t gfp); + size_t resp_ie_len, int status, gfp_t gfp); /** * cfg80211_connect_result - notify cfg80211 of connection result @@ -4842,6 +4856,29 @@ cfg80211_connect_result(struct net_device *dev, const u8 *bssid, resp_ie_len, status, gfp); } +/** + * cfg80211_connect_timeout - notify cfg80211 of connection timeout + * + * @dev: network device + * @bssid: the BSSID of the AP + * @req_ie: association request IEs (maybe be %NULL) + * @req_ie_len: association request IEs length + * @gfp: allocation flags + * + * It should be called by the underlying driver whenever connect() has failed + * in a sequence where no explicit authentication/association rejection was + * received from the AP. This could happen, e.g., due to not being able to send + * out the Authentication or Association Request frame or timing out while + * waiting for the response. + */ +static inline void +cfg80211_connect_timeout(struct net_device *dev, const u8 *bssid, + const u8 *req_ie, size_t req_ie_len, gfp_t gfp) +{ + cfg80211_connect_bss(dev, bssid, NULL, req_ie, req_ie_len, NULL, 0, -1, + gfp); +} + /** * cfg80211_roamed - notify cfg80211 of roaming * diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 0505b1f9872b..2a5060db43ca 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -486,7 +486,12 @@ * This attribute is ignored if driver does not support roam scan. * It is also sent as an event, with the BSSID and response IEs when the * connection is established or failed to be established. This can be - * determined by the STATUS_CODE attribute. + * determined by the %NL80211_ATTR_STATUS_CODE attribute (0 = success, + * non-zero = failure). If %NL80211_ATTR_TIMED_OUT is included in the + * event, the connection attempt failed due to not being able to initiate + * authentication/association or not receiving a response from the AP. + * Non-zero %NL80211_ATTR_STATUS_CODE value is indicated in that case as + * well to remain backwards compatible. * @NL80211_CMD_ROAM: request that the card roam (currently not implemented), * sent as an event when the card/driver roamed by itself. * @NL80211_CMD_DISCONNECT: drop a given connection; also used to notify diff --git a/net/wireless/core.h b/net/wireless/core.h index 46495dd821c8..1b2e372ed7c3 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -215,7 +215,7 @@ struct cfg80211_event { size_t req_ie_len; size_t resp_ie_len; struct cfg80211_bss *bss; - u16 status; + int status; /* -1 = failed; 0..65535 = status code */ } cr; struct { const u8 *req_ie; @@ -375,7 +375,7 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev, void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, const u8 *req_ie, size_t req_ie_len, const u8 *resp_ie, size_t resp_ie_len, - u16 status, bool wextev, + int status, bool wextev, struct cfg80211_bss *bss); void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, size_t ie_len, u16 reason, bool from_ap); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index dcae8ae9bfad..da2603dbda6e 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -12264,7 +12264,7 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev, struct net_device *netdev, const u8 *bssid, const u8 *req_ie, size_t req_ie_len, const u8 *resp_ie, size_t resp_ie_len, - u16 status, gfp_t gfp) + int status, gfp_t gfp) { struct sk_buff *msg; void *hdr; @@ -12282,7 +12282,10 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev, if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || (bssid && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid)) || - nla_put_u16(msg, NL80211_ATTR_STATUS_CODE, status) || + nla_put_u16(msg, NL80211_ATTR_STATUS_CODE, + status < 0 ? WLAN_STATUS_UNSPECIFIED_FAILURE : + status) || + (status < 0 && nla_put_flag(msg, NL80211_ATTR_TIMED_OUT)) || (req_ie && nla_put(msg, NL80211_ATTR_REQ_IE, req_ie_len, req_ie)) || (resp_ie && diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index 84d4edf1d545..a63f402b10b7 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h @@ -55,7 +55,7 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev, struct net_device *netdev, const u8 *bssid, const u8 *req_ie, size_t req_ie_len, const u8 *resp_ie, size_t resp_ie_len, - u16 status, gfp_t gfp); + int status, gfp_t gfp); void nl80211_send_roamed(struct cfg80211_registered_device *rdev, struct net_device *netdev, const u8 *bssid, const u8 *req_ie, size_t req_ie_len, diff --git a/net/wireless/sme.c b/net/wireless/sme.c index e5b962d2ffe7..2705d7bd56f9 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -267,9 +267,7 @@ void cfg80211_conn_work(struct work_struct *work) if (cfg80211_conn_do_work(wdev)) { __cfg80211_connect_result( wdev->netdev, bssid, - NULL, 0, NULL, 0, - WLAN_STATUS_UNSPECIFIED_FAILURE, - false, NULL); + NULL, 0, NULL, 0, -1, false, NULL); } wdev_unlock(wdev); } @@ -662,7 +660,7 @@ static DECLARE_WORK(cfg80211_disconnect_work, disconnect_work); void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, const u8 *req_ie, size_t req_ie_len, const u8 *resp_ie, size_t resp_ie_len, - u16 status, bool wextev, + int status, bool wextev, struct cfg80211_bss *bss) { struct wireless_dev *wdev = dev->ieee80211_ptr; @@ -771,7 +769,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, void cfg80211_connect_bss(struct net_device *dev, const u8 *bssid, struct cfg80211_bss *bss, const u8 *req_ie, size_t req_ie_len, const u8 *resp_ie, - size_t resp_ie_len, u16 status, gfp_t gfp) + size_t resp_ie_len, int status, gfp_t gfp) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); From 4f74effbf0deda7da5ae3393cbc9539d6fcf7ead Mon Sep 17 00:00:00 2001 From: Purushottam Kushwaha Date: Sat, 4 Mar 2017 11:05:26 +0530 Subject: [PATCH 2/4] msm: wlan: Define CFG80211_CONNECT_TIMEOUT To indicate, presence of cfg80211_connect_timeout() api to wlan driver, CFG80211_CONNECT_TIMEOUT is defined and depends on commit 48f3dee442d9 ("cfg80211: Allow cfg80211_connect_result() errors to be distinguished") which implements cfg80211_connect_timeout(). When CFG80211_CONNECT_TIMEOUT is defined and if wlan connection attempt failed due to timeout, then wlan driver invokes cfg80211_connect_timeout(). CRs-Fixed: 2004380 Change-Id: Ie2c16eb9c1a1330264daf843848c7da43da49b6c Signed-off-by: Purushottam Kushwaha --- include/net/cfg80211.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index cb10d2c2a712..6e7fa4696aed 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -71,6 +71,7 @@ struct wiphy; #define CFG80211_BEACON_TX_RATE_CUSTOM_BACKPORT 1 #define CFG80211_RAND_TA_FOR_PUBLIC_ACTION_FRAME 1 #define CFG80211_REPORT_BETTER_BSS_IN_SCHED_SCAN 1 +#define CFG80211_CONNECT_TIMEOUT 1 /* * wireless hardware capability structures From ddeaf3780adbb91a85f6f9e01cec808d9b5c627c Mon Sep 17 00:00:00 2001 From: Purushottam Kushwaha Date: Fri, 13 Jan 2017 01:12:21 +0200 Subject: [PATCH 3/4] cfg80211: Specify the reason for connect timeout This enhances the connect timeout API to also carry the reason for the timeout. These reason codes for the connect time out are represented by enum nl80211_timeout_reason and are passed to user space through a new attribute NL80211_ATTR_TIMEOUT_REASON (u32). Signed-off-by: Purushottam Kushwaha Signed-off-by: Jouni Malinen [keep gfp_t argument last] Signed-off-by: Johannes Berg Git-commit: 3093ebbeabcdddc9a982950052f2151df43c7aa2 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git CRs-Fixed: 2004380 Change-Id: If25dbf99d08d6ee658782fb08bd0ac670e95584a Signed-off-by: Purushottam Kushwaha --- include/net/cfg80211.h | 18 +++++++++++++---- include/uapi/linux/nl80211.h | 21 +++++++++++++++++++ net/wireless/core.h | 4 +++- net/wireless/mlme.c | 3 ++- net/wireless/nl80211.c | 9 +++++++-- net/wireless/nl80211.h | 4 +++- net/wireless/sme.c | 39 +++++++++++++++++++++++++----------- net/wireless/util.c | 2 +- 8 files changed, 78 insertions(+), 22 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 6e7fa4696aed..1d1ca6604a33 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -4819,6 +4819,12 @@ static inline void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp) * %WLAN_STATUS_UNSPECIFIED_FAILURE if your device cannot give you * the real status code for failures. * @gfp: allocation flags + * @timeout_reason: reason for connection timeout. This is used when the + * connection fails due to a timeout instead of an explicit rejection from + * the AP. %NL80211_TIMEOUT_UNSPECIFIED is used when the timeout reason is + * not known. This value is used only if @status < 0 to indicate that the + * failure is due to a timeout and not due to explicit rejection by the AP. + * This value is ignored in other cases (@status >= 0). * * It should be called by the underlying driver whenever connect() has * succeeded. This is similar to cfg80211_connect_result(), but with the @@ -4828,7 +4834,8 @@ static inline void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp) void cfg80211_connect_bss(struct net_device *dev, const u8 *bssid, struct cfg80211_bss *bss, const u8 *req_ie, size_t req_ie_len, const u8 *resp_ie, - size_t resp_ie_len, int status, gfp_t gfp); + size_t resp_ie_len, int status, gfp_t gfp, + enum nl80211_timeout_reason timeout_reason); /** * cfg80211_connect_result - notify cfg80211 of connection result @@ -4854,7 +4861,8 @@ cfg80211_connect_result(struct net_device *dev, const u8 *bssid, u16 status, gfp_t gfp) { cfg80211_connect_bss(dev, bssid, NULL, req_ie, req_ie_len, resp_ie, - resp_ie_len, status, gfp); + resp_ie_len, status, gfp, + NL80211_TIMEOUT_UNSPECIFIED); } /** @@ -4865,6 +4873,7 @@ cfg80211_connect_result(struct net_device *dev, const u8 *bssid, * @req_ie: association request IEs (maybe be %NULL) * @req_ie_len: association request IEs length * @gfp: allocation flags + * @timeout_reason: reason for connection timeout. * * It should be called by the underlying driver whenever connect() has failed * in a sequence where no explicit authentication/association rejection was @@ -4874,10 +4883,11 @@ cfg80211_connect_result(struct net_device *dev, const u8 *bssid, */ static inline void cfg80211_connect_timeout(struct net_device *dev, const u8 *bssid, - const u8 *req_ie, size_t req_ie_len, gfp_t gfp) + const u8 *req_ie, size_t req_ie_len, gfp_t gfp, + enum nl80211_timeout_reason timeout_reason) { cfg80211_connect_bss(dev, bssid, NULL, req_ie, req_ie_len, NULL, 0, -1, - gfp); + gfp, timeout_reason); } /** diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 2a5060db43ca..8a5c59a9ff0e 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -1953,6 +1953,10 @@ enum nl80211_commands { * better BSSs. The attribute value is a packed structure * value as specified by &struct nl80211_bss_select_rssi_adjust. * + * @NL80211_ATTR_TIMEOUT_REASON: The reason for which an operation timed out. + * u32 attribute with an &enum nl80211_timeout_reason value. This is used, + * e.g., with %NL80211_CMD_CONNECT event. + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -2362,6 +2366,8 @@ enum nl80211_attrs { NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI, NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST, + NL80211_ATTR_TIMEOUT_REASON, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -4699,6 +4705,21 @@ enum nl80211_connect_failed_reason { NL80211_CONN_FAIL_BLOCKED_CLIENT, }; +/** + * enum nl80211_timeout_reason - timeout reasons + * + * @NL80211_TIMEOUT_UNSPECIFIED: Timeout reason unspecified. + * @NL80211_TIMEOUT_SCAN: Scan (AP discovery) timed out. + * @NL80211_TIMEOUT_AUTH: Authentication timed out. + * @NL80211_TIMEOUT_ASSOC: Association timed out. + */ +enum nl80211_timeout_reason { + NL80211_TIMEOUT_UNSPECIFIED, + NL80211_TIMEOUT_SCAN, + NL80211_TIMEOUT_AUTH, + NL80211_TIMEOUT_ASSOC, +}; + /** * enum nl80211_scan_flags - scan request control flags * diff --git a/net/wireless/core.h b/net/wireless/core.h index 1b2e372ed7c3..2ec028ea7775 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -216,6 +216,7 @@ struct cfg80211_event { size_t resp_ie_len; struct cfg80211_bss *bss; int status; /* -1 = failed; 0..65535 = status code */ + enum nl80211_timeout_reason timeout_reason; } cr; struct { const u8 *req_ie; @@ -376,7 +377,8 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, const u8 *req_ie, size_t req_ie_len, const u8 *resp_ie, size_t resp_ie_len, int status, bool wextev, - struct cfg80211_bss *bss); + struct cfg80211_bss *bss, + enum nl80211_timeout_reason timeout_reason); void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, size_t ie_len, u16 reason, bool from_ap); int cfg80211_disconnect(struct cfg80211_registered_device *rdev, diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 594eeea9533b..36baa8d22108 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -48,7 +48,8 @@ void cfg80211_rx_assoc_resp(struct net_device *dev, struct cfg80211_bss *bss, /* update current_bss etc., consumes the bss reference */ __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs, status_code, - status_code == WLAN_STATUS_SUCCESS, bss); + status_code == WLAN_STATUS_SUCCESS, bss, + NL80211_TIMEOUT_UNSPECIFIED); } EXPORT_SYMBOL(cfg80211_rx_assoc_resp); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index da2603dbda6e..08bd3f3d27e3 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -408,6 +408,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { [NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST] = { .len = sizeof(struct nl80211_bss_select_rssi_adjust) }, + [NL80211_ATTR_TIMEOUT_REASON] = { .type = NLA_U32 }, }; /* policy for the key attributes */ @@ -12264,7 +12265,9 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev, struct net_device *netdev, const u8 *bssid, const u8 *req_ie, size_t req_ie_len, const u8 *resp_ie, size_t resp_ie_len, - int status, gfp_t gfp) + int status, + enum nl80211_timeout_reason timeout_reason, + gfp_t gfp) { struct sk_buff *msg; void *hdr; @@ -12285,7 +12288,9 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev, nla_put_u16(msg, NL80211_ATTR_STATUS_CODE, status < 0 ? WLAN_STATUS_UNSPECIFIED_FAILURE : status) || - (status < 0 && nla_put_flag(msg, NL80211_ATTR_TIMED_OUT)) || + (status < 0 && + (nla_put_flag(msg, NL80211_ATTR_TIMED_OUT) || + nla_put_u32(msg, NL80211_ATTR_TIMEOUT_REASON, timeout_reason))) || (req_ie && nla_put(msg, NL80211_ATTR_REQ_IE, req_ie_len, req_ie)) || (resp_ie && diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index a63f402b10b7..a749c9be2836 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h @@ -55,7 +55,9 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev, struct net_device *netdev, const u8 *bssid, const u8 *req_ie, size_t req_ie_len, const u8 *resp_ie, size_t resp_ie_len, - int status, gfp_t gfp); + int status, + enum nl80211_timeout_reason timeout_reason, + gfp_t gfp); void nl80211_send_roamed(struct cfg80211_registered_device *rdev, struct net_device *netdev, const u8 *bssid, const u8 *req_ie, size_t req_ie_len, diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 2705d7bd56f9..9c7f0ce35a06 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -34,10 +34,11 @@ struct cfg80211_conn { CFG80211_CONN_SCAN_AGAIN, CFG80211_CONN_AUTHENTICATE_NEXT, CFG80211_CONN_AUTHENTICATING, - CFG80211_CONN_AUTH_FAILED, + CFG80211_CONN_AUTH_FAILED_TIMEOUT, CFG80211_CONN_ASSOCIATE_NEXT, CFG80211_CONN_ASSOCIATING, CFG80211_CONN_ASSOC_FAILED, + CFG80211_CONN_ASSOC_FAILED_TIMEOUT, CFG80211_CONN_DEAUTH, CFG80211_CONN_CONNECTED, } state; @@ -162,7 +163,8 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev) return err; } -static int cfg80211_conn_do_work(struct wireless_dev *wdev) +static int cfg80211_conn_do_work(struct wireless_dev *wdev, + enum nl80211_timeout_reason *treason) { struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); struct cfg80211_connect_params *params; @@ -193,7 +195,8 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) NULL, 0, params->key, params->key_len, params->key_idx, NULL, 0); - case CFG80211_CONN_AUTH_FAILED: + case CFG80211_CONN_AUTH_FAILED_TIMEOUT: + *treason = NL80211_TIMEOUT_AUTH; return -ENOTCONN; case CFG80211_CONN_ASSOCIATE_NEXT: if (WARN_ON(!rdev->ops->assoc)) @@ -220,6 +223,9 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) WLAN_REASON_DEAUTH_LEAVING, false); return err; + case CFG80211_CONN_ASSOC_FAILED_TIMEOUT: + *treason = NL80211_TIMEOUT_ASSOC; + /* fall through */ case CFG80211_CONN_ASSOC_FAILED: cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, NULL, 0, @@ -243,6 +249,7 @@ void cfg80211_conn_work(struct work_struct *work) container_of(work, struct cfg80211_registered_device, conn_work); struct wireless_dev *wdev; u8 bssid_buf[ETH_ALEN], *bssid = NULL; + enum nl80211_timeout_reason treason; rtnl_lock(); @@ -264,10 +271,12 @@ void cfg80211_conn_work(struct work_struct *work) memcpy(bssid_buf, wdev->conn->params.bssid, ETH_ALEN); bssid = bssid_buf; } - if (cfg80211_conn_do_work(wdev)) { + treason = NL80211_TIMEOUT_UNSPECIFIED; + if (cfg80211_conn_do_work(wdev, &treason)) { __cfg80211_connect_result( wdev->netdev, bssid, - NULL, 0, NULL, 0, -1, false, NULL); + NULL, 0, NULL, 0, -1, false, NULL, + treason); } wdev_unlock(wdev); } @@ -372,7 +381,8 @@ void cfg80211_sme_rx_auth(struct wireless_dev *wdev, const u8 *buf, size_t len) } else if (status_code != WLAN_STATUS_SUCCESS) { __cfg80211_connect_result(wdev->netdev, mgmt->bssid, NULL, 0, NULL, 0, - status_code, false, NULL); + status_code, false, NULL, + NL80211_TIMEOUT_UNSPECIFIED); } else if (wdev->conn->state == CFG80211_CONN_AUTHENTICATING) { wdev->conn->state = CFG80211_CONN_ASSOCIATE_NEXT; schedule_work(&rdev->conn_work); @@ -420,7 +430,7 @@ void cfg80211_sme_auth_timeout(struct wireless_dev *wdev) if (!wdev->conn) return; - wdev->conn->state = CFG80211_CONN_AUTH_FAILED; + wdev->conn->state = CFG80211_CONN_AUTH_FAILED_TIMEOUT; schedule_work(&rdev->conn_work); } @@ -442,7 +452,7 @@ void cfg80211_sme_assoc_timeout(struct wireless_dev *wdev) if (!wdev->conn) return; - wdev->conn->state = CFG80211_CONN_ASSOC_FAILED; + wdev->conn->state = CFG80211_CONN_ASSOC_FAILED_TIMEOUT; schedule_work(&rdev->conn_work); } @@ -563,7 +573,9 @@ static int cfg80211_sme_connect(struct wireless_dev *wdev, /* we're good if we have a matching bss struct */ if (bss) { - err = cfg80211_conn_do_work(wdev); + enum nl80211_timeout_reason treason; + + err = cfg80211_conn_do_work(wdev, &treason); cfg80211_put_bss(wdev->wiphy, bss); } else { /* otherwise we'll need to scan for the AP first */ @@ -661,7 +673,8 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, const u8 *req_ie, size_t req_ie_len, const u8 *resp_ie, size_t resp_ie_len, int status, bool wextev, - struct cfg80211_bss *bss) + struct cfg80211_bss *bss, + enum nl80211_timeout_reason timeout_reason) { struct wireless_dev *wdev = dev->ieee80211_ptr; const u8 *country_ie; @@ -680,7 +693,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, nl80211_send_connect_result(wiphy_to_rdev(wdev->wiphy), dev, bssid, req_ie, req_ie_len, resp_ie, resp_ie_len, - status, GFP_KERNEL); + status, timeout_reason, GFP_KERNEL); #ifdef CONFIG_CFG80211_WEXT if (wextev) { @@ -769,7 +782,8 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, void cfg80211_connect_bss(struct net_device *dev, const u8 *bssid, struct cfg80211_bss *bss, const u8 *req_ie, size_t req_ie_len, const u8 *resp_ie, - size_t resp_ie_len, int status, gfp_t gfp) + size_t resp_ie_len, int status, gfp_t gfp, + enum nl80211_timeout_reason timeout_reason) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); @@ -809,6 +823,7 @@ void cfg80211_connect_bss(struct net_device *dev, const u8 *bssid, cfg80211_hold_bss(bss_from_pub(bss)); ev->cr.bss = bss; ev->cr.status = status; + ev->cr.timeout_reason = timeout_reason; spin_lock_irqsave(&wdev->event_lock, flags); list_add_tail(&ev->list, &wdev->event_list); diff --git a/net/wireless/util.c b/net/wireless/util.c index dfd0766abd6f..305370cfd1e0 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -878,7 +878,7 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev) ev->cr.resp_ie, ev->cr.resp_ie_len, ev->cr.status, ev->cr.status == WLAN_STATUS_SUCCESS, - ev->cr.bss); + ev->cr.bss, ev->cr.timeout_reason); break; case EVENT_ROAMED: __cfg80211_roamed(wdev, ev->rm.bss, ev->rm.req_ie, From 92eb55da1ce4644c653073332a21e9a716207d56 Mon Sep 17 00:00:00 2001 From: Purushottam Kushwaha Date: Sat, 4 Mar 2017 11:10:04 +0530 Subject: [PATCH 4/4] msm: wlan: Define CFG80211_CONNECT_TIMEOUT_REASON_CODE To indicate, presence of cfg80211_connect_timeout() api to wlan driver with additional parameter, CFG80211_CONNECT_TIMEOUT_REASON_CODE is defined and depends on commit eadbd4a4290b ("cfg80211: Specify the reason for connect timeout") which adds reason while indicating timeout. When CFG80211_CONNECT_TIMEOUT_REASON_CODE is defined and if wlan connection attempt failed due to timeout, then wlan driver invokes cfg80211_connect_timeout() with reason of timeout. CRs-Fixed: 2004380 Change-Id: I0ba392e05fa9db82de75abd8c29df0b7570066d6 Signed-off-by: Purushottam Kushwaha --- include/net/cfg80211.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 1d1ca6604a33..9e88da2764d7 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -72,6 +72,7 @@ struct wiphy; #define CFG80211_RAND_TA_FOR_PUBLIC_ACTION_FRAME 1 #define CFG80211_REPORT_BETTER_BSS_IN_SCHED_SCAN 1 #define CFG80211_CONNECT_TIMEOUT 1 +#define CFG80211_CONNECT_TIMEOUT_REASON_CODE 1 /* * wireless hardware capability structures