diff options
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r-- | net/mac80211/cfg.c | 112 |
1 files changed, 84 insertions, 28 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index d41974aacf5..05f3a313db8 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -20,7 +20,8 @@ | |||
20 | #include "rate.h" | 20 | #include "rate.h" |
21 | #include "mesh.h" | 21 | #include "mesh.h" |
22 | 22 | ||
23 | static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy, char *name, | 23 | static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy, |
24 | const char *name, | ||
24 | enum nl80211_iftype type, | 25 | enum nl80211_iftype type, |
25 | u32 *flags, | 26 | u32 *flags, |
26 | struct vif_params *params) | 27 | struct vif_params *params) |
@@ -102,6 +103,18 @@ static int ieee80211_change_iface(struct wiphy *wiphy, | |||
102 | return 0; | 103 | return 0; |
103 | } | 104 | } |
104 | 105 | ||
106 | static int ieee80211_start_p2p_device(struct wiphy *wiphy, | ||
107 | struct wireless_dev *wdev) | ||
108 | { | ||
109 | return ieee80211_do_open(wdev, true); | ||
110 | } | ||
111 | |||
112 | static void ieee80211_stop_p2p_device(struct wiphy *wiphy, | ||
113 | struct wireless_dev *wdev) | ||
114 | { | ||
115 | ieee80211_sdata_stop(IEEE80211_WDEV_TO_SUB_IF(wdev)); | ||
116 | } | ||
117 | |||
105 | static int ieee80211_set_noack_map(struct wiphy *wiphy, | 118 | static int ieee80211_set_noack_map(struct wiphy *wiphy, |
106 | struct net_device *dev, | 119 | struct net_device *dev, |
107 | u16 noack_map) | 120 | u16 noack_map) |
@@ -158,6 +171,38 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
158 | } | 171 | } |
159 | } | 172 | } |
160 | 173 | ||
174 | switch (sdata->vif.type) { | ||
175 | case NL80211_IFTYPE_STATION: | ||
176 | if (sdata->u.mgd.mfp != IEEE80211_MFP_DISABLED) | ||
177 | key->conf.flags |= IEEE80211_KEY_FLAG_RX_MGMT; | ||
178 | break; | ||
179 | case NL80211_IFTYPE_AP: | ||
180 | case NL80211_IFTYPE_AP_VLAN: | ||
181 | /* Keys without a station are used for TX only */ | ||
182 | if (key->sta && test_sta_flag(key->sta, WLAN_STA_MFP)) | ||
183 | key->conf.flags |= IEEE80211_KEY_FLAG_RX_MGMT; | ||
184 | break; | ||
185 | case NL80211_IFTYPE_ADHOC: | ||
186 | /* no MFP (yet) */ | ||
187 | break; | ||
188 | case NL80211_IFTYPE_MESH_POINT: | ||
189 | #ifdef CONFIG_MAC80211_MESH | ||
190 | if (sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE) | ||
191 | key->conf.flags |= IEEE80211_KEY_FLAG_RX_MGMT; | ||
192 | break; | ||
193 | #endif | ||
194 | case NL80211_IFTYPE_WDS: | ||
195 | case NL80211_IFTYPE_MONITOR: | ||
196 | case NL80211_IFTYPE_P2P_DEVICE: | ||
197 | case NL80211_IFTYPE_UNSPECIFIED: | ||
198 | case NUM_NL80211_IFTYPES: | ||
199 | case NL80211_IFTYPE_P2P_CLIENT: | ||
200 | case NL80211_IFTYPE_P2P_GO: | ||
201 | /* shouldn't happen */ | ||
202 | WARN_ON_ONCE(1); | ||
203 | break; | ||
204 | } | ||
205 | |||
161 | err = ieee80211_key_link(key, sdata, sta); | 206 | err = ieee80211_key_link(key, sdata, sta); |
162 | if (err) | 207 | if (err) |
163 | ieee80211_key_free(sdata->local, key); | 208 | ieee80211_key_free(sdata->local, key); |
@@ -330,7 +375,7 @@ static void rate_idx_to_bitrate(struct rate_info *rate, struct sta_info *sta, in | |||
330 | if (!(rate->flags & RATE_INFO_FLAGS_MCS)) { | 375 | if (!(rate->flags & RATE_INFO_FLAGS_MCS)) { |
331 | struct ieee80211_supported_band *sband; | 376 | struct ieee80211_supported_band *sband; |
332 | sband = sta->local->hw.wiphy->bands[ | 377 | sband = sta->local->hw.wiphy->bands[ |
333 | sta->local->hw.conf.channel->band]; | 378 | sta->local->oper_channel->band]; |
334 | rate->legacy = sband->bitrates[idx].bitrate; | 379 | rate->legacy = sband->bitrates[idx].bitrate; |
335 | } else | 380 | } else |
336 | rate->mcs = idx; | 381 | rate->mcs = idx; |
@@ -725,25 +770,23 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy, | |||
725 | static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, | 770 | static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, |
726 | const u8 *resp, size_t resp_len) | 771 | const u8 *resp, size_t resp_len) |
727 | { | 772 | { |
728 | struct sk_buff *new, *old; | 773 | struct probe_resp *new, *old; |
729 | 774 | ||
730 | if (!resp || !resp_len) | 775 | if (!resp || !resp_len) |
731 | return 1; | 776 | return 1; |
732 | 777 | ||
733 | old = rtnl_dereference(sdata->u.ap.probe_resp); | 778 | old = rtnl_dereference(sdata->u.ap.probe_resp); |
734 | 779 | ||
735 | new = dev_alloc_skb(resp_len); | 780 | new = kzalloc(sizeof(struct probe_resp) + resp_len, GFP_KERNEL); |
736 | if (!new) | 781 | if (!new) |
737 | return -ENOMEM; | 782 | return -ENOMEM; |
738 | 783 | ||
739 | memcpy(skb_put(new, resp_len), resp, resp_len); | 784 | new->len = resp_len; |
785 | memcpy(new->data, resp, resp_len); | ||
740 | 786 | ||
741 | rcu_assign_pointer(sdata->u.ap.probe_resp, new); | 787 | rcu_assign_pointer(sdata->u.ap.probe_resp, new); |
742 | if (old) { | 788 | if (old) |
743 | /* TODO: use call_rcu() */ | 789 | kfree_rcu(old, rcu_head); |
744 | synchronize_rcu(); | ||
745 | dev_kfree_skb(old); | ||
746 | } | ||
747 | 790 | ||
748 | return 0; | 791 | return 0; |
749 | } | 792 | } |
@@ -950,7 +993,7 @@ static void ieee80211_send_layer2_update(struct sta_info *sta) | |||
950 | /* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID) | 993 | /* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID) |
951 | * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */ | 994 | * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */ |
952 | 995 | ||
953 | memset(msg->da, 0xff, ETH_ALEN); | 996 | eth_broadcast_addr(msg->da); |
954 | memcpy(msg->sa, sta->sta.addr, ETH_ALEN); | 997 | memcpy(msg->sa, sta->sta.addr, ETH_ALEN); |
955 | msg->len = htons(6); | 998 | msg->len = htons(6); |
956 | msg->dsap = 0; | 999 | msg->dsap = 0; |
@@ -1285,9 +1328,10 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
1285 | mutex_unlock(&local->sta_mtx); | 1328 | mutex_unlock(&local->sta_mtx); |
1286 | 1329 | ||
1287 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | 1330 | if (sdata->vif.type == NL80211_IFTYPE_STATION && |
1288 | params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) | 1331 | params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) { |
1289 | ieee80211_recalc_ps(local, -1); | 1332 | ieee80211_recalc_ps(local, -1); |
1290 | 1333 | ieee80211_recalc_ps_vif(sdata); | |
1334 | } | ||
1291 | return 0; | 1335 | return 0; |
1292 | } | 1336 | } |
1293 | 1337 | ||
@@ -1378,6 +1422,8 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop, | |||
1378 | else | 1422 | else |
1379 | memset(next_hop, 0, ETH_ALEN); | 1423 | memset(next_hop, 0, ETH_ALEN); |
1380 | 1424 | ||
1425 | memset(pinfo, 0, sizeof(*pinfo)); | ||
1426 | |||
1381 | pinfo->generation = mesh_paths_generation; | 1427 | pinfo->generation = mesh_paths_generation; |
1382 | 1428 | ||
1383 | pinfo->filled = MPATH_INFO_FRAME_QLEN | | 1429 | pinfo->filled = MPATH_INFO_FRAME_QLEN | |
@@ -1396,7 +1442,6 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop, | |||
1396 | pinfo->discovery_timeout = | 1442 | pinfo->discovery_timeout = |
1397 | jiffies_to_msecs(mpath->discovery_timeout); | 1443 | jiffies_to_msecs(mpath->discovery_timeout); |
1398 | pinfo->discovery_retries = mpath->discovery_retries; | 1444 | pinfo->discovery_retries = mpath->discovery_retries; |
1399 | pinfo->flags = 0; | ||
1400 | if (mpath->flags & MESH_PATH_ACTIVE) | 1445 | if (mpath->flags & MESH_PATH_ACTIVE) |
1401 | pinfo->flags |= NL80211_MPATH_FLAG_ACTIVE; | 1446 | pinfo->flags |= NL80211_MPATH_FLAG_ACTIVE; |
1402 | if (mpath->flags & MESH_PATH_RESOLVING) | 1447 | if (mpath->flags & MESH_PATH_RESOLVING) |
@@ -1405,10 +1450,8 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop, | |||
1405 | pinfo->flags |= NL80211_MPATH_FLAG_SN_VALID; | 1450 | pinfo->flags |= NL80211_MPATH_FLAG_SN_VALID; |
1406 | if (mpath->flags & MESH_PATH_FIXED) | 1451 | if (mpath->flags & MESH_PATH_FIXED) |
1407 | pinfo->flags |= NL80211_MPATH_FLAG_FIXED; | 1452 | pinfo->flags |= NL80211_MPATH_FLAG_FIXED; |
1408 | if (mpath->flags & MESH_PATH_RESOLVING) | 1453 | if (mpath->flags & MESH_PATH_RESOLVED) |
1409 | pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING; | 1454 | pinfo->flags |= NL80211_MPATH_FLAG_RESOLVED; |
1410 | |||
1411 | pinfo->flags = mpath->flags; | ||
1412 | } | 1455 | } |
1413 | 1456 | ||
1414 | static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev, | 1457 | static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev, |
@@ -1661,7 +1704,7 @@ static int ieee80211_change_bss(struct wiphy *wiphy, | |||
1661 | } | 1704 | } |
1662 | 1705 | ||
1663 | if (!sdata->vif.bss_conf.use_short_slot && | 1706 | if (!sdata->vif.bss_conf.use_short_slot && |
1664 | sdata->local->hw.conf.channel->band == IEEE80211_BAND_5GHZ) { | 1707 | sdata->local->oper_channel->band == IEEE80211_BAND_5GHZ) { |
1665 | sdata->vif.bss_conf.use_short_slot = true; | 1708 | sdata->vif.bss_conf.use_short_slot = true; |
1666 | changed |= BSS_CHANGED_ERP_SLOT; | 1709 | changed |= BSS_CHANGED_ERP_SLOT; |
1667 | } | 1710 | } |
@@ -1775,6 +1818,7 @@ static int ieee80211_scan(struct wiphy *wiphy, | |||
1775 | case NL80211_IFTYPE_ADHOC: | 1818 | case NL80211_IFTYPE_ADHOC: |
1776 | case NL80211_IFTYPE_MESH_POINT: | 1819 | case NL80211_IFTYPE_MESH_POINT: |
1777 | case NL80211_IFTYPE_P2P_CLIENT: | 1820 | case NL80211_IFTYPE_P2P_CLIENT: |
1821 | case NL80211_IFTYPE_P2P_DEVICE: | ||
1778 | break; | 1822 | break; |
1779 | case NL80211_IFTYPE_P2P_GO: | 1823 | case NL80211_IFTYPE_P2P_GO: |
1780 | if (sdata->local->ops->hw_scan) | 1824 | if (sdata->local->ops->hw_scan) |
@@ -1927,7 +1971,7 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy, | |||
1927 | enum nl80211_tx_power_setting type, int mbm) | 1971 | enum nl80211_tx_power_setting type, int mbm) |
1928 | { | 1972 | { |
1929 | struct ieee80211_local *local = wiphy_priv(wiphy); | 1973 | struct ieee80211_local *local = wiphy_priv(wiphy); |
1930 | struct ieee80211_channel *chan = local->hw.conf.channel; | 1974 | struct ieee80211_channel *chan = local->oper_channel; |
1931 | u32 changes = 0; | 1975 | u32 changes = 0; |
1932 | 1976 | ||
1933 | switch (type) { | 1977 | switch (type) { |
@@ -2027,9 +2071,7 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, | |||
2027 | */ | 2071 | */ |
2028 | if (!sdata->u.mgd.associated || | 2072 | if (!sdata->u.mgd.associated || |
2029 | sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) { | 2073 | sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) { |
2030 | mutex_lock(&sdata->local->iflist_mtx); | ||
2031 | ieee80211_recalc_smps(sdata->local); | 2074 | ieee80211_recalc_smps(sdata->local); |
2032 | mutex_unlock(&sdata->local->iflist_mtx); | ||
2033 | return 0; | 2075 | return 0; |
2034 | } | 2076 | } |
2035 | 2077 | ||
@@ -2079,6 +2121,7 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, | |||
2079 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | 2121 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); |
2080 | 2122 | ||
2081 | ieee80211_recalc_ps(local, -1); | 2123 | ieee80211_recalc_ps(local, -1); |
2124 | ieee80211_recalc_ps_vif(sdata); | ||
2082 | 2125 | ||
2083 | return 0; | 2126 | return 0; |
2084 | } | 2127 | } |
@@ -2461,6 +2504,9 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
2461 | if (!sdata->u.mgd.associated) | 2504 | if (!sdata->u.mgd.associated) |
2462 | need_offchan = true; | 2505 | need_offchan = true; |
2463 | break; | 2506 | break; |
2507 | case NL80211_IFTYPE_P2P_DEVICE: | ||
2508 | need_offchan = true; | ||
2509 | break; | ||
2464 | default: | 2510 | default: |
2465 | return -EOPNOTSUPP; | 2511 | return -EOPNOTSUPP; |
2466 | } | 2512 | } |
@@ -2653,6 +2699,7 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, | |||
2653 | u16 status_code, struct sk_buff *skb) | 2699 | u16 status_code, struct sk_buff *skb) |
2654 | { | 2700 | { |
2655 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2701 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
2702 | struct ieee80211_local *local = sdata->local; | ||
2656 | struct ieee80211_tdls_data *tf; | 2703 | struct ieee80211_tdls_data *tf; |
2657 | 2704 | ||
2658 | tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u)); | 2705 | tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u)); |
@@ -2672,8 +2719,10 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, | |||
2672 | tf->u.setup_req.capability = | 2719 | tf->u.setup_req.capability = |
2673 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | 2720 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); |
2674 | 2721 | ||
2675 | ieee80211_add_srates_ie(sdata, skb, false); | 2722 | ieee80211_add_srates_ie(sdata, skb, false, |
2676 | ieee80211_add_ext_srates_ie(sdata, skb, false); | 2723 | local->oper_channel->band); |
2724 | ieee80211_add_ext_srates_ie(sdata, skb, false, | ||
2725 | local->oper_channel->band); | ||
2677 | ieee80211_tdls_add_ext_capab(skb); | 2726 | ieee80211_tdls_add_ext_capab(skb); |
2678 | break; | 2727 | break; |
2679 | case WLAN_TDLS_SETUP_RESPONSE: | 2728 | case WLAN_TDLS_SETUP_RESPONSE: |
@@ -2686,8 +2735,10 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, | |||
2686 | tf->u.setup_resp.capability = | 2735 | tf->u.setup_resp.capability = |
2687 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | 2736 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); |
2688 | 2737 | ||
2689 | ieee80211_add_srates_ie(sdata, skb, false); | 2738 | ieee80211_add_srates_ie(sdata, skb, false, |
2690 | ieee80211_add_ext_srates_ie(sdata, skb, false); | 2739 | local->oper_channel->band); |
2740 | ieee80211_add_ext_srates_ie(sdata, skb, false, | ||
2741 | local->oper_channel->band); | ||
2691 | ieee80211_tdls_add_ext_capab(skb); | 2742 | ieee80211_tdls_add_ext_capab(skb); |
2692 | break; | 2743 | break; |
2693 | case WLAN_TDLS_SETUP_CONFIRM: | 2744 | case WLAN_TDLS_SETUP_CONFIRM: |
@@ -2725,6 +2776,7 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, | |||
2725 | u16 status_code, struct sk_buff *skb) | 2776 | u16 status_code, struct sk_buff *skb) |
2726 | { | 2777 | { |
2727 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2778 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
2779 | struct ieee80211_local *local = sdata->local; | ||
2728 | struct ieee80211_mgmt *mgmt; | 2780 | struct ieee80211_mgmt *mgmt; |
2729 | 2781 | ||
2730 | mgmt = (void *)skb_put(skb, 24); | 2782 | mgmt = (void *)skb_put(skb, 24); |
@@ -2747,8 +2799,10 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, | |||
2747 | mgmt->u.action.u.tdls_discover_resp.capability = | 2799 | mgmt->u.action.u.tdls_discover_resp.capability = |
2748 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | 2800 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); |
2749 | 2801 | ||
2750 | ieee80211_add_srates_ie(sdata, skb, false); | 2802 | ieee80211_add_srates_ie(sdata, skb, false, |
2751 | ieee80211_add_ext_srates_ie(sdata, skb, false); | 2803 | local->oper_channel->band); |
2804 | ieee80211_add_ext_srates_ie(sdata, skb, false, | ||
2805 | local->oper_channel->band); | ||
2752 | ieee80211_tdls_add_ext_capab(skb); | 2806 | ieee80211_tdls_add_ext_capab(skb); |
2753 | break; | 2807 | break; |
2754 | default: | 2808 | default: |
@@ -3005,6 +3059,8 @@ struct cfg80211_ops mac80211_config_ops = { | |||
3005 | .add_virtual_intf = ieee80211_add_iface, | 3059 | .add_virtual_intf = ieee80211_add_iface, |
3006 | .del_virtual_intf = ieee80211_del_iface, | 3060 | .del_virtual_intf = ieee80211_del_iface, |
3007 | .change_virtual_intf = ieee80211_change_iface, | 3061 | .change_virtual_intf = ieee80211_change_iface, |
3062 | .start_p2p_device = ieee80211_start_p2p_device, | ||
3063 | .stop_p2p_device = ieee80211_stop_p2p_device, | ||
3008 | .add_key = ieee80211_add_key, | 3064 | .add_key = ieee80211_add_key, |
3009 | .del_key = ieee80211_del_key, | 3065 | .del_key = ieee80211_del_key, |
3010 | .get_key = ieee80211_get_key, | 3066 | .get_key = ieee80211_get_key, |