aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-09-10 18:01:52 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-09-15 16:48:21 -0400
commit9c6bd79011b14a8bfe58aad0acfb51e4dca05eed (patch)
tree0101b96437b5fb9421e8f291e3a99d0a2bf300a9
parent5bc75728fd43bb15b46f16ef465bcf9d487393cf (diff)
mac80211: reorder MLME code more
This way all the utility functions are at the top, then the state machine and externally callable functions are moved to the bottom. Also clean up ieee80211_i.h a bit and add a few comments about which functions are called from where. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--net/mac80211/ieee80211_i.h39
-rw-r--r--net/mac80211/iface.c17
-rw-r--r--net/mac80211/mlme.c624
3 files changed, 346 insertions, 334 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index cac0b1334548..442a43a34005 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -882,54 +882,53 @@ static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr)
882} 882}
883 883
884 884
885/* ieee80211.c */
886int ieee80211_hw_config(struct ieee80211_local *local); 885int ieee80211_hw_config(struct ieee80211_local *local);
887int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed); 886int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed);
888void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); 887void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx);
889u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht, 888u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht,
890 struct ieee80211_ht_info *req_ht_cap, 889 struct ieee80211_ht_info *req_ht_cap,
891 struct ieee80211_ht_bss_info *req_bss_cap); 890 struct ieee80211_ht_bss_info *req_bss_cap);
891void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
892 u32 changed);
892 893
893/* ieee80211_ioctl.c */ 894/* wireless extensions */
894extern const struct iw_handler_def ieee80211_iw_handler_def; 895extern const struct iw_handler_def ieee80211_iw_handler_def;
895int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freq); 896int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freq);
896 897
897/* ieee80211_sta.c */ 898/* STA/IBSS code */
898void ieee80211_sta_timer(unsigned long data); 899void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata);
899void ieee80211_sta_work(struct work_struct *work);
900void ieee80211_sta_scan_work(struct work_struct *work); 900void ieee80211_sta_scan_work(struct work_struct *work);
901void ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, 901void ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
902 struct ieee80211_rx_status *rx_status); 902 struct ieee80211_rx_status *rx_status);
903int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len); 903int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len);
904int ieee80211_sta_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len); 904int ieee80211_sta_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len);
905int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid); 905int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid);
906int ieee80211_sta_req_scan(struct ieee80211_sub_if_data *sdata, u8 *ssid, size_t ssid_len);
907void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata, 906void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata,
908 struct ieee80211_if_sta *ifsta); 907 struct ieee80211_if_sta *ifsta);
909int ieee80211_sta_scan_results(struct ieee80211_local *local,
910 struct iw_request_info *info,
911 char *buf, size_t len);
912ieee80211_rx_result ieee80211_sta_rx_scan(
913 struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
914 struct ieee80211_rx_status *rx_status);
915void ieee80211_rx_bss_list_init(struct ieee80211_local *local);
916void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local);
917int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, char *ie, size_t len);
918struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, 908struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
919 struct sk_buff *skb, u8 *bssid, 909 struct sk_buff *skb, u8 *bssid,
920 u8 *addr, u64 supp_rates); 910 u8 *addr, u64 supp_rates);
921int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason); 911int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason);
922int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason); 912int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason);
923void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
924 u32 changed);
925u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata); 913u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata);
926u64 ieee80211_sta_get_rates(struct ieee80211_local *local, 914u64 ieee80211_sta_get_rates(struct ieee80211_local *local,
927 struct ieee802_11_elems *elems, 915 struct ieee802_11_elems *elems,
928 enum ieee80211_band band); 916 enum ieee80211_band band);
929void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, 917void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
930 u8 *ssid, size_t ssid_len); 918 u8 *ssid, size_t ssid_len);
931void ieee802_11_parse_elems(u8 *start, size_t len, 919
932 struct ieee802_11_elems *elems); 920/* scan/BSS handling */
921int ieee80211_sta_req_scan(struct ieee80211_sub_if_data *sdata, u8 *ssid, size_t ssid_len);
922int ieee80211_sta_scan_results(struct ieee80211_local *local,
923 struct iw_request_info *info,
924 char *buf, size_t len);
925ieee80211_rx_result ieee80211_sta_rx_scan(
926 struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
927 struct ieee80211_rx_status *rx_status);
928void ieee80211_rx_bss_list_init(struct ieee80211_local *local);
929void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local);
930int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, char *ie, size_t len);
931
933void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local); 932void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local);
934int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *scan_sdata, 933int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *scan_sdata,
935 u8 *ssid, size_t ssid_len); 934 u8 *ssid, size_t ssid_len);
@@ -1007,6 +1006,8 @@ void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int ke
1007void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata); 1006void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata);
1008void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, 1007void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
1009 int encrypt); 1008 int encrypt);
1009void ieee802_11_parse_elems(u8 *start, size_t len,
1010 struct ieee802_11_elems *elems);
1010 1011
1011#ifdef CONFIG_MAC80211_NOINLINE 1012#ifdef CONFIG_MAC80211_NOINLINE
1012#define debug_noinline noinline 1013#define debug_noinline noinline
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index ddbaa417e2ec..61b19340488c 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -83,8 +83,6 @@ static void ieee80211_teardown_sdata(struct net_device *dev)
83static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, 83static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
84 enum ieee80211_if_types type) 84 enum ieee80211_if_types type)
85{ 85{
86 struct ieee80211_if_sta *ifsta;
87
88 /* clear type-dependent union */ 86 /* clear type-dependent union */
89 memset(&sdata->u, 0, sizeof(sdata->u)); 87 memset(&sdata->u, 0, sizeof(sdata->u));
90 88
@@ -101,20 +99,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
101 break; 99 break;
102 case IEEE80211_IF_TYPE_STA: 100 case IEEE80211_IF_TYPE_STA:
103 case IEEE80211_IF_TYPE_IBSS: 101 case IEEE80211_IF_TYPE_IBSS:
104 ifsta = &sdata->u.sta; 102 ieee80211_sta_setup_sdata(sdata);
105 INIT_WORK(&ifsta->work, ieee80211_sta_work);
106 setup_timer(&ifsta->timer, ieee80211_sta_timer,
107 (unsigned long) sdata);
108 skb_queue_head_init(&ifsta->skb_queue);
109
110 ifsta->capab = WLAN_CAPABILITY_ESS;
111 ifsta->auth_algs = IEEE80211_AUTH_ALG_OPEN |
112 IEEE80211_AUTH_ALG_SHARED_KEY;
113 ifsta->flags |= IEEE80211_STA_CREATE_IBSS |
114 IEEE80211_STA_AUTO_BSSID_SEL |
115 IEEE80211_STA_AUTO_CHANNEL_SEL;
116 if (ieee80211_num_regular_queues(&sdata->local->hw) >= 4)
117 ifsta->flags |= IEEE80211_STA_WMM_ENABLED;
118 break; 103 break;
119 case IEEE80211_IF_TYPE_MESH_POINT: 104 case IEEE80211_IF_TYPE_MESH_POINT:
120 if (ieee80211_vif_is_mesh(&sdata->vif)) 105 if (ieee80211_vif_is_mesh(&sdata->vif))
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 19c7f21e49d1..e14830106526 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -93,44 +93,46 @@ static int ieee80211_compatible_rates(struct ieee80211_sta_bss *bss,
93 return count; 93 return count;
94} 94}
95 95
96/* frame sending functions */ 96/* also used by mesh code */
97static void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, 97u64 ieee80211_sta_get_rates(struct ieee80211_local *local,
98 struct ieee80211_if_sta *ifsta, 98 struct ieee802_11_elems *elems,
99 int transaction, u8 *extra, size_t extra_len, 99 enum ieee80211_band band)
100 int encrypt)
101{ 100{
102 struct ieee80211_local *local = sdata->local; 101 struct ieee80211_supported_band *sband;
103 struct sk_buff *skb; 102 struct ieee80211_rate *bitrates;
104 struct ieee80211_mgmt *mgmt; 103 size_t num_rates;
104 u64 supp_rates;
105 int i, j;
106 sband = local->hw.wiphy->bands[band];
105 107
106 skb = dev_alloc_skb(local->hw.extra_tx_headroom + 108 if (!sband) {
107 sizeof(*mgmt) + 6 + extra_len); 109 WARN_ON(1);
108 if (!skb) { 110 sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
109 printk(KERN_DEBUG "%s: failed to allocate buffer for auth "
110 "frame\n", sdata->dev->name);
111 return;
112 } 111 }
113 skb_reserve(skb, local->hw.extra_tx_headroom);
114 112
115 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6); 113 bitrates = sband->bitrates;
116 memset(mgmt, 0, 24 + 6); 114 num_rates = sband->n_bitrates;
117 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 115 supp_rates = 0;
118 IEEE80211_STYPE_AUTH); 116 for (i = 0; i < elems->supp_rates_len +
119 if (encrypt) 117 elems->ext_supp_rates_len; i++) {
120 mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); 118 u8 rate = 0;
121 memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); 119 int own_rate;
122 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); 120 if (i < elems->supp_rates_len)
123 memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); 121 rate = elems->supp_rates[i];
124 mgmt->u.auth.auth_alg = cpu_to_le16(ifsta->auth_alg); 122 else if (elems->ext_supp_rates)
125 mgmt->u.auth.auth_transaction = cpu_to_le16(transaction); 123 rate = elems->ext_supp_rates
126 ifsta->auth_transaction = transaction + 1; 124 [i - elems->supp_rates_len];
127 mgmt->u.auth.status_code = cpu_to_le16(0); 125 own_rate = 5 * (rate & 0x7f);
128 if (extra) 126 for (j = 0; j < num_rates; j++)
129 memcpy(skb_put(skb, extra_len), extra, extra_len); 127 if (bitrates[j].bitrate == own_rate)
130 128 supp_rates |= BIT(j);
131 ieee80211_tx_skb(sdata, skb, encrypt); 129 }
130 return supp_rates;
132} 131}
133 132
133/* frame sending functions */
134
135/* also used by scanning code */
134void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, 136void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
135 u8 *ssid, size_t ssid_len) 137 u8 *ssid, size_t ssid_len)
136{ 138{
@@ -191,6 +193,43 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
191 ieee80211_tx_skb(sdata, skb, 0); 193 ieee80211_tx_skb(sdata, skb, 0);
192} 194}
193 195
196static void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
197 struct ieee80211_if_sta *ifsta,
198 int transaction, u8 *extra, size_t extra_len,
199 int encrypt)
200{
201 struct ieee80211_local *local = sdata->local;
202 struct sk_buff *skb;
203 struct ieee80211_mgmt *mgmt;
204
205 skb = dev_alloc_skb(local->hw.extra_tx_headroom +
206 sizeof(*mgmt) + 6 + extra_len);
207 if (!skb) {
208 printk(KERN_DEBUG "%s: failed to allocate buffer for auth "
209 "frame\n", sdata->dev->name);
210 return;
211 }
212 skb_reserve(skb, local->hw.extra_tx_headroom);
213
214 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6);
215 memset(mgmt, 0, 24 + 6);
216 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
217 IEEE80211_STYPE_AUTH);
218 if (encrypt)
219 mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
220 memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
221 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
222 memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
223 mgmt->u.auth.auth_alg = cpu_to_le16(ifsta->auth_alg);
224 mgmt->u.auth.auth_transaction = cpu_to_le16(transaction);
225 ifsta->auth_transaction = transaction + 1;
226 mgmt->u.auth.status_code = cpu_to_le16(0);
227 if (extra)
228 memcpy(skb_put(skb, extra_len), extra, extra_len);
229
230 ieee80211_tx_skb(sdata, skb, encrypt);
231}
232
194static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, 233static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
195 struct ieee80211_if_sta *ifsta) 234 struct ieee80211_if_sta *ifsta)
196{ 235{
@@ -1414,42 +1453,6 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
1414 return res; 1453 return res;
1415} 1454}
1416 1455
1417u64 ieee80211_sta_get_rates(struct ieee80211_local *local,
1418 struct ieee802_11_elems *elems,
1419 enum ieee80211_band band)
1420{
1421 struct ieee80211_supported_band *sband;
1422 struct ieee80211_rate *bitrates;
1423 size_t num_rates;
1424 u64 supp_rates;
1425 int i, j;
1426 sband = local->hw.wiphy->bands[band];
1427
1428 if (!sband) {
1429 WARN_ON(1);
1430 sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
1431 }
1432
1433 bitrates = sband->bitrates;
1434 num_rates = sband->n_bitrates;
1435 supp_rates = 0;
1436 for (i = 0; i < elems->supp_rates_len +
1437 elems->ext_supp_rates_len; i++) {
1438 u8 rate = 0;
1439 int own_rate;
1440 if (i < elems->supp_rates_len)
1441 rate = elems->supp_rates[i];
1442 else if (elems->ext_supp_rates)
1443 rate = elems->ext_supp_rates
1444 [i - elems->supp_rates_len];
1445 own_rate = 5 * (rate & 0x7f);
1446 for (j = 0; j < num_rates; j++)
1447 if (bitrates[j].bitrate == own_rate)
1448 supp_rates |= BIT(j);
1449 }
1450 return supp_rates;
1451}
1452
1453static u64 ieee80211_sta_get_mandatory_rates(struct ieee80211_local *local, 1456static u64 ieee80211_sta_get_mandatory_rates(struct ieee80211_local *local,
1454 enum ieee80211_band band) 1457 enum ieee80211_band band)
1455{ 1458{
@@ -1894,7 +1897,7 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata,
1894} 1897}
1895 1898
1896 1899
1897void ieee80211_sta_timer(unsigned long data) 1900static void ieee80211_sta_timer(unsigned long data)
1898{ 1901{
1899 struct ieee80211_sub_if_data *sdata = 1902 struct ieee80211_sub_if_data *sdata =
1900 (struct ieee80211_sub_if_data *) data; 1903 (struct ieee80211_sub_if_data *) data;
@@ -1937,28 +1940,6 @@ static void ieee80211_sta_reset_auth(struct ieee80211_sub_if_data *sdata,
1937} 1940}
1938 1941
1939 1942
1940void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata,
1941 struct ieee80211_if_sta *ifsta)
1942{
1943 struct ieee80211_local *local = sdata->local;
1944
1945 if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
1946 return;
1947
1948 if ((ifsta->flags & (IEEE80211_STA_BSSID_SET |
1949 IEEE80211_STA_AUTO_BSSID_SEL)) &&
1950 (ifsta->flags & (IEEE80211_STA_SSID_SET |
1951 IEEE80211_STA_AUTO_SSID_SEL))) {
1952
1953 if (ifsta->state == IEEE80211_STA_MLME_ASSOCIATED)
1954 ieee80211_set_disassoc(sdata, ifsta, true, true,
1955 WLAN_REASON_DEAUTH_LEAVING);
1956
1957 set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request);
1958 queue_work(local->hw.workqueue, &ifsta->work);
1959 }
1960}
1961
1962static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta, 1943static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta,
1963 const char *ssid, int ssid_len) 1944 const char *ssid, int ssid_len)
1964{ 1945{
@@ -2160,159 +2141,6 @@ dont_join:
2160} 2141}
2161 2142
2162 2143
2163int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len)
2164{
2165 struct ieee80211_if_sta *ifsta;
2166 int res;
2167
2168 if (len > IEEE80211_MAX_SSID_LEN)
2169 return -EINVAL;
2170
2171 ifsta = &sdata->u.sta;
2172
2173 if (ifsta->ssid_len != len || memcmp(ifsta->ssid, ssid, len) != 0) {
2174 memset(ifsta->ssid, 0, sizeof(ifsta->ssid));
2175 memcpy(ifsta->ssid, ssid, len);
2176 ifsta->ssid_len = len;
2177 ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
2178
2179 res = 0;
2180 /*
2181 * Hack! MLME code needs to be cleaned up to have different
2182 * entry points for configuration and internal selection change
2183 */
2184 if (netif_running(sdata->dev))
2185 res = ieee80211_if_config(sdata, IEEE80211_IFCC_SSID);
2186 if (res) {
2187 printk(KERN_DEBUG "%s: Failed to config new SSID to "
2188 "the low-level driver\n", sdata->dev->name);
2189 return res;
2190 }
2191 }
2192
2193 if (len)
2194 ifsta->flags |= IEEE80211_STA_SSID_SET;
2195 else
2196 ifsta->flags &= ~IEEE80211_STA_SSID_SET;
2197
2198 if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS &&
2199 !(ifsta->flags & IEEE80211_STA_BSSID_SET)) {
2200 ifsta->ibss_join_req = jiffies;
2201 ifsta->state = IEEE80211_STA_MLME_IBSS_SEARCH;
2202 return ieee80211_sta_find_ibss(sdata, ifsta);
2203 }
2204
2205 return 0;
2206}
2207
2208
2209int ieee80211_sta_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len)
2210{
2211 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
2212 memcpy(ssid, ifsta->ssid, ifsta->ssid_len);
2213 *len = ifsta->ssid_len;
2214 return 0;
2215}
2216
2217
2218int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid)
2219{
2220 struct ieee80211_if_sta *ifsta;
2221 int res;
2222
2223 ifsta = &sdata->u.sta;
2224
2225 if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) {
2226 memcpy(ifsta->bssid, bssid, ETH_ALEN);
2227 res = 0;
2228 /*
2229 * Hack! See also ieee80211_sta_set_ssid.
2230 */
2231 if (netif_running(sdata->dev))
2232 res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID);
2233 if (res) {
2234 printk(KERN_DEBUG "%s: Failed to config new BSSID to "
2235 "the low-level driver\n", sdata->dev->name);
2236 return res;
2237 }
2238 }
2239
2240 if (is_valid_ether_addr(bssid))
2241 ifsta->flags |= IEEE80211_STA_BSSID_SET;
2242 else
2243 ifsta->flags &= ~IEEE80211_STA_BSSID_SET;
2244
2245 return 0;
2246}
2247
2248
2249int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, char *ie, size_t len)
2250{
2251 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
2252
2253 kfree(ifsta->extra_ie);
2254 if (len == 0) {
2255 ifsta->extra_ie = NULL;
2256 ifsta->extra_ie_len = 0;
2257 return 0;
2258 }
2259 ifsta->extra_ie = kmalloc(len, GFP_KERNEL);
2260 if (!ifsta->extra_ie) {
2261 ifsta->extra_ie_len = 0;
2262 return -ENOMEM;
2263 }
2264 memcpy(ifsta->extra_ie, ie, len);
2265 ifsta->extra_ie_len = len;
2266 return 0;
2267}
2268
2269
2270struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
2271 struct sk_buff *skb, u8 *bssid,
2272 u8 *addr, u64 supp_rates)
2273{
2274 struct ieee80211_local *local = sdata->local;
2275 struct sta_info *sta;
2276 DECLARE_MAC_BUF(mac);
2277 int band = local->hw.conf.channel->band;
2278
2279 /* TODO: Could consider removing the least recently used entry and
2280 * allow new one to be added. */
2281 if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) {
2282 if (net_ratelimit()) {
2283 printk(KERN_DEBUG "%s: No room for a new IBSS STA "
2284 "entry %s\n", sdata->dev->name, print_mac(mac, addr));
2285 }
2286 return NULL;
2287 }
2288
2289 if (compare_ether_addr(bssid, sdata->u.sta.bssid))
2290 return NULL;
2291
2292#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
2293 printk(KERN_DEBUG "%s: Adding new IBSS station %s (dev=%s)\n",
2294 wiphy_name(local->hw.wiphy), print_mac(mac, addr), sdata->dev->name);
2295#endif
2296
2297 sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
2298 if (!sta)
2299 return NULL;
2300
2301 set_sta_flags(sta, WLAN_STA_AUTHORIZED);
2302
2303 /* make sure mandatory rates are always added */
2304 sta->supp_rates[band] = supp_rates |
2305 ieee80211_sta_get_mandatory_rates(local, band);
2306
2307 rate_control_rate_init(sta, local);
2308
2309 if (sta_info_insert(sta))
2310 return NULL;
2311
2312 return sta;
2313}
2314
2315
2316static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata, 2144static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata,
2317 struct ieee80211_if_sta *ifsta) 2145 struct ieee80211_if_sta *ifsta)
2318{ 2146{
@@ -2392,61 +2220,7 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata,
2392} 2220}
2393 2221
2394 2222
2395int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason) 2223static void ieee80211_sta_work(struct work_struct *work)
2396{
2397 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
2398
2399 printk(KERN_DEBUG "%s: deauthenticating by local choice (reason=%d)\n",
2400 sdata->dev->name, reason);
2401
2402 if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
2403 sdata->vif.type != IEEE80211_IF_TYPE_IBSS)
2404 return -EINVAL;
2405
2406 ieee80211_set_disassoc(sdata, ifsta, true, true, reason);
2407 return 0;
2408}
2409
2410
2411int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason)
2412{
2413 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
2414
2415 printk(KERN_DEBUG "%s: disassociating by local choice (reason=%d)\n",
2416 sdata->dev->name, reason);
2417
2418 if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
2419 return -EINVAL;
2420
2421 if (!(ifsta->flags & IEEE80211_STA_ASSOCIATED))
2422 return -1;
2423
2424 ieee80211_set_disassoc(sdata, ifsta, false, true, reason);
2425 return 0;
2426}
2427
2428void ieee80211_notify_mac(struct ieee80211_hw *hw,
2429 enum ieee80211_notification_types notif_type)
2430{
2431 struct ieee80211_local *local = hw_to_local(hw);
2432 struct ieee80211_sub_if_data *sdata;
2433
2434 switch (notif_type) {
2435 case IEEE80211_NOTIFY_RE_ASSOC:
2436 rcu_read_lock();
2437 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
2438 if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
2439 continue;
2440
2441 ieee80211_sta_req_auth(sdata, &sdata->u.sta);
2442 }
2443 rcu_read_unlock();
2444 break;
2445 }
2446}
2447EXPORT_SYMBOL(ieee80211_notify_mac);
2448
2449void ieee80211_sta_work(struct work_struct *work)
2450{ 2224{
2451 struct ieee80211_sub_if_data *sdata = 2225 struct ieee80211_sub_if_data *sdata =
2452 container_of(work, struct ieee80211_sub_if_data, u.sta.work); 2226 container_of(work, struct ieee80211_sub_if_data, u.sta.work);
@@ -2525,6 +2299,236 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
2525 &sdata->u.sta.work); 2299 &sdata->u.sta.work);
2526} 2300}
2527 2301
2302/* interface setup */
2303void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
2304{
2305 struct ieee80211_if_sta *ifsta;
2306
2307 ifsta = &sdata->u.sta;
2308 INIT_WORK(&ifsta->work, ieee80211_sta_work);
2309 setup_timer(&ifsta->timer, ieee80211_sta_timer,
2310 (unsigned long) sdata);
2311 skb_queue_head_init(&ifsta->skb_queue);
2312
2313 ifsta->capab = WLAN_CAPABILITY_ESS;
2314 ifsta->auth_algs = IEEE80211_AUTH_ALG_OPEN |
2315 IEEE80211_AUTH_ALG_SHARED_KEY;
2316 ifsta->flags |= IEEE80211_STA_CREATE_IBSS |
2317 IEEE80211_STA_AUTO_BSSID_SEL |
2318 IEEE80211_STA_AUTO_CHANNEL_SEL;
2319 if (ieee80211_num_regular_queues(&sdata->local->hw) >= 4)
2320 ifsta->flags |= IEEE80211_STA_WMM_ENABLED;
2321}
2322
2323/*
2324 * Add a new IBSS station, will also be called by the RX code when,
2325 * in IBSS mode, receiving a frame from a yet-unknown station, hence
2326 * must be callable in atomic context.
2327 */
2328struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
2329 struct sk_buff *skb, u8 *bssid,
2330 u8 *addr, u64 supp_rates)
2331{
2332 struct ieee80211_local *local = sdata->local;
2333 struct sta_info *sta;
2334 DECLARE_MAC_BUF(mac);
2335 int band = local->hw.conf.channel->band;
2336
2337 /* TODO: Could consider removing the least recently used entry and
2338 * allow new one to be added. */
2339 if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) {
2340 if (net_ratelimit()) {
2341 printk(KERN_DEBUG "%s: No room for a new IBSS STA "
2342 "entry %s\n", sdata->dev->name, print_mac(mac, addr));
2343 }
2344 return NULL;
2345 }
2346
2347 if (compare_ether_addr(bssid, sdata->u.sta.bssid))
2348 return NULL;
2349
2350#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
2351 printk(KERN_DEBUG "%s: Adding new IBSS station %s (dev=%s)\n",
2352 wiphy_name(local->hw.wiphy), print_mac(mac, addr), sdata->dev->name);
2353#endif
2354
2355 sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
2356 if (!sta)
2357 return NULL;
2358
2359 set_sta_flags(sta, WLAN_STA_AUTHORIZED);
2360
2361 /* make sure mandatory rates are always added */
2362 sta->supp_rates[band] = supp_rates |
2363 ieee80211_sta_get_mandatory_rates(local, band);
2364
2365 rate_control_rate_init(sta, local);
2366
2367 if (sta_info_insert(sta))
2368 return NULL;
2369
2370 return sta;
2371}
2372
2373/* configuration hooks */
2374void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata,
2375 struct ieee80211_if_sta *ifsta)
2376{
2377 struct ieee80211_local *local = sdata->local;
2378
2379 if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
2380 return;
2381
2382 if ((ifsta->flags & (IEEE80211_STA_BSSID_SET |
2383 IEEE80211_STA_AUTO_BSSID_SEL)) &&
2384 (ifsta->flags & (IEEE80211_STA_SSID_SET |
2385 IEEE80211_STA_AUTO_SSID_SEL))) {
2386
2387 if (ifsta->state == IEEE80211_STA_MLME_ASSOCIATED)
2388 ieee80211_set_disassoc(sdata, ifsta, true, true,
2389 WLAN_REASON_DEAUTH_LEAVING);
2390
2391 set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request);
2392 queue_work(local->hw.workqueue, &ifsta->work);
2393 }
2394}
2395
2396int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len)
2397{
2398 struct ieee80211_if_sta *ifsta;
2399 int res;
2400
2401 if (len > IEEE80211_MAX_SSID_LEN)
2402 return -EINVAL;
2403
2404 ifsta = &sdata->u.sta;
2405
2406 if (ifsta->ssid_len != len || memcmp(ifsta->ssid, ssid, len) != 0) {
2407 memset(ifsta->ssid, 0, sizeof(ifsta->ssid));
2408 memcpy(ifsta->ssid, ssid, len);
2409 ifsta->ssid_len = len;
2410 ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
2411
2412 res = 0;
2413 /*
2414 * Hack! MLME code needs to be cleaned up to have different
2415 * entry points for configuration and internal selection change
2416 */
2417 if (netif_running(sdata->dev))
2418 res = ieee80211_if_config(sdata, IEEE80211_IFCC_SSID);
2419 if (res) {
2420 printk(KERN_DEBUG "%s: Failed to config new SSID to "
2421 "the low-level driver\n", sdata->dev->name);
2422 return res;
2423 }
2424 }
2425
2426 if (len)
2427 ifsta->flags |= IEEE80211_STA_SSID_SET;
2428 else
2429 ifsta->flags &= ~IEEE80211_STA_SSID_SET;
2430
2431 if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS &&
2432 !(ifsta->flags & IEEE80211_STA_BSSID_SET)) {
2433 ifsta->ibss_join_req = jiffies;
2434 ifsta->state = IEEE80211_STA_MLME_IBSS_SEARCH;
2435 return ieee80211_sta_find_ibss(sdata, ifsta);
2436 }
2437
2438 return 0;
2439}
2440
2441int ieee80211_sta_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len)
2442{
2443 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
2444 memcpy(ssid, ifsta->ssid, ifsta->ssid_len);
2445 *len = ifsta->ssid_len;
2446 return 0;
2447}
2448
2449int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid)
2450{
2451 struct ieee80211_if_sta *ifsta;
2452 int res;
2453
2454 ifsta = &sdata->u.sta;
2455
2456 if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) {
2457 memcpy(ifsta->bssid, bssid, ETH_ALEN);
2458 res = 0;
2459 /*
2460 * Hack! See also ieee80211_sta_set_ssid.
2461 */
2462 if (netif_running(sdata->dev))
2463 res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID);
2464 if (res) {
2465 printk(KERN_DEBUG "%s: Failed to config new BSSID to "
2466 "the low-level driver\n", sdata->dev->name);
2467 return res;
2468 }
2469 }
2470
2471 if (is_valid_ether_addr(bssid))
2472 ifsta->flags |= IEEE80211_STA_BSSID_SET;
2473 else
2474 ifsta->flags &= ~IEEE80211_STA_BSSID_SET;
2475
2476 return 0;
2477}
2478
2479int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, char *ie, size_t len)
2480{
2481 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
2482
2483 kfree(ifsta->extra_ie);
2484 if (len == 0) {
2485 ifsta->extra_ie = NULL;
2486 ifsta->extra_ie_len = 0;
2487 return 0;
2488 }
2489 ifsta->extra_ie = kmalloc(len, GFP_KERNEL);
2490 if (!ifsta->extra_ie) {
2491 ifsta->extra_ie_len = 0;
2492 return -ENOMEM;
2493 }
2494 memcpy(ifsta->extra_ie, ie, len);
2495 ifsta->extra_ie_len = len;
2496 return 0;
2497}
2498
2499int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason)
2500{
2501 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
2502
2503 printk(KERN_DEBUG "%s: deauthenticating by local choice (reason=%d)\n",
2504 sdata->dev->name, reason);
2505
2506 if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
2507 sdata->vif.type != IEEE80211_IF_TYPE_IBSS)
2508 return -EINVAL;
2509
2510 ieee80211_set_disassoc(sdata, ifsta, true, true, reason);
2511 return 0;
2512}
2513
2514int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason)
2515{
2516 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
2517
2518 printk(KERN_DEBUG "%s: disassociating by local choice (reason=%d)\n",
2519 sdata->dev->name, reason);
2520
2521 if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
2522 return -EINVAL;
2523
2524 if (!(ifsta->flags & IEEE80211_STA_ASSOCIATED))
2525 return -1;
2526
2527 ieee80211_set_disassoc(sdata, ifsta, false, true, reason);
2528 return 0;
2529}
2530
2531/* scan finished notification */
2528void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) 2532void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local)
2529{ 2533{
2530 struct ieee80211_sub_if_data *sdata = local->scan_sdata; 2534 struct ieee80211_sub_if_data *sdata = local->scan_sdata;
@@ -2544,3 +2548,25 @@ void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local)
2544 ieee80211_restart_sta_timer(sdata); 2548 ieee80211_restart_sta_timer(sdata);
2545 rcu_read_unlock(); 2549 rcu_read_unlock();
2546} 2550}
2551
2552/* driver notification call */
2553void ieee80211_notify_mac(struct ieee80211_hw *hw,
2554 enum ieee80211_notification_types notif_type)
2555{
2556 struct ieee80211_local *local = hw_to_local(hw);
2557 struct ieee80211_sub_if_data *sdata;
2558
2559 switch (notif_type) {
2560 case IEEE80211_NOTIFY_RE_ASSOC:
2561 rcu_read_lock();
2562 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
2563 if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
2564 continue;
2565
2566 ieee80211_sta_req_auth(sdata, &sdata->u.sta);
2567 }
2568 rcu_read_unlock();
2569 break;
2570 }
2571}
2572EXPORT_SYMBOL(ieee80211_notify_mac);