summaryrefslogtreecommitdiff
path: root/sys/src
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@gmx.de>2013-06-24 17:24:50 +0200
committercinap_lenrek <cinap_lenrek@gmx.de>2013-06-24 17:24:50 +0200
commit5165864dbbdb90e41ef25c0576f5b06c990098d8 (patch)
tree3c80f66b41e6544dd17a97db3fbf6679f408166b /sys/src
parent196b39126c47d07eff30d27207fd5782354c90d2 (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.c43
-rw-r--r--sys/src/9/pc/wifi.h1
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*);