etheriwl: automatic channel scanning, transmission handling, promisc mode

the channel= plan9.ini parameter isnt needed anymore as we now
hop the channels to scan for beacons. the status is also indicated
with the link led :-)

handle all these flags on packet transmission like RTS for big
packets and sending data packets to the AP instead of broadcasting
everything.

properly setup bss hardware node table and filtering. now promisc
mode is only used when requested.

handle deauth message from ap.

increase node table to 32 entries.
This commit is contained in:
cinap_lenrek 2013-02-11 00:09:41 +01:00
parent c2f5d36d7f
commit ffb3ded366
4 changed files with 284 additions and 63 deletions

View file

@ -222,6 +222,28 @@ enum {
SchedTransTblOff5000 = 0x7e0, SchedTransTblOff5000 = 0x7e0,
}; };
enum {
FilterPromisc = 1<<0,
FilterCtl = 1<<1,
FilterMulticast = 1<<2,
FilterNoDecrypt = 1<<3,
FilterBSS = 1<<5,
FilterBeacon = 1<<6,
};
enum {
RFlag24Ghz = 1<<0,
RFlagCCK = 1<<1,
RFlagAuto = 1<<2,
RFlagShSlot = 1<<4,
RFlagShPreamble = 1<<5,
RFlagNoDiversity = 1<<7,
RFlagAntennaA = 1<<8,
RFlagAntennaB = 1<<9,
RFlagTSF = 1<<15,
RFlagCTSToSelf = 1<<30,
};
typedef struct FWInfo FWInfo; typedef struct FWInfo FWInfo;
typedef struct FWImage FWImage; typedef struct FWImage FWImage;
typedef struct FWSect FWSect; typedef struct FWSect FWSect;
@ -303,7 +325,14 @@ struct Ctlr {
u32int *nic; u32int *nic;
uchar *kwpage; uchar *kwpage;
/* assigned node ids in hardware node table or -1 if unassigned */
int bcastnodeid;
int bssnodeid;
/* current receiver settings */
int channel; int channel;
int prom;
int aid;
RXQ rx; RXQ rx;
TXQ tx[20]; TXQ tx[20];
@ -1019,12 +1048,11 @@ qcmd(Ctlr *ctlr, uint qid, uint code, uchar *data, int size, Block *block)
q = &ctlr->tx[qid]; q = &ctlr->tx[qid];
while(q->n >= Ntx){ while(q->n >= Ntx){
iunlock(ctlr); iunlock(ctlr);
eqlock(q); qlock(q);
if(waserror()){ if(!waserror()){
qunlock(q); tsleep(q, txqready, q, 10);
nexterror(); poperror();
} }
tsleep(q, txqready, q, 10);
qunlock(q); qunlock(q);
ilock(ctlr); ilock(ctlr);
} }
@ -1067,12 +1095,42 @@ qcmd(Ctlr *ctlr, uint qid, uint code, uchar *data, int size, Block *block)
iunlock(ctlr); iunlock(ctlr);
} }
static int
txqempty(void *arg)
{
TXQ *q = arg;
return q->n == 0;
}
static void
flushq(Ctlr *ctlr, uint qid)
{
TXQ *q;
q = &ctlr->tx[qid];
while(q->n > 0){
qlock(q);
if(!waserror()){
tsleep(q, txqempty, q, 10);
poperror();
}
qunlock(q);
}
}
static void static void
cmd(Ctlr *ctlr, uint code, uchar *data, int size) cmd(Ctlr *ctlr, uint code, uchar *data, int size)
{ {
qcmd(ctlr, 4, code, data, size, nil); qcmd(ctlr, 4, code, data, size, nil);
} }
static void
flushcmd(Ctlr *ctlr)
{
flushq(ctlr, 4);
}
static void static void
setled(Ctlr *ctlr, int which, int on, int off) setled(Ctlr *ctlr, int which, int on, int off)
{ {
@ -1099,9 +1157,6 @@ postboot(Ctlr *ctlr)
char *err; char *err;
int i, q; int i, q;
/* main led turn on! (verify that firmware processes commands) */
setled(ctlr, 2, 0, 1);
if((err = niclock(ctlr)) != nil) if((err = niclock(ctlr)) != nil)
error(err); error(err);
@ -1228,12 +1283,42 @@ rxon(Ether *edev, Wnode *bss)
{ {
uchar c[Tcmdsize], *p; uchar c[Tcmdsize], *p;
Ctlr *ctlr; Ctlr *ctlr;
uchar *bssid;
int filter, flags;
ctlr = edev->ctlr; ctlr = edev->ctlr;
bssid = edev->bcast;
filter = FilterMulticast | FilterBeacon;
if(ctlr->prom)
filter |= FilterPromisc;
if(bss != nil){
ctlr->channel = bss->channel;
if(bss->aid != 0){
bssid = bss->bssid;
filter |= FilterBSS;
filter &= ~FilterBeacon;
ctlr->aid = bss->aid;
ctlr->bssnodeid = -1;
} else {
filter &= ~FilterBSS;
filter |= FilterBeacon;
ctlr->aid = 0;
ctlr->bcastnodeid = -1;
}
} else {
ctlr->bcastnodeid = -1;
ctlr->bssnodeid = -1;
}
flags = RFlagTSF | RFlagCTSToSelf | RFlag24Ghz | RFlagAuto;
if(0) print("rxon: bssid %E, aid %x, channel %d, filter %x, flags %x\n",
bssid, ctlr->aid, ctlr->channel, filter, flags);
memset(p = c, 0, sizeof(c)); memset(p = c, 0, sizeof(c));
memmove(p, edev->ea, 6); p += 8; /* myaddr */ memmove(p, edev->ea, 6); p += 8; /* myaddr */
memmove(p, (bss != nil) ? bss->bssid : edev->bcast, 6); memmove(p, bssid, 6); p += 8; /* bssid */
p += 8; /* bssid */
memmove(p, edev->ea, 6); p += 8; /* wlap */ memmove(p, edev->ea, 6); p += 8; /* wlap */
*p++ = 3; /* mode (STA) */ *p++ = 3; /* mode (STA) */
*p++ = 0; /* air (?) */ *p++ = 0; /* air (?) */
@ -1242,14 +1327,13 @@ rxon(Ether *edev, Wnode *bss)
p += 2; p += 2;
*p++ = 0xff; /* ofdm mask (not yet negotiated) */ *p++ = 0xff; /* ofdm mask (not yet negotiated) */
*p++ = 0x0f; /* cck mask (not yet negotiated) */ *p++ = 0x0f; /* cck mask (not yet negotiated) */
if(bss != nil) put16(p, ctlr->aid & 0x3fff);
put16(p, bss->aid & ~0xc000);
p += 2; /* aid */ p += 2; /* aid */
put32(p, (1<<15)|(1<<30)|(1<<0)); /* flags (TSF | CTS_TO_SELF | 24GHZ) */ put32(p, flags);
p += 4; p += 4;
put32(p, 8|4|1); /* filter (NODECRYPT|MULTICAST|PROMISC) */ put32(p, filter);
p += 4; p += 4;
*p++ = bss != nil ? bss->channel : ctlr->channel; *p++ = ctlr->channel;
p++; /* reserved */ p++; /* reserved */
*p++ = 0xff; /* ht single mask */ *p++ = 0xff; /* ht single mask */
*p++ = 0xff; /* ht dual mask */ *p++ = 0xff; /* ht dual mask */
@ -1260,10 +1344,14 @@ rxon(Ether *edev, Wnode *bss)
p += 2; /* reserved */ p += 2; /* reserved */
} }
cmd(ctlr, 16, c, p - c); cmd(ctlr, 16, c, p - c);
if(ctlr->bcastnodeid == -1){
addnode(ctlr, (ctlr->type != Type4965) ? 15 : 31, edev->bcast); ctlr->bcastnodeid = (ctlr->type != Type4965) ? 15 : 31;
if(bss != nil) addnode(ctlr, ctlr->bcastnodeid, edev->bcast);
addnode(ctlr, 0, bss->bssid); }
if(ctlr->bssnodeid == -1 && bss != nil && ctlr->aid != 0){
ctlr->bssnodeid = 0;
addnode(ctlr, ctlr->bssnodeid, bss->bssid);
}
} }
static struct ratetab { static struct ratetab {
@ -1271,10 +1359,10 @@ static struct ratetab {
uchar plcp; uchar plcp;
uchar flags; uchar flags;
} ratetab[] = { } ratetab[] = {
{ 2, 10, 1<<1 }, { 2, 10, RFlagCCK },
{ 4, 20, 1<<1 }, { 4, 20, RFlagCCK },
{ 11, 55, 1<<1 }, { 11, 55, RFlagCCK },
{ 22, 110, 1<<1 }, { 22, 110, RFlagCCK },
{ 12, 0xd, 0 }, { 12, 0xd, 0 },
{ 18, 0xf, 0 }, { 18, 0xf, 0 },
{ 24, 0x5, 0 }, { 24, 0x5, 0 },
@ -1286,32 +1374,76 @@ static struct ratetab {
{ 120, 0x3, 0 } { 120, 0x3, 0 }
}; };
enum {
TFlagNeedProtection = 1<<0,
TFlagNeedRTS = 1<<1,
TFlagNeedCTS = 1<<2,
TFlagNeedACK = 1<<3,
TFlagLinkq = 1<<4,
TFlagImmBa = 1<<6,
TFlagFullTxOp = 1<<7,
TFlagBtDis = 1<<12,
TFlagAutoSeq = 1<<13,
TFlagMoreFrag = 1<<14,
TFlagInsertTs = 1<<16,
TFlagNeedPadding = 1<<20,
};
static void static void
transmit(Wifi *wifi, Wnode *, Block *b) transmit(Wifi *wifi, Wnode *wn, Block *b)
{ {
uchar c[Tcmdsize], *p; uchar c[Tcmdsize], *p;
Ether *edev;
Ctlr *ctlr; Ctlr *ctlr;
Wifipkt *w;
int flags, nodeid, rate;
ctlr = wifi->ether->ctlr; w = (Wifipkt*)b->rp;
edev = wifi->ether;
ctlr = edev->ctlr;
qlock(ctlr);
if(wn != nil && (wn->aid != ctlr->aid || wn->channel != ctlr->channel))
rxon(edev, wn);
rate = 0;
flags = 0;
nodeid = ctlr->bcastnodeid;
if((w->a1[0] & 1) == 0){
flags |= TFlagNeedACK;
if(BLEN(b) > 512-4)
flags |= TFlagNeedRTS;
if((w->fc[0] & 0x0c) == 0x08 && ctlr->bssnodeid != -1){
nodeid = ctlr->bssnodeid;
rate = 2; /* BUG: hardcode 11Mbit */
}
if(flags & (TFlagNeedRTS|TFlagNeedCTS)){
if(ctlr->type != Type4965){
flags &= ~(TFlagNeedRTS|TFlagNeedCTS);
flags |= TFlagNeedProtection;
} else
flags |= TFlagFullTxOp;
}
}
qunlock(ctlr);
memset(p = c, 0, sizeof(c)); memset(p = c, 0, sizeof(c));
put16(p, BLEN(b)); put16(p, BLEN(b));
p += 2; p += 2;
p += 2; /* lnext */ p += 2; /* lnext */
put32(p, 0); /* flags */ put32(p, flags);
p += 4; p += 4;
put32(p, 0); put32(p, 0);
p += 4; /* scratch */ p += 4; /* scratch */
/* BUG: hardcode 11Mbit */ *p++ = ratetab[rate].plcp;
*p++ = ratetab[2].plcp; /* plcp */ *p++ = ratetab[rate].flags | (1<<6);
*p++ = ratetab[2].flags | (1<<6); /* rflags */
p += 2; /* xflags */ p += 2; /* xflags */
*p++ = nodeid;
/* BUG: we always use broadcast node! */
*p++ = (ctlr->type != Type4965) ? 15 : 31;
*p++ = 0; /* security */ *p++ = 0; /* security */
*p++ = 0; /* linkq */ *p++ = 0; /* linkq */
p++; /* reserved */ p++; /* reserved */
@ -1379,11 +1511,7 @@ setoptions(Ether *edev)
int i; int i;
ctlr = edev->ctlr; ctlr = edev->ctlr;
ctlr->channel = 3;
for(i = 0; i < edev->nopt; i++){ for(i = 0; i < edev->nopt; i++){
if(strncmp(edev->opt[i], "channel=", 8) == 0)
ctlr->channel = atoi(edev->opt[i]+8);
else
if(strncmp(edev->opt[i], "essid=", 6) == 0){ if(strncmp(edev->opt[i], "essid=", 6) == 0){
snprint(buf, sizeof(buf), "essid %s", edev->opt[i]+6); snprint(buf, sizeof(buf), "essid %s", edev->opt[i]+6);
if(!waserror()){ if(!waserror()){
@ -1394,9 +1522,78 @@ setoptions(Ether *edev)
} }
} }
static void
iwlpromiscuous(void *arg, int on)
{
Ether *edev;
Ctlr *ctlr;
edev = arg;
ctlr = edev->ctlr;
qlock(ctlr);
ctlr->prom = on;
if(ctlr->prom)
rxon(edev, nil);
else
rxon(edev, ctlr->wifi->bss);
qunlock(ctlr);
}
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);
tsleep(&up->sleep, return0, 0, 1000);
}
/* wait for association */
setled(ctlr, 2, 10, 10);
while((bss = wifi->bss) != nil){
if(bss->aid != 0)
break;
tsleep(&up->sleep, return0, 0, 1000);
}
if(bss == nil)
continue;
/* wait for disassociation */
edev->link = 1;
setled(ctlr, 2, 0, 1);
while((bss = wifi->bss) != nil){
if(bss->aid == 0)
break;
tsleep(&up->sleep, return0, 0, 1000);
}
edev->link = 0;
}
}
static void static void
iwlattach(Ether *edev) iwlattach(Ether *edev)
{ {
char name[32];
FWImage *fw; FWImage *fw;
Ctlr *ctlr; Ctlr *ctlr;
char *err; char *err;
@ -1528,12 +1725,16 @@ iwlattach(Ether *edev)
bootfirmware(ctlr); bootfirmware(ctlr);
postboot(ctlr); postboot(ctlr);
ctlr->bcastnodeid = -1;
ctlr->bssnodeid = -1;
ctlr->channel = 1;
ctlr->aid = 0;
setoptions(edev); setoptions(edev);
rxon(edev, nil); snprint(name, sizeof(name), "#l%diwl", edev->ctlrno);
kproc(name, iwlproc, edev);
edev->prom = 1;
edev->link = 1;
ctlr->attached = 1; ctlr->attached = 1;
} }
qunlock(ctlr); qunlock(ctlr);
@ -1783,7 +1984,7 @@ again:
edev->attach = iwlattach; edev->attach = iwlattach;
edev->ifstat = iwlifstat; edev->ifstat = iwlifstat;
edev->ctl = iwlctl; edev->ctl = iwlctl;
edev->promiscuous = nil; edev->promiscuous = iwlpromiscuous;
edev->multicast = nil; edev->multicast = nil;
edev->mbps = 10; edev->mbps = 10;

View file

@ -121,6 +121,7 @@ trap.$O: /sys/include/tos.h
uartaxp.$O: uartaxp.i uartaxp.$O: uartaxp.i
etherm10g.$O: etherm10g2k.i etherm10g4k.i etherm10g.$O: etherm10g2k.i etherm10g4k.i
etheriwl.$O: wifi.h etheriwl.$O: wifi.h
wifi.$O: wifi.h
init.h:D: ../port/initcode.c init9.c init.h:D: ../port/initcode.c init9.c
$CC ../port/initcode.c $CC ../port/initcode.c

View file

@ -93,12 +93,12 @@ drop:
} }
static void static void
wifitx(Wifi *wifi, Block *b) wifitx(Wifi *wifi, Wnode *wn, Block *b)
{ {
Wifipkt *w; Wifipkt *w;
uint seq; uint seq;
seq = wifi->txseq++; seq = incref(&wifi->txseq);
seq <<= 4; seq <<= 4;
w = (Wifipkt*)b->rp; w = (Wifipkt*)b->rp;
@ -107,7 +107,7 @@ wifitx(Wifi *wifi, Block *b)
w->seq[0] = seq; w->seq[0] = seq;
w->seq[1] = seq>>8; w->seq[1] = seq>>8;
(*wifi->transmit)(wifi, wifi->bss, b); (*wifi->transmit)(wifi, wn, b);
} }
@ -118,18 +118,29 @@ nodelookup(Wifi *wifi, uchar *bssid, int new)
if(memcmp(bssid, wifi->ether->bcast, Eaddrlen) == 0) if(memcmp(bssid, wifi->ether->bcast, Eaddrlen) == 0)
return nil; return nil;
for(wn = nn = wifi->node; wn != &wifi->node[nelem(wifi->node)]; wn++){ if((wn = wifi->bss) != nil){
if(memcmp(wn->bssid, bssid, Eaddrlen) == 0){ if(memcmp(wn->bssid, bssid, Eaddrlen) == 0){
wn->lastseen = MACHP(0)->ticks; wn->lastseen = MACHP(0)->ticks;
return wn; return wn;
} }
if(wn != wifi->bss && wn->lastseen < nn->lastseen) }
for(wn = nn = wifi->node; wn != &wifi->node[nelem(wifi->node)]; wn++){
if(wn == wifi->bss)
continue;
if(memcmp(wn->bssid, bssid, Eaddrlen) == 0){
wn->lastseen = MACHP(0)->ticks;
return wn;
}
if(wn->lastseen < nn->lastseen)
nn = wn; nn = wn;
} }
if(!new) if(!new)
return nil; return nil;
memmove(nn->bssid, bssid, Eaddrlen); memmove(nn->bssid, bssid, Eaddrlen);
nn->lastseen = MACHP(0)->ticks; nn->lastseen = MACHP(0)->ticks;
nn->channel = 0;
nn->cap = 0;
nn->aid = 0;
return nn; return nn;
} }
@ -156,7 +167,7 @@ sendauth(Wifi *wifi, Wnode *bss)
*p++ = 0; /* status */ *p++ = 0; /* status */
*p++ = 0; *p++ = 0;
b->wp = p; b->wp = p;
wifitx(wifi, b); wifitx(wifi, bss, b);
} }
static void static void
@ -190,7 +201,7 @@ sendassoc(Wifi *wifi, Wnode *bss)
*p++ = 0x8b; *p++ = 0x8b;
*p++ = 0x96; *p++ = 0x96;
b->wp = p; b->wp = p;
wifitx(wifi, b); wifitx(wifi, bss, b);
} }
static void static void
@ -210,13 +221,14 @@ recvassoc(Wifi *wifi, Wnode *wn, uchar *d, int len)
wifi->status = Sassoc; wifi->status = Sassoc;
break; break;
default: default:
wn->aid = 0;
wifi->status = Sunassoc; wifi->status = Sunassoc;
return; return;
} }
} }
static void static void
recvbeacon(Wifi *wifi, Wnode *wn, uchar *d, int len) recvbeacon(Wifi *, Wnode *wn, uchar *d, int len)
{ {
uchar *e, *x; uchar *e, *x;
uchar t, m[256/8]; uchar t, m[256/8];
@ -251,11 +263,6 @@ recvbeacon(Wifi *wifi, Wnode *wn, uchar *d, int len)
if(len != strlen(wn->ssid) || strncmp(wn->ssid, (char*)d, len) != 0){ if(len != strlen(wn->ssid) || strncmp(wn->ssid, (char*)d, len) != 0){
strncpy(wn->ssid, (char*)d, len); strncpy(wn->ssid, (char*)d, len);
wn->ssid[len] = 0; wn->ssid[len] = 0;
if(wifi->bss == nil && strcmp(wifi->essid, wn->ssid) == 0){
wifi->bss = wn;
wifi->status = Sconn;
sendauth(wifi, wn);
}
} }
break; break;
case 3: /* DSPARAMS */ case 3: /* DSPARAMS */
@ -289,6 +296,11 @@ wifiproc(void *arg)
continue; continue;
b->rp += WIFIHDRSIZE; b->rp += WIFIHDRSIZE;
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){
wifi->bss = wn;
wifi->status = Sconn;
sendauth(wifi, wn);
}
continue; continue;
} }
if((wn = nodelookup(wifi, w->a3, 0)) == nil) if((wn = nodelookup(wifi, w->a3, 0)) == nil)
@ -306,7 +318,9 @@ wifiproc(void *arg)
sendassoc(wifi, wn); sendassoc(wifi, wn);
break; break;
case 0xc0: /* deauth */ case 0xc0: /* deauth */
wn->aid = 0;
wifi->status = Sunauth; wifi->status = Sunauth;
sendauth(wifi, wn);
break; break;
} }
} }
@ -318,6 +332,7 @@ wifietheroq(Wifi *wifi, Block *b)
{ {
Etherpkt e; Etherpkt e;
Wifipkt *w; Wifipkt *w;
Wnode *bss;
SNAP *s; SNAP *s;
if(BLEN(b) < ETHERHDRSIZE){ if(BLEN(b) < ETHERHDRSIZE){
@ -332,7 +347,8 @@ wifietheroq(Wifi *wifi, Block *b)
w = (Wifipkt*)b->rp; w = (Wifipkt*)b->rp;
w->fc[0] = 0x08; /* data */ w->fc[0] = 0x08; /* data */
w->fc[1] = 0x01; /* STA->AP */ w->fc[1] = 0x01; /* STA->AP */
memmove(w->a1, wifi->bss ? wifi->bss->bssid : wifi->ether->bcast, Eaddrlen); bss = wifi->bss;
memmove(w->a1, bss != nil ? bss->bssid : wifi->ether->bcast, Eaddrlen);
memmove(w->a2, e.s, Eaddrlen); memmove(w->a2, e.s, Eaddrlen);
memmove(w->a3, e.d, Eaddrlen); memmove(w->a3, e.d, Eaddrlen);
@ -344,7 +360,7 @@ wifietheroq(Wifi *wifi, Block *b)
s->orgcode[2] = 0; s->orgcode[2] = 0;
memmove(s->type, e.type, 2); memmove(s->type, e.type, 2);
wifitx(wifi, b); wifitx(wifi, bss, b);
} }
static void static void
@ -364,6 +380,7 @@ wifoproc(void *arg)
Wifi* Wifi*
wifiattach(Ether *ether, void (*transmit)(Wifi*, Wnode*, Block*)) wifiattach(Ether *ether, void (*transmit)(Wifi*, Wnode*, Block*))
{ {
char name[32];
Wifi *wifi; Wifi *wifi;
wifi = malloc(sizeof(Wifi)); wifi = malloc(sizeof(Wifi));
@ -372,8 +389,10 @@ wifiattach(Ether *ether, void (*transmit)(Wifi*, Wnode*, Block*))
wifi->transmit = transmit; wifi->transmit = transmit;
wifi->status = Snone; wifi->status = Snone;
kproc("wifi", wifiproc, wifi); snprint(name, sizeof(name), "#l%dwifi", ether->ctlrno);
kproc("wifo", wifoproc, wifi); kproc(name, wifiproc, wifi);
snprint(name, sizeof(name), "#l%dwifo", ether->ctlrno);
kproc(name, wifoproc, wifi);
return wifi; return wifi;
} }
@ -392,7 +411,6 @@ wifictl(Wifi *wifi, void *buf, long n)
cb = parsecmd(buf, n); cb = parsecmd(buf, n);
if(cb->f[0] && strcmp(cb->f[0], "essid") == 0){ if(cb->f[0] && strcmp(cb->f[0], "essid") == 0){
if(cb->f[1] == nil){ if(cb->f[1] == nil){
/* TODO senddeauth(wifi); */
wifi->essid[0] = 0; wifi->essid[0] = 0;
wifi->bss = nil; wifi->bss = nil;
} else { } else {
@ -425,7 +443,8 @@ wifistat(Wifi *wifi, void *buf, long n, ulong off)
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); p = seprint(p, e, "essid: %s\n", wifi->essid);
p = seprint(p, e, "bssid: %E\n", wifi->bss ? wifi->bss->bssid : zeros); wn = wifi->bss;
p = seprint(p, e, "bssid: %E\n", wn != nil ? wn->bssid : zeros);
now = MACHP(0)->ticks; now = MACHP(0)->ticks;
for(wn=wifi->node; wn != &wifi->node[nelem(wifi->node)]; wn++){ for(wn=wifi->node; wn != &wifi->node[nelem(wifi->node)]; wn++){

View file

@ -34,13 +34,13 @@ struct Wifi
Queue *iq; Queue *iq;
char *status; char *status;
Ref txseq;
void (*transmit)(Wifi*, Wnode*, Block*); void (*transmit)(Wifi*, Wnode*, Block*);
Wnode node[16]; char essid[32+2];
Wnode *bss; Wnode *bss;
uint txseq; Wnode node[32];
char essid[32+2];
}; };
Wifi *wifiattach(Ether *ether, void (*transmit)(Wifi*, Wnode*, Block*)); Wifi *wifiattach(Ether *ether, void (*transmit)(Wifi*, Wnode*, Block*));