diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c --- a/sys/compat/linuxkpi/common/src/linux_80211.c +++ b/sys/compat/linuxkpi/common/src/linux_80211.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2020-2023 The FreeBSD Foundation - * Copyright (c) 2020-2022 Bjoern A. Zeeb + * Copyright (c) 2020-2024 Bjoern A. Zeeb * * This software was developed by Björn Zeeb under sponsorship from * the FreeBSD Foundation. @@ -661,20 +661,85 @@ #ifdef LKPI_80211_HW_CRYPTO static int -_lkpi_iv_key_set_delete(struct ieee80211vap *vap, const struct ieee80211_key *k, - enum set_key_cmd cmd) +_lkpi_iv_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k) { struct ieee80211com *ic; struct lkpi_hw *lhw; struct ieee80211_hw *hw; struct lkpi_vif *lvif; + struct lkpi_sta *lsta; struct ieee80211_vif *vif; struct ieee80211_sta *sta; struct ieee80211_node *ni; struct ieee80211_key_conf *kc; int error; - /* XXX TODO Check (k->wk_flags & IEEE80211_KEY_SWENCRYPT) and don't upload to driver/hw? */ + ic = vap->iv_ic; + lhw = ic->ic_softc; + hw = LHW_TO_HW(lhw); + lvif = VAP_TO_LVIF(vap); + vif = LVIF_TO_VIF(lvif); + + ni = vap->iv_bss; + sta = ieee80211_find_sta(vif, ni->ni_bssid); + if (sta == NULL) { + ic_printf(ic, "%s: sta %6D not found\n", __func__, ni->ni_bssid, ":"); + return (0); + } + lsta = STA_TO_LSTA(sta); + + if (lsta->kc == NULL) { +#ifdef LINUXKPI_DEBUG_80211 + if (linuxkpi_debug_80211 & D80211_TRACE) + ic_printf(ic, "%s: sta %6D and no key information, " + "returning success\n", __func__, ni->ni_bssid, ":"); +#endif + return (1); + } + kc = lsta->kc; + + error = lkpi_80211_mo_set_key(hw, DISABLE_KEY, vif, sta, kc); + if (error != 0) { + ic_printf(ic, "%s: set_key cmd %d(%s) for sta %6D failed: %d\n", + __func__, DISABLE_KEY, "DISABLE", ni->ni_bssid, ":", error); + return (0); + } + +#ifdef LINUXKPI_DEBUG_80211 + if (linuxkpi_debug_80211 & D80211_TRACE) + ic_printf(ic, "%s: set_key cmd %d(%s) for sta %6D succeeded: " + "keyidx %u hw_key_idx %u flags %#10x\n", __func__, + DISABLE_KEY, "DISABLE", ni->ni_bssid, ":", + kc->keyidx, kc->hw_key_idx, kc->flags); +#endif + kc = lsta->kc; + lsta->kc = NULL; + free(kc, M_LKPI80211); + return (1); +} + +static int +lkpi_iv_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k) +{ + + /* XXX-BZ one day we should replace this iterating over VIFs, or node list? */ + return (_lkpi_iv_key_delete(vap, k)); +} + +static int +_lkpi_iv_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k) +{ + struct ieee80211com *ic; + struct lkpi_hw *lhw; + struct ieee80211_hw *hw; + struct lkpi_vif *lvif; + struct lkpi_sta *lsta; + struct ieee80211_vif *vif; + struct ieee80211_sta *sta; + struct ieee80211_node *ni; + struct ieee80211_key_conf *kc; + uint32_t lcipher; + int error; ic = vap->iv_ic; lhw = ic->ic_softc; @@ -682,10 +747,38 @@ lvif = VAP_TO_LVIF(vap); vif = LVIF_TO_VIF(lvif); - memset(&kc, 0, sizeof(kc)); - kc = malloc(sizeof(*kc) + k->wk_keylen, M_LKPI80211, M_WAITOK | M_ZERO); - kc->cipher = lkpi_net80211_to_l80211_cipher_suite( + ni = vap->iv_bss; + sta = ieee80211_find_sta(vif, ni->ni_bssid); + if (sta == NULL) { + ic_printf(ic, "%s: sta %6D not found\n", __func__, ni->ni_bssid, ":"); + return (0); + } + lsta = STA_TO_LSTA(sta); + + if (lsta->kc != NULL) { + IMPROVE("Still in firmware? Del first. Can we assert this cannot happen?"); + ic_printf(ic, "%s: sta %6D found with key information\n", + __func__, ni->ni_bssid, ":"); + kc = lsta->kc; + lsta->kc = NULL; + free(kc, M_LKPI80211); + kc = NULL; /* safeguard */ + } + + lcipher = lkpi_net80211_to_l80211_cipher_suite( k->wk_cipher->ic_cipher, k->wk_keylen); + switch (lcipher) { + case WLAN_CIPHER_SUITE_CCMP: + break; + case WLAN_CIPHER_SUITE_TKIP: + default: + ic_printf(ic, "%s: CIPHER SUITE %#x not supported\n", __func__, lcipher); + IMPROVE(); + return (0); + } + + kc = malloc(sizeof(*kc) + k->wk_keylen, M_LKPI80211, M_WAITOK | M_ZERO); + kc->cipher = lcipher; kc->keyidx = k->wk_keyix; #if 0 kc->hw_key_idx = /* set by hw and needs to be passed for TX */; @@ -701,44 +794,39 @@ break; case WLAN_CIPHER_SUITE_TKIP: default: + /* currently UNREACH */ IMPROVE(); - return (0); + break; }; + lsta->kc = kc; - ni = vap->iv_bss; - sta = ieee80211_find_sta(vif, ni->ni_bssid); - if (sta != NULL) { - struct lkpi_sta *lsta; - - lsta = STA_TO_LSTA(sta); - lsta->kc = kc; - } - - error = lkpi_80211_mo_set_key(hw, cmd, vif, sta, kc); + error = lkpi_80211_mo_set_key(hw, SET_KEY, vif, sta, kc); if (error != 0) { - /* XXX-BZ leaking kc currently */ - ic_printf(ic, "%s: set_key failed: %d\n", __func__, error); + ic_printf(ic, "%s: set_key cmd %d(%s) for sta %6D failed: %d\n", + __func__, SET_KEY, "SET", ni->ni_bssid, ":", error); return (0); - } else { - ic_printf(ic, "%s: set_key succeeded: keyidx %u hw_key_idx %u " - "flags %#10x\n", __func__, - kc->keyidx, kc->hw_key_idx, kc->flags); - return (1); } -} -static int -lkpi_iv_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k) -{ +#ifdef LINUXKPI_DEBUG_80211 + if (linuxkpi_debug_80211 & D80211_TRACE) + ic_printf(ic, "%s: set_key cmd %d(%s) for sta %6D succeeded: " + "keyidx %u hw_key_idx %u flags %#10x\n", __func__, + SET_KEY, "SET", ni->ni_bssid, ":", + kc->keyidx, kc->hw_key_idx, kc->flags); +#endif - /* XXX-BZ one day we should replace this iterating over VIFs, or node list? */ - return (_lkpi_iv_key_set_delete(vap, k, DISABLE_KEY)); +#if 0 + /* Make sure we get the delete callback? */ + k->wk_flags |= IEEE80211_KEY_DEVKEY; +#endif + return (1); } + static int lkpi_iv_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k) { - return (_lkpi_iv_key_set_delete(vap, k, SET_KEY)); + return (_lkpi_iv_key_set(vap, k)); } #endif @@ -4734,6 +4822,29 @@ rx_stats.c_freq = rx_status->freq; rx_stats.c_ieee = ieee80211_mhz2ieee(rx_stats.c_freq, rx_stats.c_band); + /* + * We only need these for LKPI_80211_HW_CRYPTO in theory but in + * case the hardware does something we do not expect always leave + * these enabled. Leaving this as documentation. + */ +#if defined(LKPI_80211_HW_CRYPTO) || 1 + if (rx_status->flag & RX_FLAG_DECRYPTED) + rx_stats.c_pktflags |= IEEE80211_RX_F_DECRYPTED; + if (rx_status->flag & RX_FLAG_MMIC_STRIPPED) + rx_stats.c_pktflags |= IEEE80211_RX_F_MMIC_STRIP; + if (rx_status->flag & RX_FLAG_MIC_STRIPPED) { + IMPROVE("WARNING: no direct mapping for RX_FLAG_MIC_STRIPPED in net80211"); + rx_stats.c_pktflags |= IEEE80211_RX_F_MMIC_STRIP; + } + if (rx_status->flag & RX_FLAG_IV_STRIPPED) + rx_stats.c_pktflags |= IEEE80211_RX_F_IV_STRIP; + if (rx_status->flag & RX_FLAG_MMIC_ERROR) + rx_stats.c_pktflags |= IEEE80211_RX_F_FAIL_MIC; + if (rx_status->flag & RX_FLAG_FAILED_FCS_CRC) + rx_stats.c_pktflags |= IEEE80211_RX_F_FAIL_FCSCRC; + IMPROVE("map as many RX_FLAG_ -> IEEE80211_RX_F_ as possible"); +#endif + /* XXX (*sta_statistics)() to get to some of that? */ /* XXX-BZ dump the FreeBSD version of rx_stats as well! */