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>