aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/cfg.c13
-rw-r--r--net/mac80211/ieee80211_i.h1
-rw-r--r--net/mac80211/iface.c10
-rw-r--r--net/mac80211/main.c30
-rw-r--r--net/mac80211/mlme.c20
-rw-r--r--net/mac80211/rx.c35
-rw-r--r--net/mac80211/tx.c11
-rw-r--r--net/mac80211/util.c1
-rw-r--r--net/mac80211/wext.c120
-rw-r--r--net/wireless/Makefile1
-rw-r--r--net/wireless/nl80211.c57
-rw-r--r--net/wireless/reg.c5
-rw-r--r--net/wireless/wext-compat.c139
13 files changed, 299 insertions, 144 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 16423f94801b..7a7a6c176dc5 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1095,6 +1095,18 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy,
1095 return 0; 1095 return 0;
1096} 1096}
1097 1097
1098static int ieee80211_set_channel(struct wiphy *wiphy,
1099 struct ieee80211_channel *chan,
1100 enum nl80211_sec_chan_offset sec_chan_offset)
1101{
1102 struct ieee80211_local *local = wiphy_priv(wiphy);
1103
1104 local->oper_channel = chan;
1105 local->oper_sec_chan_offset = sec_chan_offset;
1106
1107 return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
1108}
1109
1098struct cfg80211_ops mac80211_config_ops = { 1110struct cfg80211_ops mac80211_config_ops = {
1099 .add_virtual_intf = ieee80211_add_iface, 1111 .add_virtual_intf = ieee80211_add_iface,
1100 .del_virtual_intf = ieee80211_del_iface, 1112 .del_virtual_intf = ieee80211_del_iface,
@@ -1122,4 +1134,5 @@ struct cfg80211_ops mac80211_config_ops = {
1122#endif 1134#endif
1123 .change_bss = ieee80211_change_bss, 1135 .change_bss = ieee80211_change_bss,
1124 .set_txq_params = ieee80211_set_txq_params, 1136 .set_txq_params = ieee80211_set_txq_params,
1137 .set_channel = ieee80211_set_channel,
1125}; 1138};
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 155a20410017..527205f8c1a1 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -626,6 +626,7 @@ struct ieee80211_local {
626 struct delayed_work scan_work; 626 struct delayed_work scan_work;
627 struct ieee80211_sub_if_data *scan_sdata; 627 struct ieee80211_sub_if_data *scan_sdata;
628 struct ieee80211_channel *oper_channel, *scan_channel; 628 struct ieee80211_channel *oper_channel, *scan_channel;
629 enum nl80211_sec_chan_offset oper_sec_chan_offset;
629 u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; 630 u8 scan_ssid[IEEE80211_MAX_SSID_LEN];
630 size_t scan_ssid_len; 631 size_t scan_ssid_len;
631 struct list_head bss_list; 632 struct list_head bss_list;
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 46082125f3e1..5abbc3f07dd6 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -435,7 +435,11 @@ static int ieee80211_stop(struct net_device *dev)
435 break; 435 break;
436 case NL80211_IFTYPE_STATION: 436 case NL80211_IFTYPE_STATION:
437 case NL80211_IFTYPE_ADHOC: 437 case NL80211_IFTYPE_ADHOC:
438 sdata->u.sta.state = IEEE80211_STA_MLME_DISABLED; 438 /* Announce that we are leaving the network. */
439 if (sdata->u.sta.state != IEEE80211_STA_MLME_DISABLED)
440 ieee80211_sta_deauthenticate(sdata,
441 WLAN_REASON_DEAUTH_LEAVING);
442
439 memset(sdata->u.sta.bssid, 0, ETH_ALEN); 443 memset(sdata->u.sta.bssid, 0, ETH_ALEN);
440 del_timer_sync(&sdata->u.sta.timer); 444 del_timer_sync(&sdata->u.sta.timer);
441 /* 445 /*
@@ -694,6 +698,10 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
694 if (type == sdata->vif.type) 698 if (type == sdata->vif.type)
695 return 0; 699 return 0;
696 700
701 /* Setting ad-hoc mode on non-IBSS channel is not supported. */
702 if (sdata->local->oper_channel->flags & IEEE80211_CHAN_NO_IBSS)
703 return -EOPNOTSUPP;
704
697 /* 705 /*
698 * We could, here, on changes between IBSS/STA/MESH modes, 706 * We could, here, on changes between IBSS/STA/MESH modes,
699 * invoke an MLME function instead that disassociates etc. 707 * invoke an MLME function instead that disassociates etc.
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index cec9b6d3e1ce..29c3ecf7e914 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -195,20 +195,42 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
195 struct ieee80211_channel *chan; 195 struct ieee80211_channel *chan;
196 int ret = 0; 196 int ret = 0;
197 int power; 197 int power;
198 enum nl80211_sec_chan_offset sec_chan_offset;
198 199
199 might_sleep(); 200 might_sleep();
200 201
201 if (local->sw_scanning) 202 if (local->sw_scanning) {
202 chan = local->scan_channel; 203 chan = local->scan_channel;
203 else 204 sec_chan_offset = NL80211_SEC_CHAN_NO_HT;
205 } else {
204 chan = local->oper_channel; 206 chan = local->oper_channel;
207 sec_chan_offset = local->oper_sec_chan_offset;
208 }
205 209
206 if (chan != local->hw.conf.channel) { 210 if (chan != local->hw.conf.channel ||
211 sec_chan_offset != local->hw.conf.ht.sec_chan_offset) {
207 local->hw.conf.channel = chan; 212 local->hw.conf.channel = chan;
213 switch (sec_chan_offset) {
214 case NL80211_SEC_CHAN_NO_HT:
215 local->hw.conf.ht.enabled = false;
216 local->hw.conf.ht.sec_chan_offset = 0;
217 break;
218 case NL80211_SEC_CHAN_DISABLED:
219 local->hw.conf.ht.enabled = true;
220 local->hw.conf.ht.sec_chan_offset = 0;
221 break;
222 case NL80211_SEC_CHAN_BELOW:
223 local->hw.conf.ht.enabled = true;
224 local->hw.conf.ht.sec_chan_offset = -1;
225 break;
226 case NL80211_SEC_CHAN_ABOVE:
227 local->hw.conf.ht.enabled = true;
228 local->hw.conf.ht.sec_chan_offset = 1;
229 break;
230 }
208 changed |= IEEE80211_CONF_CHANGE_CHANNEL; 231 changed |= IEEE80211_CONF_CHANGE_CHANNEL;
209 } 232 }
210 233
211
212 if (!local->hw.conf.power_level) 234 if (!local->hw.conf.power_level)
213 power = chan->max_power; 235 power = chan->max_power;
214 else 236 else
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 7600ac9b87fe..87b2ac85d911 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -855,16 +855,26 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
855 if (self_disconnected || reason == WLAN_REASON_DISASSOC_STA_HAS_LEFT) 855 if (self_disconnected || reason == WLAN_REASON_DISASSOC_STA_HAS_LEFT)
856 ifsta->state = IEEE80211_STA_MLME_DISABLED; 856 ifsta->state = IEEE80211_STA_MLME_DISABLED;
857 857
858 sta_info_unlink(&sta);
859
860 rcu_read_unlock(); 858 rcu_read_unlock();
861 859
862 sta_info_destroy(sta);
863
864 local->hw.conf.ht.enabled = false; 860 local->hw.conf.ht.enabled = false;
865 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_HT); 861 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_HT);
866 862
867 ieee80211_bss_info_change_notify(sdata, changed); 863 ieee80211_bss_info_change_notify(sdata, changed);
864
865 rcu_read_lock();
866
867 sta = sta_info_get(local, ifsta->bssid);
868 if (!sta) {
869 rcu_read_unlock();
870 return;
871 }
872
873 sta_info_unlink(&sta);
874
875 rcu_read_unlock();
876
877 sta_info_destroy(sta);
868} 878}
869 879
870static int ieee80211_sta_wep_configured(struct ieee80211_sub_if_data *sdata) 880static int ieee80211_sta_wep_configured(struct ieee80211_sub_if_data *sdata)
@@ -2002,7 +2012,7 @@ static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta,
2002 } 2012 }
2003 } 2013 }
2004 2014
2005 if (hidden_ssid && ifsta->ssid_len == ssid_len) 2015 if (hidden_ssid && (ifsta->ssid_len == ssid_len || ssid_len == 0))
2006 return 1; 2016 return 1;
2007 2017
2008 if (ssid_len == 1 && ssid[0] == ' ') 2018 if (ssid_len == 1 && ssid[0] == ' ')
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 648a1d0e6c82..14be095b8528 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -654,9 +654,13 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
654static void ap_sta_ps_start(struct sta_info *sta) 654static void ap_sta_ps_start(struct sta_info *sta)
655{ 655{
656 struct ieee80211_sub_if_data *sdata = sta->sdata; 656 struct ieee80211_sub_if_data *sdata = sta->sdata;
657 struct ieee80211_local *local = sdata->local;
657 658
658 atomic_inc(&sdata->bss->num_sta_ps); 659 atomic_inc(&sdata->bss->num_sta_ps);
659 set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); 660 set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL);
661 if (local->ops->sta_notify_ps)
662 local->ops->sta_notify_ps(local_to_hw(local), STA_NOTIFY_SLEEP,
663 &sta->sta);
660#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG 664#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
661 printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n", 665 printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n",
662 sdata->dev->name, sta->sta.addr, sta->sta.aid); 666 sdata->dev->name, sta->sta.addr, sta->sta.aid);
@@ -673,6 +677,9 @@ static int ap_sta_ps_end(struct sta_info *sta)
673 atomic_dec(&sdata->bss->num_sta_ps); 677 atomic_dec(&sdata->bss->num_sta_ps);
674 678
675 clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL); 679 clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL);
680 if (local->ops->sta_notify_ps)
681 local->ops->sta_notify_ps(local_to_hw(local), STA_NOTIFY_AWAKE,
682 &sta->sta);
676 683
677 if (!skb_queue_empty(&sta->ps_tx_buf)) 684 if (!skb_queue_empty(&sta->ps_tx_buf))
678 sta_info_clear_tim_bit(sta); 685 sta_info_clear_tim_bit(sta);
@@ -741,17 +748,29 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
741 sta->last_qual = rx->status->qual; 748 sta->last_qual = rx->status->qual;
742 sta->last_noise = rx->status->noise; 749 sta->last_noise = rx->status->noise;
743 750
751 /*
752 * Change STA power saving mode only at the end of a frame
753 * exchange sequence.
754 */
744 if (!ieee80211_has_morefrags(hdr->frame_control) && 755 if (!ieee80211_has_morefrags(hdr->frame_control) &&
745 (rx->sdata->vif.type == NL80211_IFTYPE_AP || 756 (rx->sdata->vif.type == NL80211_IFTYPE_AP ||
746 rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) { 757 rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) {
747 /* Change STA power saving mode only in the end of a frame 758 if (test_sta_flags(sta, WLAN_STA_PS)) {
748 * exchange sequence */ 759 /*
749 if (test_sta_flags(sta, WLAN_STA_PS) && 760 * Ignore doze->wake transitions that are
750 !ieee80211_has_pm(hdr->frame_control)) 761 * indicated by non-data frames, the standard
751 rx->sent_ps_buffered += ap_sta_ps_end(sta); 762 * is unclear here, but for example going to
752 else if (!test_sta_flags(sta, WLAN_STA_PS) && 763 * PS mode and then scanning would cause a
753 ieee80211_has_pm(hdr->frame_control)) 764 * doze->wake transition for the probe request,
754 ap_sta_ps_start(sta); 765 * and that is clearly undesirable.
766 */
767 if (ieee80211_is_data(hdr->frame_control) &&
768 !ieee80211_has_pm(hdr->frame_control))
769 rx->sent_ps_buffered += ap_sta_ps_end(sta);
770 } else {
771 if (ieee80211_has_pm(hdr->frame_control))
772 ap_sta_ps_start(sta);
773 }
755 } 774 }
756 775
757 /* Drop data::nullfunc frames silently, since they are used only to 776 /* Drop data::nullfunc frames silently, since they are used only to
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 0d81b2cfd1a6..d7761e95e4cf 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1779,8 +1779,7 @@ void ieee80211_tx_pending(unsigned long data)
1779 1779
1780/* functions for drivers to get certain frames */ 1780/* functions for drivers to get certain frames */
1781 1781
1782static void ieee80211_beacon_add_tim(struct ieee80211_local *local, 1782static void ieee80211_beacon_add_tim(struct ieee80211_if_ap *bss,
1783 struct ieee80211_if_ap *bss,
1784 struct sk_buff *skb, 1783 struct sk_buff *skb,
1785 struct beacon_data *beacon) 1784 struct beacon_data *beacon)
1786{ 1785{
@@ -1848,7 +1847,6 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
1848 struct ieee80211_local *local = hw_to_local(hw); 1847 struct ieee80211_local *local = hw_to_local(hw);
1849 struct sk_buff *skb = NULL; 1848 struct sk_buff *skb = NULL;
1850 struct ieee80211_tx_info *info; 1849 struct ieee80211_tx_info *info;
1851 struct net_device *bdev;
1852 struct ieee80211_sub_if_data *sdata = NULL; 1850 struct ieee80211_sub_if_data *sdata = NULL;
1853 struct ieee80211_if_ap *ap = NULL; 1851 struct ieee80211_if_ap *ap = NULL;
1854 struct ieee80211_if_sta *ifsta = NULL; 1852 struct ieee80211_if_sta *ifsta = NULL;
@@ -1861,7 +1859,6 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
1861 rcu_read_lock(); 1859 rcu_read_lock();
1862 1860
1863 sdata = vif_to_sdata(vif); 1861 sdata = vif_to_sdata(vif);
1864 bdev = sdata->dev;
1865 1862
1866 if (sdata->vif.type == NL80211_IFTYPE_AP) { 1863 if (sdata->vif.type == NL80211_IFTYPE_AP) {
1867 ap = &sdata->u.ap; 1864 ap = &sdata->u.ap;
@@ -1889,12 +1886,12 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
1889 * of the tim bitmap in mac80211 and the driver. 1886 * of the tim bitmap in mac80211 and the driver.
1890 */ 1887 */
1891 if (local->tim_in_locked_section) { 1888 if (local->tim_in_locked_section) {
1892 ieee80211_beacon_add_tim(local, ap, skb, beacon); 1889 ieee80211_beacon_add_tim(ap, skb, beacon);
1893 } else { 1890 } else {
1894 unsigned long flags; 1891 unsigned long flags;
1895 1892
1896 spin_lock_irqsave(&local->sta_lock, flags); 1893 spin_lock_irqsave(&local->sta_lock, flags);
1897 ieee80211_beacon_add_tim(local, ap, skb, beacon); 1894 ieee80211_beacon_add_tim(ap, skb, beacon);
1898 spin_unlock_irqrestore(&local->sta_lock, flags); 1895 spin_unlock_irqrestore(&local->sta_lock, flags);
1899 } 1896 }
1900 1897
@@ -2016,14 +2013,12 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
2016 struct sk_buff *skb = NULL; 2013 struct sk_buff *skb = NULL;
2017 struct sta_info *sta; 2014 struct sta_info *sta;
2018 struct ieee80211_tx_data tx; 2015 struct ieee80211_tx_data tx;
2019 struct net_device *bdev;
2020 struct ieee80211_sub_if_data *sdata; 2016 struct ieee80211_sub_if_data *sdata;
2021 struct ieee80211_if_ap *bss = NULL; 2017 struct ieee80211_if_ap *bss = NULL;
2022 struct beacon_data *beacon; 2018 struct beacon_data *beacon;
2023 struct ieee80211_tx_info *info; 2019 struct ieee80211_tx_info *info;
2024 2020
2025 sdata = vif_to_sdata(vif); 2021 sdata = vif_to_sdata(vif);
2026 bdev = sdata->dev;
2027 bss = &sdata->u.ap; 2022 bss = &sdata->u.ap;
2028 2023
2029 if (!bss) 2024 if (!bss)
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 0f841317c7e9..505d68f344ce 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -641,6 +641,7 @@ int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freqMHz)
641 chan->flags & IEEE80211_CHAN_NO_IBSS) 641 chan->flags & IEEE80211_CHAN_NO_IBSS)
642 return ret; 642 return ret;
643 local->oper_channel = chan; 643 local->oper_channel = chan;
644 local->oper_sec_chan_offset = NL80211_SEC_CHAN_NO_HT;
644 645
645 if (local->sw_scanning || local->hw_scanning) 646 if (local->sw_scanning || local->hw_scanning)
646 ret = 0; 647 ret = 0;
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c
index b3ce28d35611..4e1fdcfacb0c 100644
--- a/net/mac80211/wext.c
+++ b/net/mac80211/wext.c
@@ -135,48 +135,6 @@ static int ieee80211_ioctl_siwgenie(struct net_device *dev,
135 return -EOPNOTSUPP; 135 return -EOPNOTSUPP;
136} 136}
137 137
138static int ieee80211_ioctl_giwname(struct net_device *dev,
139 struct iw_request_info *info,
140 char *name, char *extra)
141{
142 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
143 struct ieee80211_supported_band *sband;
144 u8 is_ht = 0, is_a = 0, is_b = 0, is_g = 0;
145
146
147 sband = local->hw.wiphy->bands[IEEE80211_BAND_5GHZ];
148 if (sband) {
149 is_a = 1;
150 is_ht |= sband->ht_cap.ht_supported;
151 }
152
153 sband = local->hw.wiphy->bands[IEEE80211_BAND_2GHZ];
154 if (sband) {
155 int i;
156 /* Check for mandatory rates */
157 for (i = 0; i < sband->n_bitrates; i++) {
158 if (sband->bitrates[i].bitrate == 10)
159 is_b = 1;
160 if (sband->bitrates[i].bitrate == 60)
161 is_g = 1;
162 }
163 is_ht |= sband->ht_cap.ht_supported;
164 }
165
166 strcpy(name, "IEEE 802.11");
167 if (is_a)
168 strcat(name, "a");
169 if (is_b)
170 strcat(name, "b");
171 if (is_g)
172 strcat(name, "g");
173 if (is_ht)
174 strcat(name, "n");
175
176 return 0;
177}
178
179
180static int ieee80211_ioctl_giwrange(struct net_device *dev, 138static int ieee80211_ioctl_giwrange(struct net_device *dev,
181 struct iw_request_info *info, 139 struct iw_request_info *info,
182 struct iw_point *data, char *extra) 140 struct iw_point *data, char *extra)
@@ -266,78 +224,6 @@ static int ieee80211_ioctl_giwrange(struct net_device *dev,
266} 224}
267 225
268 226
269static int ieee80211_ioctl_siwmode(struct net_device *dev,
270 struct iw_request_info *info,
271 __u32 *mode, char *extra)
272{
273 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
274 struct ieee80211_local *local = sdata->local;
275 int type;
276
277 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
278 return -EOPNOTSUPP;
279
280 switch (*mode) {
281 case IW_MODE_INFRA:
282 type = NL80211_IFTYPE_STATION;
283 break;
284 case IW_MODE_ADHOC:
285 /* Setting ad-hoc mode on non ibss channel is not
286 * supported.
287 */
288 if (local->oper_channel &&
289 (local->oper_channel->flags & IEEE80211_CHAN_NO_IBSS))
290 return -EOPNOTSUPP;
291
292 type = NL80211_IFTYPE_ADHOC;
293 break;
294 case IW_MODE_REPEAT:
295 type = NL80211_IFTYPE_WDS;
296 break;
297 case IW_MODE_MONITOR:
298 type = NL80211_IFTYPE_MONITOR;
299 break;
300 default:
301 return -EINVAL;
302 }
303
304 return ieee80211_if_change_type(sdata, type);
305}
306
307
308static int ieee80211_ioctl_giwmode(struct net_device *dev,
309 struct iw_request_info *info,
310 __u32 *mode, char *extra)
311{
312 struct ieee80211_sub_if_data *sdata;
313
314 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
315 switch (sdata->vif.type) {
316 case NL80211_IFTYPE_AP:
317 *mode = IW_MODE_MASTER;
318 break;
319 case NL80211_IFTYPE_STATION:
320 *mode = IW_MODE_INFRA;
321 break;
322 case NL80211_IFTYPE_ADHOC:
323 *mode = IW_MODE_ADHOC;
324 break;
325 case NL80211_IFTYPE_MONITOR:
326 *mode = IW_MODE_MONITOR;
327 break;
328 case NL80211_IFTYPE_WDS:
329 *mode = IW_MODE_REPEAT;
330 break;
331 case NL80211_IFTYPE_AP_VLAN:
332 *mode = IW_MODE_SECOND; /* FIXME */
333 break;
334 default:
335 *mode = IW_MODE_AUTO;
336 break;
337 }
338 return 0;
339}
340
341static int ieee80211_ioctl_siwfreq(struct net_device *dev, 227static int ieee80211_ioctl_siwfreq(struct net_device *dev,
342 struct iw_request_info *info, 228 struct iw_request_info *info,
343 struct iw_freq *freq, char *extra) 229 struct iw_freq *freq, char *extra)
@@ -1146,13 +1032,13 @@ static int ieee80211_ioctl_siwencodeext(struct net_device *dev,
1146static const iw_handler ieee80211_handler[] = 1032static const iw_handler ieee80211_handler[] =
1147{ 1033{
1148 (iw_handler) NULL, /* SIOCSIWCOMMIT */ 1034 (iw_handler) NULL, /* SIOCSIWCOMMIT */
1149 (iw_handler) ieee80211_ioctl_giwname, /* SIOCGIWNAME */ 1035 (iw_handler) cfg80211_wext_giwname, /* SIOCGIWNAME */
1150 (iw_handler) NULL, /* SIOCSIWNWID */ 1036 (iw_handler) NULL, /* SIOCSIWNWID */
1151 (iw_handler) NULL, /* SIOCGIWNWID */ 1037 (iw_handler) NULL, /* SIOCGIWNWID */
1152 (iw_handler) ieee80211_ioctl_siwfreq, /* SIOCSIWFREQ */ 1038 (iw_handler) ieee80211_ioctl_siwfreq, /* SIOCSIWFREQ */
1153 (iw_handler) ieee80211_ioctl_giwfreq, /* SIOCGIWFREQ */ 1039 (iw_handler) ieee80211_ioctl_giwfreq, /* SIOCGIWFREQ */
1154 (iw_handler) ieee80211_ioctl_siwmode, /* SIOCSIWMODE */ 1040 (iw_handler) cfg80211_wext_siwmode, /* SIOCSIWMODE */
1155 (iw_handler) ieee80211_ioctl_giwmode, /* SIOCGIWMODE */ 1041 (iw_handler) cfg80211_wext_giwmode, /* SIOCGIWMODE */
1156 (iw_handler) NULL, /* SIOCSIWSENS */ 1042 (iw_handler) NULL, /* SIOCSIWSENS */
1157 (iw_handler) NULL, /* SIOCGIWSENS */ 1043 (iw_handler) NULL, /* SIOCGIWSENS */
1158 (iw_handler) NULL /* not used */, /* SIOCSIWRANGE */ 1044 (iw_handler) NULL /* not used */, /* SIOCSIWRANGE */
diff --git a/net/wireless/Makefile b/net/wireless/Makefile
index cc547edb111f..9bc412c83430 100644
--- a/net/wireless/Makefile
+++ b/net/wireless/Makefile
@@ -6,4 +6,5 @@ obj-$(CONFIG_LIB80211_CRYPT_CCMP) += lib80211_crypt_ccmp.o
6obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o 6obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o
7 7
8cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o 8cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o
9cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o
9cfg80211-$(CONFIG_NL80211) += nl80211.o 10cfg80211-$(CONFIG_NL80211) += nl80211.o
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c9141e3df9ba..9caee6022e3f 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -59,6 +59,8 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
59 [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING, 59 [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
60 .len = BUS_ID_SIZE-1 }, 60 .len = BUS_ID_SIZE-1 },
61 [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED }, 61 [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED },
62 [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 },
63 [NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET] = { .type = NLA_U32 },
62 64
63 [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, 65 [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 },
64 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, 66 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
@@ -359,6 +361,61 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
359 } 361 }
360 } 362 }
361 363
364 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
365 enum nl80211_sec_chan_offset sec_chan_offset =
366 NL80211_SEC_CHAN_NO_HT;
367 struct ieee80211_channel *chan;
368 u32 freq, sec_freq;
369
370 if (!rdev->ops->set_channel) {
371 result = -EOPNOTSUPP;
372 goto bad_res;
373 }
374
375 if (info->attrs[NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET]) {
376 sec_chan_offset = nla_get_u32(
377 info->attrs[
378 NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET]);
379 if (sec_chan_offset != NL80211_SEC_CHAN_NO_HT &&
380 sec_chan_offset != NL80211_SEC_CHAN_DISABLED &&
381 sec_chan_offset != NL80211_SEC_CHAN_BELOW &&
382 sec_chan_offset != NL80211_SEC_CHAN_ABOVE) {
383 result = -EINVAL;
384 goto bad_res;
385 }
386 }
387
388 freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
389 chan = ieee80211_get_channel(&rdev->wiphy, freq);
390 if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) {
391 /* Primary channel not allowed */
392 result = -EINVAL;
393 goto bad_res;
394 }
395 if (sec_chan_offset == NL80211_SEC_CHAN_BELOW)
396 sec_freq = freq - 20;
397 else if (sec_chan_offset == NL80211_SEC_CHAN_ABOVE)
398 sec_freq = freq + 20;
399 else
400 sec_freq = 0;
401
402 if (sec_freq) {
403 struct ieee80211_channel *schan;
404 schan = ieee80211_get_channel(&rdev->wiphy, sec_freq);
405 if (!schan || schan->flags & IEEE80211_CHAN_DISABLED) {
406 /* Secondary channel not allowed */
407 result = -EINVAL;
408 goto bad_res;
409 }
410 }
411
412 result = rdev->ops->set_channel(&rdev->wiphy, chan,
413 sec_chan_offset);
414 if (result)
415 goto bad_res;
416 }
417
418
362bad_res: 419bad_res:
363 cfg80211_put_dev(rdev); 420 cfg80211_put_dev(rdev);
364 return result; 421 return result;
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 0990059f7e48..4f877535e666 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -989,6 +989,9 @@ void regulatory_hint_11d(struct wiphy *wiphy,
989 u32 checksum = 0; 989 u32 checksum = 0;
990 enum environment_cap env = ENVIRON_ANY; 990 enum environment_cap env = ENVIRON_ANY;
991 991
992 if (!last_request)
993 return;
994
992 mutex_lock(&cfg80211_drv_mutex); 995 mutex_lock(&cfg80211_drv_mutex);
993 996
994 /* IE len must be evenly divisible by 2 */ 997 /* IE len must be evenly divisible by 2 */
@@ -1330,7 +1333,7 @@ int set_regdom(const struct ieee80211_regdomain *rd)
1330/* Caller must hold cfg80211_drv_mutex */ 1333/* Caller must hold cfg80211_drv_mutex */
1331void reg_device_remove(struct wiphy *wiphy) 1334void reg_device_remove(struct wiphy *wiphy)
1332{ 1335{
1333 if (!last_request->wiphy) 1336 if (!last_request || !last_request->wiphy)
1334 return; 1337 return;
1335 if (last_request->wiphy != wiphy) 1338 if (last_request->wiphy != wiphy)
1336 return; 1339 return;
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
new file mode 100644
index 000000000000..58e489fd4aed
--- /dev/null
+++ b/net/wireless/wext-compat.c
@@ -0,0 +1,139 @@
1/*
2 * cfg80211 - wext compat code
3 *
4 * This is temporary code until all wireless functionality is migrated
5 * into cfg80211, when that happens all the exports here go away and
6 * we directly assign the wireless handlers of wireless interfaces.
7 *
8 * Copyright 2008 Johannes Berg <johannes@sipsolutions.net>
9 */
10
11#include <linux/wireless.h>
12#include <linux/nl80211.h>
13#include <net/iw_handler.h>
14#include <net/wireless.h>
15#include <net/cfg80211.h>
16#include "core.h"
17
18int cfg80211_wext_giwname(struct net_device *dev,
19 struct iw_request_info *info,
20 char *name, char *extra)
21{
22 struct wireless_dev *wdev = dev->ieee80211_ptr;
23 struct ieee80211_supported_band *sband;
24 bool is_ht = false, is_a = false, is_b = false, is_g = false;
25
26 if (!wdev)
27 return -EOPNOTSUPP;
28
29 sband = wdev->wiphy->bands[IEEE80211_BAND_5GHZ];
30 if (sband) {
31 is_a = true;
32 is_ht |= sband->ht_cap.ht_supported;
33 }
34
35 sband = wdev->wiphy->bands[IEEE80211_BAND_2GHZ];
36 if (sband) {
37 int i;
38 /* Check for mandatory rates */
39 for (i = 0; i < sband->n_bitrates; i++) {
40 if (sband->bitrates[i].bitrate == 10)
41 is_b = true;
42 if (sband->bitrates[i].bitrate == 60)
43 is_g = true;
44 }
45 is_ht |= sband->ht_cap.ht_supported;
46 }
47
48 strcpy(name, "IEEE 802.11");
49 if (is_a)
50 strcat(name, "a");
51 if (is_b)
52 strcat(name, "b");
53 if (is_g)
54 strcat(name, "g");
55 if (is_ht)
56 strcat(name, "n");
57
58 return 0;
59}
60EXPORT_SYMBOL(cfg80211_wext_giwname);
61
62int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
63 u32 *mode, char *extra)
64{
65 struct wireless_dev *wdev = dev->ieee80211_ptr;
66 struct cfg80211_registered_device *rdev;
67 struct vif_params vifparams;
68 enum nl80211_iftype type;
69
70 if (!wdev)
71 return -EOPNOTSUPP;
72
73 rdev = wiphy_to_dev(wdev->wiphy);
74
75 if (!rdev->ops->change_virtual_intf)
76 return -EOPNOTSUPP;
77
78 /* don't support changing VLANs, you just re-create them */
79 if (wdev->iftype == NL80211_IFTYPE_AP_VLAN)
80 return -EOPNOTSUPP;
81
82 switch (*mode) {
83 case IW_MODE_INFRA:
84 type = NL80211_IFTYPE_STATION;
85 break;
86 case IW_MODE_ADHOC:
87 type = NL80211_IFTYPE_ADHOC;
88 break;
89 case IW_MODE_REPEAT:
90 type = NL80211_IFTYPE_WDS;
91 break;
92 case IW_MODE_MONITOR:
93 type = NL80211_IFTYPE_MONITOR;
94 break;
95 default:
96 return -EINVAL;
97 }
98
99 memset(&vifparams, 0, sizeof(vifparams));
100
101 return rdev->ops->change_virtual_intf(wdev->wiphy, dev->ifindex, type,
102 NULL, &vifparams);
103}
104EXPORT_SYMBOL(cfg80211_wext_siwmode);
105
106int cfg80211_wext_giwmode(struct net_device *dev, struct iw_request_info *info,
107 u32 *mode, char *extra)
108{
109 struct wireless_dev *wdev = dev->ieee80211_ptr;
110
111 if (!wdev)
112 return -EOPNOTSUPP;
113
114 switch (wdev->iftype) {
115 case NL80211_IFTYPE_AP:
116 *mode = IW_MODE_MASTER;
117 break;
118 case NL80211_IFTYPE_STATION:
119 *mode = IW_MODE_INFRA;
120 break;
121 case NL80211_IFTYPE_ADHOC:
122 *mode = IW_MODE_ADHOC;
123 break;
124 case NL80211_IFTYPE_MONITOR:
125 *mode = IW_MODE_MONITOR;
126 break;
127 case NL80211_IFTYPE_WDS:
128 *mode = IW_MODE_REPEAT;
129 break;
130 case NL80211_IFTYPE_AP_VLAN:
131 *mode = IW_MODE_SECOND; /* FIXME */
132 break;
133 default:
134 *mode = IW_MODE_AUTO;
135 break;
136 }
137 return 0;
138}
139EXPORT_SYMBOL(cfg80211_wext_giwmode);