X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=net%2Fmac80211%2Frx.c;h=a7263fc476bdd4a0936f983b3acf298a36faafa1;hb=6b74c92521de123b6b3b01a8be432722121d9e8e;hp=f255579dc5647920b269644134086a33556d1b6e;hpb=52865dfd520ddd3d1176947106759ff944f0f8af;p=powerpc.git diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index f255579dc5..a7263fc476 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -13,18 +13,218 @@ #include #include #include -#include +#include #include #include #include "ieee80211_i.h" #include "ieee80211_led.h" -#include "ieee80211_common.h" #include "wep.h" #include "wpa.h" #include "tkip.h" #include "wme.h" +/* + * monitor mode reception + * + * This function cleans up the SKB, i.e. it removes all the stuff + * only useful for monitoring. + */ +static struct sk_buff *remove_monitor_info(struct ieee80211_local *local, + struct sk_buff *skb, + int rtap_len) +{ + skb_pull(skb, rtap_len); + + if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) { + if (likely(skb->len > FCS_LEN)) + skb_trim(skb, skb->len - FCS_LEN); + else { + /* driver bug */ + WARN_ON(1); + dev_kfree_skb(skb); + skb = NULL; + } + } + + return skb; +} + +static inline int should_drop_frame(struct ieee80211_rx_status *status, + struct sk_buff *skb, + int present_fcs_len, + int radiotap_len) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + + if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) + return 1; + if (unlikely(skb->len < 16 + present_fcs_len + radiotap_len)) + return 1; + if ((hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_FTYPE)) == + cpu_to_le16(IEEE80211_FTYPE_CTL)) + return 1; + return 0; +} + +/* + * This function copies a received frame to all monitor interfaces and + * returns a cleaned-up SKB that no longer includes the FCS nor the + * radiotap header the driver might have added. + */ +static struct sk_buff * +ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, + struct ieee80211_rx_status *status) +{ + struct ieee80211_sub_if_data *sdata; + struct ieee80211_rate *rate; + int needed_headroom = 0; + struct ieee80211_rtap_hdr { + struct ieee80211_radiotap_header hdr; + u8 flags; + u8 rate; + __le16 chan_freq; + __le16 chan_flags; + u8 antsignal; + u8 padding_for_rxflags; + __le16 rx_flags; + } __attribute__ ((packed)) *rthdr; + struct sk_buff *skb, *skb2; + struct net_device *prev_dev = NULL; + int present_fcs_len = 0; + int rtap_len = 0; + + /* + * First, we may need to make a copy of the skb because + * (1) we need to modify it for radiotap (if not present), and + * (2) the other RX handlers will modify the skb we got. + * + * We don't need to, of course, if we aren't going to return + * the SKB because it has a bad FCS/PLCP checksum. + */ + if (status->flag & RX_FLAG_RADIOTAP) + rtap_len = ieee80211_get_radiotap_len(origskb->data); + else + needed_headroom = sizeof(*rthdr); + + if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) + present_fcs_len = FCS_LEN; + + if (!local->monitors) { + if (should_drop_frame(status, origskb, present_fcs_len, + rtap_len)) { + dev_kfree_skb(origskb); + return NULL; + } + + return remove_monitor_info(local, origskb, rtap_len); + } + + if (should_drop_frame(status, origskb, present_fcs_len, rtap_len)) { + /* only need to expand headroom if necessary */ + skb = origskb; + origskb = NULL; + + /* + * This shouldn't trigger often because most devices have an + * RX header they pull before we get here, and that should + * be big enough for our radiotap information. We should + * probably export the length to drivers so that we can have + * them allocate enough headroom to start with. + */ + if (skb_headroom(skb) < needed_headroom && + pskb_expand_head(skb, sizeof(*rthdr), 0, GFP_ATOMIC)) { + dev_kfree_skb(skb); + return NULL; + } + } else { + /* + * Need to make a copy and possibly remove radiotap header + * and FCS from the original. + */ + skb = skb_copy_expand(origskb, needed_headroom, 0, GFP_ATOMIC); + + origskb = remove_monitor_info(local, origskb, rtap_len); + + if (!skb) + return origskb; + } + + /* if necessary, prepend radiotap information */ + if (!(status->flag & RX_FLAG_RADIOTAP)) { + rthdr = (void *) skb_push(skb, sizeof(*rthdr)); + memset(rthdr, 0, sizeof(*rthdr)); + rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr)); + rthdr->hdr.it_present = + cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | + (1 << IEEE80211_RADIOTAP_RATE) | + (1 << IEEE80211_RADIOTAP_CHANNEL) | + (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) | + (1 << IEEE80211_RADIOTAP_RX_FLAGS)); + rthdr->flags = local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS ? + IEEE80211_RADIOTAP_F_FCS : 0; + + /* FIXME: when radiotap gets a 'bad PLCP' flag use it here */ + rthdr->rx_flags = 0; + if (status->flag & + (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) + rthdr->rx_flags |= + cpu_to_le16(IEEE80211_RADIOTAP_F_RX_BADFCS); + + rate = ieee80211_get_rate(local, status->phymode, + status->rate); + if (rate) + rthdr->rate = rate->rate / 5; + + rthdr->chan_freq = cpu_to_le16(status->freq); + + if (status->phymode == MODE_IEEE80211A) + rthdr->chan_flags = + cpu_to_le16(IEEE80211_CHAN_OFDM | + IEEE80211_CHAN_5GHZ); + else + rthdr->chan_flags = + cpu_to_le16(IEEE80211_CHAN_DYN | + IEEE80211_CHAN_2GHZ); + + rthdr->antsignal = status->ssi; + } + + skb_set_mac_header(skb, 0); + skb->ip_summed = CHECKSUM_UNNECESSARY; + skb->pkt_type = PACKET_OTHERHOST; + skb->protocol = htons(ETH_P_802_2); + + list_for_each_entry_rcu(sdata, &local->interfaces, list) { + if (!netif_running(sdata->dev)) + continue; + + if (sdata->type != IEEE80211_IF_TYPE_MNTR) + continue; + + if (prev_dev) { + skb2 = skb_clone(skb, GFP_ATOMIC); + if (skb2) { + skb2->dev = prev_dev; + netif_rx(skb2); + } + } + + prev_dev = sdata->dev; + sdata->dev->stats.rx_packets++; + sdata->dev->stats.rx_bytes += skb->len; + } + + if (prev_dev) { + skb->dev = prev_dev; + netif_rx(skb); + } else + dev_kfree_skb(skb); + + return origskb; +} + + /* pre-rx handlers * * these don't have dev/sdata fields in the rx data @@ -94,8 +294,6 @@ ieee80211_rx_h_load_stats(struct ieee80211_txrx_data *rx) * 1 usec = 1/8 * (1080 / 10) = 13.5 */ if (mode->mode == MODE_IEEE80211A || - mode->mode == MODE_ATHEROS_TURBO || - mode->mode == MODE_ATHEROS_TURBOG || (mode->mode == MODE_IEEE80211G && rate->flags & IEEE80211_RATE_ERP)) hdrtime = CHAN_UTIL_HDR_SHORT; @@ -134,83 +332,6 @@ ieee80211_rx_h_if_stats(struct ieee80211_txrx_data *rx) return TXRX_CONTINUE; } -static void -ieee80211_rx_monitor(struct net_device *dev, struct sk_buff *skb, - struct ieee80211_rx_status *status) -{ - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_sub_if_data *sdata; - struct ieee80211_rate *rate; - struct ieee80211_rtap_hdr { - struct ieee80211_radiotap_header hdr; - u8 flags; - u8 rate; - __le16 chan_freq; - __le16 chan_flags; - u8 antsignal; - } __attribute__ ((packed)) *rthdr; - - skb->dev = dev; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - - if (status->flag & RX_FLAG_RADIOTAP) - goto out; - - if (skb_headroom(skb) < sizeof(*rthdr)) { - I802_DEBUG_INC(local->rx_expand_skb_head); - if (pskb_expand_head(skb, sizeof(*rthdr), 0, GFP_ATOMIC)) { - dev_kfree_skb(skb); - return; - } - } - - rthdr = (struct ieee80211_rtap_hdr *) skb_push(skb, sizeof(*rthdr)); - memset(rthdr, 0, sizeof(*rthdr)); - rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr)); - rthdr->hdr.it_present = - cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | - (1 << IEEE80211_RADIOTAP_RATE) | - (1 << IEEE80211_RADIOTAP_CHANNEL) | - (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL)); - rthdr->flags = local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS ? - IEEE80211_RADIOTAP_F_FCS : 0; - rate = ieee80211_get_rate(local, status->phymode, status->rate); - if (rate) - rthdr->rate = rate->rate / 5; - rthdr->chan_freq = cpu_to_le16(status->freq); - rthdr->chan_flags = - status->phymode == MODE_IEEE80211A ? - cpu_to_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ) : - cpu_to_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ); - rthdr->antsignal = status->ssi; - - out: - sdata->stats.rx_packets++; - sdata->stats.rx_bytes += skb->len; - - skb_set_mac_header(skb, 0); - skb->ip_summed = CHECKSUM_UNNECESSARY; - skb->pkt_type = PACKET_OTHERHOST; - skb->protocol = htons(ETH_P_802_2); - memset(skb->cb, 0, sizeof(skb->cb)); - netif_rx(skb); -} - -static ieee80211_txrx_result -ieee80211_rx_h_monitor(struct ieee80211_txrx_data *rx) -{ - if (rx->sdata->type == IEEE80211_IF_TYPE_MNTR) { - ieee80211_rx_monitor(rx->dev, rx->skb, rx->u.rx.status); - return TXRX_QUEUED; - } - - if (rx->u.rx.status->flag & RX_FLAG_RADIOTAP) - skb_pull(rx->skb, ieee80211_get_radiotap_len(rx->skb->data)); - - return TXRX_CONTINUE; -} - static ieee80211_txrx_result ieee80211_rx_h_passive_scan(struct ieee80211_txrx_data *rx) { @@ -222,7 +343,7 @@ ieee80211_rx_h_passive_scan(struct ieee80211_txrx_data *rx) return TXRX_QUEUED; } - if (unlikely(rx->u.rx.in_scan)) { + if (unlikely(rx->flags & IEEE80211_TXRXD_RXIN_SCAN)) { /* scanning finished during invoking of handlers */ I802_DEBUG_INC(local->rx_handlers_drop_passive_scan); return TXRX_DROP; @@ -242,7 +363,7 @@ ieee80211_rx_h_check(struct ieee80211_txrx_data *rx) if (unlikely(rx->fc & IEEE80211_FCTL_RETRY && rx->sta->last_seq_ctrl[rx->u.rx.queue] == hdr->seq_ctrl)) { - if (rx->u.rx.ra_match) { + if (rx->flags & IEEE80211_TXRXD_RXRA_MATCH) { rx->local->dot11FrameDuplicateCount++; rx->sta->num_duplicates++; } @@ -251,16 +372,12 @@ ieee80211_rx_h_check(struct ieee80211_txrx_data *rx) rx->sta->last_seq_ctrl[rx->u.rx.queue] = hdr->seq_ctrl; } - if ((rx->local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) && - rx->skb->len > FCS_LEN) - skb_trim(rx->skb, rx->skb->len - FCS_LEN); - if (unlikely(rx->skb->len < 16)) { I802_DEBUG_INC(rx->local->rx_handlers_drop_short); return TXRX_DROP; } - if (!rx->u.rx.ra_match) + if (!(rx->flags & IEEE80211_TXRXD_RXRA_MATCH)) rx->skb->pkt_type = PACKET_OTHERHOST; else if (compare_ether_addr(rx->dev->dev_addr, hdr->addr1) == 0) rx->skb->pkt_type = PACKET_HOST; @@ -288,18 +405,13 @@ ieee80211_rx_h_check(struct ieee80211_txrx_data *rx) if ((!(rx->fc & IEEE80211_FCTL_FROMDS) && !(rx->fc & IEEE80211_FCTL_TODS) && (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) - || !rx->u.rx.ra_match) { + || !(rx->flags & IEEE80211_TXRXD_RXRA_MATCH)) { /* Drop IBSS frames and frames for other hosts * silently. */ return TXRX_DROP; } - if (!rx->local->apdev) - return TXRX_DROP; - - ieee80211_rx_mgmt(rx->local, rx->skb, rx->u.rx.status, - ieee80211_msg_sta_not_assoc); - return TXRX_QUEUED; + return TXRX_DROP; } return TXRX_CONTINUE; @@ -307,68 +419,135 @@ ieee80211_rx_h_check(struct ieee80211_txrx_data *rx) static ieee80211_txrx_result -ieee80211_rx_h_load_key(struct ieee80211_txrx_data *rx) +ieee80211_rx_h_decrypt(struct ieee80211_txrx_data *rx) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; - int always_sta_key; + int keyidx; + int hdrlen; + ieee80211_txrx_result result = TXRX_DROP; + struct ieee80211_key *stakey = NULL; - if (rx->sdata->type == IEEE80211_IF_TYPE_STA) - always_sta_key = 0; - else - always_sta_key = 1; + /* + * Key selection 101 + * + * There are three types of keys: + * - GTK (group keys) + * - PTK (pairwise keys) + * - STK (station-to-station pairwise keys) + * + * When selecting a key, we have to distinguish between multicast + * (including broadcast) and unicast frames, the latter can only + * use PTKs and STKs while the former always use GTKs. Unless, of + * course, actual WEP keys ("pre-RSNA") are used, then unicast + * frames can also use key indizes like GTKs. Hence, if we don't + * have a PTK/STK we check the key index for a WEP key. + * + * Note that in a regular BSS, multicast frames are sent by the + * AP only, associated stations unicast the frame to the AP first + * which then multicasts it on their behalf. + * + * There is also a slight problem in IBSS mode: GTKs are negotiated + * with each station, that is something we don't currently handle. + * The spec seems to expect that one negotiates the same key with + * every station but there's no such requirement; VLANs could be + * possible. + */ + + if (!(rx->fc & IEEE80211_FCTL_PROTECTED)) + return TXRX_CONTINUE; + + /* + * No point in finding a key and decrypting if the frame is neither + * addressed to us nor a multicast frame. + */ + if (!(rx->flags & IEEE80211_TXRXD_RXRA_MATCH)) + return TXRX_CONTINUE; + + if (rx->sta) + stakey = rcu_dereference(rx->sta->key); - if (rx->sta && rx->sta->key && always_sta_key) { - rx->key = rx->sta->key; + if (!is_multicast_ether_addr(hdr->addr1) && stakey) { + rx->key = stakey; } else { - if (rx->sta && rx->sta->key) - rx->key = rx->sta->key; - else - rx->key = rx->sdata->default_key; - - if ((rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) && - rx->fc & IEEE80211_FCTL_PROTECTED) { - int keyidx = ieee80211_wep_get_keyidx(rx->skb); - - if (keyidx >= 0 && keyidx < NUM_DEFAULT_KEYS && - (!rx->sta || !rx->sta->key || keyidx > 0)) - rx->key = rx->sdata->keys[keyidx]; - - if (!rx->key) { - if (!rx->u.rx.ra_match) - return TXRX_DROP; - printk(KERN_DEBUG "%s: RX WEP frame with " - "unknown keyidx %d (A1=" MAC_FMT " A2=" - MAC_FMT " A3=" MAC_FMT ")\n", - rx->dev->name, keyidx, - MAC_ARG(hdr->addr1), - MAC_ARG(hdr->addr2), - MAC_ARG(hdr->addr3)); - if (!rx->local->apdev) - return TXRX_DROP; - ieee80211_rx_mgmt( - rx->local, rx->skb, rx->u.rx.status, - ieee80211_msg_wep_frame_unknown_key); - return TXRX_QUEUED; - } - } + /* + * The device doesn't give us the IV so we won't be + * able to look up the key. That's ok though, we + * don't need to decrypt the frame, we just won't + * be able to keep statistics accurate. + * Except for key threshold notifications, should + * we somehow allow the driver to tell us which key + * the hardware used if this flag is set? + */ + if ((rx->u.rx.status->flag & RX_FLAG_DECRYPTED) && + (rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED)) + return TXRX_CONTINUE; + + hdrlen = ieee80211_get_hdrlen(rx->fc); + + if (rx->skb->len < 8 + hdrlen) + return TXRX_DROP; /* TODO: count this? */ + + /* + * no need to call ieee80211_wep_get_keyidx, + * it verifies a bunch of things we've done already + */ + keyidx = rx->skb->data[hdrlen + 3] >> 6; + + rx->key = rcu_dereference(rx->sdata->keys[keyidx]); + + /* + * RSNA-protected unicast frames should always be sent with + * pairwise or station-to-station keys, but for WEP we allow + * using a key index as well. + */ + if (rx->key && rx->key->conf.alg != ALG_WEP && + !is_multicast_ether_addr(hdr->addr1)) + rx->key = NULL; } - if (rx->fc & IEEE80211_FCTL_PROTECTED && rx->key && rx->u.rx.ra_match) { + if (rx->key) { rx->key->tx_rx_count++; - if (unlikely(rx->local->key_tx_rx_threshold && - rx->key->tx_rx_count > - rx->local->key_tx_rx_threshold)) { - ieee80211_key_threshold_notify(rx->dev, rx->key, - rx->sta); - } + /* TODO: add threshold stuff again */ + } else { +#ifdef CONFIG_MAC80211_DEBUG + if (net_ratelimit()) + printk(KERN_DEBUG "%s: RX protected frame," + " but have no key\n", rx->dev->name); +#endif /* CONFIG_MAC80211_DEBUG */ + return TXRX_DROP; } - return TXRX_CONTINUE; + /* Check for weak IVs if possible */ + if (rx->sta && rx->key->conf.alg == ALG_WEP && + ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) && + (!(rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED) || + !(rx->u.rx.status->flag & RX_FLAG_DECRYPTED)) && + ieee80211_wep_is_weak_iv(rx->skb, rx->key)) + rx->sta->wep_weak_iv_count++; + + switch (rx->key->conf.alg) { + case ALG_WEP: + result = ieee80211_crypto_wep_decrypt(rx); + break; + case ALG_TKIP: + result = ieee80211_crypto_tkip_decrypt(rx); + break; + case ALG_CCMP: + result = ieee80211_crypto_ccmp_decrypt(rx); + break; + } + + /* either the frame has been decrypted or will be dropped */ + rx->u.rx.status->flag |= RX_FLAG_DECRYPTED; + + return result; } static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta) { struct ieee80211_sub_if_data *sdata; + DECLARE_MAC_BUF(mac); + sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); if (sdata->bss) @@ -376,8 +555,8 @@ static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta) sta->flags |= WLAN_STA_PS; sta->pspoll = 0; #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG - printk(KERN_DEBUG "%s: STA " MAC_FMT " aid %d enters power " - "save mode\n", dev->name, MAC_ARG(sta->addr), sta->aid); + printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n", + dev->name, print_mac(mac, sta->addr), sta->aid); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ } @@ -388,6 +567,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) int sent = 0; struct ieee80211_sub_if_data *sdata; struct ieee80211_tx_packet_data *pkt_data; + DECLARE_MAC_BUF(mac); sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); if (sdata->bss) @@ -401,14 +581,14 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) bss_tim_clear(local, sdata->bss, sta->aid); } #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG - printk(KERN_DEBUG "%s: STA " MAC_FMT " aid %d exits power " - "save mode\n", dev->name, MAC_ARG(sta->addr), sta->aid); + printk(KERN_DEBUG "%s: STA %s aid %d exits power save mode\n", + dev->name, print_mac(mac, sta->addr), sta->aid); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ /* Send all buffered frames to the station */ while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) { pkt_data = (struct ieee80211_tx_packet_data *) skb->cb; sent++; - pkt_data->requeue = 1; + pkt_data->flags |= IEEE80211_TXPD_REQUEUE; dev_queue_xmit(skb); } while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) { @@ -416,11 +596,11 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) local->total_ps_buffered--; sent++; #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG - printk(KERN_DEBUG "%s: STA " MAC_FMT " aid %d send PS frame " + printk(KERN_DEBUG "%s: STA %s aid %d send PS frame " "since STA not sleeping anymore\n", dev->name, - MAC_ARG(sta->addr), sta->aid); + print_mac(mac, sta->addr), sta->aid); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ - pkt_data->requeue = 1; + pkt_data->flags |= IEEE80211_TXPD_REQUEUE; dev_queue_xmit(skb); } @@ -454,17 +634,14 @@ ieee80211_rx_h_sta_process(struct ieee80211_txrx_data *rx) sta->last_rx = jiffies; } - if (!rx->u.rx.ra_match) + if (!(rx->flags & IEEE80211_TXRXD_RXRA_MATCH)) return TXRX_CONTINUE; sta->rx_fragments++; sta->rx_bytes += rx->skb->len; - sta->last_rssi = (sta->last_rssi * 15 + - rx->u.rx.status->ssi) / 16; - sta->last_signal = (sta->last_signal * 15 + - rx->u.rx.status->signal) / 16; - sta->last_noise = (sta->last_noise * 15 + - rx->u.rx.status->noise) / 16; + sta->last_rssi = rx->u.rx.status->ssi; + sta->last_signal = rx->u.rx.status->signal; + sta->last_noise = rx->u.rx.status->noise; if (!(rx->fc & IEEE80211_FCTL_MOREFRAGS)) { /* Change STA power saving mode only in the end of a frame @@ -491,62 +668,6 @@ ieee80211_rx_h_sta_process(struct ieee80211_txrx_data *rx) return TXRX_CONTINUE; } /* ieee80211_rx_h_sta_process */ -static ieee80211_txrx_result -ieee80211_rx_h_wep_weak_iv_detection(struct ieee80211_txrx_data *rx) -{ - if (!rx->sta || !(rx->fc & IEEE80211_FCTL_PROTECTED) || - (rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || - !rx->key || rx->key->alg != ALG_WEP || !rx->u.rx.ra_match) - return TXRX_CONTINUE; - - /* Check for weak IVs, if hwaccel did not remove IV from the frame */ - if ((rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) || - rx->key->force_sw_encrypt) { - u8 *iv = ieee80211_wep_is_weak_iv(rx->skb, rx->key); - if (iv) { - rx->sta->wep_weak_iv_count++; - } - } - - return TXRX_CONTINUE; -} - -static ieee80211_txrx_result -ieee80211_rx_h_wep_decrypt(struct ieee80211_txrx_data *rx) -{ - /* If the device handles decryption totally, skip this test */ - if (rx->local->hw.flags & IEEE80211_HW_DEVICE_HIDES_WEP) - return TXRX_CONTINUE; - - if ((rx->key && rx->key->alg != ALG_WEP) || - !(rx->fc & IEEE80211_FCTL_PROTECTED) || - ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA && - ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT || - (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_AUTH))) - return TXRX_CONTINUE; - - if (!rx->key) { - printk(KERN_DEBUG "%s: RX WEP frame, but no key set\n", - rx->dev->name); - return TXRX_DROP; - } - - if (!(rx->u.rx.status->flag & RX_FLAG_DECRYPTED) || - rx->key->force_sw_encrypt) { - if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key)) { - printk(KERN_DEBUG "%s: RX WEP frame, decrypt " - "failed\n", rx->dev->name); - return TXRX_DROP; - } - } else if (rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) { - ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key); - /* remove ICV */ - skb_trim(rx->skb, rx->skb->len - 4); - } - - return TXRX_CONTINUE; -} - static inline struct ieee80211_fragment_entry * ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata, unsigned int frag, unsigned int seq, int rx_queue, @@ -564,13 +685,15 @@ ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata, #ifdef CONFIG_MAC80211_DEBUG struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) entry->skb_list.next->data; + DECLARE_MAC_BUF(mac); + DECLARE_MAC_BUF(mac2); printk(KERN_DEBUG "%s: RX reassembly removed oldest " "fragment entry (idx=%d age=%lu seq=%d last_frag=%d " - "addr1=" MAC_FMT " addr2=" MAC_FMT "\n", + "addr1=%s addr2=%s\n", sdata->dev->name, idx, jiffies - entry->first_frag_time, entry->seq, - entry->last_frag, MAC_ARG(hdr->addr1), - MAC_ARG(hdr->addr2)); + entry->last_frag, print_mac(mac, hdr->addr1), + print_mac(mac2, hdr->addr2)); #endif /* CONFIG_MAC80211_DEBUG */ __skb_queue_purge(&entry->skb_list); } @@ -636,6 +759,7 @@ ieee80211_rx_h_defragment(struct ieee80211_txrx_data *rx) unsigned int frag, seq; struct ieee80211_fragment_entry *entry; struct sk_buff *skb; + DECLARE_MAC_BUF(mac); hdr = (struct ieee80211_hdr *) rx->skb->data; sc = le16_to_cpu(hdr->seq_ctrl); @@ -655,7 +779,7 @@ ieee80211_rx_h_defragment(struct ieee80211_txrx_data *rx) /* This is the first fragment of a new frame. */ entry = ieee80211_reassemble_add(rx->sdata, frag, seq, rx->u.rx.queue, &(rx->skb)); - if (rx->key && rx->key->alg == ALG_CCMP && + if (rx->key && rx->key->conf.alg == ALG_CCMP && (rx->fc & IEEE80211_FCTL_PROTECTED)) { /* Store CCMP PN so that we can verify that the next * fragment has a sequential PN value. */ @@ -682,7 +806,7 @@ ieee80211_rx_h_defragment(struct ieee80211_txrx_data *rx) if (entry->ccmp) { int i; u8 pn[CCMP_PN_LEN], *rpn; - if (!rx->key || rx->key->alg != ALG_CCMP) + if (!rx->key || rx->key->conf.alg != ALG_CCMP) return TXRX_DROP; memcpy(pn, entry->last_pn, CCMP_PN_LEN); for (i = CCMP_PN_LEN - 1; i >= 0; i--) { @@ -692,12 +816,15 @@ ieee80211_rx_h_defragment(struct ieee80211_txrx_data *rx) } rpn = rx->key->u.ccmp.rx_pn[rx->u.rx.queue]; if (memcmp(pn, rpn, CCMP_PN_LEN) != 0) { - printk(KERN_DEBUG "%s: defrag: CCMP PN not sequential" - " A2=" MAC_FMT " PN=%02x%02x%02x%02x%02x%02x " - "(expected %02x%02x%02x%02x%02x%02x)\n", - rx->dev->name, MAC_ARG(hdr->addr2), - rpn[0], rpn[1], rpn[2], rpn[3], rpn[4], rpn[5], - pn[0], pn[1], pn[2], pn[3], pn[4], pn[5]); + if (net_ratelimit()) + printk(KERN_DEBUG "%s: defrag: CCMP PN not " + "sequential A2=%s" + " PN=%02x%02x%02x%02x%02x%02x " + "(expected %02x%02x%02x%02x%02x%02x)\n", + rx->dev->name, print_mac(mac, hdr->addr2), + rpn[0], rpn[1], rpn[2], rpn[3], rpn[4], + rpn[5], pn[0], pn[1], pn[2], pn[3], + pn[4], pn[5]); return TXRX_DROP; } memcpy(entry->last_pn, pn, CCMP_PN_LEN); @@ -728,7 +855,7 @@ ieee80211_rx_h_defragment(struct ieee80211_txrx_data *rx) } /* Complete frame has been reassembled - process it now */ - rx->fragmented = 1; + rx->flags |= IEEE80211_TXRXD_FRAGMENTED; out: if (rx->sta) @@ -745,11 +872,12 @@ ieee80211_rx_h_ps_poll(struct ieee80211_txrx_data *rx) { struct sk_buff *skb; int no_pending_pkts; + DECLARE_MAC_BUF(mac); if (likely(!rx->sta || (rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_CTL || (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_PSPOLL || - !rx->u.rx.ra_match)) + !(rx->flags & IEEE80211_TXRXD_RXRA_MATCH))) return TXRX_CONTINUE; skb = skb_dequeue(&rx->sta->tx_filtered); @@ -770,9 +898,8 @@ ieee80211_rx_h_ps_poll(struct ieee80211_txrx_data *rx) rx->sta->pspoll = 1; #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG - printk(KERN_DEBUG "STA " MAC_FMT " aid %d: PS Poll (entries " - "after %d)\n", - MAC_ARG(rx->sta->addr), rx->sta->aid, + printk(KERN_DEBUG "STA %s aid %d: PS Poll (entries after %d)\n", + print_mac(mac, rx->sta->addr), rx->sta->aid, skb_queue_len(&rx->sta->ps_tx_buf)); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ @@ -795,9 +922,9 @@ ieee80211_rx_h_ps_poll(struct ieee80211_txrx_data *rx) } #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG } else if (!rx->u.rx.sent_ps_buffered) { - printk(KERN_DEBUG "%s: STA " MAC_FMT " sent PS Poll even " + printk(KERN_DEBUG "%s: STA %s sent PS Poll even " "though there is no buffered frames for it\n", - rx->dev->name, MAC_ARG(rx->sta->addr)); + rx->dev->name, print_mac(mac, rx->sta->addr)); #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ } @@ -833,15 +960,9 @@ static ieee80211_txrx_result ieee80211_rx_h_802_1x_pae(struct ieee80211_txrx_data *rx) { if (rx->sdata->eapol && ieee80211_is_eapol(rx->skb) && - rx->sdata->type != IEEE80211_IF_TYPE_STA && rx->u.rx.ra_match) { - /* Pass both encrypted and unencrypted EAPOL frames to user - * space for processing. */ - if (!rx->local->apdev) - return TXRX_DROP; - ieee80211_rx_mgmt(rx->local, rx->skb, rx->u.rx.status, - ieee80211_msg_normal); - return TXRX_QUEUED; - } + rx->sdata->type != IEEE80211_IF_TYPE_STA && + (rx->flags & IEEE80211_TXRXD_RXRA_MATCH)) + return TXRX_CONTINUE; if (unlikely(rx->sdata->ieee802_1x && (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA && @@ -851,9 +972,10 @@ ieee80211_rx_h_802_1x_pae(struct ieee80211_txrx_data *rx) #ifdef CONFIG_MAC80211_DEBUG struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; - printk(KERN_DEBUG "%s: dropped frame from " MAC_FMT + DECLARE_MAC_BUF(mac); + printk(KERN_DEBUG "%s: dropped frame from %s" " (unauthorized port)\n", rx->dev->name, - MAC_ARG(hdr->addr2)); + print_mac(mac, hdr->addr2)); #endif /* CONFIG_MAC80211_DEBUG */ return TXRX_DROP; } @@ -864,8 +986,11 @@ ieee80211_rx_h_802_1x_pae(struct ieee80211_txrx_data *rx) static ieee80211_txrx_result ieee80211_rx_h_drop_unencrypted(struct ieee80211_txrx_data *rx) { - /* If the device handles decryption totally, skip this test */ - if (rx->local->hw.flags & IEEE80211_HW_DEVICE_HIDES_WEP) + /* + * Pass through unencrypted frames if the hardware has + * decrypted them already. + */ + if (rx->u.rx.status->flag & RX_FLAG_DECRYPTED) return TXRX_CONTINUE; /* Drop unencrypted frames if key is set. */ @@ -873,10 +998,10 @@ ieee80211_rx_h_drop_unencrypted(struct ieee80211_txrx_data *rx) (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA && (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_NULLFUNC && (rx->key || rx->sdata->drop_unencrypted) && - (rx->sdata->eapol == 0 || - !ieee80211_is_eapol(rx->skb)))) { - printk(KERN_DEBUG "%s: RX non-WEP frame, but expected " - "encryption\n", rx->dev->name); + (rx->sdata->eapol == 0 || !ieee80211_is_eapol(rx->skb)))) { + if (net_ratelimit()) + printk(KERN_DEBUG "%s: RX non-WEP frame, but expected " + "encryption\n", rx->dev->name); return TXRX_DROP; } return TXRX_CONTINUE; @@ -894,6 +1019,10 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx) u8 src[ETH_ALEN]; struct sk_buff *skb = rx->skb, *skb2; struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + DECLARE_MAC_BUF(mac); + DECLARE_MAC_BUF(mac2); + DECLARE_MAC_BUF(mac3); + DECLARE_MAC_BUF(mac4); fc = rx->fc; if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)) @@ -922,10 +1051,13 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx) if (unlikely(sdata->type != IEEE80211_IF_TYPE_AP && sdata->type != IEEE80211_IF_TYPE_VLAN)) { - printk(KERN_DEBUG "%s: dropped ToDS frame (BSSID=" - MAC_FMT " SA=" MAC_FMT " DA=" MAC_FMT ")\n", - dev->name, MAC_ARG(hdr->addr1), - MAC_ARG(hdr->addr2), MAC_ARG(hdr->addr3)); + if (net_ratelimit()) + printk(KERN_DEBUG "%s: dropped ToDS frame " + "(BSSID=%s SA=%s DA=%s)\n", + dev->name, + print_mac(mac, hdr->addr1), + print_mac(mac2, hdr->addr2), + print_mac(mac3, hdr->addr3)); return TXRX_DROP; } break; @@ -935,12 +1067,14 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx) memcpy(src, hdr->addr4, ETH_ALEN); if (unlikely(sdata->type != IEEE80211_IF_TYPE_WDS)) { - printk(KERN_DEBUG "%s: dropped FromDS&ToDS frame (RA=" - MAC_FMT " TA=" MAC_FMT " DA=" MAC_FMT " SA=" - MAC_FMT ")\n", - rx->dev->name, MAC_ARG(hdr->addr1), - MAC_ARG(hdr->addr2), MAC_ARG(hdr->addr3), - MAC_ARG(hdr->addr4)); + if (net_ratelimit()) + printk(KERN_DEBUG "%s: dropped FromDS&ToDS " + "frame (RA=%s TA=%s DA=%s SA=%s)\n", + rx->dev->name, + print_mac(mac, hdr->addr1), + print_mac(mac2, hdr->addr2), + print_mac(mac3, hdr->addr3), + print_mac(mac4, hdr->addr4)); return TXRX_DROP; } break; @@ -949,9 +1083,10 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx) memcpy(dst, hdr->addr1, ETH_ALEN); memcpy(src, hdr->addr3, ETH_ALEN); - if (sdata->type != IEEE80211_IF_TYPE_STA) { + if (sdata->type != IEEE80211_IF_TYPE_STA || + (is_multicast_ether_addr(dst) && + !compare_ether_addr(src, dev->dev_addr))) return TXRX_DROP; - } break; case 0: /* DA SA BSSID */ @@ -960,12 +1095,12 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx) if (sdata->type != IEEE80211_IF_TYPE_IBSS) { if (net_ratelimit()) { - printk(KERN_DEBUG "%s: dropped IBSS frame (DA=" - MAC_FMT " SA=" MAC_FMT " BSSID=" MAC_FMT - ")\n", - dev->name, MAC_ARG(hdr->addr1), - MAC_ARG(hdr->addr2), - MAC_ARG(hdr->addr3)); + printk(KERN_DEBUG "%s: dropped IBSS frame " + "(DA=%s SA=%s BSSID=%s)\n", + dev->name, + print_mac(mac, hdr->addr1), + print_mac(mac2, hdr->addr2), + print_mac(mac3, hdr->addr3)); } return TXRX_DROP; } @@ -1006,24 +1141,26 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx) skb2 = NULL; - sdata->stats.rx_packets++; - sdata->stats.rx_bytes += skb->len; + dev->stats.rx_packets++; + dev->stats.rx_bytes += skb->len; if (local->bridge_packets && (sdata->type == IEEE80211_IF_TYPE_AP - || sdata->type == IEEE80211_IF_TYPE_VLAN) && rx->u.rx.ra_match) { + || sdata->type == IEEE80211_IF_TYPE_VLAN) && + (rx->flags & IEEE80211_TXRXD_RXRA_MATCH)) { if (is_multicast_ether_addr(skb->data)) { /* send multicast frames both to higher layers in * local net stack and back to the wireless media */ skb2 = skb_copy(skb, GFP_ATOMIC); - if (!skb2) + if (!skb2 && net_ratelimit()) printk(KERN_DEBUG "%s: failed to clone " "multicast frame\n", dev->name); } else { struct sta_info *dsta; dsta = sta_info_get(local, skb->data); if (dsta && !dsta->dev) { - printk(KERN_DEBUG "Station with null dev " - "structure!\n"); + if (net_ratelimit()) + printk(KERN_DEBUG "Station with null " + "dev structure!\n"); } else if (dsta && dsta->dev == dev) { /* Destination station is associated to this * AP, so send the frame directly to it and @@ -1060,21 +1197,17 @@ ieee80211_rx_h_mgmt(struct ieee80211_txrx_data *rx) { struct ieee80211_sub_if_data *sdata; - if (!rx->u.rx.ra_match) + if (!(rx->flags & IEEE80211_TXRXD_RXRA_MATCH)) return TXRX_DROP; sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); if ((sdata->type == IEEE80211_IF_TYPE_STA || sdata->type == IEEE80211_IF_TYPE_IBSS) && - !rx->local->user_space_mlme) { + !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)) ieee80211_sta_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status); - } else { - /* Management frames are sent to hostapd for processing */ - if (!rx->local->apdev) - return TXRX_DROP; - ieee80211_rx_mgmt(rx->local, rx->skb, rx->u.rx.status, - ieee80211_msg_normal); - } + else + return TXRX_DROP; + return TXRX_QUEUED; } @@ -1126,6 +1259,8 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev, struct ieee80211_txrx_data *rx) { int keyidx, hdrlen; + DECLARE_MAC_BUF(mac); + DECLARE_MAC_BUF(mac2); hdrlen = ieee80211_get_hdrlen_from_skb(rx->skb); if (rx->skb->len >= hdrlen + 4) @@ -1133,80 +1268,59 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev, else keyidx = -1; - /* TODO: verify that this is not triggered by fragmented - * frames (hw does not verify MIC for them). */ - printk(KERN_DEBUG "%s: TKIP hwaccel reported Michael MIC " - "failure from " MAC_FMT " to " MAC_FMT " keyidx=%d\n", - dev->name, MAC_ARG(hdr->addr2), MAC_ARG(hdr->addr1), keyidx); + if (net_ratelimit()) + printk(KERN_DEBUG "%s: TKIP hwaccel reported Michael MIC " + "failure from %s to %s keyidx=%d\n", + dev->name, print_mac(mac, hdr->addr2), + print_mac(mac2, hdr->addr1), keyidx); if (!sta) { - /* Some hardware versions seem to generate incorrect - * Michael MIC reports; ignore them to avoid triggering - * countermeasures. */ - printk(KERN_DEBUG "%s: ignored spurious Michael MIC " - "error for unknown address " MAC_FMT "\n", - dev->name, MAC_ARG(hdr->addr2)); + /* + * Some hardware seem to generate incorrect Michael MIC + * reports; ignore them to avoid triggering countermeasures. + */ + if (net_ratelimit()) + printk(KERN_DEBUG "%s: ignored spurious Michael MIC " + "error for unknown address %s\n", + dev->name, print_mac(mac, hdr->addr2)); goto ignore; } if (!(rx->fc & IEEE80211_FCTL_PROTECTED)) { - printk(KERN_DEBUG "%s: ignored spurious Michael MIC " - "error for a frame with no ISWEP flag (src " - MAC_FMT ")\n", dev->name, MAC_ARG(hdr->addr2)); + if (net_ratelimit()) + printk(KERN_DEBUG "%s: ignored spurious Michael MIC " + "error for a frame with no PROTECTED flag (src " + "%s)\n", dev->name, print_mac(mac, hdr->addr2)); goto ignore; } - if ((rx->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV) && - rx->sdata->type == IEEE80211_IF_TYPE_AP) { - keyidx = ieee80211_wep_get_keyidx(rx->skb); - /* AP with Pairwise keys support should never receive Michael - * MIC errors for non-zero keyidx because these are reserved - * for group keys and only the AP is sending real multicast - * frames in BSS. */ - if (keyidx) { + if (rx->sdata->type == IEEE80211_IF_TYPE_AP && keyidx) { + /* + * APs with pairwise keys should never receive Michael MIC + * errors for non-zero keyidx because these are reserved for + * group keys and only the AP is sending real multicast + * frames in the BSS. + */ + if (net_ratelimit()) printk(KERN_DEBUG "%s: ignored Michael MIC error for " - "a frame with non-zero keyidx (%d) (src " MAC_FMT - ")\n", dev->name, keyidx, MAC_ARG(hdr->addr2)); - goto ignore; - } + "a frame with non-zero keyidx (%d)" + " (src %s)\n", dev->name, keyidx, + print_mac(mac, hdr->addr2)); + goto ignore; } if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA && ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT || (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_AUTH)) { - printk(KERN_DEBUG "%s: ignored spurious Michael MIC " - "error for a frame that cannot be encrypted " - "(fc=0x%04x) (src " MAC_FMT ")\n", - dev->name, rx->fc, MAC_ARG(hdr->addr2)); + if (net_ratelimit()) + printk(KERN_DEBUG "%s: ignored spurious Michael MIC " + "error for a frame that cannot be encrypted " + "(fc=0x%04x) (src %s)\n", + dev->name, rx->fc, print_mac(mac, hdr->addr2)); goto ignore; } - do { - union iwreq_data wrqu; - char *buf = kmalloc(128, GFP_ATOMIC); - if (!buf) - break; - - /* TODO: needed parameters: count, key type, TSC */ - sprintf(buf, "MLME-MICHAELMICFAILURE.indication(" - "keyid=%d %scast addr=" MAC_FMT ")", - keyidx, hdr->addr1[0] & 0x01 ? "broad" : "uni", - MAC_ARG(hdr->addr2)); - memset(&wrqu, 0, sizeof(wrqu)); - wrqu.data.length = strlen(buf); - wireless_send_event(rx->dev, IWEVCUSTOM, &wrqu, buf); - kfree(buf); - } while (0); - - /* TODO: consider verifying the MIC error report with software - * implementation if we get too many spurious reports from the - * hardware. */ - if (!rx->local->apdev) - goto ignore; - ieee80211_rx_mgmt(rx->local, rx->skb, rx->u.rx.status, - ieee80211_msg_michael_mic_failure); - return; - + mac80211_ev_michael_mic_failure(rx->dev, keyidx, hdr); ignore: dev_kfree_skb(rx->skb); rx->skb = NULL; @@ -1215,15 +1329,10 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev, ieee80211_rx_handler ieee80211_rx_handlers[] = { ieee80211_rx_h_if_stats, - ieee80211_rx_h_monitor, ieee80211_rx_h_passive_scan, ieee80211_rx_h_check, - ieee80211_rx_h_load_key, + ieee80211_rx_h_decrypt, ieee80211_rx_h_sta_process, - ieee80211_rx_h_ccmp_decrypt, - ieee80211_rx_h_tkip_decrypt, - ieee80211_rx_h_wep_weak_iv_detection, - ieee80211_rx_h_wep_decrypt, ieee80211_rx_h_defragment, ieee80211_rx_h_ps_poll, ieee80211_rx_h_michael_mic_verify, @@ -1252,34 +1361,35 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, if (!bssid) return 0; if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) { - if (!rx->u.rx.in_scan) + if (!(rx->flags & IEEE80211_TXRXD_RXIN_SCAN)) return 0; - rx->u.rx.ra_match = 0; + rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH; } else if (!multicast && compare_ether_addr(sdata->dev->dev_addr, hdr->addr1) != 0) { - if (!sdata->promisc) + if (!(sdata->dev->flags & IFF_PROMISC)) return 0; - rx->u.rx.ra_match = 0; + rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH; } break; case IEEE80211_IF_TYPE_IBSS: if (!bssid) return 0; if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) { - if (!rx->u.rx.in_scan) + if (!(rx->flags & IEEE80211_TXRXD_RXIN_SCAN)) return 0; - rx->u.rx.ra_match = 0; + rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH; } else if (!multicast && compare_ether_addr(sdata->dev->dev_addr, hdr->addr1) != 0) { - if (!sdata->promisc) + if (!(sdata->dev->flags & IFF_PROMISC)) return 0; - rx->u.rx.ra_match = 0; + rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH; } else if (!rx->sta) rx->sta = ieee80211_ibss_add_sta(sdata->dev, rx->skb, bssid, hdr->addr2); break; + case IEEE80211_IF_TYPE_VLAN: case IEEE80211_IF_TYPE_AP: if (!bssid) { if (compare_ether_addr(sdata->dev->dev_addr, @@ -1287,11 +1397,12 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, return 0; } else if (!ieee80211_bssid_match(bssid, sdata->dev->dev_addr)) { - if (!rx->u.rx.in_scan) + if (!(rx->flags & IEEE80211_TXRXD_RXIN_SCAN)) return 0; - rx->u.rx.ra_match = 0; + rx->flags &= ~IEEE80211_TXRXD_RXRA_MATCH; } - if (sdata->dev == sdata->local->mdev && !rx->u.rx.in_scan) + if (sdata->dev == sdata->local->mdev && + !(rx->flags & IEEE80211_TXRXD_RXIN_SCAN)) /* do not receive anything via * master device when not scanning */ return 0; @@ -1303,6 +1414,13 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2)) return 0; break; + case IEEE80211_IF_TYPE_MNTR: + /* take everything */ + break; + case IEEE80211_IF_TYPE_INVALID: + /* should never get here */ + WARN_ON(1); + break; } return 1; @@ -1321,14 +1439,29 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_hdr *hdr; struct ieee80211_txrx_data rx; u16 type; - int radiotap_len = 0, prepres; + int prepres; struct ieee80211_sub_if_data *prev = NULL; struct sk_buff *skb_new; u8 *bssid; + int hdrlen; - if (status->flag & RX_FLAG_RADIOTAP) { - radiotap_len = ieee80211_get_radiotap_len(skb->data); - skb_pull(skb, radiotap_len); + /* + * key references and virtual interfaces are protected using RCU + * and this requires that we are in a read-side RCU section during + * receive processing + */ + rcu_read_lock(); + + /* + * Frames with failed FCS/PLCP checksum are not returned, + * all other frames are returned without radiotap header + * if it was previously present. + * Also, frames with less than 16 bytes are dropped. + */ + skb = ieee80211_rx_monitor(local, skb, status); + if (!skb) { + rcu_read_unlock(); + return; } hdr = (struct ieee80211_hdr *) skb->data; @@ -1337,19 +1470,29 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, rx.local = local; rx.u.rx.status = status; - rx.fc = skb->len >= 2 ? le16_to_cpu(hdr->frame_control) : 0; + rx.fc = le16_to_cpu(hdr->frame_control); type = rx.fc & IEEE80211_FCTL_FTYPE; + + /* + * Drivers are required to align the payload data to a four-byte + * boundary, so the last two bits of the address where it starts + * may not be set. The header is required to be directly before + * the payload data, padding like atheros hardware adds which is + * inbetween the 802.11 header and the payload is not supported, + * the driver is required to move the 802.11 header further back + * in that case. + */ + hdrlen = ieee80211_get_hdrlen(rx.fc); + WARN_ON_ONCE(((unsigned long)(skb->data + hdrlen)) & 3); + if (type == IEEE80211_FTYPE_DATA || type == IEEE80211_FTYPE_MGMT) local->dot11ReceivedFragmentCount++; - if (skb->len >= 16) { - sta = rx.sta = sta_info_get(local, hdr->addr2); - if (sta) { - rx.dev = rx.sta->dev; - rx.sdata = IEEE80211_DEV_TO_SUB_IF(rx.dev); - } - } else - sta = rx.sta = NULL; + sta = rx.sta = sta_info_get(local, hdr->addr2); + if (sta) { + rx.dev = rx.sta->dev; + rx.sdata = IEEE80211_DEV_TO_SUB_IF(rx.dev); + } if ((status->flag & RX_FLAG_MMIC_ERROR)) { ieee80211_rx_michael_mic_report(local->mdev, hdr, sta, &rx); @@ -1357,29 +1500,34 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, } if (unlikely(local->sta_scanning)) - rx.u.rx.in_scan = 1; + rx.flags |= IEEE80211_TXRXD_RXIN_SCAN; if (__ieee80211_invoke_rx_handlers(local, local->rx_pre_handlers, &rx, sta) != TXRX_CONTINUE) goto end; skb = rx.skb; - skb_push(skb, radiotap_len); - if (sta && !sta->assoc_ap && !(sta->flags & WLAN_STA_WDS) && - !local->iff_promiscs && !is_multicast_ether_addr(hdr->addr1)) { - rx.u.rx.ra_match = 1; + if (sta && !(sta->flags & (WLAN_STA_WDS | WLAN_STA_ASSOC_AP)) && + !atomic_read(&local->iff_promiscs) && + !is_multicast_ether_addr(hdr->addr1)) { + rx.flags |= IEEE80211_TXRXD_RXRA_MATCH; ieee80211_invoke_rx_handlers(local, local->rx_handlers, &rx, rx.sta); sta_info_put(sta); + rcu_read_unlock(); return; } - bssid = ieee80211_get_bssid(hdr, skb->len - radiotap_len); + bssid = ieee80211_get_bssid(hdr, skb->len); - read_lock(&local->sub_if_lock); - list_for_each_entry(sdata, &local->sub_if_list, list) { - rx.u.rx.ra_match = 1; + list_for_each_entry_rcu(sdata, &local->interfaces, list) { + if (!netif_running(sdata->dev)) + continue; + if (sdata->type == IEEE80211_IF_TYPE_MNTR) + continue; + + rx.flags |= IEEE80211_TXRXD_RXRA_MATCH; prepres = prepare_for_handlers(sdata, bssid, &rx, hdr); /* prepare_for_handlers can change sta */ sta = rx.sta; @@ -1387,21 +1535,36 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, if (!prepres) continue; - if (prev) { - skb_new = skb_copy(skb, GFP_ATOMIC); - if (!skb_new) { - if (net_ratelimit()) - printk(KERN_DEBUG "%s: failed to copy " - "multicast frame for %s", - local->mdev->name, prev->dev->name); - continue; - } - rx.skb = skb_new; - rx.dev = prev->dev; - rx.sdata = prev; - ieee80211_invoke_rx_handlers(local, local->rx_handlers, - &rx, sta); + /* + * frame is destined for this interface, but if it's not + * also for the previous one we handle that after the + * loop to avoid copying the SKB once too much + */ + + if (!prev) { + prev = sdata; + continue; + } + + /* + * frame was destined for the previous interface + * so invoke RX handlers for it + */ + + skb_new = skb_copy(skb, GFP_ATOMIC); + if (!skb_new) { + if (net_ratelimit()) + printk(KERN_DEBUG "%s: failed to copy " + "multicast frame for %s", + wiphy_name(local->hw.wiphy), + prev->dev->name); + continue; } + rx.skb = skb_new; + rx.dev = prev->dev; + rx.sdata = prev; + ieee80211_invoke_rx_handlers(local, local->rx_handlers, + &rx, sta); prev = sdata; } if (prev) { @@ -1412,9 +1575,10 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, &rx, sta); } else dev_kfree_skb(skb); - read_unlock(&local->sub_if_lock); end: + rcu_read_unlock(); + if (sta) sta_info_put(sta); }