From 5165864dbbdb90e41ef25c0576f5b06c990098d8 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Mon, 24 Jun 2013 17:24:50 +0200 Subject: [PATCH] wifi: add watchdog to drop bss if stuck in ap association or get deauthenticated by the ap --- sys/src/9/pc/wifi.c | 43 +++++++++++++++++++++++++++++++++---------- 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; infile; 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*);