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.
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:
.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

View file

@ -1953,7 +1953,9 @@ setoptions(Ether *edev)
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()){

View file

@ -32,7 +32,7 @@ enum {
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 @@ wifiproc(void *arg)
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 @@ wifiattach(Ether *ether, void (*transmit)(Wifi*, Wnode*, Block*))
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 @@ enum {
CMdebug,
CMessid,
CMauth,
CMbssid,
CMrxkey0,
CMrxkey1,
CMrxkey2,
@ -580,6 +591,7 @@ static Cmdtab wifictlmsg[] =
CMdebug, "debug", 0,
CMessid, "essid", 0,
CMauth, "auth", 0,
CMbssid, "bssid", 0,
CMrxkey0, "rxkey0", 0, /* group keys */
CMrxkey1, "rxkey1", 0,
@ -595,6 +607,7 @@ static Cmdtab wifictlmsg[] =
long
wifictl(Wifi *wifi, void *buf, long n)
{
uchar addr[Eaddrlen];
Cmdbuf *cb;
Cmdtab *ct;
Wnode *wn;
@ -607,20 +620,19 @@ wifictl(Wifi *wifi, void *buf, long n)
}
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--;
wn = nodelookup(wifi, addr, 0);
}
}
if(wn == nil)
if(wn == nil && ct->index != CMbssid)
error("missing node");
}
switch(ct->index){
@ -647,6 +659,17 @@ wifictl(Wifi *wifi, void *buf, long n)
}
}
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 @@ wifistat(Wifi *wifi, void *buf, long n, ulong off)
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 @@ wifistat(Wifi *wifi, void *buf, long n, ulong off)
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;

View file

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