URI:
       tp80211.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tp80211.c (6470B)
       ---
            1 /*
            2  * IEEE 802.11.
            3  */
            4 
            5 #include <u.h>
            6 #include <libc.h>
            7 #include <ip.h>
            8 #include "dat.h"
            9 #include "protos.h"
           10 
           11 enum
           12 {
           13         Tmgmt = 0,
           14         Tctl,
           15         Tdata,
           16 
           17         CtlPoll = 0xA,
           18         CtlRts,
           19         CtlCts,
           20         CtlAck,
           21         CtlCfEnd,
           22         CtlCfEndAck,
           23 
           24         Data = 0,
           25         DataCfAck,
           26         DataCfPoll,
           27         DataCfAckPoll,
           28         Nodata,
           29         NodataCfAck,
           30         NodataCfPoll,
           31         NodataCfAckPoll,
           32 
           33         FlagTods = 0x1,
           34         FlagFromds = 0x2,
           35         FlagMoreflag = 0x4,
           36         FlagRetry = 0x8,
           37         FlagPowerMgmt = 0x10,
           38         FlagMoreData = 0x20,
           39         FlagWep = 0x40,
           40         FlagOrder = 0x80,
           41 
           42         ProtoNone = 0,
           43         ProtoLlc,
           44 };
           45 
           46 static Mux p_mux[] =
           47 {
           48         { "llc", ProtoLlc },
           49         { 0 }
           50 };
           51 
           52 typedef struct Hdr Hdr;
           53 struct Hdr
           54 {
           55         uchar vers;
           56         uchar type;
           57         uchar subtype;
           58         uchar flags;
           59         ushort dur;
           60         uchar aid;
           61         uchar ra[6];
           62         uchar ta[6];
           63         uchar bssid[6];
           64         uchar sa[6];
           65         uchar da[6];
           66         ushort seq;
           67         int proto;
           68         int hdrlen;
           69 };
           70 
           71 static int
           72 unpackhdr(uchar *p, uchar *ep, Hdr *h)
           73 {
           74         if(p+2 > ep)
           75                 return -1;
           76         h->vers = p[0]&3;
           77         if(h->vers != 0){
           78                 h->hdrlen = 2;
           79                 return -1;
           80         }
           81         h->type = (p[0]>>2)&3;
           82         h->subtype = (p[0]>>4)&15;
           83         h->flags = p[1];
           84         h->hdrlen = 2;
           85 
           86         if(h->vers != 0)
           87                 return 0;
           88 
           89         switch(h->type){
           90         case Tmgmt:
           91                 // fc dur da sa bssid seq
           92                 if(p+2+2+6+6+6+2 > ep)
           93                         return -1;
           94                 h->hdrlen = 24;
           95                 h->dur = LittleS(p+2);
           96                 memmove(h->da, p+4, 6);
           97                 memmove(h->sa, p+10, 6);
           98                 memmove(h->bssid, p+16, 6);
           99                 h->seq = LittleS(p+22);
          100                 break;
          101 
          102         case Tctl:
          103                 switch(h->subtype){
          104                 case CtlPoll:
          105                         // fc aid bssid ta
          106                         if(p+2+2+6+6 > ep)
          107                                 return -1;
          108                         h->hdrlen = 16;
          109                         h->aid = LittleS(p+2);
          110                         memmove(h->bssid, p+4, 6);
          111                         memmove(h->ta, p+10, 6);
          112                         break;
          113 
          114                 case CtlRts:
          115                         // fc dur ra ta
          116                         if(p+2+2+6+6 > ep)
          117                                 return -1;
          118                         h->hdrlen = 16;
          119                         h->dur = LittleS(p+2);
          120                         memmove(h->ra, p+4, 6);
          121                         memmove(h->ta, p+10, 6);
          122                         break;
          123 
          124                 case CtlCts:
          125                 case CtlAck:
          126                         // fc dur ra
          127                         if(p+2+2+6 > ep)
          128                                 return -1;
          129                         h->hdrlen = 10;
          130                         h->dur = LittleS(p+2);
          131                         memmove(h->ra, p+4, 6);
          132                         break;
          133 
          134                 case CtlCfEnd:
          135                 case CtlCfEndAck:
          136                         // fc dur ra bssid
          137                         if(p+2+2+6+6 > ep)
          138                                 return -1;
          139                         h->hdrlen = 16;
          140                         h->dur = LittleS(p+2);
          141                         memmove(h->ra, p+4, 6);
          142                         memmove(h->bssid, p+10, 6);
          143                         break;
          144                 }
          145                 break;
          146 
          147         case Tdata:
          148                 if(p+24 > ep)
          149                         return -1;
          150                 h->hdrlen = 24;
          151                 h->dur = LittleS(p+2);        // ??? maybe
          152                 // Also, what is at p+22?
          153 
          154                 switch(h->flags&(FlagFromds|FlagTods)){
          155                 case 0:
          156                         memmove(h->da, p+4, 6);
          157                         memmove(h->sa, p+10, 6);
          158                         memmove(h->bssid, p+16, 6);
          159                         break;
          160                 case FlagFromds:
          161                         memmove(h->da, p+4, 6);
          162                         memmove(h->bssid, p+10, 6);
          163                         memmove(h->sa, p+16, 6);
          164                         break;
          165                 case FlagTods:
          166                         memmove(h->bssid, p+4, 6);
          167                         memmove(h->sa, p+10, 6);
          168                         memmove(h->da, p+16, 6);
          169                         break;
          170                 case FlagFromds|FlagTods:
          171                         if(p+30 > ep)
          172                                 return -1;
          173                         h->hdrlen = 30;
          174                         memmove(h->ra, p+4, 6);
          175                         memmove(h->ta, p+10, 6);
          176                         memmove(h->da, p+16, 6);
          177                         memmove(h->sa, p+24, 6);        // 24 sic
          178                         break;
          179                 }
          180                 p += h->hdrlen;
          181                 h->proto = ProtoNone;
          182                 if(!(h->flags&FlagWep))
          183                         h->proto = ProtoLlc;
          184                 break;
          185         }
          186         return 0;
          187 }
          188 
          189 enum
          190 {
          191         Os,
          192         Od,
          193         Ot,
          194         Or,
          195         Obssid,
          196         Oa,
          197         Opr,
          198 };
          199 
          200 static Field p_fields[] =
          201 {
          202         { "s",        Fether,        Os,        "source address" },
          203         { "d",        Fether,        Od,        "destination address" },
          204         { "t",        Fether,        Ot,        "transmit address" },
          205         { "r",        Fether,        Or,        "receive address" },
          206         { "bssid", Fether,        Obssid, "bssid address" },
          207         { "a",        Fether,        Oa,        "any address" },
          208         { "sd",        Fether,        Oa,        "source|destination address" },
          209         { 0 }
          210 };
          211 
          212 static void
          213 p_compile(Filter *f)
          214 {
          215         Mux *m;
          216 
          217         if(f->op == '='){
          218                 compile_cmp(p80211.name, f, p_fields);
          219                 return;
          220         }
          221         if(strcmp(f->s, "mgmt") == 0){
          222                 f->pr = &p80211;
          223                 f->ulv = Tmgmt;
          224                 f->subop = Ot;
          225                 return;
          226         }
          227         if(strcmp(f->s, "ctl") == 0){
          228                 f->pr = &p80211;
          229                 f->ulv = Tctl;
          230                 f->subop = Ot;
          231                 return;
          232         }
          233         if(strcmp(f->s, "data") == 0){
          234                 f->pr = &p80211;
          235                 f->ulv = Tdata;
          236                 f->subop = Ot;
          237                 return;
          238         }
          239         for(m = p_mux; m->name != nil; m++){
          240                 if(strcmp(f->s, m->name) == 0){
          241                         f->pr = m->pr;
          242                         f->ulv = m->val;
          243                         f->subop = Opr;
          244                         return;
          245                 }
          246         }
          247         sysfatal("unknown 802.11 field or protocol: %s", f->s);
          248 }
          249 
          250 static int
          251 p_filter(Filter *f, Msg *m)
          252 {
          253         Hdr h;
          254 
          255         memset(&h, 0, sizeof h);
          256         if(unpackhdr(m->ps, m->pe, &h) < 0)
          257                 return 0;
          258         m->ps += h.hdrlen;
          259 
          260         switch(f->subop){
          261         case Os:
          262                 return memcmp(h.sa, f->a, 6) == 0;
          263         case Od:
          264                 return memcmp(h.da, f->a, 6) == 0;
          265         case Ot:
          266                 return memcmp(h.ta, f->a, 6) == 0;
          267         case Or:
          268                 return memcmp(h.ra, f->a, 6) == 0;
          269         case Obssid:
          270                 return memcmp(h.bssid, f->a, 6) == 0;
          271         case Oa:
          272                 return memcmp(h.sa, f->a, 6) == 0
          273                         || memcmp(h.da, f->a, 6) == 0
          274                         || memcmp(h.ta, f->a, 6) == 0
          275                         || memcmp(h.ra, f->a, 6) == 0
          276                         || memcmp(h.bssid, f->a, 6) == 0;
          277         case Opr:
          278                 return h.proto == f->ulv;
          279         }
          280         return 0;
          281 }
          282 
          283 static int
          284 p_seprint(Msg *m)
          285 {
          286         Hdr h;
          287 
          288         memset(&h, 0, sizeof h);
          289         if(unpackhdr(m->ps, m->pe, &h) < 0)
          290                 return -1;
          291 
          292         m->pr = &dump;
          293         m->p = seprint(m->p, m->e, "fc=%02x flags=%02x ", m->ps[0], m->ps[1]);
          294         switch(h.type){
          295         case Tmgmt:
          296                 m->p = seprint(m->p, m->e, "mgmt dur=%d d=%E s=%E bssid=%E seq=%d",
          297                         h.dur, h.da, h.sa, h.bssid, h.seq);
          298                 break;
          299         case Tctl:
          300                 switch(h.subtype){
          301                 case CtlPoll:
          302                         m->p = seprint(m->p, m->e, "ctl poll aid=%d bssid=%E t=%E",
          303                                 h.aid, h.bssid, h.ta);
          304                         break;
          305                 case CtlRts:
          306                         m->p = seprint(m->p, m->e, "ctl rts dur=%d r=%E t=%E",
          307                                 h.dur, h.ra, h.ta);
          308                         break;
          309                 case CtlCts:
          310                         m->p = seprint(m->p, m->e, "ctl cts dur=%d r=%E",
          311                                 h.dur, h.ra);
          312                         break;
          313                 case CtlAck:
          314                         m->p = seprint(m->p, m->e, "ctl ack dur=%d r=%E",
          315                                 h.dur, h.ra);
          316                         break;
          317                 case CtlCfEnd:
          318                         m->p = seprint(m->p, m->e, "ctl cf end dur=%d r=%E bssid=%E",
          319                                 h.dur, h.ra, h.bssid);
          320                         break;
          321                 case CtlCfEndAck:
          322                         m->p = seprint(m->p, m->e, "ctl cf end ack dur=%d r=%E bssid=%E",
          323                                 h.dur, h.ra, h.bssid);
          324                         break;
          325                 default:
          326                         m->p = seprint(m->p, m->e, "ctl %.*H", m->ps, h.hdrlen);
          327                         break;
          328                 }
          329                 break;
          330         case Tdata:
          331                 switch(h.flags&(FlagFromds|FlagTods)){
          332                 case 0:
          333                         m->p = seprint(m->p, m->e, "data d=%E s=%E bssid=%E",
          334                                 h.da, h.sa, h.bssid);
          335                         break;
          336                 case FlagFromds:
          337                         m->p = seprint(m->p, m->e, "data fds d=%E bssid=%E s=%E",
          338                                 h.da, h.bssid, h.sa);
          339                         break;
          340                 case FlagTods:
          341                         m->p = seprint(m->p, m->e, "data tds bssid=%E s=%E d=%E",
          342                                 h.bssid, h.sa, h.da);
          343                         break;
          344                 case FlagFromds|FlagTods:
          345                         m->p = seprint(m->p, m->e, "data fds tds r=%E t=%E d=%E s=%E",
          346                                 h.ra, h.ta, h.da, h.sa);
          347                         break;
          348                 }
          349                 if(!(h.flags&FlagWep))
          350                         m->pr = &llc;
          351                 break;
          352         }
          353         m->ps += h.hdrlen;
          354         return 0;
          355 }
          356 
          357 Proto p80211 =
          358 {
          359         "802.11",
          360         p_compile,
          361         p_filter,
          362         p_seprint,
          363         p_mux,
          364         nil,
          365         nil,
          366         defaultframer
          367 };