summaryrefslogtreecommitdiffstats
path: root/sys/dev/an
diff options
context:
space:
mode:
authorbrooks <brooks@FreeBSD.org>2001-06-22 23:35:24 +0000
committerbrooks <brooks@FreeBSD.org>2001-06-22 23:35:24 +0000
commitcb05fc6c2a8bdf494106b7b9b73e2a36ef37f0df (patch)
treecc8cdfa400f80dd560f8e223192365ce6a55a456 /sys/dev/an
parentdfa68807f4be9196e97eddca29217d6347a289d0 (diff)
downloadFreeBSD-src-cb05fc6c2a8bdf494106b7b9b73e2a36ef37f0df.zip
FreeBSD-src-cb05fc6c2a8bdf494106b7b9b73e2a36ef37f0df.tar.gz
Fix a number of bugs in the implementation of the WEP related status
functions in ifconfig. "ifconfig an0" should output the correct status now. Also, make the read and write functions both more robust and more consistant. This should stop most of the incorrect size complaints and eliminate the possiability of panics from firmware that increases resource sizes. PR: kern/27826 Reviewed by: imp, jlemon Submitted by: Doug Ambrisko <ambrisko@ambrisko.com> David Wolfskill <dhw@whistle.com>
Diffstat (limited to 'sys/dev/an')
-rw-r--r--sys/dev/an/if_aironet_ieee.h2
-rw-r--r--sys/dev/an/if_an.c219
-rw-r--r--sys/dev/an/if_anreg.h2
3 files changed, 156 insertions, 67 deletions
diff --git a/sys/dev/an/if_aironet_ieee.h b/sys/dev/an/if_aironet_ieee.h
index a1eeb26..b1ab4be 100644
--- a/sys/dev/an/if_aironet_ieee.h
+++ b/sys/dev/an/if_aironet_ieee.h
@@ -528,7 +528,7 @@ struct an_ltv_status {
u_int16_t an_max_noise_prev_sec; /* 0x7A */
u_int16_t an_avg_noise_prev_min; /* 0x7C */
u_int16_t an_max_noise_prev_min; /* 0x7E */
- u_int16_t an_spare[3];
+ u_int16_t an_spare[5];
};
#define AN_STATUS_OPMODE_CONFIGURED 0x0001
diff --git a/sys/dev/an/if_an.c b/sys/dev/an/if_an.c
index f7a383d..5f1262b 100644
--- a/sys/dev/an/if_an.c
+++ b/sys/dev/an/if_an.c
@@ -162,9 +162,13 @@ static void an_cache_store __P((struct an_softc *, struct ether_header *,
struct mbuf *, unsigned short));
#endif
+static void an_dump_record __P((struct an_softc *,struct an_ltv_gen *,
+ char *));
+
static int an_media_change __P((struct ifnet *));
static void an_media_status __P((struct ifnet *, struct ifmediareq *));
+static int an_dump = 0;
/*
* We probe for an Aironet 4500/4800 card by attempting to
* read the default SSID list. On reset, the first entry in
@@ -181,7 +185,7 @@ int an_probe(dev)
bzero((char *)&ssid, sizeof(ssid));
error = an_alloc_port(dev, 0, AN_IOSIZ);
- if (error)
+ if (error != 0)
return (0);
/* can't do autoprobing */
@@ -393,12 +397,12 @@ int an_attach(sc, unit, flags)
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,
IFM_IEEE80211_ADHOC, 0), 0);
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0), 0);
- if(sc->an_caps.an_rates[2] == AN_RATE_5_5MBPS) {
+ if (sc->an_caps.an_rates[2] == AN_RATE_5_5MBPS) {
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,
IFM_IEEE80211_ADHOC, 0), 0);
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 0, 0), 0);
}
- if(sc->an_caps.an_rates[3] == AN_RATE_11MBPS) {
+ if (sc->an_caps.an_rates[3] == AN_RATE_11MBPS) {
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,
IFM_IEEE80211_ADHOC, 0), 0);
ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0), 0);
@@ -490,7 +494,7 @@ static void an_rxeof(sc)
error = an_read_data(sc, id, 0x44, (caddr_t)&(eh->ether_type),
rx_frame_802_3.an_rx_802_3_payload_len);
- if (error) {
+ if (error != 0) {
m_freem(m);
ifp->if_ierrors++;
return;
@@ -511,7 +515,7 @@ static void an_txeof(sc, status)
int status;
{
struct ifnet *ifp;
- int id;
+ int id, i;
/* TX DONE enable lan monitor DJA
an_enable_sniff();
@@ -529,12 +533,13 @@ static void an_txeof(sc, status)
} else
ifp->if_opackets++;
- if (id != sc->an_rdata.an_tx_ring[sc->an_rdata.an_tx_cons])
- printf("an%d: id mismatch: expected %x, got %x\n",
- sc->an_unit,
- sc->an_rdata.an_tx_ring[sc->an_rdata.an_tx_cons], id);
+ for (i = 0; i < AN_TX_RING_CNT; i++) {
+ if (id == sc->an_rdata.an_tx_ring[i]) {
+ sc->an_rdata.an_tx_ring[i] = 0;
+ break;
+ }
+ }
- sc->an_rdata.an_tx_ring[sc->an_rdata.an_tx_cons] = 0;
AN_INC(sc->an_rdata.an_tx_cons, AN_TX_RING_CNT);
return;
@@ -720,9 +725,10 @@ static int an_read_record(sc, ltv)
struct an_ltv_gen *ltv;
{
u_int16_t *ptr;
+ u_int8_t *ptr2;
int i, len;
- if (ltv->an_len == 0 || ltv->an_type == 0)
+ if (ltv->an_len < 4 || ltv->an_type == 0)
return(EINVAL);
/* Tell the NIC to enter record read mode. */
@@ -741,20 +747,29 @@ static int an_read_record(sc, ltv)
* Read the length and record type and make sure they
* match what we expect (this verifies that we have enough
* room to hold all of the returned data).
+ * Length includes type but not length.
*/
len = CSR_READ_2(sc, AN_DATA1);
if (len > (ltv->an_len - 2)) {
printf("an%d: record length mismatch -- expected %d, "
- "got %d\n", sc->an_unit, (ltv->an_len - 2), len);
- len = (ltv->an_len - 2);
+ "got %d for Rid %x\n", sc->an_unit,
+ ltv->an_len - 2, len, ltv->an_type);
+ len = ltv->an_len - 2;
+ } else {
+ ltv->an_len = len + 2;
}
- ltv->an_len = len;
-
/* Now read the data. */
+ len -= 2; /* skip the type */
ptr = &ltv->an_val;
- for (i = 0; i < (ltv->an_len - 2) >> 1; i++)
- ptr[i] = CSR_READ_2(sc, AN_DATA1);
+ for (i = len; i > 1; i -= 2)
+ *ptr++ = CSR_READ_2(sc, AN_DATA1);
+ if (i) {
+ ptr2 = (u_int8_t *)ptr;
+ *ptr2 = CSR_READ_1(sc, AN_DATA1);
+ }
+ if (an_dump)
+ an_dump_record(sc, ltv, "Read");
return(0);
}
@@ -767,19 +782,32 @@ static int an_write_record(sc, ltv)
struct an_ltv_gen *ltv;
{
u_int16_t *ptr;
- int i;
+ u_int8_t *ptr2;
+ int i, len;
+
+ if (an_dump)
+ an_dump_record(sc, ltv, "Write");
if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_READ, ltv->an_type))
return(EIO);
-
+
if (an_seek(sc, ltv->an_type, 0, AN_BAP1))
return(EIO);
- CSR_WRITE_2(sc, AN_DATA1, ltv->an_len-2);
+ /*
+ * Length includes type but not length.
+ */
+ len = ltv->an_len - 2;
+ CSR_WRITE_2(sc, AN_DATA1, len);
+ len -= 2; /* skip the type */
ptr = &ltv->an_val;
- for (i = 0; i < (ltv->an_len - 4) >> 1; i++)
- CSR_WRITE_2(sc, AN_DATA1, ptr[i]);
+ for (i = len; i > 1; i -= 2)
+ CSR_WRITE_2(sc, AN_DATA1, *ptr++);
+ if (i) {
+ ptr2 = (u_int8_t *)ptr;
+ CSR_WRITE_1(sc, AN_DATA0, *ptr2);
+ }
if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_WRITE, ltv->an_type))
return(EIO);
@@ -787,6 +815,50 @@ static int an_write_record(sc, ltv)
return(0);
}
+static void an_dump_record(sc, ltv, string)
+ struct an_softc *sc;
+ struct an_ltv_gen *ltv;
+ char *string;
+{
+ u_int8_t *ptr2;
+ int len;
+ int i;
+ int count = 0;
+ char buf[17], temp;
+
+ len = ltv->an_len - 4;
+ printf("an%d: RID %4x, Length %4d, Mode %s\n",
+ sc->an_unit, ltv->an_type, ltv->an_len - 4, string);
+
+ if (an_dump == 1 || (an_dump == ltv->an_type)) {
+ printf("an%d:\t", sc->an_unit);
+ bzero(buf,sizeof(buf));
+
+ ptr2 = (u_int8_t *)&ltv->an_val;
+ for (i = len; i > 0; i--) {
+ printf("%02x ", *ptr2);
+
+ temp = *ptr2++;
+ if (temp >= ' ' && temp <= '~')
+ buf[count] = temp;
+ else if (temp >= 'A' && temp <= 'Z')
+ buf[count] = temp;
+ else
+ buf[count] = '.';
+ if (++count == 16) {
+ count = 0;
+ printf("%s\n",buf);
+ printf("an%d:\t", sc->an_unit);
+ bzero(buf,sizeof(buf));
+ }
+ }
+ for (; count != 16; count++) {
+ printf(" ");
+ }
+ printf(" %s\n",buf);
+ }
+}
+
static int an_seek(sc, id, off, chan)
struct an_softc *sc;
int id, off, chan;
@@ -838,12 +910,11 @@ static int an_read_data(sc, id, off, buf, len)
}
ptr = (u_int16_t *)buf;
- for (i = 0; i < len / 2; i++)
- ptr[i] = CSR_READ_2(sc, AN_DATA1);
- i*=2;
- if (i<len){
- ptr2 = (u_int8_t *)buf;
- ptr2[i] = CSR_READ_1(sc, AN_DATA1);
+ for (i = len; i > 1; i -= 2)
+ *ptr++ = CSR_READ_2(sc, AN_DATA1);
+ if (i) {
+ ptr2 = (u_int8_t *)ptr;
+ *ptr2 = CSR_READ_1(sc, AN_DATA1);
}
return(0);
@@ -865,12 +936,11 @@ static int an_write_data(sc, id, off, buf, len)
}
ptr = (u_int16_t *)buf;
- for (i = 0; i < (len / 2); i++)
- CSR_WRITE_2(sc, AN_DATA0, ptr[i]);
- i*=2;
- if (i<len){
- ptr2 = (u_int8_t *)buf;
- CSR_WRITE_1(sc, AN_DATA0, ptr2[i]);
+ for (i = len; i > 1; i -= 2)
+ CSR_WRITE_2(sc, AN_DATA0, *ptr++);
+ if (i) {
+ ptr2 = (u_int8_t *)ptr;
+ CSR_WRITE_1(sc, AN_DATA0, *ptr2);
}
return(0);
@@ -1076,7 +1146,7 @@ static int an_ioctl(ifp, command, data)
break;
case SIOCGAIRONET:
error = copyin(ifr->ifr_data, &areq, sizeof(areq));
- if (error)
+ if (error != 0)
break;
#ifdef ANCACHE
if (areq.an_type == AN_RID_ZERO_CACHE) {
@@ -1104,7 +1174,7 @@ static int an_ioctl(ifp, command, data)
if ((error = suser(p)))
goto out;
error = copyin(ifr->ifr_data, &areq, sizeof(areq));
- if (error)
+ if (error != 0)
break;
an_setdef(sc, &areq);
break;
@@ -1112,7 +1182,7 @@ static int an_ioctl(ifp, command, data)
areq.an_len = sizeof(areq);
switch(ireq->i_type) {
case IEEE80211_IOC_SSID:
- if(ireq->i_val == -1) {
+ if (ireq->i_val == -1) {
areq.an_type = AN_RID_STATUS;
if (an_read_record(sc,
(struct an_ltv_gen *)&areq)) {
@@ -1121,20 +1191,20 @@ static int an_ioctl(ifp, command, data)
}
len = status->an_ssidlen;
tmpptr = status->an_ssid;
- } else if(ireq->i_val >= 0) {
+ } else if (ireq->i_val >= 0) {
areq.an_type = AN_RID_SSIDLIST;
if (an_read_record(sc,
(struct an_ltv_gen *)&areq)) {
error = EINVAL;
break;
}
- if(ireq->i_val == 0) {
+ if (ireq->i_val == 0) {
len = ssids->an_ssid1_len;
tmpptr = ssids->an_ssid1;
- } else if(ireq->i_val == 1) {
+ } else if (ireq->i_val == 1) {
len = ssids->an_ssid2_len;
tmpptr = ssids->an_ssid3;
- } else if(ireq->i_val == 1) {
+ } else if (ireq->i_val == 1) {
len = ssids->an_ssid3_len;
tmpptr = ssids->an_ssid3;
} else {
@@ -1145,7 +1215,7 @@ static int an_ioctl(ifp, command, data)
error = EINVAL;
break;
}
- if(len > IEEE80211_NWID_LEN) {
+ if (len > IEEE80211_NWID_LEN) {
error = EINVAL;
break;
}
@@ -1165,8 +1235,8 @@ static int an_ioctl(ifp, command, data)
error = EINVAL;
break;
}
- if(config->an_authtype & AN_AUTHTYPE_PRIVACY_IN_USE) {
- if(config->an_authtype &
+ if (config->an_authtype & AN_AUTHTYPE_PRIVACY_IN_USE) {
+ if (config->an_authtype &
AN_AUTHTYPE_ALLOW_UNENCRYPTED)
ireq->i_val = IEEE80211_WEP_MIXED;
else
@@ -1183,27 +1253,27 @@ static int an_ioctl(ifp, command, data)
* ancontrol so it will have to do until we get
* access to actual Cisco code.
*/
- if(ireq->i_val < 0 || ireq->i_val > 7) {
+ if (ireq->i_val < 0 || ireq->i_val > 7) {
error = EINVAL;
break;
}
len = 0;
- if(ireq->i_val < 4) {
+ if (ireq->i_val < 4) {
areq.an_type = AN_RID_WEP_TEMP;
- for(i=0; i<4; i++) {
- areq.an_len = sizeof(areq);
+ for (i = 0; i < 5; i++) {
if (an_read_record(sc,
(struct an_ltv_gen *)&areq)) {
error = EINVAL;
break;
}
- len = key->klen;
- if(i == ireq->i_val)
+ if (key->kindex == 0xffff)
break;
+ if (key->kindex == ireq->i_val)
+ len = key->klen;
/* Required to get next entry */
areq.an_type = AN_RID_WEP_PERM;
}
- if(error)
+ if (error != 0)
break;
}
/* We aren't allowed to read the value of the
@@ -1219,6 +1289,25 @@ static int an_ioctl(ifp, command, data)
ireq->i_val = 8;
break;
case IEEE80211_IOC_WEPTXKEY:
+ /*
+ * For some strange reason, you have to read all
+ * keys before you can read the txkey.
+ */
+ areq.an_type = AN_RID_WEP_TEMP;
+ for (i = 0; i < 5; i++) {
+ if (an_read_record(sc,
+ (struct an_ltv_gen *)&areq)) {
+ error = EINVAL;
+ break;
+ }
+ if (key->kindex == 0xffff)
+ break;
+ /* Required to get next entry */
+ areq.an_type = AN_RID_WEP_PERM;
+ }
+ if (error != 0)
+ break;
+
areq.an_type = AN_RID_WEP_PERM;
key->kindex = 0xffff;
if (an_read_record(sc,
@@ -1277,13 +1366,13 @@ static int an_ioctl(ifp, command, data)
error = EINVAL;
break;
}
- if(config->an_psave_mode == AN_PSAVE_NONE) {
+ if (config->an_psave_mode == AN_PSAVE_NONE) {
ireq->i_val = IEEE80211_POWERSAVE_OFF;
- } else if(config->an_psave_mode == AN_PSAVE_CAM) {
+ } else if (config->an_psave_mode == AN_PSAVE_CAM) {
ireq->i_val = IEEE80211_POWERSAVE_CAM;
- } else if(config->an_psave_mode == AN_PSAVE_PSP) {
+ } else if (config->an_psave_mode == AN_PSAVE_PSP) {
ireq->i_val = IEEE80211_POWERSAVE_PSP;
- } else if(config->an_psave_mode == AN_PSAVE_PSP_CAM) {
+ } else if (config->an_psave_mode == AN_PSAVE_PSP_CAM) {
ireq->i_val = IEEE80211_POWERSAVE_PSP_CAM;
} else
error = EINVAL;
@@ -1326,7 +1415,7 @@ static int an_ioctl(ifp, command, data)
error = EINVAL;
break;
}
- if(ireq->i_len > IEEE80211_NWID_LEN) {
+ if (ireq->i_len > IEEE80211_NWID_LEN) {
error = EINVAL;
break;
}
@@ -1381,13 +1470,13 @@ static int an_ioctl(ifp, command, data)
break;
}
error = copyin(ireq->i_data, tmpstr, 13);
- if(error)
+ if (error != 0)
break;
bzero(&areq, sizeof(struct an_ltv_key));
areq.an_len = sizeof(struct an_ltv_key);
key->mac[0] = 1; /* The others are 0. */
key->kindex = ireq->i_val % 4;
- if(ireq->i_val < 4)
+ if (ireq->i_val < 4)
areq.an_type = AN_RID_WEP_TEMP;
else
areq.an_type = AN_RID_WEP_PERM;
@@ -1395,7 +1484,7 @@ static int an_ioctl(ifp, command, data)
bcopy(tmpstr, key->key, key->klen);
break;
case IEEE80211_IOC_WEPTXKEY:
- if(ireq->i_val < 0 || ireq->i_val > 3) {
+ if (ireq->i_val < 0 || ireq->i_val > 3) {
error = EINVAL;
break;
}
@@ -1424,7 +1513,7 @@ static int an_ioctl(ifp, command, data)
}
break;
case IEEE80211_IOC_STATIONNAME:
- if(ireq->i_len > 16) {
+ if (ireq->i_len > 16) {
error = EINVAL;
break;
}
@@ -1478,7 +1567,7 @@ static int an_ioctl(ifp, command, data)
out:
AN_UNLOCK(sc);
- return(error);
+ return(error != 0);
}
static int an_init_tx_ring(sc)
@@ -1647,7 +1736,7 @@ static void an_start(ifp)
tx_frame_802_3.an_tx_802_3_payload_len,
(caddr_t)&sc->an_txbuf);
- txcontrol=AN_TXCTL_8023;
+ txcontrol = AN_TXCTL_8023;
/* write the txcontrol only */
an_write_data(sc, id, 0x08, (caddr_t)&txcontrol,
sizeof(txcontrol));
@@ -1827,7 +1916,7 @@ void an_cache_store (sc, eh, m, rx_quality)
int i;
static int cache_slot = 0; /* use this cache entry */
static int wrapindex = 0; /* next "free" cache entry */
- int saanp=0;
+ int saanp = 0;
/* filters:
* 1. ip only
@@ -1868,7 +1957,7 @@ void an_cache_store (sc, eh, m, rx_quality)
* . MAC address is 6 bytes,
* . var w_nextitem holds total number of entries already cached
*/
- for(i = 0; i < sc->an_nextitem; i++) {
+ for (i = 0; i < sc->an_nextitem; i++) {
if (! bcmp(eh->ether_shost , sc->an_sigcache[i].macsrc, 6 )) {
/* Match!,
* so we already have this entry,
@@ -1988,7 +2077,7 @@ static void an_media_status(ifp, imr)
imr->ifm_status = IFM_AVALID|IFM_ACTIVE;
}
- if(sc->an_tx_rate == 0) {
+ if (sc->an_tx_rate == 0) {
imr->ifm_active = IFM_IEEE80211|IFM_AUTO;
if (sc->an_config.an_opmode == AN_OPMODE_IBSS_ADHOC)
imr->ifm_active |= IFM_IEEE80211_ADHOC;
diff --git a/sys/dev/an/if_anreg.h b/sys/dev/an/if_anreg.h
index e86e354..e26561f 100644
--- a/sys/dev/an/if_anreg.h
+++ b/sys/dev/an/if_anreg.h
@@ -532,7 +532,7 @@ struct an_ltv_status {
u_int16_t an_max_noise_prev_sec; /* 0x7A */
u_int16_t an_avg_noise_prev_min; /* 0x7C */
u_int16_t an_max_noise_prev_min; /* 0x7E */
- u_int16_t an_spare[3];
+ u_int16_t an_spare[5];
};
#define AN_STATUS_OPMODE_CONFIGURED 0x0001
OpenPOWER on IntegriCloud