diff options
author | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-06-24 17:24:50 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-06-24 17:24:50 +0200 |
commit | 5165864dbbdb90e41ef25c0576f5b06c990098d8 (patch) | |
tree | 3c80f66b41e6544dd17a97db3fbf6679f408166b /sys/src | |
parent | 196b39126c47d07eff30d27207fd5782354c90d2 (diff) |
wifi: add watchdog to drop bss if stuck in ap association or get deauthenticated by the ap
Diffstat (limited to 'sys/src')
-rw-r--r-- | sys/src/9/pc/wifi.c | 43 | ||||
-rw-r--r-- | sys/src/9/pc/wifi.h | 1 |
2 files changed, 34 insertions, 10 deletions
diff --git a/sys/src/9/pc/wifi.c b/sys/src/9/pc/wifi.c index 4ad8db90f..5f473470c 100644 --- a/sys/src/9/pc/wifi.c +++ b/sys/src/9/pc/wifi.c @@ -285,7 +285,6 @@ recvassoc(Wifi *wifi, Wnode *wn, uchar *d, int len) default: wn->aid = 0; setstatus(wifi, Sunassoc); - return; } } @@ -346,21 +345,26 @@ recvbeacon(Wifi *, Wnode *wn, uchar *d, int len) } } -/* notify aux/wpa with a zero length write that we got deassociated from the ap */ static void -wifideassoc(Wifi *wifi) +wifideassoc(Wifi *wifi, Wnode *wn) { Ether *ether; Netfile *f; int i; + /* deassociate node, clear keys */ + if(wn != nil){ + memset(wn->rxkey, 0, sizeof(wn->rxkey)); + memset(wn->txkey, 0, sizeof(wn->txkey)); + wn->aid = 0; + } + + /* notify aux/wpa with a zero length write that we got deassociated from the ap */ ether = wifi->ether; for(i=0; i<ether->nfile; i++){ f = ether->f[i]; if(f == nil || f->in == nil || f->inuse == 0 || f->type != 0x888e) continue; - if(wifi->debug) - print("#l%d: wifideassoc: %#p\n", ether->ctlrno, f); qwrite(f->in, 0, 0); } } @@ -419,10 +423,28 @@ wifiproc(void *arg) b->rp += wifihdrlen(w); recvbeacon(wifi, wn, b->rp, BLEN(b)); if(wifi->bss == nil && goodbss(wifi, wn)){ + wifi->watchdog = 0; wifi->bss = wn; setstatus(wifi, Sconn); sendauth(wifi, wn); } + if(wn == wifi->bss){ + ulong wdog; + + /* on each beacon from the bss, check if we'r stuck */ + wdog = ++wifi->watchdog; + if(wifi->status == Sconn && (wdog & 0x1f) == 0){ + setstatus(wifi, Sunauth); + wifi->bss = nil; + } else if(wifi->status == Sauth && (wdog & 0x1f) == 0){ + setstatus(wifi, Sunauth); + wifi->bss = nil; + } else if(wifi->status == Sblocked && (wdog & 0x3f) == 0){ + setstatus(wifi, Sunauth); + wifideassoc(wifi, wn); + wifi->bss = nil; + } + } continue; } if(memcmp(w->a1, wifi->ether->ea, Eaddrlen)) @@ -432,6 +454,8 @@ wifiproc(void *arg) if(wn != wifi->bss) continue; switch(w->fc[0] & 0xf0){ + default: + continue; case 0x10: /* assoc response */ case 0x30: /* reassoc response */ b->rp += wifihdrlen(w); @@ -445,13 +469,11 @@ wifiproc(void *arg) break; case 0xc0: /* deauth */ setstatus(wifi, Sunauth); - memset(wn->rxkey, 0, sizeof(wn->rxkey)); - memset(wn->txkey, 0, sizeof(wn->txkey)); - wn->aid = 0; - wifideassoc(wifi); - sendauth(wifi, wn); + wifideassoc(wifi, wn); + wifi->bss = nil; break; } + wifi->watchdog = 0; } pexit("wifi in queue closed", 0); } @@ -683,6 +705,7 @@ wifictl(Wifi *wifi, void *buf, long n) break; for(wn = wifi->node; wn != &wifi->node[nelem(wifi->node)]; wn++) if(goodbss(wifi, wn)){ + wifi->watchdog = 0; wifi->bss = wn; setstatus(wifi, Sconn); sendauth(wifi, wn); diff --git a/sys/src/9/pc/wifi.h b/sys/src/9/pc/wifi.h index 8f67324eb..047f80a92 100644 --- a/sys/src/9/pc/wifi.h +++ b/sys/src/9/pc/wifi.h @@ -49,6 +49,7 @@ struct Wifi Queue *iq; char *status; + ulong watchdog; Ref txseq; void (*transmit)(Wifi*, Wnode*, Block*); |