git: 9front

Download patch

ref: 424a68630b6decd4906eb98fb9649b3f37045e44
parent: 378eefc2bd358d0c6bc014a3069b6061dc802b3b
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Wed Jul 3 20:04:47 EDT 2013

wifi: move scanning/probe into wifi layer, avoid associating with wpa network until rsne is setup

--- a/sys/src/9/pc/etheriwl.c
+++ b/sys/src/9/pc/etheriwl.c
@@ -1745,6 +1745,13 @@
 	}
 	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 @@
 		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);
@@ -1989,61 +1995,8 @@
 }
 
 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;
@@ -2087,9 +2040,6 @@
 		ctlr->aid = 0;
 
 		setoptions(edev);
-
-		snprint(name, sizeof(name), "#l%diwl", edev->ctlrno);
-		kproc(name, iwlproc, edev);
 
 		ctlr->attached = 1;
 	}
--- a/sys/src/9/pc/wifi.c
+++ b/sys/src/9/pc/wifi.c
@@ -31,6 +31,7 @@
 
 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 @@
 	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 @@
 	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 @@
 	return nn;
 }
 
-void
-wifiprobe(Wifi *wifi, int channel)
+static void
+wifiprobe(Wifi *wifi, Wnode *wn)
 {
 	Wifipkt *w;
 	Block *b;
@@ -192,8 +193,11 @@
 	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 @@
 	*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 @@
 	*p++ = 0;	/* status */
 	*p++ = 0;
 	b->wp = p;
+
+	bss->aid = 0;
+
 	wifitx(wifi, bss, b);
 }
 
@@ -408,7 +413,8 @@
 	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 @@
 				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 @@
 				(*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 @@
 	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 @@
 	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 @@
 			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 @@
 			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:
--- a/sys/src/9/pc/wifi.h
+++ b/sys/src/9/pc/wifi.h
@@ -81,6 +81,3 @@
 
 long wifistat(Wifi*, void*, long, ulong);
 long wifictl(Wifi*, void*, long);
-
-int wifichecklink(Wifi*);
-void wifiprobe(Wifi*, int);
--