cleanup haeders.

add opt_awi.h to define AWI_DEBUG, AWI_WEP_ARC4.
show the firmware version at attach.
create a framework to support WEP (encryption code is not included for now).
a new wiconfig compatible ioctl interface replaced the awictl interface.
fix memory leak in selecting AP
fix bugs in ESSID selection
changes from FreeBSD-current by Warner Losh:
  revision 1.2
  date: 2000/04/17 22:58:15;  author: imp;  state: Exp;  lines: +16 -1
  Provide mem* for compat with NetBSD to fix LINT
fixes from FreeBSD-current by Guido van Rooij:
  revision 1.4
  date: 2000/05/29 19:58:10;  author: guido;  state: Exp;  lines: +5 -2
  Fix a panic resulting from an obvious null pointer deref.
  Apparently some other panics still exist in this driver, but with
  this fix, it was at least possible to run the Nokia card at SANE 2000.
This commit is contained in:
onoe 2000-06-09 05:31:15 +00:00
parent e802a7df62
commit 4da3935bae
9 changed files with 1183 additions and 356 deletions

View File

@ -1,10 +1,10 @@
# $NetBSD: Makefile,v 1.11 2000/05/07 00:29:03 wiz Exp $
# $NetBSD: Makefile,v 1.12 2000/06/09 05:31:15 onoe Exp $
INCSDIR= /usr/include/dev/ic
INCS= ad1848reg.h ahareg.h ahavar.h aic6360reg.h aic6360var.h \
aic77xxreg.h aic77xxvar.h aic7xxxvar.h am7930reg.h am7990reg.h \
am7990var.h awictl.h bhareg.h bhavar.h bt431reg.h bt459reg.h \
am7990var.h bhareg.h bhavar.h bt431reg.h bt459reg.h \
bt463reg.h bt485reg.h bt8xx.h cacreg.h cacvar.h cd1190reg.h \
cd1400reg.h comreg.h comvar.h cs4231reg.h cyreg.h \
cyvar.h dc21040reg.h dp8390reg.h dp8390var.h dptreg.h dptvar.h ds.h \

View File

@ -1,4 +1,4 @@
/* $NetBSD: awi.c,v 1.17 2000/05/29 17:37:12 jhawk Exp $ */
/* $NetBSD: awi.c,v 1.18 2000/06/09 05:31:15 onoe Exp $ */
/*
* Copyright (c) 2000 The NetBSD Foundation, Inc.
@ -48,23 +48,14 @@
* and to support adhoc mode by Atsushi Onoe <onoe@netbsd.org>
*/
#ifdef __NetBSD__
#include "opt_awi.h"
#include "opt_inet.h"
#include "opt_ns.h"
#include "bpfilter.h"
#include "rnd.h"
#endif
#ifdef __FreeBSD__
#if __FreeBSD__ >= 3
#include "opt_inet.h"
#endif
#if __FreeBSD__ >= 4
#if defined(__FreeBSD__) && __FreeBSD__ >= 4
#include "bpf.h"
#define NBPFILTER NBPF
#else
#include "bpfilter.h"
#endif
#endif
#include <sys/param.h>
#include <sys/systm.h>
@ -73,22 +64,14 @@
#include <sys/malloc.h>
#include <sys/proc.h>
#include <sys/socket.h>
#ifdef __FreeBSD__
#include <sys/sockio.h>
#else
#include <sys/ioctl.h>
#endif
#include <sys/errno.h>
#include <sys/syslog.h>
#include <sys/select.h>
#if defined(__FreeBSD__) && __FreeBSD__ >= 4
#include <sys/bus.h>
#else
#include <sys/device.h>
#endif
#if NRND > 0
#include <sys/rnd.h>
#endif
#include <net/if.h>
#include <net/if_dl.h>
@ -113,11 +96,6 @@
#endif
#endif
#ifdef NS
#include <netns/ns.h>
#include <netns/ns_if.h>
#endif
#if NBPFILTER > 0
#include <net/bpf.h>
#include <net/bpfdesc.h>
@ -137,14 +115,12 @@
#include <dev/ic/am79c930var.h>
#include <dev/ic/awireg.h>
#include <dev/ic/awivar.h>
#include <dev/ic/awictl.h>
#endif
#ifdef __FreeBSD__
#include <dev/awi/am79c930reg.h>
#include <dev/awi/am79c930var.h>
#include <dev/awi/awireg.h>
#include <dev/awi/awivar.h>
#include <dev/awi/awictl.h>
#endif
static int awi_ioctl __P((struct ifnet *ifp, u_long cmd, caddr_t data));
@ -154,10 +130,6 @@ static int awi_media_opt2rate __P((struct awi_softc *sc, int opt));
static int awi_media_change __P((struct ifnet *ifp));
static void awi_media_status __P((struct ifnet *ifp, struct ifmediareq *imr));
#endif
static int awi_drvget __P((struct ifnet *ifp, u_long cmd, caddr_t data));
static int awi_drvset __P((struct ifnet *ifp, u_long cmd, caddr_t data));
static int awi_init __P((struct awi_softc *sc));
static void awi_stop __P((struct awi_softc *sc));
static void awi_watchdog __P((struct ifnet *ifp));
static void awi_start __P((struct ifnet *ifp));
static void awi_txint __P((struct awi_softc *sc));
@ -165,12 +137,11 @@ static struct mbuf * awi_fix_txhdr __P((struct awi_softc *sc, struct mbuf *m0));
static struct mbuf * awi_fix_rxhdr __P((struct awi_softc *sc, struct mbuf *m0));
static void awi_input __P((struct awi_softc *sc, struct mbuf *m, u_int32_t rxts, u_int8_t rssi));
static void awi_rxint __P((struct awi_softc *sc));
struct mbuf * awi_devget __P((struct awi_softc *sc, u_int32_t off, u_int16_t len));
static struct mbuf * awi_devget __P((struct awi_softc *sc, u_int32_t off, u_int16_t len));
static int awi_init_hw __P((struct awi_softc *sc));
static int awi_init_mibs __P((struct awi_softc *sc));
static int awi_init_txrx __P((struct awi_softc *sc));
static void awi_stop_txrx __P((struct awi_softc *sc));
static int awi_init_region __P((struct awi_softc *sc));
static int awi_start_scan __P((struct awi_softc *sc));
static int awi_next_scan __P((struct awi_softc *sc));
static void awi_stop_scan __P((struct awi_softc *sc));
@ -227,10 +198,6 @@ int awi_dump_len = 28;
#endif
#ifdef __FreeBSD__
#if __FreeBSD__ < 4
#define memset(p, v, n) bzero(p, n) /*XXX*/
#endif
#if __FreeBSD__ >= 4
devclass_t awi_devclass;
#endif
@ -254,17 +221,16 @@ awi_attach(sc)
struct awi_softc *sc;
{
struct ifnet *ifp = sc->sc_ifp;
int s;
int error;
#ifdef IFM_IEEE80211
int i;
u_int8_t *phy_rates;
int mword;
struct ifmediareq imr;
#endif
int s;
int error;
s = splnet();
/*
* Even if we can sleep in initialization state,
* all other processes (e.g. ifconfig) have to wait for
@ -307,10 +273,13 @@ awi_attach(sc)
ETHER_ADDR_LEN);
#endif
printf("%s: IEEE802.11 (%s %dMbps) address %s\n",
awi_read_bytes(sc, AWI_BANNER, sc->sc_banner, AWI_BANNER_LEN);
printf("%s: IEEE802.11 %s %dMbps (firmware %s)\n",
sc->sc_dev.dv_xname,
sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH ? "FH" : "DS",
sc->sc_tx_rate / 10, ether_sprintf(sc->sc_mib_addr.aMAC_Address));
sc->sc_tx_rate / 10, sc->sc_banner);
printf("%s: address %s\n",
sc->sc_dev.dv_xname, ether_sprintf(sc->sc_mib_addr.aMAC_Address));
if_attach(ifp);
#ifdef __FreeBSD__
ether_ifattach(ifp);
@ -369,6 +338,8 @@ awi_detach(sc)
wakeup(sc);
(void)tsleep(sc, PWAIT, "awidet", 1);
}
if (sc->sc_wep_ctx != NULL)
free(sc->sc_wep_ctx, M_DEVBUF);
#if NBPFILTER > 0
bpfdetach(ifp);
#endif
@ -410,27 +381,36 @@ awi_activate(self, act)
return error;
}
#endif /* __NetBSD__ */
void
awi_reset(sc)
awi_power(sc, why)
struct awi_softc *sc;
int why;
{
int s;
int ocansleep;
if (!sc->sc_enabled)
return;
s = splnet();
sc->sc_invalid = 1;
awi_stop(sc);
if (sc->sc_disable)
(*sc->sc_disable)(sc);
sc->sc_enabled = 0;
DELAY(1000);
sc->sc_invalid = 0;
(void)awi_init(sc);
ocansleep = sc->sc_cansleep;
sc->sc_cansleep = 0;
#ifdef needtobefixed /*ONOE*/
if (why == PWR_RESUME) {
sc->sc_enabled = 0;
awi_init(sc);
(void)awi_intr(sc);
} else {
awi_stop(sc);
if (sc->sc_disable)
(*sc->sc_disable)(sc);
}
#endif
sc->sc_cansleep = ocansleep;
splx(s);
}
#endif /* __NetBSD__ */
static int
awi_ioctl(ifp, cmd, data)
@ -486,6 +466,9 @@ awi_ioctl(ifp, cmd, data)
ether_addmulti(ifr, &sc->sc_ec) :
ether_delmulti(ifr, &sc->sc_ec);
#endif
/*
* Do not rescan BSS. Rather, just reset multicast filter.
*/
if (error == ENETRESET) {
if (sc->sc_enabled)
error = awi_init(sc);
@ -534,14 +517,8 @@ awi_ioctl(ifp, cmd, data)
error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
break;
#endif
case SIOCGDRVSPEC:
error = awi_drvget(ifp, cmd, data);
break;
case SIOCSDRVSPEC:
error = awi_drvset(ifp, cmd, data);
break;
default:
error = EINVAL;
error = awi_wicfg(ifp, cmd, data);
break;
}
awi_unlock(sc);
@ -685,187 +662,6 @@ awi_media_status(ifp, imr)
}
#endif /* IFM_IEEE80211 */
/*
* XXX
* The following stuff is partially duplicated with SIOC[GS]IFMEDIA and
* SIOC[GS]80211NWID, which should be integrated as well as other common
* stuff among 802.11 wireless LAN drivers.
*/
static int
awi_drvget(ifp, cmd, data)
struct ifnet *ifp;
u_long cmd;
caddr_t data;
{
struct awi_softc *sc = ifp->if_softc;
struct ifdrv *ifd = (struct ifdrv *)data;
u_int8_t buf[AWICTL_BUFSIZE];
u_int8_t *essid;
int error = 0;
switch (ifd->ifd_cmd) {
case AWICTL_REGION:
if (ifd->ifd_len < 1)
return ENOSPC;
ifd->ifd_len = 1;
buf[0] = sc->sc_mib_phy.aCurrent_Reg_Domain;
break;
case AWICTL_CHANSET:
if (ifd->ifd_len < 3)
return ENOSPC;
ifd->ifd_len = 3;
buf[0] = sc->sc_bss.chanset;
buf[1] = sc->sc_scan_min;
buf[2] = sc->sc_scan_max;
break;
case AWICTL_RAWBPF:
if (ifd->ifd_len < 1)
return ENOSPC;
ifd->ifd_len = 1;
buf[0] = sc->sc_rawbpf;
break;
case AWICTL_DESSID:
case AWICTL_CESSID:
if (ifd->ifd_cmd == AWICTL_DESSID)
essid = sc->sc_mib_mac.aDesired_ESS_ID;
else
essid = sc->sc_bss.essid;
if (ifd->ifd_len < essid[1])
return ENOSPC;
ifd->ifd_len = essid[1];
if (ifd->ifd_len > 0)
memcpy(buf, essid, ifd->ifd_len);
break;
case AWICTL_MODE:
if (ifd->ifd_len < 1)
return ENOSPC;
ifd->ifd_len = 1;
if (sc->sc_mib_local.Network_Mode == 0) {
if (sc->sc_no_bssid)
buf[0] = AWICTL_MODE_NOBSSID;
else
buf[0] = AWICTL_MODE_ADHOC;
} else
buf[0] = AWICTL_MODE_INFRA;
break;
default:
error = EINVAL;
break;
}
if (error == 0 && ifd->ifd_len > 0)
error = copyout(ifd->ifd_data, buf, ifd->ifd_len);
return error;
}
static int
awi_drvset(ifp, cmd, data)
struct ifnet *ifp;
u_long cmd;
caddr_t data;
{
struct awi_softc *sc = ifp->if_softc;
struct ifdrv *ifd = (struct ifdrv *)data;
u_int8_t buf[AWICTL_BUFSIZE];
u_int8_t oregion;
int error = 0;
if (ifd->ifd_len > sizeof(buf))
return EINVAL;
error = copyin(ifd->ifd_data, buf, ifd->ifd_len);
if (error)
return error;
switch (ifd->ifd_cmd) {
case AWICTL_REGION:
if (ifd->ifd_len != 1)
return EINVAL;
oregion = sc->sc_mib_phy.aCurrent_Reg_Domain;
if (buf[0] == oregion)
break;
sc->sc_mib_phy.aCurrent_Reg_Domain = buf[0];
error = awi_init_region(sc);
if (error) {
sc->sc_mib_phy.aCurrent_Reg_Domain = oregion;
break;
}
if (sc->sc_enabled) {
awi_stop(sc);
error = awi_init(sc);
}
break;
case AWICTL_CHANSET:
if (ifd->ifd_len != 3)
return EINVAL;
/* reset scan min/max */
awi_init_region(sc);
if (buf[0] < sc->sc_scan_min || buf[0] > sc->sc_scan_max ||
buf[1] < sc->sc_scan_min || buf[1] > sc->sc_scan_max ||
buf[2] < sc->sc_scan_min || buf[2] > sc->sc_scan_max)
return EINVAL;
sc->sc_scan_cur = buf[0];
sc->sc_scan_min = buf[1];
sc->sc_scan_max = buf[2];
if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH)
sc->sc_scan_set = sc->sc_scan_cur % 3 + 1;
if (sc->sc_enabled) {
awi_stop(sc);
error = awi_init(sc);
}
break;
case AWICTL_RAWBPF:
if (ifd->ifd_len != 1)
return EINVAL;
sc->sc_rawbpf = buf[0];
break;
case AWICTL_DESSID:
if (ifd->ifd_len > IEEE80211_NWID_LEN)
return EINVAL;
if (sc->sc_mib_mac.aDesired_ESS_ID[1] == ifd->ifd_len &&
memcmp(&sc->sc_mib_mac.aDesired_ESS_ID[2], buf,
ifd->ifd_len) == 0)
break;
memset(sc->sc_mib_mac.aDesired_ESS_ID, 0, AWI_ESS_ID_SIZE);
sc->sc_mib_mac.aDesired_ESS_ID[0] = IEEE80211_ELEMID_SSID;
sc->sc_mib_mac.aDesired_ESS_ID[1] = ifd->ifd_len;
memcpy(&sc->sc_mib_mac.aDesired_ESS_ID[2], buf, ifd->ifd_len);
if (sc->sc_enabled) {
awi_stop(sc);
error = awi_init(sc);
}
break;
case AWICTL_CESSID:
error = EINVAL;
break;
case AWICTL_MODE:
switch (buf[0]) {
case AWICTL_MODE_INFRA:
sc->sc_mib_local.Network_Mode = 1;
sc->sc_no_bssid = 0;
break;
case AWICTL_MODE_ADHOC:
sc->sc_mib_local.Network_Mode = 0;
sc->sc_no_bssid = 0;
break;
case AWICTL_MODE_NOBSSID:
sc->sc_mib_local.Network_Mode = 0;
sc->sc_no_bssid = 1;
break;
default:
return EINVAL;
}
if (sc->sc_enabled) {
awi_stop(sc);
error = awi_init(sc);
}
break;
default:
error = EINVAL;
break;
}
return error;
}
int
awi_intr(arg)
void *arg;
@ -917,7 +713,7 @@ awi_intr(arg)
return handled;
}
static int
int
awi_init(sc)
struct awi_softc *sc;
{
@ -1005,7 +801,7 @@ awi_init(sc)
return error;
}
static void
void
awi_stop(sc)
struct awi_softc *sc;
{
@ -1036,8 +832,10 @@ awi_stop(sc)
break;
m_freem(m);
}
while ((bp = TAILQ_FIRST(&sc->sc_scan)) != NULL)
while ((bp = TAILQ_FIRST(&sc->sc_scan)) != NULL) {
TAILQ_REMOVE(&sc->sc_scan, bp, list);
free(bp, M_DEVBUF);
}
}
static void
@ -1111,14 +909,22 @@ awi_start(ifp)
IF_DEQUEUE(&ifp->if_snd, m0);
if (m0 == NULL)
break;
if (awi_next_txd(sc, m0->m_pkthdr.len +
sizeof(struct ieee80211_frame), &frame, &ntxd)) {
len = m0->m_pkthdr.len + sizeof(struct ieee80211_frame);
if (sc->sc_format_llc)
len += sizeof(struct llc) -
sizeof(struct ether_header);
if (sc->sc_wep_algo != NULL)
len += IEEE80211_WEP_IVLEN +
IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
if (awi_next_txd(sc, len, &frame, &ntxd)) {
IF_PREPEND(&ifp->if_snd, m0);
ifp->if_flags |= IFF_OACTIVE;
break;
}
AWI_BPF_MTAP(sc, m0, AWI_BPF_NORM);
m0 = awi_fix_txhdr(sc, m0);
if (sc->sc_wep_algo != NULL && m0 != NULL)
m0 = awi_wep_encrypt(sc, m0, 1);
if (m0 == NULL) {
ifp->if_oerrors++;
continue;
@ -1288,6 +1094,8 @@ awi_input(sc, m, rxts, rssi)
struct ether_header *eh;
#endif
/* trim CRC here for WEP can find its own CRC at the end of packet. */
m_adj(m, -ETHER_CRC_LEN);
AWI_BPF_MTAP(sc, m, AWI_BPF_RAW);
wh = mtod(m, struct ieee80211_frame *);
if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) !=
@ -1295,8 +1103,17 @@ awi_input(sc, m, rxts, rssi)
printf("%s; receive packet with wrong version: %x\n",
sc->sc_dev.dv_xname, wh->i_fc[0]);
m_freem(m);
ifp->if_ierrors++;
return;
}
if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
m = awi_wep_encrypt(sc, m, 0);
if (m == NULL) {
ifp->if_ierrors++;
return;
}
wh = mtod(m, struct ieee80211_frame *);
}
#ifdef AWI_DEBUG
if (awi_dump)
awi_dump_pkt(sc, m, rssi);
@ -1330,14 +1147,14 @@ awi_input(sc, m, rxts, rssi)
break;
}
ifp->if_ipackets++;
#if !(defined(__FreeBSD__) && __FreeBSD__ >= 4)
AWI_BPF_MTAP(sc, m, AWI_BPF_NORM);
#endif
#ifdef __NetBSD__
m->m_flags |= M_HASFCS;
(*ifp->if_input)(ifp, m);
#else
eh = mtod(m, struct ether_header *);
m_adj(m, sizeof(*eh));
m_adj(m, -ETHER_CRC_LEN);
ether_input(ifp, eh, m);
#endif
break;
@ -1423,22 +1240,25 @@ awi_rxint(sc)
sc->sc_rxdoff = rxoff;
}
struct mbuf *
static struct mbuf *
awi_devget(sc, off, len)
struct awi_softc *sc;
u_int32_t off;
u_int16_t len;
{
struct mbuf *m;
struct mbuf *top, **mp = &top;
struct mbuf *top, **mp;
u_int tlen;
top = sc->sc_rxpend;
mp = &top;
if (top != NULL) {
sc->sc_rxpend = NULL;
top->m_pkthdr.len += len;
while ((m = *mp) != NULL)
while (*mp != NULL) {
m = *mp;
mp = &m->m_next;
}
if (m->m_flags & M_EXT)
tlen = m->m_ext.ext_size;
else if (m->m_flags & M_PKTHDR)
@ -1497,7 +1317,6 @@ awi_init_hw(sc)
u_int8_t status;
u_int16_t intmask;
int i, error;
u_int8_t banner[AWI_BANNER_LEN];
sc->sc_enab_intr = 0;
awi_drvstate(sc, AWI_DRV_RESET);
@ -1534,12 +1353,12 @@ awi_init_hw(sc)
}
/* check banner to confirm firmware write it */
awi_read_bytes(sc, AWI_BANNER, banner, AWI_BANNER_LEN);
if (memcmp(banner, "PCnetMobile:", 12) != 0) {
awi_read_bytes(sc, AWI_BANNER, sc->sc_banner, AWI_BANNER_LEN);
if (memcmp(sc->sc_banner, "PCnetMobile:", 12) != 0) {
printf("%s: failed to complete selftest (bad banner)\n",
sc->sc_dev.dv_xname);
for (i = 0; i < AWI_BANNER_LEN; i++)
printf("%s%02x", i ? ":" : "\t", banner[i]);
printf("%s%02x", i ? ":" : "\t", sc->sc_banner[i]);
printf("\n");
return ENXIO;
}
@ -1679,7 +1498,7 @@ awi_stop_txrx(sc)
(void)awi_cmd(sc, AWI_CMD_FLUSH_TX);
}
static int
int
awi_init_region(sc)
struct awi_softc *sc;
{
@ -1707,7 +1526,6 @@ awi_init_region(sc)
default:
return EINVAL;
}
sc->sc_scan_cur = sc->sc_scan_min;
sc->sc_scan_set = sc->sc_scan_cur % 3 + 1;
} else {
switch (sc->sc_mib_phy.aCurrent_Reg_Domain) {
@ -1741,6 +1559,7 @@ awi_init_region(sc)
return EINVAL;
}
}
sc->sc_ownch = sc->sc_scan_cur;
return 0;
}
@ -1749,19 +1568,24 @@ awi_start_scan(sc)
struct awi_softc *sc;
{
int error = 0;
struct awi_bss *bp;
while ((bp = TAILQ_FIRST(&sc->sc_scan)) != NULL) {
TAILQ_REMOVE(&sc->sc_scan, bp, list);
free(bp, M_DEVBUF);
}
if (!sc->sc_mib_local.Network_Mode && sc->sc_no_bssid) {
memset(&sc->sc_bss, 0, sizeof(sc->sc_bss));
sc->sc_bss.rxtime = 0;
memcpy(sc->sc_bss.essid, &sc->sc_mib_mac.aDesired_ESS_ID,
sizeof(sc->sc_bss.essid));
if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) {
sc->sc_bss.chanset = sc->sc_scan_set;
sc->sc_bss.pattern = sc->sc_scan_cur;
sc->sc_bss.chanset = sc->sc_ownch % 3 + 1;
sc->sc_bss.pattern = sc->sc_ownch;
sc->sc_bss.index = 1;
sc->sc_bss.dwell_time = 19; /*XXX*/
} else
sc->sc_bss.chanset = sc->sc_scan_cur;
sc->sc_bss.chanset = sc->sc_ownch;
sc->sc_status = AWI_ST_SETSS;
error = awi_set_ss(sc);
} else {
@ -1836,13 +1660,13 @@ awi_stop_scan(sc)
* during my scan. So we retries to associate with
* it unless there are any suitable AP.
*/
if (bp->fails < 3)
if (bp->fails++ < 3)
continue;
bp->fails = 0;
}
if (sc->sc_mib_mac.aDesired_ESS_ID[1] != 0 &&
memcmp(&sc->sc_mib_mac.aDesired_ESS_ID, bp->essid,
sizeof(bp->essid) != 0))
sizeof(bp->essid)) != 0)
continue;
/*
* Since the firmware apparently scans not only the specified
@ -2336,8 +2160,6 @@ awi_recv_asresp(sc, m0)
sc->sc_status = AWI_ST_RUNNING;
sc->sc_ifp->if_flags |= IFF_RUNNING;
awi_drvstate(sc, AWI_DRV_INFASSOC);
while ((bp = TAILQ_FIRST(&sc->sc_scan)) != NULL)
TAILQ_REMOVE(&sc->sc_scan, bp, list);
awi_start(sc->sc_ifp);
}

450
sys/dev/ic/awi_wep.c Normal file
View File

@ -0,0 +1,450 @@
/* $NetBSD: awi_wep.c,v 1.1 2000/06/09 05:31:16 onoe Exp $ */
/*
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Atsushi Onoe.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* WEP support framework for the awi driver.
*
* No actual encryption capability is provided here, but any can be added
* to awi_wep_algo table below.
*
* Note that IEEE802.11 specification states WEP uses RC4 with 40bit key,
* which is a proprietary encryption algorithm available under license
* from RSA Data Security Inc. Using another algorithm, includes null
* encryption provided here, the awi driver cannot be able to communicate
* with other stations.
*/
#include "opt_awi.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/mbuf.h>
#include <sys/malloc.h>
#include <sys/proc.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <sys/sockio.h>
#if defined(__FreeBSD__) && __FreeBSD__ >= 4
#include <sys/bus.h>
#else
#include <sys/device.h>
#endif
#include <net/if.h>
#include <net/if_dl.h>
#ifdef __FreeBSD__
#include <net/ethernet.h>
#include <net/if_arp.h>
#else
#include <net/if_ether.h>
#endif
#include <net/if_media.h>
#include <net/if_ieee80211.h>
#include <machine/cpu.h>
#include <machine/bus.h>
#ifdef __FreeBSD__
#include <machine/clock.h>
#endif
#ifdef __NetBSD__
#include <dev/ic/am79c930reg.h>
#include <dev/ic/am79c930var.h>
#include <dev/ic/awireg.h>
#include <dev/ic/awivar.h>
#endif
#ifdef __FreeBSD__
#include <dev/awi/am79c930reg.h>
#include <dev/awi/am79c930var.h>
#include <dev/awi/awireg.h>
#include <dev/awi/awivar.h>
#endif
static void awi_crc_init __P((void));
static u_int32_t awi_crc_update __P((u_int32_t crc, u_int8_t *buf, int len));
static int awi_null_ctxlen __P((void));
static void awi_null_setkey __P((void *ctx, u_int8_t *key, int keylen));
static void awi_null_copy __P((void *ctx, u_int8_t *dst, u_int8_t *src, int len));
#ifdef AWI_WEP_ARC4
extern int awi_arc4_ctxlen __P((void));
extern void awi_arc4_setkey __P((void *ctx, u_int8_t *key, int keylen));
extern void awi_arc4_encrypt __P((void *ctx, u_int8_t *dst, u_int8_t *src, int len));
#endif
#ifdef AWI_WEP_DES3
extern int awi_des3_ctxlen __P((void));
extern void awi_des3_setkey __P((void *ctx, u_int8_t *key, int keylen));
extern void awi_des3_encrypt __P((void *ctx, u_int8_t *dst, u_int8_t *src, int len));
#endif
/* XXX: the order should be known to wiconfig/user */
static struct awi_wep_algo awi_wep_algo[] = {
{ "no" }, /* dummy for no wep */
#ifdef AWI_WEP_ARC4
{ "arc4", awi_arc4_ctxlen, awi_arc4_setkey,
awi_arc4_encrypt, awi_arc4_encrypt },
#else
{ NULL }, /* not supported */
#endif
#ifdef AWI_WEP_DES3
{ "des3", awi_des3_ctxlen, awi_des3_setkey,
awi_des3_encrypt, awi_des3_decrypt },
#else
{ NULL }, /* not supported */
#endif
{ "null", awi_null_ctxlen, awi_null_setkey,
awi_null_copy, awi_null_copy },
/* dummy for wep without encryption */
};
int
awi_wep_getalgo(sc)
struct awi_softc *sc;
{
if (sc->sc_wep_algo == NULL)
return 0;
return sc->sc_wep_algo - awi_wep_algo;
}
int
awi_wep_setalgo(sc, algo)
struct awi_softc *sc;
int algo;
{
struct awi_wep_algo *awa;
int ctxlen;
awi_crc_init(); /* XXX: not belongs here */
if (algo < 0 || algo > sizeof(awi_wep_algo)/sizeof(awi_wep_algo[0]))
return EINVAL;
awa = &awi_wep_algo[algo];
if (awa->awa_name == NULL)
return EINVAL;
if (awa->awa_ctxlen == NULL) {
awa = NULL;
ctxlen = 0;
} else
ctxlen = awa->awa_ctxlen();
if (sc->sc_wep_ctx != NULL) {
free(sc->sc_wep_ctx, M_DEVBUF);
sc->sc_wep_ctx = NULL;
}
if (ctxlen) {
sc->sc_wep_ctx = malloc(ctxlen, M_DEVBUF, M_NOWAIT);
if (sc->sc_wep_ctx == NULL)
return ENOMEM;
}
sc->sc_wep_algo = awa;
return 0;
}
int
awi_wep_setkey(sc, kid, key, keylen)
struct awi_softc *sc;
int kid;
unsigned char *key;
int keylen;
{
if (kid < 0 || kid >= IEEE80211_WEP_NKID)
return EINVAL;
if (keylen < 0 || keylen + IEEE80211_WEP_IVLEN > AWI_MAX_KEYLEN)
return EINVAL;
sc->sc_wep_keylen[kid] = keylen;
if (keylen > 0)
memcpy(sc->sc_wep_key[kid] + IEEE80211_WEP_IVLEN, key, keylen);
return 0;
}
int
awi_wep_getkey(sc, kid, key, keylen)
struct awi_softc *sc;
int kid;
unsigned char *key;
int *keylen;
{
if (kid < 0 || kid >= IEEE80211_WEP_NKID)
return EINVAL;
if (*keylen < sc->sc_wep_keylen[kid])
return ENOSPC;
*keylen = sc->sc_wep_keylen[kid];
if (*keylen > 0)
memcpy(key, sc->sc_wep_key[kid] + IEEE80211_WEP_IVLEN, *keylen);
return 0;
}
struct mbuf *
awi_wep_encrypt(sc, m0, txflag)
struct awi_softc *sc;
struct mbuf *m0;
int txflag;
{
struct mbuf *m, *n, *n0;
struct ieee80211_frame *wh;
struct awi_wep_algo *awa;
int left, len, moff, noff, keylen, kid;
u_int32_t iv, crc;
u_int8_t *key, *ivp;
void *ctx;
u_int8_t crcbuf[IEEE80211_WEP_CRCLEN];
n0 = NULL;
awa = sc->sc_wep_algo;
if (awa == NULL)
goto fail;
ctx = sc->sc_wep_ctx;
m = m0;
left = m->m_pkthdr.len;
MGET(n, M_DONTWAIT, m->m_type);
n0 = n;
if (n == NULL)
goto fail;
M_COPY_PKTHDR(n, m);
len = IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN;
if (txflag) {
n->m_pkthdr.len += len;
} else {
wh = mtod(n, struct ieee80211_frame *);
n->m_pkthdr.len -= len;
left -= len;
}
n->m_len = MHLEN;
if (n->m_pkthdr.len >= MINCLSIZE) {
MCLGET(n, M_DONTWAIT);
if (n->m_flags & M_EXT)
n->m_len = n->m_ext.ext_size;
}
len = sizeof(struct ieee80211_frame);
memcpy(mtod(n, caddr_t), mtod(m, caddr_t), len);
left -= len;
moff = len;
noff = len;
if (txflag) {
kid = sc->sc_wep_defkid;
wh = mtod(n, struct ieee80211_frame *);
wh->i_fc[1] |= IEEE80211_FC1_WEP;
iv = random();
/*
* store IV, byte order is not the matter since it's random.
* assuming IEEE80211_WEP_IVLEN is 3
*/
ivp = mtod(n, u_int8_t *) + noff;
ivp[0] = (iv >> 16) & 0xff;
ivp[1] = (iv >> 8) & 0xff;
ivp[2] = iv & 0xff;
ivp[3] = kid & 0x03; /* clear pad and keyid */
noff += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
} else {
ivp = mtod(m, u_int8_t *) + moff;
moff += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN;
kid = ivp[IEEE80211_WEP_IVLEN] & 0x03;
}
key = sc->sc_wep_key[kid];
keylen = sc->sc_wep_keylen[kid];
/* assuming IEEE80211_WEP_IVLEN is 3 */
key[0] = ivp[0];
key[1] = ivp[1];
key[2] = ivp[2];
awa->awa_setkey(ctx, key, IEEE80211_WEP_IVLEN + keylen);
/* encrypt with calculating CRC */
crc = ~0;
while (left > 0) {
len = m->m_len - moff;
if (len == 0) {
m = m->m_next;
moff = 0;
continue;
}
if (len > n->m_len - noff) {
len = n->m_len - noff;
if (len == 0) {
MGET(n->m_next, M_DONTWAIT, n->m_type);
if (n->m_next == NULL)
goto fail;
n = n->m_next;
n->m_len = MLEN;
if (left >= MINCLSIZE) {
MCLGET(n, M_DONTWAIT);
if (n->m_flags & M_EXT)
n->m_len = n->m_ext.ext_size;
}
noff = 0;
continue;
}
}
if (len > left)
len = left;
if (txflag) {
awa->awa_encrypt(ctx, mtod(n, caddr_t) + noff,
mtod(m, caddr_t) + moff, len);
crc = awi_crc_update(crc, mtod(m, caddr_t) + moff, len);
} else {
awa->awa_decrypt(ctx, mtod(n, caddr_t) + noff,
mtod(m, caddr_t) + moff, len);
crc = awi_crc_update(crc, mtod(n, caddr_t) + noff, len);
}
left -= len;
moff += len;
noff += len;
}
crc = ~crc;
if (txflag) {
LE_WRITE_4(crcbuf, crc);
if (n->m_len >= noff + sizeof(crcbuf))
n->m_len = noff + sizeof(crcbuf);
else {
n->m_len = noff;
MGET(n->m_next, M_DONTWAIT, n->m_type);
if (n->m_next == NULL)
goto fail;
n = n->m_next;
n->m_len = sizeof(crcbuf);
noff = 0;
}
awa->awa_encrypt(ctx, mtod(n, caddr_t) + noff, crcbuf,
sizeof(crcbuf));
} else {
n->m_len = noff;
noff = 0;
for (; noff < sizeof(crcbuf); noff += len, m = m->m_next) {
if (m->m_len < moff + len)
len = m->m_len - moff;
if (len == 0)
continue;
awa->awa_decrypt(ctx, crcbuf + noff,
mtod(m, caddr_t) + moff, len);
}
if (crc != LE_READ_4(crcbuf))
goto fail;
}
m_freem(m0);
return n0;
fail:
m_freem(m0);
m_freem(n0);
return NULL;
}
/*
* CRC 32 -- routine from RFC 2083
*/
/* Table of CRCs of all 8-bit messages */
static u_int32_t awi_crc_table[256];
static int awi_crc_table_computed = 0;
/* Make the table for a fast CRC. */
static void
awi_crc_init()
{
u_int32_t c;
int n, k;
if (awi_crc_table_computed)
return;
for (n = 0; n < 256; n++) {
c = (u_int32_t)n;
for (k = 0; k < 8; k++) {
if (c & 1)
c = 0xedb88320UL ^ (c >> 1);
else
c = c >> 1;
}
awi_crc_table[n] = c;
}
awi_crc_table_computed = 1;
}
/*
* Update a running CRC with the bytes buf[0..len-1]--the CRC
* should be initialized to all 1's, and the transmitted value
* is the 1's complement of the final running CRC
*/
static u_int32_t
awi_crc_update(crc, buf, len)
u_int32_t crc;
u_int8_t *buf;
int len;
{
u_int8_t *endbuf;
for (endbuf = buf + len; buf < endbuf; buf++)
crc = awi_crc_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
return crc;
}
/*
* Null -- do nothing but copy.
*/
static int
awi_null_ctxlen()
{
return 0;
}
static void
awi_null_setkey(ctx, key, keylen)
void *ctx;
u_char *key;
int keylen;
{
}
static void
awi_null_copy(ctx, dst, src, len)
void *ctx;
u_char *dst;
u_char *src;
int len;
{
memcpy(dst, src, len);
}

584
sys/dev/ic/awi_wicfg.c Normal file
View File

@ -0,0 +1,584 @@
/* $NetBSD: awi_wicfg.c,v 1.1 2000/06/09 05:31:17 onoe Exp $ */
/*
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Atsushi Onoe.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* WaveLAN compatible configuration support routines for the awi driver.
*/
#include "opt_awi.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/mbuf.h>
#include <sys/malloc.h>
#include <sys/proc.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <sys/sockio.h>
#if defined(__FreeBSD__) && __FreeBSD__ >= 4
#include <sys/bus.h>
#else
#include <sys/device.h>
#endif
#include <net/if.h>
#include <net/if_dl.h>
#ifdef __FreeBSD__
#include <net/ethernet.h>
#include <net/if_arp.h>
#else
#include <net/if_ether.h>
#endif
#include <net/if_media.h>
#include <net/if_ieee80211.h>
#include <machine/cpu.h>
#include <machine/bus.h>
#ifdef __FreeBSD__
#include <machine/clock.h>
#endif
#ifdef __NetBSD__
#include <dev/ic/am79c930reg.h>
#include <dev/ic/am79c930var.h>
#include <dev/ic/awireg.h>
#include <dev/ic/awivar.h>
#include <dev/pcmcia/if_wi_ieee.h> /* XXX */
#endif
#ifdef __FreeBSD__
#include <dev/awi/am79c930reg.h>
#include <dev/awi/am79c930var.h>
#undef _KERNEL /* XXX */
#include <i386/include/if_wavelan_ieee.h> /* XXX */
#define _KERNEL /* XXX */
#include <dev/awi/awireg.h>
#include <dev/awi/awivar.h>
#endif
static int awi_cfgget __P((struct ifnet *ifp, u_long cmd, caddr_t data));
static int awi_cfgset __P((struct ifnet *ifp, u_long cmd, caddr_t data));
int
awi_wicfg(ifp, cmd, data)
struct ifnet *ifp;
u_long cmd;
caddr_t data;
{
int error;
switch (cmd) {
case SIOCGWAVELAN:
error = awi_cfgget(ifp, cmd, data);
break;
case SIOCSWAVELAN:
error = suser(curproc->p_ucred, &curproc->p_acflag);
if (error)
break;
error = awi_cfgset(ifp, cmd, data);
break;
default:
error = EINVAL;
break;
}
return error;
}
static int
awi_cfgget(ifp, cmd, data)
struct ifnet *ifp;
u_long cmd;
caddr_t data;
{
int i, error, keylen;
char *p;
struct awi_softc *sc = (struct awi_softc *)ifp->if_softc;
struct ifreq *ifr = (struct ifreq *)data;
struct wi_ltv_keys *keys;
struct wi_key *k;
struct wi_req wreq;
#ifdef WICACHE
struct wi_sigcache wsc;
struct awi_bss *bp;
#endif /* WICACHE */
error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
if (error)
return error;
switch (wreq.wi_type) {
case WI_RID_SERIALNO:
memcpy(wreq.wi_val, sc->sc_banner, AWI_BANNER_LEN);
wreq.wi_len = (AWI_BANNER_LEN + 1) / 2;
break;
case WI_RID_NODENAME:
strcpy((char *)&wreq.wi_val[1], hostname);
wreq.wi_val[0] = strlen(hostname);
wreq.wi_len = (1 + wreq.wi_val[0] + 1) / 2;
break;
case WI_RID_OWN_SSID:
p = sc->sc_ownssid;
wreq.wi_val[0] = p[1];
memcpy(&wreq.wi_val[1], p + 2, p[1]);
wreq.wi_len = (1 + wreq.wi_val[0] + 1) / 2;
break;
case WI_RID_CURRENT_SSID:
if (ifp->if_flags & IFF_RUNNING) {
p = sc->sc_bss.essid;
wreq.wi_val[0] = p[1];
memcpy(&wreq.wi_val[1], p + 2, p[1]);
} else {
wreq.wi_val[0] = 0;
wreq.wi_val[1] = '\0';
}
wreq.wi_len = (1 + wreq.wi_val[0] + 1) / 2;
break;
case WI_RID_DESIRED_SSID:
p = sc->sc_mib_mac.aDesired_ESS_ID;
wreq.wi_val[0] = p[1];
memcpy(&wreq.wi_val[1], p + 2, p[1]);
wreq.wi_len = (1 + wreq.wi_val[0] + 1) / 2;
break;
case WI_RID_CURRENT_BSSID:
if (ifp->if_flags & IFF_RUNNING)
memcpy(wreq.wi_val, sc->sc_bss.bssid, ETHER_ADDR_LEN);
else
memset(wreq.wi_val, 0, ETHER_ADDR_LEN);
wreq.wi_len = ETHER_ADDR_LEN / 2;
break;
case WI_RID_CHANNEL_LIST:
if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH) {
wreq.wi_val[0] = sc->sc_scan_min;
wreq.wi_val[1] = sc->sc_scan_max;
wreq.wi_len = 2;
} else {
wreq.wi_val[0] = 0;
for (i = sc->sc_scan_min; i <= sc->sc_scan_max; i++)
wreq.wi_val[0] |= 1 << (i - 1);
wreq.wi_len = 1;
}
break;
case WI_RID_OWN_CHNL:
wreq.wi_val[0] = sc->sc_scan_cur;
wreq.wi_len = 1;
break;
case WI_RID_CURRENT_CHAN:
if (sc->sc_mib_phy.IEEE_PHY_Type == AWI_PHY_TYPE_FH)
wreq.wi_val[0] = sc->sc_bss.pattern;
else
wreq.wi_val[0] = sc->sc_bss.chanset;
wreq.wi_len = 1;
break;
case WI_RID_COMMS_QUALITY:
wreq.wi_val[0] = 0; /* quality */
wreq.wi_val[1] = sc->sc_bss.rssi; /* signal */
wreq.wi_val[2] = 0; /* noise */
wreq.wi_len = 3;
break;
case WI_RID_PROMISC:
wreq.wi_val[0] = sc->sc_mib_mac.aPromiscuous_Enable;
wreq.wi_len = 1;
break;
case WI_RID_PORTTYPE:
if (sc->sc_mib_local.Network_Mode)
wreq.wi_val[0] = 1;
else if (!sc->sc_no_bssid)
wreq.wi_val[0] = 2;
else
wreq.wi_val[0] = 3;
wreq.wi_len = 1;
break;
case WI_RID_MAC_NODE:
memcpy(wreq.wi_val, sc->sc_mib_addr.aMAC_Address,
ETHER_ADDR_LEN);
wreq.wi_len = ETHER_ADDR_LEN / 2;
break;
case WI_RID_TX_RATE:
case WI_RID_CUR_TX_RATE:
wreq.wi_val[0] = sc->sc_tx_rate / 10;
wreq.wi_len = 1;
break;
case WI_RID_RTS_THRESH:
wreq.wi_val[0] = LE_READ_2(&sc->sc_mib_mac.aRTS_Threshold);
wreq.wi_len = 1;
break;
case WI_RID_CREATE_IBSS:
wreq.wi_val[0] = sc->sc_start_bss;
wreq.wi_len = 1;
break;
case WI_RID_SYSTEM_SCALE:
wreq.wi_val[0] = 1; /* low density ... not supported */
wreq.wi_len = 1;
break;
case WI_RID_PM_ENABLED:
wreq.wi_val[0] = sc->sc_mib_local.Power_Saving_Mode_Dis ? 0 : 1;
wreq.wi_len = 1;
break;
case WI_RID_MAX_SLEEP:
wreq.wi_val[0] = 0; /* not implemented */
wreq.wi_len = 1;
break;
case WI_RID_WEP_AVAIL:
wreq.wi_val[0] = 1;
wreq.wi_len = 1;
break;
case WI_RID_ENCRYPTION:
wreq.wi_val[0] = awi_wep_getalgo(sc);
wreq.wi_len = 1;
break;
case WI_RID_TX_CRYPT_KEY:
wreq.wi_val[0] = sc->sc_wep_defkid;
wreq.wi_len = 1;
break;
case WI_RID_DEFLT_CRYPT_KEYS:
keys = (struct wi_ltv_keys *)&wreq;
for (i = 0; i < IEEE80211_WEP_NKID; i++) {
k = &keys->wi_keys[i];
keylen = sizeof(k->wi_keydat);
error = awi_wep_getkey(sc, i, k->wi_keydat, &keylen);
if (error)
break;
k->wi_keylen = keylen;
}
wreq.wi_len = sizeof(*keys) / 2;
break;
case WI_RID_MAX_DATALEN:
wreq.wi_val[0] = LE_READ_2(&sc->sc_mib_mac.aMax_Frame_Length);
wreq.wi_len = 1;
break;
case WI_RID_IFACE_STATS:
/* not implemented yet */
wreq.wi_len = 0;
break;
#ifdef WICACHE
case WI_RID_READ_CACHE:
for (bp = TAILQ_FIRST(&sc->sc_scan), i = 0;
bp != NULL && i < MAXWICACHE;
bp = TAILQ_NEXT(bp, list), i++) {
memcpy(wsc.macsrc, bp->esrc, ETHER_ADDR_LEN);
/*XXX*/
memcpy(&wsc.ipsrc, bp->bssid, sizeof(wsc.ipsrc));
wsc.signal = bp->rssi;
wsc.noise = 0;
wsc.quality = 0;
memcpy((caddr_t)wreq.wi_val + sizeof(wsc) * i,
&wsc, sizeof(wsc));
}
wreq.wi_len = sizeof(wsc) * i / 2;
break;
#endif /* WICACHE */
default:
error = EINVAL;
break;
}
if (error == 0) {
wreq.wi_len++;
error = copyout(&wreq, ifr->ifr_data, sizeof(wreq));
}
return error;
}
static int
awi_cfgset(ifp, cmd, data)
struct ifnet *ifp;
u_long cmd;
caddr_t data;
{
int i, error, rate, oregion;
u_int8_t *phy_rates;
struct awi_softc *sc = (struct awi_softc *)ifp->if_softc;
struct ifreq *ifr = (struct ifreq *)data;
struct wi_ltv_keys *keys;
struct wi_key *k;
struct wi_req wreq;
error = copyin(ifr->ifr_data, &wreq, sizeof(wreq));
if (error)
return error;
if (wreq.wi_len-- < 1)
return EINVAL;
switch (wreq.wi_type) {
case WI_RID_SERIALNO:
case WI_RID_NODENAME:
error = EPERM;
break;
case WI_RID_OWN_SSID:
if (wreq.wi_len < (1 + wreq.wi_val[0] + 1) / 2) {
error = EINVAL;
break;
}
if (wreq.wi_val[0] > IEEE80211_NWID_LEN) {
error = EINVAL;
break;
}
memset(sc->sc_ownssid, 0, AWI_ESS_ID_SIZE);
sc->sc_ownssid[0] = IEEE80211_ELEMID_SSID;
sc->sc_ownssid[1] = wreq.wi_val[0];
memcpy(&sc->sc_ownssid[2], &wreq.wi_val[1], wreq.wi_val[0]);
if (!sc->sc_mib_local.Network_Mode &&
!sc->sc_no_bssid && sc->sc_start_bss)
error = ENETRESET;
break;
case WI_RID_CURRENT_SSID:
error = EPERM;
break;
case WI_RID_DESIRED_SSID:
if (wreq.wi_len < (1 + wreq.wi_val[0] + 1) / 2) {
error = EINVAL;
break;
}
if (wreq.wi_val[0] > IEEE80211_NWID_LEN) {
error = EINVAL;
break;
}
memset(sc->sc_mib_mac.aDesired_ESS_ID, 0, AWI_ESS_ID_SIZE);
sc->sc_mib_mac.aDesired_ESS_ID[0] = IEEE80211_ELEMID_SSID;
sc->sc_mib_mac.aDesired_ESS_ID[1] = wreq.wi_val[0];
memcpy(&sc->sc_mib_mac.aDesired_ESS_ID[2], &wreq.wi_val[1],
wreq.wi_val[0]);
if (sc->sc_mib_local.Network_Mode || !sc->sc_no_bssid)
error = ENETRESET;
break;
case WI_RID_CURRENT_BSSID:
error = EPERM;
break;
case WI_RID_CHANNEL_LIST:
if (wreq.wi_len != 1) {
error = EINVAL;
break;
}
oregion = sc->sc_mib_phy.aCurrent_Reg_Domain;
if (wreq.wi_val[0] == oregion)
break;
sc->sc_mib_phy.aCurrent_Reg_Domain = wreq.wi_val[0];
error = awi_init_region(sc);
if (error) {
sc->sc_mib_phy.aCurrent_Reg_Domain = oregion;
break;
}
error = ENETRESET;
break;
case WI_RID_OWN_CHNL:
if (wreq.wi_len != 1) {
error = EINVAL;
break;
}
if (wreq.wi_val[0] < sc->sc_scan_min ||
wreq.wi_val[0] > sc->sc_scan_max) {
error = EINVAL;
break;
}
sc->sc_ownch = wreq.wi_val[0];
if (!sc->sc_mib_local.Network_Mode &&
!sc->sc_no_bssid && sc->sc_start_bss)
error = ENETRESET;
break;
case WI_RID_CURRENT_CHAN:
error = EPERM;
break;
case WI_RID_COMMS_QUALITY:
error = EPERM;
break;
case WI_RID_PROMISC:
error = EPERM;
break;
case WI_RID_PORTTYPE:
if (wreq.wi_len != 1) {
error = EINVAL;
break;
}
switch (wreq.wi_val[0]) {
case 1:
sc->sc_mib_local.Network_Mode = 1;
sc->sc_no_bssid = 0;
error = ENETRESET;
break;
case 2:
sc->sc_mib_local.Network_Mode = 0;
sc->sc_no_bssid = 0;
error = ENETRESET;
break;
case 3:
sc->sc_mib_local.Network_Mode = 0;
sc->sc_no_bssid = 1;
error = ENETRESET;
break;
default:
error = EINVAL;
break;
}
break;
case WI_RID_MAC_NODE:
/* should be implemented? */
error = EPERM;
break;
case WI_RID_TX_RATE:
if (wreq.wi_len != 1) {
error = EINVAL;
break;
}
phy_rates = sc->sc_mib_phy.aSuprt_Data_Rates;
switch (wreq.wi_val[0]) {
case 1:
case 2:
case 5:
case 11:
rate = wreq.wi_val[0] * 10;
if (rate == 50)
rate += 5; /*XXX*/
break;
case 3:
case 6:
case 7:
/* auto rate */
phy_rates = sc->sc_mib_phy.aSuprt_Data_Rates;
rate = AWI_RATE_1MBIT;
for (i = 0; i < phy_rates[1]; i++) {
if (AWI_80211_RATE(phy_rates[2 + i]) > rate)
rate = AWI_80211_RATE(phy_rates[2 + i]);
}
break;
default:
rate = 0;
error = EINVAL;
break;
}
if (error)
break;
for (i = 0; i < phy_rates[1]; i++) {
if (rate == AWI_80211_RATE(phy_rates[2 + i]))
break;
}
if (i == phy_rates[1]) {
error = EINVAL;
break;
}
sc->sc_tx_rate = rate;
break;
case WI_RID_CUR_TX_RATE:
error = EPERM;
break;
case WI_RID_RTS_THRESH:
if (wreq.wi_len != 1) {
error = EINVAL;
break;
}
LE_WRITE_2(&sc->sc_mib_mac.aRTS_Threshold, wreq.wi_val[0]);
error = ENETRESET;
break;
case WI_RID_CREATE_IBSS:
if (wreq.wi_len != 1) {
error = EINVAL;
break;
}
sc->sc_start_bss = wreq.wi_val[0] ? 1 : 0;
error = ENETRESET;
break;
case WI_RID_SYSTEM_SCALE:
error = EINVAL; /* not supported */
break;
case WI_RID_PM_ENABLED:
case WI_RID_MAX_SLEEP:
error = EINVAL; /* not implemented */
break;
case WI_RID_WEP_AVAIL:
error = EPERM;
break;
case WI_RID_ENCRYPTION:
if (wreq.wi_len != 1) {
error = EINVAL;
break;
}
error = awi_wep_setalgo(sc, wreq.wi_val[0]);
if (error)
break;
error = ENETRESET;
break;
case WI_RID_TX_CRYPT_KEY:
if (wreq.wi_len != 1) {
error = EINVAL;
break;
}
if (wreq.wi_val[0] >= IEEE80211_WEP_NKID) {
error = EINVAL;
break;
}
sc->sc_wep_defkid = wreq.wi_val[1];
break;
case WI_RID_DEFLT_CRYPT_KEYS:
if (wreq.wi_len != sizeof(*keys) / 2) {
error = EINVAL;
break;
}
keys = (struct wi_ltv_keys *)&wreq;
for (i = 0; i < IEEE80211_WEP_NKID; i++) {
k = &keys->wi_keys[i];
error = awi_wep_setkey(sc, i, k->wi_keydat,
k->wi_keylen);
if (error)
break;
}
break;
case WI_RID_MAX_DATALEN:
if (wreq.wi_len != 1) {
error = EINVAL;
break;
}
if (wreq.wi_val[0] < 350 || wreq.wi_val[0] > 2304) {
error = EINVAL;
break;
}
LE_WRITE_2(&sc->sc_mib_mac.aMax_Frame_Length, wreq.wi_val[0]);
break;
case WI_RID_IFACE_STATS:
error = EPERM;
break;
default:
error = EINVAL;
break;
}
if (error == ENETRESET) {
if (sc->sc_enabled) {
awi_stop(sc);
error = awi_init(sc);
} else
error = 0;
}
return error;
}

View File

@ -1,71 +0,0 @@
/* $NetBSD: awictl.h,v 1.1 2000/03/23 06:04:24 onoe Exp $ */
/*
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Atsushi Onoe
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _IC_AWICTL_H
#define _IC_AWICTL_H
#define AWICTL_BUFSIZE 32
#define AWICTL_REGION 1 /* u_int8_t: region code */
#define AWICTL_CHANSET 2 /* u_int8_t[3]: cur, min, max */
#define AWICTL_RAWBPF 3 /* u_int8_t: pass raw 802.11 header to bpf */
#define AWICTL_DESSID 4 /* u_int8_t[IEEE80211_NWID_LEN]: desired ESSID*/
#define AWICTL_CESSID 5 /* u_int8_t[IEEE80211_NWID_LEN]: current ESSID*/
#define AWICTL_MODE 6 /* u_int8_t: mode */
#define AWICTL_MODE_INFRA 0 /* infrastructure mode */
#define AWICTL_MODE_ADHOC 1 /* adhoc mode */
#define AWICTL_MODE_NOBSSID 2 /* adhoc without bssid mode */
#ifndef SIOCSDRVSPEC
#define SIOCSDRVSPEC _IOW('i', 123, struct ifdrv)
#endif
#ifndef SIOCGDRVSPEC
#define SIOCGDRVSPEC _IOWR('i', 122, struct ifdrv)
#endif
#ifdef __FreeBSD__
struct ifdrv {
char ifd_name[IFNAMSIZ]; /* if name, e.g. "en0" */
unsigned long ifd_cmd;
size_t ifd_len;
void *ifd_data;
};
#endif
#endif /* !_IC_AWICTL_H */

View File

@ -1,4 +1,4 @@
/* $NetBSD: awivar.h,v 1.8 2000/05/29 17:37:12 jhawk Exp $ */
/* $NetBSD: awivar.h,v 1.9 2000/06/09 05:31:18 onoe Exp $ */
/*
* Copyright (c) 2000 The NetBSD Foundation, Inc.
@ -47,6 +47,7 @@
#define AWI_TRANS_TIMEOUT 2000
#define AWI_NTXBUFS 4
#define AWI_MAX_KEYLEN 16
enum awi_status {
AWI_ST_INIT,
@ -76,6 +77,14 @@ struct awi_bss
u_int8_t essid[IEEE80211_NWID_LEN + 2];
};
struct awi_wep_algo {
char *awa_name;
int (*awa_ctxlen) __P((void));
void (*awa_setkey) __P((void *, u_char *, int));
void (*awa_encrypt) __P((void *, u_char *, u_char *, int));
void (*awa_decrypt) __P((void *, u_char *, u_char *, int));
};
struct awi_softc
{
#ifdef __NetBSD__
@ -92,7 +101,6 @@ struct awi_softc
struct device sc_dev;
#endif
struct arpcom sc_ec;
struct callout_handle sc_tohandle;
#endif
struct am79c930_softc sc_chip;
struct ifnet *sc_ifp;
@ -123,6 +131,8 @@ struct awi_softc
u_int8_t sc_scan_max;
u_int8_t sc_scan_set;
struct awi_bss sc_bss;
u_int8_t sc_ownssid[IEEE80211_NWID_LEN + 2];
u_int8_t sc_ownch;
int sc_rx_timer;
u_int32_t sc_rxdoff;
@ -137,6 +147,13 @@ struct awi_softc
u_int32_t sc_txnext;
u_int32_t sc_txdone;
int sc_wep_keylen[IEEE80211_WEP_NKID]; /* keylen */
u_int8_t sc_wep_key[IEEE80211_WEP_NKID][AWI_MAX_KEYLEN];
int sc_wep_defkid;
void *sc_wep_ctx; /* work area */
struct awi_wep_algo *sc_wep_algo;
char sc_banner[AWI_BANNER_LEN];
struct awi_mib_local sc_mib_local;
struct awi_mib_addr sc_mib_addr;
struct awi_mib_mac sc_mib_mac;
@ -186,4 +203,32 @@ void awi_reset __P((struct awi_softc *));
#ifdef __NetBSD__
int awi_activate __P((struct device *, enum devact));
int awi_detach __P((struct awi_softc *));
void awi_power __P((struct awi_softc *, int));
#endif
void awi_stop __P((struct awi_softc *sc));
int awi_init __P((struct awi_softc *sc));
int awi_init_region __P((struct awi_softc *));
int awi_wicfg __P((struct ifnet *, u_long, caddr_t));
int awi_wep_getalgo __P((struct awi_softc *));
int awi_wep_setalgo __P((struct awi_softc *, int));
int awi_wep_setkey __P((struct awi_softc *, int, unsigned char *, int));
int awi_wep_getkey __P((struct awi_softc *, int, unsigned char *, int *));
struct mbuf *awi_wep_encrypt __P((struct awi_softc *, struct mbuf *, int));
#ifdef __FreeBSD__
/* Provide mem* for compat with NetBSD to fix LINT */
static __inline int
memcmp(const void *b1, const void *b2, size_t len)
{
return (bcmp(b1, b2, len));
}
static __inline void *
memset(void *b, int c, size_t len)
{
bzero(b, len);
return (b);
}
#endif

View File

@ -1,4 +1,4 @@
# $NetBSD: files.pcmcia,v 1.27 2000/06/06 16:16:36 soren Exp $
# $NetBSD: files.pcmcia,v 1.28 2000/06/09 05:31:19 onoe Exp $
#
# Config.new file and device description for machine-independent PCMCIA code.
# Included by ports that need it.
@ -93,8 +93,11 @@ file dev/pcmcia/if_ray.c ray
# AMD 79c930-based 802.11 cards (including BayStack 650 FH card).
device awi: arp, ether, ifnet
attach awi at pcmcia with awi_pcmcia
defopt opt_awi.h AWI_DEBUG
file dev/pcmcia/if_awi_pcmcia.c awi_pcmcia
file dev/ic/awi.c awi
file dev/ic/awi_wep.c awi
file dev/ic/awi_wicfg.c awi
file dev/ic/am79c930.c awi
# Xircom Ethernet cards

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_awi_pcmcia.c,v 1.14 2000/03/22 22:33:47 mycroft Exp $ */
/* $NetBSD: if_awi_pcmcia.c,v 1.15 2000/06/09 05:31:19 onoe Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@ -44,6 +44,7 @@
* DS cards based on the same chipset.
*/
#include "opt_awi.h"
#include "opt_inet.h"
#include "opt_ns.h"
#include "bpfilter.h"
@ -122,11 +123,6 @@ struct cfattach awi_pcmcia_ca = {
awi_pcmcia_detach, awi_activate
};
#if __NetBSD_Version__ <= 104120000
#define PCMCIA_VENDOR_BAY 0x01eb /* Bay Networks */
#define PCMCIA_PRODUCT_BAY_STACK_650 0x804
#endif
static struct awi_pcmcia_product {
u_int32_t app_vendor; /* vendor ID */
u_int32_t app_product; /* product ID */
@ -242,7 +238,6 @@ awi_pcmcia_find(psc, pa, cfe)
{
struct awi_softc *sc = &psc->sc_awi;
int fail = 0;
u_int8_t version[AWI_BANNER_LEN];
/*
* see if we can read the firmware version sanely
@ -270,9 +265,9 @@ awi_pcmcia_find(psc, pa, cfe)
DELAY(1000);
awi_read_bytes(sc, AWI_BANNER, version, AWI_BANNER_LEN);
awi_read_bytes(sc, AWI_BANNER, sc->sc_banner, AWI_BANNER_LEN);
if (memcmp(version, "PCnetMobile:", 12) == 0)
if (memcmp(sc->sc_banner, "PCnetMobile:", 12) == 0)
return (0);
fail++;
@ -433,12 +428,6 @@ awi_pcmcia_powerhook(why, arg)
{
struct awi_pcmcia_softc *psc = arg;
struct awi_softc *sc = &psc->sc_awi;
int ocansleep;
if (why == PWR_RESUME) {
ocansleep = sc->sc_cansleep;
sc->sc_cansleep = 0;
awi_reset(sc);
sc->sc_cansleep = ocansleep;
}
awi_power(sc, why);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_ieee80211.h,v 1.2 2000/03/10 05:44:23 onoe Exp $ */
/* $NetBSD: if_ieee80211.h,v 1.3 2000/06/09 05:31:20 onoe Exp $ */
#ifndef _NET_IF_IEEE80211_H_
@ -103,6 +103,11 @@ struct ieee80211_frame {
#define IEEE80211_STATUS_CHALLENGE 15
#define IEEE80211_STATUS_TIMEOUT 16
#define IEEE80211_WEP_KEYLEN 5 /* 40bit */
#define IEEE80211_WEP_IVLEN 3 /* 24bit */
#define IEEE80211_WEP_KIDLEN 1 /* 1 octet */
#define IEEE80211_WEP_CRCLEN 4 /* CRC-32 */
#define IEEE80211_WEP_NKID 4 /* number of key ids */
#define IEEE80211_NWID_LEN 32