ieee80211_rx_h_load_key(struct ieee80211_txrx_data *rx)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
- int always_sta_key;
+ int keyidx;
+ int hdrlen;
- 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.
+ *
+ * There is also a slight problem in IBSS mode: GTKs are negotiated
+ * with each station, that is something we don't currently handle.
+ */
+
+ if (!(rx->fc & IEEE80211_FCTL_PROTECTED))
+ return TXRX_CONTINUE;
- if (rx->sta && rx->sta->key && always_sta_key) {
+ /*
+ * No point in finding a key if the frame is neither
+ * addressed to us nor a multicast frame.
+ */
+ if (!rx->u.rx.ra_match)
+ return TXRX_CONTINUE;
+
+ if (!is_multicast_ether_addr(hdr->addr1) && rx->sta && rx->sta->key) {
rx->key = rx->sta->key;
} 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->local->hw.flags & IEEE80211_HW_WEP_INCLUDE_IV))
+ 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 = 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->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 >
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 &&
return TXRX_CONTINUE;
if (!rx->key) {
- printk(KERN_DEBUG "%s: RX WEP frame, but no key set\n",
- rx->dev->name);
+ if (net_ratelimit())
+ 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);
+ if (net_ratelimit())
+ 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) {
}
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=" 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]);
return TXRX_DROP;
}
memcpy(entry->last_pn, pn, CCMP_PN_LEN);
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 might have
+ * decrypted them already without telling us, but that can only
+ * be true if we either didn't find a key or the found key is
+ * uploaded to the hardware.
+ */
+ if ((rx->local->hw.flags & IEEE80211_HW_DEVICE_HIDES_WEP) &&
+ (!rx->key || !rx->key->force_sw_encrypt))
return TXRX_CONTINUE;
/* Drop unencrypted frames if key is set. */
(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);
+ if (net_ratelimit())
+ printk(KERN_DEBUG "%s: RX non-WEP frame, but expected "
+ "encryption\n", rx->dev->name);
return TXRX_DROP;
}
return TXRX_CONTINUE;
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=" MAC_FMT
+ " SA=" MAC_FMT
+ " DA=" MAC_FMT ")\n",
+ dev->name,
+ MAC_ARG(hdr->addr1),
+ MAC_ARG(hdr->addr2),
+ MAC_ARG(hdr->addr3));
return TXRX_DROP;
}
break;
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=" 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));
return TXRX_DROP;
}
break;
/* 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
/* 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 " MAC_FMT " to " MAC_FMT " keyidx=%d\n",
+ dev->name, MAC_ARG(hdr->addr2), MAC_ARG(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));
+ if (net_ratelimit())
+ printk(KERN_DEBUG "%s: ignored spurious Michael MIC "
+ "error for unknown address " MAC_FMT "\n",
+ dev->name, MAC_ARG(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 ISWEP flag (src "
+ MAC_FMT ")\n", dev->name, MAC_ARG(hdr->addr2));
goto ignore;
}
* for group keys and only the AP is sending real multicast
* frames in BSS. */
if (keyidx) {
- 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));
+ 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;
}
}
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 " MAC_FMT ")\n",
+ dev->name, rx->fc, MAC_ARG(hdr->addr2));
goto ignore;
}
list_for_each_entry(sdata, &local->sub_if_list, list) {
rx.u.rx.ra_match = 1;
+ if (!netif_running(sdata->dev))
+ continue;
+
prepres = prepare_for_handlers(sdata, bssid, &rx, hdr);
/* prepare_for_handlers can change sta */
sta = rx.sta;
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",
+ 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);
prev = sdata;
}
if (prev) {