typedef struct Wkey Wkey;
typedef struct Wnode Wnode;
typedef struct Wifi Wifi;
typedef struct Wifipkt Wifipkt;
typedef struct DMAT DMAT;
typedef struct DMTE DMTE;

enum {
       Essidlen = 32,
};

/* cipher */
enum {
       TKIP    = 1,
       CCMP    = 2,
};

struct Wkey
{
       int             cipher;
       int             len;
       uvlong          tsc;
       uchar           key[];
};

struct Wnode
{
       uchar   bssid[Eaddrlen];
       char    ssid[Essidlen+2];

       char    *status;

       int     rsnelen;
       uchar   rsne[258];
       Wkey    *txkey[1];
       Wkey    *rxkey[5];

       int     aid;            /* association id */
       ulong   lastsend;
       ulong   lastseen;

       uchar   *minrate;       /* pointers into wifi->rates */
       uchar   *maxrate;
       uchar   *actrate;

       ulong   validrates;     /* bitmap on wifi->rates */
       ulong   basicrates;

       ulong   txcount;        /* statistics for rate adaption */
       ulong   txerror;

       /* stuff from beacon */
       int     ival;
       int     cap;
       int     channel;
       int     brsnelen;
       uchar   brsne[258];
};

struct DMTE
{
       uchar   ip[16];
       uchar   mac[6];
       uchar   valid;
};

struct DMAT
{
       DMTE    tab[127];       /* prime */
       uvlong  map;
};

struct Wifi
{
       Ether   *ether;

       int     debug;

       RWlock  crypt;
       Queue   *iq;
       ulong   watchdog;
       ulong   lastauth;
       Ref     txseq;
       void    (*transmit)(Wifi*, Wnode*, Block*);

       /* for searching */
       uchar   bssid[Eaddrlen];
       char    essid[Essidlen+2];

       /* supported data rates by hardware */
       uchar   *rates;

       /* effective base station */
       Wnode   *bss;

       Wnode   node[32];

       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];
};

Wifi *wifiattach(Ether *ether, void (*transmit)(Wifi*, Wnode*, Block*));
void wifiiq(Wifi*, Block*);
int wifihdrlen(Wifipkt*);
void wifitxfail(Wifi*, Block*);

long wifistat(Wifi*, void*, long, ulong);
long wifictl(Wifi*, void*, long);
void wificfg(Wifi*, char*);