From: damien Date: Thu, 28 Aug 2008 14:40:44 +0000 (+0000) Subject: WPA support for ipw(4). X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=2eb7e770256327b5318500fb6a207bacc6b6884c;p=openbsd WPA support for ipw(4). Did a lot of cleanup while I was there. --- diff --git a/share/man/man4/ipw.4 b/share/man/man4/ipw.4 index ad9e17cdf13..8bfd82c1b64 100644 --- a/share/man/man4/ipw.4 +++ b/share/man/man4/ipw.4 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ipw.4,v 1.27 2008/07/29 17:03:35 jmc Exp $ +.\" $OpenBSD: ipw.4,v 1.28 2008/08/28 14:40:44 damien Exp $ .\" .\" Copyright (c) 2004 .\" Damien Bergamini . All rights reserved. @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd $Mdocdate: July 29 2008 $ +.Dd $Mdocdate: August 28 2008 $ .Os .Dt IPW 4 .Sh NAME @@ -70,12 +70,18 @@ or to scan for access points. .Pp The .Nm -driver can be configured to use software -Wireless Equivalent Privacy (WEP). +driver can be configured to use +Wireless Equivalent Privacy (WEP) or +Wi-Fi Protected Access (WPA-PSK and WPA2-PSK). +WPA is the de facto encryption standard for wireless networks. It is strongly recommended that WEP not be used as the sole mechanism to secure wireless communication, due to serious weaknesses in it. +The +.Nm +driver relies on the software 802.11 stack for both encryption and decryption +of data frames. .Pp The .Nm @@ -118,16 +124,19 @@ channel 11, obtaining an IP address using DHCP: dhcp NONE NONE NONE nwkey 0x1deadbeef1 chan 11 .Ed .Pp -Configure ipw0 for WEP, using hex key -.Dq 0x1deadbeef1 : +Configure ipw0 to join network +.Dq my_net +using WPA-PSK with passphrase +.Dq my_passphrase : .Bd -literal -offset indent -# ifconfig ipw0 nwkey 0x1deadbeef1 +# ifconfig ipw0 nwid my_net wpa wpapsk \e + $(wpa-psk my_net my_passphrase) .Ed .Pp Return ipw0 to its default settings: .Bd -literal -offset indent # ifconfig ipw0 -bssid -chan media autoselect \e - nwid "" -nwkey + nwid "" -nwkey -wpa -wpapsk .Ed .Pp Join an existing BSS network, diff --git a/sys/dev/pci/if_ipw.c b/sys/dev/pci/if_ipw.c index dec88cbf888..ce7e03cc9c0 100644 --- a/sys/dev/pci/if_ipw.c +++ b/sys/dev/pci/if_ipw.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ipw.c,v 1.75 2008/08/27 09:28:38 damien Exp $ */ +/* $OpenBSD: if_ipw.c,v 1.76 2008/08/28 14:40:44 damien Exp $ */ /*- * Copyright (c) 2004-2008 @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -106,6 +107,8 @@ int ipw_reset(struct ipw_softc *); int ipw_load_ucode(struct ipw_softc *, u_char *, int); int ipw_load_firmware(struct ipw_softc *, u_char *, int); int ipw_read_firmware(struct ipw_softc *, struct ipw_firmware *); +void ipw_scan(void *, void *); +void ipw_auth_and_assoc(void *, void *); int ipw_config(struct ipw_softc *); int ipw_init(struct ifnet *); void ipw_stop(struct ifnet *, int); @@ -235,6 +238,7 @@ ipw_attach(struct device *parent, struct device *self, void *aux) IEEE80211_C_TXPMGT | /* tx power management */ IEEE80211_C_SHPREAMBLE | /* short preamble supported */ IEEE80211_C_WEP | /* s/w WEP */ + IEEE80211_C_RSN | /* WPA/RSN */ IEEE80211_C_SCANALL; /* h/w scanning */ /* read MAC address from EEPROM */ @@ -665,29 +669,25 @@ int ipw_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) { struct ipw_softc *sc = ic->ic_softc; - struct ieee80211_node *ni; - uint8_t macaddr[IEEE80211_ADDR_LEN]; - uint32_t len; + int error; switch (nstate) { - case IEEE80211_S_RUN: - DELAY(100); /* firmware needs a short delay here */ - - len = IEEE80211_ADDR_LEN; - ipw_read_table2(sc, IPW_INFO_CURRENT_BSSID, macaddr, &len); - - ni = ieee80211_find_node(ic, macaddr); - if (ni == NULL) - break; + case IEEE80211_S_SCAN: + error = workq_add_task(NULL, 0, ipw_scan, sc, NULL); + if (error != 0) + return error; + break; - (*ic->ic_node_copy)(ic, ic->ic_bss, ni); - ieee80211_node_newstate(ni, IEEE80211_STA_BSS); + case IEEE80211_S_AUTH: + error = workq_add_task(NULL, 0, ipw_auth_and_assoc, sc, NULL); + if (error != 0) + return error; break; + case IEEE80211_S_RUN: case IEEE80211_S_INIT: - case IEEE80211_S_SCAN: - case IEEE80211_S_AUTH: case IEEE80211_S_ASSOC: + /* nothing to do */ break; } @@ -761,11 +761,10 @@ ipw_command_intr(struct ipw_softc *sc, struct ipw_soft_buf *sbuf) cmd = mtod(sbuf->m, struct ipw_cmd *); - DPRINTFN(2, ("RX!CMD!%u!%u!%u!%u!%u\n", - letoh32(cmd->type), letoh32(cmd->subtype), letoh32(cmd->seq), - letoh32(cmd->len), letoh32(cmd->status))); + DPRINTFN(2, ("received command ack type=%u,status=%u\n", + letoh32(cmd->type), letoh32(cmd->status))); - wakeup(sc); + wakeup(&sc->cmd); } void @@ -780,29 +779,26 @@ ipw_newstate_intr(struct ipw_softc *sc, struct ipw_soft_buf *sbuf) state = letoh32(*mtod(sbuf->m, uint32_t *)); - DPRINTFN(2, ("RX!NEWSTATE!%u\n", state)); + DPRINTFN(2, ("firmware state changed to 0x%x\n", state)); switch (state) { case IPW_STATE_ASSOCIATED: ieee80211_new_state(ic, IEEE80211_S_RUN, -1); break; - case IPW_STATE_SCANNING: - /* don't leave run state on background scan */ - if (ic->ic_state != IEEE80211_S_RUN) - ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); - - ic->ic_flags |= IEEE80211_F_ASCAN; - break; - case IPW_STATE_SCAN_COMPLETE: - ic->ic_flags &= ~IEEE80211_F_ASCAN; + if (ic->ic_state == IEEE80211_S_SCAN) + ieee80211_end_scan(ifp); break; case IPW_STATE_ASSOCIATION_LOST: ieee80211_new_state(ic, IEEE80211_S_INIT, -1); break; + case IPW_STATE_DISABLED: + wakeup(sc); + break; + case IPW_STATE_RADIO_DISABLED: ifp->if_flags &= ~IFF_UP; ipw_stop(&ic->ic_if, 1); @@ -822,7 +818,8 @@ ipw_data_intr(struct ipw_softc *sc, struct ipw_status *status, struct ieee80211_node *ni; int error; - DPRINTFN(5, ("RX!DATA!%u!%u\n", letoh32(status->len), status->rssi)); + DPRINTFN(5, ("received data frame len=%u,rssi=%u\n", + letoh32(status->len), status->rssi)); /* * Try to allocate a new mbuf for this ring element and load it before @@ -907,7 +904,7 @@ ipw_data_intr(struct ipw_softc *sc, struct ipw_status *status, void ipw_notification_intr(struct ipw_softc *sc, struct ipw_soft_buf *sbuf) { - DPRINTFN(2, ("RX!NOTIFICATION\n")); + DPRINTFN(2, ("received notification\n")); } void @@ -1043,8 +1040,6 @@ ipw_intr(void *arg) /* disable interrupts */ CSR_WRITE_4(sc, IPW_CSR_INTR_MASK, 0); - DPRINTFN(8, ("INTR!0x%08x\n", r)); - if (r & (IPW_INTR_FATAL_ERROR | IPW_INTR_PARITY_ERROR)) { printf("%s: fatal firmware error\n", sc->sc_dev.dv_xname); ifp->if_flags &= ~IFF_UP; @@ -1074,25 +1069,27 @@ int ipw_cmd(struct ipw_softc *sc, uint32_t type, void *data, uint32_t len) { struct ipw_soft_bd *sbd; - int error; + int s, error; - sbd = &sc->stbd_list[sc->txcur]; + s = splnet(); + + sc->cmd.type = htole32(type); + sc->cmd.subtype = htole32(0); + sc->cmd.len = htole32(len); + sc->cmd.seq = htole32(0); + if (data != NULL) + bcopy(data, sc->cmd.data, len); error = bus_dmamap_load(sc->sc_dmat, sc->cmd_map, &sc->cmd, sizeof (struct ipw_cmd), NULL, BUS_DMA_NOWAIT); if (error != 0) { printf("%s: could not map command DMA memory\n", sc->sc_dev.dv_xname); + splx(s); return error; } - sc->cmd.type = htole32(type); - sc->cmd.subtype = htole32(0); - sc->cmd.len = htole32(len); - sc->cmd.seq = htole32(0); - if (data != NULL) - bcopy(data, sc->cmd.data, len); - + sbd = &sc->stbd_list[sc->txcur]; sbd->type = IPW_SBD_TYPE_COMMAND; sbd->bd->physaddr = htole32(sc->cmd_map->dm_segs[0].ds_addr); sbd->bd->len = htole32(sizeof (struct ipw_cmd)); @@ -1102,7 +1099,6 @@ 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); @@ -1111,10 +1107,13 @@ ipw_cmd(struct ipw_softc *sc, uint32_t type, void *data, uint32_t len) sc->txfree--; CSR_WRITE_4(sc, IPW_CSR_TX_WRITE_INDEX, sc->txcur); - DPRINTFN(2, ("TX!CMD!%u!%u!%u!%u\n", type, 0, 0, len)); + DPRINTFN(2, ("sending command type=%u,len=%u\n", type, len)); /* wait at most one second for command to complete */ - return tsleep(sc, 0, "ipwcmd", hz); + error = tsleep(&sc->cmd, 0, "ipwcmd", hz); + splx(s); + + return error; } int @@ -1241,11 +1240,6 @@ ipw_tx_start(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni) sbd->bd->flags = IPW_BD_FLAG_TX_FRAME_802_3 | IPW_BD_FLAG_TX_NOT_LAST_FRAGMENT; - DPRINTFN(5, ("TX!HDR!%u!%u!%u!%u", shdr->hdr.type, shdr->hdr.subtype, - shdr->hdr.encrypted, shdr->hdr.encrypt)); - DPRINTFN(5, ("!%s", ether_sprintf(shdr->hdr.src_addr))); - DPRINTFN(5, ("!%s\n", ether_sprintf(shdr->hdr.dst_addr))); - bus_dmamap_sync(sc->sc_dmat, sc->tbd_map, sc->txcur * sizeof (struct ipw_bd), sizeof (struct ipw_bd), BUS_DMASYNC_PREWRITE); @@ -1271,9 +1265,6 @@ ipw_tx_start(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni) sbd->bd->flags |= IPW_BD_FLAG_TX_NOT_LAST_FRAGMENT; } - DPRINTFN(5, ("TX!FRAG!%d!%d\n", i, - sbuf->map->dm_segs[i].ds_len)); - bus_dmamap_sync(sc->sc_dmat, sc->tbd_map, sc->txcur * sizeof (struct ipw_bd), sizeof (struct ipw_bd), BUS_DMASYNC_PREWRITE); @@ -1301,11 +1292,10 @@ ipw_start(struct ifnet *ifp) struct ieee80211_node *ni; struct mbuf *m; - for (;;) { - IF_PURGE(&ic->ic_mgtq); + if (ic->ic_state != IEEE80211_S_RUN) + return; - if (ic->ic_state != IEEE80211_S_RUN) - return; + for (;;) { IFQ_POLL(&ifp->if_snd, m); if (m == NULL) break; @@ -1671,18 +1661,174 @@ fail: free(fw->data, M_DEVBUF); return error; } +void +ipw_scan(void *arg1, void *arg2) +{ + struct ipw_softc *sc = arg1; + struct ifnet *ifp = &sc->sc_ic.ic_if; + struct ipw_scan_options scan; + uint8_t ssid[IEEE80211_NWID_LEN]; + int error; + + /* + * Firmware has a bug and does not honour the ``do not associate + * after scan'' bit in the scan command. To prevent the firmware + * from associating after the scan, we set the ESSID to something + * unlikely to be used by a real AP. + * XXX would setting the BSSID to a multicast address work? + */ + memset(ssid, '\r', sizeof ssid); + error = ipw_cmd(sc, IPW_CMD_SET_ESSID, ssid, sizeof ssid); + if (error != 0) + goto fail; + + /* no mandatory BSSID */ + DPRINTF(("Setting mandatory BSSID to null\n")); + error = ipw_cmd(sc, IPW_CMD_SET_MANDATORY_BSSID, NULL, 0); + if (error != 0) + goto fail; + + scan.flags = htole32(IPW_SCAN_DO_NOT_ASSOCIATE | IPW_SCAN_MIXED_CELL); + scan.channels = htole32(0x3fff); /* scan channels 1-14 */ + DPRINTF(("Setting scan options to 0x%x\n", letoh32(scan.flags))); + error = ipw_cmd(sc, IPW_CMD_SET_SCAN_OPTIONS, &scan, sizeof scan); + if (error != 0) + goto fail; + + /* start scanning */ + DPRINTF(("Enabling adapter\n")); + error = ipw_cmd(sc, IPW_CMD_ENABLE, NULL, 0); + if (error != 0) + goto fail; + + return; + fail: + printf("%s: scan request failed (error=%d)\n", sc->sc_dev.dv_xname, + error); + ieee80211_end_scan(ifp); +} + +void +ipw_auth_and_assoc(void *arg1, void *arg2) +{ + struct ipw_softc *sc = arg1; + struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211_node *ni = ic->ic_bss; + struct ipw_scan_options scan; + struct ipw_security security; + struct ipw_assoc_req assoc; + uint32_t data; + uint8_t chan; + int s, error; + + DPRINTF(("Disabling adapter\n")); + error = ipw_cmd(sc, IPW_CMD_DISABLE, NULL, 0); + if (error != 0) + goto fail; +#if 1 + /* wait at most one second for card to be disabled */ + s = splnet(); + error = tsleep(sc, 0, "ipwdis", hz); + splx(s); + if (error != 0) { + printf("%s: timeout waiting for disabled state\n", + sc->sc_dev.dv_xname); + goto fail; + } +#else + /* Intel's Linux driver polls for the DISABLED state instead.. */ + for (ntries = 0; ntries < 1000; ntries++) { + if (ipw_read_table1(sc, IPW_INFO_CARD_DISABLED) == 1) + break; + DELAY(10); + } + if (ntries == 1000) { + printf("%s: timeout waiting for disabled state\n", + sc->sc_dev.dv_xname); + goto fail; + } +#endif + + bzero(&security, sizeof security); + security.authmode = IPW_AUTH_OPEN; + security.ciphers = htole32(IPW_CIPHER_NONE); + DPRINTF(("Setting authmode to %u\n", security.authmode)); + error = ipw_cmd(sc, IPW_CMD_SET_SECURITY_INFORMATION, &security, + sizeof security); + if (error != 0) + goto fail; + +#ifdef IPW_DEBUG + if (ipw_debug > 0) { + printf("Setting ESSID to "); + ieee80211_print_essid(ni->ni_essid, ni->ni_esslen); + printf("\n"); + } +#endif + error = ipw_cmd(sc, IPW_CMD_SET_ESSID, ni->ni_essid, ni->ni_esslen); + if (error != 0) + goto fail; + + DPRINTF(("Setting BSSID to %s\n", ether_sprintf(ni->ni_bssid))); + error = ipw_cmd(sc, IPW_CMD_SET_MANDATORY_BSSID, ni->ni_bssid, + IEEE80211_ADDR_LEN); + if (error != 0) + goto fail; + + data = htole32((ic->ic_flags & (IEEE80211_F_WEPON | + IEEE80211_F_RSNON)) ? IPW_PRIVACYON : 0); + DPRINTF(("Setting privacy flags to 0x%x\n", letoh32(data))); + error = ipw_cmd(sc, IPW_CMD_SET_PRIVACY_FLAGS, &data, sizeof data); + if (error != 0) + goto fail; + + /* let firmware set the capinfo, lintval, and bssid fixed fields */ + bzero(&assoc, sizeof assoc); + if (ic->ic_flags & IEEE80211_F_RSNON) { + uint8_t *frm = assoc.optie; + + /* tell firmware to add a WPA or RSN IE in (Re)Assoc req */ + if (ni->ni_rsnprotos & IEEE80211_PROTO_RSN) + frm = ieee80211_add_rsn(frm, ic, ni); + else if (ni->ni_rsnprotos & IEEE80211_PROTO_WPA) + frm = ieee80211_add_wpa(frm, ic, ni); + assoc.optie_len = htole32(frm - assoc.optie); + } + DPRINTF(("Preparing assocation request (optional IE length=%d)\n", + letoh32(assoc.optie_len))); + error = ipw_cmd(sc, IPW_CMD_SET_ASSOC_REQ, &assoc, sizeof assoc); + if (error != 0) + goto fail; + + scan.flags = htole32(IPW_SCAN_MIXED_CELL); + chan = ieee80211_chan2ieee(ic, ni->ni_chan); + scan.channels = htole32(1 << (chan - 1)); + DPRINTF(("Setting scan options to 0x%x\n", letoh32(scan.flags))); + error = ipw_cmd(sc, IPW_CMD_SET_SCAN_OPTIONS, &scan, sizeof scan); + if (error != 0) + goto fail; + + /* trigger scan+association */ + DPRINTF(("Enabling adapter\n")); + error = ipw_cmd(sc, IPW_CMD_ENABLE, NULL, 0); + if (error != 0) + goto fail; + + return; + fail: + printf("%s: association failed (error=%d)\n", sc->sc_dev.dv_xname, + error); + ieee80211_begin_scan(&ic->ic_if); +} + int ipw_config(struct ipw_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; struct ifnet *ifp = &ic->ic_if; - struct ipw_security security; - struct ieee80211_key *k; - struct ipw_wep_key wepkey; - struct ipw_scan_options options; struct ipw_configuration config; uint32_t data; - int error, i; + int error; switch (ic->ic_opmode) { case IEEE80211_M_STA: @@ -1730,7 +1876,7 @@ ipw_config(struct ipw_softc *sc) return error; config.flags = htole32(IPW_CFG_BSS_MASK | IPW_CFG_IBSS_MASK | - IPW_CFG_PREAMBLE_AUTO | IPW_CFG_802_1x_ENABLE); + IPW_CFG_PREAMBLE_AUTO | IPW_CFG_802_1X_ENABLE); #ifndef IEEE80211_STA_ONLY if (ic->ic_opmode == IEEE80211_M_IBSS) config.flags |= htole32(IPW_CFG_IBSS_AUTO_START); @@ -1744,6 +1890,18 @@ ipw_config(struct ipw_softc *sc) if (error != 0) return error; + data = htole32(ic->ic_rtsthreshold); + DPRINTF(("Setting RTS threshold to %u\n", letoh32(data))); + error = ipw_cmd(sc, IPW_CMD_SET_RTS_THRESHOLD, &data, sizeof data); + if (error != 0) + return error; + + data = htole32(ic->ic_fragthreshold); + DPRINTF(("Setting frag threshold to %u\n", letoh32(data))); + error = ipw_cmd(sc, IPW_CMD_SET_FRAG_THRESHOLD, &data, sizeof data); + if (error != 0) + return error; + data = htole32(0x3); /* 1, 2 */ DPRINTF(("Setting basic tx rates to 0x%x\n", letoh32(data))); error = ipw_cmd(sc, IPW_CMD_SET_BASIC_TX_RATES, &data, sizeof data); @@ -1756,6 +1914,12 @@ ipw_config(struct ipw_softc *sc) if (error != 0) return error; + data = htole32(0xf); /* 1, 2, 5.5, 11 */ + DPRINTF(("Setting MSDU tx rates to 0x%x\n", letoh32(data))); + error = ipw_cmd(sc, IPW_CMD_SET_MSDU_TX_RATES, &data, sizeof data); + if (error != 0) + return error; + data = htole32(IPW_POWER_MODE_CAM); DPRINTF(("Setting power mode to %u\n", letoh32(data))); error = ipw_cmd(sc, IPW_CMD_SET_POWER_MODE, &data, sizeof data); @@ -1770,92 +1934,7 @@ ipw_config(struct ipw_softc *sc) sizeof data); if (error != 0) return error; - } -#endif - - data = htole32(ic->ic_rtsthreshold); - DPRINTF(("Setting RTS threshold to %u\n", letoh32(data))); - error = ipw_cmd(sc, IPW_CMD_SET_RTS_THRESHOLD, &data, sizeof data); - if (error != 0) - return error; - - data = htole32(ic->ic_fragthreshold); - DPRINTF(("Setting frag threshold to %u\n", letoh32(data))); - error = ipw_cmd(sc, IPW_CMD_SET_FRAG_THRESHOLD, &data, sizeof data); - if (error != 0) - return error; - -#ifdef IPW_DEBUG - if (ipw_debug > 0) { - printf("Setting ESSID to "); - ieee80211_print_essid(ic->ic_des_essid, ic->ic_des_esslen); - printf("\n"); - } -#endif - error = ipw_cmd(sc, IPW_CMD_SET_ESSID, ic->ic_des_essid, - ic->ic_des_esslen); - if (error != 0) - return error; - - /* no mandatory BSSID */ - DPRINTF(("Setting mandatory BSSID to null\n")); - error = ipw_cmd(sc, IPW_CMD_SET_MANDATORY_BSSID, NULL, 0); - if (error != 0) - return error; - - if (ic->ic_flags & IEEE80211_F_DESBSSID) { - DPRINTF(("Setting adapter BSSID to %s\n", - ether_sprintf(ic->ic_des_bssid))); - error = ipw_cmd(sc, IPW_CMD_SET_DESIRED_BSSID, - ic->ic_des_bssid, IEEE80211_ADDR_LEN); - if (error != 0) - return error; - } - - bzero(&security, sizeof security); - security.authmode = IPW_AUTH_OPEN; /* XXX shared mode */ - security.ciphers = htole32(IPW_CIPHER_NONE); - DPRINTF(("Setting authmode to %u\n", security.authmode)); - error = ipw_cmd(sc, IPW_CMD_SET_SECURITY_INFORMATION, &security, - sizeof security); - if (error != 0) - return error; - - if (ic->ic_flags & IEEE80211_F_WEPON) { - k = ic->ic_nw_keys; - for (i = 0; i < IEEE80211_WEP_NKID; i++, k++) { - if (k->k_len == 0) - continue; - - wepkey.idx = i; - wepkey.len = k->k_len; - bzero(wepkey.key, sizeof wepkey.key); - bcopy(k->k_key, wepkey.key, k->k_len); - DPRINTF(("Setting wep key index %u len %u\n", - wepkey.idx, wepkey.len)); - error = ipw_cmd(sc, IPW_CMD_SET_WEP_KEY, &wepkey, - sizeof wepkey); - if (error != 0) - return error; - } - - data = htole32(ic->ic_wep_txkey); - DPRINTF(("Setting wep tx key index to %u\n", letoh32(data))); - error = ipw_cmd(sc, IPW_CMD_SET_WEP_KEY_INDEX, &data, - sizeof data); - if (error != 0) - return error; - } - - data = htole32((ic->ic_flags & IEEE80211_F_WEPON) ? IPW_WEPON : 0); - DPRINTF(("Setting wep flags to 0x%x\n", letoh32(data))); - error = ipw_cmd(sc, IPW_CMD_SET_WEP_FLAGS, &data, sizeof data); - if (error != 0) - return error; -#ifndef IEEE80211_STA_ONLY - if (ic->ic_opmode == IEEE80211_M_IBSS || - ic->ic_opmode == IEEE80211_M_HOSTAP) { data = htole32(ic->ic_lintval); DPRINTF(("Setting beacon interval to %u\n", letoh32(data))); error = ipw_cmd(sc, IPW_CMD_SET_BEACON_INTERVAL, &data, @@ -1864,23 +1943,14 @@ ipw_config(struct ipw_softc *sc) return error; } #endif - - options.flags = htole32(0); - options.channels = htole32(0x3fff); /* scan channels 1-14 */ - DPRINTF(("Setting scan options to 0x%x\n", letoh32(options.flags))); - error = ipw_cmd(sc, IPW_CMD_SET_SCAN_OPTIONS, &options, sizeof options); - if (error != 0) - return error; - - /* finally, enable adapter (start scanning for an access point) */ - DPRINTF(("Enabling adapter\n")); - return ipw_cmd(sc, IPW_CMD_ENABLE, NULL, 0); + return 0; } int ipw_init(struct ifnet *ifp) { struct ipw_softc *sc = ifp->if_softc; + struct ieee80211com *ic = &sc->sc_ic; struct ipw_firmware fw; int error; @@ -1941,14 +2011,19 @@ ipw_init(struct ifnet *ifp) sc->sc_dev.dv_xname); goto fail2; } + ifp->if_flags &= ~IFF_OACTIVE; ifp->if_flags |= IFF_RUNNING; + if (ic->ic_opmode != IEEE80211_M_MONITOR) + ieee80211_begin_scan(ifp); + else + ieee80211_new_state(ic, IEEE80211_S_RUN, -1); + return 0; fail2: free(fw.data, M_DEVBUF); fail1: ipw_stop(ifp, 0); - return error; } diff --git a/sys/dev/pci/if_ipwreg.h b/sys/dev/pci/if_ipwreg.h index 54521f8631b..a048b56b68d 100644 --- a/sys/dev/pci/if_ipwreg.h +++ b/sys/dev/pci/if_ipwreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ipwreg.h,v 1.14 2006/02/26 19:14:40 damien Exp $ */ +/* $OpenBSD: if_ipwreg.h,v 1.15 2008/08/28 14:40:44 damien Exp $ */ /*- * Copyright (c) 2004-2006 @@ -182,7 +182,7 @@ struct ipw_cmd { #define IPW_CMD_SET_BASIC_TX_RATES 19 #define IPW_CMD_SET_WEP_KEY 20 #define IPW_CMD_SET_WEP_KEY_INDEX 25 -#define IPW_CMD_SET_WEP_FLAGS 26 +#define IPW_CMD_SET_PRIVACY_FLAGS 26 #define IPW_CMD_ADD_MULTICAST 27 #define IPW_CMD_SET_BEACON_INTERVAL 29 #define IPW_CMD_SET_TX_POWER_INDEX 36 @@ -192,7 +192,9 @@ struct ipw_cmd { #define IPW_CMD_SET_SCAN_OPTIONS 46 #define IPW_CMD_PREPARE_POWER_DOWN 58 #define IPW_CMD_DISABLE_PHY 61 +#define IPW_CMD_SET_MSDU_TX_RATES 62 #define IPW_CMD_SET_SECURITY_INFORMATION 67 +#define IPW_CMD_SET_ASSOC_REQ 69 uint32_t subtype; uint32_t seq; uint32_t len; @@ -210,8 +212,8 @@ struct ipw_cmd { #define IPW_MODE_IBSS 1 #define IPW_MODE_MONITOR 2 -/* possible flags for command IPW_CMD_SET_WEP_FLAGS */ -#define IPW_WEPON 0x8 +/* possible flags for command IPW_CMD_SET_PRIVACY_FLAGS */ +#define IPW_PRIVACYON 0x8 /* structure for command IPW_CMD_SET_WEP_KEY */ struct ipw_wep_key { @@ -225,6 +227,8 @@ struct ipw_security { uint32_t ciphers; #define IPW_CIPHER_NONE 0x00000001 #define IPW_CIPHER_WEP40 0x00000002 +#define IPW_CIPHER_TKIP 0x00000004 +#define IPW_CIPHER_CCMP 0x00000010 #define IPW_CIPHER_WEP104 0x00000020 uint16_t reserved1; uint8_t authmode; @@ -237,6 +241,7 @@ struct ipw_security { struct ipw_scan_options { uint32_t flags; #define IPW_SCAN_DO_NOT_ASSOCIATE 0x00000001 +#define IPW_SCAN_MIXED_CELL 0x00000002 #define IPW_SCAN_PASSIVE 0x00000008 uint32_t channels; } __packed; @@ -247,14 +252,25 @@ struct ipw_configuration { #define IPW_CFG_PROMISCUOUS 0x00000004 #define IPW_CFG_PREAMBLE_AUTO 0x00000010 #define IPW_CFG_IBSS_AUTO_START 0x00000020 -#define IPW_CFG_802_1x_ENABLE 0x00004000 +#define IPW_CFG_802_1X_ENABLE 0x00004000 #define IPW_CFG_BSS_MASK 0x00008000 #define IPW_CFG_IBSS_MASK 0x00010000 uint32_t bss_chan; uint32_t ibss_chan; } __packed; -/* EEPROM = Electrically Erasable Programmable Read-Only Memory */ +/* structure for command IPW_CMD_SET_ASSOC_REQ */ +struct ipw_assoc_req { + uint16_t flags; +#define IPW_ASSOC_CAPINFO 0x0001 +#define IPW_ASSOC_LINTVAL 0x0002 +#define IPW_ASSOC_BSSID 0x0004 /* reassoc */ + uint16_t capinfo; + uint16_t lintval; + uint8_t bssid[IEEE80211_ADDR_LEN]; + uint32_t optie_len; + uint8_t optie[384]; +} __packed; #define IPW_MEM_EEPROM_CTL 0x00300040 @@ -324,5 +340,5 @@ struct ipw_configuration { #define IPW_EEPROM_CTL(sc, val) do { \ MEM_WRITE_4((sc), IPW_MEM_EEPROM_CTL, (val)); \ DELAY(IPW_EEPROM_DELAY); \ -} while (0) +} while (/* CONSTCOND */0)