diff options
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r-- | net/mac80211/cfg.c | 135 |
1 files changed, 87 insertions, 48 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 12d52cec9515..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; |
@@ -468,7 +463,7 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, | |||
468 | int size; | 463 | int size; |
469 | int err = -EINVAL; | 464 | int err = -EINVAL; |
470 | 465 | ||
471 | old = sdata->u.ap.beacon; | 466 | old = rtnl_dereference(sdata->u.ap.beacon); |
472 | 467 | ||
473 | /* head must not be zero-length */ | 468 | /* head must not be zero-length */ |
474 | if (params->head && !params->head_len) | 469 | if (params->head && !params->head_len) |
@@ -563,8 +558,7 @@ static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
563 | 558 | ||
564 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 559 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
565 | 560 | ||
566 | old = sdata->u.ap.beacon; | 561 | old = rtnl_dereference(sdata->u.ap.beacon); |
567 | |||
568 | if (old) | 562 | if (old) |
569 | return -EALREADY; | 563 | return -EALREADY; |
570 | 564 | ||
@@ -579,8 +573,7 @@ static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
579 | 573 | ||
580 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 574 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
581 | 575 | ||
582 | old = sdata->u.ap.beacon; | 576 | old = rtnl_dereference(sdata->u.ap.beacon); |
583 | |||
584 | if (!old) | 577 | if (!old) |
585 | return -ENOENT; | 578 | return -ENOENT; |
586 | 579 | ||
@@ -594,8 +587,7 @@ static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) | |||
594 | 587 | ||
595 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 588 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
596 | 589 | ||
597 | old = sdata->u.ap.beacon; | 590 | old = rtnl_dereference(sdata->u.ap.beacon); |
598 | |||
599 | if (!old) | 591 | if (!old) |
600 | return -ENOENT; | 592 | return -ENOENT; |
601 | 593 | ||
@@ -734,15 +726,29 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
734 | params->ht_capa, | 726 | params->ht_capa, |
735 | &sta->sta.ht_cap); | 727 | &sta->sta.ht_cap); |
736 | 728 | ||
737 | if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) { | 729 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
738 | switch (params->plink_action) { | 730 | #ifdef CONFIG_MAC80211_MESH |
739 | case PLINK_ACTION_OPEN: | 731 | if (sdata->u.mesh.security & IEEE80211_MESH_SEC_SECURED) |
740 | mesh_plink_open(sta); | 732 | switch (params->plink_state) { |
741 | break; | 733 | case NL80211_PLINK_LISTEN: |
742 | case PLINK_ACTION_BLOCK: | 734 | case NL80211_PLINK_ESTAB: |
743 | mesh_plink_block(sta); | 735 | case NL80211_PLINK_BLOCKED: |
744 | break; | 736 | sta->plink_state = params->plink_state; |
745 | } | 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 | ||
746 | } | 752 | } |
747 | } | 753 | } |
748 | 754 | ||
@@ -943,8 +949,10 @@ static int ieee80211_change_mpath(struct wiphy *wiphy, | |||
943 | 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, |
944 | struct mpath_info *pinfo) | 950 | struct mpath_info *pinfo) |
945 | { | 951 | { |
946 | if (mpath->next_hop) | 952 | struct sta_info *next_hop_sta = rcu_dereference(mpath->next_hop); |
947 | 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); | ||
948 | else | 956 | else |
949 | memset(next_hop, 0, ETH_ALEN); | 957 | memset(next_hop, 0, ETH_ALEN); |
950 | 958 | ||
@@ -1064,7 +1072,11 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh, | |||
1064 | memcpy(ifmsh->mesh_id, setup->mesh_id, ifmsh->mesh_id_len); | 1072 | memcpy(ifmsh->mesh_id, setup->mesh_id, ifmsh->mesh_id_len); |
1065 | ifmsh->mesh_pp_id = setup->path_sel_proto; | 1073 | ifmsh->mesh_pp_id = setup->path_sel_proto; |
1066 | ifmsh->mesh_pm_id = setup->path_metric; | 1074 | ifmsh->mesh_pm_id = setup->path_metric; |
1067 | ifmsh->is_secure = setup->is_secure; | 1075 | ifmsh->security = IEEE80211_MESH_SEC_NONE; |
1076 | if (setup->is_authenticated) | ||
1077 | ifmsh->security |= IEEE80211_MESH_SEC_AUTHED; | ||
1078 | if (setup->is_secure) | ||
1079 | ifmsh->security |= IEEE80211_MESH_SEC_SECURED; | ||
1068 | 1080 | ||
1069 | return 0; | 1081 | return 0; |
1070 | } | 1082 | } |
@@ -1297,9 +1309,10 @@ static int ieee80211_set_channel(struct wiphy *wiphy, | |||
1297 | } | 1309 | } |
1298 | 1310 | ||
1299 | #ifdef CONFIG_PM | 1311 | #ifdef CONFIG_PM |
1300 | static int ieee80211_suspend(struct wiphy *wiphy) | 1312 | static int ieee80211_suspend(struct wiphy *wiphy, |
1313 | struct cfg80211_wowlan *wowlan) | ||
1301 | { | 1314 | { |
1302 | return __ieee80211_suspend(wiphy_priv(wiphy)); | 1315 | return __ieee80211_suspend(wiphy_priv(wiphy), wowlan); |
1303 | } | 1316 | } |
1304 | 1317 | ||
1305 | static int ieee80211_resume(struct wiphy *wiphy) | 1318 | static int ieee80211_resume(struct wiphy *wiphy) |
@@ -1342,6 +1355,30 @@ static int ieee80211_scan(struct wiphy *wiphy, | |||
1342 | return ieee80211_request_scan(sdata, req); | 1355 | return ieee80211_request_scan(sdata, req); |
1343 | } | 1356 | } |
1344 | 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 | |||
1345 | static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev, | 1382 | static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev, |
1346 | struct cfg80211_auth_request *req) | 1383 | struct cfg80211_auth_request *req) |
1347 | { | 1384 | { |
@@ -2083,6 +2120,8 @@ struct cfg80211_ops mac80211_config_ops = { | |||
2083 | .suspend = ieee80211_suspend, | 2120 | .suspend = ieee80211_suspend, |
2084 | .resume = ieee80211_resume, | 2121 | .resume = ieee80211_resume, |
2085 | .scan = ieee80211_scan, | 2122 | .scan = ieee80211_scan, |
2123 | .sched_scan_start = ieee80211_sched_scan_start, | ||
2124 | .sched_scan_stop = ieee80211_sched_scan_stop, | ||
2086 | .auth = ieee80211_auth, | 2125 | .auth = ieee80211_auth, |
2087 | .assoc = ieee80211_assoc, | 2126 | .assoc = ieee80211_assoc, |
2088 | .deauth = ieee80211_deauth, | 2127 | .deauth = ieee80211_deauth, |