Back to home page

Quest Cross Reference

 
 

    


Warning, cross-references for /kernel/drivers/net/mac80211.c need to be fixed.

0001 /*                    The Quest Operating System
0002  *  Copyright (C) 2005-2010  Richard West, Boston University
0003  *
0004  *  This program is free software: you can redistribute it and/or modify
0005  *  it under the terms of the GNU General Public License as published by
0006  *  the Free Software Foundation, either version 3 of the License, or
0007  *  (at your option) any later version.
0008  *
0009  *  This program is distributed in the hope that it will be useful,
0010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
0011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0012  *  GNU General Public License for more details.
0013  *
0014  *  You should have received a copy of the GNU General Public License
0015  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
0016  */
0017 
0018 /* MAC 802.11 implements the link-layer protocol for 802.11-based
0019  * wireless networking. */
0020 
0021 #include <kernel.h>
0022 #include <drivers/net/ieee80211.h>
0023 #include <drivers/net/mac80211.h>
0024 #include <drivers/net/ieee80211_standard.h>
0025 #include <drivers/net/ethernet.h>
0026 #include <util/debug.h>
0027 #include <mem/pow2.h>
0028 #include <sched/sched.h>
0029 #include <arch/i386.h>
0030 #include <string.h>
0031 
0032 typedef uint8 ethaddr_t[ETH_ADDR_LEN];
0033 #define SSID "quest"
0034 ethaddr_t quest_bssid = {
0035   0xb6, 0x27, 0x07, 0xb6, 0x73, 0x7E
0036 };
0037 #define TIME_UNIT 1024          /* usec */
0038 
0039 #define DEBUG_MAC80211
0040 
0041 #ifdef DEBUG_MAC80211
0042 #define DLOG(fmt,...) DLOG_PREFIX("mac80211",fmt,##__VA_ARGS__)
0043 #else
0044 #define DLOG(fmt,...) ;
0045 #endif
0046 
0047 
0048 #define MAX_MACS 4
0049 
0050 struct ieee80211_local {
0051   struct ieee80211_hw hw;
0052   const struct ieee80211_ops *ops;
0053   ethernet_device ethdev;
0054   char *ssid;
0055   u64 prev_time_update;
0056   struct ieee80211_vif vif;
0057   char priv[0] ALIGNED(32);
0058 };
0059 typedef struct ieee80211_local local_t;
0060 
0061 static inline struct ieee80211_local *
0062 hw_to_local(struct ieee80211_hw *hw)
0063 {
0064   return container_of(hw, struct ieee80211_local, hw);
0065 }
0066 
0067 static inline struct ieee80211_hw *
0068 local_to_hw(struct ieee80211_local *local)
0069 {
0070   return &local->hw;
0071 }
0072 
0073 struct wiphy *
0074 wiphy_new (int sizeof_priv)
0075 {
0076   int sz = sizeof_priv + sizeof (struct wiphy);
0077   struct wiphy *wiphy;
0078   if (pow2_alloc (sz, (u8 **)&wiphy))
0079     return wiphy;
0080   else
0081     return NULL;
0082 }
0083 
0084 struct ieee80211_hw *
0085 ieee80211_alloc_hw (size_t priv_data_len,
0086                     const struct ieee80211_ops *ops)
0087 {
0088   local_t *local;
0089   struct wiphy *wiphy;
0090 
0091   wiphy = wiphy_new (priv_data_len + sizeof (local_t));
0092   if (!wiphy) return NULL;
0093 
0094   local = (void *)wiphy->priv;
0095 
0096   local->ops = ops;
0097 
0098   return &local->hw;
0099 }
0100 
0101 static int num_macs = 0;
0102 static local_t *hw_table[MAX_MACS];
0103 
0104 static struct ieee80211_channel channels[] = {
0105   { .center_freq = 2412 },
0106   { .center_freq = 2417 },
0107   { .center_freq = 2422 },
0108   { .center_freq = 2427 },
0109   { .center_freq = 2432 },
0110   { .center_freq = 2437 },
0111   { .center_freq = 2442 },
0112   { .center_freq = 2447 },
0113   { .center_freq = 2452 },
0114   { .center_freq = 2457 },
0115   { .center_freq = 2462 },
0116   { .center_freq = 2467 },
0117   { .center_freq = 2472 },
0118   { .center_freq = 2484 },
0119 };
0120 
0121 static uint32 beacon_stack[1024] ALIGNED(0x1000);
0122 static void beacon_thread (local_t *);
0123 local_t *hack_local = NULL;
0124 sint mac80211_tx (uint8* buffer, sint len);
0125 bool mac80211_get_hwaddr (uint8 addr[ETH_ADDR_LEN]);
0126 void mac80211_poll (void);
0127 static void init_tsc_ufreq (void);
0128 
0129 bool
0130 ieee80211_register_hw (struct ieee80211_hw *hw)
0131 {
0132   local_t *local = hw_to_local (hw);
0133   struct ieee80211_if_init_conf if_conf;
0134   struct ieee80211_tx_queue_params tx_q_p = {
0135     .txop = 94,
0136     .cw_min = 7,
0137     .cw_max = 15,
0138     .aifs = 2
0139   };
0140 
0141   if (num_macs < MAX_MACS) {
0142     hw_table[num_macs] = local;
0143     num_macs++;
0144   } else return FALSE;
0145 
0146   /* initialize things */
0147 
0148   DLOG ("register_hw: initialize");
0149   if (!local->ops->add_interface (hw, &if_conf))
0150     return FALSE;
0151 
0152   local->ops->conf_tx (hw, 0, &tx_q_p);
0153   local->ops->conf_tx (hw, 1, &tx_q_p);
0154   local->ops->conf_tx (hw, 2, &tx_q_p);
0155   local->ops->conf_tx (hw, 3, &tx_q_p);
0156 
0157   if (!local->ops->start (hw))
0158     return FALSE;
0159 
0160   hw->conf.channel = &channels[0];
0161 
0162   if (!local->ops->config (hw, 0))
0163     return FALSE;
0164 
0165   local->vif.bss_conf.bssid = quest_bssid;
0166   local->vif.bss_conf.timestamp = 0;
0167   local->vif.bss_conf.beacon_int = 0x64;       /* FIXME */
0168   local->vif.bss_conf.assoc_capability = 0x22; /* FIXME */
0169   local->ssid = SSID;
0170 
0171   local->ethdev.recv_func = NULL;
0172   local->ethdev.send_func = mac80211_tx;
0173   local->ethdev.get_hwaddr_func = mac80211_get_hwaddr;
0174   local->ethdev.poll_func = mac80211_poll;
0175   hack_local = local;           /* until I fix ethernet_device */
0176   if (!net_register_device (&local->ethdev)) {
0177     DLOG ("registration failed");
0178     return FALSE;
0179   }
0180 
0181   init_tsc_ufreq ();
0182 
0183   create_kernel_thread_args ((u32) beacon_thread, (u32) &beacon_stack[1023],
0184                              TRUE, 1, local);
0185 
0186   return TRUE;
0187 }
0188 
0189 /* ************************************************** */
0190 
0191 static u32 tsc_ufreq;           /* tsc per usec */
0192 extern u64 tsc_freq;
0193 
0194 static void
0195 init_tsc_ufreq (void)
0196 {
0197   u64 f;
0198   u32 f_hi, f_lo;
0199   u32 divisor = 1000000;
0200   f = tsc_freq;
0201 
0202   f_hi = (u32) (f >> 32);
0203   f_lo = (u32) (f & 0xFFFFFFFF);
0204   asm volatile ("div %1":"=a" (tsc_ufreq):"r" (divisor),"a" (f_lo),"d" (f_hi));
0205 
0206   DLOG ("tsc_ufreq=%d", tsc_ufreq);
0207 }
0208 
0209 static void
0210 update_timestamp (local_t *local)
0211 {
0212   u64 new_time_update, diff;
0213   RDTSC (new_time_update);
0214   if (local->prev_time_update == 0) {
0215     local->prev_time_update = new_time_update;
0216   } else {
0217     diff = new_time_update - local->prev_time_update;
0218     u32 f_hi, f_lo, udiff;
0219     f_hi = (u32) (diff >> 32);
0220     f_lo = (u32) (diff & 0xFFFFFFFF);
0221     asm volatile ("div %1":"=a" (udiff):"r" (tsc_ufreq),"a" (f_lo),"d" (f_hi));
0222     local->vif.bss_conf.timestamp += udiff;
0223   }
0224 }
0225 
0226 /* ************************************************** */
0227 
0228 #if 0
0229 static bool
0230 make_mgmt_pkt (u8 subtype, u8 control,
0231                ethaddr_t da, ethaddr_t sa, ethaddr_t bssid);
0232 #endif
0233 
0234 static u8 *insert_eid (u8 *ptr, u8 eid, u8 len, void *data)
0235 {
0236   *(ptr++) = eid;
0237   *(ptr++) = len;
0238   memcpy (ptr, data, len);
0239   return ptr + len;
0240 }
0241 
0242 static u32
0243 make_beacon_pkt (local_t *local,
0244                  ethaddr_t sa,
0245                  u8 *rates, u8 rates_len,
0246                  u8 chan,
0247                  u8 *buf, u32 len)
0248 {
0249   uint8 *bssid = local->vif.bss_conf.bssid;
0250   char *ssid = local->ssid;
0251   struct ieee80211_mgmt *m = (struct ieee80211_mgmt *)buf;
0252   int i;
0253   u8 *ptr, ssid_len = strlen (ssid);
0254   u32 req = ((u32) m->u.beacon.variable - (u32) m)
0255     + 2 + ssid_len + 2 + rates_len + 3;
0256 
0257   if (len < req) return req;
0258 
0259   m->frame_control =
0260     IEEE80211_FTYPE_MGMT |
0261     IEEE80211_STYPE_BEACON;
0262   m->duration = 0;               /* FIXME */
0263   for (i=0;i<ETH_ADDR_LEN;i++) {
0264     m->da[i] = 0xFF;
0265     m->sa[i] = sa[i];
0266     m->bssid[i] = bssid[i];
0267   }
0268   m->u.beacon.timestamp = local->vif.bss_conf.timestamp;
0269   m->u.beacon.beacon_int = local->vif.bss_conf.beacon_int;
0270   m->u.beacon.capab_info = local->vif.bss_conf.assoc_capability;
0271   ptr = m->u.beacon.variable;
0272   ptr = insert_eid (ptr, WLAN_EID_SSID, ssid_len, ssid);
0273   ptr = insert_eid (ptr, WLAN_EID_SUPP_RATES, rates_len, rates);
0274   ptr = insert_eid (ptr, WLAN_EID_DS_PARAMS, 1, &chan);
0275 
0276   return req;
0277 }
0278 
0279 static u32
0280 make_probe_req_pkt (ethaddr_t sa, ethaddr_t bssid,
0281                     char *ssid,
0282                     u8 *rates, u8 rates_len,
0283                     u8 *buf, u32 len)
0284 {
0285   struct ieee80211_mgmt *m = (struct ieee80211_mgmt *)buf;
0286   int i;
0287   u8 *ptr, ssid_len = strlen (ssid);
0288   u32 req = ((u32) m->u.probe_req.variable - (u32) m)
0289     + 2 + ssid_len + 2 + rates_len;
0290 
0291   if (len < req) return req;
0292 
0293   m->frame_control =
0294     IEEE80211_FTYPE_MGMT |
0295     IEEE80211_STYPE_PROBE_REQ;
0296   m->duration = 0x013A;         /* FIXME */
0297   for (i=0;i<ETH_ADDR_LEN;i++) {
0298     m->da[i] = 0xFF;
0299     m->sa[i] = sa[i];
0300     m->bssid[i] = bssid[i];
0301   }
0302   m->seq_ctrl = 0x4640;         /* FIXME */
0303   ptr = m->u.probe_req.variable;
0304   ptr = insert_eid (ptr, WLAN_EID_SSID, ssid_len, ssid);
0305   ptr = insert_eid (ptr, WLAN_EID_SUPP_RATES, rates_len, rates);
0306 
0307   return req;
0308 }
0309 
0310 static u32
0311 make_ack_pkt (ethaddr_t ra, u8 *buf, u32 len)
0312 {
0313   struct ieee80211_hdr *h = (struct ieee80211_hdr *) buf;
0314   int i;
0315   if (len < 10) return 10;
0316   h->frame_control =
0317     IEEE80211_FTYPE_CTL |
0318     IEEE80211_STYPE_ACK;
0319   h->duration_id = 0;
0320   for (i=0; i<ETH_ADDR_LEN; i++)
0321     h->addr1[i] = ra[i];
0322   return 10;
0323 }
0324 
0325 static uint8 rates[8] = {
0326   0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24,
0327 };
0328 
0329 static void
0330 tx_beacon (struct ieee80211_local *local)
0331 {
0332   uint8 pkt[128];
0333   ethaddr_t sa = {
0334     0x00, 0x1E, 0x2A, 0x42, 0x73, 0x7E
0335   };
0336   u32 len = make_beacon_pkt (local, sa, rates, 8, 1, pkt, 128);
0337   if (len > 128) { DLOG ("make_beacon_pkt wants %d bytes", len); return; }
0338   struct sk_buff skb = {
0339     .data = pkt,
0340     .len = len,
0341   };
0342   local->ops->tx (local_to_hw (local), &skb);
0343 }
0344 
0345 static void
0346 beacon_thread (local_t *local)
0347 {
0348   DLOG ("beacon: hello from 0x%x", str ());
0349   for (;;) {
0350     sched_usleep (1000000);
0351     DLOG ("sending beacon timestamp=0x%.08X %.08X",
0352           (u32) (local->vif.bss_conf.timestamp >> 32),
0353           (u32) local->vif.bss_conf.timestamp);
0354     tx_beacon (local);
0355   }
0356 }
0357 
0358 static bool
0359 find_eid (struct ieee80211_mgmt *m, s32 len, u8 eid,
0360           u8 *output, u8 max_len, u8 *act_len)
0361 {
0362   //char *what;
0363   uint8 *ptr;
0364   u32 hdr_len;
0365 #define CASE(x)                                         \
0366   if (ieee80211_is_##x (m->frame_control)) {            \
0367     ptr = m->u.x.variable;                              \
0368     hdr_len = ((u32) m->u.x.variable) - ((u32) m);      \
0369   }
0370   CASE(beacon);
0371   CASE(probe_req);
0372   CASE(probe_resp);
0373   CASE(assoc_req);
0374   CASE(assoc_resp);
0375 #undef CASE
0376   //DLOG ("find_eid: eid=%d len=%d hdr_len=%d what=%s", eid, len, hdr_len, what);
0377   len -= hdr_len;
0378   for (;len > 0;) {
0379     //DLOG ("len=%d ptr[0]=%d ptr[1]=%d", len, ptr[0], ptr[1]);
0380     if (ptr[0] == eid) {
0381       if (ptr[1] > max_len) {
0382         return FALSE;
0383       } if (ptr[1] + 2 > len) {
0384         return FALSE;
0385       } else {
0386         memcpy (output, &ptr[2], ptr[1]);
0387         *act_len = ptr[1];
0388         return TRUE;
0389       }
0390     }
0391     len -= (ptr[1] + 2);
0392     ptr += (ptr[1] + 2);
0393   }
0394   return FALSE;
0395 }
0396 
0397 static void
0398 tx_probe_resp (struct ieee80211_local *local)
0399 {
0400   uint8 pkt[] = {
0401     0x50, 0x00, 0x3A, 0x01,             /* PROBE RESPONSE */
0402     0x00, 0x23, 0x4D, 0xAF, 0x00, 0x3C, /* DA */
0403 
0404     //0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0405     //0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0406     0x00, 0x1E, 0x2A, 0x42, 0x73, 0x7E, /* SA */
0407     0xb6, 0x27, 0x07, 0xb6, 0x73, 0x7E, /* BSS ID */
0408 
0409     0x20, 0x00,
0410 
0411     0x8E, 0x91, 0x42, 0x11, 0x67, 0x00, 0x00, 0x00, /* timestamp */
0412     0x64, 0x00,                                     /* interval */
0413     0x01, 0x04,                                     /* capability */
0414 
0415     0x00, 0x05, 'q', 'u', 'e', 's', 't',
0416 
0417     0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x0C, 0x12, 0x18, 0x24
0418   };
0419   struct sk_buff skb = {
0420     .data = pkt,
0421     .len = sizeof (pkt)
0422   };
0423   struct ieee80211_mgmt *m = (struct ieee80211_mgmt *) pkt;
0424   m->u.probe_resp.timestamp = __cpu_to_le64 (local->vif.bss_conf.timestamp);
0425   local->ops->tx (local_to_hw (local), &skb);
0426 }
0427 
0428 /*
0429 
0430 18:16:40.153738 314us arp who-has 169.254.237.67 tell 0.0.0.0
0431         0x0000:  0800 3a01 ffff ffff ffff 0023 4daf 003c
0432         0x0010:  b627 07b6 737e 4002 aaaa 0300 0000 0806
0433         0x0020:  0001 0800 0604 0001 0023 4daf 003c 0000
0434         0x0030:  0000 0000 0000 0000 a9fe ed43
0435 
0436 18:16:40.181611 314us IP6 (hlim 1, next-header: Options (0), length: 36) fe80::e196:3567:8822:ed43 > ff02::16: HBH (rtalert: 0x0000) (padn)[icmp6 sum ok] ICMP6, multicast listener report v2, length 28, 1 group record(s) [gaddr ff02::1:3 to_ex { }]
0437         0x0000:  0800 3a01 3333 0000 0016 0023 4daf 003c
0438         0x0010:  b627 07b6 737e 5002 aaaa 0300 0000 86dd
0439         0x0020:  6000 0000 0024 0001 fe80 0000 0000 0000
0440         0x0030:  e196 3567 8822 ed43 ff02 0000 0000 0000
0441         0x0040:  0000 0000 0000 0016 3a00 0502 0000 0100
0442         0x0050:  8f00 e3a2 0000 0001 0400 0000 ff02 0000
0443         0x0060:  0000 0000 0000 0000 0001 0003
0444 
0445 18:16:40.184486 314us IP (tos 0x0, ttl   1, id 10136, offset 0, flags [none], proto: IGMP (2), length: 40, options ( RA (148) len 4 )) 169.254.237.67 > IGMP.MCAST.NET: igmp v3 report, 1 group record(s) [gaddr 224.0.0.252 to_ex { }]
0446         0x0000:  0800 3a01 0100 5e00 0016 0023 4daf 003c
0447         0x0010:  b627 07b6 737e 6002 aaaa 0300 0000 0800
0448         0x0020:  4600 0028 2798 0000 0102 85df a9fe ed43
0449         0x0030:  e000 0016 9404 0000 2200 f901 0000 0001
0450         0x0040:  0400 0000 e000 00fc
0451 
0452 18:16:40.196611 314us IP6 (hlim 1, next-header: UDP (17), length: 32) fe80::e196:3567:8822:ed43.49845 > ff02::1:3.hostmon: [udp sum ok] UDP, length 24
0453         0x0000:  0800 3a01 3333 0001 0003 0023 4daf 003c
0454         0x0010:  b627 07b6 737e 7002 aaaa 0300 0000 86dd
0455         0x0020:  6000 0000 0020 1101 fe80 0000 0000 0000
0456         0x0030:  e196 3567 8822 ed43 ff02 0000 0000 0000
0457         0x0040:  0000 0000 0001 0003 c2b5 14eb 0020 3ecf
0458         0x0050:  1115 0000 0001 0000 0000 0000 0663 686f
0459         0x0060:  7069 6e00 00ff 0001
0460 
0461 18:16:40.197611 314us IP (tos 0x0, ttl   1, id 10137, offset 0, flags [none], proto: UDP (17), length: 52) 169.254.237.67.55152 > 224.0.0.252.hostmon: [udp sum ok] UDP, length 24
0462         0x0000:  0800 3a01 0100 5e00 00fc 0023 4daf 003c
0463         0x0010:  b627 07b6 737e 8002 aaaa 0300 0000 0800
0464         0x0020:  4500 0034 2799 0000 0111 19e2 a9fe ed43
0465         0x0030:  e000 00fc d770 14eb 0020 3bc1 1115 0000
0466         0x0040:  0001 0000 0000 0000 0663 686f 7069 6e00
0467         0x0050:  00ff 0001
0468 
0469 
0470 18:33:49.213779 314us arp who-has 169.254.237.1 tell 169.254.237.67
0471         0x0000:  0800 3a01 ffff ffff ffff 0023 4daf 003c
0472         0x0010:  b627 07b6 737e 9094 aaaa 0300 0000 0806
0473         0x0020:  0001 0800 0604 0001 0023 4daf 003c a9fe
0474         0x0030:  ed43 0000 0000 0000 a9fe ed01
0475 
0476  */
0477 
0478 static void
0479 debug_buf (char *prefix, uint8 *buf, u32 len)
0480 {
0481   s32 i, j;
0482 
0483   for (i=0;i<len;i+=8) {
0484     logger_printf ("%s: ", prefix);
0485     for (j=0;j<8;j++) {
0486       if (i+j >= len) break;
0487       logger_printf ("%.02X ", buf[i+j]);
0488     }
0489     logger_printf ("\n");
0490   }
0491 }
0492 
0493 extern void
0494 ieee80211_rx (struct ieee80211_hw *hw, struct sk_buff *skb)
0495 {
0496   local_t *local = hw_to_local (hw);
0497   struct ieee80211_hdr *hdr;
0498   char ssid[IEEE80211_MAX_SSID_LEN+1];
0499   u8 act_len;
0500   u8 pkt[128];
0501   u32 len, i;
0502   ethaddr_t sa = {
0503     0x00, 0x1E, 0x2A, 0x42, 0x73, 0x7E
0504   };
0505   ethaddr_t bssid = {
0506     0xB6, 0x27, 0x07, 0xB6, 0x73, 0x7E
0507   };
0508 
0509   update_timestamp (local);
0510 
0511   hdr = (struct ieee80211_hdr *)skb->data;
0512 
0513   if (ieee80211_is_mgmt (hdr->frame_control)) {
0514     struct ieee80211_mgmt *m = (struct ieee80211_mgmt *)skb->data;
0515     if (ieee80211_is_beacon (hdr->frame_control)) {
0516       if (find_eid (m, skb->len, WLAN_EID_SSID,
0517                     (u8 *)ssid, IEEE80211_MAX_SSID_LEN, &act_len)) {
0518         ssid[act_len] = 0;
0519         //DLOG ("beacon %s", ssid);
0520         if (strncmp (SSID, ssid, act_len) == 0) {
0521           local->vif.bss_conf.timestamp = m->u.beacon.timestamp + TIME_UNIT;
0522           local->vif.bss_conf.beacon_int = m->u.beacon.beacon_int;
0523           local->vif.bss_conf.assoc_capability = m->u.beacon.capab_info;
0524           DLOG ("beacon %s; synchronizing beacon_int=0x%x capab=0x%x",
0525                 ssid, local->vif.bss_conf.beacon_int,
0526                 local->vif.bss_conf.assoc_capability);
0527           DLOG ("  new timestamp=0x%.08X %.08X",
0528                 (u32) (local->vif.bss_conf.timestamp >> 32),
0529                 (u32) local->vif.bss_conf.timestamp);
0530         }
0531 #if 0
0532         len = make_probe_req_pkt (sa, m->bssid, ssid, rates, 8,
0533                                   pkt, sizeof (pkt));
0534         if (len <= sizeof (pkt)) {
0535           struct sk_buff skb = {
0536             .data = pkt,
0537             .len = len,
0538           };
0539           local->ops->tx (local_to_hw (local), &skb);
0540         }
0541 #endif
0542       } else {
0543         //DLOG ("beacon, no SSID");
0544       }
0545     } else if (ieee80211_is_probe_req (hdr->frame_control)) {
0546       if (find_eid (m, skb->len, WLAN_EID_SSID,
0547                     (u8 *)ssid, IEEE80211_MAX_SSID_LEN, &act_len)) {
0548         ssid[act_len] = 0;
0549         DLOG ("probe_req %s", ssid);
0550         if (strncmp (SSID, ssid, act_len) == 0) {
0551           tx_probe_resp (local);
0552         }
0553       } else {
0554         DLOG ("probe_req, no SSID");
0555       }
0556     } else if (ieee80211_is_probe_resp (hdr->frame_control)) {
0557       if (find_eid (m, skb->len, WLAN_EID_SSID,
0558                     (u8 *)ssid, IEEE80211_MAX_SSID_LEN, &act_len)) {
0559         ssid[act_len] = 0;
0560         DLOG ("probe_resp %s", ssid);
0561       } else {
0562         DLOG ("probe_resp, no SSID");
0563       }
0564       len = make_ack_pkt (m->sa, pkt, sizeof (pkt));
0565       if (len <= sizeof (pkt)) {
0566         struct sk_buff skb = {
0567           .data = pkt,
0568           .len = len,
0569         };
0570         local->ops->tx (local_to_hw (local), &skb);
0571       }
0572     }
0573   } else if (ieee80211_is_data (hdr->frame_control)) {
0574     if ((hdr->seq_ctrl & 0xF) == 0) {
0575       DLOG ("data for %.02X:%.02X:%.02X:%.02X:%.02X:%.02X",
0576             hdr->addr1[0], hdr->addr1[1], hdr->addr1[2],
0577             hdr->addr1[3], hdr->addr1[4], hdr->addr1[5]);
0578       for (i=0; i<ETH_ADDR_LEN; i++)
0579         if (hdr->addr3[i] != bssid[i])
0580           return;
0581 #ifdef DEBUG_MAC80211
0582       debug_buf ("mac80211: data", skb->data, skb->len);
0583 #endif
0584       /* hack in an "ethernet frame" */
0585       memcpy (skb->data + 18, skb->data + 4, ETH_ADDR_LEN);
0586       memcpy (skb->data + 24, skb->data + 10, ETH_ADDR_LEN);
0587       local->ethdev.recv_func (&local->ethdev,
0588                                skb->data + 18,
0589                                skb->len - 18);
0590     }
0591   } else if (ieee80211_is_ctl (hdr->frame_control)) {
0592     if (ieee80211_is_ack (hdr->frame_control)) {
0593       DLOG ("ack");
0594     }
0595   }
0596 }
0597 
0598 
0599 static u8 tx_buf[2500];
0600 
0601 sint
0602 mac80211_tx (uint8* buffer, sint len)
0603 {
0604   struct ieee80211_hw *hw = local_to_hw (hack_local);
0605   bool is_arp=FALSE;
0606   u8 hdr[] = {
0607     0x08, 0x00, 0x3a, 0x01,
0608     0x00, 0x23, 0x4d, 0xaf, 0x00, 0x3c,
0609     0x00, 0x1e, 0x2a, 0x42, 0x73, 0x7e,
0610     0xb6, 0x27, 0x07, 0xb6, 0x73, 0x7e,
0611     0x90, 0x94,
0612     /* RFC 1042 SNAP header */
0613     0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00,
0614     /* ARP */
0615     //0x08, 0x06
0616     /* IP */
0617     0x08, 0x00
0618   };
0619 
0620   /* skip ethernet link layer header */
0621   len -= 14;
0622   buffer += 14;
0623 
0624   DLOG ("mac80211_tx: %p %d bytes: %x %x", buffer, len, buffer[0], buffer[1]);
0625   if (buffer[0] == 0 && buffer[1] == 1)
0626     is_arp = TRUE;              /* guess ARP */
0627 
0628   struct sk_buff skb = {
0629     .data = tx_buf,
0630     .len = len + sizeof (hdr)
0631   };
0632   memcpy (tx_buf, hdr, sizeof (hdr));
0633   memcpy (tx_buf + sizeof (hdr), buffer, len);
0634   if (is_arp) tx_buf[sizeof (hdr) - 1] = 6;
0635 
0636   return hack_local->ops->tx (hw, &skb);
0637 }
0638 
0639 bool
0640 mac80211_get_hwaddr (uint8 addr[ETH_ADDR_LEN])
0641 {
0642   int i;
0643   /* FIXME */
0644   ethaddr_t sa = {
0645     0x00, 0x1E, 0x2A, 0x42, 0x73, 0x7E
0646   };
0647 
0648   for (i=0; i<ETH_ADDR_LEN; i++)
0649     addr[i] = sa[i];
0650   return TRUE;
0651 }
0652 
0653 void
0654 mac80211_poll (void)
0655 {
0656 }
0657 
0658 u16
0659 ieee80211_calc_duration (u32 len, s16 rate)
0660 {
0661   u16 duration;
0662   u16 drift;
0663   switch (rate) {
0664   case 0: //1mbps
0665     duration = ((len+4)<<4) / 0x2;
0666     drift = ((len+4)<<4) % 0x2;
0667     if (drift == 0) break;
0668     duration++;
0669     break;
0670 
0671   case 1: //2mbps
0672     duration = ((len+4)<<4) / 0x4;
0673     drift = ((len+4)<<4) % 0x4;
0674     if (drift == 0) break;
0675     duration++;
0676     break;
0677 
0678   case 2: //5.5mbps
0679     duration = ((len+4)<<4) / 0xb;
0680     drift = ((len+4)<<4) % 0xb;
0681     if (drift == 0) break;
0682     duration++;
0683     break;
0684 
0685   default:
0686   case 3: //11mbps                         
0687     duration = ((len+4)<<4) / 0x16;
0688     drift = ((len+4)<<4) % 0x16;
0689     if (drift == 0) break;
0690     duration++;
0691     break;
0692   }
0693 
0694   return duration;
0695 }
0696 
0697 
0698 
0699 /*
0700  * Local Variables:
0701  * indent-tabs-mode: nil
0702  * mode: C
0703  * c-file-style: "gnu"
0704  * c-basic-offset: 2
0705  * End:
0706  */
0707 
0708 /* vi: set et sw=2 sts=2: */