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:
parent
c2f5d36d7f
commit
ffb3ded366
4 changed files with 284 additions and 63 deletions
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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++){
|
||||||
|
|
|
@ -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*));
|
||||||
|
|
Loading…
Reference in a new issue