diff options
-rw-r--r-- | sys/dev/pci/if_iwm.c | 229 |
1 files changed, 14 insertions, 215 deletions
diff --git a/sys/dev/pci/if_iwm.c b/sys/dev/pci/if_iwm.c index d0dba0daa30..0b2116dbc13 100644 --- a/sys/dev/pci/if_iwm.c +++ b/sys/dev/pci/if_iwm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_iwm.c,v 1.248 2019/09/02 12:50:12 stsp Exp $ */ +/* $OpenBSD: if_iwm.c,v 1.249 2019/09/05 16:28:06 stsp Exp $ */ /* * Copyright (c) 2014, 2016 genua gmbh <info@genua.de> @@ -367,8 +367,6 @@ int iwm_get_signal_strength(struct iwm_softc *, struct iwm_rx_phy_info *); void iwm_rx_rx_phy_cmd(struct iwm_softc *, struct iwm_rx_packet *, struct iwm_rx_data *); int iwm_get_noise(const struct iwm_statistics_rx_non_phy *); -int iwm_ccmp_decap(struct iwm_softc *, struct mbuf *, - struct ieee80211_node *); void iwm_rx_rx_mpdu(struct iwm_softc *, struct iwm_rx_packet *, struct iwm_rx_data *); void iwm_enable_ht_cck_fallback(struct iwm_softc *, struct iwm_node *); @@ -450,10 +448,6 @@ int iwm_disassoc(struct iwm_softc *); int iwm_run(struct iwm_softc *); int iwm_run_stop(struct iwm_softc *); struct ieee80211_node *iwm_node_alloc(struct ieee80211com *); -int iwm_set_key(struct ieee80211com *, struct ieee80211_node *, - struct ieee80211_key *); -void iwm_delete_key(struct ieee80211com *, - struct ieee80211_node *, struct ieee80211_key *); void iwm_calib_timeout(void *); int iwm_media_change(struct ifnet *); void iwm_newstate_task(void *); @@ -3435,91 +3429,11 @@ iwm_get_noise(const struct iwm_statistics_rx_non_phy *stats) return (nbant == 0) ? -127 : (total / nbant) - 107; } -int -iwm_ccmp_decap(struct iwm_softc *sc, struct mbuf *m, struct ieee80211_node *ni) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct ieee80211_key *k = &ni->ni_pairwise_key; - struct ieee80211_frame *wh; - struct ieee80211_rx_ba *ba; - uint64_t pn, *prsc; - uint8_t *ivp; - uint8_t tid; - int hdrlen, hasqos; - - wh = mtod(m, struct ieee80211_frame *); - hdrlen = ieee80211_get_hdrlen(wh); - ivp = (uint8_t *)wh + hdrlen; - - /* Check that ExtIV bit is be set. */ - if (!(ivp[3] & IEEE80211_WEP_EXTIV)) { - DPRINTF(("CCMP decap ExtIV not set\n")); - return 1; - } - hasqos = ieee80211_has_qos(wh); - tid = hasqos ? ieee80211_get_qos(wh) & IEEE80211_QOS_TID : 0; - ba = hasqos ? &ni->ni_rx_ba[tid] : NULL; - prsc = &k->k_rsc[tid]; - - /* Extract the 48-bit PN from the CCMP header. */ - pn = (uint64_t)ivp[0] | - (uint64_t)ivp[1] << 8 | - (uint64_t)ivp[4] << 16 | - (uint64_t)ivp[5] << 24 | - (uint64_t)ivp[6] << 32 | - (uint64_t)ivp[7] << 40; - if (pn <= *prsc) { - if (hasqos && ba->ba_state == IEEE80211_BA_AGREED) { - /* - * This is an A-MPDU subframe. - * Such frames may be received out of order due to - * legitimate retransmissions of failed subframes - * in previous A-MPDUs. Duplicates will be handled - * in ieee80211_input() as part of A-MPDU reordering. - */ - } else if (ieee80211_has_seq(wh)) { - /* - * Not necessarily a replayed frame since we did not - * check the sequence number of the 802.11 header yet. - */ - int nrxseq, orxseq; - - nrxseq = letoh16(*(u_int16_t *)wh->i_seq) >> - IEEE80211_SEQ_SEQ_SHIFT; - if (hasqos) - orxseq = ni->ni_qos_rxseqs[tid]; - else - orxseq = ni->ni_rxseq; - if (nrxseq < orxseq) { - DPRINTF(("CCMP replayed (n=%d < o=%d)\n", - nrxseq, orxseq)); - ic->ic_stats.is_ccmp_replays++; - return 1; - } - } else { - DPRINTF(("CCMP replayed\n")); - ic->ic_stats.is_ccmp_replays++; - return 1; - } - } - /* Update last seen packet number. */ - *prsc = pn; - - /* Clear Protected bit and strip IV. */ - wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED; - memmove(mtod(m, caddr_t) + IEEE80211_CCMP_HDRLEN, wh, hdrlen); - m_adj(m, IEEE80211_CCMP_HDRLEN); - /* Strip MIC. */ - m_adj(m, -IEEE80211_CCMP_MICLEN); - return 0; -} - void iwm_rx_rx_mpdu(struct iwm_softc *sc, struct iwm_rx_packet *pkt, struct iwm_rx_data *data) { struct ieee80211com *ic = &sc->sc_ic; - struct ifnet *ifp = IC2IFP(ic); struct ieee80211_frame *wh; struct ieee80211_node *ni; struct ieee80211_rxinfo rxi; @@ -3594,38 +3508,6 @@ iwm_rx_rx_mpdu(struct iwm_softc *sc, struct iwm_rx_packet *pkt, rxi.rxi_rssi = rssi; rxi.rxi_tstamp = device_timestamp; - /* Handle hardware decryption. */ - if (((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_CTL) - && (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) && - !IEEE80211_IS_MULTICAST(wh->i_addr1) && - (ni->ni_flags & IEEE80211_NODE_RXPROT) && - ni->ni_pairwise_key.k_cipher == IEEE80211_CIPHER_CCMP) { - if ((rx_pkt_status & IWM_RX_MPDU_RES_STATUS_SEC_ENC_MSK) != - IWM_RX_MPDU_RES_STATUS_SEC_CCM_ENC) { - ic->ic_stats.is_ccmp_dec_errs++; - ifp->if_ierrors++; - m_freem(m); - goto done; - } - /* Check whether decryption was successful or not. */ - if ((rx_pkt_status & - (IWM_RX_MPDU_RES_STATUS_DEC_DONE | - IWM_RX_MPDU_RES_STATUS_MIC_OK)) != - (IWM_RX_MPDU_RES_STATUS_DEC_DONE | - IWM_RX_MPDU_RES_STATUS_MIC_OK)) { - ic->ic_stats.is_ccmp_dec_errs++; - ifp->if_ierrors++; - m_freem(m); - goto done; - } - if (iwm_ccmp_decap(sc, m, ni) != 0) { - ifp->if_ierrors++; - m_freem(m); - goto done; - } - rxi.rxi_flags |= IEEE80211_RXI_HWDEC; - } - #if NBPFILTER > 0 if (sc->sc_drvbpf != NULL) { struct mbuf mb; @@ -3683,7 +3565,6 @@ iwm_rx_rx_mpdu(struct iwm_softc *sc, struct iwm_rx_packet *pkt, } #endif ieee80211_input(IC2IFP(ic), m, ni, &rxi); -done: /* * ieee80211_input() might have changed our BSS. * Restore ic_bss's channel if we are still in the same BSS. @@ -4330,7 +4211,6 @@ iwm_tx(struct iwm_softc *sc, struct mbuf *m, struct ieee80211_node *ni, int ac) struct ieee80211_frame *wh; struct ieee80211_key *k = NULL; const struct iwm_rate *rinfo; - uint8_t *ivp; uint32_t flags; u_int hdrlen; bus_dma_segment_t *seg; @@ -4397,47 +4277,15 @@ iwm_tx(struct iwm_softc *sc, struct mbuf *m, struct ieee80211_node *ni, int ac) bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT); } #endif - totlen = m->m_pkthdr.len; if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { - k = ieee80211_get_txkey(ic, wh, ni); - if (k->k_cipher != IEEE80211_CIPHER_CCMP) { - if ((m = ieee80211_encrypt(ic, m, k)) == NULL) - return ENOBUFS; - - /* 802.11 header may have moved. */ - wh = mtod(m, struct ieee80211_frame *); - totlen = m->m_pkthdr.len; - } else { - /* HW appends CCMP MIC */ - totlen += IEEE80211_CCMP_HDRLEN; - } - } - - /* Copy 802.11 header in TX command. */ - memcpy(((uint8_t *)tx) + sizeof(*tx), wh, hdrlen); - - if (k != NULL && k->k_cipher == IEEE80211_CIPHER_CCMP) { - /* Trim 802.11 header and prepend CCMP IV. */ - m_adj(m, hdrlen - IEEE80211_CCMP_HDRLEN); - ivp = mtod(m, u_int8_t *); - k->k_tsc++; /* increment the 48-bit PN */ - ivp[0] = k->k_tsc; /* PN0 */ - ivp[1] = k->k_tsc >> 8; /* PN1 */ - ivp[2] = 0; /* Rsvd */ - ivp[3] = k->k_id << 6 | IEEE80211_WEP_EXTIV; - ivp[4] = k->k_tsc >> 16; /* PN2 */ - ivp[5] = k->k_tsc >> 24; /* PN3 */ - ivp[6] = k->k_tsc >> 32; /* PN4 */ - ivp[7] = k->k_tsc >> 40; /* PN5 */ - - tx->sec_ctl = IWM_TX_CMD_SEC_CCM; - memcpy(tx->key, k->k_key, k->k_len); - } else { - /* Trim 802.11 header. */ - m_adj(m, hdrlen); - tx->sec_ctl = 0; + k = ieee80211_get_txkey(ic, wh, ni); + if ((m = ieee80211_encrypt(ic, m, k)) == NULL) + return ENOBUFS; + /* 802.11 header may have moved. */ + wh = mtod(m, struct ieee80211_frame *); } + totlen = m->m_pkthdr.len; flags = 0; if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { @@ -4490,10 +4338,17 @@ iwm_tx(struct iwm_softc *sc, struct mbuf *m, struct ieee80211_node *ni, int ac) tx->dram_lsb_ptr = htole32(data->scratch_paddr); tx->dram_msb_ptr = iwm_get_dma_hi_addr(data->scratch_paddr); + /* Copy 802.11 header in TX command. */ + memcpy(((uint8_t *)tx) + sizeof(*tx), wh, hdrlen); + flags |= IWM_TX_CMD_FLG_BT_DIS | IWM_TX_CMD_FLG_SEQ_CTL; + tx->sec_ctl = 0; tx->tx_flags |= htole32(flags); + /* Trim 802.11 header. */ + m_adj(m, hdrlen); + err = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m, BUS_DMA_NOWAIT | BUS_DMA_WRITE); if (err && err != EFBIG) { @@ -6090,59 +5945,6 @@ iwm_node_alloc(struct ieee80211com *ic) return malloc(sizeof (struct iwm_node), M_DEVBUF, M_NOWAIT | M_ZERO); } -int -iwm_set_key(struct ieee80211com *ic, struct ieee80211_node *ni, - struct ieee80211_key *k) -{ - struct iwm_softc *sc = ic->ic_softc; - struct iwm_add_sta_key_cmd cmd = { 0 }; - - if ((k->k_flags & IEEE80211_KEY_GROUP) || - k->k_cipher != IEEE80211_CIPHER_CCMP) { - /* Fallback to software crypto for other ciphers. */ - return (ieee80211_set_key(ic, ni, k)); - } - - cmd.key_flags = htole16(IWM_STA_KEY_FLG_CCM | - IWM_STA_KEY_FLG_WEP_KEY_MAP | - ((k->k_id << IWM_STA_KEY_FLG_KEYID_POS) & - IWM_STA_KEY_FLG_KEYID_MSK)); - if (k->k_flags & IEEE80211_KEY_GROUP) - cmd.key_flags |= htole16(IWM_STA_KEY_MULTICAST); - - memcpy(cmd.key, k->k_key, k->k_len); - cmd.key_offset = 0; - cmd.sta_id = IWM_STATION_ID; - - return iwm_send_cmd_pdu(sc, IWM_ADD_STA_KEY, IWM_CMD_ASYNC, - sizeof(cmd), &cmd); -} - -void -iwm_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni, - struct ieee80211_key *k) -{ - struct iwm_softc *sc = ic->ic_softc; - struct iwm_add_sta_key_cmd cmd = { 0 }; - - if ((k->k_flags & IEEE80211_KEY_GROUP) || - (k->k_cipher != IEEE80211_CIPHER_CCMP)) { - /* Fallback to software crypto for other ciphers. */ - ieee80211_delete_key(ic, ni, k); - return; - } - - cmd.key_flags = htole16(IWM_STA_KEY_NOT_VALID | - IWM_STA_KEY_FLG_NO_ENC | IWM_STA_KEY_FLG_WEP_KEY_MAP | - ((k->k_id << IWM_STA_KEY_FLG_KEYID_POS) & - IWM_STA_KEY_FLG_KEYID_MSK)); - memcpy(cmd.key, k->k_key, k->k_len); - cmd.key_offset = 0; - cmd.sta_id = IWM_STATION_ID; - - iwm_send_cmd_pdu(sc, IWM_ADD_STA_KEY, IWM_CMD_ASYNC, sizeof(cmd), &cmd); -} - void iwm_calib_timeout(void *arg) { @@ -7336,7 +7138,6 @@ iwm_notif_intr(struct iwm_softc *sc) case IWM_DTS_MEASUREMENT_NOTIFICATION: break; - case IWM_ADD_STA_KEY: case IWM_PHY_CONFIGURATION_CMD: case IWM_TX_ANT_CONFIGURATION_CMD: case IWM_ADD_STA: @@ -8019,8 +7820,6 @@ iwm_attach(struct device *parent, struct device *self, void *aux) ic->ic_node_alloc = iwm_node_alloc; ic->ic_bgscan_start = iwm_bgscan; - ic->ic_set_key = iwm_set_key; - ic->ic_delete_key = iwm_delete_key; /* Override 802.11 state transition machine. */ sc->sc_newstate = ic->ic_newstate; |