ref: 424a68630b6decd4906eb98fb9649b3f37045e44
parent: 378eefc2bd358d0c6bc014a3069b6061dc802b3b
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Wed Jul 3 20:04:47 EDT 2013
wifi: move scanning/probe into wifi layer, avoid associating with wpa network until rsne is setup
--- a/sys/src/9/pc/etheriwl.c
+++ b/sys/src/9/pc/etheriwl.c
@@ -1745,6 +1745,13 @@
}
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 @@
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);
@@ -1989,61 +1995,8 @@
}
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;
@@ -2087,9 +2040,6 @@
ctlr->aid = 0;
setoptions(edev);
-
- snprint(name, sizeof(name), "#l%diwl", edev->ctlrno);
- kproc(name, iwlproc, edev);
ctlr->attached = 1;
}
--- a/sys/src/9/pc/wifi.c
+++ b/sys/src/9/pc/wifi.c
@@ -31,6 +31,7 @@
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 @@
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 @@
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 @@
return nn;
}
-void
-wifiprobe(Wifi *wifi, int channel)
+static void
+wifiprobe(Wifi *wifi, Wnode *wn)
{Wifipkt *w;
Block *b;
@@ -192,8 +193,11 @@
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 @@
*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 @@
*p++ = 0; /* status */
*p++ = 0;
b->wp = p;
+
+ bss->aid = 0;
+
wifitx(wifi, bss, b);
}
@@ -408,7 +413,8 @@
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 @@
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 @@
(*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 @@
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 @@
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 @@
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 @@
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:
--- a/sys/src/9/pc/wifi.h
+++ b/sys/src/9/pc/wifi.h
@@ -81,6 +81,3 @@
long wifistat(Wifi*, void*, long, ulong);
long wifictl(Wifi*, void*, long);
-
-int wifichecklink(Wifi*);
-void wifiprobe(Wifi*, int);
--
⑨