aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/cfg.c140
-rw-r--r--net/mac80211/ieee80211_i.h7
-rw-r--r--net/mac80211/mlme.c45
-rw-r--r--net/mac80211/wext.c3
4 files changed, 184 insertions, 11 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 58693e52d458..223e536e8426 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1300,6 +1300,142 @@ static int ieee80211_scan(struct wiphy *wiphy,
1300 return ieee80211_request_scan(sdata, req); 1300 return ieee80211_request_scan(sdata, req);
1301} 1301}
1302 1302
1303static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev,
1304 struct cfg80211_auth_request *req)
1305{
1306 struct ieee80211_sub_if_data *sdata;
1307
1308 if (!netif_running(dev))
1309 return -ENETDOWN;
1310
1311 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1312
1313 if (sdata->vif.type != NL80211_IFTYPE_STATION)
1314 return -EOPNOTSUPP;
1315
1316 switch (req->auth_type) {
1317 case NL80211_AUTHTYPE_OPEN_SYSTEM:
1318 sdata->u.mgd.auth_algs = IEEE80211_AUTH_ALG_OPEN;
1319 break;
1320 case NL80211_AUTHTYPE_SHARED_KEY:
1321 sdata->u.mgd.auth_algs = IEEE80211_AUTH_ALG_SHARED_KEY;
1322 break;
1323 case NL80211_AUTHTYPE_FT:
1324 sdata->u.mgd.auth_algs = IEEE80211_AUTH_ALG_FT;
1325 break;
1326 case NL80211_AUTHTYPE_NETWORK_EAP:
1327 sdata->u.mgd.auth_algs = IEEE80211_AUTH_ALG_LEAP;
1328 break;
1329 default:
1330 return -EOPNOTSUPP;
1331 }
1332
1333 memcpy(sdata->u.mgd.bssid, req->peer_addr, ETH_ALEN);
1334 sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
1335 sdata->u.mgd.flags |= IEEE80211_STA_BSSID_SET;
1336
1337 /* TODO: req->chan */
1338 sdata->u.mgd.flags |= IEEE80211_STA_AUTO_CHANNEL_SEL;
1339
1340 if (req->ssid) {
1341 sdata->u.mgd.flags |= IEEE80211_STA_SSID_SET;
1342 memcpy(sdata->u.mgd.ssid, req->ssid, req->ssid_len);
1343 sdata->u.mgd.ssid_len = req->ssid_len;
1344 sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_SSID_SEL;
1345 }
1346
1347 kfree(sdata->u.mgd.sme_auth_ie);
1348 sdata->u.mgd.sme_auth_ie = NULL;
1349 sdata->u.mgd.sme_auth_ie_len = 0;
1350 if (req->ie) {
1351 sdata->u.mgd.sme_auth_ie = kmalloc(req->ie_len, GFP_KERNEL);
1352 if (sdata->u.mgd.sme_auth_ie == NULL)
1353 return -ENOMEM;
1354 memcpy(sdata->u.mgd.sme_auth_ie, req->ie, req->ie_len);
1355 sdata->u.mgd.sme_auth_ie_len = req->ie_len;
1356 }
1357
1358 sdata->u.mgd.flags |= IEEE80211_STA_EXT_SME;
1359 sdata->u.mgd.state = IEEE80211_STA_MLME_DIRECT_PROBE;
1360 ieee80211_sta_req_auth(sdata);
1361 return 0;
1362}
1363
1364static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev,
1365 struct cfg80211_assoc_request *req)
1366{
1367 struct ieee80211_sub_if_data *sdata;
1368 int ret;
1369
1370 if (!netif_running(dev))
1371 return -ENETDOWN;
1372
1373 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1374
1375 if (sdata->vif.type != NL80211_IFTYPE_STATION)
1376 return -EOPNOTSUPP;
1377
1378 if (memcmp(sdata->u.mgd.bssid, req->peer_addr, ETH_ALEN) != 0 ||
1379 !(sdata->u.mgd.flags & IEEE80211_STA_AUTHENTICATED))
1380 return -ENOLINK; /* not authenticated */
1381
1382 sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
1383 sdata->u.mgd.flags |= IEEE80211_STA_BSSID_SET;
1384
1385 /* TODO: req->chan */
1386 sdata->u.mgd.flags |= IEEE80211_STA_AUTO_CHANNEL_SEL;
1387
1388 if (req->ssid) {
1389 sdata->u.mgd.flags |= IEEE80211_STA_SSID_SET;
1390 memcpy(sdata->u.mgd.ssid, req->ssid, req->ssid_len);
1391 sdata->u.mgd.ssid_len = req->ssid_len;
1392 sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_SSID_SEL;
1393 } else
1394 sdata->u.mgd.flags |= IEEE80211_STA_AUTO_SSID_SEL;
1395
1396 ret = ieee80211_sta_set_extra_ie(sdata, req->ie, req->ie_len);
1397 if (ret)
1398 return ret;
1399
1400 sdata->u.mgd.flags |= IEEE80211_STA_EXT_SME;
1401 sdata->u.mgd.state = IEEE80211_STA_MLME_ASSOCIATE;
1402 ieee80211_sta_req_auth(sdata);
1403 return 0;
1404}
1405
1406static int ieee80211_deauth(struct wiphy *wiphy, struct net_device *dev,
1407 struct cfg80211_deauth_request *req)
1408{
1409 struct ieee80211_sub_if_data *sdata;
1410
1411 if (!netif_running(dev))
1412 return -ENETDOWN;
1413
1414 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1415 if (sdata->vif.type != NL80211_IFTYPE_STATION)
1416 return -EOPNOTSUPP;
1417
1418 /* TODO: req->ie */
1419 return ieee80211_sta_deauthenticate(sdata, req->reason_code);
1420}
1421
1422static int ieee80211_disassoc(struct wiphy *wiphy, struct net_device *dev,
1423 struct cfg80211_disassoc_request *req)
1424{
1425 struct ieee80211_sub_if_data *sdata;
1426
1427 if (!netif_running(dev))
1428 return -ENETDOWN;
1429
1430 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1431
1432 if (sdata->vif.type != NL80211_IFTYPE_STATION)
1433 return -EOPNOTSUPP;
1434
1435 /* TODO: req->ie */
1436 return ieee80211_sta_disassociate(sdata, req->reason_code);
1437}
1438
1303struct cfg80211_ops mac80211_config_ops = { 1439struct cfg80211_ops mac80211_config_ops = {
1304 .add_virtual_intf = ieee80211_add_iface, 1440 .add_virtual_intf = ieee80211_add_iface,
1305 .del_virtual_intf = ieee80211_del_iface, 1441 .del_virtual_intf = ieee80211_del_iface,
@@ -1333,4 +1469,8 @@ struct cfg80211_ops mac80211_config_ops = {
1333 .suspend = ieee80211_suspend, 1469 .suspend = ieee80211_suspend,
1334 .resume = ieee80211_resume, 1470 .resume = ieee80211_resume,
1335 .scan = ieee80211_scan, 1471 .scan = ieee80211_scan,
1472 .auth = ieee80211_auth,
1473 .assoc = ieee80211_assoc,
1474 .deauth = ieee80211_deauth,
1475 .disassoc = ieee80211_disassoc,
1336}; 1476};
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index ad12c2a03a95..7b96d95f48b1 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -256,6 +256,7 @@ struct mesh_preq_queue {
256#define IEEE80211_STA_TKIP_WEP_USED BIT(14) 256#define IEEE80211_STA_TKIP_WEP_USED BIT(14)
257#define IEEE80211_STA_CSA_RECEIVED BIT(15) 257#define IEEE80211_STA_CSA_RECEIVED BIT(15)
258#define IEEE80211_STA_MFP_ENABLED BIT(16) 258#define IEEE80211_STA_MFP_ENABLED BIT(16)
259#define IEEE80211_STA_EXT_SME BIT(17)
259/* flags for MLME request */ 260/* flags for MLME request */
260#define IEEE80211_STA_REQ_SCAN 0 261#define IEEE80211_STA_REQ_SCAN 0
261#define IEEE80211_STA_REQ_DIRECT_PROBE 1 262#define IEEE80211_STA_REQ_DIRECT_PROBE 1
@@ -266,6 +267,7 @@ struct mesh_preq_queue {
266#define IEEE80211_AUTH_ALG_OPEN BIT(0) 267#define IEEE80211_AUTH_ALG_OPEN BIT(0)
267#define IEEE80211_AUTH_ALG_SHARED_KEY BIT(1) 268#define IEEE80211_AUTH_ALG_SHARED_KEY BIT(1)
268#define IEEE80211_AUTH_ALG_LEAP BIT(2) 269#define IEEE80211_AUTH_ALG_LEAP BIT(2)
270#define IEEE80211_AUTH_ALG_FT BIT(3)
269 271
270struct ieee80211_if_managed { 272struct ieee80211_if_managed {
271 struct timer_list timer; 273 struct timer_list timer;
@@ -335,6 +337,9 @@ struct ieee80211_if_managed {
335 size_t ie_deauth_len; 337 size_t ie_deauth_len;
336 u8 *ie_disassoc; 338 u8 *ie_disassoc;
337 size_t ie_disassoc_len; 339 size_t ie_disassoc_len;
340
341 u8 *sme_auth_ie;
342 size_t sme_auth_ie_len;
338}; 343};
339 344
340enum ieee80211_ibss_flags { 345enum ieee80211_ibss_flags {
@@ -970,7 +975,7 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata,
970 struct sk_buff *skb, 975 struct sk_buff *skb,
971 struct ieee80211_rx_status *rx_status); 976 struct ieee80211_rx_status *rx_status);
972int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, 977int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata,
973 char *ie, size_t len); 978 const char *ie, size_t len);
974 979
975void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local); 980void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local);
976void ieee80211_scan_failed(struct ieee80211_local *local); 981void ieee80211_scan_failed(struct ieee80211_local *local);
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 6dc7a61bc18b..d1bcc8438772 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -730,6 +730,8 @@ static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata)
730{ 730{
731 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 731 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
732 struct ieee80211_local *local = sdata->local; 732 struct ieee80211_local *local = sdata->local;
733 u8 *ies;
734 size_t ies_len;
733 735
734 ifmgd->auth_tries++; 736 ifmgd->auth_tries++;
735 if (ifmgd->auth_tries > IEEE80211_AUTH_MAX_TRIES) { 737 if (ifmgd->auth_tries > IEEE80211_AUTH_MAX_TRIES) {
@@ -755,7 +757,14 @@ static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata)
755 printk(KERN_DEBUG "%s: authenticate with AP %pM\n", 757 printk(KERN_DEBUG "%s: authenticate with AP %pM\n",
756 sdata->dev->name, ifmgd->bssid); 758 sdata->dev->name, ifmgd->bssid);
757 759
758 ieee80211_send_auth(sdata, 1, ifmgd->auth_alg, NULL, 0, 760 if (ifmgd->flags & IEEE80211_STA_EXT_SME) {
761 ies = ifmgd->sme_auth_ie;
762 ies_len = ifmgd->sme_auth_ie_len;
763 } else {
764 ies = NULL;
765 ies_len = 0;
766 }
767 ieee80211_send_auth(sdata, 1, ifmgd->auth_alg, ies, ies_len,
759 ifmgd->bssid, 0); 768 ifmgd->bssid, 0);
760 ifmgd->auth_transaction = 2; 769 ifmgd->auth_transaction = 2;
761 770
@@ -870,7 +879,8 @@ static int ieee80211_privacy_mismatch(struct ieee80211_sub_if_data *sdata)
870 int wep_privacy; 879 int wep_privacy;
871 int privacy_invoked; 880 int privacy_invoked;
872 881
873 if (!ifmgd || (ifmgd->flags & IEEE80211_STA_MIXED_CELL)) 882 if (!ifmgd || (ifmgd->flags & (IEEE80211_STA_MIXED_CELL |
883 IEEE80211_STA_EXT_SME)))
874 return 0; 884 return 0;
875 885
876 bss = ieee80211_rx_bss_get(local, ifmgd->bssid, 886 bss = ieee80211_rx_bss_get(local, ifmgd->bssid,
@@ -998,7 +1008,11 @@ static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata)
998 1008
999 printk(KERN_DEBUG "%s: authenticated\n", sdata->dev->name); 1009 printk(KERN_DEBUG "%s: authenticated\n", sdata->dev->name);
1000 ifmgd->flags |= IEEE80211_STA_AUTHENTICATED; 1010 ifmgd->flags |= IEEE80211_STA_AUTHENTICATED;
1001 ieee80211_associate(sdata); 1011 if (ifmgd->flags & IEEE80211_STA_EXT_SME) {
1012 /* Wait for SME to request association */
1013 ifmgd->state = IEEE80211_STA_MLME_DISABLED;
1014 } else
1015 ieee80211_associate(sdata);
1002} 1016}
1003 1017
1004 1018
@@ -1084,6 +1098,7 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
1084 switch (ifmgd->auth_alg) { 1098 switch (ifmgd->auth_alg) {
1085 case WLAN_AUTH_OPEN: 1099 case WLAN_AUTH_OPEN:
1086 case WLAN_AUTH_LEAP: 1100 case WLAN_AUTH_LEAP:
1101 case WLAN_AUTH_FT:
1087 ieee80211_auth_completed(sdata); 1102 ieee80211_auth_completed(sdata);
1088 cfg80211_send_rx_auth(sdata->dev, (u8 *) mgmt, len); 1103 cfg80211_send_rx_auth(sdata->dev, (u8 *) mgmt, len);
1089 break; 1104 break;
@@ -1117,9 +1132,10 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
1117 printk(KERN_DEBUG "%s: deauthenticated (Reason: %u)\n", 1132 printk(KERN_DEBUG "%s: deauthenticated (Reason: %u)\n",
1118 sdata->dev->name, reason_code); 1133 sdata->dev->name, reason_code);
1119 1134
1120 if (ifmgd->state == IEEE80211_STA_MLME_AUTHENTICATE || 1135 if (!(ifmgd->flags & IEEE80211_STA_EXT_SME) &&
1121 ifmgd->state == IEEE80211_STA_MLME_ASSOCIATE || 1136 (ifmgd->state == IEEE80211_STA_MLME_AUTHENTICATE ||
1122 ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED) { 1137 ifmgd->state == IEEE80211_STA_MLME_ASSOCIATE ||
1138 ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED)) {
1123 ifmgd->state = IEEE80211_STA_MLME_DIRECT_PROBE; 1139 ifmgd->state = IEEE80211_STA_MLME_DIRECT_PROBE;
1124 mod_timer(&ifmgd->timer, jiffies + 1140 mod_timer(&ifmgd->timer, jiffies +
1125 IEEE80211_RETRY_AUTH_INTERVAL); 1141 IEEE80211_RETRY_AUTH_INTERVAL);
@@ -1150,7 +1166,8 @@ static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
1150 printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n", 1166 printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n",
1151 sdata->dev->name, reason_code); 1167 sdata->dev->name, reason_code);
1152 1168
1153 if (ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED) { 1169 if (!(ifmgd->flags & IEEE80211_STA_EXT_SME) &&
1170 ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED) {
1154 ifmgd->state = IEEE80211_STA_MLME_ASSOCIATE; 1171 ifmgd->state = IEEE80211_STA_MLME_ASSOCIATE;
1155 mod_timer(&ifmgd->timer, jiffies + 1172 mod_timer(&ifmgd->timer, jiffies +
1156 IEEE80211_RETRY_AUTH_INTERVAL); 1173 IEEE80211_RETRY_AUTH_INTERVAL);
@@ -1664,6 +1681,8 @@ static void ieee80211_sta_reset_auth(struct ieee80211_sub_if_data *sdata)
1664 ifmgd->auth_alg = WLAN_AUTH_SHARED_KEY; 1681 ifmgd->auth_alg = WLAN_AUTH_SHARED_KEY;
1665 else if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_LEAP) 1682 else if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_LEAP)
1666 ifmgd->auth_alg = WLAN_AUTH_LEAP; 1683 ifmgd->auth_alg = WLAN_AUTH_LEAP;
1684 else if (ifmgd->auth_algs & IEEE80211_AUTH_ALG_FT)
1685 ifmgd->auth_alg = WLAN_AUTH_FT;
1667 else 1686 else
1668 ifmgd->auth_alg = WLAN_AUTH_OPEN; 1687 ifmgd->auth_alg = WLAN_AUTH_OPEN;
1669 ifmgd->auth_transaction = -1; 1688 ifmgd->auth_transaction = -1;
@@ -1687,7 +1706,8 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata)
1687 u16 capa_val = WLAN_CAPABILITY_ESS; 1706 u16 capa_val = WLAN_CAPABILITY_ESS;
1688 struct ieee80211_channel *chan = local->oper_channel; 1707 struct ieee80211_channel *chan = local->oper_channel;
1689 1708
1690 if (ifmgd->flags & (IEEE80211_STA_AUTO_SSID_SEL | 1709 if (!(ifmgd->flags & IEEE80211_STA_EXT_SME) &&
1710 ifmgd->flags & (IEEE80211_STA_AUTO_SSID_SEL |
1691 IEEE80211_STA_AUTO_BSSID_SEL | 1711 IEEE80211_STA_AUTO_BSSID_SEL |
1692 IEEE80211_STA_AUTO_CHANNEL_SEL)) { 1712 IEEE80211_STA_AUTO_CHANNEL_SEL)) {
1693 capa_mask |= WLAN_CAPABILITY_PRIVACY; 1713 capa_mask |= WLAN_CAPABILITY_PRIVACY;
@@ -1884,7 +1904,11 @@ void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata)
1884 ieee80211_set_disassoc(sdata, true, true, 1904 ieee80211_set_disassoc(sdata, true, true,
1885 WLAN_REASON_DEAUTH_LEAVING); 1905 WLAN_REASON_DEAUTH_LEAVING);
1886 1906
1887 set_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request); 1907 if (!(ifmgd->flags & IEEE80211_STA_EXT_SME) ||
1908 ifmgd->state != IEEE80211_STA_MLME_ASSOCIATE)
1909 set_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request);
1910 else if (ifmgd->flags & IEEE80211_STA_EXT_SME)
1911 set_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request);
1888 queue_work(local->hw.workqueue, &ifmgd->work); 1912 queue_work(local->hw.workqueue, &ifmgd->work);
1889 } 1913 }
1890} 1914}
@@ -1953,7 +1977,8 @@ int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid)
1953 return ieee80211_sta_commit(sdata); 1977 return ieee80211_sta_commit(sdata);
1954} 1978}
1955 1979
1956int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, char *ie, size_t len) 1980int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata,
1981 const char *ie, size_t len)
1957{ 1982{
1958 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 1983 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1959 1984
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c
index e55d2834764c..ce21d66b1023 100644
--- a/net/mac80211/wext.c
+++ b/net/mac80211/wext.c
@@ -137,6 +137,7 @@ static int ieee80211_ioctl_siwgenie(struct net_device *dev,
137 if (ret) 137 if (ret)
138 return ret; 138 return ret;
139 sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL; 139 sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
140 sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME;
140 ieee80211_sta_req_auth(sdata); 141 ieee80211_sta_req_auth(sdata);
141 return 0; 142 return 0;
142 } 143 }
@@ -224,6 +225,7 @@ static int ieee80211_ioctl_siwessid(struct net_device *dev,
224 if (ret) 225 if (ret)
225 return ret; 226 return ret;
226 227
228 sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME;
227 ieee80211_sta_req_auth(sdata); 229 ieee80211_sta_req_auth(sdata);
228 return 0; 230 return 0;
229 } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) 231 } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
@@ -287,6 +289,7 @@ static int ieee80211_ioctl_siwap(struct net_device *dev,
287 ret = ieee80211_sta_set_bssid(sdata, (u8 *) &ap_addr->sa_data); 289 ret = ieee80211_sta_set_bssid(sdata, (u8 *) &ap_addr->sa_data);
288 if (ret) 290 if (ret)
289 return ret; 291 return ret;
292 sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME;
290 ieee80211_sta_req_auth(sdata); 293 ieee80211_sta_req_auth(sdata);
291 return 0; 294 return 0;
292 } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { 295 } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {