diff options
Diffstat (limited to 'sys/dev/ic/if_wi.c')
-rw-r--r-- | sys/dev/ic/if_wi.c | 90 |
1 files changed, 84 insertions, 6 deletions
diff --git a/sys/dev/ic/if_wi.c b/sys/dev/ic/if_wi.c index f574ec96406..43f57873903 100644 --- a/sys/dev/ic/if_wi.c +++ b/sys/dev/ic/if_wi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_wi.c,v 1.87 2002/10/27 14:46:30 markus Exp $ */ +/* $OpenBSD: if_wi.c,v 1.88 2002/10/27 16:20:48 millert Exp $ */ /* * Copyright (c) 1997, 1998, 1999 @@ -124,7 +124,7 @@ u_int32_t widebug = WIDEBUG; #if !defined(lint) && !defined(__OpenBSD__) static const char rcsid[] = - "$OpenBSD: if_wi.c,v 1.87 2002/10/27 14:46:30 markus Exp $"; + "$OpenBSD: if_wi.c,v 1.88 2002/10/27 16:20:48 millert Exp $"; #endif /* lint */ #ifdef foo @@ -234,6 +234,7 @@ wi_attach(sc) sc->wi_roaming = WI_DEFAULT_ROAMING; sc->wi_authtype = WI_DEFAULT_AUTHTYPE; sc->wi_diversity = WI_DEFAULT_DIVERSITY; + sc->wi_crypto_algorithm = WI_CRYPTO_FIRMWARE_WEP; /* * Read the default channel from the NIC. This may vary @@ -701,6 +702,46 @@ wi_rxeof(sc) ifp->if_ipackets++; + if (sc->wi_use_wep && + rx_frame.wi_frame_ctl & WI_FCTL_WEP) { + int len; + u_int8_t rx_buf[1596]; + + switch (sc->wi_crypto_algorithm) { + case WI_CRYPTO_FIRMWARE_WEP: + break; + case WI_CRYPTO_SOFTWARE_WEP: + m_copydata(m, 0, m->m_pkthdr.len, + (caddr_t)rx_buf); + len = m->m_pkthdr.len - + sizeof(struct ether_header); + if (wi_do_hostdecrypt(sc, rx_buf + + sizeof(struct ether_header), len)) { + if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG) + printf(WI_PRT_FMT ": Error decrypting incoming packet.\n", WI_PRT_ARG(sc)); + return; + } + len -= IEEE80211_WEP_IVLEN + + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN; + /* + * copy data back to mbufs: + * we need to ditch the IV & most LLC/SNAP stuff + * (except SNAP type, we're going use that to + * overwrite the ethertype in the ether_header) + */ + m_copyback(m, sizeof(struct ether_header) - + WI_ETHERTYPE_LEN, WI_ETHERTYPE_LEN + + (len - WI_SNAPHDR_LEN), + rx_buf + sizeof(struct ether_header) + + IEEE80211_WEP_IVLEN + + IEEE80211_WEP_KIDLEN + WI_SNAPHDR_LEN); + m_adj(m, -(WI_ETHERTYPE_LEN + + IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + + WI_SNAPHDR_LEN)); + break; + } + } + if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) { /* * Give host AP code first crack at data packets. @@ -1034,7 +1075,7 @@ wi_write_record(sc, ltv) struct wi_ltv_gen *ltv; { u_int8_t *ptr; - u_int16_t val; + u_int16_t val = 0; int i; struct wi_ltv_gen p2ltv; @@ -1081,9 +1122,20 @@ wi_write_record(sc, ltv) if (sc->wi_authtype != IEEE80211_AUTH_OPEN || sc->sc_firmware_type == WI_SYMBOL) val |= EXCLUDE_UNENCRYPTED; - /* TX encryption is broken in Host AP mode. */ - if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) - val |= HOST_ENCRYPT; + + switch (sc->wi_crypto_algorithm) { + case WI_CRYPTO_FIRMWARE_WEP: + /* + * TX encryption is broken in + * Host AP mode. + */ + if (sc->wi_ptype == WI_PORTTYPE_HOSTAP) + val |= HOST_ENCRYPT; + break; + case WI_CRYPTO_SOFTWARE_WEP: + val |= HOST_ENCRYPT|HOST_DECRYPT; + break; + } p2ltv.wi_val = htole16(val); } else p2ltv.wi_val = htole16(HOST_ENCRYPT | HOST_DECRYPT); @@ -1400,6 +1452,20 @@ wi_setdef(sc, wreq) bcopy((char *)wreq, (char *)&sc->wi_keys, sizeof(struct wi_ltv_keys)); break; + case WI_FRID_CRYPTO_ALG: + switch (letoh16(wreq->wi_val[0])) { + case WI_CRYPTO_FIRMWARE_WEP: + sc->wi_crypto_algorithm = WI_CRYPTO_FIRMWARE_WEP; + break; + case WI_CRYPTO_SOFTWARE_WEP: + sc->wi_crypto_algorithm = WI_CRYPTO_SOFTWARE_WEP; + break; + default: + printf(WI_PRT_FMT ": unsupported crypto algorithm %d\n", + WI_PRT_ARG(sc), letoh16(wreq->wi_val[0])); + error = EINVAL; + } + break; default: error = EINVAL; break; @@ -1558,6 +1624,11 @@ wi_ioctl(ifp, command, data) wreq.wi_len = sc->wi_scanbuf_len; break; } + case WI_FRID_CRYPTO_ALG: + wreq.wi_val[0] = + htole16((u_int16_t)sc->wi_crypto_algorithm); + wreq.wi_len = 1; + break; default: if (wi_read_record(sc, (struct wi_ltv_gen *)&wreq)) { error = EINVAL; @@ -1593,6 +1664,13 @@ wi_ioctl(ifp, command, data) error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq); break; + case WI_FRID_CRYPTO_ALG: + if (sc->sc_firmware_type != WI_LUCENT) { + error = wi_setdef(sc, &wreq); + if (!error && (ifp->if_flags & IFF_UP)) + wi_init(sc); + } + break; case WI_RID_SYMBOL_DIVERSITY: case WI_RID_ROAMING_MODE: case WI_RID_CREATE_IBSS: |