diff --git a/sys/src/9/pc/etheriwl.c b/sys/src/9/pc/etheriwl.c index e61d725d7..9bf90ef07 100644 --- a/sys/src/9/pc/etheriwl.c +++ b/sys/src/9/pc/etheriwl.c @@ -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); diff --git a/sys/src/9/pc/wifi.c b/sys/src/9/pc/wifi.c index 345cf458c..0e6ae0c3a 100644 --- a/sys/src/9/pc/wifi.c +++ b/sys/src/9/pc/wifi.c @@ -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: diff --git a/sys/src/9/pc/wifi.h b/sys/src/9/pc/wifi.h index 0989ae45b..d338f1f04 100644 --- a/sys/src/9/pc/wifi.h +++ b/sys/src/9/pc/wifi.h @@ -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);