wifi: move scanning/probe into wifi layer, avoid associating with wpa network until rsne is setup
This commit is contained in:
parent
82ccf5b26a
commit
3fbf35112f
|
@ -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);
|
||||||
|
|
|
@ -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++ = channel;
|
*p++ = wn->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 */
|
||||||
|
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);
|
setstatus(wifi, wn, Sauth);
|
||||||
if(wifi->bss == nil && goodbss(wifi, wn)){
|
if(wifi->bss == nil && goodbss(wifi, wn)){
|
||||||
wifi->bss = wn;
|
wifi->bss = wn;
|
||||||
|
if(wn->status == Sauth)
|
||||||
sendassoc(wifi, wn);
|
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){
|
||||||
|
if(goodbss(wifi, wn))
|
||||||
break;
|
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));
|
||||||
|
if(wn->aid == 0){
|
||||||
|
setstatus(wifi, wn, Sconn);
|
||||||
|
sendauth(wifi, wn);
|
||||||
|
} else {
|
||||||
setstatus(wifi, wn, Sauth);
|
setstatus(wifi, wn, Sauth);
|
||||||
sendassoc(wifi, wn);
|
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:
|
||||||
|
|
|
@ -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);
|
|
||||||
|
|
Loading…
Reference in a new issue