X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=net%2Fmac80211%2Fmlme.c;h=df12e746b03e24d5988ca99a85b85888adae205f;hb=17dce5dfe38ae2fb359b61e855f5d8a3a8b7892b;hp=902cac1bd246ab7f861cb2f1aa8b3c06168dc33a;hpb=82a28c794f27aac17d7a3ebd7f14d731a11a5532;p=safe%2Fjmp%2Flinux-2.6 diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 902cac1..df12e74 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -34,6 +34,7 @@ #include "led.h" #include "mesh.h" +#define IEEE80211_ASSOC_SCANS_MAX_TRIES 2 #define IEEE80211_AUTH_TIMEOUT (HZ / 5) #define IEEE80211_AUTH_MAX_TRIES 3 #define IEEE80211_ASSOC_TIMEOUT (HZ / 5) @@ -73,19 +74,19 @@ #define IEEE80211_MIN_AMPDU_BUF 0x8 #define IEEE80211_MAX_AMPDU_BUF 0x40 -static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, +static void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, u8 *ssid, size_t ssid_len); static struct ieee80211_sta_bss * -ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int freq, +ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, u8 *ssid, u8 ssid_len); static void ieee80211_rx_bss_put(struct ieee80211_local *local, struct ieee80211_sta_bss *bss); -static int ieee80211_sta_find_ibss(struct net_device *dev, +static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta); -static int ieee80211_sta_wep_configured(struct net_device *dev); -static int ieee80211_sta_start_scan(struct net_device *dev, +static int ieee80211_sta_wep_configured(struct ieee80211_sub_if_data *sdata); +static int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *sdata, u8 *ssid, size_t ssid_len); -static int ieee80211_sta_config_auth(struct net_device *dev, +static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta); static void sta_rx_agg_session_timer_expired(unsigned long data); @@ -97,6 +98,8 @@ void ieee802_11_parse_elems(u8 *start, size_t len, u8 *pos = start; memset(elems, 0, sizeof(*elems)); + elems->ie_start = start; + elems->total_len = len; while (left >= 2) { u8 id, elen; @@ -233,17 +236,37 @@ void ieee802_11_parse_elems(u8 *start, size_t len, } +static u8 * ieee80211_bss_get_ie(struct ieee80211_sta_bss *bss, u8 ie) +{ + u8 *end, *pos; + + pos = bss->ies; + if (pos == NULL) + return NULL; + end = pos + bss->ies_len; + + while (pos + 1 < end) { + if (pos + 2 + pos[1] > end) + break; + if (pos[0] == ie) + return pos; + pos += 2 + pos[1]; + } + + return NULL; +} + + static int ecw2cw(int ecw) { return (1 << ecw) - 1; } -static void ieee80211_sta_def_wmm_params(struct net_device *dev, +static void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, struct ieee80211_sta_bss *bss, int ibss) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; int i, have_higher_than_11mbit = 0; @@ -281,11 +304,10 @@ static void ieee80211_sta_def_wmm_params(struct net_device *dev, } } -static void ieee80211_sta_wmm_params(struct net_device *dev, +static void ieee80211_sta_wmm_params(struct ieee80211_local *local, struct ieee80211_if_sta *ifsta, u8 *wmm_param, size_t wmm_param_len) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_tx_queue_params params; size_t left; int count; @@ -349,14 +371,14 @@ static void ieee80211_sta_wmm_params(struct net_device *dev, #ifdef CONFIG_MAC80211_VERBOSE_DEBUG printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d " "cWmin=%d cWmax=%d txop=%d\n", - dev->name, queue, aci, acm, params.aifs, params.cw_min, + local->mdev->name, queue, aci, acm, params.aifs, params.cw_min, params.cw_max, params.txop); #endif /* TODO: handle ACM (block TX, fallback to next lowest allowed * AC for now) */ if (local->ops->conf_tx(local_to_hw(local), queue, ¶ms)) { printk(KERN_DEBUG "%s: failed to set TX queue " - "parameters for queue %d\n", dev->name, queue); + "parameters for queue %d\n", local->mdev->name, queue); } } } @@ -475,62 +497,30 @@ int ieee80211_ht_addt_info_ie_to_ht_bss_info( return 0; } -static void ieee80211_sta_send_associnfo(struct net_device *dev, +static void ieee80211_sta_send_associnfo(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { - char *buf; - size_t len; - int i; union iwreq_data wrqu; - if (!ifsta->assocreq_ies && !ifsta->assocresp_ies) - return; - - buf = kmalloc(50 + 2 * (ifsta->assocreq_ies_len + - ifsta->assocresp_ies_len), GFP_KERNEL); - if (!buf) - return; - - len = sprintf(buf, "ASSOCINFO("); if (ifsta->assocreq_ies) { - len += sprintf(buf + len, "ReqIEs="); - for (i = 0; i < ifsta->assocreq_ies_len; i++) { - len += sprintf(buf + len, "%02x", - ifsta->assocreq_ies[i]); - } + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.length = ifsta->assocreq_ies_len; + wireless_send_event(sdata->dev, IWEVASSOCREQIE, &wrqu, + ifsta->assocreq_ies); } if (ifsta->assocresp_ies) { - if (ifsta->assocreq_ies) - len += sprintf(buf + len, " "); - len += sprintf(buf + len, "RespIEs="); - for (i = 0; i < ifsta->assocresp_ies_len; i++) { - len += sprintf(buf + len, "%02x", - ifsta->assocresp_ies[i]); - } + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.length = ifsta->assocresp_ies_len; + wireless_send_event(sdata->dev, IWEVASSOCRESPIE, &wrqu, + ifsta->assocresp_ies); } - len += sprintf(buf + len, ")"); - - if (len > IW_CUSTOM_MAX) { - len = sprintf(buf, "ASSOCRESPIE="); - for (i = 0; i < ifsta->assocresp_ies_len; i++) { - len += sprintf(buf + len, "%02x", - ifsta->assocresp_ies[i]); - } - } - - memset(&wrqu, 0, sizeof(wrqu)); - wrqu.data.length = len; - wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf); - - kfree(buf); } -static void ieee80211_set_associated(struct net_device *dev, +static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, bool assoc) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; struct ieee80211_conf *conf = &local_to_hw(local)->conf; union iwreq_data wrqu; @@ -544,7 +534,7 @@ static void ieee80211_set_associated(struct net_device *dev, if (sdata->vif.type != IEEE80211_IF_TYPE_STA) return; - bss = ieee80211_rx_bss_get(dev, ifsta->bssid, + bss = ieee80211_rx_bss_get(local, ifsta->bssid, conf->channel->center_freq, ifsta->ssid, ifsta->ssid_len); if (bss) { @@ -568,12 +558,12 @@ static void ieee80211_set_associated(struct net_device *dev, ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET; memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN); memcpy(wrqu.ap_addr.sa_data, sdata->u.sta.bssid, ETH_ALEN); - ieee80211_sta_send_associnfo(dev, ifsta); + ieee80211_sta_send_associnfo(sdata, ifsta); } else { - netif_carrier_off(dev); - ieee80211_sta_tear_down_BA_sessions(dev, ifsta->bssid); + netif_carrier_off(sdata->dev); + ieee80211_sta_tear_down_BA_sessions(sdata, ifsta->bssid); ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; - changed |= ieee80211_reset_erp_info(dev); + changed |= ieee80211_reset_erp_info(sdata); sdata->bss_conf.assoc_ht = 0; sdata->bss_conf.ht_conf = NULL; @@ -588,27 +578,27 @@ static void ieee80211_set_associated(struct net_device *dev, ieee80211_bss_info_change_notify(sdata, changed); if (assoc) - netif_carrier_on(dev); + netif_carrier_on(sdata->dev); wrqu.ap_addr.sa_family = ARPHRD_ETHER; - wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); + wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL); } -static void ieee80211_set_disassoc(struct net_device *dev, +static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, int deauth) { - if (deauth) + if (deauth) { + ifsta->direct_probe_tries = 0; ifsta->auth_tries = 0; + } + ifsta->assoc_scan_tries = 0; ifsta->assoc_tries = 0; - ieee80211_set_associated(dev, ifsta, 0); + ieee80211_set_associated(sdata, ifsta, 0); } -void ieee80211_sta_tx(struct net_device *dev, struct sk_buff *skb, +void ieee80211_sta_tx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, int encrypt) { - struct ieee80211_sub_if_data *sdata; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); skb->dev = sdata->local->mdev; skb_set_mac_header(skb, 0); skb_set_network_header(skb, 0); @@ -621,12 +611,12 @@ void ieee80211_sta_tx(struct net_device *dev, struct sk_buff *skb, } -static void ieee80211_send_auth(struct net_device *dev, +static void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, int transaction, u8 *extra, size_t extra_len, int encrypt) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; @@ -634,19 +624,19 @@ static void ieee80211_send_auth(struct net_device *dev, sizeof(*mgmt) + 6 + extra_len); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for auth " - "frame\n", dev->name); + "frame\n", sdata->dev->name); return; } skb_reserve(skb, local->hw.extra_tx_headroom); mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6); memset(mgmt, 0, 24 + 6); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_AUTH); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_AUTH); if (encrypt) mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); mgmt->u.auth.auth_alg = cpu_to_le16(ifsta->auth_alg); mgmt->u.auth.auth_transaction = cpu_to_le16(transaction); @@ -655,11 +645,41 @@ static void ieee80211_send_auth(struct net_device *dev, if (extra) memcpy(skb_put(skb, extra_len), extra, extra_len); - ieee80211_sta_tx(dev, skb, encrypt); + ieee80211_sta_tx(sdata, skb, encrypt); } +static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata, + struct ieee80211_if_sta *ifsta) +{ + DECLARE_MAC_BUF(mac); + + ifsta->direct_probe_tries++; + if (ifsta->direct_probe_tries > IEEE80211_AUTH_MAX_TRIES) { + printk(KERN_DEBUG "%s: direct probe to AP %s timed out\n", + sdata->dev->name, print_mac(mac, ifsta->bssid)); + ifsta->state = IEEE80211_STA_MLME_DISABLED; + return; + } + + printk(KERN_DEBUG "%s: direct probe to AP %s try %d\n", + sdata->dev->name, print_mac(mac, ifsta->bssid), + ifsta->direct_probe_tries); + + ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE; -static void ieee80211_authenticate(struct net_device *dev, + set_bit(IEEE80211_STA_REQ_DIRECT_PROBE, &ifsta->request); + + /* Direct probe is sent to broadcast address as some APs + * will not answer to direct packet in unassociated state. + */ + ieee80211_send_probe_req(sdata, NULL, + ifsta->ssid, ifsta->ssid_len); + + mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT); +} + + +static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { DECLARE_MAC_BUF(mac); @@ -668,16 +688,16 @@ static void ieee80211_authenticate(struct net_device *dev, if (ifsta->auth_tries > IEEE80211_AUTH_MAX_TRIES) { printk(KERN_DEBUG "%s: authentication with AP %s" " timed out\n", - dev->name, print_mac(mac, ifsta->bssid)); - ifsta->state = IEEE80211_DISABLED; + sdata->dev->name, print_mac(mac, ifsta->bssid)); + ifsta->state = IEEE80211_STA_MLME_DISABLED; return; } - ifsta->state = IEEE80211_AUTHENTICATE; + ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; printk(KERN_DEBUG "%s: authenticate with AP %s\n", - dev->name, print_mac(mac, ifsta->bssid)); + sdata->dev->name, print_mac(mac, ifsta->bssid)); - ieee80211_send_auth(dev, ifsta, 1, NULL, 0, 0); + ieee80211_send_auth(sdata, ifsta, 1, NULL, 0, 0); mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT); } @@ -703,13 +723,13 @@ static int ieee80211_compatible_rates(struct ieee80211_sta_bss *bss, return count; } -static void ieee80211_send_assoc(struct net_device *dev, +static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; - u8 *pos, *ies; + u8 *pos, *ies, *ht_add_ie; int i, len, count, rates_len, supp_rates_len; u16 capab; struct ieee80211_sta_bss *bss; @@ -722,7 +742,7 @@ static void ieee80211_send_assoc(struct net_device *dev, ifsta->ssid_len); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " - "frame\n", dev->name); + "frame\n", sdata->dev->name); return; } skb_reserve(skb, local->hw.extra_tx_headroom); @@ -738,13 +758,13 @@ static void ieee80211_send_assoc(struct net_device *dev, capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; } - bss = ieee80211_rx_bss_get(dev, ifsta->bssid, + bss = ieee80211_rx_bss_get(local, ifsta->bssid, local->hw.conf.channel->center_freq, ifsta->ssid, ifsta->ssid_len); if (bss) { if (bss->capability & WLAN_CAPABILITY_PRIVACY) capab |= WLAN_CAPABILITY_PRIVACY; - if (bss->wmm_ie) + if (bss->wmm_used) wmm = 1; /* get all rates supported by the device and the AP as @@ -766,13 +786,13 @@ static void ieee80211_send_assoc(struct net_device *dev, mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); memset(mgmt, 0, 24); memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); if (ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) { skb_put(skb, 10); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_REASSOC_REQ); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_REASSOC_REQ); mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab); mgmt->u.reassoc_req.listen_interval = cpu_to_le16(local->hw.conf.listen_interval); @@ -780,8 +800,8 @@ static void ieee80211_send_assoc(struct net_device *dev, ETH_ALEN); } else { skb_put(skb, 4); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_ASSOC_REQ); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ASSOC_REQ); mgmt->u.assoc_req.capab_info = cpu_to_le16(capab); mgmt->u.reassoc_req.listen_interval = cpu_to_le16(local->hw.conf.listen_interval); @@ -866,9 +886,10 @@ static void ieee80211_send_assoc(struct net_device *dev, /* wmm support is a must to HT */ if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED) && - sband->ht_info.ht_supported && bss->ht_add_ie) { + sband->ht_info.ht_supported && + (ht_add_ie = ieee80211_bss_get_ie(bss, WLAN_EID_HT_EXTRA_INFO))) { struct ieee80211_ht_addt_info *ht_add_info = - (struct ieee80211_ht_addt_info *)bss->ht_add_ie; + (struct ieee80211_ht_addt_info *)ht_add_ie; u16 cap = sband->ht_info.cap; __le16 tmp; u32 flags = local->hw.conf.channel->flags; @@ -907,21 +928,21 @@ static void ieee80211_send_assoc(struct net_device *dev, if (ifsta->assocreq_ies) memcpy(ifsta->assocreq_ies, ies, ifsta->assocreq_ies_len); - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); } -static void ieee80211_send_deauth(struct net_device *dev, +static void ieee80211_send_deauth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, u16 reason) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for deauth " - "frame\n", dev->name); + "frame\n", sdata->dev->name); return; } skb_reserve(skb, local->hw.extra_tx_headroom); @@ -929,28 +950,28 @@ static void ieee80211_send_deauth(struct net_device *dev, mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); memset(mgmt, 0, 24); memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_DEAUTH); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_DEAUTH); skb_put(skb, 2); mgmt->u.deauth.reason_code = cpu_to_le16(reason); - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); } -static void ieee80211_send_disassoc(struct net_device *dev, +static void ieee80211_send_disassoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, u16 reason) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for disassoc " - "frame\n", dev->name); + "frame\n", sdata->dev->name); return; } skb_reserve(skb, local->hw.extra_tx_headroom); @@ -958,21 +979,21 @@ static void ieee80211_send_disassoc(struct net_device *dev, mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); memset(mgmt, 0, 24); memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_DISASSOC); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_DISASSOC); skb_put(skb, 2); mgmt->u.disassoc.reason_code = cpu_to_le16(reason); - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); } -static int ieee80211_privacy_mismatch(struct net_device *dev, +static int ieee80211_privacy_mismatch(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct ieee80211_sta_bss *bss; int bss_privacy; int wep_privacy; @@ -981,14 +1002,14 @@ static int ieee80211_privacy_mismatch(struct net_device *dev, if (!ifsta || (ifsta->flags & IEEE80211_STA_MIXED_CELL)) return 0; - bss = ieee80211_rx_bss_get(dev, ifsta->bssid, + bss = ieee80211_rx_bss_get(local, ifsta->bssid, local->hw.conf.channel->center_freq, ifsta->ssid, ifsta->ssid_len); if (!bss) return 0; bss_privacy = !!(bss->capability & WLAN_CAPABILITY_PRIVACY); - wep_privacy = !!ieee80211_sta_wep_configured(dev); + wep_privacy = !!ieee80211_sta_wep_configured(sdata); privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED); ieee80211_rx_bss_put(local, bss); @@ -1000,7 +1021,7 @@ static int ieee80211_privacy_mismatch(struct net_device *dev, } -static void ieee80211_associate(struct net_device *dev, +static void ieee80211_associate(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { DECLARE_MAC_BUF(mac); @@ -1009,31 +1030,31 @@ static void ieee80211_associate(struct net_device *dev, if (ifsta->assoc_tries > IEEE80211_ASSOC_MAX_TRIES) { printk(KERN_DEBUG "%s: association with AP %s" " timed out\n", - dev->name, print_mac(mac, ifsta->bssid)); - ifsta->state = IEEE80211_DISABLED; + sdata->dev->name, print_mac(mac, ifsta->bssid)); + ifsta->state = IEEE80211_STA_MLME_DISABLED; return; } - ifsta->state = IEEE80211_ASSOCIATE; + ifsta->state = IEEE80211_STA_MLME_ASSOCIATE; printk(KERN_DEBUG "%s: associate with AP %s\n", - dev->name, print_mac(mac, ifsta->bssid)); - if (ieee80211_privacy_mismatch(dev, ifsta)) { + sdata->dev->name, print_mac(mac, ifsta->bssid)); + if (ieee80211_privacy_mismatch(sdata, ifsta)) { printk(KERN_DEBUG "%s: mismatch in privacy configuration and " - "mixed-cell disabled - abort association\n", dev->name); - ifsta->state = IEEE80211_DISABLED; + "mixed-cell disabled - abort association\n", sdata->dev->name); + ifsta->state = IEEE80211_STA_MLME_DISABLED; return; } - ieee80211_send_assoc(dev, ifsta); + ieee80211_send_assoc(sdata, ifsta); mod_timer(&ifsta->timer, jiffies + IEEE80211_ASSOC_TIMEOUT); } -static void ieee80211_associated(struct net_device *dev, +static void ieee80211_associated(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sta_info *sta; int disassoc; DECLARE_MAC_BUF(mac); @@ -1043,14 +1064,14 @@ static void ieee80211_associated(struct net_device *dev, * for better APs. */ /* TODO: remove expired BSSes */ - ifsta->state = IEEE80211_ASSOCIATED; + ifsta->state = IEEE80211_STA_MLME_ASSOCIATED; rcu_read_lock(); sta = sta_info_get(local, ifsta->bssid); if (!sta) { printk(KERN_DEBUG "%s: No STA entry for own AP %s\n", - dev->name, print_mac(mac, ifsta->bssid)); + sdata->dev->name, print_mac(mac, ifsta->bssid)); disassoc = 1; } else { disassoc = 0; @@ -1060,11 +1081,11 @@ static void ieee80211_associated(struct net_device *dev, printk(KERN_DEBUG "%s: No ProbeResp from " "current AP %s - assume out of " "range\n", - dev->name, print_mac(mac, ifsta->bssid)); + sdata->dev->name, print_mac(mac, ifsta->bssid)); disassoc = 1; sta_info_unlink(&sta); } else - ieee80211_send_probe_req(dev, ifsta->bssid, + ieee80211_send_probe_req(sdata, ifsta->bssid, local->scan_ssid, local->scan_ssid_len); ifsta->flags ^= IEEE80211_STA_PROBEREQ_POLL; @@ -1073,7 +1094,7 @@ static void ieee80211_associated(struct net_device *dev, if (time_after(jiffies, ifsta->last_probe + IEEE80211_PROBE_INTERVAL)) { ifsta->last_probe = jiffies; - ieee80211_send_probe_req(dev, ifsta->bssid, + ieee80211_send_probe_req(sdata, ifsta->bssid, ifsta->ssid, ifsta->ssid_len); } @@ -1086,8 +1107,8 @@ static void ieee80211_associated(struct net_device *dev, sta_info_destroy(sta); if (disassoc) { - ifsta->state = IEEE80211_DISABLED; - ieee80211_set_associated(dev, ifsta, 0); + ifsta->state = IEEE80211_STA_MLME_DISABLED; + ieee80211_set_associated(sdata, ifsta, 0); } else { mod_timer(&ifsta->timer, jiffies + IEEE80211_MONITORING_INTERVAL); @@ -1095,10 +1116,10 @@ static void ieee80211_associated(struct net_device *dev, } -static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, +static void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, u8 *ssid, size_t ssid_len) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct ieee80211_supported_band *sband; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; @@ -1108,16 +1129,16 @@ static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200); if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer for probe " - "request\n", dev->name); + "request\n", sdata->dev->name); return; } skb_reserve(skb, local->hw.extra_tx_headroom); mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); memset(mgmt, 0, 24); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_PROBE_REQ); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_PROBE_REQ); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); if (dst) { memcpy(mgmt->da, dst, ETH_ALEN); memcpy(mgmt->bssid, dst, ETH_ALEN); @@ -1152,13 +1173,12 @@ static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, *pos = rate->bitrate / 5; } - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); } -static int ieee80211_sta_wep_configured(struct net_device *dev) +static int ieee80211_sta_wep_configured(struct ieee80211_sub_if_data *sdata) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (!sdata || !sdata->default_key || sdata->default_key->conf.alg != ALG_WEP) return 0; @@ -1166,16 +1186,16 @@ static int ieee80211_sta_wep_configured(struct net_device *dev) } -static void ieee80211_auth_completed(struct net_device *dev, +static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { - printk(KERN_DEBUG "%s: authenticated\n", dev->name); + printk(KERN_DEBUG "%s: authenticated\n", sdata->dev->name); ifsta->flags |= IEEE80211_STA_AUTHENTICATED; - ieee80211_associate(dev, ifsta); + ieee80211_associate(sdata, ifsta); } -static void ieee80211_auth_challenge(struct net_device *dev, +static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, struct ieee80211_mgmt *mgmt, size_t len) @@ -1187,17 +1207,16 @@ static void ieee80211_auth_challenge(struct net_device *dev, ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); if (!elems.challenge) return; - ieee80211_send_auth(dev, ifsta, 3, elems.challenge - 2, + ieee80211_send_auth(sdata, ifsta, 3, elems.challenge - 2, elems.challenge_len + 2, 1); } -static void ieee80211_send_addba_resp(struct net_device *dev, u8 *da, u16 tid, +static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, u8 dialog_token, u16 status, u16 policy, u16 buf_size, u16 timeout) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_if_sta *ifsta = &sdata->u.sta; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; u16 capab; @@ -1206,7 +1225,7 @@ static void ieee80211_send_addba_resp(struct net_device *dev, u8 *da, u16 tid, if (!skb) { printk(KERN_DEBUG "%s: failed to allocate buffer " - "for addba resp frame\n", dev->name); + "for addba resp frame\n", sdata->dev->name); return; } @@ -1214,13 +1233,13 @@ static void ieee80211_send_addba_resp(struct net_device *dev, u8 *da, u16 tid, mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); memset(mgmt, 0, 24); memcpy(mgmt->da, da, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); if (sdata->vif.type == IEEE80211_IF_TYPE_AP) - memcpy(mgmt->bssid, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); else memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_ACTION); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION); skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_resp)); mgmt->u.action.category = WLAN_CATEGORY_BACK; @@ -1235,17 +1254,16 @@ static void ieee80211_send_addba_resp(struct net_device *dev, u8 *da, u16 tid, mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout); mgmt->u.action.u.addba_resp.status = cpu_to_le16(status); - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); return; } -void ieee80211_send_addba_request(struct net_device *dev, const u8 *da, +void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, const u8 *da, u16 tid, u8 dialog_token, u16 start_seq_num, u16 agg_size, u16 timeout) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; struct ieee80211_if_sta *ifsta = &sdata->u.sta; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; @@ -1255,21 +1273,21 @@ void ieee80211_send_addba_request(struct net_device *dev, const u8 *da, if (!skb) { printk(KERN_ERR "%s: failed to allocate buffer " - "for addba request frame\n", dev->name); + "for addba request frame\n", sdata->dev->name); return; } skb_reserve(skb, local->hw.extra_tx_headroom); mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); memset(mgmt, 0, 24); memcpy(mgmt->da, da, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); if (sdata->vif.type == IEEE80211_IF_TYPE_AP) - memcpy(mgmt->bssid, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); else memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_ACTION); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION); skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_req)); @@ -1287,14 +1305,13 @@ void ieee80211_send_addba_request(struct net_device *dev, const u8 *da, mgmt->u.action.u.addba_req.start_seq_num = cpu_to_le16(start_seq_num << 4); - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); } -static void ieee80211_sta_process_addba_request(struct net_device *dev, +static void ieee80211_sta_process_addba_request(struct ieee80211_local *local, struct ieee80211_mgmt *mgmt, size_t len) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_hw *hw = &local->hw; struct ieee80211_conf *conf = &hw->conf; struct sta_info *sta; @@ -1426,16 +1443,15 @@ end: spin_unlock_bh(&sta->lock); end_no_lock: - ieee80211_send_addba_resp(sta->sdata->dev, sta->addr, tid, + ieee80211_send_addba_resp(sta->sdata, sta->addr, tid, dialog_token, status, 1, buf_size, timeout); rcu_read_unlock(); } -static void ieee80211_sta_process_addba_resp(struct net_device *dev, +static void ieee80211_sta_process_addba_resp(struct ieee80211_local *local, struct ieee80211_mgmt *mgmt, size_t len) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_hw *hw = &local->hw; struct sta_info *sta; u16 capab; @@ -1497,11 +1513,10 @@ addba_resp_exit: rcu_read_unlock(); } -void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid, +void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, const u8 *da, u16 tid, u16 initiator, u16 reason_code) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; struct ieee80211_if_sta *ifsta = &sdata->u.sta; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; @@ -1511,7 +1526,7 @@ void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid, if (!skb) { printk(KERN_ERR "%s: failed to allocate buffer " - "for delba frame\n", dev->name); + "for delba frame\n", sdata->dev->name); return; } @@ -1519,13 +1534,13 @@ void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid, mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); memset(mgmt, 0, 24); memcpy(mgmt->da, da, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); if (sdata->vif.type == IEEE80211_IF_TYPE_AP) - memcpy(mgmt->bssid, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); else memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_ACTION); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION); skb_put(skb, 1 + sizeof(mgmt->u.action.u.delba)); @@ -1537,12 +1552,12 @@ void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid, mgmt->u.action.u.delba.params = cpu_to_le16(params); mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code); - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); } -void ieee80211_send_bar(struct net_device *dev, u8 *ra, u16 tid, u16 ssn) +void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct ieee80211_bar *bar; u16 bar_control = 0; @@ -1550,29 +1565,29 @@ void ieee80211_send_bar(struct net_device *dev, u8 *ra, u16 tid, u16 ssn) skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom); if (!skb) { printk(KERN_ERR "%s: failed to allocate buffer for " - "bar frame\n", dev->name); + "bar frame\n", sdata->dev->name); return; } skb_reserve(skb, local->hw.extra_tx_headroom); bar = (struct ieee80211_bar *)skb_put(skb, sizeof(*bar)); memset(bar, 0, sizeof(*bar)); - bar->frame_control = IEEE80211_FC(IEEE80211_FTYPE_CTL, - IEEE80211_STYPE_BACK_REQ); + bar->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | + IEEE80211_STYPE_BACK_REQ); memcpy(bar->ra, ra, ETH_ALEN); - memcpy(bar->ta, dev->dev_addr, ETH_ALEN); + memcpy(bar->ta, sdata->dev->dev_addr, ETH_ALEN); bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL; bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA; bar_control |= (u16)(tid << 12); bar->control = cpu_to_le16(bar_control); bar->start_seq_num = cpu_to_le16(ssn); - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); } -void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid, +void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 initiator, u16 reason) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct ieee80211_hw *hw = &local->hw; struct sta_info *sta; int ret, i; @@ -1620,7 +1635,7 @@ void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid, /* check if this is a self generated aggregation halt */ if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER) - ieee80211_send_delba(dev, ra, tid, 0, reason); + ieee80211_send_delba(sdata, ra, tid, 0, reason); /* free the reordering buffer */ for (i = 0; i < sta->ampdu_mlme.tid_rx[tid]->buf_size; i++) { @@ -1641,10 +1656,10 @@ void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid, } -static void ieee80211_sta_process_delba(struct net_device *dev, +static void ieee80211_sta_process_delba(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sta_info *sta; u16 tid, params; u16 initiator; @@ -1671,7 +1686,7 @@ static void ieee80211_sta_process_delba(struct net_device *dev, #endif /* CONFIG_MAC80211_HT_DEBUG */ if (initiator == WLAN_BACK_INITIATOR) - ieee80211_sta_stop_rx_ba_session(dev, sta->addr, tid, + ieee80211_sta_stop_rx_ba_session(sdata, sta->addr, tid, WLAN_BACK_INITIATOR, 0); else { /* WLAN_BACK_RECIPIENT */ spin_lock_bh(&sta->lock); @@ -1758,31 +1773,31 @@ static void sta_rx_agg_session_timer_expired(unsigned long data) #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); #endif - ieee80211_sta_stop_rx_ba_session(sta->sdata->dev, sta->addr, + ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->addr, (u16)*ptid, WLAN_BACK_TIMER, WLAN_REASON_QSTA_TIMEOUT); } -void ieee80211_sta_tear_down_BA_sessions(struct net_device *dev, u8 *addr) +void ieee80211_sta_tear_down_BA_sessions(struct ieee80211_sub_if_data *sdata, u8 *addr) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; int i; for (i = 0; i < STA_TID_NUM; i++) { ieee80211_stop_tx_ba_session(&local->hw, addr, i, WLAN_BACK_INITIATOR); - ieee80211_sta_stop_rx_ba_session(dev, addr, i, + ieee80211_sta_stop_rx_ba_session(sdata, addr, i, WLAN_BACK_RECIPIENT, WLAN_REASON_QSTA_LEAVE_QBSS); } } -static void ieee80211_send_refuse_measurement_request(struct net_device *dev, +static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_data *sdata, struct ieee80211_msrment_ie *request_ie, const u8 *da, const u8 *bssid, u8 dialog_token) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sk_buff *skb; struct ieee80211_mgmt *msr_report; @@ -1791,7 +1806,7 @@ static void ieee80211_send_refuse_measurement_request(struct net_device *dev, if (!skb) { printk(KERN_ERR "%s: failed to allocate buffer for " - "measurement report frame\n", dev->name); + "measurement report frame\n", sdata->dev->name); return; } @@ -1799,9 +1814,9 @@ static void ieee80211_send_refuse_measurement_request(struct net_device *dev, msr_report = (struct ieee80211_mgmt *)skb_put(skb, 24); memset(msr_report, 0, 24); memcpy(msr_report->da, da, ETH_ALEN); - memcpy(msr_report->sa, dev->dev_addr, ETH_ALEN); + memcpy(msr_report->sa, sdata->dev->dev_addr, ETH_ALEN); memcpy(msr_report->bssid, bssid, ETH_ALEN); - msr_report->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, + msr_report->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION); skb_put(skb, 1 + sizeof(msr_report->u.action.u.measurement)); @@ -1821,10 +1836,10 @@ static void ieee80211_send_refuse_measurement_request(struct net_device *dev, IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED; msr_report->u.action.u.measurement.msr_elem.type = request_ie->type; - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); } -static void ieee80211_sta_process_measurement_req(struct net_device *dev, +static void ieee80211_sta_process_measurement_req(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len) { @@ -1835,23 +1850,22 @@ static void ieee80211_sta_process_measurement_req(struct net_device *dev, * For now just refuse * TODO: Answer basic measurement as unmeasured */ - ieee80211_send_refuse_measurement_request(dev, + ieee80211_send_refuse_measurement_request(sdata, &mgmt->u.action.u.measurement.msr_elem, mgmt->sa, mgmt->bssid, mgmt->u.action.u.measurement.dialog_token); } -static void ieee80211_rx_mgmt_auth(struct net_device *dev, +static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, struct ieee80211_mgmt *mgmt, size_t len) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); u16 auth_alg, auth_transaction, status_code; DECLARE_MAC_BUF(mac); - if (ifsta->state != IEEE80211_AUTHENTICATE && + if (ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE && sdata->vif.type != IEEE80211_IF_TYPE_IBSS) return; @@ -1879,7 +1893,7 @@ static void ieee80211_rx_mgmt_auth(struct net_device *dev, */ if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) return; - ieee80211_send_auth(dev, ifsta, 2, NULL, 0, 0); + ieee80211_send_auth(sdata, ifsta, 2, NULL, 0, 0); } if (auth_alg != ifsta->auth_alg || @@ -1912,7 +1926,7 @@ static void ieee80211_rx_mgmt_auth(struct net_device *dev, algs[pos] == 0xff) continue; if (algs[pos] == WLAN_AUTH_SHARED_KEY && - !ieee80211_sta_wep_configured(dev)) + !ieee80211_sta_wep_configured(sdata)) continue; ifsta->auth_alg = algs[pos]; break; @@ -1924,19 +1938,19 @@ static void ieee80211_rx_mgmt_auth(struct net_device *dev, switch (ifsta->auth_alg) { case WLAN_AUTH_OPEN: case WLAN_AUTH_LEAP: - ieee80211_auth_completed(dev, ifsta); + ieee80211_auth_completed(sdata, ifsta); break; case WLAN_AUTH_SHARED_KEY: if (ifsta->auth_transaction == 4) - ieee80211_auth_completed(dev, ifsta); + ieee80211_auth_completed(sdata, ifsta); else - ieee80211_auth_challenge(dev, ifsta, mgmt, len); + ieee80211_auth_challenge(sdata, ifsta, mgmt, len); break; } } -static void ieee80211_rx_mgmt_deauth(struct net_device *dev, +static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, struct ieee80211_mgmt *mgmt, size_t len) @@ -1953,22 +1967,22 @@ static void ieee80211_rx_mgmt_deauth(struct net_device *dev, reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); if (ifsta->flags & IEEE80211_STA_AUTHENTICATED) - printk(KERN_DEBUG "%s: deauthenticated\n", dev->name); + printk(KERN_DEBUG "%s: deauthenticated\n", sdata->dev->name); - if (ifsta->state == IEEE80211_AUTHENTICATE || - ifsta->state == IEEE80211_ASSOCIATE || - ifsta->state == IEEE80211_ASSOCIATED) { - ifsta->state = IEEE80211_AUTHENTICATE; + if (ifsta->state == IEEE80211_STA_MLME_AUTHENTICATE || + ifsta->state == IEEE80211_STA_MLME_ASSOCIATE || + ifsta->state == IEEE80211_STA_MLME_ASSOCIATED) { + ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE; mod_timer(&ifsta->timer, jiffies + IEEE80211_RETRY_AUTH_INTERVAL); } - ieee80211_set_disassoc(dev, ifsta, 1); + ieee80211_set_disassoc(sdata, ifsta, 1); ifsta->flags &= ~IEEE80211_STA_AUTHENTICATED; } -static void ieee80211_rx_mgmt_disassoc(struct net_device *dev, +static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, struct ieee80211_mgmt *mgmt, size_t len) @@ -1985,15 +1999,15 @@ static void ieee80211_rx_mgmt_disassoc(struct net_device *dev, reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); if (ifsta->flags & IEEE80211_STA_ASSOCIATED) - printk(KERN_DEBUG "%s: disassociated\n", dev->name); + printk(KERN_DEBUG "%s: disassociated\n", sdata->dev->name); - if (ifsta->state == IEEE80211_ASSOCIATED) { - ifsta->state = IEEE80211_ASSOCIATE; + if (ifsta->state == IEEE80211_STA_MLME_ASSOCIATED) { + ifsta->state = IEEE80211_STA_MLME_ASSOCIATE; mod_timer(&ifsta->timer, jiffies + IEEE80211_RETRY_AUTH_INTERVAL); } - ieee80211_set_disassoc(dev, ifsta, 0); + ieee80211_set_disassoc(sdata, ifsta, 0); } @@ -2004,7 +2018,6 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, int reassoc) { struct ieee80211_local *local = sdata->local; - struct net_device *dev = sdata->dev; struct ieee80211_supported_band *sband; struct sta_info *sta; u64 rates, basic_rates; @@ -2019,7 +2032,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, /* AssocResp and ReassocResp have identical structure, so process both * of them in this function. */ - if (ifsta->state != IEEE80211_ASSOCIATE) + if (ifsta->state != IEEE80211_STA_MLME_ASSOCIATE) return; if (len < 24 + 6) @@ -2034,12 +2047,12 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, printk(KERN_DEBUG "%s: RX %sssocResp from %s (capab=0x%x " "status=%d aid=%d)\n", - dev->name, reassoc ? "Rea" : "A", print_mac(mac, mgmt->sa), + sdata->dev->name, reassoc ? "Rea" : "A", print_mac(mac, mgmt->sa), capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); if (status_code != WLAN_STATUS_SUCCESS) { printk(KERN_DEBUG "%s: AP denied association (code=%d)\n", - dev->name, status_code); + sdata->dev->name, status_code); /* if this was a reassociation, ensure we try a "full" * association next time. This works around some broken APs * which do not correctly reject reassociation requests. */ @@ -2049,7 +2062,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not " - "set\n", dev->name, aid); + "set\n", sdata->dev->name, aid); aid &= ~(BIT(15) | BIT(14)); pos = mgmt->u.assoc_resp.variable; @@ -2057,11 +2070,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, if (!elems.supp_rates) { printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", - dev->name); + sdata->dev->name); return; } - printk(KERN_DEBUG "%s: associated\n", dev->name); + printk(KERN_DEBUG "%s: associated\n", sdata->dev->name); ifsta->aid = aid; ifsta->ap_capab = capab_info; @@ -2082,11 +2095,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, sta = sta_info_alloc(sdata, ifsta->bssid, GFP_ATOMIC); if (!sta) { printk(KERN_DEBUG "%s: failed to alloc STA entry for" - " the AP\n", dev->name); + " the AP\n", sdata->dev->name); rcu_read_unlock(); return; } - bss = ieee80211_rx_bss_get(dev, ifsta->bssid, + bss = ieee80211_rx_bss_get(local, ifsta->bssid, local->hw.conf.channel->center_freq, ifsta->ssid, ifsta->ssid_len); if (bss) { @@ -2099,7 +2112,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, err = sta_info_insert(sta); if (err) { printk(KERN_DEBUG "%s: failed to insert STA entry for" - " the AP (error %d)\n", dev->name, err); + " the AP (error %d)\n", sdata->dev->name, err); rcu_read_unlock(); return; } @@ -2179,7 +2192,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, if (elems.wmm_param) { set_sta_flags(sta, WLAN_STA_WME); rcu_read_unlock(); - ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param, + ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param, elems.wmm_param_len); } else rcu_read_unlock(); @@ -2188,17 +2201,16 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, * ieee80211_set_associated() will tell the driver */ bss_conf->aid = aid; bss_conf->assoc_capability = capab_info; - ieee80211_set_associated(dev, ifsta, 1); + ieee80211_set_associated(sdata, ifsta, 1); - ieee80211_associated(dev, ifsta); + ieee80211_associated(sdata, ifsta); } /* Caller must hold local->sta_bss_lock */ -static void __ieee80211_rx_bss_hash_add(struct net_device *dev, +static void __ieee80211_rx_bss_hash_add(struct ieee80211_local *local, struct ieee80211_sta_bss *bss) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); u8 hash_idx; if (bss_mesh_cfg(bss)) @@ -2234,10 +2246,10 @@ static void __ieee80211_rx_bss_hash_del(struct ieee80211_local *local, static struct ieee80211_sta_bss * -ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int freq, +ieee80211_rx_bss_add(struct ieee80211_sub_if_data *sdata, u8 *bssid, int freq, u8 *ssid, u8 ssid_len) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct ieee80211_sta_bss *bss; bss = kzalloc(sizeof(*bss), GFP_ATOMIC); @@ -2255,16 +2267,15 @@ ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int freq, spin_lock_bh(&local->sta_bss_lock); /* TODO: order by RSSI? */ list_add_tail(&bss->list, &local->sta_bss_list); - __ieee80211_rx_bss_hash_add(dev, bss); + __ieee80211_rx_bss_hash_add(local, bss); spin_unlock_bh(&local->sta_bss_lock); return bss; } static struct ieee80211_sta_bss * -ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int freq, +ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, u8 *ssid, u8 ssid_len) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sta_bss *bss; spin_lock_bh(&local->sta_bss_lock); @@ -2286,10 +2297,9 @@ ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int freq, #ifdef CONFIG_MAC80211_MESH static struct ieee80211_sta_bss * -ieee80211_rx_mesh_bss_get(struct net_device *dev, u8 *mesh_id, int mesh_id_len, +ieee80211_rx_mesh_bss_get(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len, u8 *mesh_cfg, int freq) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sta_bss *bss; spin_lock_bh(&local->sta_bss_lock); @@ -2311,10 +2321,9 @@ ieee80211_rx_mesh_bss_get(struct net_device *dev, u8 *mesh_id, int mesh_id_len, } static struct ieee80211_sta_bss * -ieee80211_rx_mesh_bss_add(struct net_device *dev, u8 *mesh_id, int mesh_id_len, +ieee80211_rx_mesh_bss_add(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len, u8 *mesh_cfg, int mesh_config_len, int freq) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sta_bss *bss; if (mesh_config_len != MESH_CFG_LEN) @@ -2348,7 +2357,7 @@ ieee80211_rx_mesh_bss_add(struct net_device *dev, u8 *mesh_id, int mesh_id_len, spin_lock_bh(&local->sta_bss_lock); /* TODO: order by RSSI? */ list_add_tail(&bss->list, &local->sta_bss_list); - __ieee80211_rx_bss_hash_add(dev, bss); + __ieee80211_rx_bss_hash_add(local, bss); spin_unlock_bh(&local->sta_bss_lock); return bss; } @@ -2356,11 +2365,7 @@ ieee80211_rx_mesh_bss_add(struct net_device *dev, u8 *mesh_id, int mesh_id_len, static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss) { - kfree(bss->wpa_ie); - kfree(bss->rsn_ie); - kfree(bss->wmm_ie); - kfree(bss->ht_ie); - kfree(bss->ht_add_ie); + kfree(bss->ies); kfree(bss_mesh_id(bss)); kfree(bss_mesh_cfg(bss)); kfree(bss); @@ -2399,23 +2404,20 @@ void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local) } -static int ieee80211_sta_join_ibss(struct net_device *dev, +static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, struct ieee80211_sta_bss *bss) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; int res, rates, i, j; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; u8 *pos; - struct ieee80211_sub_if_data *sdata; struct ieee80211_supported_band *sband; union iwreq_data wrqu; sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - /* Remove possible STA entries from other IBSS networks. */ sta_info_flush_delayed(sdata); @@ -2433,7 +2435,7 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, sdata->drop_unencrypted = bss->capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; - res = ieee80211_set_freq(dev, bss->freq); + res = ieee80211_set_freq(sdata, bss->freq); if (res) return res; @@ -2446,10 +2448,10 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + sizeof(mgmt->u.beacon)); memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); - mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, - IEEE80211_STYPE_PROBE_RESP); + mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_PROBE_RESP); memset(mgmt->da, 0xff, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); + memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); mgmt->u.beacon.beacon_int = cpu_to_le16(local->hw.conf.beacon_int); @@ -2506,14 +2508,14 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, } ifsta->supp_rates_bits[local->hw.conf.channel->band] = rates; - ieee80211_sta_def_wmm_params(dev, bss, 1); + ieee80211_sta_def_wmm_params(sdata, bss, 1); - ifsta->state = IEEE80211_IBSS_JOINED; + ifsta->state = IEEE80211_STA_MLME_IBSS_JOINED; mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); memset(&wrqu, 0, sizeof(wrqu)); memcpy(wrqu.ap_addr.sa_data, bss->bssid, ETH_ALEN); - wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); + wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL); return res; } @@ -2554,55 +2556,91 @@ u64 ieee80211_sta_get_rates(struct ieee80211_local *local, return supp_rates; } +static u64 ieee80211_sta_get_mandatory_rates(struct ieee80211_local *local, + enum ieee80211_band band) +{ + struct ieee80211_supported_band *sband; + struct ieee80211_rate *bitrates; + u64 mandatory_rates; + enum ieee80211_rate_flags mandatory_flag; + int i; + + sband = local->hw.wiphy->bands[band]; + if (!sband) { + WARN_ON(1); + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + } -static void ieee80211_rx_bss_info(struct net_device *dev, + if (band == IEEE80211_BAND_2GHZ) + mandatory_flag = IEEE80211_RATE_MANDATORY_B; + else + mandatory_flag = IEEE80211_RATE_MANDATORY_A; + + bitrates = sband->bitrates; + mandatory_rates = 0; + for (i = 0; i < sband->n_bitrates; i++) + if (bitrates[i].flags & mandatory_flag) + mandatory_rates |= BIT(i); + return mandatory_rates; +} + +static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_rx_status *rx_status, - struct ieee802_11_elems *elems, - int beacon) + struct ieee802_11_elems *elems) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; int freq, clen; struct ieee80211_sta_bss *bss; struct sta_info *sta; - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - u64 beacon_timestamp, rx_timestamp; struct ieee80211_channel *channel; + u64 beacon_timestamp, rx_timestamp; + u64 supp_rates = 0; + bool beacon = ieee80211_is_beacon(mgmt->frame_control); + enum ieee80211_band band = rx_status->band; DECLARE_MAC_BUF(mac); DECLARE_MAC_BUF(mac2); - if (!beacon && memcmp(mgmt->da, dev->dev_addr, ETH_ALEN)) - return; /* ignore ProbeResp to foreign address */ - beacon_timestamp = le64_to_cpu(mgmt->u.beacon.timestamp); if (ieee80211_vif_is_mesh(&sdata->vif) && elems->mesh_id && - elems->mesh_config && mesh_matches_local(elems, dev)) { - u64 rates = ieee80211_sta_get_rates(local, elems, - rx_status->band); + elems->mesh_config && mesh_matches_local(elems, sdata)) { + supp_rates = ieee80211_sta_get_rates(local, elems, band); - mesh_neighbour_update(mgmt->sa, rates, dev, - mesh_peer_accepts_plinks(elems, dev)); + mesh_neighbour_update(mgmt->sa, supp_rates, sdata, + mesh_peer_accepts_plinks(elems)); } rcu_read_lock(); if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems->supp_rates && - memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 && - (sta = sta_info_get(local, mgmt->sa))) { - u64 prev_rates; - u64 supp_rates = ieee80211_sta_get_rates(local, elems, - rx_status->band); - - prev_rates = sta->supp_rates[rx_status->band]; - sta->supp_rates[rx_status->band] &= supp_rates; - if (sta->supp_rates[rx_status->band] == 0) { - /* No matching rates - this should not really happen. - * Make sure that at least one rate is marked - * supported to avoid issues with TX rate ctrl. */ - sta->supp_rates[rx_status->band] = - sdata->u.sta.supp_rates_bits[rx_status->band]; + memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) { + + supp_rates = ieee80211_sta_get_rates(local, elems, band); + + sta = sta_info_get(local, mgmt->sa); + if (sta) { + u64 prev_rates; + + prev_rates = sta->supp_rates[band]; + /* make sure mandatory rates are always added */ + sta->supp_rates[band] = supp_rates | + ieee80211_sta_get_mandatory_rates(local, band); + +#ifdef CONFIG_MAC80211_IBSS_DEBUG + if (sta->supp_rates[band] != prev_rates) + printk(KERN_DEBUG "%s: updated supp_rates set " + "for %s based on beacon info (0x%llx | " + "0x%llx -> 0x%llx)\n", + sdata->dev->name, print_mac(mac, sta->addr), + (unsigned long long) prev_rates, + (unsigned long long) supp_rates, + (unsigned long long) sta->supp_rates[band]); +#endif + } else { + ieee80211_ibss_add_sta(sdata, NULL, mgmt->bssid, + mgmt->sa, supp_rates); } } @@ -2620,21 +2658,21 @@ static void ieee80211_rx_bss_info(struct net_device *dev, #ifdef CONFIG_MAC80211_MESH if (elems->mesh_config) - bss = ieee80211_rx_mesh_bss_get(dev, elems->mesh_id, + bss = ieee80211_rx_mesh_bss_get(local, elems->mesh_id, elems->mesh_id_len, elems->mesh_config, freq); else #endif - bss = ieee80211_rx_bss_get(dev, mgmt->bssid, freq, + bss = ieee80211_rx_bss_get(local, mgmt->bssid, freq, elems->ssid, elems->ssid_len); if (!bss) { #ifdef CONFIG_MAC80211_MESH if (elems->mesh_config) - bss = ieee80211_rx_mesh_bss_add(dev, elems->mesh_id, + bss = ieee80211_rx_mesh_bss_add(local, elems->mesh_id, elems->mesh_id_len, elems->mesh_config, elems->mesh_config_len, freq); else #endif - bss = ieee80211_rx_bss_add(dev, mgmt->bssid, freq, + bss = ieee80211_rx_bss_add(sdata, mgmt->bssid, freq, elems->ssid, elems->ssid_len); if (!bss) return; @@ -2653,43 +2691,6 @@ static void ieee80211_rx_bss_info(struct net_device *dev, bss->has_erp_value = 1; } - if (elems->ht_cap_elem && - (!bss->ht_ie || bss->ht_ie_len != elems->ht_cap_elem_len || - memcmp(bss->ht_ie, elems->ht_cap_elem, elems->ht_cap_elem_len))) { - kfree(bss->ht_ie); - bss->ht_ie = kmalloc(elems->ht_cap_elem_len + 2, GFP_ATOMIC); - if (bss->ht_ie) { - memcpy(bss->ht_ie, elems->ht_cap_elem - 2, - elems->ht_cap_elem_len + 2); - bss->ht_ie_len = elems->ht_cap_elem_len + 2; - } else - bss->ht_ie_len = 0; - } else if (!elems->ht_cap_elem && bss->ht_ie) { - kfree(bss->ht_ie); - bss->ht_ie = NULL; - bss->ht_ie_len = 0; - } - - if (elems->ht_info_elem && - (!bss->ht_add_ie || - bss->ht_add_ie_len != elems->ht_info_elem_len || - memcmp(bss->ht_add_ie, elems->ht_info_elem, - elems->ht_info_elem_len))) { - kfree(bss->ht_add_ie); - bss->ht_add_ie = - kmalloc(elems->ht_info_elem_len + 2, GFP_ATOMIC); - if (bss->ht_add_ie) { - memcpy(bss->ht_add_ie, elems->ht_info_elem - 2, - elems->ht_info_elem_len + 2); - bss->ht_add_ie_len = elems->ht_info_elem_len + 2; - } else - bss->ht_add_ie_len = 0; - } else if (!elems->ht_info_elem && bss->ht_add_ie) { - kfree(bss->ht_add_ie); - bss->ht_add_ie = NULL; - bss->ht_add_ie_len = 0; - } - bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); @@ -2721,108 +2722,36 @@ static void ieee80211_rx_bss_info(struct net_device *dev, bss->supp_rates_len += clen; } - bss->band = rx_status->band; + bss->band = band; bss->timestamp = beacon_timestamp; bss->last_update = jiffies; bss->signal = rx_status->signal; bss->noise = rx_status->noise; bss->qual = rx_status->qual; - if (!beacon && !bss->probe_resp) - bss->probe_resp = true; - + if (!beacon) + bss->last_probe_resp = jiffies; /* * In STA mode, the remaining parameters should not be overridden * by beacons because they're not necessarily accurate there. */ if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS && - bss->probe_resp && beacon) { + bss->last_probe_resp && beacon) { ieee80211_rx_bss_put(local, bss); return; } - if (elems->wpa && - (!bss->wpa_ie || bss->wpa_ie_len != elems->wpa_len || - memcmp(bss->wpa_ie, elems->wpa, elems->wpa_len))) { - kfree(bss->wpa_ie); - bss->wpa_ie = kmalloc(elems->wpa_len + 2, GFP_ATOMIC); - if (bss->wpa_ie) { - memcpy(bss->wpa_ie, elems->wpa - 2, elems->wpa_len + 2); - bss->wpa_ie_len = elems->wpa_len + 2; - } else - bss->wpa_ie_len = 0; - } else if (!elems->wpa && bss->wpa_ie) { - kfree(bss->wpa_ie); - bss->wpa_ie = NULL; - bss->wpa_ie_len = 0; - } - - if (elems->rsn && - (!bss->rsn_ie || bss->rsn_ie_len != elems->rsn_len || - memcmp(bss->rsn_ie, elems->rsn, elems->rsn_len))) { - kfree(bss->rsn_ie); - bss->rsn_ie = kmalloc(elems->rsn_len + 2, GFP_ATOMIC); - if (bss->rsn_ie) { - memcpy(bss->rsn_ie, elems->rsn - 2, elems->rsn_len + 2); - bss->rsn_ie_len = elems->rsn_len + 2; - } else - bss->rsn_ie_len = 0; - } else if (!elems->rsn && bss->rsn_ie) { - kfree(bss->rsn_ie); - bss->rsn_ie = NULL; - bss->rsn_ie_len = 0; + if (bss->ies == NULL || bss->ies_len < elems->total_len) { + kfree(bss->ies); + bss->ies = kmalloc(elems->total_len, GFP_ATOMIC); } + if (bss->ies) { + memcpy(bss->ies, elems->ie_start, elems->total_len); + bss->ies_len = elems->total_len; + } else + bss->ies_len = 0; - /* - * Cf. - * http://www.wipo.int/pctdb/en/wo.jsp?wo=2007047181&IA=WO2007047181&DISPLAY=DESC - * - * quoting: - * - * In particular, "Wi-Fi CERTIFIED for WMM - Support for Multimedia - * Applications with Quality of Service in Wi-Fi Networks," Wi- Fi - * Alliance (September 1, 2004) is incorporated by reference herein. - * The inclusion of the WMM Parameters in probe responses and - * association responses is mandatory for WMM enabled networks. The - * inclusion of the WMM Parameters in beacons, however, is optional. - */ - - if (elems->wmm_param && - (!bss->wmm_ie || bss->wmm_ie_len != elems->wmm_param_len || - memcmp(bss->wmm_ie, elems->wmm_param, elems->wmm_param_len))) { - kfree(bss->wmm_ie); - bss->wmm_ie = kmalloc(elems->wmm_param_len + 2, GFP_ATOMIC); - if (bss->wmm_ie) { - memcpy(bss->wmm_ie, elems->wmm_param - 2, - elems->wmm_param_len + 2); - bss->wmm_ie_len = elems->wmm_param_len + 2; - } else - bss->wmm_ie_len = 0; - } else if (elems->wmm_info && - (!bss->wmm_ie || bss->wmm_ie_len != elems->wmm_info_len || - memcmp(bss->wmm_ie, elems->wmm_info, - elems->wmm_info_len))) { - /* As for certain AP's Fifth bit is not set in WMM IE in - * beacon frames.So while parsing the beacon frame the - * wmm_info structure is used instead of wmm_param. - * wmm_info structure was never used to set bss->wmm_ie. - * This code fixes this problem by copying the WME - * information from wmm_info to bss->wmm_ie and enabling - * n-band association. - */ - kfree(bss->wmm_ie); - bss->wmm_ie = kmalloc(elems->wmm_info_len + 2, GFP_ATOMIC); - if (bss->wmm_ie) { - memcpy(bss->wmm_ie, elems->wmm_info - 2, - elems->wmm_info_len + 2); - bss->wmm_ie_len = elems->wmm_info_len + 2; - } else - bss->wmm_ie_len = 0; - } else if (!elems->wmm_param && !elems->wmm_info && bss->wmm_ie) { - kfree(bss->wmm_ie); - bss->wmm_ie = NULL; - bss->wmm_ie_len = 0; - } + bss->wmm_used = elems->wmm_param || elems->wmm_info; /* check if we need to merge IBSS */ if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && beacon && @@ -2848,7 +2777,7 @@ static void ieee80211_rx_bss_info(struct net_device *dev, * e.g: at 1 MBit that means mactime is 192 usec earlier * (=24 bytes * 8 usecs/byte) than the beacon timestamp. */ - int rate = local->hw.wiphy->bands[rx_status->band]-> + int rate = local->hw.wiphy->bands[band]-> bitrates[rx_status->rate_idx].bitrate; rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate); } else if (local && local->ops && local->ops->get_tsf) @@ -2871,12 +2800,12 @@ static void ieee80211_rx_bss_info(struct net_device *dev, #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG "%s: beacon TSF higher than " "local TSF - IBSS merge with BSSID %s\n", - dev->name, print_mac(mac, mgmt->bssid)); + sdata->dev->name, print_mac(mac, mgmt->bssid)); #endif - ieee80211_sta_join_ibss(dev, &sdata->u.sta, bss); - ieee80211_ibss_add_sta(dev, NULL, + ieee80211_sta_join_ibss(sdata, &sdata->u.sta, bss); + ieee80211_ibss_add_sta(sdata, NULL, mgmt->bssid, mgmt->sa, - BIT(rx_status->rate_idx)); + supp_rates); } } @@ -2884,13 +2813,17 @@ static void ieee80211_rx_bss_info(struct net_device *dev, } -static void ieee80211_rx_mgmt_probe_resp(struct net_device *dev, +static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_rx_status *rx_status) { size_t baselen; struct ieee802_11_elems elems; + struct ieee80211_if_sta *ifsta = &sdata->u.sta; + + if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN)) + return; /* ignore ProbeResp to foreign address */ baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; if (baselen > len) @@ -2899,20 +2832,27 @@ static void ieee80211_rx_mgmt_probe_resp(struct net_device *dev, ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, &elems); - ieee80211_rx_bss_info(dev, mgmt, len, rx_status, &elems, 0); + ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems); + + /* direct probe may be part of the association flow */ + if (test_and_clear_bit(IEEE80211_STA_REQ_DIRECT_PROBE, + &ifsta->request)) { + printk(KERN_DEBUG "%s direct probe responded\n", + sdata->dev->name); + ieee80211_authenticate(sdata, ifsta); + } } -static void ieee80211_rx_mgmt_beacon(struct net_device *dev, +static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_rx_status *rx_status) { - struct ieee80211_sub_if_data *sdata; struct ieee80211_if_sta *ifsta; size_t baselen; struct ieee802_11_elems elems; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct ieee80211_conf *conf = &local->hw.conf; u32 changed = 0; @@ -2923,9 +2863,8 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev, ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems); - ieee80211_rx_bss_info(dev, mgmt, len, rx_status, &elems, 1); + ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems); - sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type != IEEE80211_IF_TYPE_STA) return; ifsta = &sdata->u.sta; @@ -2934,7 +2873,7 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev, memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0) return; - ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param, + ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param, elems.wmm_param_len); /* Do not send changes to driver if we are scanning. This removes @@ -2966,14 +2905,13 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev, } -static void ieee80211_rx_mgmt_probe_req(struct net_device *dev, +static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_rx_status *rx_status) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; int tx_last_beacon; struct sk_buff *skb; struct ieee80211_mgmt *resp; @@ -2985,7 +2923,7 @@ static void ieee80211_rx_mgmt_probe_req(struct net_device *dev, #endif if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS || - ifsta->state != IEEE80211_IBSS_JOINED || + ifsta->state != IEEE80211_STA_MLME_IBSS_JOINED || len < 24 + 2 || !ifsta->probe_resp) return; @@ -2997,7 +2935,7 @@ static void ieee80211_rx_mgmt_probe_req(struct net_device *dev, #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG "%s: RX ProbeReq SA=%s DA=%s BSSID=" "%s (tx_last_beacon=%d)\n", - dev->name, print_mac(mac, mgmt->sa), print_mac(mac2, mgmt->da), + sdata->dev->name, print_mac(mac, mgmt->sa), print_mac(mac2, mgmt->da), print_mac(mac3, mgmt->bssid), tx_last_beacon); #endif /* CONFIG_MAC80211_IBSS_DEBUG */ @@ -3015,7 +2953,7 @@ static void ieee80211_rx_mgmt_probe_req(struct net_device *dev, #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG "%s: Invalid SSID IE in ProbeReq " "from %s\n", - dev->name, print_mac(mac, mgmt->sa)); + sdata->dev->name, print_mac(mac, mgmt->sa)); #endif return; } @@ -3035,19 +2973,18 @@ static void ieee80211_rx_mgmt_probe_req(struct net_device *dev, memcpy(resp->da, mgmt->sa, ETH_ALEN); #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG "%s: Sending ProbeResp to %s\n", - dev->name, print_mac(mac, resp->da)); + sdata->dev->name, print_mac(mac, resp->da)); #endif /* CONFIG_MAC80211_IBSS_DEBUG */ - ieee80211_sta_tx(dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); } -static void ieee80211_rx_mgmt_action(struct net_device *dev, +static void ieee80211_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta, struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_rx_status *rx_status) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; if (len < IEEE80211_MIN_ACTION_SIZE) return; @@ -3061,7 +2998,7 @@ static void ieee80211_rx_mgmt_action(struct net_device *dev, if (len < (IEEE80211_MIN_ACTION_SIZE + sizeof(mgmt->u.action.u.measurement))) break; - ieee80211_sta_process_measurement_req(dev, mgmt, len); + ieee80211_sta_process_measurement_req(sdata, mgmt, len); break; } break; @@ -3071,38 +3008,37 @@ static void ieee80211_rx_mgmt_action(struct net_device *dev, if (len < (IEEE80211_MIN_ACTION_SIZE + sizeof(mgmt->u.action.u.addba_req))) break; - ieee80211_sta_process_addba_request(dev, mgmt, len); + ieee80211_sta_process_addba_request(local, mgmt, len); break; case WLAN_ACTION_ADDBA_RESP: if (len < (IEEE80211_MIN_ACTION_SIZE + sizeof(mgmt->u.action.u.addba_resp))) break; - ieee80211_sta_process_addba_resp(dev, mgmt, len); + ieee80211_sta_process_addba_resp(local, mgmt, len); break; case WLAN_ACTION_DELBA: if (len < (IEEE80211_MIN_ACTION_SIZE + sizeof(mgmt->u.action.u.delba))) break; - ieee80211_sta_process_delba(dev, mgmt, len); + ieee80211_sta_process_delba(sdata, mgmt, len); break; } break; case PLINK_CATEGORY: if (ieee80211_vif_is_mesh(&sdata->vif)) - mesh_rx_plink_frame(dev, mgmt, len, rx_status); + mesh_rx_plink_frame(sdata, mgmt, len, rx_status); break; case MESH_PATH_SEL_CATEGORY: if (ieee80211_vif_is_mesh(&sdata->vif)) - mesh_rx_path_sel_frame(dev, mgmt, len); + mesh_rx_path_sel_frame(sdata, mgmt, len); break; } } -void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb, +void ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, struct ieee80211_rx_status *rx_status) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_sub_if_data *sdata; + struct ieee80211_local *local = sdata->local; struct ieee80211_if_sta *ifsta; struct ieee80211_mgmt *mgmt; u16 fc; @@ -3110,7 +3046,6 @@ void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb, if (skb->len < 24) goto fail; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); ifsta = &sdata->u.sta; mgmt = (struct ieee80211_mgmt *) skb->data; @@ -3136,17 +3071,14 @@ void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb, kfree_skb(skb); } - -static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev, +static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) { struct ieee80211_rx_status *rx_status; - struct ieee80211_sub_if_data *sdata; struct ieee80211_if_sta *ifsta; struct ieee80211_mgmt *mgmt; u16 fc; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); ifsta = &sdata->u.sta; rx_status = (struct ieee80211_rx_status *) skb->cb; @@ -3155,17 +3087,17 @@ static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev, switch (fc & IEEE80211_FCTL_STYPE) { case IEEE80211_STYPE_PROBE_REQ: - ieee80211_rx_mgmt_probe_req(dev, ifsta, mgmt, skb->len, + ieee80211_rx_mgmt_probe_req(sdata, ifsta, mgmt, skb->len, rx_status); break; case IEEE80211_STYPE_PROBE_RESP: - ieee80211_rx_mgmt_probe_resp(dev, mgmt, skb->len, rx_status); + ieee80211_rx_mgmt_probe_resp(sdata, mgmt, skb->len, rx_status); break; case IEEE80211_STYPE_BEACON: - ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len, rx_status); + ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, rx_status); break; case IEEE80211_STYPE_AUTH: - ieee80211_rx_mgmt_auth(dev, ifsta, mgmt, skb->len); + ieee80211_rx_mgmt_auth(sdata, ifsta, mgmt, skb->len); break; case IEEE80211_STYPE_ASSOC_RESP: ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 0); @@ -3174,13 +3106,13 @@ static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev, ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 1); break; case IEEE80211_STYPE_DEAUTH: - ieee80211_rx_mgmt_deauth(dev, ifsta, mgmt, skb->len); + ieee80211_rx_mgmt_deauth(sdata, ifsta, mgmt, skb->len); break; case IEEE80211_STYPE_DISASSOC: - ieee80211_rx_mgmt_disassoc(dev, ifsta, mgmt, skb->len); + ieee80211_rx_mgmt_disassoc(sdata, ifsta, mgmt, skb->len); break; case IEEE80211_STYPE_ACTION: - ieee80211_rx_mgmt_action(dev, ifsta, mgmt, skb->len, rx_status); + ieee80211_rx_mgmt_action(sdata, ifsta, mgmt, skb->len, rx_status); break; } @@ -3189,7 +3121,7 @@ static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev, ieee80211_rx_result -ieee80211_sta_rx_scan(struct net_device *dev, struct sk_buff *skb, +ieee80211_sta_rx_scan(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, struct ieee80211_rx_status *rx_status) { struct ieee80211_mgmt *mgmt; @@ -3208,13 +3140,13 @@ ieee80211_sta_rx_scan(struct net_device *dev, struct sk_buff *skb, return RX_DROP_MONITOR; if (ieee80211_is_probe_resp(fc)) { - ieee80211_rx_mgmt_probe_resp(dev, mgmt, skb->len, rx_status); + ieee80211_rx_mgmt_probe_resp(sdata, mgmt, skb->len, rx_status); dev_kfree_skb(skb); return RX_QUEUED; } if (ieee80211_is_beacon(fc)) { - ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len, rx_status); + ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, rx_status); dev_kfree_skb(skb); return RX_QUEUED; } @@ -3223,12 +3155,11 @@ ieee80211_sta_rx_scan(struct net_device *dev, struct sk_buff *skb, } -static int ieee80211_sta_active_ibss(struct net_device *dev) +static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; int active = 0; struct sta_info *sta; - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); rcu_read_lock(); @@ -3247,9 +3178,9 @@ static int ieee80211_sta_active_ibss(struct net_device *dev) } -static void ieee80211_sta_expire(struct net_device *dev, unsigned long exp_time) +static void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, unsigned long exp_time) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sta_info *sta, *tmp; LIST_HEAD(tmp_list); DECLARE_MAC_BUF(mac); @@ -3260,7 +3191,7 @@ static void ieee80211_sta_expire(struct net_device *dev, unsigned long exp_time) if (time_after(jiffies, sta->last_rx + exp_time)) { #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG "%s: expiring inactive STA %s\n", - dev->name, print_mac(mac, sta->addr)); + sdata->dev->name, print_mac(mac, sta->addr)); #endif __sta_info_unlink(&sta); if (sta) @@ -3273,30 +3204,29 @@ static void ieee80211_sta_expire(struct net_device *dev, unsigned long exp_time) } -static void ieee80211_sta_merge_ibss(struct net_device *dev, +static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); - ieee80211_sta_expire(dev, IEEE80211_IBSS_INACTIVITY_LIMIT); - if (ieee80211_sta_active_ibss(dev)) + ieee80211_sta_expire(sdata, IEEE80211_IBSS_INACTIVITY_LIMIT); + if (ieee80211_sta_active_ibss(sdata)) return; printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " - "IBSS networks with same SSID (merge)\n", dev->name); - ieee80211_sta_req_scan(dev, ifsta->ssid, ifsta->ssid_len); + "IBSS networks with same SSID (merge)\n", sdata->dev->name); + ieee80211_sta_req_scan(sdata, ifsta->ssid, ifsta->ssid_len); } #ifdef CONFIG_MAC80211_MESH -static void ieee80211_mesh_housekeeping(struct net_device *dev, +static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); bool free_plinks; - ieee80211_sta_expire(dev, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); - mesh_path_expire(dev); + ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); + mesh_path_expire(sdata); free_plinks = mesh_plink_availables(sdata); if (free_plinks != sdata->u.sta.accepting_plinks) @@ -3307,12 +3237,11 @@ static void ieee80211_mesh_housekeeping(struct net_device *dev, } -void ieee80211_start_mesh(struct net_device *dev) +void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_sta *ifsta; - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); ifsta = &sdata->u.sta; - ifsta->state = IEEE80211_MESH_UP; + ifsta->state = IEEE80211_STA_MLME_MESH_UP; ieee80211_sta_timer((unsigned long)sdata); ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); } @@ -3324,7 +3253,7 @@ void ieee80211_sta_timer(unsigned long data) struct ieee80211_sub_if_data *sdata = (struct ieee80211_sub_if_data *) data; struct ieee80211_if_sta *ifsta = &sdata->u.sta; - struct ieee80211_local *local = wdev_priv(&sdata->wdev); + struct ieee80211_local *local = sdata->local; set_bit(IEEE80211_STA_REQ_RUN, &ifsta->request); queue_work(local->hw.workqueue, &ifsta->work); @@ -3334,12 +3263,11 @@ void ieee80211_sta_work(struct work_struct *work) { struct ieee80211_sub_if_data *sdata = container_of(work, struct ieee80211_sub_if_data, u.sta.work); - struct net_device *dev = sdata->dev; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct ieee80211_if_sta *ifsta; struct sk_buff *skb; - if (!netif_running(dev)) + if (!netif_running(sdata->dev)) return; if (local->sta_sw_scanning || local->sta_hw_scanning) @@ -3352,53 +3280,57 @@ void ieee80211_sta_work(struct work_struct *work) ifsta = &sdata->u.sta; while ((skb = skb_dequeue(&ifsta->skb_queue))) - ieee80211_sta_rx_queued_mgmt(dev, skb); + ieee80211_sta_rx_queued_mgmt(sdata, skb); #ifdef CONFIG_MAC80211_MESH if (ifsta->preq_queue_len && time_after(jiffies, ifsta->last_preq + msecs_to_jiffies(ifsta->mshcfg.dot11MeshHWMPpreqMinInterval))) - mesh_path_start_discovery(dev); + mesh_path_start_discovery(sdata); #endif - if (ifsta->state != IEEE80211_AUTHENTICATE && - ifsta->state != IEEE80211_ASSOCIATE && + if (ifsta->state != IEEE80211_STA_MLME_DIRECT_PROBE && + ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE && + ifsta->state != IEEE80211_STA_MLME_ASSOCIATE && test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) { if (ifsta->scan_ssid_len) - ieee80211_sta_start_scan(dev, ifsta->scan_ssid, ifsta->scan_ssid_len); + ieee80211_sta_start_scan(sdata, ifsta->scan_ssid, ifsta->scan_ssid_len); else - ieee80211_sta_start_scan(dev, NULL, 0); + ieee80211_sta_start_scan(sdata, NULL, 0); return; } if (test_and_clear_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request)) { - if (ieee80211_sta_config_auth(dev, ifsta)) + if (ieee80211_sta_config_auth(sdata, ifsta)) return; clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request); } else if (!test_and_clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request)) return; switch (ifsta->state) { - case IEEE80211_DISABLED: + case IEEE80211_STA_MLME_DISABLED: + break; + case IEEE80211_STA_MLME_DIRECT_PROBE: + ieee80211_direct_probe(sdata, ifsta); break; - case IEEE80211_AUTHENTICATE: - ieee80211_authenticate(dev, ifsta); + case IEEE80211_STA_MLME_AUTHENTICATE: + ieee80211_authenticate(sdata, ifsta); break; - case IEEE80211_ASSOCIATE: - ieee80211_associate(dev, ifsta); + case IEEE80211_STA_MLME_ASSOCIATE: + ieee80211_associate(sdata, ifsta); break; - case IEEE80211_ASSOCIATED: - ieee80211_associated(dev, ifsta); + case IEEE80211_STA_MLME_ASSOCIATED: + ieee80211_associated(sdata, ifsta); break; - case IEEE80211_IBSS_SEARCH: - ieee80211_sta_find_ibss(dev, ifsta); + case IEEE80211_STA_MLME_IBSS_SEARCH: + ieee80211_sta_find_ibss(sdata, ifsta); break; - case IEEE80211_IBSS_JOINED: - ieee80211_sta_merge_ibss(dev, ifsta); + case IEEE80211_STA_MLME_IBSS_JOINED: + ieee80211_sta_merge_ibss(sdata, ifsta); break; #ifdef CONFIG_MAC80211_MESH - case IEEE80211_MESH_UP: - ieee80211_mesh_housekeeping(dev, ifsta); + case IEEE80211_STA_MLME_MESH_UP: + ieee80211_mesh_housekeeping(sdata, ifsta); break; #endif default: @@ -3406,20 +3338,20 @@ void ieee80211_sta_work(struct work_struct *work) break; } - if (ieee80211_privacy_mismatch(dev, ifsta)) { + if (ieee80211_privacy_mismatch(sdata, ifsta)) { printk(KERN_DEBUG "%s: privacy configuration mismatch and " - "mixed-cell disabled - disassociate\n", dev->name); + "mixed-cell disabled - disassociate\n", sdata->dev->name); - ieee80211_send_disassoc(dev, ifsta, WLAN_REASON_UNSPECIFIED); - ieee80211_set_disassoc(dev, ifsta, 0); + ieee80211_send_disassoc(sdata, ifsta, WLAN_REASON_UNSPECIFIED); + ieee80211_set_disassoc(sdata, ifsta, 0); } } -static void ieee80211_sta_reset_auth(struct net_device *dev, +static void ieee80211_sta_reset_auth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; if (local->ops->reset_tsf) { /* Reset own TSF to allow time synchronization work. */ @@ -3439,16 +3371,18 @@ static void ieee80211_sta_reset_auth(struct net_device *dev, ifsta->auth_alg = WLAN_AUTH_OPEN; ifsta->auth_transaction = -1; ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; - ifsta->auth_tries = ifsta->assoc_tries = 0; - netif_carrier_off(dev); + ifsta->assoc_scan_tries = 0; + ifsta->direct_probe_tries = 0; + ifsta->auth_tries = 0; + ifsta->assoc_tries = 0; + netif_carrier_off(sdata->dev); } -void ieee80211_sta_req_auth(struct net_device *dev, +void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; if (sdata->vif.type != IEEE80211_IF_TYPE_STA) return; @@ -3492,11 +3426,10 @@ static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta, return 0; } -static int ieee80211_sta_config_auth(struct net_device *dev, +static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = sdata->local; struct ieee80211_sta_bss *bss, *selected = NULL; int top_rssi = 0, freq; @@ -3535,38 +3468,48 @@ static int ieee80211_sta_config_auth(struct net_device *dev, spin_unlock_bh(&local->sta_bss_lock); if (selected) { - ieee80211_set_freq(dev, selected->freq); + ieee80211_set_freq(sdata, selected->freq); if (!(ifsta->flags & IEEE80211_STA_SSID_SET)) - ieee80211_sta_set_ssid(dev, selected->ssid, + ieee80211_sta_set_ssid(sdata, selected->ssid, selected->ssid_len); - ieee80211_sta_set_bssid(dev, selected->bssid); - ieee80211_sta_def_wmm_params(dev, selected, 0); + ieee80211_sta_set_bssid(sdata, selected->bssid); + ieee80211_sta_def_wmm_params(sdata, selected, 0); + + /* Send out direct probe if no probe resp was received or + * the one we have is outdated + */ + if (!selected->last_probe_resp || + time_after(jiffies, selected->last_probe_resp + + IEEE80211_SCAN_RESULT_EXPIRE)) + ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE; + else + ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; + ieee80211_rx_bss_put(local, selected); - ifsta->state = IEEE80211_AUTHENTICATE; - ieee80211_sta_reset_auth(dev, ifsta); + ieee80211_sta_reset_auth(sdata, ifsta); return 0; } else { - if (ifsta->state != IEEE80211_AUTHENTICATE) { + if (ifsta->assoc_scan_tries < IEEE80211_ASSOC_SCANS_MAX_TRIES) { + ifsta->assoc_scan_tries++; if (ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) - ieee80211_sta_start_scan(dev, NULL, 0); + ieee80211_sta_start_scan(sdata, NULL, 0); else - ieee80211_sta_start_scan(dev, ifsta->ssid, + ieee80211_sta_start_scan(sdata, ifsta->ssid, ifsta->ssid_len); - ifsta->state = IEEE80211_AUTHENTICATE; + ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request); } else - ifsta->state = IEEE80211_DISABLED; + ifsta->state = IEEE80211_STA_MLME_DISABLED; } return -1; } -static int ieee80211_sta_create_ibss(struct net_device *dev, +static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct ieee80211_sta_bss *bss; - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_supported_band *sband; u8 bssid[ETH_ALEN], *pos; int i; @@ -3582,15 +3525,15 @@ static int ieee80211_sta_create_ibss(struct net_device *dev, * random number generator get different BSSID. */ get_random_bytes(bssid, ETH_ALEN); for (i = 0; i < ETH_ALEN; i++) - bssid[i] ^= dev->dev_addr[i]; + bssid[i] ^= sdata->dev->dev_addr[i]; bssid[0] &= ~0x01; bssid[0] |= 0x02; #endif printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %s\n", - dev->name, print_mac(mac, bssid)); + sdata->dev->name, print_mac(mac, bssid)); - bss = ieee80211_rx_bss_add(dev, bssid, + bss = ieee80211_rx_bss_add(sdata, bssid, local->hw.conf.channel->center_freq, sdata->u.sta.ssid, sdata->u.sta.ssid_len); if (!bss) @@ -3617,16 +3560,16 @@ static int ieee80211_sta_create_ibss(struct net_device *dev, *pos++ = (u8) (rate / 5); } - ret = ieee80211_sta_join_ibss(dev, ifsta, bss); + ret = ieee80211_sta_join_ibss(sdata, ifsta, bss); ieee80211_rx_bss_put(local, bss); return ret; } -static int ieee80211_sta_find_ibss(struct net_device *dev, +static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_sta *ifsta) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct ieee80211_sta_bss *bss; int found = 0; u8 bssid[ETH_ALEN]; @@ -3637,10 +3580,10 @@ static int ieee80211_sta_find_ibss(struct net_device *dev, if (ifsta->ssid_len == 0) return -EINVAL; - active_ibss = ieee80211_sta_active_ibss(dev); + active_ibss = ieee80211_sta_active_ibss(sdata); #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n", - dev->name, active_ibss); + sdata->dev->name, active_ibss); #endif /* CONFIG_MAC80211_IBSS_DEBUG */ spin_lock_bh(&local->sta_bss_lock); list_for_each_entry(bss, &local->sta_bss_list, list) { @@ -3675,15 +3618,15 @@ static int ieee80211_sta_find_ibss(struct net_device *dev, else search_freq = local->hw.conf.channel->center_freq; - bss = ieee80211_rx_bss_get(dev, bssid, search_freq, + bss = ieee80211_rx_bss_get(local, bssid, search_freq, ifsta->ssid, ifsta->ssid_len); if (!bss) goto dont_join; printk(KERN_DEBUG "%s: Selected IBSS BSSID %s" " based on configured SSID\n", - dev->name, print_mac(mac, bssid)); - ret = ieee80211_sta_join_ibss(dev, ifsta, bss); + sdata->dev->name, print_mac(mac, bssid)); + ret = ieee80211_sta_join_ibss(sdata, ifsta, bss); ieee80211_rx_bss_put(local, bss); return ret; } @@ -3694,17 +3637,17 @@ dont_join: #endif /* CONFIG_MAC80211_IBSS_DEBUG */ /* Selected IBSS not found in current scan results - try to scan */ - if (ifsta->state == IEEE80211_IBSS_JOINED && - !ieee80211_sta_active_ibss(dev)) { + if (ifsta->state == IEEE80211_STA_MLME_IBSS_JOINED && + !ieee80211_sta_active_ibss(sdata)) { mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); } else if (time_after(jiffies, local->last_scan_completed + IEEE80211_SCAN_INTERVAL)) { printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " - "join\n", dev->name); - return ieee80211_sta_req_scan(dev, ifsta->ssid, + "join\n", sdata->dev->name); + return ieee80211_sta_req_scan(sdata, ifsta->ssid, ifsta->ssid_len); - } else if (ifsta->state != IEEE80211_IBSS_JOINED) { + } else if (ifsta->state != IEEE80211_STA_MLME_IBSS_JOINED) { int interval = IEEE80211_SCAN_INTERVAL; if (time_after(jiffies, ifsta->ibss_join_req + @@ -3712,10 +3655,10 @@ dont_join: if ((ifsta->flags & IEEE80211_STA_CREATE_IBSS) && (!(local->oper_channel->flags & IEEE80211_CHAN_NO_IBSS))) - return ieee80211_sta_create_ibss(dev, ifsta); + return ieee80211_sta_create_ibss(sdata, ifsta); if (ifsta->flags & IEEE80211_STA_CREATE_IBSS) { printk(KERN_DEBUG "%s: IBSS not allowed on" - " %d MHz\n", dev->name, + " %d MHz\n", sdata->dev->name, local->hw.conf.channel->center_freq); } @@ -3724,7 +3667,7 @@ dont_join: interval = IEEE80211_SCAN_INTERVAL_SLOW; } - ifsta->state = IEEE80211_IBSS_SEARCH; + ifsta->state = IEEE80211_STA_MLME_IBSS_SEARCH; mod_timer(&ifsta->timer, jiffies + interval); return 0; } @@ -3733,9 +3676,8 @@ dont_join: } -int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len) +int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_if_sta *ifsta; int res; @@ -3759,7 +3701,7 @@ int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len) res = ieee80211_if_config(sdata, IEEE80211_IFCC_SSID); if (res) { printk(KERN_DEBUG "%s: Failed to config new SSID to " - "the low-level driver\n", dev->name); + "the low-level driver\n", sdata->dev->name); return res; } } @@ -3772,17 +3714,16 @@ int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len) if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && !(ifsta->flags & IEEE80211_STA_BSSID_SET)) { ifsta->ibss_join_req = jiffies; - ifsta->state = IEEE80211_IBSS_SEARCH; - return ieee80211_sta_find_ibss(dev, ifsta); + ifsta->state = IEEE80211_STA_MLME_IBSS_SEARCH; + return ieee80211_sta_find_ibss(sdata, ifsta); } return 0; } -int ieee80211_sta_get_ssid(struct net_device *dev, char *ssid, size_t *len) +int ieee80211_sta_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_if_sta *ifsta = &sdata->u.sta; memcpy(ssid, ifsta->ssid, ifsta->ssid_len); *len = ifsta->ssid_len; @@ -3790,13 +3731,11 @@ int ieee80211_sta_get_ssid(struct net_device *dev, char *ssid, size_t *len) } -int ieee80211_sta_set_bssid(struct net_device *dev, u8 *bssid) +int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid) { - struct ieee80211_sub_if_data *sdata; struct ieee80211_if_sta *ifsta; int res; - sdata = IEEE80211_DEV_TO_SUB_IF(dev); ifsta = &sdata->u.sta; if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) { @@ -3809,7 +3748,7 @@ int ieee80211_sta_set_bssid(struct net_device *dev, u8 *bssid) res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID); if (res) { printk(KERN_DEBUG "%s: Failed to config new BSSID to " - "the low-level driver\n", dev->name); + "the low-level driver\n", sdata->dev->name); return res; } } @@ -3850,7 +3789,7 @@ static void ieee80211_send_nullfunc(struct ieee80211_local *local, memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN); memcpy(nullfunc->addr3, sdata->u.sta.bssid, ETH_ALEN); - ieee80211_sta_tx(sdata->dev, skb, 0); + ieee80211_sta_tx(sdata, skb, 0); } @@ -3922,9 +3861,9 @@ done: if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { struct ieee80211_if_sta *ifsta = &sdata->u.sta; if (!(ifsta->flags & IEEE80211_STA_BSSID_SET) || - (!(ifsta->state == IEEE80211_IBSS_JOINED) && - !ieee80211_sta_active_ibss(dev))) - ieee80211_sta_find_ibss(dev, ifsta); + (!(ifsta->state == IEEE80211_STA_MLME_IBSS_JOINED) && + !ieee80211_sta_active_ibss(sdata))) + ieee80211_sta_find_ibss(sdata, ifsta); } } EXPORT_SYMBOL(ieee80211_scan_completed); @@ -4013,7 +3952,7 @@ void ieee80211_sta_scan_work(struct work_struct *work) if (local->scan_channel->flags & IEEE80211_CHAN_PASSIVE_SCAN) break; - ieee80211_send_probe_req(dev, NULL, local->scan_ssid, + ieee80211_send_probe_req(sdata, NULL, local->scan_ssid, local->scan_ssid_len); next_delay = IEEE80211_CHANNEL_TIME; break; @@ -4025,10 +3964,10 @@ void ieee80211_sta_scan_work(struct work_struct *work) } -static int ieee80211_sta_start_scan(struct net_device *dev, +static int ieee80211_sta_start_scan(struct ieee80211_sub_if_data *scan_sdata, u8 *ssid, size_t ssid_len) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = scan_sdata->local; struct ieee80211_sub_if_data *sdata; if (ssid_len > IEEE80211_MAX_SSID_LEN) @@ -4052,7 +3991,7 @@ static int ieee80211_sta_start_scan(struct net_device *dev, */ if (local->sta_sw_scanning || local->sta_hw_scanning) { - if (local->scan_dev == dev) + if (local->scan_dev == scan_sdata->dev) return 0; return -EBUSY; } @@ -4062,7 +4001,7 @@ static int ieee80211_sta_start_scan(struct net_device *dev, ssid, ssid_len); if (!rc) { local->sta_hw_scanning = 1; - local->scan_dev = dev; + local->scan_dev = scan_sdata->dev; } return rc; } @@ -4086,7 +4025,7 @@ static int ieee80211_sta_start_scan(struct net_device *dev, local->scan_state = SCAN_SET_CHANNEL; local->scan_channel_idx = 0; local->scan_band = IEEE80211_BAND_2GHZ; - local->scan_dev = dev; + local->scan_dev = scan_sdata->dev; netif_addr_lock_bh(local->mdev); local->filter_flags |= FIF_BCN_PRBRESP_PROMISC; @@ -4105,17 +4044,16 @@ static int ieee80211_sta_start_scan(struct net_device *dev, } -int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len) +int ieee80211_sta_req_scan(struct ieee80211_sub_if_data *sdata, u8 *ssid, size_t ssid_len) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_if_sta *ifsta = &sdata->u.sta; - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; if (sdata->vif.type != IEEE80211_IF_TYPE_STA) - return ieee80211_sta_start_scan(dev, ssid, ssid_len); + return ieee80211_sta_start_scan(sdata, ssid, ssid_len); if (local->sta_sw_scanning || local->sta_hw_scanning) { - if (local->scan_dev == dev) + if (local->scan_dev == sdata->dev) return 0; return -EBUSY; } @@ -4128,13 +4066,54 @@ int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len) return 0; } + +static void ieee80211_sta_add_scan_ies(struct iw_request_info *info, + struct ieee80211_sta_bss *bss, + char **current_ev, char *end_buf) +{ + u8 *pos, *end, *next; + struct iw_event iwe; + + if (bss == NULL || bss->ies == NULL) + return; + + /* + * If needed, fragment the IEs buffer (at IE boundaries) into short + * enough fragments to fit into IW_GENERIC_IE_MAX octet messages. + */ + pos = bss->ies; + end = pos + bss->ies_len; + + while (end - pos > IW_GENERIC_IE_MAX) { + next = pos + 2 + pos[1]; + while (next + 2 + next[1] - pos < IW_GENERIC_IE_MAX) + next = next + 2 + next[1]; + + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVGENIE; + iwe.u.data.length = next - pos; + *current_ev = iwe_stream_add_point(info, *current_ev, + end_buf, &iwe, pos); + + pos = next; + } + + if (end > pos) { + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVGENIE; + iwe.u.data.length = end - pos; + *current_ev = iwe_stream_add_point(info, *current_ev, + end_buf, &iwe, pos); + } +} + + static char * -ieee80211_sta_scan_result(struct net_device *dev, +ieee80211_sta_scan_result(struct ieee80211_local *local, struct iw_request_info *info, struct ieee80211_sta_bss *bss, char *current_ev, char *end_buf) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct iw_event iwe; if (time_after(jiffies, @@ -4208,29 +4187,7 @@ ieee80211_sta_scan_result(struct net_device *dev, current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, ""); - if (bss && bss->wpa_ie) { - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVGENIE; - iwe.u.data.length = bss->wpa_ie_len; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, bss->wpa_ie); - } - - if (bss && bss->rsn_ie) { - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVGENIE; - iwe.u.data.length = bss->rsn_ie_len; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, bss->rsn_ie); - } - - if (bss && bss->ht_ie) { - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVGENIE; - iwe.u.data.length = bss->ht_ie_len; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, bss->ht_ie); - } + ieee80211_sta_add_scan_ies(info, bss, ¤t_ev, end_buf); if (bss && bss->supp_rates_len > 0) { /* display all supported rates in readable format */ @@ -4321,11 +4278,10 @@ ieee80211_sta_scan_result(struct net_device *dev, } -int ieee80211_sta_scan_results(struct net_device *dev, +int ieee80211_sta_scan_results(struct ieee80211_local *local, struct iw_request_info *info, char *buf, size_t len) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); char *current_ev = buf; char *end_buf = buf + len; struct ieee80211_sta_bss *bss; @@ -4336,7 +4292,7 @@ int ieee80211_sta_scan_results(struct net_device *dev, spin_unlock_bh(&local->sta_bss_lock); return -E2BIG; } - current_ev = ieee80211_sta_scan_result(dev, info, bss, + current_ev = ieee80211_sta_scan_result(local, info, bss, current_ev, end_buf); } spin_unlock_bh(&local->sta_bss_lock); @@ -4344,9 +4300,8 @@ int ieee80211_sta_scan_results(struct net_device *dev, } -int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len) +int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, char *ie, size_t len) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_if_sta *ifsta = &sdata->u.sta; kfree(ifsta->extra_ie); @@ -4366,13 +4321,12 @@ int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len) } -struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev, +struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, u8 *bssid, u8 *addr, u64 supp_rates) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_local *local = sdata->local; struct sta_info *sta; - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); DECLARE_MAC_BUF(mac); int band = local->hw.conf.channel->band; @@ -4381,7 +4335,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev, if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) { if (net_ratelimit()) { printk(KERN_DEBUG "%s: No room for a new IBSS STA " - "entry %s\n", dev->name, print_mac(mac, addr)); + "entry %s\n", sdata->dev->name, print_mac(mac, addr)); } return NULL; } @@ -4391,7 +4345,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev, #ifdef CONFIG_MAC80211_VERBOSE_DEBUG printk(KERN_DEBUG "%s: Adding new IBSS station %s (dev=%s)\n", - wiphy_name(local->hw.wiphy), print_mac(mac, addr), dev->name); + wiphy_name(local->hw.wiphy), print_mac(mac, addr), sdata->dev->name); #endif sta = sta_info_alloc(sdata, addr, GFP_ATOMIC); @@ -4400,10 +4354,9 @@ struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev, set_sta_flags(sta, WLAN_STA_AUTHORIZED); - if (supp_rates) - sta->supp_rates[band] = supp_rates; - else - sta->supp_rates[band] = sdata->u.sta.supp_rates_bits[band]; + /* make sure mandatory rates are always added */ + sta->supp_rates[band] = supp_rates | + ieee80211_sta_get_mandatory_rates(local, band); rate_control_rate_init(sta, local); @@ -4414,31 +4367,29 @@ struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev, } -int ieee80211_sta_deauthenticate(struct net_device *dev, u16 reason) +int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_if_sta *ifsta = &sdata->u.sta; printk(KERN_DEBUG "%s: deauthenticating by local choice (reason=%d)\n", - dev->name, reason); + sdata->dev->name, reason); if (sdata->vif.type != IEEE80211_IF_TYPE_STA && sdata->vif.type != IEEE80211_IF_TYPE_IBSS) return -EINVAL; - ieee80211_send_deauth(dev, ifsta, reason); - ieee80211_set_disassoc(dev, ifsta, 1); + ieee80211_send_deauth(sdata, ifsta, reason); + ieee80211_set_disassoc(sdata, ifsta, 1); return 0; } -int ieee80211_sta_disassociate(struct net_device *dev, u16 reason) +int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_if_sta *ifsta = &sdata->u.sta; printk(KERN_DEBUG "%s: disassociating by local choice (reason=%d)\n", - dev->name, reason); + sdata->dev->name, reason); if (sdata->vif.type != IEEE80211_IF_TYPE_STA) return -EINVAL; @@ -4446,8 +4397,8 @@ int ieee80211_sta_disassociate(struct net_device *dev, u16 reason) if (!(ifsta->flags & IEEE80211_STA_ASSOCIATED)) return -1; - ieee80211_send_disassoc(dev, ifsta, reason); - ieee80211_set_disassoc(dev, ifsta, 0); + ieee80211_send_disassoc(sdata, ifsta, reason); + ieee80211_set_disassoc(sdata, ifsta, 0); return 0; } @@ -4464,7 +4415,7 @@ void ieee80211_notify_mac(struct ieee80211_hw *hw, if (sdata->vif.type != IEEE80211_IF_TYPE_STA) continue; - ieee80211_sta_req_auth(sdata->dev, &sdata->u.sta); + ieee80211_sta_req_auth(sdata, &sdata->u.sta); } rcu_read_unlock(); break;