diff options
Diffstat (limited to 'net/ieee80211')
-rw-r--r-- | net/ieee80211/Kconfig | 2 | ||||
-rw-r--r-- | net/ieee80211/ieee80211_module.c | 25 | ||||
-rw-r--r-- | net/ieee80211/ieee80211_rx.c | 80 | ||||
-rw-r--r-- | net/ieee80211/ieee80211_tx.c | 4 | ||||
-rw-r--r-- | net/ieee80211/softmac/ieee80211softmac_assoc.c | 56 | ||||
-rw-r--r-- | net/ieee80211/softmac/ieee80211softmac_auth.c | 24 | ||||
-rw-r--r-- | net/ieee80211/softmac/ieee80211softmac_io.c | 11 | ||||
-rw-r--r-- | net/ieee80211/softmac/ieee80211softmac_module.c | 1 | ||||
-rw-r--r-- | net/ieee80211/softmac/ieee80211softmac_scan.c | 7 | ||||
-rw-r--r-- | net/ieee80211/softmac/ieee80211softmac_wx.c | 71 |
10 files changed, 186 insertions, 95 deletions
diff --git a/net/ieee80211/Kconfig b/net/ieee80211/Kconfig index f7e84e9d13a..a64be6cdf07 100644 --- a/net/ieee80211/Kconfig +++ b/net/ieee80211/Kconfig @@ -32,6 +32,7 @@ config IEEE80211_CRYPT_WEP depends on IEEE80211 select CRYPTO select CRYPTO_ARC4 + select CRYPTO_ECB select CRC32 ---help--- Include software based cipher suites in support of IEEE @@ -58,6 +59,7 @@ config IEEE80211_CRYPT_TKIP depends on IEEE80211 && NET_RADIO select CRYPTO select CRYPTO_MICHAEL_MIC + select CRYPTO_ECB select CRC32 ---help--- Include software based cipher suites in support of IEEE 802.11i diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c index 13b1e5fff7e..b1c6d1f717d 100644 --- a/net/ieee80211/ieee80211_module.c +++ b/net/ieee80211/ieee80211_module.c @@ -67,7 +67,7 @@ static int ieee80211_networks_allocate(struct ieee80211_device *ieee) return 0; ieee->networks = - kmalloc(MAX_NETWORK_COUNT * sizeof(struct ieee80211_network), + kzalloc(MAX_NETWORK_COUNT * sizeof(struct ieee80211_network), GFP_KERNEL); if (!ieee->networks) { printk(KERN_WARNING "%s: Out of memory allocating beacons\n", @@ -75,9 +75,6 @@ static int ieee80211_networks_allocate(struct ieee80211_device *ieee) return -ENOMEM; } - memset(ieee->networks, 0, - MAX_NETWORK_COUNT * sizeof(struct ieee80211_network)); - return 0; } @@ -118,6 +115,21 @@ static void ieee80211_networks_initialize(struct ieee80211_device *ieee) &ieee->network_free_list); } +static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) +{ + if ((new_mtu < 68) || (new_mtu > IEEE80211_DATA_LEN)) + return -EINVAL; + dev->mtu = new_mtu; + return 0; +} + +static struct net_device_stats *ieee80211_generic_get_stats( + struct net_device *dev) +{ + struct ieee80211_device *ieee = netdev_priv(dev); + return &ieee->stats; +} + struct net_device *alloc_ieee80211(int sizeof_priv) { struct ieee80211_device *ieee; @@ -133,6 +145,11 @@ struct net_device *alloc_ieee80211(int sizeof_priv) } ieee = netdev_priv(dev); dev->hard_start_xmit = ieee80211_xmit; + dev->change_mtu = ieee80211_change_mtu; + + /* Drivers are free to override this if the generic implementation + * does not meet their needs. */ + dev->get_stats = ieee80211_generic_get_stats; ieee->dev = dev; diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c index 770704183a1..d97e5412e31 100644 --- a/net/ieee80211/ieee80211_rx.c +++ b/net/ieee80211/ieee80211_rx.c @@ -415,17 +415,16 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, ieee->host_mc_decrypt : ieee->host_decrypt; if (can_be_decrypted) { - int idx = 0; if (skb->len >= hdrlen + 3) { /* Top two-bits of byte 3 are the key index */ - idx = skb->data[hdrlen + 3] >> 6; + keyidx = skb->data[hdrlen + 3] >> 6; } - /* ieee->crypt[] is WEP_KEY (4) in length. Given that idx - * is only allowed 2-bits of storage, no value of idx can - * be provided via above code that would result in idx + /* ieee->crypt[] is WEP_KEY (4) in length. Given that keyidx + * is only allowed 2-bits of storage, no value of keyidx can + * be provided via above code that would result in keyidx * being out of range */ - crypt = ieee->crypt[idx]; + crypt = ieee->crypt[keyidx]; #ifdef NOT_YET sta = NULL; @@ -479,6 +478,11 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, goto rx_exit; } #endif + /* drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.29) */ + if (sc == ieee->prev_seq_ctl) + goto rx_dropped; + else + ieee->prev_seq_ctl = sc; /* Data frame - extract src/dst addresses */ if (skb->len < IEEE80211_3ADDR_LEN) @@ -655,6 +659,51 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, goto rx_dropped; } + /* If the frame was decrypted in hardware, we may need to strip off + * any security data (IV, ICV, etc) that was left behind */ + if (!can_be_decrypted && (fc & IEEE80211_FCTL_PROTECTED) && + ieee->host_strip_iv_icv) { + int trimlen = 0; + + /* Top two-bits of byte 3 are the key index */ + if (skb->len >= hdrlen + 3) + keyidx = skb->data[hdrlen + 3] >> 6; + + /* To strip off any security data which appears before the + * payload, we simply increase hdrlen (as the header gets + * chopped off immediately below). For the security data which + * appears after the payload, we use skb_trim. */ + + switch (ieee->sec.encode_alg[keyidx]) { + case SEC_ALG_WEP: + /* 4 byte IV */ + hdrlen += 4; + /* 4 byte ICV */ + trimlen = 4; + break; + case SEC_ALG_TKIP: + /* 4 byte IV, 4 byte ExtIV */ + hdrlen += 8; + /* 8 byte MIC, 4 byte ICV */ + trimlen = 12; + break; + case SEC_ALG_CCMP: + /* 8 byte CCMP header */ + hdrlen += 8; + /* 8 byte MIC */ + trimlen = 8; + break; + } + + if (skb->len < trimlen) + goto rx_dropped; + + __skb_trim(skb, skb->len - trimlen); + + if (skb->len < hdrlen) + goto rx_dropped; + } + /* skb: hdr + (possible reassembled) full plaintext payload */ payload = skb->data + hdrlen; @@ -1078,12 +1127,12 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element while (length >= sizeof(*info_element)) { if (sizeof(*info_element) + info_element->len > length) { - IEEE80211_ERROR("Info elem: parse failed: " - "info_element->len + 2 > left : " - "info_element->len+2=%zd left=%d, id=%d.\n", - info_element->len + - sizeof(*info_element), - length, info_element->id); + IEEE80211_DEBUG_MGMT("Info elem: parse failed: " + "info_element->len + 2 > left : " + "info_element->len+2=%zd left=%d, id=%d.\n", + info_element->len + + sizeof(*info_element), + length, info_element->id); /* We stop processing but don't return an error here * because some misbehaviour APs break this rule. ie. * Orinoco AP1000. */ @@ -1255,12 +1304,11 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element case MFIE_TYPE_IBSS_DFS: if (network->ibss_dfs) break; - network->ibss_dfs = - kmalloc(info_element->len, GFP_ATOMIC); + network->ibss_dfs = kmemdup(info_element->data, + info_element->len, + GFP_ATOMIC); if (!network->ibss_dfs) return 1; - memcpy(network->ibss_dfs, info_element->data, - info_element->len); network->flags |= NETWORK_HAS_IBSS_DFS; break; diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c index ae254497ba3..854fc13cd78 100644 --- a/net/ieee80211/ieee80211_tx.c +++ b/net/ieee80211/ieee80211_tx.c @@ -390,7 +390,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) * this stack is providing the full 802.11 header, one will * eventually be affixed to this fragment -- so we must account * for it when determining the amount of payload space. */ - bytes_per_frag = frag_size - IEEE80211_3ADDR_LEN; + bytes_per_frag = frag_size - hdr_len; if (ieee->config & (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) bytes_per_frag -= IEEE80211_FCS_LEN; @@ -412,7 +412,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) } else { nr_frags = 1; bytes_per_frag = bytes_last_frag = bytes; - frag_size = bytes + IEEE80211_3ADDR_LEN; + frag_size = bytes + hdr_len; } rts_required = (frag_size > ieee->rts diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c index 589f6d2c548..cf51c87a971 100644 --- a/net/ieee80211/softmac/ieee80211softmac_assoc.c +++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c @@ -48,7 +48,7 @@ ieee80211softmac_assoc(struct ieee80211softmac_device *mac, struct ieee80211soft dprintk(KERN_INFO PFX "sent association request!\n"); spin_lock_irqsave(&mac->lock, flags); - mac->associated = 0; /* just to make sure */ + mac->associnfo.associated = 0; /* just to make sure */ /* Set a timer for timeout */ /* FIXME: make timeout configurable */ @@ -62,24 +62,22 @@ ieee80211softmac_assoc_timeout(void *d) { struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d; struct ieee80211softmac_network *n; - unsigned long flags; - spin_lock_irqsave(&mac->lock, flags); + mutex_lock(&mac->associnfo.mutex); /* we might race against ieee80211softmac_handle_assoc_response, * so make sure only one of us does something */ - if (!mac->associnfo.associating) { - spin_unlock_irqrestore(&mac->lock, flags); - return; - } + if (!mac->associnfo.associating) + goto out; mac->associnfo.associating = 0; mac->associnfo.bssvalid = 0; - mac->associated = 0; + mac->associnfo.associated = 0; n = ieee80211softmac_get_network_by_bssid_locked(mac, mac->associnfo.bssid); - spin_unlock_irqrestore(&mac->lock, flags); dprintk(KERN_INFO PFX "assoc request timed out!\n"); ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT, n); +out: + mutex_unlock(&mac->associnfo.mutex); } void @@ -93,7 +91,7 @@ ieee80211softmac_disassoc(struct ieee80211softmac_device *mac) netif_carrier_off(mac->dev); - mac->associated = 0; + mac->associnfo.associated = 0; mac->associnfo.bssvalid = 0; mac->associnfo.associating = 0; ieee80211softmac_init_bss(mac); @@ -107,7 +105,7 @@ ieee80211softmac_send_disassoc_req(struct ieee80211softmac_device *mac, u16 reas { struct ieee80211softmac_network *found; - if (mac->associnfo.bssvalid && mac->associated) { + if (mac->associnfo.bssvalid && mac->associnfo.associated) { found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid); if (found) ieee80211softmac_send_mgt_frame(mac, found, IEEE80211_STYPE_DISASSOC, reason); @@ -196,17 +194,18 @@ ieee80211softmac_assoc_work(void *d) int bssvalid; unsigned long flags; + mutex_lock(&mac->associnfo.mutex); + + if (!mac->associnfo.associating) + goto out; + /* ieee80211_disassoc might clear this */ bssvalid = mac->associnfo.bssvalid; /* meh */ - if (mac->associated) + if (mac->associnfo.associated) ieee80211softmac_send_disassoc_req(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT); - spin_lock_irqsave(&mac->lock, flags); - mac->associnfo.associating = 1; - spin_unlock_irqrestore(&mac->lock, flags); - /* try to find the requested network in our list, if we found one already */ if (bssvalid || mac->associnfo.bssfixed) found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid); @@ -260,10 +259,8 @@ ieee80211softmac_assoc_work(void *d) if (!found) { if (mac->associnfo.scan_retry > 0) { - spin_lock_irqsave(&mac->lock, flags); mac->associnfo.scan_retry--; - spin_unlock_irqrestore(&mac->lock, flags); - + /* We know of no such network. Let's scan. * NB: this also happens if we had no memory to copy the network info... * Maybe we can hope to have more memory after scanning finishes ;) @@ -272,19 +269,17 @@ ieee80211softmac_assoc_work(void *d) ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify_scan, NULL); if (ieee80211softmac_start_scan(mac)) dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n"); - return; + goto out; } else { - spin_lock_irqsave(&mac->lock, flags); mac->associnfo.associating = 0; - mac->associated = 0; - spin_unlock_irqrestore(&mac->lock, flags); + mac->associnfo.associated = 0; dprintk(KERN_INFO PFX "Unable to find matching network after scan!\n"); /* reset the retry counter for the next user request since we * break out and don't reschedule ourselves after this point. */ mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT; ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND, NULL); - return; + goto out; } } @@ -297,7 +292,7 @@ ieee80211softmac_assoc_work(void *d) /* copy the ESSID for displaying it */ mac->associnfo.associate_essid.len = found->essid.len; memcpy(mac->associnfo.associate_essid.data, found->essid.data, IW_ESSID_MAX_SIZE + 1); - + /* we found a network! authenticate (if necessary) and associate to it. */ if (found->authenticating) { dprintk(KERN_INFO PFX "Already requested authentication, waiting...\n"); @@ -305,7 +300,7 @@ ieee80211softmac_assoc_work(void *d) mac->associnfo.assoc_wait = 1; ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL); } - return; + goto out; } if (!found->authenticated && !found->authenticating) { /* This relies on the fact that _auth_req only queues the work, @@ -321,11 +316,14 @@ ieee80211softmac_assoc_work(void *d) mac->associnfo.assoc_wait = 0; ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, found); } - return; + goto out; } /* finally! now we can start associating */ mac->associnfo.assoc_wait = 0; ieee80211softmac_assoc(mac, found); + +out: + mutex_unlock(&mac->associnfo.mutex); } /* call this to do whatever is necessary when we're associated */ @@ -341,7 +339,7 @@ ieee80211softmac_associated(struct ieee80211softmac_device *mac, mac->bssinfo.supported_rates = net->supported_rates; ieee80211softmac_recalc_txrates(mac); - mac->associated = 1; + mac->associnfo.associated = 1; mac->associnfo.short_preamble_available = (cap & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0; @@ -421,7 +419,7 @@ ieee80211softmac_handle_assoc_response(struct net_device * dev, dprintk(KERN_INFO PFX "associating failed (reason: 0x%x)!\n", status); mac->associnfo.associating = 0; mac->associnfo.bssvalid = 0; - mac->associated = 0; + mac->associnfo.associated = 0; ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, network); } diff --git a/net/ieee80211/softmac/ieee80211softmac_auth.c b/net/ieee80211/softmac/ieee80211softmac_auth.c index 4cef39e171d..0612015f1c7 100644 --- a/net/ieee80211/softmac/ieee80211softmac_auth.c +++ b/net/ieee80211/softmac/ieee80211softmac_auth.c @@ -158,7 +158,7 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth) /* Make sure that we've got an auth queue item for this request */ if(aq == NULL) { - printkl(KERN_DEBUG PFX "Authentication response received from "MAC_FMT" but no queue item exists.\n", MAC_ARG(auth->header.addr2)); + dprintkl(KERN_DEBUG PFX "Authentication response received from "MAC_FMT" but no queue item exists.\n", MAC_ARG(auth->header.addr2)); /* Error #? */ return -1; } @@ -166,7 +166,7 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth) /* Check for out of order authentication */ if(!net->authenticating) { - printkl(KERN_DEBUG PFX "Authentication response received from "MAC_FMT" but did not request authentication.\n",MAC_ARG(auth->header.addr2)); + dprintkl(KERN_DEBUG PFX "Authentication response received from "MAC_FMT" but did not request authentication.\n",MAC_ARG(auth->header.addr2)); return -1; } @@ -216,10 +216,16 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth) net->challenge_len = *data++; if (net->challenge_len > WLAN_AUTH_CHALLENGE_LEN) net->challenge_len = WLAN_AUTH_CHALLENGE_LEN; - if (net->challenge != NULL) - kfree(net->challenge); - net->challenge = kmalloc(net->challenge_len, GFP_ATOMIC); - memcpy(net->challenge, data, net->challenge_len); + kfree(net->challenge); + net->challenge = kmemdup(data, net->challenge_len, + GFP_ATOMIC); + if (net->challenge == NULL) { + printkl(KERN_NOTICE PFX "Shared Key " + "Authentication failed due to " + "memory shortage.\n"); + spin_unlock_irqrestore(&mac->lock, flags); + break; + } aq->state = IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE; /* We reuse the work struct from the auth request here. @@ -342,7 +348,7 @@ ieee80211softmac_deauth_req(struct ieee80211softmac_device *mac, /* Make sure the network is authenticated */ if (!net->authenticated) { - printkl(KERN_DEBUG PFX "Can't send deauthentication packet, network is not authenticated.\n"); + dprintkl(KERN_DEBUG PFX "Can't send deauthentication packet, network is not authenticated.\n"); /* Error okay? */ return -EPERM; } @@ -376,7 +382,7 @@ ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *de net = ieee80211softmac_get_network_by_bssid(mac, deauth->header.addr2); if (net == NULL) { - printkl(KERN_DEBUG PFX "Received deauthentication packet from "MAC_FMT", but that network is unknown.\n", + dprintkl(KERN_DEBUG PFX "Received deauthentication packet from "MAC_FMT", but that network is unknown.\n", MAC_ARG(deauth->header.addr2)); return 0; } @@ -384,7 +390,7 @@ ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *de /* Make sure the network is authenticated */ if(!net->authenticated) { - printkl(KERN_DEBUG PFX "Can't perform deauthentication, network is not authenticated.\n"); + dprintkl(KERN_DEBUG PFX "Can't perform deauthentication, network is not authenticated.\n"); /* Error okay? */ return -EPERM; } diff --git a/net/ieee80211/softmac/ieee80211softmac_io.c b/net/ieee80211/softmac/ieee80211softmac_io.c index 82bfddbf33a..b96931001b4 100644 --- a/net/ieee80211/softmac/ieee80211softmac_io.c +++ b/net/ieee80211/softmac/ieee80211softmac_io.c @@ -304,7 +304,7 @@ ieee80211softmac_auth(struct ieee80211_auth **pkt, 2 + /* Auth Transaction Seq */ 2 + /* Status Code */ /* Challenge Text IE */ - is_shared_response ? 0 : 1 + 1 + net->challenge_len + (is_shared_response ? 1 + 1 + net->challenge_len : 0) ); if (unlikely((*pkt) == NULL)) return 0; @@ -475,8 +475,13 @@ int ieee80211softmac_handle_beacon(struct net_device *dev, { struct ieee80211softmac_device *mac = ieee80211_priv(dev); - if (mac->associated && memcmp(network->bssid, mac->associnfo.bssid, ETH_ALEN) == 0) - ieee80211softmac_process_erp(mac, network->erp_value); + /* This might race, but we don't really care and it's not worth + * adding heavyweight locking in this fastpath. + */ + if (mac->associnfo.associated) { + if (memcmp(network->bssid, mac->associnfo.bssid, ETH_ALEN) == 0) + ieee80211softmac_process_erp(mac, network->erp_value); + } return 0; } diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c index addea1cf73a..33aff4f4a47 100644 --- a/net/ieee80211/softmac/ieee80211softmac_module.c +++ b/net/ieee80211/softmac/ieee80211softmac_module.c @@ -57,6 +57,7 @@ struct net_device *alloc_ieee80211softmac(int sizeof_priv) INIT_LIST_HEAD(&softmac->network_list); INIT_LIST_HEAD(&softmac->events); + mutex_init(&softmac->associnfo.mutex); INIT_WORK(&softmac->associnfo.work, ieee80211softmac_assoc_work, softmac); INIT_WORK(&softmac->associnfo.timeout, ieee80211softmac_assoc_timeout, softmac); softmac->start_scan = ieee80211softmac_start_scan_implementation; diff --git a/net/ieee80211/softmac/ieee80211softmac_scan.c b/net/ieee80211/softmac/ieee80211softmac_scan.c index d31cf77498c..5507feab32d 100644 --- a/net/ieee80211/softmac/ieee80211softmac_scan.c +++ b/net/ieee80211/softmac/ieee80211softmac_scan.c @@ -47,7 +47,6 @@ ieee80211softmac_start_scan(struct ieee80211softmac_device *sm) sm->scanning = 1; spin_unlock_irqrestore(&sm->lock, flags); - netif_tx_disable(sm->ieee->dev); ret = sm->start_scan(sm->dev); if (ret) { spin_lock_irqsave(&sm->lock, flags); @@ -135,7 +134,8 @@ void ieee80211softmac_scan(void *d) si->started = 0; spin_unlock_irqrestore(&sm->lock, flags); - dprintk(PFX "Scanning finished\n"); + dprintk(PFX "Scanning finished: scanned %d channels starting with channel %d\n", + sm->scaninfo->number_channels, sm->scaninfo->channels[0].channel); ieee80211softmac_scan_finished(sm); complete_all(&sm->scaninfo->finished); } @@ -183,8 +183,6 @@ int ieee80211softmac_start_scan_implementation(struct net_device *dev) sm->scaninfo->channels = sm->ieee->geo.bg; sm->scaninfo->number_channels = sm->ieee->geo.bg_channels; } - dprintk(PFX "Start scanning with channel: %d\n", sm->scaninfo->channels[0].channel); - dprintk(PFX "Scanning %d channels\n", sm->scaninfo->number_channels); sm->scaninfo->current_channel_idx = 0; sm->scaninfo->started = 1; sm->scaninfo->stop = 0; @@ -248,7 +246,6 @@ void ieee80211softmac_scan_finished(struct ieee80211softmac_device *sm) if (net) sm->set_channel(sm->dev, net->channel); } - netif_wake_queue(sm->ieee->dev); ieee80211softmac_call_events(sm, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, NULL); } EXPORT_SYMBOL_GPL(ieee80211softmac_scan_finished); diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c index 2aa779d18f3..23068a830f7 100644 --- a/net/ieee80211/softmac/ieee80211softmac_wx.c +++ b/net/ieee80211/softmac/ieee80211softmac_wx.c @@ -73,13 +73,14 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev, struct ieee80211softmac_network *n; struct ieee80211softmac_auth_queue_item *authptr; int length = 0; - unsigned long flags; + + mutex_lock(&sm->associnfo.mutex); /* Check if we're already associating to this or another network * If it's another network, cancel and start over with our new network * If it's our network, ignore the change, we're already doing it! */ - if((sm->associnfo.associating || sm->associated) && + if((sm->associnfo.associating || sm->associnfo.associated) && (data->essid.flags && data->essid.length)) { /* Get the associating network */ n = ieee80211softmac_get_network_by_bssid(sm, sm->associnfo.bssid); @@ -87,10 +88,9 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev, !memcmp(n->essid.data, extra, n->essid.len)) { dprintk(KERN_INFO PFX "Already associating or associated to "MAC_FMT"\n", MAC_ARG(sm->associnfo.bssid)); - return 0; + goto out; } else { dprintk(KERN_INFO PFX "Canceling existing associate request!\n"); - spin_lock_irqsave(&sm->lock,flags); /* Cancel assoc work */ cancel_delayed_work(&sm->associnfo.work); /* We don't have to do this, but it's a little cleaner */ @@ -98,14 +98,13 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev, cancel_delayed_work(&authptr->work); sm->associnfo.bssvalid = 0; sm->associnfo.bssfixed = 0; - spin_unlock_irqrestore(&sm->lock,flags); flush_scheduled_work(); + sm->associnfo.associating = 0; + sm->associnfo.associated = 0; } } - spin_lock_irqsave(&sm->lock, flags); - sm->associnfo.static_essid = 0; sm->associnfo.assoc_wait = 0; @@ -121,10 +120,12 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev, * If applicable, we have already copied the data in */ sm->associnfo.req_essid.len = length; + sm->associnfo.associating = 1; /* queue lower level code to do work (if necessary) */ schedule_work(&sm->associnfo.work); +out: + mutex_unlock(&sm->associnfo.mutex); - spin_unlock_irqrestore(&sm->lock, flags); return 0; } EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_essid); @@ -136,10 +137,8 @@ ieee80211softmac_wx_get_essid(struct net_device *net_dev, char *extra) { struct ieee80211softmac_device *sm = ieee80211_priv(net_dev); - unsigned long flags; - /* avoid getting inconsistent information */ - spin_lock_irqsave(&sm->lock, flags); + mutex_lock(&sm->associnfo.mutex); /* If all fails, return ANY (empty) */ data->essid.length = 0; data->essid.flags = 0; /* active */ @@ -152,12 +151,13 @@ ieee80211softmac_wx_get_essid(struct net_device *net_dev, } /* If we're associating/associated, return that */ - if (sm->associated || sm->associnfo.associating) { + if (sm->associnfo.associated || sm->associnfo.associating) { data->essid.length = sm->associnfo.associate_essid.len; data->essid.flags = 1; /* active */ memcpy(extra, sm->associnfo.associate_essid.data, sm->associnfo.associate_essid.len); } - spin_unlock_irqrestore(&sm->lock, flags); + mutex_unlock(&sm->associnfo.mutex); + return 0; } EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_essid); @@ -322,15 +322,15 @@ ieee80211softmac_wx_get_wap(struct net_device *net_dev, { struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); int err = 0; - unsigned long flags; - spin_lock_irqsave(&mac->lock, flags); + mutex_lock(&mac->associnfo.mutex); if (mac->associnfo.bssvalid) memcpy(data->ap_addr.sa_data, mac->associnfo.bssid, ETH_ALEN); else memset(data->ap_addr.sa_data, 0xff, ETH_ALEN); data->ap_addr.sa_family = ARPHRD_ETHER; - spin_unlock_irqrestore(&mac->lock, flags); + mutex_unlock(&mac->associnfo.mutex); + return err; } EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_wap); @@ -342,28 +342,27 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev, char *extra) { struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); - unsigned long flags; /* sanity check */ if (data->ap_addr.sa_family != ARPHRD_ETHER) { return -EINVAL; } - spin_lock_irqsave(&mac->lock, flags); + mutex_lock(&mac->associnfo.mutex); if (is_broadcast_ether_addr(data->ap_addr.sa_data)) { /* the bssid we have is not to be fixed any longer, * and we should reassociate to the best AP. */ mac->associnfo.bssfixed = 0; /* force reassociation */ mac->associnfo.bssvalid = 0; - if (mac->associated) + if (mac->associnfo.associated) schedule_work(&mac->associnfo.work); } else if (is_zero_ether_addr(data->ap_addr.sa_data)) { /* the bssid we have is no longer fixed */ mac->associnfo.bssfixed = 0; } else { if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) { - if (mac->associnfo.associating || mac->associated) { + if (mac->associnfo.associating || mac->associnfo.associated) { /* bssid unchanged and associated or associating - just return */ goto out; } @@ -378,7 +377,8 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev, } out: - spin_unlock_irqrestore(&mac->lock, flags); + mutex_unlock(&mac->associnfo.mutex); + return 0; } EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_wap); @@ -394,7 +394,8 @@ ieee80211softmac_wx_set_genie(struct net_device *dev, int err = 0; char *buf; int i; - + + mutex_lock(&mac->associnfo.mutex); spin_lock_irqsave(&mac->lock, flags); /* bleh. shouldn't be locked for that kmalloc... */ @@ -432,6 +433,8 @@ ieee80211softmac_wx_set_genie(struct net_device *dev, out: spin_unlock_irqrestore(&mac->lock, flags); + mutex_unlock(&mac->associnfo.mutex); + return err; } EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_genie); @@ -446,7 +449,8 @@ ieee80211softmac_wx_get_genie(struct net_device *dev, unsigned long flags; int err = 0; int space = wrqu->data.length; - + + mutex_lock(&mac->associnfo.mutex); spin_lock_irqsave(&mac->lock, flags); wrqu->data.length = 0; @@ -459,6 +463,8 @@ ieee80211softmac_wx_get_genie(struct net_device *dev, err = -E2BIG; } spin_unlock_irqrestore(&mac->lock, flags); + mutex_lock(&mac->associnfo.mutex); + return err; } EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_genie); @@ -473,10 +479,13 @@ ieee80211softmac_wx_set_mlme(struct net_device *dev, struct iw_mlme *mlme = (struct iw_mlme *)extra; u16 reason = cpu_to_le16(mlme->reason_code); struct ieee80211softmac_network *net; + int err = -EINVAL; + + mutex_lock(&mac->associnfo.mutex); if (memcmp(mac->associnfo.bssid, mlme->addr.sa_data, ETH_ALEN)) { printk(KERN_DEBUG PFX "wx_set_mlme: requested operation on net we don't use\n"); - return -EINVAL; + goto out; } switch (mlme->cmd) { @@ -484,14 +493,22 @@ ieee80211softmac_wx_set_mlme(struct net_device *dev, net = ieee80211softmac_get_network_by_bssid_locked(mac, mlme->addr.sa_data); if (!net) { printk(KERN_DEBUG PFX "wx_set_mlme: we should know the net here...\n"); - return -EINVAL; + goto out; } return ieee80211softmac_deauth_req(mac, net, reason); case IW_MLME_DISASSOC: ieee80211softmac_send_disassoc_req(mac, reason); - return 0; + mac->associnfo.associated = 0; + mac->associnfo.associating = 0; + err = 0; + goto out; default: - return -EOPNOTSUPP; + err = -EOPNOTSUPP; } + +out: + mutex_unlock(&mac->associnfo.mutex); + + return err; } EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_mlme); |