[802.11] The 802.11 MAC layer, second big commit
[people/oremanj/gpxe.git] / src / net / net80211.c
1 /*
2  * The gPXE 802.11 MAC layer.
3  *
4  * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of the
9  * License, or any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21 FILE_LICENCE ( GPL2_OR_LATER );
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <byteswap.h>
26 #include <stdlib.h>
27 #include <gpxe/settings.h>
28 #include <gpxe/if_arp.h>
29 #include <gpxe/ethernet.h>
30 #include <gpxe/ieee80211.h>
31 #include <gpxe/netdevice.h>
32 #include <gpxe/net80211.h>
33 #include <gpxe/timer.h>
34 #include <errno.h>
35
36 /** List of 802.11 devices */
37 static struct list_head net80211_devices = LIST_HEAD_INIT(net80211_devices);
38
39 /** The network name to associate with
40  *
41  * If this is blank, we scan for all entworks and use the one with the
42  * greatest signal strength.
43  */
44 struct setting net80211_ssid_setting __setting = {
45         .name = "ssid",
46         .description = "802.11 SSID (network name)",
47         .type = &setting_type_string,
48 };
49
50 /** Whether to use active scanning
51  *
52  * In order to associate with a hidden SSID, it's necessary to use an
53  * active scan (send probe packets). If this setting is nonzero, an
54  * active scan on the 2.4GHz band will be used to associate.
55  */
56 struct setting net80211_hidden_setting __setting = {
57         .name = "hidden",
58         .description = "Associate with 802.11 hidden network",
59         .type = &setting_type_int8,
60 };
61
62 /** Set of device operations that does nothing */
63 static struct net80211_device_operations net80211_null_ops;
64
65 /** Single-step the association process. */
66 void net80211_step_associate ( struct process *proc );
67
68 /** Structure for keeping a queue of saved management packet signal
69     strengths in parallel to the saved iobs. */
70 struct net80211_rx_info
71 {
72         int signal;
73         struct list_head list;
74 };
75
76 /* ---------- net_device wrapper ---------- */
77
78 int net80211_netdev_open(struct net_device *netdev) 
79 {
80         struct net80211_device *dev = netdev->priv;
81
82         if (dev->op->open)
83                 return dev->op->open(dev);
84
85         net80211_autoassociate(dev);
86         return 0;
87 }
88
89 void net80211_netdev_close(struct net_device *netdev)
90 {
91         struct net80211_device *dev = netdev->priv;
92
93         if (dev->op->close)
94                 dev->op->close(dev);
95 }
96
97 int net80211_netdev_transmit(struct net_device *netdev, struct io_buffer *iobuf)
98 {
99         struct net80211_device *dev = netdev->priv;
100         
101         if (dev->crypto) {
102                 struct io_buffer *niob = dev->crypto->encrypt(dev, iobuf);
103                 if (!niob)
104                         return -ENOMEM; /* only reason encryption could fail */
105
106                 free_iob(iobuf);
107                 iobuf = niob;
108         }
109         
110         if (dev->op->transmit)
111                 return dev->op->transmit(dev, iobuf);
112         return -ENOSYS;
113 }
114
115 void net80211_netdev_poll(struct net_device *netdev)
116 {
117         struct net80211_device *dev = netdev->priv;
118         
119         if (dev->op->poll)
120                 dev->op->poll(dev);
121 }
122
123 void net80211_netdev_irq(struct net_device *netdev, int enable)
124 {
125         struct net80211_device *dev = netdev->priv;
126         
127         if (dev->op->irq)
128                 dev->op->irq(dev, enable);
129 }
130
131 struct net_device_operations net80211_netdev_ops = {
132         .open = net80211_netdev_open,
133         .close = net80211_netdev_close,
134         .transmit = net80211_netdev_transmit,
135         .poll = net80211_netdev_poll,
136         .irq = net80211_netdev_irq,
137 };
138
139 /* ---------- 802.11 link-layer protocol ---------- */
140
141 static u8 net80211_ll_broadcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
142
143 /* Returns the time taken to transmit a packet of length `bytes' using
144    the current PHY parameters of `dev', measured in microseconds
145    starting immediately after reception of the previous packet is
146    complete. */
147 static u16 net80211_duration(struct net80211_device *dev, int bytes) 
148 {
149         struct net80211_channel *chan = &dev->channels[dev->channel];
150         u16 ratecode = dev->rates[dev->rate];
151         u32 kbps = NET80211_RATE_VALUE(ratecode) * 100;
152         
153         if (chan->band == NET80211_BAND_5GHZ || ratecode & NET80211_RATE_ERP) {
154                 /* OFDM encoding (802.11a/g) */
155                 int bits_per_symbol = (kbps * 4) / 1000; /* 4us/symbol */
156                 int bits = 22 + (bytes << 3); /* 22-bit PLCP */
157                 int symbols = (bits + bits_per_symbol - 1) / bits_per_symbol;
158                 return 16 + 20 + (symbols * 4); /* 16us SIFS, 20us preamble */
159         } else {
160                 /* CCK encoding (802.11b) */
161                 int phy_time = 144 + 48; /* preamble + PLCP */
162                 if (dev->erp_flags & NET80211_ERP_USE_SHORT_PREAMBLE)
163                         phy_time >>= 1;
164                 int bits = bytes << 3;
165                 int data_time = (bits * 1000) / kbps;
166                 return 10 + phy_time + data_time; /* 10us SIFS */
167         }
168 }
169
170 static int net80211_ll_push(struct net_device *netdev, struct io_buffer *iobuf,
171                             const void *ll_dest, const void *ll_source,
172                             uint16_t net_proto)
173 {
174         struct net80211_device *dev = netdev->priv;
175         struct ieee80211_frame *hdr = iob_push(iobuf, IEEE80211_LLC_HEADER_LEN +
176                                                IEEE80211_TYP_FRAME_HEADER_LEN);
177         struct ieee80211_llc_snap_header *lhdr = (struct ieee80211_llc_snap_header *)
178                 ((u8 *)hdr + IEEE80211_TYP_FRAME_HEADER_LEN);
179
180         hdr->fc = IEEE80211_THIS_VERSION | IEEE80211_TYPE_DATA |
181                   IEEE80211_STYPE_DATA | IEEE80211_FC_TODS;
182
183         /* We don't send fragmented frames, so duration is the time
184            for an SIFS + 10-byte ACK. */
185         hdr->duration = net80211_duration(dev, 10);
186
187         memcpy(hdr->addr1, dev->bssid, ETH_ALEN);
188         memcpy(hdr->addr2, ll_source, ETH_ALEN);
189         memcpy(hdr->addr3, ll_dest, ETH_ALEN);
190
191         hdr->seq = ++dev->last_tx_seqnr & 0x0FFF; /* fragment 0 */
192
193         lhdr->dsap = IEEE80211_LLC_DSAP;
194         lhdr->ssap = IEEE80211_LLC_SSAP;
195         lhdr->ctrl = IEEE80211_LLC_CTRL;
196         memset(lhdr->oui, 0x00, 3);
197         lhdr->ethertype = net_proto;
198
199         return 0;
200 }
201
202 static int net80211_ll_pull(struct net_device *netdev __unused,
203                             struct io_buffer *iobuf, const void **ll_dest,
204                             const void **ll_source, uint16_t *net_proto)
205 {
206         struct ieee80211_frame *hdr = iobuf->data;
207         struct ieee80211_llc_snap_header *lhdr = (struct ieee80211_llc_snap_header *)
208                 ((u8 *)hdr + IEEE80211_TYP_FRAME_HEADER_LEN);
209
210         /* Bunch of sanity checks */
211         if (iob_len(iobuf) < IEEE80211_TYP_FRAME_HEADER_LEN +
212                                 IEEE80211_LLC_HEADER_LEN) {
213                 DBG("802.11 packet too short (%zd bytes)\n", iob_len(iobuf));
214                 return -EINVAL;
215         }
216
217         if ((hdr->fc & IEEE80211_FC_VERSION) != IEEE80211_THIS_VERSION) {
218                 DBG("802.11 packet invalid version %04x\n",
219                     hdr->fc & IEEE80211_FC_VERSION);
220                 return -EINVAL;
221         }
222
223         if ((hdr->fc & IEEE80211_FC_TYPE) != IEEE80211_TYPE_DATA ||
224             (hdr->fc & IEEE80211_FC_SUBTYPE) != IEEE80211_STYPE_DATA) {
225                 DBG("802.11 packet not data/data (fc=%04x)\n", hdr->fc);
226                 return -EINVAL;
227         }
228
229         if ((hdr->fc & (IEEE80211_FC_TODS|IEEE80211_FC_FROMDS)) !=
230             IEEE80211_FC_FROMDS) {
231                 DBG("802.11 packet not from DS (fc=%04x)\n", hdr->fc);
232                 return -EINVAL;
233         }
234
235         if (lhdr->dsap != IEEE80211_LLC_DSAP || lhdr->ssap != IEEE80211_LLC_SSAP ||
236             lhdr->ctrl != IEEE80211_LLC_CTRL || lhdr->oui[0] || lhdr->oui[1] ||
237             lhdr->oui[2]) {
238                 DBG("802.11 LLC header is not plain EtherType encapsulator: "
239                     "%02x->%02x [%02x] %02x:%02x:%02x %04x\n",
240                     lhdr->dsap, lhdr->ssap, lhdr->ctrl, lhdr->oui[0],
241                     lhdr->oui[1], lhdr->oui[2], lhdr->ethertype);
242                 return -EINVAL;
243         }
244
245         iob_pull(iobuf, sizeof(*hdr) + sizeof(*lhdr));
246
247         *ll_dest = hdr->addr1;
248         *ll_source = hdr->addr3;
249         *net_proto = lhdr->ethertype;
250         return 0;
251 }
252
253 static int net80211_ll_mc_hash(unsigned int af __unused,
254                                const void *net_addr __unused,
255                                void *ll_addr __unused) 
256 {
257         return -ENOTSUP;
258 }
259
260 static struct ll_protocol net80211_ll_protocol __ll_protocol = {
261         .name           = "802.11",
262         .push           = net80211_ll_push,
263         .pull           = net80211_ll_pull,
264         .ntoa           = eth_ntoa,
265         .mc_hash        = net80211_ll_mc_hash,
266         .ll_proto       = htons(ARPHRD_ETHER), /* it's "encapsulated Ethernet" */
267         .ll_addr_len    = ETH_ALEN,
268         .ll_header_len  = IEEE80211_TYP_FRAME_HEADER_LEN +
269                           IEEE80211_LLC_HEADER_LEN,
270         .ll_broadcast   = net80211_ll_broadcast,
271 };
272
273 /* ---------- 802.11 network management API ---------- */
274
275 struct net80211_device *net80211_get(struct net_device *netdev) 
276 {
277         struct net80211_device *dev;
278         
279         list_for_each_entry(dev, &net80211_devices, list) {
280                 if (netdev->priv == dev)
281                         return netdev->priv;
282         }
283
284         return NULL;
285 }
286
287 int net80211_keep_mgmt(struct net80211_device *dev, int enable) 
288 {
289         int oldenab = dev->keep_mgmt;
290         dev->keep_mgmt = enable;
291         return oldenab;
292 }
293
294 struct io_buffer *net80211_mgmt_dequeue(struct net80211_device *dev,
295                                         int *signal)
296 {
297         struct io_buffer *iobuf;
298         struct net80211_rx_info *rxi;
299
300         list_for_each_entry(rxi, &dev->mgmt_info_queue, list) {
301                 list_del(&rxi->list);
302                 if (signal)
303                         *signal = rxi->signal;
304                 break;
305         }
306         list_for_each_entry(iobuf, &dev->mgmt_queue, list) {
307                 list_del(&iobuf->list);
308                 return iobuf;
309         }
310         return NULL;
311 }
312
313 int net80211_tx_mgmt(struct net80211_device *dev, u16 fc, u8 dest[6],
314                      struct io_buffer *iob) 
315 {
316         struct ieee80211_frame *hdr = iob_push(iob,
317                                                IEEE80211_TYP_FRAME_HEADER_LEN);
318         
319         hdr->fc = IEEE80211_THIS_VERSION | IEEE80211_TYPE_MGMT |
320                   (fc & ~IEEE80211_FC_PROTECTED);
321         hdr->duration = net80211_duration(dev, 10);
322         hdr->seq = ++dev->last_tx_seqnr & 0x0FFF;
323
324         memcpy(hdr->addr1, dest, ETH_ALEN); /* DA = RA */
325         memcpy(hdr->addr2, dev->netdev->ll_addr, ETH_ALEN); /* SA = TA */
326         memcpy(hdr->addr3, dest, ETH_ALEN); /* BSSID */
327
328         if (fc & IEEE80211_FC_PROTECTED) {
329                 if (!dev->crypto)
330                         return -EINVAL;
331                 
332                 struct io_buffer *eiob = dev->crypto->encrypt(dev, iob);
333                 free_iob(iob);
334                 iob = eiob;
335         }
336
337         return netdev_tx(dev->netdev, iob);
338 }
339
340
341 /* ---------- driver API ---------- */
342
343 struct net80211_device *net80211_alloc(size_t priv_size) 
344 {
345         struct net80211_device *dev;
346         struct net_device *netdev = alloc_netdev(sizeof(*dev) + priv_size);
347
348         if (!netdev)
349                 return NULL;
350
351         netdev->ll_protocol = &net80211_ll_protocol;
352         netdev->max_pkt_len = IEEE80211_MAX_DATA_LEN;
353         netdev_init(netdev, &net80211_netdev_ops);
354
355         dev = netdev->priv;
356         dev->netdev = netdev;
357         dev->priv = (u8 *)dev + sizeof(*dev);
358         dev->op = &net80211_null_ops;
359         dev->last_rx_seq = -1;
360
361         dev->proc_assoc.step = net80211_step_associate;
362         INIT_LIST_HEAD(&dev->mgmt_queue);
363
364         return dev;
365 }
366
367 int net80211_register(struct net80211_device *dev,
368                       struct net80211_device_operations *ops,
369                       struct net80211_hw_info *hw) 
370 {
371         dev->op = ops;
372         dev->hw = malloc(sizeof(*hw));
373         if (!dev->hw)
374                 return -ENOMEM;
375
376         memcpy(dev->hw, hw, sizeof(*hw));
377         memcpy(dev->netdev->ll_addr, hw->hwaddr, ETH_ALEN);
378         
379         list_add_tail(&dev->list, &net80211_devices);
380         return register_netdev(dev->netdev);
381 }
382
383 void net80211_unregister(struct net80211_device *dev) 
384 {
385         unregister_netdev(dev->netdev);
386         list_del(&dev->list);
387         dev->op = &net80211_null_ops;
388 }
389
390 void net80211_free(struct net80211_device *dev) 
391 {
392         free(dev->hw);
393         netdev_nullify(dev->netdev);
394         netdev_put(dev->netdev);
395 }
396
397 /* ---------- 802.11 network management workhorse code ---------- */
398
399 /* Clear the flags in `clear', set those in `set', and set status to
400    `status'. Clears are done before sets. The LINK_UP bit is cleared
401    when association is cleared, but not set when association is set -
402    that's left to the association task to do after it checks
403    everything's OK. */
404 static inline void net80211_set_state(struct net80211_device *dev,
405                                       short clear, short set, u16 status) 
406 {
407         /* The conditions in this function are deliberately formulated
408            to be decidable at compile-time. */
409
410         if (clear & NET80211_AUTHENTICATED)
411                 clear |= NET80211_ASSOCIATED;
412         if (clear & NET80211_ASSOCIATED)
413                 clear |= NET80211_CRYPTO_SYNCED;
414
415         dev->state = (dev->state & ~clear) | set;
416         dev->state = (dev->state & ~NET80211_STATUS_MASK) |
417                 (status & NET80211_STATUS_MASK);
418
419         if (clear & NET80211_ASSOCIATED)
420                 dev->netdev->state &= ~NETDEV_LINK_UP;
421
422         if ((clear | set) & NET80211_ASSOCIATED)
423                 dev->op->config(dev, NET80211_CFG_ASSOC);
424 }
425
426 static void net80211_add_channels(struct net80211_device *dev, int start,
427                                   int len, int txpower) 
428 {
429         int i, chan = start;
430
431         for (i = dev->nr_channels; len-- && i < NET80211_MAX_CHANNELS; i++) {
432                 dev->channels[i].channel_nr = chan;
433                 dev->channels[i].maxpower = txpower;
434
435                 if (chan >= 1 && chan <= 14) {
436                         dev->channels[i].band = NET80211_BAND_2GHZ;
437                         if (chan == 14)
438                                 dev->channels[i].center_freq = 2484;
439                         else
440                                 dev->channels[i].center_freq = 2407 + 5*chan;
441                         chan++;
442                 } else {
443                         dev->channels[i].band = NET80211_BAND_5GHZ;
444                         dev->channels[i].center_freq = 5000 + 5*chan;
445                         chan += 4;
446                 }
447         }
448
449         dev->nr_channels = i;
450 }
451
452 static int net80211_process_capab(struct net80211_device *dev, u16 capab)
453 {
454         u16 old_erp = dev->erp_flags;
455
456         if ((capab & (IEEE80211_CAPAB_MANAGED | IEEE80211_CAPAB_ADHOC)) !=
457             IEEE80211_CAPAB_MANAGED) {
458                 DBG("802.11 cannot handle IBSS network\n");
459                 return -ENOSYS;
460         }
461
462         if (capab & IEEE80211_CAPAB_SPECTRUM_MGMT) {
463                 DBG("802.11 cannot handle spectrum managed network\n");
464                 return -ENOSYS;
465         }
466
467         dev->erp_flags &= ~(NET80211_ERP_USE_SHORT_PREAMBLE |
468                             NET80211_ERP_USE_SHORT_SLOT);
469
470         if (capab & IEEE80211_CAPAB_SHORT_PMBL)
471                 dev->erp_flags |= NET80211_ERP_USE_SHORT_PREAMBLE;
472
473         if (capab & IEEE80211_CAPAB_SHORT_SLOT)
474                 dev->erp_flags |= NET80211_ERP_USE_SHORT_SLOT;
475
476         if (old_erp != dev->erp_flags)
477                 dev->op->config(dev, NET80211_CFG_ERP_PARAMS);
478
479         return 0;
480 }
481
482 static int net80211_process_ie(struct net80211_device *dev,
483                                struct ieee80211_ie *ie, int len)
484 {
485         void *ie_byte = (u8 *)ie;
486         void *ie_byte_end = ie_byte + len;
487         u16 old_rate = NET80211_RATE_VALUE(dev->rates[dev->rate]);
488         u16 old_erp = dev->erp_flags;
489         int have_rates = 0, i;
490         int ds_channel = 0;
491         int changed = 0;
492
493         for (ie = ie_byte; ie_byte < ie_byte_end;
494              ie_byte += ie->len + 2, ie = ie_byte) {
495                 switch (ie->id) {
496                 case IEEE80211_IE_SSID:
497                         if (ie->len <= 32) {
498                                 memcpy(dev->essid, ie->ssid, ie->len);
499                                 dev->essid[ie->len] = 0;
500                         }
501                         break;
502
503                 case IEEE80211_IE_RATES:
504                 case IEEE80211_IE_EXT_RATES:
505                         if (!have_rates) {
506                                 dev->nr_rates = 0;
507                                 dev->basic_rates = 0;
508                                 have_rates = 1;
509                         }
510                         for (i = 0; i < ie->len &&
511                                      dev->nr_rates < NET80211_MAX_RATES; i++) {
512                                 u8 rid = ie->rates[i];
513                                 u16 rate = (rid & 0x7f) * 5;
514                                 if (rid & 0x80)
515                                         dev->basic_rates |= (1 << dev->nr_rates);
516                                 if (rate != 10 && rate != 20 && rate != 55 &&
517                                     rate != 110) /* 802.11b rates */
518                                         rate |= NET80211_RATE_ERP;
519                                 dev->rates[dev->nr_rates++] = rate;
520                         }
521                         
522                         break;
523
524                 case IEEE80211_IE_DS_PARAM:
525                         if (dev->channel < dev->nr_channels &&
526                             dev->channels[dev->channel].channel_nr == ds_channel)
527                                 break;
528                         ds_channel = ie->ds_param.current_channel;
529                         changed |= NET80211_CFG_CHANNEL;
530                         break;
531
532                 case IEEE80211_IE_COUNTRY:
533                         dev->nr_channels = 0;
534
535                         DBG("802.11 setting country regulations for %c%c\n",
536                             ie->country.name[0], ie->country.name[1]);
537                         for (i = 0; i < (ie->len - 3) / 3; i++) {
538                                 if (ie->country.triplet[i].ext.reg_ext_id > 200) {
539                                         DBG("802.11 don't know how to parse "
540                                             "regulatory extension information\n");
541                                 } else {
542                                         net80211_add_channels(dev,
543                                           ie->country.triplet[i].band.first_channel,
544                                           ie->country.triplet[i].band.nr_channels,
545                                           ie->country.triplet[i].band.max_txpower);
546                                 }
547                         }
548                         break;
549                         
550                 case IEEE80211_IE_ERP_INFO:
551                         dev->erp_flags &= ~(NET80211_ERP_USE_PROTECTION |
552                                             NET80211_ERP_USE_SHORT_PREAMBLE);
553                         if (ie->erp_info & IEEE80211_ERP_USE_PROTECTION)
554                                 dev->erp_flags |= NET80211_ERP_USE_PROTECTION;
555                         if (!(ie->erp_info & IEEE80211_ERP_BARKER_LONG))
556                                 dev->erp_flags |= NET80211_ERP_USE_SHORT_PREAMBLE;
557                         break;
558                         
559                 case IEEE80211_IE_RSN:
560                         /* XXX need to implement WPA stuff */
561                         break;
562                 }
563         }
564
565         if (have_rates) {
566                 /* Allow only those rates that are also supported by
567                    the hardware. */
568                 int delta = 0, j;
569
570                 dev->rate = 0;
571                 for (i = 0; i < dev->nr_rates; i++) {
572                         int ok = 0;
573                         for (j = 0; j < dev->hw->nr_supported_rates; j++) {
574                                 if (dev->hw->supported_rates[i] ==
575                                     dev->rates[i]) {                                    
576                                         ok = 1;
577                                         break;
578                                 }
579                         }
580
581                         if (!ok)
582                                 delta++;
583                         else {
584                                 dev->rates[i - delta] = dev->rates[i];
585                                 if (old_rate == dev->rates[i])
586                                         dev->rate = i - delta;
587                         }
588                 }
589
590                 dev->nr_rates -= delta;
591
592                 if (dev->rates[dev->rate] != old_rate)
593                         changed |= NET80211_CFG_RATE;
594         }
595
596         if (ds_channel) {
597                 for (i = 0; i < dev->nr_channels; i++) {
598                         if (dev->channels[i].channel_nr == ds_channel) {
599                                 dev->channel = i;
600                                 break;
601                         }
602                 }
603         }
604
605         if (dev->hw->flags & NET80211_HW_NO_SHORT_PREAMBLE)
606                 dev->erp_flags &= ~NET80211_ERP_USE_SHORT_PREAMBLE;
607         if (dev->hw->flags & NET80211_HW_NO_SHORT_SLOT)
608                 dev->erp_flags &= ~NET80211_ERP_USE_SHORT_SLOT;
609
610         if (old_erp != dev->erp_flags)
611                 changed |= NET80211_CFG_ERP_PARAMS;
612
613         if (changed)
614                 dev->op->config(dev, changed);
615
616         return 0;
617 }
618
619 struct net80211_wlan *net80211_probe(struct net80211_device *dev,
620                                      const char *essid, int active) 
621 {
622         (void)dev; (void)essid; (void)active;
623         return NULL;
624 }
625
626 void net80211_free_wlan ( struct net80211_wlan *wlan )
627 {
628         free_iob ( wlan->beacon );
629         free ( wlan );
630 }
631
632 void net80211_step_associate ( struct process *proc )
633 {
634         struct net80211_device *dev =
635                 container_of ( proc, struct net80211_device, proc_assoc );
636         int rc = 0;
637         int status = dev->state & NET80211_STATUS_MASK;
638
639         if ( dev->state & NET80211_WAITING )
640                 return;
641
642         if ( ! dev->associating ) {
643                 /* state: scan */
644                 int hidden = fetch_intz_setting ( NULL,
645                                                   &net80211_hidden_setting );
646                 int band = dev->hw->bands;
647
648                 if ( hidden )
649                         band &= ~NET80211_BAND_5GHZ;
650
651                 rc = net80211_prepare_default ( dev, band, hidden );
652                 if ( rc )
653                         goto fail;
654
655                 dev->associating = net80211_probe ( dev, dev->essid, hidden );
656                 if ( ! dev->associating )
657                         goto fail;
658
659                 DBG ( "802.11 found network %s (%s)\n", dev->associating->essid,
660                       eth_ntoa ( dev->associating->bssid ) );
661
662                 dev->associating->method = IEEE80211_AUTH_OPEN_SYSTEM;
663                 return;
664         }
665
666         if ( ! ( dev->state & NET80211_AUTHENTICATED ) ) {
667                 /* state: prepare and authenticate */
668                 int method = dev->associating->method;
669
670                 if ( status != IEEE80211_STATUS_SUCCESS ) {
671                         /* we tried authenticating already, but failed */
672
673                         if ( method == IEEE80211_AUTH_OPEN_SYSTEM &&
674                              ( status == IEEE80211_STATUS_AUTH_ALGO_UNSUPP ||
675                                status == IEEE80211_STATUS_AUTH_CHALL_INVALID ) ) {
676                                 /* Maybe this network uses Shared Key? */
677                                 method = dev->associating->method =
678                                         IEEE80211_AUTH_SHARED_KEY;
679                         } else {
680                                 goto fail;
681                         }
682                 }
683
684                 DBG ( "802.11 authenticating with method %d\n", method );
685
686                 rc = net80211_prepare ( dev, dev->associating );
687                 if ( rc )
688                         goto fail;
689
690                 rc = net80211_send_auth ( dev, dev->associating, method );
691                 if ( rc )
692                         goto fail;
693
694                 return;
695         }
696
697         if ( ! ( dev->state & NET80211_ASSOCIATED ) ) {
698                 /* state: associate */
699                 DBG ( "802.11 associating\n");
700
701                 if ( status != IEEE80211_STATUS_SUCCESS )
702                         goto fail;
703
704                 rc = net80211_send_assoc ( dev, dev->associating );
705                 if ( rc )
706                         goto fail;
707
708                 return;
709         }
710
711         if ( ! ( dev->state & NET80211_CRYPTO_SYNCED ) ) {
712                 /* state: crypto sync */
713                 dev->state |= NET80211_CRYPTO_SYNCED;
714                 /* XXX need to actually do something here once we
715                    support WPA */
716                 return;
717         }
718
719         /* state: done! */
720         dev->netdev->state |= NETDEV_LINK_UP;
721         dev->state &= ~NET80211_WORKING;
722         printf ( "[associated to %s] ", dev->essid );
723         process_del ( proc );
724
725  fail:
726         DBG ( "802.11 association process failed with state=%04x "
727               "rc=%08x\n", dev->state, rc );
728         printf ( "association error: %s\n", strerror ( rc ) );
729         dev->state &= ~NET80211_WORKING;
730         process_del ( proc );
731 }
732
733 void net80211_autoassociate ( struct net80211_device *dev )
734 {
735         int len;
736
737         if ( ! ( dev->state & NET80211_WORKING ) )
738                 process_add ( &dev->proc_assoc );
739         if ( dev->associating )
740                 net80211_free_wlan ( dev->associating );
741
742         len = fetch_setting ( netdev_settings ( dev->netdev ),
743                               &net80211_ssid_setting, dev->essid,
744                               IEEE80211_MAX_SSID_LEN );
745         dev->essid[len] = 0;
746         dev->state |= NET80211_WORKING;
747         dev->associating = NULL;
748 }
749
750 int net80211_prepare_default(struct net80211_device *dev, int band, int active)
751 {
752         if (active && band != NET80211_BAND_2GHZ) {
753                 DBG("802.11 cannot perform active scanning on 5GHz band\n");
754                 return -EINVAL;
755         }
756
757         dev->nr_channels = 0;
758
759         if (active)
760                 net80211_add_channels(dev, 1, 11, NET80211_REG_TXPOWER);
761         else {
762                 if (band & NET80211_BAND_2GHZ)
763                         net80211_add_channels(dev, 1, 14, NET80211_REG_TXPOWER);
764                 if (band & NET80211_BAND_5GHZ)
765                         net80211_add_channels(dev, 36, 8, NET80211_REG_TXPOWER);
766         }
767
768         dev->channel = 0;
769         dev->op->config(dev, NET80211_CFG_CHANNEL);
770         return 0;
771 }
772
773 int net80211_prepare(struct net80211_device *dev, struct net80211_wlan *wlan)
774 {
775         struct ieee80211_frame *hdr = wlan->beacon->data;
776         struct ieee80211_beacon *beacon = (struct ieee80211_beacon *)hdr->data;
777         int rc;
778
779         net80211_set_state(dev, NET80211_ASSOCIATED, 0, 0);
780         memcpy(dev->bssid, wlan->bssid, ETH_ALEN);
781         strcpy(dev->essid, wlan->essid);
782
783         /* do crypto setup here */
784         
785         rc = net80211_process_capab(dev, beacon->capability);
786         if (rc)
787                 return rc;
788
789         rc = net80211_process_ie(dev, beacon->info_element,
790                                  iob_len(wlan->beacon) - sizeof(*hdr));
791         if (rc)
792                 return rc;
793
794         return 0;
795 }
796
797 int net80211_send_auth(struct net80211_device *dev, struct net80211_wlan *wlan,
798                        int method) 
799 {
800         struct io_buffer *iob = alloc_iob(64);
801         struct ieee80211_auth *auth;
802
803         iob_reserve(iob, IEEE80211_TYP_FRAME_HEADER_LEN);
804         auth = iob->data;
805         auth->algorithm = method;
806         auth->tx_seq = 1;
807         auth->status = 0;
808
809         return net80211_tx_mgmt(dev, IEEE80211_STYPE_AUTH, wlan->bssid, iob);
810 }
811
812 static void net80211_handle_auth(struct net80211_device *dev,
813                                  struct io_buffer *iob) 
814 {
815         struct ieee80211_frame *hdr = iob->data;
816         struct ieee80211_auth *auth = (struct ieee80211_auth *)hdr->data;
817
818         if (auth->tx_seq & 1) {
819                 DBG("%s: 802.11 authentication received improperly directed "
820                     "frame (sequence %d)\n", dev->netdev->name, auth->tx_seq);
821                 net80211_set_state(dev, NET80211_WAITING, 0,
822                                    IEEE80211_STATUS_FAILURE);
823                 return;
824         }
825
826         if (auth->status != IEEE80211_STATUS_SUCCESS) {
827                 DBG("%s: 802.11 authentication failed: status %d\n",
828                     dev->netdev->name, auth->status);
829                 net80211_set_state(dev, NET80211_WAITING, 0, auth->status);
830                 return;
831         }
832
833         if (auth->algorithm == IEEE80211_AUTH_SHARED_KEY && !dev->crypto) {
834                 DBG("%s: 802.11 can't perform shared-key authentication without "
835                     "a cryptosystem\n", dev->netdev->name);
836                 net80211_set_state(dev, NET80211_WAITING, 0,
837                                    IEEE80211_STATUS_FAILURE);
838                 return;
839         }
840
841         if (auth->algorithm == IEEE80211_AUTH_SHARED_KEY && auth->tx_seq == 2) {
842                 /* Since the iob we got is going to be freed as soon
843                    as we return, we can do some in-place
844                    modification. */
845                 auth->tx_seq = 3;
846                 auth->status = 0;
847
848                 memcpy(hdr->addr2, hdr->addr1, ETH_ALEN);
849                 memcpy(hdr->addr1, hdr->addr3, ETH_ALEN);
850
851                 netdev_tx(dev->netdev, dev->crypto->encrypt(dev, iob));
852                 return;
853         }
854
855         net80211_set_state(dev, NET80211_WAITING, NET80211_AUTHENTICATED,
856                            IEEE80211_STATUS_SUCCESS);
857
858         return;
859 }
860
861 int net80211_send_assoc(struct net80211_device *dev, struct net80211_wlan *wlan)
862 {
863         struct io_buffer *iob = alloc_iob(128);
864         struct ieee80211_assoc_req *assoc;
865         struct ieee80211_ie *ie;
866         void *ie_byte;
867         int i;
868
869         iob_reserve(iob, IEEE80211_TYP_FRAME_HEADER_LEN);
870         assoc = iob->data;
871
872         assoc->capability = IEEE80211_CAPAB_MANAGED;
873         if (!(dev->hw->flags & NET80211_HW_NO_SHORT_PREAMBLE))
874                 assoc->capability |= IEEE80211_CAPAB_SHORT_PMBL;
875         if (!(dev->hw->flags & NET80211_HW_NO_SHORT_SLOT))
876                 assoc->capability |= IEEE80211_CAPAB_SHORT_SLOT;
877         if (wlan->security)
878                 assoc->capability |= IEEE80211_CAPAB_PRIVACY;
879
880         assoc->listen_interval = 1;
881
882         ie = assoc->info_element;
883         ie_byte = ie;
884
885         ie->id = IEEE80211_IE_SSID;
886         ie->len = strlen(wlan->essid);
887         strcpy(ie->ssid, wlan->essid);
888
889         ie_byte += ie->len;
890         ie = ie_byte;
891
892         ie->id = IEEE80211_IE_RATES;
893         ie->len = dev->hw->nr_supported_rates;
894         if (ie->len > 8)
895                 ie->len = 8;
896         for (i = 0; i < ie->len; i++) {
897                 ie->rates[i] = dev->hw->supported_rates[i] / 5;
898         }
899
900         ie_byte += ie->len;
901         ie = ie_byte;
902
903         if (i < dev->hw->nr_supported_rates) {
904                 ie->id = IEEE80211_IE_EXT_RATES;
905                 ie->len = dev->hw->nr_supported_rates - i;
906                 for (; i < ie->len; i++) {
907                         ie->rates[i - 8] = dev->hw->supported_rates[i] / 5;
908                 }
909
910                 ie_byte += ie->len;
911                 ie = ie_byte;
912         }
913
914         /* XXX add RSN ie for WPA support */
915
916         return net80211_tx_mgmt(dev, IEEE80211_STYPE_ASSOC_REQ, wlan->bssid,
917                                 iob);
918 }
919
920 static void net80211_handle_assoc_reply(struct net80211_device *dev,
921                                         struct io_buffer *iob) 
922 {
923         struct ieee80211_frame *hdr = iob->data;
924         struct ieee80211_assoc_resp *assoc =
925                 (struct ieee80211_assoc_resp *)hdr->data;
926
927         net80211_process_capab(dev, assoc->capability);
928         net80211_process_ie(dev, assoc->info_element,
929                             iob_len(iob) - sizeof(*hdr));
930
931         if (assoc->status != IEEE80211_STATUS_SUCCESS) {
932                 DBG("%s: 802.11 association failed: status %d\n",
933                     dev->netdev->name, assoc->status);
934                 net80211_set_state(dev, NET80211_WAITING, 0, assoc->status);
935                 return;
936         }
937
938         /* ESSID was filled before the association request was sent */
939         memcpy(dev->bssid, hdr->addr3, ETH_ALEN);
940         dev->aid = assoc->aid;
941
942         net80211_set_state(dev, NET80211_WAITING, NET80211_ASSOCIATED,
943                            IEEE80211_STATUS_SUCCESS);
944 }
945
946 static void net80211_handle_mgmt(struct net80211_device *dev,
947                                  struct io_buffer *iob, int signal) 
948 {
949         struct ieee80211_frame *hdr = iob->data;
950         u16 stype = hdr->fc & IEEE80211_FC_SUBTYPE;
951         int keep = 0;
952
953         if ((hdr->fc & IEEE80211_FC_TYPE) != IEEE80211_TYPE_MGMT) {
954                 free_iob(iob);
955                 return;         /* only handle management frames */
956         }
957
958         switch (stype) {
959         case IEEE80211_STYPE_DEAUTH:
960                 net80211_set_state(dev, NET80211_AUTHENTICATED, 0, 0);
961                 DBG("%s: 802.11 deauthenticated\n", dev->netdev->name);
962                 net80211_autoassociate(dev);
963                 break;
964         case IEEE80211_STYPE_DISASSOC:
965                 net80211_set_state(dev, NET80211_ASSOCIATED, 0, 0);
966                 DBG("%s: 802.11 disassociated\n", dev->netdev->name);
967                 net80211_autoassociate(dev);
968                 break;
969
970                 /* We handle authentication and association. */
971         case IEEE80211_STYPE_AUTH:
972                 if (!(dev->state & NET80211_AUTHENTICATED))
973                         net80211_handle_auth(dev, iob);
974                 break;
975
976         case IEEE80211_STYPE_ASSOC_RESP:
977         case IEEE80211_STYPE_REASSOC_RESP:
978                 if (!(dev->state & NET80211_ASSOCIATED))
979                         net80211_handle_assoc_reply(dev, iob);
980                 break;
981
982                 /* We pass probes and beacons onto network scanning
983                    code. Pass actions for future extensibility. */
984         case IEEE80211_STYPE_PROBE_RESP:
985         case IEEE80211_STYPE_BEACON:
986         case IEEE80211_STYPE_ACTION:
987                 if (dev->keep_mgmt) {
988                         struct net80211_rx_info *rxinf;
989                         rxinf = zalloc(sizeof(*rxinf));
990                         if (!rxinf) {
991                                 DBG("No memory for rxinf structure\n");
992                                 break;
993                         }
994                         rxinf->signal = signal;
995                         list_add_tail(&iob->list, &dev->mgmt_queue);
996                         list_add_tail(&rxinf->list, &dev->mgmt_info_queue);
997                         keep = 1;
998                 }
999                 break;
1000
1001         case IEEE80211_STYPE_ASSOC_REQ:
1002         case IEEE80211_STYPE_REASSOC_REQ:
1003         case IEEE80211_STYPE_PROBE_REQ:
1004                 /* We should never receive these, only send them. */
1005                 DBG("Received strange management request (%04x)\n", stype);
1006                 break;
1007         default:
1008                 DBG("Received unimplemented management packet (%04x)\n", stype);
1009                 break;
1010         }
1011
1012         if (!keep)
1013                 free_iob(iob);
1014 }
1015
1016 /* ---------- Packet handling functions ---------- */
1017
1018 /* Free the iob's for frag cache entry fcid and mark it unused. */
1019 static void net80211_free_frags(struct net80211_device *dev, int fcid) 
1020 {
1021         int j;
1022         struct net80211_frag_cache *frag = &dev->frags[fcid];
1023
1024         for (j = 0; j < 16; j++) {
1025                 if (frag->iob[j]) {
1026                         free_iob(frag->iob[j]);
1027                         frag->iob[j] = NULL;
1028                 }
1029         }
1030
1031         frag->seqnr = 0;
1032         frag->nfrags = 0;
1033         frag->start_ticks = 0;
1034         frag->state = NET80211_FRAG_AVAIL;
1035 }
1036
1037 /* Accumulate fragments from frag cache entry fcid, of total size
1038    `size' (headers included), into one iob and return it. */
1039 static struct io_buffer *net80211_accum_frags(struct net80211_device *dev,
1040                                               int fcid, int size)
1041 {
1042         struct net80211_frag_cache *frag = &dev->frags[fcid];
1043         int hdrsize = IEEE80211_TYP_FRAME_HEADER_LEN;
1044         int nfrags = frag->nfrags;
1045         int nsize = size - hdrsize * (nfrags - 1);
1046         int i;
1047
1048         struct io_buffer *niob = alloc_iob(nsize);
1049         struct ieee80211_frame *hdr;
1050
1051         /* Add the header from the first one... */
1052         memcpy(iob_put(niob, hdrsize), frag->iob[0]->data, hdrsize);
1053
1054         /* ... and all the data from all of them. */
1055         for (i = 0; i < frag->nfrags; i++) {
1056                 int len = iob_len(frag->iob[i]) - hdrsize;
1057                 memcpy(iob_put(niob, len), frag->iob[i]->data + hdrsize, len);
1058         }
1059
1060         /* Turn off the fragment bit. */
1061         hdr = niob->data;
1062         hdr->fc &= ~IEEE80211_FC_MORE_FRAG;
1063
1064         return niob;
1065 }
1066
1067 static void net80211_rx_frag(struct net80211_device *dev, struct io_buffer *iob,
1068                              int signal)
1069 {
1070         struct ieee80211_frame *hdr = iob->data;
1071
1072         if (IEEE80211_FRAG(hdr->seq) == 0 && (hdr->fc & IEEE80211_FC_MORE_FRAG)) {
1073                 /* start a frag cache entry */
1074                 int i, newest = -1;
1075                 u32 curr_ticks = currticks(), newest_ticks = 0;
1076                 u32 timeout = ticks_per_sec() * NET80211_FRAG_TIMEOUT;
1077
1078                 for (i = 0; i < NET80211_NR_CONCURRENT_FRAGS; i++) {
1079                         if (dev->frags[i].state == NET80211_FRAG_AVAIL)
1080                                 break;
1081
1082                         if (dev->frags[i].start_ticks + timeout >= curr_ticks) {
1083                                 net80211_free_frags(dev, i);
1084                                 break;
1085                         }
1086
1087                         if (dev->frags[i].start_ticks > newest_ticks) {
1088                                 newest = i;
1089                                 newest_ticks = dev->frags[i].start_ticks;
1090                         }
1091                 }
1092
1093                 /* If we're being sent more concurrent fragmented
1094                    packets than we can handle, drop the newest so the
1095                    oldest has time to complete. */
1096                 if (i == NET80211_NR_CONCURRENT_FRAGS) {
1097                         i = newest;
1098                         net80211_free_frags(dev, i);
1099                 }
1100
1101                 dev->frags[i].state = NET80211_FRAG_WAITING;
1102                 dev->frags[i].seqnr = IEEE80211_SEQNR(hdr->seq);
1103                 dev->frags[i].start_ticks = currticks();
1104                 dev->frags[i].iob[0] = iob;
1105                 return;
1106         } else {
1107                 int i;
1108                 for (i = 0; i < NET80211_NR_CONCURRENT_FRAGS; i++) {
1109                         if (dev->frags[i].state != NET80211_FRAG_AVAIL &&
1110                             dev->frags[i].seqnr == IEEE80211_SEQNR(hdr->seq))
1111                                 break;
1112                 }
1113                 if (i == NET80211_NR_CONCURRENT_FRAGS) {
1114                         /* drop non-first not-in-cache fragments */
1115                         DBG2("802.11 dropped fragment fc=%04x seq=%04x\n",
1116                              hdr->fc, hdr->seq);
1117                         free_iob(iob);
1118                         return;
1119                 }
1120
1121                 dev->frags[i].iob[IEEE80211_FRAG(hdr->seq)] = iob;
1122
1123                 if (dev->frags[i].state == NET80211_FRAG_WAITING &&
1124                     !(hdr->fc & IEEE80211_FC_MORE_FRAG)) {
1125                         dev->frags[i].state = NET80211_FRAG_FINISHING;
1126                         dev->frags[i].nfrags = IEEE80211_FRAG(hdr->seq) + 1;
1127                 }
1128                 
1129                 if (dev->frags[i].state == NET80211_FRAG_FINISHING) {
1130                         int j, size = 0;
1131                         for (j = 0; j < dev->frags[i].nfrags; j++) {
1132                                 size += iob_len(dev->frags[i].iob[j]);
1133                                 if (dev->frags[i].iob[j] == NULL)
1134                                         break;
1135                         }
1136                         if (j == dev->frags[i].nfrags) {
1137                                 /* we've got everything! */
1138                                 struct io_buffer *niob =
1139                                         net80211_accum_frags(dev, i, size);
1140                                 net80211_free_frags(dev, i);
1141                                 net80211_rx(dev, niob, signal);
1142                         }
1143                 }
1144         }
1145 }
1146
1147 void net80211_rx(struct net80211_device *dev, struct io_buffer *iob, int signal)
1148 {
1149         struct ieee80211_frame *hdr = iob->data;
1150         u16 type = hdr->fc & IEEE80211_FC_TYPE;
1151         if ((hdr->fc & IEEE80211_FC_VERSION) != IEEE80211_THIS_VERSION)
1152                 goto drop;      /* drop invalid-version packets */
1153
1154         if (type == IEEE80211_TYPE_CTRL)
1155                 goto drop;      /* we don't handle control packets,
1156                                    the hardware does */
1157
1158         if (dev->last_rx_seq == hdr->seq)
1159                 goto drop;      /* avoid duplicate packet */
1160         dev->last_rx_seq = hdr->seq;
1161
1162         if (dev->hw->flags & NET80211_HW_RX_HAS_FCS) {
1163                 /* discard the FCS */
1164                 iob_unput(iob, 4);
1165         }
1166
1167         if (hdr->fc & IEEE80211_FC_PROTECTED) {
1168                 struct io_buffer *niob;
1169                 if (!dev->crypto)
1170                         goto drop;      /* can't decrypt packets on an open network */
1171
1172                 niob = dev->crypto->decrypt(dev, iob);
1173                 if (!niob)
1174                         goto drop;      /* drop failed decryption */
1175                 free_iob(iob);
1176                 iob = niob;
1177         }
1178
1179         /* Fragments go into the frag cache or get dropped. */
1180         if (IEEE80211_FRAG(hdr->seq) != 0 || (hdr->fc & IEEE80211_FC_MORE_FRAG)) {
1181                 net80211_rx_frag(dev, iob, signal);
1182                 return;
1183         }
1184
1185         /* Management frames get handled, enqueued, or dropped. */
1186         if (type == IEEE80211_TYPE_MGMT) {
1187                 net80211_handle_mgmt(dev, iob, signal);
1188                 return;
1189         }
1190
1191         /* Data frames get dropped or sent to the net_device. */
1192         if ((hdr->fc & IEEE80211_FC_SUBTYPE) != IEEE80211_STYPE_DATA)
1193                 goto drop;      /* drop QoS, CFP, or null data packets */
1194
1195         if (dev->netdev->state & NETDEV_LINK_UP) {
1196                 netdev_rx(dev->netdev, iob);
1197                 return;
1198         }
1199
1200  drop:
1201         DBG2("802.11 dropped packet fc=%04x seq=%04x\n", hdr->fc, hdr->seq);
1202         free_iob(iob);
1203         return;
1204 }