2 * SME code for cfg80211's connect emulation.
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 <linux/workqueue.h>
11 #include <net/cfg80211.h>
12 #include <net/rtnetlink.h>
16 void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
17 const u8 *req_ie, size_t req_ie_len,
18 const u8 *resp_ie, size_t resp_ie_len,
19 u16 status, gfp_t gfp)
21 struct wireless_dev *wdev = dev->ieee80211_ptr;
22 struct cfg80211_bss *bss;
23 #ifdef CONFIG_WIRELESS_EXT
24 union iwreq_data wrqu;
27 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
30 if (WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTING))
33 if (wdev->current_bss) {
34 cfg80211_unhold_bss(wdev->current_bss);
35 cfg80211_put_bss(wdev->current_bss);
36 wdev->current_bss = NULL;
39 if (status == WLAN_STATUS_SUCCESS) {
40 bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
41 wdev->ssid, wdev->ssid_len,
48 cfg80211_hold_bss(bss);
49 wdev->current_bss = bss;
51 wdev->sme_state = CFG80211_SME_CONNECTED;
53 wdev->sme_state = CFG80211_SME_IDLE;
56 nl80211_send_connect_result(wiphy_to_dev(wdev->wiphy), dev, bssid,
57 req_ie, req_ie_len, resp_ie, resp_ie_len,
60 #ifdef CONFIG_WIRELESS_EXT
61 if (req_ie && status == WLAN_STATUS_SUCCESS) {
62 memset(&wrqu, 0, sizeof(wrqu));
63 wrqu.data.length = req_ie_len;
64 wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, req_ie);
67 if (resp_ie && status == WLAN_STATUS_SUCCESS) {
68 memset(&wrqu, 0, sizeof(wrqu));
69 wrqu.data.length = resp_ie_len;
70 wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, resp_ie);
73 memset(&wrqu, 0, sizeof(wrqu));
74 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
76 memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
77 wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
80 EXPORT_SYMBOL(cfg80211_connect_result);
82 void cfg80211_roamed(struct net_device *dev, const u8 *bssid,
83 const u8 *req_ie, size_t req_ie_len,
84 const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp)
86 struct wireless_dev *wdev = dev->ieee80211_ptr;
87 struct cfg80211_bss *bss;
88 #ifdef CONFIG_WIRELESS_EXT
89 union iwreq_data wrqu;
92 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
95 if (WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTED))
98 /* internal error -- how did we get to CONNECTED w/o BSS? */
99 if (WARN_ON(!wdev->current_bss)) {
103 cfg80211_unhold_bss(wdev->current_bss);
104 cfg80211_put_bss(wdev->current_bss);
105 wdev->current_bss = NULL;
107 bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
108 wdev->ssid, wdev->ssid_len,
109 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
114 cfg80211_hold_bss(bss);
115 wdev->current_bss = bss;
117 nl80211_send_roamed(wiphy_to_dev(wdev->wiphy), dev, bssid,
118 req_ie, req_ie_len, resp_ie, resp_ie_len, gfp);
120 #ifdef CONFIG_WIRELESS_EXT
122 memset(&wrqu, 0, sizeof(wrqu));
123 wrqu.data.length = req_ie_len;
124 wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, req_ie);
128 memset(&wrqu, 0, sizeof(wrqu));
129 wrqu.data.length = resp_ie_len;
130 wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, resp_ie);
133 memset(&wrqu, 0, sizeof(wrqu));
134 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
135 memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
136 wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
139 EXPORT_SYMBOL(cfg80211_roamed);
141 static void __cfg80211_disconnected(struct net_device *dev, gfp_t gfp,
142 u8 *ie, size_t ie_len, u16 reason,
145 struct wireless_dev *wdev = dev->ieee80211_ptr;
146 #ifdef CONFIG_WIRELESS_EXT
147 union iwreq_data wrqu;
150 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
153 if (WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTED))
156 if (wdev->current_bss) {
157 cfg80211_unhold_bss(wdev->current_bss);
158 cfg80211_put_bss(wdev->current_bss);
161 wdev->current_bss = NULL;
162 wdev->sme_state = CFG80211_SME_IDLE;
164 nl80211_send_disconnected(wiphy_to_dev(wdev->wiphy), dev,
165 reason, ie, ie_len, from_ap, gfp);
167 #ifdef CONFIG_WIRELESS_EXT
168 memset(&wrqu, 0, sizeof(wrqu));
169 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
170 wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
174 void cfg80211_disconnected(struct net_device *dev, u16 reason,
175 u8 *ie, size_t ie_len, gfp_t gfp)
177 __cfg80211_disconnected(dev, reason, ie, ie_len, true, gfp);
179 EXPORT_SYMBOL(cfg80211_disconnected);
181 int cfg80211_connect(struct cfg80211_registered_device *rdev,
182 struct net_device *dev,
183 struct cfg80211_connect_params *connect)
186 struct wireless_dev *wdev = dev->ieee80211_ptr;
188 if (wdev->sme_state != CFG80211_SME_IDLE)
191 if (!rdev->ops->connect) {
194 wdev->sme_state = CFG80211_SME_CONNECTING;
195 err = rdev->ops->connect(&rdev->wiphy, dev, connect);
197 wdev->sme_state = CFG80211_SME_IDLE;
202 memcpy(wdev->ssid, connect->ssid, connect->ssid_len);
203 wdev->ssid_len = connect->ssid_len;
208 int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
209 struct net_device *dev, u16 reason)
213 if (!rdev->ops->disconnect) {
216 err = rdev->ops->disconnect(&rdev->wiphy, dev, reason);
221 __cfg80211_disconnected(dev, 0, NULL, 0, false, GFP_KERNEL);