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; 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) if(ctlr->wifi->debug)
print("#l%d: rxon: bssid %E, aid %x, channel %d, filter %x, flags %x\n", 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); edev->ctlrno, ctlr->bssid, ctlr->aid, ctlr->channel, filter, flags);
@ -1846,7 +1853,6 @@ transmit(Wifi *wifi, Wnode *wn, Block *b)
return; return;
} }
if(wn != nil)
if((wn->channel != ctlr->channel) if((wn->channel != ctlr->channel)
|| (!ctlr->prom && (wn->aid != ctlr->aid || memcmp(wn->bssid, ctlr->bssid, Eaddrlen) != 0))) || (!ctlr->prom && (wn->aid != ctlr->aid || memcmp(wn->bssid, ctlr->bssid, Eaddrlen) != 0)))
rxon(edev, wn); rxon(edev, wn);
@ -1988,62 +1994,9 @@ iwlpromiscuous(void *arg, int on)
qunlock(ctlr); 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 static void
iwlattach(Ether *edev) iwlattach(Ether *edev)
{ {
char name[32];
FWImage *fw; FWImage *fw;
Ctlr *ctlr; Ctlr *ctlr;
char *err; char *err;
@ -2088,9 +2041,6 @@ iwlattach(Ether *edev)
setoptions(edev); setoptions(edev);
snprint(name, sizeof(name), "#l%diwl", edev->ctlrno);
kproc(name, iwlproc, edev);
ctlr->attached = 1; ctlr->attached = 1;
} }
qunlock(ctlr); qunlock(ctlr);

View file

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

View file

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