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

This commit is contained in:
cinap_lenrek 2013-06-23 23:54:15 +02:00
parent 43323512f0
commit a8cc5cff0e
4 changed files with 53 additions and 11 deletions

View file

@ -392,18 +392,28 @@ or
.B /boot. .B /boot.
To select the access point, the To select the access point, the
.B essid= .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: like:
.EX .EX
echo essid left-armpit >/net/ether1/clone echo essid left-armpit >/net/ether1/clone
.EE .EE
If both
.B essid=
and
.B bssid=
are spcified, both must match.
Scan results appear in the Scan results appear in the
.B ifstats .B ifstats
file and can be read out like: file and can be read out like:
.EX .EX
cat /net/ether1/ifstats cat /net/ether1/ifstats
.EE .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 .SS DISKS, TAPES
(S)ATA controllers are autodetected. (S)ATA controllers are autodetected.
.SS \fL*nodma=\fP .SS \fL*nodma=\fP

View file

@ -1953,7 +1953,9 @@ setoptions(Ether *edev)
p = strchr(buf, '='); p = strchr(buf, '=');
if(p != nil) if(p != nil)
*p = 0; *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) if(p != nil)
*p = ' '; *p = ' ';
if(!waserror()){ if(!waserror()){

View file

@ -32,7 +32,7 @@ enum {
static char Snone[] = "new"; static char Snone[] = "new";
static char Sconn[] = "connecting"; static char Sconn[] = "connecting";
static char Sauth[] = "authenticated"; static char Sauth[] = "authenticated";
static char Sunauth[] = "unauthentictaed"; static char Sunauth[] = "unauthenticated";
static char Sassoc[] = "associated"; static char Sassoc[] = "associated";
static char Sunassoc[] = "unassociated"; static char Sunassoc[] = "unassociated";
static char Sblocked[] = "blocked"; /* no keys negotiated. only pass EAPOL frames */ static char Sblocked[] = "blocked"; /* no keys negotiated. only pass EAPOL frames */
@ -385,7 +385,14 @@ wifiproc(void *arg)
continue; continue;
b->rp += wifihdrlen(w); b->rp += wifihdrlen(w);
recvbeacon(wifi, wn, b->rp, BLEN(b)); 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; wifi->bss = wn;
setstatus(wifi, Sconn); setstatus(wifi, Sconn);
sendauth(wifi, wn); sendauth(wifi, wn);
@ -498,6 +505,9 @@ wifiattach(Ether *ether, void (*transmit)(Wifi*, Wnode*, Block*))
wifi->transmit = transmit; wifi->transmit = transmit;
wifi->status = Snone; wifi->status = Snone;
wifi->essid[0] = 0;
memmove(wifi->bssid, ether->bcast, Eaddrlen);
snprint(name, sizeof(name), "#l%dwifi", ether->ctlrno); snprint(name, sizeof(name), "#l%dwifi", ether->ctlrno);
kproc(name, wifiproc, wifi); kproc(name, wifiproc, wifi);
snprint(name, sizeof(name), "#l%dwifo", ether->ctlrno); snprint(name, sizeof(name), "#l%dwifo", ether->ctlrno);
@ -567,6 +577,7 @@ enum {
CMdebug, CMdebug,
CMessid, CMessid,
CMauth, CMauth,
CMbssid,
CMrxkey0, CMrxkey0,
CMrxkey1, CMrxkey1,
CMrxkey2, CMrxkey2,
@ -580,6 +591,7 @@ static Cmdtab wifictlmsg[] =
CMdebug, "debug", 0, CMdebug, "debug", 0,
CMessid, "essid", 0, CMessid, "essid", 0,
CMauth, "auth", 0, CMauth, "auth", 0,
CMbssid, "bssid", 0,
CMrxkey0, "rxkey0", 0, /* group keys */ CMrxkey0, "rxkey0", 0, /* group keys */
CMrxkey1, "rxkey1", 0, CMrxkey1, "rxkey1", 0,
@ -595,6 +607,7 @@ static Cmdtab wifictlmsg[] =
long long
wifictl(Wifi *wifi, void *buf, long n) wifictl(Wifi *wifi, void *buf, long n)
{ {
uchar addr[Eaddrlen];
Cmdbuf *cb; Cmdbuf *cb;
Cmdtab *ct; Cmdtab *ct;
Wnode *wn; Wnode *wn;
@ -607,20 +620,19 @@ wifictl(Wifi *wifi, void *buf, long n)
} }
if(wifi->debug) if(wifi->debug)
print("#l%d: wifictl: %.*s\n", wifi->ether->ctlrno, (int)n, buf); print("#l%d: wifictl: %.*s\n", wifi->ether->ctlrno, (int)n, buf);
memmove(addr, wifi->ether->bcast, Eaddrlen);
wn = wifi->bss; wn = wifi->bss;
cb = parsecmd(buf, n); cb = parsecmd(buf, n);
ct = lookupcmd(cb, wifictlmsg, nelem(wifictlmsg)); ct = lookupcmd(cb, wifictlmsg, nelem(wifictlmsg));
if(ct->index >= CMauth){ if(ct->index >= CMauth){
if(ct->index >= CMrxkey0 && cb->nf > 1){ if(cb->nf > 1 && (ct->index == CMbssid || ct->index >= CMrxkey0)){
uchar addr[Eaddrlen];
if(parseether(addr, cb->f[1]) == 0){ if(parseether(addr, cb->f[1]) == 0){
cb->f++; cb->f++;
cb->nf--; cb->nf--;
wn = nodelookup(wifi, addr, 0); wn = nodelookup(wifi, addr, 0);
} }
} }
if(wn == nil) if(wn == nil && ct->index != CMbssid)
error("missing node"); error("missing node");
} }
switch(ct->index){ switch(ct->index){
@ -647,6 +659,17 @@ wifictl(Wifi *wifi, void *buf, long n)
} }
} }
break; 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: case CMauth:
setstatus(wifi, Sauth); setstatus(wifi, Sauth);
memset(wn->rxkey, 0, sizeof(wn->rxkey)); memset(wn->rxkey, 0, sizeof(wn->rxkey));
@ -687,11 +710,12 @@ wifistat(Wifi *wifi, void *buf, long n, ulong off)
e = s + 4096; e = s + 4096;
p = seprint(p, e, "status: %s\n", wifi->status); p = seprint(p, e, "status: %s\n", wifi->status);
p = seprint(p, e, "essid: %s\n", wifi->essid);
wn = wifi->bss; wn = wifi->bss;
if(wn != nil){ 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, "bssid: %E\n", wn->bssid);
p = seprint(p, e, "channel: %.2d\n", wn->channel);
/* only print key ciphers and key length */ /* only print key ciphers and key length */
for(i = 0; i<nelem(wn->rxkey); i++) for(i = 0; i<nelem(wn->rxkey); i++)
@ -707,7 +731,9 @@ wifistat(Wifi *wifi, void *buf, long n, ulong off)
p = seprint(p, e, "%.2X", wn->brsne[i]); p = seprint(p, e, "%.2X", wn->brsne[i]);
p = seprint(p, e, "\n"); 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; now = MACHP(0)->ticks;

View file

@ -52,7 +52,11 @@ struct Wifi
Ref txseq; Ref txseq;
void (*transmit)(Wifi*, Wnode*, Block*); void (*transmit)(Wifi*, Wnode*, Block*);
/* for searching */
uchar bssid[Eaddrlen];
char essid[Essidlen+2]; char essid[Essidlen+2];
/* effective base station */
Wnode *bss; Wnode *bss;
Wnode node[32]; Wnode node[32];