diff options
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r-- | net/mac80211/cfg.c | 103 |
1 files changed, 80 insertions, 23 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index a58c0b649ba1..05f3a313db88 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 | ||
@@ -1660,7 +1704,7 @@ static int ieee80211_change_bss(struct wiphy *wiphy, | |||
1660 | } | 1704 | } |
1661 | 1705 | ||
1662 | if (!sdata->vif.bss_conf.use_short_slot && | 1706 | if (!sdata->vif.bss_conf.use_short_slot && |
1663 | sdata->local->hw.conf.channel->band == IEEE80211_BAND_5GHZ) { | 1707 | sdata->local->oper_channel->band == IEEE80211_BAND_5GHZ) { |
1664 | sdata->vif.bss_conf.use_short_slot = true; | 1708 | sdata->vif.bss_conf.use_short_slot = true; |
1665 | changed |= BSS_CHANGED_ERP_SLOT; | 1709 | changed |= BSS_CHANGED_ERP_SLOT; |
1666 | } | 1710 | } |
@@ -1774,6 +1818,7 @@ static int ieee80211_scan(struct wiphy *wiphy, | |||
1774 | case NL80211_IFTYPE_ADHOC: | 1818 | case NL80211_IFTYPE_ADHOC: |
1775 | case NL80211_IFTYPE_MESH_POINT: | 1819 | case NL80211_IFTYPE_MESH_POINT: |
1776 | case NL80211_IFTYPE_P2P_CLIENT: | 1820 | case NL80211_IFTYPE_P2P_CLIENT: |
1821 | case NL80211_IFTYPE_P2P_DEVICE: | ||
1777 | break; | 1822 | break; |
1778 | case NL80211_IFTYPE_P2P_GO: | 1823 | case NL80211_IFTYPE_P2P_GO: |
1779 | if (sdata->local->ops->hw_scan) | 1824 | if (sdata->local->ops->hw_scan) |
@@ -1926,7 +1971,7 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy, | |||
1926 | enum nl80211_tx_power_setting type, int mbm) | 1971 | enum nl80211_tx_power_setting type, int mbm) |
1927 | { | 1972 | { |
1928 | struct ieee80211_local *local = wiphy_priv(wiphy); | 1973 | struct ieee80211_local *local = wiphy_priv(wiphy); |
1929 | struct ieee80211_channel *chan = local->hw.conf.channel; | 1974 | struct ieee80211_channel *chan = local->oper_channel; |
1930 | u32 changes = 0; | 1975 | u32 changes = 0; |
1931 | 1976 | ||
1932 | switch (type) { | 1977 | switch (type) { |
@@ -2026,9 +2071,7 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, | |||
2026 | */ | 2071 | */ |
2027 | if (!sdata->u.mgd.associated || | 2072 | if (!sdata->u.mgd.associated || |
2028 | sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) { | 2073 | sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) { |
2029 | mutex_lock(&sdata->local->iflist_mtx); | ||
2030 | ieee80211_recalc_smps(sdata->local); | 2074 | ieee80211_recalc_smps(sdata->local); |
2031 | mutex_unlock(&sdata->local->iflist_mtx); | ||
2032 | return 0; | 2075 | return 0; |
2033 | } | 2076 | } |
2034 | 2077 | ||
@@ -2078,6 +2121,7 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, | |||
2078 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | 2121 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); |
2079 | 2122 | ||
2080 | ieee80211_recalc_ps(local, -1); | 2123 | ieee80211_recalc_ps(local, -1); |
2124 | ieee80211_recalc_ps_vif(sdata); | ||
2081 | 2125 | ||
2082 | return 0; | 2126 | return 0; |
2083 | } | 2127 | } |
@@ -2460,6 +2504,9 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
2460 | if (!sdata->u.mgd.associated) | 2504 | if (!sdata->u.mgd.associated) |
2461 | need_offchan = true; | 2505 | need_offchan = true; |
2462 | break; | 2506 | break; |
2507 | case NL80211_IFTYPE_P2P_DEVICE: | ||
2508 | need_offchan = true; | ||
2509 | break; | ||
2463 | default: | 2510 | default: |
2464 | return -EOPNOTSUPP; | 2511 | return -EOPNOTSUPP; |
2465 | } | 2512 | } |
@@ -2652,6 +2699,7 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, | |||
2652 | u16 status_code, struct sk_buff *skb) | 2699 | u16 status_code, struct sk_buff *skb) |
2653 | { | 2700 | { |
2654 | 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; | ||
2655 | struct ieee80211_tdls_data *tf; | 2703 | struct ieee80211_tdls_data *tf; |
2656 | 2704 | ||
2657 | tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u)); | 2705 | tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u)); |
@@ -2671,8 +2719,10 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, | |||
2671 | tf->u.setup_req.capability = | 2719 | tf->u.setup_req.capability = |
2672 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | 2720 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); |
2673 | 2721 | ||
2674 | ieee80211_add_srates_ie(sdata, skb, false); | 2722 | ieee80211_add_srates_ie(sdata, skb, false, |
2675 | 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); | ||
2676 | ieee80211_tdls_add_ext_capab(skb); | 2726 | ieee80211_tdls_add_ext_capab(skb); |
2677 | break; | 2727 | break; |
2678 | case WLAN_TDLS_SETUP_RESPONSE: | 2728 | case WLAN_TDLS_SETUP_RESPONSE: |
@@ -2685,8 +2735,10 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, | |||
2685 | tf->u.setup_resp.capability = | 2735 | tf->u.setup_resp.capability = |
2686 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | 2736 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); |
2687 | 2737 | ||
2688 | ieee80211_add_srates_ie(sdata, skb, false); | 2738 | ieee80211_add_srates_ie(sdata, skb, false, |
2689 | 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); | ||
2690 | ieee80211_tdls_add_ext_capab(skb); | 2742 | ieee80211_tdls_add_ext_capab(skb); |
2691 | break; | 2743 | break; |
2692 | case WLAN_TDLS_SETUP_CONFIRM: | 2744 | case WLAN_TDLS_SETUP_CONFIRM: |
@@ -2724,6 +2776,7 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, | |||
2724 | u16 status_code, struct sk_buff *skb) | 2776 | u16 status_code, struct sk_buff *skb) |
2725 | { | 2777 | { |
2726 | 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; | ||
2727 | struct ieee80211_mgmt *mgmt; | 2780 | struct ieee80211_mgmt *mgmt; |
2728 | 2781 | ||
2729 | mgmt = (void *)skb_put(skb, 24); | 2782 | mgmt = (void *)skb_put(skb, 24); |
@@ -2746,8 +2799,10 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, | |||
2746 | mgmt->u.action.u.tdls_discover_resp.capability = | 2799 | mgmt->u.action.u.tdls_discover_resp.capability = |
2747 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | 2800 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); |
2748 | 2801 | ||
2749 | ieee80211_add_srates_ie(sdata, skb, false); | 2802 | ieee80211_add_srates_ie(sdata, skb, false, |
2750 | 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); | ||
2751 | ieee80211_tdls_add_ext_capab(skb); | 2806 | ieee80211_tdls_add_ext_capab(skb); |
2752 | break; | 2807 | break; |
2753 | default: | 2808 | default: |
@@ -3004,6 +3059,8 @@ struct cfg80211_ops mac80211_config_ops = { | |||
3004 | .add_virtual_intf = ieee80211_add_iface, | 3059 | .add_virtual_intf = ieee80211_add_iface, |
3005 | .del_virtual_intf = ieee80211_del_iface, | 3060 | .del_virtual_intf = ieee80211_del_iface, |
3006 | .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, | ||
3007 | .add_key = ieee80211_add_key, | 3064 | .add_key = ieee80211_add_key, |
3008 | .del_key = ieee80211_del_key, | 3065 | .del_key = ieee80211_del_key, |
3009 | .get_key = ieee80211_get_key, | 3066 | .get_key = ieee80211_get_key, |