2 * cfg80211 wext compat for managed mode.
4 * Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
5 * Copyright (C) 2009 Intel Corporation. All rights reserved.
8 #include <linux/etherdevice.h>
9 #include <linux/if_arp.h>
10 #include <net/cfg80211.h>
13 static int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
14 struct wireless_dev *wdev)
18 if (!netif_running(wdev->netdev))
21 wdev->wext.connect.ie = wdev->wext.ie;
22 wdev->wext.connect.ie_len = wdev->wext.ie_len;
23 wdev->wext.connect.privacy = wdev->wext.default_key != -1;
26 if (wdev->wext.connect.ssid_len != 0)
27 err = cfg80211_connect(rdev, wdev->netdev,
33 int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
34 struct iw_request_info *info,
35 struct iw_freq *freq, char *extra)
37 struct wireless_dev *wdev = dev->ieee80211_ptr;
38 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
39 struct ieee80211_channel *chan;
42 /* call only for station! */
43 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
46 chan = cfg80211_wext_freq(wdev->wiphy, freq);
47 if (chan && IS_ERR(chan))
50 if (chan && (chan->flags & IEEE80211_CHAN_DISABLED))
53 if (wdev->wext.connect.channel == chan)
56 if (wdev->sme_state != CFG80211_SME_IDLE) {
58 /* if SSID set, we'll try right again, avoid event */
59 if (wdev->wext.connect.ssid_len)
61 err = cfg80211_disconnect(wiphy_to_dev(wdev->wiphy),
62 dev, WLAN_REASON_DEAUTH_LEAVING,
68 wdev->wext.connect.channel = chan;
70 /* SSID is not set, we just want to switch channel */
71 if (wdev->wext.connect.ssid_len && chan) {
72 if (!rdev->ops->set_channel)
75 return rdev->ops->set_channel(wdev->wiphy, chan,
79 return cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev);
81 /* temporary symbol - mark GPL - in the future the handler won't be */
82 EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_siwfreq);
84 int cfg80211_mgd_wext_giwfreq(struct net_device *dev,
85 struct iw_request_info *info,
86 struct iw_freq *freq, char *extra)
88 struct wireless_dev *wdev = dev->ieee80211_ptr;
89 struct ieee80211_channel *chan = NULL;
91 /* call only for station! */
92 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
95 if (wdev->current_bss)
96 chan = wdev->current_bss->channel;
97 else if (wdev->wext.connect.channel)
98 chan = wdev->wext.connect.channel;
101 freq->m = chan->center_freq;
106 /* no channel if not joining */
109 /* temporary symbol - mark GPL - in the future the handler won't be */
110 EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_giwfreq);
112 int cfg80211_mgd_wext_siwessid(struct net_device *dev,
113 struct iw_request_info *info,
114 struct iw_point *data, char *ssid)
116 struct wireless_dev *wdev = dev->ieee80211_ptr;
117 size_t len = data->length;
120 /* call only for station! */
121 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
127 /* iwconfig uses nul termination in SSID.. */
128 if (len > 0 && ssid[len - 1] == '\0')
131 if (wdev->wext.connect.ssid && len &&
132 len == wdev->wext.connect.ssid_len &&
133 memcmp(wdev->wext.connect.ssid, ssid, len))
136 if (wdev->sme_state != CFG80211_SME_IDLE) {
138 /* if SSID set now, we'll try to connect, avoid event */
141 err = cfg80211_disconnect(wiphy_to_dev(wdev->wiphy),
142 dev, WLAN_REASON_DEAUTH_LEAVING,
148 wdev->wext.connect.ssid = wdev->wext.ssid;
149 memcpy(wdev->wext.ssid, ssid, len);
150 wdev->wext.connect.ssid_len = len;
152 wdev->wext.connect.crypto.control_port = false;
154 return cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev);
156 /* temporary symbol - mark GPL - in the future the handler won't be */
157 EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_siwessid);
159 int cfg80211_mgd_wext_giwessid(struct net_device *dev,
160 struct iw_request_info *info,
161 struct iw_point *data, char *ssid)
163 struct wireless_dev *wdev = dev->ieee80211_ptr;
165 /* call only for station! */
166 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
171 if (wdev->ssid_len) {
173 data->length = wdev->ssid_len;
174 memcpy(ssid, wdev->ssid, data->length);
175 } else if (wdev->wext.connect.ssid && wdev->wext.connect.ssid_len) {
177 data->length = wdev->wext.connect.ssid_len;
178 memcpy(ssid, wdev->wext.connect.ssid, data->length);
184 /* temporary symbol - mark GPL - in the future the handler won't be */
185 EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_giwessid);
187 int cfg80211_mgd_wext_siwap(struct net_device *dev,
188 struct iw_request_info *info,
189 struct sockaddr *ap_addr, char *extra)
191 struct wireless_dev *wdev = dev->ieee80211_ptr;
192 u8 *bssid = ap_addr->sa_data;
195 /* call only for station! */
196 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
199 if (ap_addr->sa_family != ARPHRD_ETHER)
203 if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid))
207 if (!bssid && !wdev->wext.connect.bssid)
210 /* fixed already - and no change */
211 if (wdev->wext.connect.bssid && bssid &&
212 compare_ether_addr(bssid, wdev->wext.connect.bssid) == 0)
215 if (wdev->sme_state != CFG80211_SME_IDLE) {
216 err = cfg80211_disconnect(wiphy_to_dev(wdev->wiphy),
217 dev, WLAN_REASON_DEAUTH_LEAVING,
224 memcpy(wdev->wext.bssid, bssid, ETH_ALEN);
225 wdev->wext.connect.bssid = wdev->wext.bssid;
227 wdev->wext.connect.bssid = NULL;
229 return cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev);
231 /* temporary symbol - mark GPL - in the future the handler won't be */
232 EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_siwap);
234 int cfg80211_mgd_wext_giwap(struct net_device *dev,
235 struct iw_request_info *info,
236 struct sockaddr *ap_addr, char *extra)
238 struct wireless_dev *wdev = dev->ieee80211_ptr;
240 /* call only for station! */
241 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
244 ap_addr->sa_family = ARPHRD_ETHER;
246 if (wdev->current_bss)
247 memcpy(ap_addr->sa_data, wdev->current_bss->bssid, ETH_ALEN);
248 else if (wdev->wext.connect.bssid)
249 memcpy(ap_addr->sa_data, wdev->wext.connect.bssid, ETH_ALEN);
251 memset(ap_addr->sa_data, 0, ETH_ALEN);
255 /* temporary symbol - mark GPL - in the future the handler won't be */
256 EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_giwap);
258 int cfg80211_wext_siwgenie(struct net_device *dev,
259 struct iw_request_info *info,
260 struct iw_point *data, char *extra)
262 struct wireless_dev *wdev = dev->ieee80211_ptr;
263 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
265 int ie_len = data->length, err;
267 if (wdev->iftype != NL80211_IFTYPE_STATION)
274 if (wdev->wext.ie_len == ie_len &&
275 memcmp(wdev->wext.ie, ie, ie_len) == 0)
279 ie = kmemdup(extra, ie_len, GFP_KERNEL);
285 kfree(wdev->wext.ie);
287 wdev->wext.ie_len = ie_len;
289 if (wdev->sme_state != CFG80211_SME_IDLE) {
290 err = cfg80211_disconnect(rdev, dev,
291 WLAN_REASON_DEAUTH_LEAVING, false);
296 /* userspace better not think we'll reconnect */
299 EXPORT_SYMBOL_GPL(cfg80211_wext_siwgenie);
301 int cfg80211_wext_siwmlme(struct net_device *dev,
302 struct iw_request_info *info,
303 struct iw_point *data, char *extra)
305 struct wireless_dev *wdev = dev->ieee80211_ptr;
306 struct iw_mlme *mlme = (struct iw_mlme *)extra;
307 struct cfg80211_registered_device *rdev;
312 rdev = wiphy_to_dev(wdev->wiphy);
314 if (wdev->iftype != NL80211_IFTYPE_STATION)
317 if (mlme->addr.sa_family != ARPHRD_ETHER)
322 case IW_MLME_DISASSOC:
323 return cfg80211_disconnect(rdev, dev, mlme->reason_code,
329 EXPORT_SYMBOL_GPL(cfg80211_wext_siwmlme);