diff options
author | Damien Bergamini <damien@cvs.openbsd.org> | 2008-04-16 18:32:16 +0000 |
---|---|---|
committer | Damien Bergamini <damien@cvs.openbsd.org> | 2008-04-16 18:32:16 +0000 |
commit | 792a7af405f1bcd074df2d192736f0ff71180ce6 (patch) | |
tree | d1c8127338d31609e63b5a8c220604e11d416fa8 /sys/dev/pci | |
parent | c257d1252aa088da82103c7952e3c42933d743da (diff) |
Kernel implementation of the 4-way handshake and group-key
handshake protocols (both supplicant and authenticator state
machines) as defined in the IEEE 802.11i standard.
Software implementation of the TKIP (Temporal Key Integrity
Protocol) and CCMP (CTR with CBC-MAC Protocol) protocols.
This diff doesn't implement any of the 802.1X authentication
protocols and thus only PSK authentication (using pre-shared
keys) is currently supported.
In concrete terms, this adds support for WPA-PSK and WPA2-PSK
protocols, both in station and hostap modes.
The following drivers are marked as WPA-capable and should
work: bwi(4), malo(4), ral(4), iwn(4), wpi(4), ural(4),
rum(4), upgt(4), and zyd(4)
The following options have been added to ifconfig(8):
wpa, wpapsk, wpaprotos, wpaakms, wpaciphers, wpagroupcipher
wpa-psk(8) can be used to generate keys from passphrases.
tested by many@
ok deraadt@
Diffstat (limited to 'sys/dev/pci')
-rw-r--r-- | sys/dev/pci/if_ipw.c | 111 | ||||
-rw-r--r-- | sys/dev/pci/if_ipwvar.h | 4 | ||||
-rw-r--r-- | sys/dev/pci/if_iwn.c | 35 | ||||
-rw-r--r-- | sys/dev/pci/if_wpi.c | 33 |
4 files changed, 76 insertions, 107 deletions
diff --git a/sys/dev/pci/if_ipw.c b/sys/dev/pci/if_ipw.c index 9810a9f77d6..b6ff2171dcd 100644 --- a/sys/dev/pci/if_ipw.c +++ b/sys/dev/pci/if_ipw.c @@ -1,7 +1,7 @@ -/* $OpenBSD: if_ipw.c,v 1.71 2008/02/23 20:38:08 hshoexer Exp $ */ +/* $OpenBSD: if_ipw.c,v 1.72 2008/04/16 18:32:15 damien Exp $ */ /*- - * Copyright (c) 2004-2006 + * Copyright (c) 2004-2008 * Damien Bergamini <damien.bergamini@free.fr>. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -496,7 +496,6 @@ ipw_dma_alloc(struct ipw_softc *sc) error = ENOMEM; goto fail; } - MCLGET(sbuf->m, M_DONTWAIT); if (!(sbuf->m->m_flags & M_EXT)) { m_freem(sbuf->m); @@ -645,15 +644,12 @@ ipw_media_status(struct ifnet *ifp, struct ifmediareq *imr) switch (ic->ic_opmode) { case IEEE80211_M_STA: break; - case IEEE80211_M_IBSS: imr->ifm_active |= IFM_IEEE80211_IBSS; break; - case IEEE80211_M_MONITOR: imr->ifm_active |= IFM_IEEE80211_MONITOR; break; - case IEEE80211_M_AHDEMO: case IEEE80211_M_HOSTAP: /* should not get there */ @@ -835,7 +831,6 @@ ipw_data_intr(struct ipw_softc *sc, struct ipw_status *status, ifp->if_ierrors++; return; } - MCLGET(mnew, M_DONTWAIT); if (!(mnew->m_flags & M_EXT)) { m_freem(mnew); @@ -894,7 +889,6 @@ ipw_data_intr(struct ipw_softc *sc, struct ipw_status *status, #endif wh = mtod(m, struct ieee80211_frame *); - ni = ieee80211_find_rxnode(ic, wh); /* send the frame to the upper layer */ @@ -1101,7 +1095,7 @@ ipw_cmd(struct ipw_softc *sc, uint32_t type, void *data, uint32_t len) bus_dmamap_sync(sc->sc_dmat, sc->cmd_map, 0, sizeof (struct ipw_cmd), BUS_DMASYNC_PREWRITE); - + bus_dmamap_sync(sc->sc_dmat, sc->tbd_map, sc->txcur * sizeof (struct ipw_bd), sizeof (struct ipw_bd), BUS_DMASYNC_PREWRITE); @@ -1122,6 +1116,7 @@ ipw_tx_start(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni) struct ipw_softc *sc = ifp->if_softc; struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_frame *wh; + struct ieee80211_key *k; struct ipw_soft_bd *sbd; struct ipw_soft_hdr *shdr; struct ipw_soft_buf *sbuf; @@ -1130,9 +1125,10 @@ ipw_tx_start(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni) wh = mtod(m, struct ieee80211_frame *); - if (wh->i_fc[1] & IEEE80211_FC1_WEP) { - m = ieee80211_wep_crypt(ifp, m, 1); - if (m == NULL) + if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { + k = ieee80211_get_txkey(ic, wh, ni); + + if ((m = ieee80211_encrypt(ic, m, k)) == NULL) return ENOBUFS; /* packet header may have moved, reset our local pointer */ @@ -1163,7 +1159,7 @@ ipw_tx_start(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni) shdr->hdr.type = htole32(IPW_HDR_TYPE_SEND); shdr->hdr.subtype = htole32(0); - shdr->hdr.encrypted = (wh->i_fc[1] & IEEE80211_FC1_WEP) ? 1 : 0; + shdr->hdr.encrypted = (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) ? 1 : 0; shdr->hdr.encrypt = 0; shdr->hdr.keyidx = 0; shdr->hdr.keysz = 0; @@ -1192,7 +1188,6 @@ ipw_tx_start(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni) m_freem(m); return ENOMEM; } - M_DUP_PKTHDR(mnew, m); if (m->m_pkthdr.len > MHLEN) { MCLGET(mnew, M_DONTWAIT); @@ -1202,7 +1197,6 @@ ipw_tx_start(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni) return ENOMEM; } } - m_copydata(m, 0, m->m_pkthdr.len, mtod(mnew, caddr_t)); m_freem(m); mnew->m_len = mnew->m_pkthdr.len; @@ -1297,8 +1291,8 @@ ipw_start(struct ifnet *ifp) { struct ipw_softc *sc = ifp->if_softc; struct ieee80211com *ic = &sc->sc_ic; - struct mbuf *m; struct ieee80211_node *ni; + struct mbuf *m; if (ic->ic_state != IEEE80211_S_RUN) return; @@ -1317,16 +1311,13 @@ ipw_start(struct ifnet *ifp) if (ifp->if_bpf != NULL) bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT); #endif - m = ieee80211_encap(ifp, m, &ni); if (m == NULL) continue; - #if NBPFILTER > 0 if (ic->ic_rawbpf != NULL) bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT); #endif - if (ipw_tx_start(ifp, m, ni) != 0) { if (ni != NULL) ieee80211_release_node(ic, ni); @@ -1452,14 +1443,13 @@ ipw_read_table2(struct ipw_softc *sc, uint32_t off, void *buf, uint32_t *len) info = MEM_READ_4(sc, sc->table2_base + off + 4); count = info >> 16; - size = info & 0xffff; + size = info & 0xffff; total = count * size; if (total > *len) { *len = total; return EINVAL; } - *len = total; ipw_read_mem_1(sc, addr, buf, total); @@ -1469,6 +1459,7 @@ ipw_read_table2(struct ipw_softc *sc, uint32_t off, void *buf, uint32_t *len) void ipw_stop_master(struct ipw_softc *sc) { + uint32_t tmp; int ntries; /* disable interrupts */ @@ -1484,8 +1475,8 @@ ipw_stop_master(struct ipw_softc *sc) printf("%s: timeout waiting for master\n", sc->sc_dev.dv_xname); - CSR_WRITE_4(sc, IPW_CSR_RST, CSR_READ_4(sc, IPW_CSR_RST) | - IPW_RST_PRINCETON_RESET); + tmp = CSR_READ_4(sc, IPW_CSR_RST); + CSR_WRITE_4(sc, IPW_CSR_RST, tmp | IPW_RST_PRINCETON_RESET); sc->flags &= ~IPW_FLAG_FW_INITED; } @@ -1493,13 +1484,14 @@ ipw_stop_master(struct ipw_softc *sc) int ipw_reset(struct ipw_softc *sc) { + uint32_t tmp; int ntries; ipw_stop_master(sc); /* move adapter to D0 state */ - CSR_WRITE_4(sc, IPW_CSR_CTL, CSR_READ_4(sc, IPW_CSR_CTL) | - IPW_CTL_INIT); + tmp = CSR_READ_4(sc, IPW_CSR_CTL); + CSR_WRITE_4(sc, IPW_CSR_CTL, tmp | IPW_CTL_INIT); /* wait for clock stabilization */ for (ntries = 0; ntries < 1000; ntries++) { @@ -1510,13 +1502,13 @@ ipw_reset(struct ipw_softc *sc) if (ntries == 1000) return EIO; - CSR_WRITE_4(sc, IPW_CSR_RST, CSR_READ_4(sc, IPW_CSR_RST) | - IPW_RST_SW_RESET); + tmp = CSR_READ_4(sc, IPW_CSR_RST); + CSR_WRITE_4(sc, IPW_CSR_RST, tmp | IPW_RST_SW_RESET); DELAY(10); - CSR_WRITE_4(sc, IPW_CSR_CTL, CSR_READ_4(sc, IPW_CSR_CTL) | - IPW_CTL_INIT); + tmp = CSR_READ_4(sc, IPW_CSR_CTL); + CSR_WRITE_4(sc, IPW_CSR_CTL, tmp | IPW_CTL_INIT); return 0; } @@ -1526,6 +1518,7 @@ ipw_load_ucode(struct ipw_softc *sc, u_char *uc, int size) { int ntries; + /* voodoo from the Intel Linux driver */ MEM_WRITE_4(sc, 0x3000e0, 0x80000000); CSR_WRITE_4(sc, IPW_CSR_RST, 0); @@ -1577,7 +1570,7 @@ int ipw_load_firmware(struct ipw_softc *sc, u_char *fw, int size) { u_char *p, *end; - uint32_t dst; + uint32_t tmp, dst; uint16_t len; int error; @@ -1605,8 +1598,8 @@ ipw_load_firmware(struct ipw_softc *sc, u_char *fw, int size) /* tell the adapter to initialize the firmware */ CSR_WRITE_4(sc, IPW_CSR_RST, 0); - CSR_WRITE_4(sc, IPW_CSR_CTL, CSR_READ_4(sc, IPW_CSR_CTL) | - IPW_CTL_ALLOW_STANDBY); + tmp = CSR_READ_4(sc, IPW_CSR_CTL); + CSR_WRITE_4(sc, IPW_CSR_CTL, tmp | IPW_CTL_ALLOW_STANDBY); /* wait at most one second for firmware initialization to complete */ if ((error = tsleep(sc, 0, "ipwinit", hz)) != 0) { @@ -1615,8 +1608,9 @@ ipw_load_firmware(struct ipw_softc *sc, u_char *fw, int size) return error; } - CSR_WRITE_4(sc, IPW_CSR_IO, CSR_READ_4(sc, IPW_CSR_IO) | - IPW_IO_GPIO1_MASK | IPW_IO_GPIO3_MASK); + tmp = CSR_READ_4(sc, IPW_CSR_IO); + CSR_WRITE_4(sc, IPW_CSR_IO, tmp | IPW_IO_GPIO1_MASK | + IPW_IO_GPIO3_MASK); return 0; } @@ -1624,52 +1618,42 @@ ipw_load_firmware(struct ipw_softc *sc, u_char *fw, int size) int ipw_read_firmware(struct ipw_softc *sc, struct ipw_firmware *fw) { - struct ipw_firmware_hdr *hdr; + const struct ipw_firmware_hdr *hdr; const char *name; - u_char *p; size_t size; int error; switch (sc->sc_ic.ic_opmode) { case IEEE80211_M_STA: - case IEEE80211_M_HOSTAP: name = "ipw-bss"; break; - case IEEE80211_M_IBSS: - case IEEE80211_M_AHDEMO: name = "ipw-ibss"; break; - case IEEE80211_M_MONITOR: name = "ipw-monitor"; break; + default: + /* should not get there */ + return ENODEV; } - if ((error = loadfirmware(name, &fw->data, &size)) != 0) return error; - if (size < sizeof (struct ipw_firmware_hdr)) { + if (size < sizeof (*hdr)) { error = EINVAL; goto fail; } - - p = fw->data; - hdr = (struct ipw_firmware_hdr *)p; - fw->main_size = letoh32(hdr->main_size); + hdr = (const struct ipw_firmware_hdr *)fw->data; + fw->main_size = letoh32(hdr->main_size); fw->ucode_size = letoh32(hdr->ucode_size); - p += sizeof (struct ipw_firmware_hdr); - size -= sizeof (struct ipw_firmware_hdr); - - if (size < fw->main_size + fw->ucode_size) { + if (size < sizeof (*hdr) + fw->main_size + fw->ucode_size) { error = EINVAL; goto fail; } - - fw->main = p; - fw->ucode = p + fw->main_size; - sc->fw_data = fw->data; + fw->main = fw->data + sizeof (*hdr); + fw->ucode = fw->main + fw->main_size; return 0; @@ -1692,18 +1676,17 @@ ipw_config(struct ipw_softc *sc) switch (ic->ic_opmode) { case IEEE80211_M_STA: - case IEEE80211_M_HOSTAP: data = htole32(IPW_MODE_BSS); break; - case IEEE80211_M_IBSS: - case IEEE80211_M_AHDEMO: data = htole32(IPW_MODE_IBSS); break; - case IEEE80211_M_MONITOR: data = htole32(IPW_MODE_MONITOR); break; + default: + /* should not get there */ + return ENODEV; } DPRINTF(("Setting mode to %u\n", letoh32(data))); error = ipw_cmd(sc, IPW_CMD_SET_MODE, &data, sizeof data); @@ -1892,7 +1875,6 @@ ipw_init(struct ifnet *ifp) sc->sc_dev.dv_xname, error); goto fail1; } - if ((error = ipw_load_ucode(sc, fw.ucode, fw.ucode_size)) != 0) { printf("%s: could not load microcode\n", sc->sc_dev.dv_xname); goto fail2; @@ -1924,8 +1906,8 @@ ipw_init(struct ifnet *ifp) printf("%s: could not load firmware\n", sc->sc_dev.dv_xname); goto fail2; } - sc->flags |= IPW_FLAG_FW_INITED; + free(fw.data, M_DEVBUF); /* retrieve information tables base addresses */ sc->table1_base = CSR_READ_4(sc, IPW_CSR_TABLE1_BASE); @@ -1938,7 +1920,6 @@ ipw_init(struct ifnet *ifp) sc->sc_dev.dv_xname); goto fail2; } - ifp->if_flags &= ~IFF_OACTIVE; ifp->if_flags |= IFF_RUNNING; @@ -1969,14 +1950,6 @@ ipw_stop(struct ifnet *ifp, int disable) for (i = 0; i < IPW_NTBD; i++) ipw_release_sbd(sc, &sc->stbd_list[i]); - /* - * Free memory claimed by firmware. - */ - if (sc->fw_data) { - free(sc->fw_data, M_DEVBUF); - sc->fw_data = NULL; - } - ieee80211_new_state(ic, IEEE80211_S_INIT, -1); } diff --git a/sys/dev/pci/if_ipwvar.h b/sys/dev/pci/if_ipwvar.h index 56348ad2f92..ca0d5b73a4d 100644 --- a/sys/dev/pci/if_ipwvar.h +++ b/sys/dev/pci/if_ipwvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ipwvar.h,v 1.15 2008/02/23 21:35:41 hshoexer Exp $ */ +/* $OpenBSD: if_ipwvar.h,v 1.16 2008/04/16 18:32:15 damien Exp $ */ /*- * Copyright (c) 2004-2006 @@ -158,6 +158,4 @@ struct ipw_softc { #define sc_txtap sc_txtapu.th int sc_txtap_len; #endif - - void *fw_data; }; diff --git a/sys/dev/pci/if_iwn.c b/sys/dev/pci/if_iwn.c index 71f793a9bac..11eb562932e 100644 --- a/sys/dev/pci/if_iwn.c +++ b/sys/dev/pci/if_iwn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_iwn.c,v 1.17 2008/03/08 16:24:44 espie Exp $ */ +/* $OpenBSD: if_iwn.c,v 1.18 2008/04/16 18:32:15 damien Exp $ */ /*- * Copyright (c) 2007 @@ -135,7 +135,7 @@ int iwn_ioctl(struct ifnet *, u_long, caddr_t); int iwn_cmd(struct iwn_softc *, int, const void *, int, int); int iwn_setup_node_mrr(struct iwn_softc *, uint8_t, int); int iwn_set_key(struct ieee80211com *, struct ieee80211_node *, - const struct ieee80211_key *); + struct ieee80211_key *); void iwn_updateedca(struct ieee80211com *); void iwn_set_led(struct iwn_softc *, uint8_t, uint8_t, uint8_t); int iwn_set_critical_temp(struct iwn_softc *); @@ -293,6 +293,7 @@ iwn_attach(struct device *parent, struct device *self, void *aux) /* set device capabilities */ ic->ic_caps = IEEE80211_C_WEP | /* s/w WEP */ + IEEE80211_C_RSN | /* WPA/RSN */ IEEE80211_C_MONITOR | /* monitor mode supported */ IEEE80211_C_TXPMGT | /* tx power management */ IEEE80211_C_SHSLOT | /* short slot time supported */ @@ -322,7 +323,9 @@ iwn_attach(struct device *parent, struct device *self, void *aux) ieee80211_ifattach(ifp); ic->ic_node_alloc = iwn_node_alloc; ic->ic_newassoc = iwn_newassoc; +#ifdef notyet ic->ic_set_key = iwn_set_key; +#endif ic->ic_updateedca = iwn_updateedca; /* override state transition machine */ @@ -1457,7 +1460,7 @@ iwn_notif_intr(struct iwn_softc *sc) DPRINTFN(4,("rx notification qid=%x idx=%d flags=%x type=%d " "len=%d\n", desc->qid, desc->idx, desc->flags, desc->type, - letoh32(desc->len))); + letoh16(desc->len))); if (!(desc->qid & 0x80)) /* reply to a command */ iwn_cmd_intr(sc, desc); @@ -1674,12 +1677,13 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m0, struct ieee80211_node *ni, struct iwn_tx_cmd *cmd; struct iwn_cmd_data *tx; struct ieee80211_frame *wh; + struct ieee80211_key *k; struct mbuf *mnew; bus_addr_t paddr; uint32_t flags; uint8_t type; u_int hdrlen; - int i, rate, error, pad, ovhd = 0; + int i, rate, error, pad; desc = &ring->desc[ring->cur]; data = &ring->data[ring->cur]; @@ -1733,18 +1737,13 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m0, struct ieee80211_node *ni, /* no need to bzero tx, all fields are reinitialized here */ if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { - const struct ieee80211_key *key = - &ic->ic_nw_keys[ic->ic_wep_txkey]; - if (key->k_cipher == IEEE80211_CIPHER_WEP40) - tx->security = IWN_CIPHER_WEP40; - else - tx->security = IWN_CIPHER_WEP104; - tx->security |= ic->ic_wep_txkey << 6; - memcpy(&tx->key[3], key->k_key, key->k_len); - /* compute crypto overhead */ - ovhd = IEEE80211_WEP_TOTLEN; - } else - tx->security = 0; + k = ieee80211_get_txkey(ic, wh, ni); + + if ((m0 = ieee80211_encrypt(ic, m0, k)) == NULL) + return ENOBUFS; + + wh = mtod(m0, struct ieee80211_frame *); + } flags = IWN_TX_AUTO_SEQ; if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) @@ -1759,7 +1758,7 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m0, struct ieee80211_node *ni, /* check if RTS/CTS or CTS-to-self protection must be used */ if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { /* multicast frames are not sent at OFDM rates in 802.11b/g */ - if (m0->m_pkthdr.len + ovhd + IEEE80211_CRC_LEN > + if (m0->m_pkthdr.len + IEEE80211_CRC_LEN > ic->ic_rtsthreshold) { flags |= IWN_TX_NEED_RTS | IWN_TX_FULL_TXOP; } else if ((ic->ic_flags & IEEE80211_F_USEPROT) && @@ -2256,7 +2255,7 @@ iwn_setup_node_mrr(struct iwn_softc *sc, uint8_t id, int async) */ int iwn_set_key(struct ieee80211com *ic, struct ieee80211_node *ni, - const struct ieee80211_key *k) + struct ieee80211_key *k) { struct iwn_softc *sc = ic->ic_softc; struct iwn_node_info node; diff --git a/sys/dev/pci/if_wpi.c b/sys/dev/pci/if_wpi.c index f0cd31a8a1e..0549b16de86 100644 --- a/sys/dev/pci/if_wpi.c +++ b/sys/dev/pci/if_wpi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_wpi.c,v 1.59 2008/03/08 16:24:45 espie Exp $ */ +/* $OpenBSD: if_wpi.c,v 1.60 2008/04/16 18:32:15 damien Exp $ */ /*- * Copyright (c) 2006, 2007 @@ -130,7 +130,7 @@ int wpi_ioctl(struct ifnet *, u_long, caddr_t); int wpi_cmd(struct wpi_softc *, int, const void *, int, int); int wpi_mrr_setup(struct wpi_softc *); int wpi_set_key(struct ieee80211com *, struct ieee80211_node *, - const struct ieee80211_key *); + struct ieee80211_key *); void wpi_updateedca(struct ieee80211com *); void wpi_set_led(struct wpi_softc *, uint8_t, uint8_t, uint8_t); void wpi_enable_tsf(struct wpi_softc *, struct ieee80211_node *); @@ -270,6 +270,7 @@ wpi_attach(struct device *parent, struct device *self, void *aux) /* set device capabilities */ ic->ic_caps = IEEE80211_C_WEP | /* s/w WEP */ + IEEE80211_C_RSN | /* WPA/RSN */ IEEE80211_C_MONITOR | /* monitor mode supported */ IEEE80211_C_TXPMGT | /* tx power management */ IEEE80211_C_SHSLOT | /* short slot time supported */ @@ -299,7 +300,9 @@ wpi_attach(struct device *parent, struct device *self, void *aux) ieee80211_ifattach(ifp); ic->ic_node_alloc = wpi_node_alloc; ic->ic_newassoc = wpi_newassoc; +#ifdef notyet ic->ic_set_key = wpi_set_key; +#endif ic->ic_updateedca = wpi_updateedca; /* override state transition machine */ @@ -1569,9 +1572,10 @@ wpi_tx_data(struct wpi_softc *sc, struct mbuf *m0, struct ieee80211_node *ni, struct wpi_tx_cmd *cmd; struct wpi_cmd_data *tx; struct ieee80211_frame *wh; + struct ieee80211_key *k; struct mbuf *mnew; u_int hdrlen; - int i, rate, error, ovhd = 0; + int i, rate, error; desc = &ring->desc[ring->cur]; data = &ring->data[ring->cur]; @@ -1626,18 +1630,13 @@ wpi_tx_data(struct wpi_softc *sc, struct mbuf *m0, struct ieee80211_node *ni, tx->flags = 0; if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { - const struct ieee80211_key *key = - &ic->ic_nw_keys[ic->ic_wep_txkey]; - if (key->k_cipher == IEEE80211_CIPHER_WEP40) - tx->security = WPI_CIPHER_WEP40; - else - tx->security = WPI_CIPHER_WEP104; - tx->security |= ic->ic_wep_txkey << 6; - memcpy(&tx->key[3], key->k_key, key->k_len); - /* compute crypto overhead */ - ovhd = IEEE80211_WEP_TOTLEN; - } else - tx->security = 0; + k = ieee80211_get_txkey(ic, wh, ni); + + if ((m0 = ieee80211_encrypt(ic, m0, k)) == NULL) + return ENOBUFS; + + wh = mtod(m0, struct ieee80211_frame *); + } if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { tx->id = WPI_ID_BSS; @@ -1648,7 +1647,7 @@ wpi_tx_data(struct wpi_softc *sc, struct mbuf *m0, struct ieee80211_node *ni, /* check if RTS/CTS or CTS-to-self protection must be used */ if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { /* multicast frames are not sent at OFDM rates in 802.11b/g */ - if (m0->m_pkthdr.len + ovhd + IEEE80211_CRC_LEN > + if (m0->m_pkthdr.len + IEEE80211_CRC_LEN > ic->ic_rtsthreshold) { tx->flags |= htole32(WPI_TX_NEED_RTS | WPI_TX_FULL_TXOP); @@ -2118,7 +2117,7 @@ wpi_mrr_setup(struct wpi_softc *sc) */ int wpi_set_key(struct ieee80211com *ic, struct ieee80211_node *ni, - const struct ieee80211_key *k) + struct ieee80211_key *k) { struct wpi_softc *sc = ic->ic_softc; struct wpi_node_info node; |