git: 9front

Download patch

ref: 8678b005454a1743c78ab06ea1bb8f8372f84548
parent: ea6e7f4d473a527b7823d131c1e9143e3cd20e5d
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Mon Jun 24 13:24:50 EDT 2013

wifi: add watchdog to drop bss if stuck in ap association or get deauthenticated by the ap

--- a/sys/src/9/pc/wifi.c
+++ b/sys/src/9/pc/wifi.c
@@ -285,7 +285,6 @@
 	default:
 		wn->aid = 0;
 		setstatus(wifi, Sunassoc);
-		return;
 	}
 }
 
@@ -346,21 +345,26 @@
 	}
 }
 
-/* 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 @@
 			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 @@
 		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 @@
 			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 @@
 			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);
--- a/sys/src/9/pc/wifi.h
+++ b/sys/src/9/pc/wifi.h
@@ -49,6 +49,7 @@
 
 	Queue	*iq;
 	char	*status;
+	ulong	watchdog;
 	Ref	txseq;
 	void	(*transmit)(Wifi*, Wnode*, Block*);
 
--