wifi: move scanning/probe into wifi layer, avoid associating with wpa network until rsne is setup

This commit is contained in:
cinap_lenrek 2013-07-04 00:04:47 +02:00
parent 82ccf5b26a
commit 3fbf35112f
3 changed files with 102 additions and 102 deletions

View file

@ -1745,6 +1745,13 @@ rxon(Ether *edev, Wnode *bss)
}
flags = RFlagTSF | RFlagCTSToSelf | RFlag24Ghz | RFlagAuto;
if(ctlr->aid != 0)
setled(ctlr, 2, 0, 1); /* on when associated */
else if(memcmp(ctlr->bssid, edev->bcast, Eaddrlen) != 0)
setled(ctlr, 2, 10, 10); /* slow blink when connecting */
else
setled(ctlr, 2, 5, 5); /* fast blink when scanning */
if(ctlr->wifi->debug)
print("#l%d: rxon: bssid %E, aid %x, channel %d, filter %x, flags %x\n",
edev->ctlrno, ctlr->bssid, ctlr->aid, ctlr->channel, filter, flags);
@ -1846,7 +1853,6 @@ transmit(Wifi *wifi, Wnode *wn, Block *b)
return;
}
if(wn != nil)
if((wn->channel != ctlr->channel)
|| (!ctlr->prom && (wn->aid != ctlr->aid || memcmp(wn->bssid, ctlr->bssid, Eaddrlen) != 0)))
rxon(edev, wn);
@ -1988,62 +1994,9 @@ iwlpromiscuous(void *arg, int on)
qunlock(ctlr);
}
static void
iwlproc(void *arg)
{
Ether *edev;
Ctlr *ctlr;
Wifi *wifi;
Wnode *bss;
edev = arg;
ctlr = edev->ctlr;
wifi = ctlr->wifi;
for(;;){
/* hop channels for catching beacons */
setled(ctlr, 2, 5, 5);
while(wifi->bss == nil){
qlock(ctlr);
if(wifi->bss != nil){
qunlock(ctlr);
break;
}
ctlr->channel = 1 + ctlr->channel % 11;
ctlr->aid = 0;
rxon(edev, nil);
qunlock(ctlr);
wifiprobe(ctlr->wifi, ctlr->channel);
tsleep(&up->sleep, return0, 0, 1000);
}
/* wait for association */
setled(ctlr, 2, 10, 10);
while(wifichecklink(wifi) && (bss = wifi->bss) != nil){
if(bss->aid != 0)
break;
tsleep(&up->sleep, return0, 0, 1000);
}
if(wifi->bss == nil)
continue;
/* wait for disassociation */
edev->link = 1;
setled(ctlr, 2, 0, 1);
while(wifichecklink(wifi) && (bss = wifi->bss) != nil){
if(bss->aid == 0)
break;
tsleep(&up->sleep, return0, 0, 1000);
}
edev->link = 0;
}
}
static void
iwlattach(Ether *edev)
{
char name[32];
FWImage *fw;
Ctlr *ctlr;
char *err;
@ -2088,9 +2041,6 @@ iwlattach(Ether *edev)
setoptions(edev);
snprint(name, sizeof(name), "#l%diwl", edev->ctlrno);
kproc(name, iwlproc, edev);
ctlr->attached = 1;
}
qunlock(ctlr);

View file

@ -31,6 +31,7 @@ enum {
static char Sconn[] = "connecting";
static char Sauth[] = "authenticated";
static char Sneedauth[] = "need authentication";
static char Sunauth[] = "unauthenticated";
static char Sassoc[] = "associated";
@ -132,8 +133,8 @@ wifitx(Wifi *wifi, Wnode *wn, Block *b)
Wifipkt *w;
uint seq;
if(wn != nil)
wn->lastsend = MACHP(0)->ticks;
wn->lastsend = MACHP(0)->ticks;
seq = incref(&wifi->txseq);
seq <<= 4;
@ -143,7 +144,7 @@ wifitx(Wifi *wifi, Wnode *wn, Block *b)
w->seq[0] = seq;
w->seq[1] = seq>>8;
if((w->fc[0] & 0x0c) != 0x00 && wn != nil)
if((w->fc[0] & 0x0c) != 0x00)
b = wifiencrypt(wifi, wn, b);
if(b != nil)
@ -183,8 +184,8 @@ nodelookup(Wifi *wifi, uchar *bssid, int new)
return nn;
}
void
wifiprobe(Wifi *wifi, int channel)
static void
wifiprobe(Wifi *wifi, Wnode *wn)
{
Wifipkt *w;
Block *b;
@ -192,8 +193,11 @@ wifiprobe(Wifi *wifi, int channel)
int n;
n = strlen(wifi->essid);
if(n == 0)
if(n == 0){
/* no specific essid, just tell driver to tune channel */
(*wifi->transmit)(wifi, wn, nil);
return;
}
b = allocb(WIFIHDRSIZE + 512);
w = (Wifipkt*)b->wp;
@ -217,14 +221,12 @@ wifiprobe(Wifi *wifi, int channel)
*p++ = 0x8b;
*p++ = 0x96;
if(channel > 0){
*p++ = 0x03; /* ds parameter set */
*p++ = 1;
*p++ = channel;
}
*p++ = 0x03; /* ds parameter set */
*p++ = 1;
*p++ = wn->channel;
b->wp = p;
wifitx(wifi, nil, b);
wifitx(wifi, wn, b);
}
static void
@ -250,6 +252,9 @@ sendauth(Wifi *wifi, Wnode *bss)
*p++ = 0; /* status */
*p++ = 0;
b->wp = p;
bss->aid = 0;
wifitx(wifi, bss, b);
}
@ -408,7 +413,8 @@ wifideauth(Wifi *wifi, Wnode *wn)
wn->aid = 0;
if(wn == wifi->bss){
wifi->bss = nil;
/* notify driver about node aid association */
(*wifi->transmit)(wifi, wn, nil);
/* notify aux/wpa with a zero length write that we got deassociated from the ap */
ether = wifi->ether;
@ -478,10 +484,9 @@ wifiproc(void *arg)
continue;
b->rp += wifihdrlen(w);
recvbeacon(wifi, wn, b->rp, BLEN(b));
if(wifi->bss != nil)
continue;
if(((wn->status == nil || wn->status == Sunauth)
|| (wn->status == Sconn && TK2SEC(wn->lastseen - wn->lastsend) > 2))
if(wifi->bss == nil
&& TK2MS(MACHP(0)->ticks - wn->lastsend) > 1000
&& goodbss(wifi, wn)){
setstatus(wifi, wn, Sconn);
sendauth(wifi, wn);
@ -503,15 +508,21 @@ wifiproc(void *arg)
(*wifi->transmit)(wifi, wn, nil);
break;
case 0xb0: /* auth */
setstatus(wifi, wn, Sauth);
if(wifi->debug)
print("#l%d: got auth from %E\n", wifi->ether->ctlrno, wn->bssid);
if(wn->brsnelen > 0 && wn->rsnelen == 0)
setstatus(wifi, wn, Sneedauth);
else
setstatus(wifi, wn, Sauth);
if(wifi->bss == nil && goodbss(wifi, wn)){
wifi->bss = wn;
sendassoc(wifi, wn);
if(wn->status == Sauth)
sendassoc(wifi, wn);
}
break;
case 0xc0: /* deauth */
if(wifi->debug)
print("#l%d: got deauth\n", wifi->ether->ctlrno);
print("#l%d: got deauth from %E\n", wifi->ether->ctlrno, wn->bssid);
wifideauth(wifi, wn);
break;
}
@ -579,6 +590,56 @@ wifoproc(void *arg)
pexit("ether out queue closed", 0);
}
static void
wifsproc(void *arg)
{
Ether *ether;
Wifi *wifi;
Wnode wnscan;
Wnode *wn;
ulong now, tmout;
wifi = arg;
ether = wifi->ether;
wn = &wnscan;
memset(wn, 0, sizeof(*wn));
memmove(wn->bssid, ether->bcast, Eaddrlen);
while(waserror())
;
Scan:
/* scan for access point */
while(wifi->bss == nil){
ether->link = 0;
wnscan.channel = 1 + wnscan.channel % 11;
wifiprobe(wifi, &wnscan);
tsleep(&up->sleep, return0, 0, 1000);
}
/* maintain access point */
tmout = 0;
while((wn = wifi->bss) != nil){
ether->link = (wn->status == Sassoc) || (wn->status == Sblocked);
now = MACHP(0)->ticks;
if(wn->status != Sneedauth && TK2SEC(now - wn->lastseen) > 60 || goodbss(wifi, wn) == 0){
wifideauth(wifi, wn);
wifi->bss = nil;
break;
}
if(TK2MS(now - wn->lastsend) > 1000){
if(wn->status == Sauth && (++tmout & 7) == 0)
wifideauth(wifi, wn); /* stuck in auth, start over */
if(wn->status == Sconn || wn->status == Sunauth)
sendauth(wifi, wn);
if(wn->status == Sauth)
sendassoc(wifi, wn);
}
tsleep(&up->sleep, return0, 0, 500);
}
goto Scan;
}
Wifi*
wifiattach(Ether *ether, void (*transmit)(Wifi*, Wnode*, Block*))
{
@ -603,28 +664,12 @@ wifiattach(Ether *ether, void (*transmit)(Wifi*, Wnode*, Block*))
kproc(name, wifiproc, wifi);
snprint(name, sizeof(name), "#l%dwifo", ether->ctlrno);
kproc(name, wifoproc, wifi);
snprint(name, sizeof(name), "#l%dwifs", ether->ctlrno);
kproc(name, wifsproc, wifi);
return wifi;
}
int
wifichecklink(Wifi *wifi)
{
Wnode *wn;
wn = wifi->bss;
if(wn == nil)
return 0;
if((TK2SEC(MACHP(0)->ticks - wn->lastseen) > 60)
|| (TK2SEC(wn->lastseen - wn->lastsend) > 5) && (wn->status == Sauth || wn->status == Sblocked)){
if(wifi->debug)
print("#l%d: link broken\n", wifi->ether->ctlrno);
wifideauth(wifi, wn);
return 0;
}
return 1;
}
static int
hextob(char *s, char **sp, uchar *b, int n)
{
@ -760,8 +805,11 @@ wifictl(Wifi *wifi, void *buf, long n)
wifi->essid[0] = 0;
Findbss:
wn = wifi->bss;
if(wn != nil && goodbss(wifi, wn))
break;
if(wn != nil){
if(goodbss(wifi, wn))
break;
wifideauth(wifi, wn);
}
wifi->bss = nil;
if(wifi->essid[0] == 0 && memcmp(wifi->bssid, wifi->ether->bcast, Eaddrlen) == 0)
break;
@ -791,8 +839,13 @@ wifictl(Wifi *wifi, void *buf, long n)
wn->rsnelen = 0;
else
wn->rsnelen = hextob(cb->f[1], nil, wn->rsne, sizeof(wn->rsne));
setstatus(wifi, wn, Sauth);
sendassoc(wifi, wn);
if(wn->aid == 0){
setstatus(wifi, wn, Sconn);
sendauth(wifi, wn);
} else {
setstatus(wifi, wn, Sauth);
sendassoc(wifi, wn);
}
break;
case CMrxkey0: case CMrxkey1: case CMrxkey2: case CMrxkey3: case CMrxkey4:
case CMtxkey0:

View file

@ -81,6 +81,3 @@ void wifiiq(Wifi*, Block*);
long wifistat(Wifi*, void*, long, ulong);
long wifictl(Wifi*, void*, long);
int wifichecklink(Wifi*);
void wifiprobe(Wifi*, int);