aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <jouni@qca.qualcomm.com>2016-05-30 17:16:50 -0400
committerJohannes Berg <johannes.berg@intel.com>2016-05-31 09:22:15 -0400
commitbf1ecd210541ef5f3a110e88e8ca5d33b4aa5c23 (patch)
treeebbfa932f41701f525ff541555c5414c541e9e18
parent0bb7ed426373cebf406ff3ae7b6d2344f2f4364c (diff)
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 <jouni@qca.qualcomm.com> [johannes: fix cfg80211_connect_bss() prototype to use int for status, add cfg80211_connect_timeout() to docbook, fix docbook] Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--Documentation/DocBook/80211.tmpl1
-rw-r--r--include/net/cfg80211.h53
-rw-r--r--include/uapi/linux/nl80211.h7
-rw-r--r--net/wireless/core.h4
-rw-r--r--net/wireless/nl80211.c7
-rw-r--r--net/wireless/nl80211.h2
-rw-r--r--net/wireless/sme.c8
7 files changed, 58 insertions, 24 deletions
diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl
index 5f7c55999c77..800fe7a9024c 100644
--- a/Documentation/DocBook/80211.tmpl
+++ b/Documentation/DocBook/80211.tmpl
@@ -136,6 +136,7 @@
136!Finclude/net/cfg80211.h cfg80211_ibss_joined 136!Finclude/net/cfg80211.h cfg80211_ibss_joined
137!Finclude/net/cfg80211.h cfg80211_connect_result 137!Finclude/net/cfg80211.h cfg80211_connect_result
138!Finclude/net/cfg80211.h cfg80211_connect_bss 138!Finclude/net/cfg80211.h cfg80211_connect_bss
139!Finclude/net/cfg80211.h cfg80211_connect_timeout
139!Finclude/net/cfg80211.h cfg80211_roamed 140!Finclude/net/cfg80211.h cfg80211_roamed
140!Finclude/net/cfg80211.h cfg80211_disconnected 141!Finclude/net/cfg80211.h cfg80211_disconnected
141!Finclude/net/cfg80211.h cfg80211_ready_on_channel 142!Finclude/net/cfg80211.h cfg80211_ready_on_channel
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 63921672bed0..537f010cf5e1 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2367,19 +2367,23 @@ struct cfg80211_qos_map {
2367 * (invoked with the wireless_dev mutex held) 2367 * (invoked with the wireless_dev mutex held)
2368 * 2368 *
2369 * @connect: Connect to the ESS with the specified parameters. When connected, 2369 * @connect: Connect to the ESS with the specified parameters. When connected,
2370 * call cfg80211_connect_result() with status code %WLAN_STATUS_SUCCESS. 2370 * call cfg80211_connect_result()/cfg80211_connect_bss() with status code
2371 * If the connection fails for some reason, call cfg80211_connect_result() 2371 * %WLAN_STATUS_SUCCESS. If the connection fails for some reason, call
2372 * with the status from the AP. The driver is allowed to roam to other 2372 * cfg80211_connect_result()/cfg80211_connect_bss() with the status code
2373 * BSSes within the ESS when the other BSS matches the connect parameters. 2373 * from the AP or cfg80211_connect_timeout() if no frame with status code
2374 * When such roaming is initiated by the driver, the driver is expected to 2374 * was received.
2375 * verify that the target matches the configured security parameters and 2375 * The driver is allowed to roam to other BSSes within the ESS when the
2376 * to use Reassociation Request frame instead of Association Request frame. 2376 * other BSS matches the connect parameters. When such roaming is initiated
2377 * The connect function can also be used to request the driver to perform 2377 * by the driver, the driver is expected to verify that the target matches
2378 * a specific roam when connected to an ESS. In that case, the prev_bssid 2378 * the configured security parameters and to use Reassociation Request
2379 * frame instead of Association Request frame.
2380 * The connect function can also be used to request the driver to perform a
2381 * specific roam when connected to an ESS. In that case, the prev_bssid
2379 * parameter is set to the BSSID of the currently associated BSS as an 2382 * parameter is set to the BSSID of the currently associated BSS as an
2380 * indication of requesting reassociation. In both the driver-initiated and 2383 * indication of requesting reassociation.
2381 * new connect() call initiated roaming cases, the result of roaming is 2384 * In both the driver-initiated and new connect() call initiated roaming
2382 * indicated with a call to cfg80211_roamed() or cfg80211_roamed_bss(). 2385 * cases, the result of roaming is indicated with a call to
2386 * cfg80211_roamed() or cfg80211_roamed_bss().
2383 * (invoked with the wireless_dev mutex held) 2387 * (invoked with the wireless_dev mutex held)
2384 * @disconnect: Disconnect from the BSS/ESS. 2388 * @disconnect: Disconnect from the BSS/ESS.
2385 * (invoked with the wireless_dev mutex held) 2389 * (invoked with the wireless_dev mutex held)
@@ -4680,7 +4684,7 @@ static inline void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp)
4680void cfg80211_connect_bss(struct net_device *dev, const u8 *bssid, 4684void cfg80211_connect_bss(struct net_device *dev, const u8 *bssid,
4681 struct cfg80211_bss *bss, const u8 *req_ie, 4685 struct cfg80211_bss *bss, const u8 *req_ie,
4682 size_t req_ie_len, const u8 *resp_ie, 4686 size_t req_ie_len, const u8 *resp_ie,
4683 size_t resp_ie_len, u16 status, gfp_t gfp); 4687 size_t resp_ie_len, int status, gfp_t gfp);
4684 4688
4685/** 4689/**
4686 * cfg80211_connect_result - notify cfg80211 of connection result 4690 * cfg80211_connect_result - notify cfg80211 of connection result
@@ -4710,6 +4714,29 @@ cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
4710} 4714}
4711 4715
4712/** 4716/**
4717 * cfg80211_connect_timeout - notify cfg80211 of connection timeout
4718 *
4719 * @dev: network device
4720 * @bssid: the BSSID of the AP
4721 * @req_ie: association request IEs (maybe be %NULL)
4722 * @req_ie_len: association request IEs length
4723 * @gfp: allocation flags
4724 *
4725 * It should be called by the underlying driver whenever connect() has failed
4726 * in a sequence where no explicit authentication/association rejection was
4727 * received from the AP. This could happen, e.g., due to not being able to send
4728 * out the Authentication or Association Request frame or timing out while
4729 * waiting for the response.
4730 */
4731static inline void
4732cfg80211_connect_timeout(struct net_device *dev, const u8 *bssid,
4733 const u8 *req_ie, size_t req_ie_len, gfp_t gfp)
4734{
4735 cfg80211_connect_bss(dev, bssid, NULL, req_ie, req_ie_len, NULL, 0, -1,
4736 gfp);
4737}
4738
4739/**
4713 * cfg80211_roamed - notify cfg80211 of roaming 4740 * cfg80211_roamed - notify cfg80211 of roaming
4714 * 4741 *
4715 * @dev: network device 4742 * @dev: network device
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index e23d78685a01..8d995316aadb 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -493,7 +493,12 @@
493 * This attribute is ignored if driver does not support roam scan. 493 * This attribute is ignored if driver does not support roam scan.
494 * It is also sent as an event, with the BSSID and response IEs when the 494 * It is also sent as an event, with the BSSID and response IEs when the
495 * connection is established or failed to be established. This can be 495 * connection is established or failed to be established. This can be
496 * determined by the STATUS_CODE attribute. 496 * determined by the %NL80211_ATTR_STATUS_CODE attribute (0 = success,
497 * non-zero = failure). If %NL80211_ATTR_TIMED_OUT is included in the
498 * event, the connection attempt failed due to not being able to initiate
499 * authentication/association or not receiving a response from the AP.
500 * Non-zero %NL80211_ATTR_STATUS_CODE value is indicated in that case as
501 * well to remain backwards compatible.
497 * @NL80211_CMD_ROAM: request that the card roam (currently not implemented), 502 * @NL80211_CMD_ROAM: request that the card roam (currently not implemented),
498 * sent as an event when the card/driver roamed by itself. 503 * sent as an event when the card/driver roamed by itself.
499 * @NL80211_CMD_DISCONNECT: drop a given connection; also used to notify 504 * @NL80211_CMD_DISCONNECT: drop a given connection; also used to notify
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 025b7a5d508b..a4d547f99f8d 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -214,7 +214,7 @@ struct cfg80211_event {
214 size_t req_ie_len; 214 size_t req_ie_len;
215 size_t resp_ie_len; 215 size_t resp_ie_len;
216 struct cfg80211_bss *bss; 216 struct cfg80211_bss *bss;
217 u16 status; 217 int status; /* -1 = failed; 0..65535 = status code */
218 } cr; 218 } cr;
219 struct { 219 struct {
220 const u8 *req_ie; 220 const u8 *req_ie;
@@ -374,7 +374,7 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
374void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, 374void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
375 const u8 *req_ie, size_t req_ie_len, 375 const u8 *req_ie, size_t req_ie_len,
376 const u8 *resp_ie, size_t resp_ie_len, 376 const u8 *resp_ie, size_t resp_ie_len,
377 u16 status, bool wextev, 377 int status, bool wextev,
378 struct cfg80211_bss *bss); 378 struct cfg80211_bss *bss);
379void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, 379void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
380 size_t ie_len, u16 reason, bool from_ap); 380 size_t ie_len, u16 reason, bool from_ap);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index bf75afa18699..03ac2ba8b174 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -12092,7 +12092,7 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
12092 struct net_device *netdev, const u8 *bssid, 12092 struct net_device *netdev, const u8 *bssid,
12093 const u8 *req_ie, size_t req_ie_len, 12093 const u8 *req_ie, size_t req_ie_len,
12094 const u8 *resp_ie, size_t resp_ie_len, 12094 const u8 *resp_ie, size_t resp_ie_len,
12095 u16 status, gfp_t gfp) 12095 int status, gfp_t gfp)
12096{ 12096{
12097 struct sk_buff *msg; 12097 struct sk_buff *msg;
12098 void *hdr; 12098 void *hdr;
@@ -12110,7 +12110,10 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
12110 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || 12110 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
12111 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || 12111 nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
12112 (bssid && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid)) || 12112 (bssid && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid)) ||
12113 nla_put_u16(msg, NL80211_ATTR_STATUS_CODE, status) || 12113 nla_put_u16(msg, NL80211_ATTR_STATUS_CODE,
12114 status < 0 ? WLAN_STATUS_UNSPECIFIED_FAILURE :
12115 status) ||
12116 (status < 0 && nla_put_flag(msg, NL80211_ATTR_TIMED_OUT)) ||
12114 (req_ie && 12117 (req_ie &&
12115 nla_put(msg, NL80211_ATTR_REQ_IE, req_ie_len, req_ie)) || 12118 nla_put(msg, NL80211_ATTR_REQ_IE, req_ie_len, req_ie)) ||
12116 (resp_ie && 12119 (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,
55 struct net_device *netdev, const u8 *bssid, 55 struct net_device *netdev, const u8 *bssid,
56 const u8 *req_ie, size_t req_ie_len, 56 const u8 *req_ie, size_t req_ie_len,
57 const u8 *resp_ie, size_t resp_ie_len, 57 const u8 *resp_ie, size_t resp_ie_len,
58 u16 status, gfp_t gfp); 58 int status, gfp_t gfp);
59void nl80211_send_roamed(struct cfg80211_registered_device *rdev, 59void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
60 struct net_device *netdev, const u8 *bssid, 60 struct net_device *netdev, const u8 *bssid,
61 const u8 *req_ie, size_t req_ie_len, 61 const u8 *req_ie, size_t req_ie_len,
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 584fdc347221..add6824c44fd 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -244,9 +244,7 @@ void cfg80211_conn_work(struct work_struct *work)
244 if (cfg80211_conn_do_work(wdev)) { 244 if (cfg80211_conn_do_work(wdev)) {
245 __cfg80211_connect_result( 245 __cfg80211_connect_result(
246 wdev->netdev, bssid, 246 wdev->netdev, bssid,
247 NULL, 0, NULL, 0, 247 NULL, 0, NULL, 0, -1, false, NULL);
248 WLAN_STATUS_UNSPECIFIED_FAILURE,
249 false, NULL);
250 } 248 }
251 wdev_unlock(wdev); 249 wdev_unlock(wdev);
252 } 250 }
@@ -648,7 +646,7 @@ static DECLARE_WORK(cfg80211_disconnect_work, disconnect_work);
648void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, 646void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
649 const u8 *req_ie, size_t req_ie_len, 647 const u8 *req_ie, size_t req_ie_len,
650 const u8 *resp_ie, size_t resp_ie_len, 648 const u8 *resp_ie, size_t resp_ie_len,
651 u16 status, bool wextev, 649 int status, bool wextev,
652 struct cfg80211_bss *bss) 650 struct cfg80211_bss *bss)
653{ 651{
654 struct wireless_dev *wdev = dev->ieee80211_ptr; 652 struct wireless_dev *wdev = dev->ieee80211_ptr;
@@ -757,7 +755,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
757void cfg80211_connect_bss(struct net_device *dev, const u8 *bssid, 755void cfg80211_connect_bss(struct net_device *dev, const u8 *bssid,
758 struct cfg80211_bss *bss, const u8 *req_ie, 756 struct cfg80211_bss *bss, const u8 *req_ie,
759 size_t req_ie_len, const u8 *resp_ie, 757 size_t req_ie_len, const u8 *resp_ie,
760 size_t resp_ie_len, u16 status, gfp_t gfp) 758 size_t resp_ie_len, int status, gfp_t gfp)
761{ 759{
762 struct wireless_dev *wdev = dev->ieee80211_ptr; 760 struct wireless_dev *wdev = dev->ieee80211_ptr;
763 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); 761 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);