Skip site navigation (1)Skip section navigation (2)
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 = &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 +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 = &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 +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 *)&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 +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>