Date: Fri, 1 Jun 2001 19:31:23 -0700 (PDT) From: brooks@one-eyed-alien.net To: FreeBSD-gnats-submit@freebsd.org Cc: Doug Ambrisko <ambrisko@ambrisko.com> Subject: kern/27826: [PATCH] correct minor bugs in an(4) ifconfig support Message-ID: <20010602023123.59E3524D1F@minya.sea.one-eyed-alien.net>
next in thread | raw e-mail | index | archive | help
>Number: 27826
>Category: kern
>Synopsis: [PATCH] correct minor bugs in an(4) ifconfig support
>Confidential: no
>Severity: serious
>Priority: high
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Fri Jun 01 19:30:00 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator: Brooks Davis
>Release: FreeBSD 5.0-CURRENT i386
>Organization:
>Environment:
System: FreeBSD minya.sea.one-eyed-alien.net 5.0-CURRENT FreeBSD 5.0-CURRENT #22: Wed May 30 14:16:46 PDT 2001 root@minya.sea.one-eyed-alien.net:/usr/obj/usr/src/sys/MINYA i386
>Description:
The attached patch corrects the remaining known bugs in the ifconfig
support for an(4). The credit for this patch goes to Doug Ambrisko
<ambrisko@ambrisko.com>. He did the work, I just made a few minor
changes and tested it. He requested that I submit it.
>How-To-Repeat:
Type ifconfig and look at WEP settings if any keys are set. They are
generally wrong due to bugs in ancontrol that I copied to the kernel
support.
>Fix:
Index: if_aironet_ieee.h
===================================================================
RCS file: /home/ncvs/src/sys/dev/an/if_aironet_ieee.h,v
retrieving revision 1.5
diff -u -r1.5 if_aironet_ieee.h
--- if_aironet_ieee.h 2001/05/26 09:26:58 1.5
+++ if_aironet_ieee.h 2001/06/01 23:24:42
@@ -528,7 +528,7 @@
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
Index: if_an.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/an/if_an.c,v
retrieving revision 1.17
diff -u -r1.17 if_an.c
--- if_an.c 2001/05/26 09:26:58 1.17
+++ if_an.c 2001/06/01 23:31:33
@@ -162,9 +162,14 @@
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;
+static char an_conf[256];
/*
* We probe for an Aironet 4500/4800 card by attempting to
* read the default SSID list. On reset, the first entry in
@@ -511,7 +516,7 @@
int status;
{
struct ifnet *ifp;
- int id;
+ int id, i;
/* TX DONE enable lan monitor DJA
an_enable_sniff();
@@ -529,12 +534,13 @@
} 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 +726,10 @@
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 <= 2 || ltv->an_type == 0)
return(EINVAL);
/* Tell the NIC to enter record read mode. */
@@ -741,20 +748,29 @@
* 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)) {
+ 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 = <v->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 +783,32 @@
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 = <v->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 +816,50 @@
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 *)<v->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 +911,11 @@
}
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 +937,11 @@
}
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);
@@ -1190,16 +1261,16 @@
len = 0;
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;
}
@@ -1219,6 +1290,25 @@
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)
+ break;
+
areq.an_type = AN_RID_WEP_PERM;
key->kindex = 0xffff;
if (an_read_record(sc,
Index: if_anreg.h
===================================================================
RCS file: /home/ncvs/src/sys/dev/an/if_anreg.h,v
retrieving revision 1.7
diff -u -r1.7 if_anreg.h
--- if_anreg.h 2001/05/26 09:26:58 1.7
+++ if_anreg.h 2001/06/01 23:24:42
@@ -532,7 +532,7 @@
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
>Release-Note:
>Audit-Trail:
>Unformatted:
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010602023123.59E3524D1F>
