diff options
Diffstat (limited to 'net/ieee80211')
-rw-r--r-- | net/ieee80211/ieee80211_crypt_tkip.c | 11 | ||||
-rw-r--r-- | net/ieee80211/ieee80211_rx.c | 18 | ||||
-rw-r--r-- | net/ieee80211/ieee80211_tx.c | 63 | ||||
-rw-r--r-- | net/ieee80211/ieee80211_wx.c | 44 | ||||
-rw-r--r-- | net/ieee80211/softmac/ieee80211softmac_assoc.c | 2 | ||||
-rw-r--r-- | net/ieee80211/softmac/ieee80211softmac_event.c | 25 | ||||
-rw-r--r-- | net/ieee80211/softmac/ieee80211softmac_priv.h | 1 | ||||
-rw-r--r-- | net/ieee80211/softmac/ieee80211softmac_wx.c | 32 |
8 files changed, 134 insertions, 62 deletions
diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c index 93def94..3fa5df2 100644 --- a/net/ieee80211/ieee80211_crypt_tkip.c +++ b/net/ieee80211/ieee80211_crypt_tkip.c @@ -501,8 +501,11 @@ static int michael_mic(struct ieee80211_tkip_data *tkey, u8 * key, u8 * hdr, static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr) { struct ieee80211_hdr_4addr *hdr11; + u16 stype; hdr11 = (struct ieee80211_hdr_4addr *)skb->data; + stype = WLAN_FC_GET_STYPE(le16_to_cpu(hdr11->frame_ctl)); + switch (le16_to_cpu(hdr11->frame_ctl) & (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) { case IEEE80211_FCTL_TODS: @@ -523,7 +526,13 @@ static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr) break; } - hdr[12] = 0; /* priority */ + if (stype & IEEE80211_STYPE_QOS_DATA) { + const struct ieee80211_hdr_3addrqos *qoshdr = + (struct ieee80211_hdr_3addrqos *)skb->data; + hdr[12] = le16_to_cpu(qoshdr->qos_ctl) & IEEE80211_QCTL_TID; + } else + hdr[12] = 0; /* priority */ + hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */ } diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c index 604b7b0..2bf567f 100644 --- a/net/ieee80211/ieee80211_rx.c +++ b/net/ieee80211/ieee80211_rx.c @@ -369,7 +369,6 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, /* Put this code here so that we avoid duplicating it in all * Rx paths. - Jean II */ -#ifdef CONFIG_WIRELESS_EXT #ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */ /* If spy monitoring on */ if (ieee->spy_data.spy_number > 0) { @@ -398,7 +397,6 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, wireless_spy_update(ieee->dev, hdr->addr2, &wstats); } #endif /* IW_WIRELESS_SPY */ -#endif /* CONFIG_WIRELESS_EXT */ #ifdef NOT_YET hostap_update_rx_stats(local->ap, hdr, rx_stats); @@ -1692,8 +1690,8 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee, WLAN_FC_GET_STYPE(le16_to_cpu (header->frame_ctl))); - IEEE80211_WARNING("%s: IEEE80211_REASSOC_REQ received\n", - ieee->dev->name); + IEEE80211_DEBUG_MGMT("%s: IEEE80211_REASSOC_REQ received\n", + ieee->dev->name); if (ieee->handle_reassoc_request != NULL) ieee->handle_reassoc_request(ieee->dev, (struct ieee80211_reassoc_request *) @@ -1705,8 +1703,8 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee, WLAN_FC_GET_STYPE(le16_to_cpu (header->frame_ctl))); - IEEE80211_WARNING("%s: IEEE80211_ASSOC_REQ received\n", - ieee->dev->name); + IEEE80211_DEBUG_MGMT("%s: IEEE80211_ASSOC_REQ received\n", + ieee->dev->name); if (ieee->handle_assoc_request != NULL) ieee->handle_assoc_request(ieee->dev); break; @@ -1722,10 +1720,10 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee, IEEE80211_DEBUG_MGMT("received UNKNOWN (%d)\n", WLAN_FC_GET_STYPE(le16_to_cpu (header->frame_ctl))); - IEEE80211_WARNING("%s: Unknown management packet: %d\n", - ieee->dev->name, - WLAN_FC_GET_STYPE(le16_to_cpu - (header->frame_ctl))); + IEEE80211_DEBUG_MGMT("%s: Unknown management packet: %d\n", + ieee->dev->name, + WLAN_FC_GET_STYPE(le16_to_cpu + (header->frame_ctl))); break; } } diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c index 8b4332f..233d527 100644 --- a/net/ieee80211/ieee80211_tx.c +++ b/net/ieee80211/ieee80211_tx.c @@ -220,13 +220,43 @@ static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size, return txb; } +static int ieee80211_classify(struct sk_buff *skb) +{ + struct ethhdr *eth; + struct iphdr *ip; + + eth = (struct ethhdr *)skb->data; + if (eth->h_proto != __constant_htons(ETH_P_IP)) + return 0; + + ip = skb->nh.iph; + switch (ip->tos & 0xfc) { + case 0x20: + return 2; + case 0x40: + return 1; + case 0x60: + return 3; + case 0x80: + return 4; + case 0xa0: + return 5; + case 0xc0: + return 6; + case 0xe0: + return 7; + default: + return 0; + } +} + /* Incoming skb is converted to a txb which consists of * a block of 802.11 fragment packets (stored as skbs) */ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) { struct ieee80211_device *ieee = netdev_priv(dev); struct ieee80211_txb *txb = NULL; - struct ieee80211_hdr_3addr *frag_hdr; + struct ieee80211_hdr_3addrqos *frag_hdr; int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size, rts_required; unsigned long flags; @@ -234,9 +264,10 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) int ether_type, encrypt, host_encrypt, host_encrypt_msdu, host_build_iv; int bytes, fc, hdr_len; struct sk_buff *skb_frag; - struct ieee80211_hdr_3addr header = { /* Ensure zero initialized */ + struct ieee80211_hdr_3addrqos header = {/* Ensure zero initialized */ .duration_id = 0, - .seq_ctl = 0 + .seq_ctl = 0, + .qos_ctl = 0 }; u8 dest[ETH_ALEN], src[ETH_ALEN]; struct ieee80211_crypt_data *crypt; @@ -282,12 +313,6 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) memcpy(dest, skb->data, ETH_ALEN); memcpy(src, skb->data + ETH_ALEN, ETH_ALEN); - /* Advance the SKB to the start of the payload */ - skb_pull(skb, sizeof(struct ethhdr)); - - /* Determine total amount of storage required for TXB packets */ - bytes = skb->len + SNAP_SIZE + sizeof(u16); - if (host_encrypt || host_build_iv) fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA | IEEE80211_FCTL_PROTECTED; @@ -306,9 +331,23 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) memcpy(header.addr2, src, ETH_ALEN); memcpy(header.addr3, ieee->bssid, ETH_ALEN); } - header.frame_ctl = cpu_to_le16(fc); hdr_len = IEEE80211_3ADDR_LEN; + if (ieee->is_qos_active && ieee->is_qos_active(dev, skb)) { + fc |= IEEE80211_STYPE_QOS_DATA; + hdr_len += 2; + + skb->priority = ieee80211_classify(skb); + header.qos_ctl |= skb->priority & IEEE80211_QCTL_TID; + } + header.frame_ctl = cpu_to_le16(fc); + + /* Advance the SKB to the start of the payload */ + skb_pull(skb, sizeof(struct ethhdr)); + + /* Determine total amount of storage required for TXB packets */ + bytes = skb->len + SNAP_SIZE + sizeof(u16); + /* Encrypt msdu first on the whole data packet. */ if ((host_encrypt || host_encrypt_msdu) && crypt && crypt->ops && crypt->ops->encrypt_msdu) { @@ -402,7 +441,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) if (rts_required) { skb_frag = txb->fragments[0]; frag_hdr = - (struct ieee80211_hdr_3addr *)skb_put(skb_frag, hdr_len); + (struct ieee80211_hdr_3addrqos *)skb_put(skb_frag, hdr_len); /* * Set header frame_ctl to the RTS. @@ -433,7 +472,7 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) crypt->ops->extra_mpdu_prefix_len); frag_hdr = - (struct ieee80211_hdr_3addr *)skb_put(skb_frag, hdr_len); + (struct ieee80211_hdr_3addrqos *)skb_put(skb_frag, hdr_len); memcpy(frag_hdr, &header, hdr_len); /* If this is not the last fragment, then add the MOREFRAGS diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c index b885fd1..0ea55cb 100644 --- a/net/ieee80211/ieee80211_wx.c +++ b/net/ieee80211/ieee80211_wx.c @@ -50,7 +50,8 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee, char *p; struct iw_event iwe; int i, j; - u8 max_rate, rate; + char *current_val; /* For rates */ + u8 rate; /* First entry *MUST* be the AP MAC address */ iwe.cmd = SIOCGIWAP; @@ -107,9 +108,13 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee, start = iwe_stream_add_point(start, stop, &iwe, network->ssid); /* Add basic and extended rates */ - max_rate = 0; - p = custom; - p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): "); + /* Rate : stuffing multiple values in a single event require a bit + * more of magic - Jean II */ + current_val = start + IW_EV_LCP_LEN; + iwe.cmd = SIOCGIWRATE; + /* Those two flags are ignored... */ + iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; + for (i = 0, j = 0; i < network->rates_len;) { if (j < network->rates_ex_len && ((network->rates_ex[j] & 0x7F) < @@ -117,28 +122,21 @@ static char *ieee80211_translate_scan(struct ieee80211_device *ieee, rate = network->rates_ex[j++] & 0x7F; else rate = network->rates[i++] & 0x7F; - if (rate > max_rate) - max_rate = rate; - p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), - "%d%s ", rate >> 1, (rate & 1) ? ".5" : ""); + /* Bit rate given in 500 kb/s units (+ 0x80) */ + iwe.u.bitrate.value = ((rate & 0x7f) * 500000); + /* Add new value to event */ + current_val = iwe_stream_add_value(start, current_val, stop, &iwe, IW_EV_PARAM_LEN); } for (; j < network->rates_ex_len; j++) { rate = network->rates_ex[j] & 0x7F; - p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), - "%d%s ", rate >> 1, (rate & 1) ? ".5" : ""); - if (rate > max_rate) - max_rate = rate; - } - - iwe.cmd = SIOCGIWRATE; - iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; - iwe.u.bitrate.value = max_rate * 500000; - start = iwe_stream_add_event(start, stop, &iwe, IW_EV_PARAM_LEN); - - iwe.cmd = IWEVCUSTOM; - iwe.u.data.length = p - custom; - if (iwe.u.data.length) - start = iwe_stream_add_point(start, stop, &iwe, custom); + /* Bit rate given in 500 kb/s units (+ 0x80) */ + iwe.u.bitrate.value = ((rate & 0x7f) * 500000); + /* Add new value to event */ + current_val = iwe_stream_add_value(start, current_val, stop, &iwe, IW_EV_PARAM_LEN); + } + /* Check if we added any rate */ + if((current_val - start) > IW_EV_LCP_LEN) + start = current_val; /* Add quality statistics */ iwe.cmd = IWEVQUAL; diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c index 57ea9f6..d4c79ce 100644 --- a/net/ieee80211/softmac/ieee80211softmac_assoc.c +++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c @@ -83,7 +83,7 @@ ieee80211softmac_assoc_timeout(void *d) } /* Sends out a disassociation request to the desired AP */ -static void +void ieee80211softmac_disassoc(struct ieee80211softmac_device *mac, u16 reason) { unsigned long flags; diff --git a/net/ieee80211/softmac/ieee80211softmac_event.c b/net/ieee80211/softmac/ieee80211softmac_event.c index 8cc8f3f..4b153f7 100644 --- a/net/ieee80211/softmac/ieee80211softmac_event.c +++ b/net/ieee80211/softmac/ieee80211softmac_event.c @@ -38,7 +38,8 @@ * The event context is private and can only be used from * within this module. Its meaning varies with the event * type: - * SCAN_FINISHED: no special meaning + * SCAN_FINISHED, + * DISASSOCIATED: NULL * ASSOCIATED, * ASSOCIATE_FAILED, * ASSOCIATE_TIMEOUT, @@ -59,15 +60,15 @@ */ static char *event_descriptions[IEEE80211SOFTMAC_EVENT_LAST+1] = { - "scan finished", - "associated", + NULL, /* scan finished */ + NULL, /* associated */ "associating failed", "associating timed out", "authenticated", "authenticating failed", "authenticating timed out", "associating failed because no suitable network was found", - "disassociated", + NULL, /* disassociated */ }; @@ -136,30 +137,24 @@ ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int eve int we_event; char *msg = NULL; + memset(&wrqu, '\0', sizeof (union iwreq_data)); + switch(event) { case IEEE80211SOFTMAC_EVENT_ASSOCIATED: network = (struct ieee80211softmac_network *)event_ctx; - wrqu.data.length = 0; - wrqu.data.flags = 0; memcpy(wrqu.ap_addr.sa_data, &network->bssid[0], ETH_ALEN); - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - we_event = SIOCGIWAP; - break; + /* fall through */ case IEEE80211SOFTMAC_EVENT_DISASSOCIATED: - wrqu.data.length = 0; - wrqu.data.flags = 0; - memset(&wrqu, '\0', sizeof (union iwreq_data)); wrqu.ap_addr.sa_family = ARPHRD_ETHER; we_event = SIOCGIWAP; break; case IEEE80211SOFTMAC_EVENT_SCAN_FINISHED: - wrqu.data.length = 0; - wrqu.data.flags = 0; - memset(&wrqu, '\0', sizeof (union iwreq_data)); we_event = SIOCGIWSCAN; break; default: msg = event_descriptions[event]; + if (!msg) + msg = "SOFTMAC EVENT BUG"; wrqu.data.length = strlen(msg); we_event = IWEVCUSTOM; break; diff --git a/net/ieee80211/softmac/ieee80211softmac_priv.h b/net/ieee80211/softmac/ieee80211softmac_priv.h index 65d9816..8c95b3a 100644 --- a/net/ieee80211/softmac/ieee80211softmac_priv.h +++ b/net/ieee80211/softmac/ieee80211softmac_priv.h @@ -150,6 +150,7 @@ int ieee80211softmac_handle_disassoc(struct net_device * dev, int ieee80211softmac_handle_reassoc_req(struct net_device * dev, struct ieee80211_reassoc_request * reassoc); void ieee80211softmac_assoc_timeout(void *d); +void ieee80211softmac_disassoc(struct ieee80211softmac_device *mac, u16 reason); /* some helper functions */ static inline int ieee80211softmac_scan_handlers_check_self(struct ieee80211softmac_device *sm) diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c index 27edb2b..8d0c226 100644 --- a/net/ieee80211/softmac/ieee80211softmac_wx.c +++ b/net/ieee80211/softmac/ieee80211softmac_wx.c @@ -431,3 +431,35 @@ ieee80211softmac_wx_get_genie(struct net_device *dev, } EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_genie); +int +ieee80211softmac_wx_set_mlme(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct ieee80211softmac_device *mac = ieee80211_priv(dev); + struct iw_mlme *mlme = (struct iw_mlme *)extra; + u16 reason = cpu_to_le16(mlme->reason_code); + struct ieee80211softmac_network *net; + + 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; + } + + switch (mlme->cmd) { + case IW_MLME_DEAUTH: + 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; + } + return ieee80211softmac_deauth_req(mac, net, reason); + case IW_MLME_DISASSOC: + ieee80211softmac_disassoc(mac, reason); + return 0; + default: + return -EOPNOTSUPP; + } +} +EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_mlme); |