summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorStefan Sperling <stsp@cvs.openbsd.org>2021-05-03 08:23:06 +0000
committerStefan Sperling <stsp@cvs.openbsd.org>2021-05-03 08:23:06 +0000
commit6627b22a0378ef07326564b9d6684148aa7bb225 (patch)
treef7cfe771124499e928093a57471d48f33865455e /sys
parentb4fedf929d5bb07acd8a6f6ee14c12092cc28bf7 (diff)
work around an athn(4) device problem with bogus Michael MIC failures
Clients using Tx aggregation against an athn(4) hostap will send block ack request control frames whenever they need to sync their Tx block ack window. athn(4) dropped such frames due to bogus Michael MIC failures reported by the hardware decryption engine. Ignore such failures for control frames in order to fix athn(4) hostap mode against clients which use Tx aggregation. Additionally, only report Michael MIC failures to the net80211 stack if the offending client is actually using TKIP, which would also have prevented the problem since we require CCMP as group cipher in our default configuration. Problem reported and fix tested by kettenis@
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/ic/ar5008.c37
1 files changed, 26 insertions, 11 deletions
diff --git a/sys/dev/ic/ar5008.c b/sys/dev/ic/ar5008.c
index 2b77b0d686d..816a3b09ee2 100644
--- a/sys/dev/ic/ar5008.c
+++ b/sys/dev/ic/ar5008.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ar5008.c,v 1.65 2021/04/15 18:25:43 stsp Exp $ */
+/* $OpenBSD: ar5008.c,v 1.66 2021/05/03 08:23:05 stsp Exp $ */
/*-
* Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
@@ -865,7 +865,7 @@ ar5008_rx_process(struct athn_softc *sc, struct mbuf_list *ml)
struct ieee80211_rxinfo rxi;
struct ieee80211_node *ni;
struct mbuf *m, *m1;
- int error, len;
+ int error, len, michael_mic_failure = 0;
bf = SIMPLEQ_FIRST(&rxq->head);
if (__predict_false(bf == NULL)) { /* Should not happen. */
@@ -915,16 +915,12 @@ ar5008_rx_process(struct athn_softc *sc, struct mbuf_list *ml)
ic->ic_stats.is_ccmp_dec_errs++;
} else if (ds->ds_status8 & AR_RXS8_MICHAEL_ERR) {
DPRINTFN(2, ("Michael MIC failure\n"));
- /* Report Michael MIC failures to net80211. */
- ic->ic_stats.is_rx_locmicfail++;
- ieee80211_michael_mic_failure(ic, 0);
- /*
- * XXX Check that it is not a control frame
- * (invalid MIC failures on valid ctl frames).
- */
+ michael_mic_failure = 1;
+ }
+ if (!michael_mic_failure) {
+ ifp->if_ierrors++;
+ goto skip;
}
- ifp->if_ierrors++;
- goto skip;
}
len = MS(ds->ds_status1, AR_RXS1_DATA_LEN);
@@ -978,6 +974,25 @@ ar5008_rx_process(struct athn_softc *sc, struct mbuf_list *ml)
wh = mtod(m, struct ieee80211_frame *);
ni = ieee80211_find_rxnode(ic, wh);
+ if (michael_mic_failure) {
+ /*
+ * Check that it is not a control frame
+ * (invalid MIC failures on valid ctl frames).
+ */
+ if (!(wh->i_fc[0] & IEEE80211_FC0_TYPE_CTL) &&
+ (ic->ic_flags & IEEE80211_F_RSNON) &&
+ (ni->ni_rsncipher == IEEE80211_CIPHER_TKIP ||
+ ni->ni_rsngroupcipher == IEEE80211_CIPHER_TKIP)) {
+ /* Report Michael MIC failures to net80211. */
+ ic->ic_stats.is_rx_locmicfail++;
+ ieee80211_michael_mic_failure(ic, 0);
+ ifp->if_ierrors++;
+ ieee80211_release_node(ic, ni);
+ m_freem(m);
+ goto skip;
+ }
+ }
+
/* Remove any HW padding after the 802.11 header. */
if (!(wh->i_fc[0] & IEEE80211_FC0_TYPE_CTL)) {
u_int hdrlen = ieee80211_get_hdrlen(wh);