diff 46bac13b16df5cbd92ea1da12cfef168201f0dad uncommitted --- a/sys/src/9/pc/etherrt2860.c +++ b/sys/src/9/pc/etherrt2860.c @@ -1251,23 +1251,7 @@ static void selchangroup(Ctlr*, int); static void setleds(Ctlr*, u16int); -static uint -get16(uchar *p){ - return *((u16int*)p); -} -static uint -get32(uchar *p){ - return *((u32int*)p); -} static void -put32(uchar *p, uint v){ - *((u32int*)p) = v; -} -static void -put16(uchar *p, uint v){ - *((u16int*)p) = v; -}; -static void memwrite(Ctlr *ctlr, u32int off, uchar *data, uint size){ memmove((uchar*)ctlr->nic + off, data, size); } @@ -2562,7 +2546,7 @@ { Ether *edev; Ctlr *ctlr; - Wifipkt *w; + Wframe w; u8int mcs, qid; int ridx, /*ctl_ridx,*/ hdrlen; uchar *p; @@ -2596,17 +2580,15 @@ tx = &ctlr->tx[qid]; nodeid = ctlr->bcastnodeid; - w = (Wifipkt*)b->rp; - hdrlen = wifihdrlen(w); - + hdrlen = wifiunpack(&w, b->rp); p = pool->p + pool->i * TxwiDmaSz; - if((w->a1[0] & 1) == 0){ + if((w.a1[0] & 1) == 0){ *(p+4) = TxAck; /* xflags */ if(BLEN(b) > 512-4) *(p+1) = TxTxopBackoff; /* txop */ - if((w->fc[0] & 0x0c) == 0x08 && ctlr->bssnodeid != -1){ + if((w.fc[0] & Wfc0typemask) == Wfc0typedat && ctlr->bssnodeid != -1){ nodeid = ctlr->bssnodeid; ridx = 2; /* BUG: hardcode 11Mbit */ } @@ -2652,11 +2634,8 @@ /* setup payload segments */ put32(p + 8, PCIWADDR(outb->rp)); /* sdp1 */ put16(p + 4, BLEN(outb) | TxLs1); /* sdl1 */ - - p = pool->p + pool->i * TxwiDmaSz; - w = (Wifipkt*)(p + Txwisize); if(ctlr->wifi->debug){ - print("transmit: %E->%E,%E nodeid=%x txq[%d]=%d size=%zd\n", w->a2, w->a1, w->a3, nodeid, qid, ctlr->tx[qid].i, BLEN(outb)); + print("transmit: %E->%E,%E nodeid=%x txq[%d]=%d size=%zd\n", w.a2, w.a1, w.a3, nodeid, qid, ctlr->tx[qid].i, BLEN(outb)); } tx->i = (tx->i + 1) % Ntx; @@ -2730,7 +2709,7 @@ u16int sdl0, len; u32int flags; uchar *p; - Wifipkt *w; + Wframe w; int hdrlen; p = (uchar*)rx->p + Rdscsize * rx->i; @@ -2761,16 +2740,15 @@ len = get16(b->rp + 2 /* wcid, keyidx */) & 0xfff; b->rp = d + Rxwisize; b->wp = b->rp + len; - w = (Wifipkt*)b->rp; - hdrlen = wifihdrlen(w); + hdrlen = wifiunpack(&w, b->rp); /* HW may insert 2 padding bytes after 802.11 header */ if(flags & RxL2pad){ memmove(b->rp + 2, b->rp, hdrlen); b->rp += 2; } - w = (Wifipkt*)b->rp; + wifiunpack(&w, b->rp); if(ctlr->wifi->debug) - print("receive: %E->%E,%E wcid 0x%x \n", w->a2, w->a1, w->a3, ctlr->wcid); + print("receive: %E->%E,%E wcid 0x%x \n", w.a2, w.a1, w.a3, ctlr->wcid); wifiiq(ctlr->wifi, b); skip: put16(p + 4 /* sdp0 */ + 2 /* sdl1 */, sdl0 & ~RxDdone); --- a/sys/src/9/pc/etherwpi.c +++ b/sys/src/9/pc/etherwpi.c @@ -290,24 +290,6 @@ #define csr32r(c, r) (*((c)->nic+((r)/4))) #define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v)) -static uint -get32(uchar *p){ - return *((u32int*)p); -} -static uint -get16(uchar *p) -{ - return *((u16int*)p); -} -static void -put32(uchar *p, uint v){ - *((u32int*)p) = v; -} -static void -put16(uchar *p, uint v){ - *((u16int*)p) = v; -}; - static char* niclock(Ctlr *ctlr) { @@ -1402,7 +1384,7 @@ uchar c[Tcmdsize], *p; Ether *edev; Ctlr *ctlr; - Wifipkt *w; + Wframe w; int flags, nodeid, rate, timeout; char *err; @@ -1430,14 +1412,15 @@ timeout = 3; nodeid = ctlr->bcastnodeid; p = wn->minrate; - w = (Wifipkt*)b->rp; - if((w->a1[0] & 1) == 0){ + + wifiunpack(&w, b->rp); + if((w.a1[0] & 1) == 0){ flags |= TFlagNeedACK; if(BLEN(b) > 512-4) flags |= TFlagNeedRTS|TFlagFullTxOp; - if((w->fc[0] & 0x0c) == 0x08 && ctlr->bssnodeid != -1){ + if((w.fc[0] & Wfc0typemask) == Wfc0typedat && ctlr->bssnodeid != -1){ timeout = 0; nodeid = ctlr->bssnodeid; p = wn->actrate; --- a/sys/src/9/port/etheriwl.c +++ b/sys/src/9/port/etheriwl.c @@ -722,28 +722,6 @@ #define csr32r(c, r) (*((c)->nic+((r)/4))) #define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v)) -static uint -get16(uchar *p){ - return *((u16int*)p); -} -static uint -get32(uchar *p){ - return *((u32int*)p); -} -static void -put32(uchar *p, uint v){ - *((u32int*)p) = v; -} -static void -put64(uchar *p, uvlong v) -{ - *((u64int*)p) = v; -} -static void -put16(uchar *p, uint v){ - *((u16int*)p) = v; -}; - static char* niclock(Ctlr *ctlr) { @@ -1692,12 +1670,13 @@ coherence(); ctlr->rx.b[i] = b; - if(ctlr->mqrx) + if(ctlr->mqrx) { put64(ctlr->rx.p + (i<<3), PCIWADDR(b->rp)); - else + } else { put32(ctlr->rx.p + (i<<2), PCIWADDR(b->rp) >> 8); - dmaflush(1, ctlr->rx.p + i*ctlr->rx.psz, ctlr->rx.psz); + } + dmaflush(1, ctlr->rx.p + i*ctlr->rx.psz, ctlr->rx.psz); return 0; } @@ -3839,7 +3818,7 @@ Ether *edev; Station *sta; Ctlr *ctlr; - Wifipkt *w; + Wframe w; char *err; edev = wifi->ether; @@ -3876,14 +3855,15 @@ flags = 0; sta = &ctlr->bcast; p = wn->minrate; - w = (Wifipkt*)b->rp; - if((w->a1[0] & 1) == 0){ + + wifiunpack(&w, b->rp); + if((w.a1[0] & 1) == 0){ flags |= TFlagNeedACK; if(BLEN(b) > 512-4) flags |= TFlagNeedRTS; - if((w->fc[0] & 0x0c) == 0x08 && ctlr->bss.id != -1){ + if((w.fc[0] & 0x0c) == 0x08 && ctlr->bss.id != -1){ sta = &ctlr->bss; p = wn->actrate; } --- a/sys/src/9/port/portdat.h +++ b/sys/src/9/port/portdat.h @@ -135,12 +135,13 @@ /* flag values */ enum { - BINTR = (1<<0), - BFREE = (1<<1), - Bipck = (1<<2), /* ip checksum */ - Budpck = (1<<3), /* udp checksum */ - Btcpck = (1<<4), /* tcp checksum */ - Bpktck = (1<<5), /* packet checksum */ + BINTR = (1<<0), + BFREE = (1<<1), + Bipck = (1<<2), /* ip checksum */ + Budpck = (1<<3), /* udp checksum */ + Btcpck = (1<<4), /* tcp checksum */ + Bpktck = (1<<5), /* packet checksum */ + Btimestamp = (1<<6), /* timestamp prefix */ }; struct Block --- a/sys/src/9/port/wifi.c +++ b/sys/src/9/port/wifi.c @@ -45,46 +45,133 @@ 0 }; -static Block* wifidecrypt(Wifi *, Wnode *, Block *); -static Block* wifiencrypt(Wifi *, Wnode *, Block *); +static Block* wifidecrypt(Wifi *, Wnode *, Wframe *, Block *); +static Block* wifiencrypt(Wifi *, Wnode *, Wframe *, Block *); static void freewifikeys(Wifi *, Wnode *); static void dmatproxy(Block *bp, int upstream, uchar proxy[Eaddrlen], DMAT *t); static uchar* -srcaddr(Wifipkt *w) +srcaddr(Wframe *f) { - if((w->fc[1] & 0x02) == 0) - return w->a2; - if((w->fc[1] & 0x01) == 0) - return w->a3; - return w->a4; + if((f->fc[1] & 0x02) == 0) + return f->a2; + if((f->fc[1] & 0x01) == 0) + return f->a3; + + return f->a4; } + static uchar* -dstaddr(Wifipkt *w) +dstaddr(Wframe *f) { - if((w->fc[1] & 0x01) != 0) - return w->a3; - return w->a1; + if((f->fc[1] & 0x01) != 0) + return f->a3; + + return f->a1; } int -wifihdrlen(Wifipkt *w) +wifilen(Wframe *w) { - int n; + int l = WIFIHDRSIZE; - n = WIFIHDRSIZE; - if((w->fc[0] & 0x0c) == 0x08) - if((w->fc[0] & 0xf0) == 0x80){ /* QOS */ - n += 2; - if(w->fc[1] & 0x80) - n += 4; + /* got a4? */ + if((w->fc[1] & Wfc1dirmask) == Wfc1diraptoap) + l += Eaddrlen; + + /* got qos? */ + if((w->fc[0] & Wfc0typemask) == Wfc0typedat) { + if((w->fc[0] & Wfc0submask) == Wfc0subqos) { + l += 2; + + /* got ht? */ + if(w->fc[1] & Wfc1order) + l += 4; } - if((w->fc[1] & 3) == 0x03) - n += Eaddrlen; - return n; + } + + return l; } +int +wifipack(Wframe *w, uchar *p) +{ + uchar *s = p; + + *p++ = w->fc[0]; + *p++ = w->fc[1]; + *p++ = w->dur; + *p++ = w->dur >> 8; + + memmove(p, w->a1, Eaddrlen); p += Eaddrlen; + memmove(p, w->a2, Eaddrlen); p += Eaddrlen; + memmove(p, w->a3, Eaddrlen); p += Eaddrlen; + + *p = w->seq; + *p = w->seq >> 8; + + /* got a4? */ + if((w->fc[1] & Wfc1dirmask) == Wfc1diraptoap) { + memmove(p, w->a4, Eaddrlen); + p += Eaddrlen; + } + + /* got qos? */ + if((w->fc[0] & Wfc0typemask) == Wfc0typedat) { + if((w->fc[0] & Wfc0submask) == Wfc0subqos) { + *p++ = w->qos; + *p++ = w->qos >> 8; + + /* got ht? */ + if(w->fc[1] & Wfc1order) + p += 4; + } + } + + return p - s; +} + +int +wifiunpack(Wframe *w, uchar *p) +{ + uchar *s = p; + + w->fc[0] = *p++; + w->fc[1] = *p++; + + w->dur = *p++; + w->dur |= *p++ << 8; + + memmove(w->a1, p, Eaddrlen); p += Eaddrlen; + memmove(w->a2, p, Eaddrlen); p += Eaddrlen; + memmove(w->a3, p, Eaddrlen); p += Eaddrlen; + + w->seq = *p++; + w->seq |= *p++ << 8; + + /* got a4? */ + if((w->fc[1] & Wfc1dirmask) == Wfc1diraptoap) { + memmove(w->a4, p, Eaddrlen); + p += Eaddrlen; + } + + /* got qos? */ + if((w->fc[0] & Wfc0typemask) == Wfc0typedat) { + if((w->fc[0] & Wfc0submask) == Wfc0subqos) { + w->qos = *p++; + w->qos |= *p++ << 8; + + /* got ht? */ + if(w->fc[1] & Wfc1order) + p += 4; + } + } + + return p - s; +} + + static uvlong getts(uchar *d) { @@ -102,7 +189,7 @@ wifiiq(Wifi *wifi, Block *b) { SNAP s; - Wifipkt h, *w; + Wframe w; Etherpkt *e; int hdrlen; @@ -110,49 +197,55 @@ assert(b->rp - b->base >= 8); if(BLEN(b) < WIFIHDRSIZE) goto drop; - w = (Wifipkt*)b->rp; - hdrlen = wifihdrlen(w); + + hdrlen = wifiunpack(&w, b->rp); if(BLEN(b) < hdrlen) goto drop; - if(memcmp(srcaddr(w), wifi->ether->ea, Eaddrlen) == 0) + if(memcmp(srcaddr(&w), wifi->ether->ea, Eaddrlen) == 0) goto drop; - if(w->fc[1] & 0x40){ + + if(w.fc[1] & 0x40){ /* encrypted */ qpass(wifi->iq, b); return; } - switch(w->fc[0] & 0x0c){ - case 0x00: /* management */ - if((w->fc[1] & 3) != 0x00) /* STA->STA */ + switch(w.fc[0] & Wfc0typemask){ + case Wfc0typemgt: + if((w.fc[1] & Wfc1dirmask) != Wfc1dirstatosta) break; qpass(wifi->iq, b); return; - case 0x04: /* control */ + case Wfc0typectl: break; - case 0x08: /* data */ + case Wfc0typedat: b->flag &= ~Btimestamp; b->rp += hdrlen; - switch(w->fc[0] & 0xf0){ + switch(w.fc[0] & Wfc0submask){ default: goto drop; - case 0x80: /* QOS */ - case 0x00: + + case Wfc0subqos: + case Wfc0subdata: break; } - if(BLEN(b) < SNAPHDRSIZE) + if(BLEN(b) < SNAPHDRSIZE) { + iprint("wifiq: dropped, no snap\n"); break; + } + memmove(&s, b->rp, SNAPHDRSIZE); if(s.dsap != 0xAA || s.ssap != 0xAA || s.control != 3) break; if(s.orgcode[0] != 0 || s.orgcode[1] != 0 || s.orgcode[2] != 0) break; + b->rp += SNAPHDRSIZE-ETHERHDRSIZE; - h = *w; e = (Etherpkt*)b->rp; - memmove(e->d, dstaddr(&h), Eaddrlen); - memmove(e->s, srcaddr(&h), Eaddrlen); + memmove(e->d, dstaddr(&w), Eaddrlen); + memmove(e->s, srcaddr(&w), Eaddrlen); memmove(e->type, s.type, 2); dmatproxy(b, 0, wifi->ether->ea, &wifi->dmat); + etheriq(wifi->ether, b); return; } @@ -161,28 +254,24 @@ } static void -wifitx(Wifi *wifi, Wnode *wn, Block *b) +wifitx(Wifi *wifi, Wnode *wn, Wframe *f, Block *b) { - Wifipkt *w; - uint seq; - wn->lastsend = MACHP(0)->ticks; - seq = incref(&wifi->txseq); - seq <<= 4; - - w = (Wifipkt*)b->rp; - w->dur[0] = 0; - w->dur[1] = 0; - w->seq[0] = seq; - w->seq[1] = seq>>8; - - if((w->fc[0] & 0x0c) != 0x00){ - b = wifiencrypt(wifi, wn, b); + if((f->fc[0] & Wfc0typemask) != Wfc0typemgt){ + b = wifiencrypt(wifi, wn, f, b); if(b == nil) return; } + b = padblock(b, wifilen(f)); + if(!b) + return; + + f->dur = 0; + f->seq = incref(&wifi->txseq) << 4; + wifipack(f, b->rp); + if((wn->txcount++ & 255) == 255 && wn->actrate != nil && wn->actrate != wn->maxrate){ uchar *a, *p; @@ -229,13 +318,14 @@ void wifitxfail(Wifi *wifi, Block *b) { - Wifipkt *w; + Wframe w; Wnode *wn; if(b == nil) return; - w = (Wifipkt*)b->rp; - wn = nodelookup(wifi, w->a1, 0); + + wifiunpack(&w, b->rp); + wn = nodelookup(wifi, w.a1, 0); if(wn == nil) return; wn->txerror++; @@ -310,7 +400,7 @@ static void wifiprobe(Wifi *wifi, Wnode *wn) { - Wifipkt *w; + Wframe f; Block *b; uchar *p; int n; @@ -322,15 +412,13 @@ return; } - b = allocb(WIFIHDRSIZE + 512); - w = (Wifipkt*)b->wp; - - w->fc[0] = 0x40; /* probe request */ - w->fc[1] = 0x00; /* STA->STA */ - memmove(w->a1, wifi->ether->bcast, Eaddrlen); /* ??? */ - memmove(w->a2, wifi->ether->ea, Eaddrlen); - memmove(w->a3, wifi->ether->bcast, Eaddrlen); - b->wp += WIFIHDRSIZE; + b = allocb(512); + f.fc[0] = Wfc0typemgt | Wfc0subprobe; + f.fc[1] = Wfc1dirstatosta; + memmove(f.a1, wifi->ether->bcast, Eaddrlen); + memmove(f.a2, wifi->ether->ea, Eaddrlen); + memmove(f.a3, wifi->ether->bcast, Eaddrlen); + p = b->wp; *p++ = 0; /* set */ @@ -345,24 +433,23 @@ *p++ = wn->channel; b->wp = p; - wifitx(wifi, wn, b); + wifitx(wifi, wn, &f, b); } static void sendauth(Wifi *wifi, Wnode *bss) { - Wifipkt *w; + Wframe f; Block *b; uchar *p; - b = allocb(WIFIHDRSIZE + 3*2); - w = (Wifipkt*)b->wp; - w->fc[0] = 0xB0; /* auth request */ - w->fc[1] = 0x00; /* STA->STA */ - memmove(w->a1, bss->bssid, Eaddrlen); /* ??? */ - memmove(w->a2, wifi->ether->ea, Eaddrlen); - memmove(w->a3, bss->bssid, Eaddrlen); - b->wp += WIFIHDRSIZE; + b = allocb(3*2); + f.fc[0] = Wfc0typemgt | Wfc0subauth; + f.fc[1] = Wfc1dirstatosta; + memmove(f.a1, bss->bssid, Eaddrlen); /* ??? */ + memmove(f.a2, wifi->ether->ea, Eaddrlen); + memmove(f.a3, bss->bssid, Eaddrlen); + p = b->wp; *p++ = 0; /* alg */ *p++ = 0; @@ -374,26 +461,24 @@ bss->aid = 0; - wifitx(wifi, bss, b); + wifitx(wifi, bss, &f, b); } static void sendassoc(Wifi *wifi, Wnode *bss) { - Wifipkt *w; + Wframe f; Block *b; uchar *p; int cap, n; - b = allocb(WIFIHDRSIZE + 512); - w = (Wifipkt*)b->wp; - w->fc[0] = 0x00; /* assoc request */ - w->fc[1] = 0x00; /* STA->STA */ - memmove(w->a1, bss->bssid, Eaddrlen); /* ??? */ - memmove(w->a2, wifi->ether->ea, Eaddrlen); - memmove(w->a3, bss->bssid, Eaddrlen); + b = allocb(512); + f.fc[0] = Wfc0typemgt | Wfc0subassoc; + f.fc[1] = Wfc1dirstatosta; + memmove(f.a1, bss->bssid, Eaddrlen); /* ??? */ + memmove(f.a2, wifi->ether->ea, Eaddrlen); + memmove(f.a3, bss->bssid, Eaddrlen); - b->wp += WIFIHDRSIZE; p = b->wp; /* capinfo */ @@ -422,7 +507,7 @@ } b->wp = p; - wifitx(wifi, bss, b); + wifitx(wifi, bss, &f, b); } static void @@ -621,7 +706,7 @@ wifiproc(void *arg) { Wifi *wifi; - Wifipkt *w; + Wframe f; Wnode *wn; Block *b; @@ -637,16 +722,17 @@ } if((b = qbread(wifi->iq, 100000)) == nil) break; - w = (Wifipkt*)b->rp; - if(w->fc[1] & 0x40){ + + b->rp += wifiunpack(&f, b->rp); + if(f.fc[1] & Wfc1prot){ /* encrypted */ - if((wn = nodelookup(wifi, w->a2, 0)) == nil) + if((wn = nodelookup(wifi, f.a2, 0)) == nil) continue; wn->lastseen = MACHP(0)->ticks; - if((b = wifidecrypt(wifi, wn, b)) != nil){ - w = (Wifipkt*)b->rp; - if(w->fc[1] & 0x40) + if((b = wifidecrypt(wifi, wn, &f, b)) != nil){ + if(f.fc[1] & Wfc1prot) continue; + b->flag &= ~Btimestamp; wifiiq(wifi, b); b = nil; @@ -653,22 +739,23 @@ } continue; } + /* management */ - if((w->fc[0] & 0x0c) != 0x00) + if((f.fc[0] & Wfc0typemask) != Wfc0typemgt) continue; - switch(w->fc[0] & 0xf0){ - case 0x50: /* probe response */ + switch(f.fc[0] & Wfc0submask){ + case Wfc0subprober: if(wifi->debug) - print("#l%d: got probe from %E\n", wifi->ether->ctlrno, w->a3); + print("#l%d: got probe from %E\n", wifi->ether->ctlrno, f.a3); /* no break */ - case 0x80: /* beacon */ - if((wn = nodelookup(wifi, w->a3, 1)) == nil) + case Wfc0subbeacon: + if((wn = nodelookup(wifi, f.a3, 1)) == nil) continue; wn->lastseen = MACHP(0)->ticks; if(b->flag & Btimestamp) wn->rs = getts(b->rp - 8); - b->rp += wifihdrlen(w); + recvbeacon(wifi, wn, b->rp, BLEN(b)); if(wifi->bss == nil @@ -681,23 +768,22 @@ continue; } - if(memcmp(w->a1, wifi->ether->ea, Eaddrlen)) + if(memcmp(f.a1, wifi->ether->ea, Eaddrlen)) continue; - if((wn = nodelookup(wifi, w->a3, 0)) == nil) + if((wn = nodelookup(wifi, f.a3, 0)) == nil) continue; wn->lastseen = MACHP(0)->ticks; if(b->flag & Btimestamp) wn->rs = getts(b->rp - 8); - switch(w->fc[0] & 0xf0){ - case 0x10: /* assoc response */ - case 0x30: /* reassoc response */ - b->rp += wifihdrlen(w); + switch(f.fc[0] & Wfc0submask){ + case Wfc0subassocr: + case Wfc0subreassocr: recvassoc(wifi, wn, b->rp, BLEN(b)); /* notify driver about node aid association */ if(wn == wifi->bss) (*wifi->transmit)(wifi, wn, nil); break; - case 0xb0: /* auth */ + case Wfc0subauth: if(wifi->debug) print("#l%d: got auth from %E\n", wifi->ether->ctlrno, wn->bssid); if(wn->brsnelen > 0 && wn->rsnelen == 0) @@ -710,7 +796,7 @@ sendassoc(wifi, wn); } break; - case 0xc0: /* deauth */ + case Wfc0subdeauth: if(wifi->debug) print("#l%d: got deauth from %E\n", wifi->ether->ctlrno, wn->bssid); wifideauth(wifi, wn); @@ -724,8 +810,7 @@ wifietheroq(Wifi *wifi, Block *b) { Etherpkt e; - Wifipkt h; - int hdrlen; + Wframe f; Wnode *wn; SNAP *s; @@ -745,21 +830,19 @@ } else if(wn->status != Sassoc) goto drop; - h.fc[0] = 0x08; /* data */ - memmove(h.a1, wn->bssid, Eaddrlen); + f.fc[0] = Wfc0typedat; + memmove(f.a1, wn->bssid, Eaddrlen); if(memcmp(e.s, wifi->ether->ea, Eaddrlen) == 0) { - h.fc[1] = 0x01; /* STA->AP */ + f.fc[1] = Wfc1dirstatoap; } else { - h.fc[1] = 0x03; /* AP->AP (WDS) */ - memmove(h.a2, wifi->ether->ea, Eaddrlen); + f.fc[1] = Wfc1diraptoap; + memmove(f.a2, wifi->ether->ea, Eaddrlen); } - memmove(dstaddr(&h), e.d, Eaddrlen); - memmove(srcaddr(&h), e.s, Eaddrlen); + memmove(dstaddr(&f), e.d, Eaddrlen); + memmove(srcaddr(&f), e.s, Eaddrlen); - hdrlen = wifihdrlen(&h); - b = padblock(b, hdrlen + SNAPHDRSIZE); - memmove(b->rp, &h, hdrlen); - s = (SNAP*)(b->rp + hdrlen); + b = padblock(b, SNAPHDRSIZE); + s = (SNAP*)(b->rp); s->dsap = s->ssap = 0xAA; s->control = 0x03; s->orgcode[0] = 0; @@ -767,7 +850,7 @@ s->orgcode[2] = 0; memmove(s->type, e.type, 2); - wifitx(wifi, wn, b); + wifitx(wifi, wn, &f, b); return; drop: freeb(b); @@ -1153,18 +1236,18 @@ return n; } -static void tkipencrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc); -static int tkipdecrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc); -static void ccmpencrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc); -static int ccmpdecrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc); +static void tkipencrypt(Wkey *k, Wframe *w, Block *b, uvlong tsc); +static int tkipdecrypt(Wkey *k, Wframe *w, Block *b, uvlong tsc); +static void ccmpencrypt(Wkey *k, Wframe *w, Block *b, uvlong tsc); +static int ccmpdecrypt(Wkey *k, Wframe *w, Block *b, uvlong tsc); static Block* -wifiencrypt(Wifi *wifi, Wnode *wn, Block *b) +wifiencrypt(Wifi *wifi, Wnode *wn, Wframe *f, Block *b) { uvlong tsc; - int n, kid; - Wifipkt *w; + int kid; Wkey *k; + uchar *p; rlock(&wifi->crypt); @@ -1175,15 +1258,10 @@ return b; } - n = wifihdrlen((Wifipkt*)b->rp); - b = padblock(b, 8); b = padblock(b, -(8+4)); + p = b->rp; - w = (Wifipkt*)b->rp; - memmove(w, b->rp+8, n); - b->rp += n; - tsc = ++k->tsc; switch(k->cipher){ @@ -1197,7 +1275,7 @@ b->rp[6] = tsc>>32; b->rp[7] = tsc>>40; b->rp += 8; - tkipencrypt(k, w, b, tsc); + tkipencrypt(k, f, b, tsc); break; case CCMP: b->rp[0] = tsc; @@ -1209,29 +1287,24 @@ b->rp[6] = tsc>>32; b->rp[7] = tsc>>40; b->rp += 8; - ccmpencrypt(k, w, b, tsc); + ccmpencrypt(k, f, b, tsc); break; } - runlock(&wifi->crypt); - b->rp = (uchar*)w; - w->fc[1] |= 0x40; + runlock(&wifi->crypt); + f->fc[1] |= Wfc1prot; + b->rp = p; return b; } static Block* -wifidecrypt(Wifi *wifi, Wnode *wn, Block *b) +wifidecrypt(Wifi *wifi, Wnode *wn, Wframe *f, Block *b) { uvlong tsc; - int n, kid; - Wifipkt *w; + int kid; Wkey *k; rlock(&wifi->crypt); - - w = (Wifipkt*)b->rp; - n = wifihdrlen(w); - b->rp += n; if(BLEN(b) < 8+8) goto drop; @@ -1238,7 +1311,7 @@ kid = b->rp[3]>>6; if((b->rp[3] & 0x20) == 0) goto drop; - if((w->a1[0] & 1) == 0) + if((f->a1[0] & 1) == 0) kid = 4; /* use peerwise key for non-unicast */ k = wn->rxkey[kid]; @@ -1255,7 +1328,7 @@ b->rp += 8; if(tsc <= k->tsc) goto drop; - if(tkipdecrypt(k, w, b, tsc) != 0) + if(tkipdecrypt(k, f, b, tsc) != 0) goto drop; break; case CCMP: @@ -1268,7 +1341,7 @@ b->rp += 8; if(tsc <= k->tsc) goto drop; - if(ccmpdecrypt(k, w, b, tsc) != 0) + if(ccmpdecrypt(k, f, b, tsc) != 0) goto drop; break; default: @@ -1280,10 +1353,7 @@ runlock(&wifi->crypt); k->tsc = tsc; - b->rp -= n; - memmove(b->rp, w, n); - w = (Wifipkt*)b->rp; - w->fc[1] &= ~0x40; + f->fc[1] &= ~Wfc1prot; return b; } @@ -1518,7 +1588,7 @@ static uchar pad4[4] = { 0x00, 0x00, 0x00, 0x00, }; static void -tkipencrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc) +tkipencrypt(Wkey *k, Wframe *f, Block *b, uvlong tsc) { u16int tk[8], p1k[5]; uchar seed[16]; @@ -1527,8 +1597,8 @@ ulong crc; micsetup(&ms, k->key+24); - micupdate(&ms, dstaddr(w), Eaddrlen); - micupdate(&ms, srcaddr(w), Eaddrlen); + micupdate(&ms, dstaddr(f), Eaddrlen); + micupdate(&ms, srcaddr(f), Eaddrlen); micupdate(&ms, pad4, 4); micupdate(&ms, b->rp, BLEN(b)); micfinish(&ms, b->wp); @@ -1543,7 +1613,7 @@ b->wp += 4; tkipk2tk(k->key, tk); - tkipphase1(tsc >> 16, w->a2, tk, p1k); + tkipphase1(tsc >> 16, f->a2, tk, p1k); tkipphase2(tsc & 0xFFFF, p1k, tk, seed); setupRC4state(&rs, seed, sizeof(seed)); rc4(&rs, b->rp, BLEN(b)); @@ -1550,7 +1620,7 @@ } static int -tkipdecrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc) +tkipdecrypt(Wkey *k, Wframe *f, Block *b, uvlong tsc) { uchar seed[16], mic[8]; u16int tk[8], p1k[5]; @@ -1562,7 +1632,7 @@ return -1; tkipk2tk(k->key, tk); - tkipphase1(tsc >> 16, w->a2, tk, p1k); + tkipphase1(tsc >> 16, f->a2, tk, p1k); tkipphase2(tsc & 0xFFFF, p1k, tk, seed); setupRC4state(&rs, seed, sizeof(seed)); rc4(&rs, b->rp, BLEN(b)); @@ -1577,8 +1647,8 @@ b->wp -= 8; micsetup(&ms, k->key+16); - micupdate(&ms, dstaddr(w), Eaddrlen); - micupdate(&ms, srcaddr(w), Eaddrlen); + micupdate(&ms, dstaddr(f), Eaddrlen); + micupdate(&ms, srcaddr(f), Eaddrlen); micupdate(&ms, pad4, 4); micupdate(&ms, b->rp, BLEN(b)); micfinish(&ms, mic); @@ -1708,12 +1778,12 @@ } static int -setupCCMP(Wifipkt *w, uvlong tsc, uchar nonce[13], uchar auth[32]) +setupCCMP(Wframe *f, uvlong tsc, uchar nonce[13], uchar auth[32]) { uchar *p; - nonce[0] = ((w->fc[0] & 0x0c) == 0x00) << 4; - memmove(&nonce[1], w->a2, Eaddrlen); + nonce[0] = ((f->fc[0] & 0x0c) == 0x00) << 4; + memmove(&nonce[1], f->a2, Eaddrlen); nonce[7] = tsc >> 40; nonce[8] = tsc >> 32; nonce[9] = tsc >> 24; @@ -1722,15 +1792,15 @@ nonce[12] = tsc; p = auth; - *p++ = (w->fc[0] & (((w->fc[0] & 0x0c) == 0x08) ? 0x0f : 0xff)); - *p++ = (w->fc[1] & ~0x38) | 0x40; - memmove(p, w->a1, Eaddrlen); p += Eaddrlen; - memmove(p, w->a2, Eaddrlen); p += Eaddrlen; - memmove(p, w->a3, Eaddrlen); p += Eaddrlen; - *p++ = w->seq[0] & 0x0f; + *p++ = (f->fc[0] & (((f->fc[0] & 0x0c) == 0x08) ? 0x0f : 0xff)); + *p++ = (f->fc[1] & ~0x38) | 0x40; + memmove(p, f->a1, Eaddrlen); p += Eaddrlen; + memmove(p, f->a2, Eaddrlen); p += Eaddrlen; + memmove(p, f->a3, Eaddrlen); p += Eaddrlen; + *p++ = f->seq & 0x0f; *p++ = 0; - if((w->fc[1] & 3) == 0x03) { - memmove(p, w->a4, Eaddrlen); + if((f->fc[1] & 3) == 0x03) { + memmove(p, f->a4, Eaddrlen); p += Eaddrlen; } @@ -1737,19 +1807,20 @@ return p - auth; } + static void -ccmpencrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc) +ccmpencrypt(Wkey *k, Wframe *f, Block *b, uvlong tsc) { uchar auth[32], nonce[13]; aesCCMencrypt(2, 8, nonce, auth, - setupCCMP(w, tsc, nonce, auth), + setupCCMP(f, tsc, nonce, auth), b->rp, BLEN(b), (AESstate*)k->key); b->wp += 8; } static int -ccmpdecrypt(Wkey *k, Wifipkt *w, Block *b, uvlong tsc) +ccmpdecrypt(Wkey *k, Wframe *f, Block *b, uvlong tsc) { uchar auth[32], nonce[13]; @@ -1758,7 +1829,7 @@ b->wp -= 8; return aesCCMdecrypt(2, 8, nonce, auth, - setupCCMP(w, tsc, nonce, auth), + setupCCMP(f, tsc, nonce, auth), b->rp, BLEN(b), (AESstate*)k->key); } --- a/sys/src/9/port/wifi.h +++ b/sys/src/9/port/wifi.h @@ -1,7 +1,7 @@ typedef struct Wkey Wkey; typedef struct Wnode Wnode; +typedef struct Wframe Wframe; typedef struct Wifi Wifi; -typedef struct Wifipkt Wifipkt; typedef struct DMAT DMAT; typedef struct DMTE DMTE; @@ -15,6 +15,53 @@ CCMP = 2, }; +/* 802.11 frame fc[0] */ +enum { + Wfc0vermask = 0x03, + Wfc0typemask = 0x0c, + Wfc0submask = 0xf0, + + /* frame types */ + Wfc0typemgt = 0x00, + Wfc0typectl = 0x04, + Wfc0typedat = 0x08, + + /* frame subtypes (management) */ + Wfc0subassoc = 0x00, + Wfc0subassocr = 0x10, + Wfc0subreassoc = 0x20, + Wfc0subreassocr = 0x30, + Wfc0subprobe = 0x40, + Wfc0subprober = 0x50, + Wfc0subbeacon = 0x80, + Wfc0subdisassoc = 0xa0, + Wfc0subauth = 0xb0, + Wfc0subdeauth = 0xc0, + + /* frame subtypes (data) */ + Wfc0subdata = 0x00, + Wfc0subnodata = 0x40, + Wfc0subqos = 0x80, +}; + +/* 802.11 frame fc[1] */ +enum { + Wfc1dirmask = 0x03, + + /* frame direction */ + Wfc1dirstatosta = 0x00, + Wfc1dirstatoap = 0x01, + Wfc1diraptosta = 0x02, + Wfc1diraptoap = 0x03, + + Wfc1frag = 0x04, + Wfc1retry = 0x08, + Wfc1pwrmgt = 0x10, + Wfc1data = 0x20, + Wfc1prot = 0x40, + Wfc1order = 0x80, +}; + struct Wkey { int cipher; @@ -61,6 +108,20 @@ uchar brsne[258]; }; +struct Wframe +{ + u8int fc[2]; + + u16int dur; + u16int seq; + u16int qos; + + uchar a1[Eaddrlen]; + uchar a2[Eaddrlen]; + uchar a3[Eaddrlen]; + uchar a4[Eaddrlen]; +}; + struct DMTE { uchar ip[16]; @@ -85,6 +146,7 @@ ulong watchdog; ulong lastauth; Ref txseq; + void (*transmit)(Wifi*, Wnode*, Block*); /* for searching */ @@ -102,25 +164,33 @@ DMAT dmat; }; -struct Wifipkt -{ - uchar fc[2]; - uchar dur[2]; - uchar a1[Eaddrlen]; - uchar a2[Eaddrlen]; - uchar a3[Eaddrlen]; - uchar seq[2]; - uchar a4[Eaddrlen]; -}; +#define get16(p) ((p)[0] | (p)[1] << 8) +#define get32(p) ((p)[0] | (p)[1] << 8 | (p)[2] << 16 | (p)[3] << 24) -enum { - Btimestamp = 1<<15, -}; +#define put16(p, v) (p)[0] = (v); (p)[1] = (v) >> 8 +#define put32(p, v) \ + (p)[0] = (v); \ + (p)[1] = (v) >> 8; \ + (p)[2] = (v) >> 16; \ + (p)[3] = (v) >> 24 +#define put64(p, v) \ + (p)[0] = (v); \ + (p)[1] = (v) >> 8; \ + (p)[2] = (v) >> 16; \ + (p)[3] = (v) >> 24; \ + (p)[4] = (v) >> 32; \ + (p)[5] = (v) >> 40; \ + (p)[6] = (v) >> 48; \ + (p)[7] = (v) >> 56 Wifi *wifiattach(Ether *ether, void (*transmit)(Wifi*, Wnode*, Block*)); + void wifiiq(Wifi*, Block*); -int wifihdrlen(Wifipkt*); void wifitxfail(Wifi*, Block*); + +int wifilen(Wframe *); +int wifipack(Wframe *, uchar *p); +int wifiunpack(Wframe *, uchar *p); long wifistat(Wifi*, void*, long, ulong); long wifictl(Wifi*, void*, long);