diff options
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r-- | net/mac80211/cfg.c | 188 |
1 files changed, 123 insertions, 65 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 44049733c4ea..be70c70d3f5b 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -136,7 +136,10 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
136 | mutex_lock(&sdata->local->sta_mtx); | 136 | mutex_lock(&sdata->local->sta_mtx); |
137 | 137 | ||
138 | if (mac_addr) { | 138 | if (mac_addr) { |
139 | sta = sta_info_get_bss(sdata, mac_addr); | 139 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
140 | sta = sta_info_get(sdata, mac_addr); | ||
141 | else | ||
142 | sta = sta_info_get_bss(sdata, mac_addr); | ||
140 | if (!sta) { | 143 | if (!sta) { |
141 | ieee80211_key_free(sdata->local, key); | 144 | ieee80211_key_free(sdata->local, key); |
142 | err = -ENOENT; | 145 | err = -ENOENT; |
@@ -157,13 +160,14 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
157 | static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | 160 | static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, |
158 | u8 key_idx, bool pairwise, const u8 *mac_addr) | 161 | u8 key_idx, bool pairwise, const u8 *mac_addr) |
159 | { | 162 | { |
160 | struct ieee80211_sub_if_data *sdata; | 163 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
164 | struct ieee80211_local *local = sdata->local; | ||
161 | struct sta_info *sta; | 165 | struct sta_info *sta; |
166 | struct ieee80211_key *key = NULL; | ||
162 | int ret; | 167 | int ret; |
163 | 168 | ||
164 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 169 | mutex_lock(&local->sta_mtx); |
165 | 170 | mutex_lock(&local->key_mtx); | |
166 | mutex_lock(&sdata->local->sta_mtx); | ||
167 | 171 | ||
168 | if (mac_addr) { | 172 | if (mac_addr) { |
169 | ret = -ENOENT; | 173 | ret = -ENOENT; |
@@ -172,33 +176,24 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | |||
172 | if (!sta) | 176 | if (!sta) |
173 | goto out_unlock; | 177 | goto out_unlock; |
174 | 178 | ||
175 | if (pairwise) { | 179 | if (pairwise) |
176 | if (sta->ptk) { | 180 | key = key_mtx_dereference(local, sta->ptk); |
177 | ieee80211_key_free(sdata->local, sta->ptk); | 181 | else |
178 | ret = 0; | 182 | key = key_mtx_dereference(local, sta->gtk[key_idx]); |
179 | } | 183 | } else |
180 | } else { | 184 | key = key_mtx_dereference(local, sdata->keys[key_idx]); |
181 | if (sta->gtk[key_idx]) { | ||
182 | ieee80211_key_free(sdata->local, | ||
183 | sta->gtk[key_idx]); | ||
184 | ret = 0; | ||
185 | } | ||
186 | } | ||
187 | |||
188 | goto out_unlock; | ||
189 | } | ||
190 | 185 | ||
191 | if (!sdata->keys[key_idx]) { | 186 | if (!key) { |
192 | ret = -ENOENT; | 187 | ret = -ENOENT; |
193 | goto out_unlock; | 188 | goto out_unlock; |
194 | } | 189 | } |
195 | 190 | ||
196 | ieee80211_key_free(sdata->local, sdata->keys[key_idx]); | 191 | __ieee80211_key_free(key); |
197 | WARN_ON(sdata->keys[key_idx]); | ||
198 | 192 | ||
199 | ret = 0; | 193 | ret = 0; |
200 | out_unlock: | 194 | out_unlock: |
201 | mutex_unlock(&sdata->local->sta_mtx); | 195 | mutex_unlock(&local->key_mtx); |
196 | mutex_unlock(&local->sta_mtx); | ||
202 | 197 | ||
203 | return ret; | 198 | return ret; |
204 | } | 199 | } |
@@ -228,11 +223,11 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
228 | goto out; | 223 | goto out; |
229 | 224 | ||
230 | if (pairwise) | 225 | if (pairwise) |
231 | key = sta->ptk; | 226 | key = rcu_dereference(sta->ptk); |
232 | else if (key_idx < NUM_DEFAULT_KEYS) | 227 | else if (key_idx < NUM_DEFAULT_KEYS) |
233 | key = sta->gtk[key_idx]; | 228 | key = rcu_dereference(sta->gtk[key_idx]); |
234 | } else | 229 | } else |
235 | key = sdata->keys[key_idx]; | 230 | key = rcu_dereference(sdata->keys[key_idx]); |
236 | 231 | ||
237 | if (!key) | 232 | if (!key) |
238 | goto out; | 233 | goto out; |
@@ -330,6 +325,7 @@ static void rate_idx_to_bitrate(struct rate_info *rate, struct sta_info *sta, in | |||
330 | static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | 325 | static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) |
331 | { | 326 | { |
332 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 327 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
328 | struct timespec uptime; | ||
333 | 329 | ||
334 | sinfo->generation = sdata->local->sta_generation; | 330 | sinfo->generation = sdata->local->sta_generation; |
335 | 331 | ||
@@ -342,7 +338,12 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
342 | STATION_INFO_TX_FAILED | | 338 | STATION_INFO_TX_FAILED | |
343 | STATION_INFO_TX_BITRATE | | 339 | STATION_INFO_TX_BITRATE | |
344 | STATION_INFO_RX_BITRATE | | 340 | STATION_INFO_RX_BITRATE | |
345 | STATION_INFO_RX_DROP_MISC; | 341 | STATION_INFO_RX_DROP_MISC | |
342 | STATION_INFO_BSS_PARAM | | ||
343 | STATION_INFO_CONNECTED_TIME; | ||
344 | |||
345 | do_posix_clock_monotonic_gettime(&uptime); | ||
346 | sinfo->connected_time = uptime.tv_sec - sta->last_connected; | ||
346 | 347 | ||
347 | sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); | 348 | sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); |
348 | sinfo->rx_bytes = sta->rx_bytes; | 349 | sinfo->rx_bytes = sta->rx_bytes; |
@@ -389,6 +390,16 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
389 | sinfo->plink_state = sta->plink_state; | 390 | sinfo->plink_state = sta->plink_state; |
390 | #endif | 391 | #endif |
391 | } | 392 | } |
393 | |||
394 | sinfo->bss_param.flags = 0; | ||
395 | if (sdata->vif.bss_conf.use_cts_prot) | ||
396 | sinfo->bss_param.flags |= BSS_PARAM_FLAGS_CTS_PROT; | ||
397 | if (sdata->vif.bss_conf.use_short_preamble) | ||
398 | sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE; | ||
399 | if (sdata->vif.bss_conf.use_short_slot) | ||
400 | sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME; | ||
401 | sinfo->bss_param.dtim_period = sdata->local->hw.conf.ps_dtim_period; | ||
402 | sinfo->bss_param.beacon_interval = sdata->vif.bss_conf.beacon_int; | ||
392 | } | 403 | } |
393 | 404 | ||
394 | 405 | ||
@@ -452,7 +463,7 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, | |||
452 | int size; | 463 | int size; |
453 | int err = -EINVAL; | 464 | int err = -EINVAL; |
454 | 465 | ||
455 | old = sdata->u.ap.beacon; | 466 | old = rtnl_dereference(sdata->u.ap.beacon); |
456 | 467 | ||
457 | /* head must not be zero-length */ | 468 | /* head must not be zero-length */ |
458 | if (params->head && !params->head_len) | 469 | if (params->head && !params->head_len) |
@@ -547,8 +558,7 @@ static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
547 | 558 | ||
548 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 559 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
549 | 560 | ||
550 | old = sdata->u.ap.beacon; | 561 | old = rtnl_dereference(sdata->u.ap.beacon); |
551 | |||
552 | if (old) | 562 | if (old) |
553 | return -EALREADY; | 563 | return -EALREADY; |
554 | 564 | ||
@@ -563,8 +573,7 @@ static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
563 | 573 | ||
564 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 574 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
565 | 575 | ||
566 | old = sdata->u.ap.beacon; | 576 | old = rtnl_dereference(sdata->u.ap.beacon); |
567 | |||
568 | if (!old) | 577 | if (!old) |
569 | return -ENOENT; | 578 | return -ENOENT; |
570 | 579 | ||
@@ -578,8 +587,7 @@ static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) | |||
578 | 587 | ||
579 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 588 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
580 | 589 | ||
581 | old = sdata->u.ap.beacon; | 590 | old = rtnl_dereference(sdata->u.ap.beacon); |
582 | |||
583 | if (!old) | 591 | if (!old) |
584 | return -ENOENT; | 592 | return -ENOENT; |
585 | 593 | ||
@@ -675,6 +683,12 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
675 | if (set & BIT(NL80211_STA_FLAG_MFP)) | 683 | if (set & BIT(NL80211_STA_FLAG_MFP)) |
676 | sta->flags |= WLAN_STA_MFP; | 684 | sta->flags |= WLAN_STA_MFP; |
677 | } | 685 | } |
686 | |||
687 | if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) { | ||
688 | sta->flags &= ~WLAN_STA_AUTH; | ||
689 | if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) | ||
690 | sta->flags |= WLAN_STA_AUTH; | ||
691 | } | ||
678 | spin_unlock_irqrestore(&sta->flaglock, flags); | 692 | spin_unlock_irqrestore(&sta->flaglock, flags); |
679 | 693 | ||
680 | /* | 694 | /* |
@@ -712,15 +726,29 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
712 | params->ht_capa, | 726 | params->ht_capa, |
713 | &sta->sta.ht_cap); | 727 | &sta->sta.ht_cap); |
714 | 728 | ||
715 | if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) { | 729 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
716 | switch (params->plink_action) { | 730 | #ifdef CONFIG_MAC80211_MESH |
717 | case PLINK_ACTION_OPEN: | 731 | if (sdata->u.mesh.security & IEEE80211_MESH_SEC_SECURED) |
718 | mesh_plink_open(sta); | 732 | switch (params->plink_state) { |
719 | break; | 733 | case NL80211_PLINK_LISTEN: |
720 | case PLINK_ACTION_BLOCK: | 734 | case NL80211_PLINK_ESTAB: |
721 | mesh_plink_block(sta); | 735 | case NL80211_PLINK_BLOCKED: |
722 | break; | 736 | sta->plink_state = params->plink_state; |
723 | } | 737 | break; |
738 | default: | ||
739 | /* nothing */ | ||
740 | break; | ||
741 | } | ||
742 | else | ||
743 | switch (params->plink_action) { | ||
744 | case PLINK_ACTION_OPEN: | ||
745 | mesh_plink_open(sta); | ||
746 | break; | ||
747 | case PLINK_ACTION_BLOCK: | ||
748 | mesh_plink_block(sta); | ||
749 | break; | ||
750 | } | ||
751 | #endif | ||
724 | } | 752 | } |
725 | } | 753 | } |
726 | 754 | ||
@@ -921,8 +949,10 @@ static int ieee80211_change_mpath(struct wiphy *wiphy, | |||
921 | static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop, | 949 | static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop, |
922 | struct mpath_info *pinfo) | 950 | struct mpath_info *pinfo) |
923 | { | 951 | { |
924 | if (mpath->next_hop) | 952 | struct sta_info *next_hop_sta = rcu_dereference(mpath->next_hop); |
925 | memcpy(next_hop, mpath->next_hop->sta.addr, ETH_ALEN); | 953 | |
954 | if (next_hop_sta) | ||
955 | memcpy(next_hop, next_hop_sta->sta.addr, ETH_ALEN); | ||
926 | else | 956 | else |
927 | memset(next_hop, 0, ETH_ALEN); | 957 | memset(next_hop, 0, ETH_ALEN); |
928 | 958 | ||
@@ -1023,26 +1053,30 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh, | |||
1023 | u8 *new_ie; | 1053 | u8 *new_ie; |
1024 | const u8 *old_ie; | 1054 | const u8 *old_ie; |
1025 | 1055 | ||
1026 | /* first allocate the new vendor information element */ | 1056 | /* allocate information elements */ |
1027 | new_ie = NULL; | 1057 | new_ie = NULL; |
1028 | old_ie = ifmsh->vendor_ie; | 1058 | old_ie = ifmsh->ie; |
1029 | 1059 | ||
1030 | ifmsh->vendor_ie_len = setup->vendor_ie_len; | 1060 | if (setup->ie_len) { |
1031 | if (setup->vendor_ie_len) { | 1061 | new_ie = kmemdup(setup->ie, setup->ie_len, |
1032 | new_ie = kmemdup(setup->vendor_ie, setup->vendor_ie_len, | ||
1033 | GFP_KERNEL); | 1062 | GFP_KERNEL); |
1034 | if (!new_ie) | 1063 | if (!new_ie) |
1035 | return -ENOMEM; | 1064 | return -ENOMEM; |
1036 | } | 1065 | } |
1066 | ifmsh->ie_len = setup->ie_len; | ||
1067 | ifmsh->ie = new_ie; | ||
1068 | kfree(old_ie); | ||
1037 | 1069 | ||
1038 | /* now copy the rest of the setup parameters */ | 1070 | /* now copy the rest of the setup parameters */ |
1039 | ifmsh->mesh_id_len = setup->mesh_id_len; | 1071 | ifmsh->mesh_id_len = setup->mesh_id_len; |
1040 | memcpy(ifmsh->mesh_id, setup->mesh_id, ifmsh->mesh_id_len); | 1072 | memcpy(ifmsh->mesh_id, setup->mesh_id, ifmsh->mesh_id_len); |
1041 | ifmsh->mesh_pp_id = setup->path_sel_proto; | 1073 | ifmsh->mesh_pp_id = setup->path_sel_proto; |
1042 | ifmsh->mesh_pm_id = setup->path_metric; | 1074 | ifmsh->mesh_pm_id = setup->path_metric; |
1043 | ifmsh->vendor_ie = new_ie; | 1075 | ifmsh->security = IEEE80211_MESH_SEC_NONE; |
1044 | 1076 | if (setup->is_authenticated) | |
1045 | kfree(old_ie); | 1077 | ifmsh->security |= IEEE80211_MESH_SEC_AUTHED; |
1078 | if (setup->is_secure) | ||
1079 | ifmsh->security |= IEEE80211_MESH_SEC_SECURED; | ||
1046 | 1080 | ||
1047 | return 0; | 1081 | return 0; |
1048 | } | 1082 | } |
@@ -1275,9 +1309,10 @@ static int ieee80211_set_channel(struct wiphy *wiphy, | |||
1275 | } | 1309 | } |
1276 | 1310 | ||
1277 | #ifdef CONFIG_PM | 1311 | #ifdef CONFIG_PM |
1278 | static int ieee80211_suspend(struct wiphy *wiphy) | 1312 | static int ieee80211_suspend(struct wiphy *wiphy, |
1313 | struct cfg80211_wowlan *wowlan) | ||
1279 | { | 1314 | { |
1280 | return __ieee80211_suspend(wiphy_priv(wiphy)); | 1315 | return __ieee80211_suspend(wiphy_priv(wiphy), wowlan); |
1281 | } | 1316 | } |
1282 | 1317 | ||
1283 | static int ieee80211_resume(struct wiphy *wiphy) | 1318 | static int ieee80211_resume(struct wiphy *wiphy) |
@@ -1320,6 +1355,30 @@ static int ieee80211_scan(struct wiphy *wiphy, | |||
1320 | return ieee80211_request_scan(sdata, req); | 1355 | return ieee80211_request_scan(sdata, req); |
1321 | } | 1356 | } |
1322 | 1357 | ||
1358 | static int | ||
1359 | ieee80211_sched_scan_start(struct wiphy *wiphy, | ||
1360 | struct net_device *dev, | ||
1361 | struct cfg80211_sched_scan_request *req) | ||
1362 | { | ||
1363 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1364 | |||
1365 | if (!sdata->local->ops->sched_scan_start) | ||
1366 | return -EOPNOTSUPP; | ||
1367 | |||
1368 | return ieee80211_request_sched_scan_start(sdata, req); | ||
1369 | } | ||
1370 | |||
1371 | static int | ||
1372 | ieee80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev) | ||
1373 | { | ||
1374 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1375 | |||
1376 | if (!sdata->local->ops->sched_scan_stop) | ||
1377 | return -EOPNOTSUPP; | ||
1378 | |||
1379 | return ieee80211_request_sched_scan_stop(sdata); | ||
1380 | } | ||
1381 | |||
1323 | static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev, | 1382 | static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev, |
1324 | struct cfg80211_auth_request *req) | 1383 | struct cfg80211_auth_request *req) |
1325 | { | 1384 | { |
@@ -1611,16 +1670,13 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, | |||
1611 | { | 1670 | { |
1612 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1671 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1613 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1672 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
1614 | int i; | 1673 | int i, ret; |
1615 | |||
1616 | /* | ||
1617 | * This _could_ be supported by providing a hook for | ||
1618 | * drivers for this function, but at this point it | ||
1619 | * doesn't seem worth bothering. | ||
1620 | */ | ||
1621 | if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) | ||
1622 | return -EOPNOTSUPP; | ||
1623 | 1674 | ||
1675 | if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) { | ||
1676 | ret = drv_set_bitrate_mask(local, sdata, mask); | ||
1677 | if (ret) | ||
1678 | return ret; | ||
1679 | } | ||
1624 | 1680 | ||
1625 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) | 1681 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) |
1626 | sdata->rc_rateidx_mask[i] = mask->control[i].legacy; | 1682 | sdata->rc_rateidx_mask[i] = mask->control[i].legacy; |
@@ -2064,6 +2120,8 @@ struct cfg80211_ops mac80211_config_ops = { | |||
2064 | .suspend = ieee80211_suspend, | 2120 | .suspend = ieee80211_suspend, |
2065 | .resume = ieee80211_resume, | 2121 | .resume = ieee80211_resume, |
2066 | .scan = ieee80211_scan, | 2122 | .scan = ieee80211_scan, |
2123 | .sched_scan_start = ieee80211_sched_scan_start, | ||
2124 | .sched_scan_stop = ieee80211_sched_scan_stop, | ||
2067 | .auth = ieee80211_auth, | 2125 | .auth = ieee80211_auth, |
2068 | .assoc = ieee80211_assoc, | 2126 | .assoc = ieee80211_assoc, |
2069 | .deauth = ieee80211_deauth, | 2127 | .deauth = ieee80211_deauth, |