git: 9front

Download patch

ref: 17357cd71f36d19b3cf2f3f9656a1505ed318efb
parent: 4ccbd5042434734c09f171e47ca0b78682dc2c36
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Sun Jun 23 19:54:15 EDT 2013

wifi: allow selecting specific access point with bssid= parameter and wifictl command

--- a/sys/man/8/plan9.ini
+++ b/sys/man/8/plan9.ini
@@ -392,11 +392,18 @@
 .B /boot.
 To select the access point, the
 .B essid=
-parameter can be specified at boot or set during runtime
+and
+.B bssid=
+parameters can be specified at boot or set during runtime
 like:
 .EX
 	echo essid left-armpit >/net/ether1/clone
 .EE
+If both
+.B essid=
+and
+.B bssid=
+are spcified, both must match.
 Scan results appear in the
 .B ifstats
 file and can be read out like:
@@ -403,7 +410,10 @@
 .EX
 	cat /net/ether1/ifstats
 .EE
-Ad-hoc mode or encryption is currently not supported.
+Ad-hoc mode or WEP encryption is currently not supported.
+To enable WPA/WPA2 encryption, see
+.IR wpa (8)
+for details.
 .SS DISKS, TAPES
 (S)ATA controllers are autodetected.
 .SS \fL*nodma=\fP
--- a/sys/src/9/pc/etheriwl.c
+++ b/sys/src/9/pc/etheriwl.c
@@ -1953,7 +1953,9 @@
 		p = strchr(buf, '=');
 		if(p != nil)
 			*p = 0;
-		if(strcmp(buf, "debug") == 0 || strcmp(buf, "essid") == 0){
+		if(strcmp(buf, "debug") == 0
+		|| strcmp(buf, "essid") == 0
+		|| strcmp(buf, "bssid") == 0){
 			if(p != nil)
 				*p = ' ';
 			if(!waserror()){
--- a/sys/src/9/pc/wifi.c
+++ b/sys/src/9/pc/wifi.c
@@ -32,7 +32,7 @@
 static char Snone[] = "new";
 static char Sconn[] = "connecting";
 static char Sauth[] = "authenticated";
-static char Sunauth[] = "unauthentictaed";
+static char Sunauth[] = "unauthenticated";
 static char Sassoc[] = "associated";
 static char Sunassoc[] = "unassociated";
 static char Sblocked[] = "blocked";	/* no keys negotiated. only pass EAPOL frames */
@@ -385,7 +385,14 @@
 				continue;
 			b->rp += wifihdrlen(w);
 			recvbeacon(wifi, wn, b->rp, BLEN(b));
-			if(wifi->bss == nil && wifi->essid[0] != 0 && strcmp(wifi->essid, wn->ssid) == 0){
+			if(wifi->bss == nil){
+				if(memcmp(wifi->bssid, wifi->ether->bcast, Eaddrlen) != 0){
+					if(memcmp(wifi->bssid, wn->bssid, Eaddrlen) != 0)
+						continue;	/* bssid doesnt match */
+				} else if(wifi->essid[0] == 0)
+					continue;	/* both bssid and essid unspecified */
+				if(wifi->essid[0] != 0 && strcmp(wifi->essid, wn->ssid) != 0)
+					continue;	/* essid doesnt match */
 				wifi->bss = wn;
 				setstatus(wifi, Sconn);
 				sendauth(wifi, wn);
@@ -498,6 +505,9 @@
 	wifi->transmit = transmit;
 	wifi->status = Snone;
 
+	wifi->essid[0] = 0;
+	memmove(wifi->bssid, ether->bcast, Eaddrlen);
+
 	snprint(name, sizeof(name), "#l%dwifi", ether->ctlrno);
 	kproc(name, wifiproc, wifi);
 	snprint(name, sizeof(name), "#l%dwifo", ether->ctlrno);
@@ -567,6 +577,7 @@
 	CMdebug,
 	CMessid,
 	CMauth,
+	CMbssid,
 	CMrxkey0,
 	CMrxkey1,
 	CMrxkey2,
@@ -580,6 +591,7 @@
 	CMdebug,	"debug",	0,
 	CMessid,	"essid",	0,
 	CMauth,		"auth",		0,
+	CMbssid,	"bssid",	0,
 
 	CMrxkey0,	"rxkey0",	0,	/* group keys */
 	CMrxkey1,	"rxkey1",	0,
@@ -595,6 +607,7 @@
 long
 wifictl(Wifi *wifi, void *buf, long n)
 {
+	uchar addr[Eaddrlen];
 	Cmdbuf *cb;
 	Cmdtab *ct;
 	Wnode *wn;
@@ -607,13 +620,12 @@
 	}
 	if(wifi->debug)
 		print("#l%d: wifictl: %.*s\n", wifi->ether->ctlrno, (int)n, buf);
+	memmove(addr, wifi->ether->bcast, Eaddrlen);
 	wn = wifi->bss;
 	cb = parsecmd(buf, n);
 	ct = lookupcmd(cb, wifictlmsg, nelem(wifictlmsg));
 	if(ct->index >= CMauth){
-		if(ct->index >= CMrxkey0 && cb->nf > 1){
-			uchar addr[Eaddrlen];
-
+		if(cb->nf > 1 && (ct->index == CMbssid || ct->index >= CMrxkey0)){
 			if(parseether(addr, cb->f[1]) == 0){
 				cb->f++;
 				cb->nf--;
@@ -620,7 +632,7 @@
 				wn = nodelookup(wifi, addr, 0);
 			}
 		}
-		if(wn == nil)
+		if(wn == nil && ct->index != CMbssid)
 			error("missing node");
 	}
 	switch(ct->index){
@@ -647,6 +659,17 @@
 				}
 		}
 		break;
+	case CMbssid:
+		memmove(wifi->bssid, addr, Eaddrlen);
+		if(wn == nil){
+			wifi->bss = nil;
+			setstatus(wifi, Snone);
+		} else {
+			wifi->bss = wn;
+			setstatus(wifi, Sconn);
+			sendauth(wifi, wn);
+		}
+		break;
 	case CMauth:
 		setstatus(wifi, Sauth);
 		memset(wn->rxkey, 0, sizeof(wn->rxkey));
@@ -687,11 +710,12 @@
 	e = s + 4096;
 
 	p = seprint(p, e, "status: %s\n", wifi->status);
-	p = seprint(p, e, "essid: %s\n", wifi->essid);
 
 	wn = wifi->bss;
 	if(wn != nil){
+		p = seprint(p, e, "essid: %s\n", wn->ssid);
 		p = seprint(p, e, "bssid: %E\n", wn->bssid);
+		p = seprint(p, e, "channel: %.2d\n", wn->channel);
 
 		/* only print key ciphers and key length */
 		for(i = 0; i<nelem(wn->rxkey); i++)
@@ -707,7 +731,9 @@
 				p = seprint(p, e, "%.2X", wn->brsne[i]);
 			p = seprint(p, e, "\n");
 		}
-		p = seprint(p, e, "channel: %.2d\n", wn->channel);
+	} else {
+		p = seprint(p, e, "essid: %s\n", wifi->essid);
+		p = seprint(p, e, "bssid: %E\n", wifi->bssid);
 	}
 
 	now = MACHP(0)->ticks;
--- a/sys/src/9/pc/wifi.h
+++ b/sys/src/9/pc/wifi.h
@@ -52,7 +52,11 @@
 	Ref	txseq;
 	void	(*transmit)(Wifi*, Wnode*, Block*);
 
+	/* for searching */
+	uchar	bssid[Eaddrlen];
 	char	essid[Essidlen+2];
+
+	/* effective base station */
 	Wnode	*bss;
 
 	Wnode	node[32];
--