4db5a9197134d17869e0b5d6a9fcd5b73734f142
[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 <string.h>
24 #include <byteswap.h>
25 #include <stdlib.h>
26 #include <gpxe/if_arp.h>
27 #include <gpxe/ethernet.h>
28 #include <gpxe/ieee80211.h>
29 #include <gpxe/netdevice.h>
30 #include <gpxe/net80211.h>
31 #include <gpxe/timer.h>
32 #include <errno.h>
33
34 /** List of 802.11 devices */
35 static struct list_head net80211_devices = LIST_HEAD_INIT(net80211_devices);
36
37 /** Set of device operations that does nothing */
38 static struct net80211_device_operations net80211_null_ops;
39
40 /* ---------- still needs implementing... ---------- */
41 void net80211_handle_mgmt(struct net80211_device *dev, struct io_buffer *iob)
42 {
43         (void)dev; (void)iob;
44         /* ... */
45 }
46
47 void net80211_autoassociate(struct net80211_device *dev) 
48 {
49         (void)dev;
50         /* ... */
51 }
52
53 /* ---------- net_device wrapper ---------- */
54
55 int net80211_netdev_open(struct net_device *netdev) 
56 {
57         struct net80211_device *dev = netdev->priv;
58
59         if (dev->op->open)
60                 return dev->op->open(dev);
61
62         net80211_autoassociate(dev);
63         return 0;
64 }
65
66 void net80211_netdev_close(struct net_device *netdev)
67 {
68         struct net80211_device *dev = netdev->priv;
69
70         if (dev->op->close)
71                 dev->op->close(dev);
72 }
73
74 int net80211_netdev_transmit(struct net_device *netdev, struct io_buffer *iobuf)
75 {
76         struct net80211_device *dev = netdev->priv;
77         
78         if (dev->crypto) {
79                 struct io_buffer *niob = dev->crypto->encrypt(dev, iobuf);
80                 if (!niob)
81                         return -ENOMEM; /* only reason encryption could fail */
82
83                 free_iob(iobuf);
84                 iobuf = niob;
85         }
86         
87         if (dev->op->transmit)
88                 return dev->op->transmit(dev, iobuf);
89         return -ENOSYS;
90 }
91
92 void net80211_netdev_poll(struct net_device *netdev)
93 {
94         struct net80211_device *dev = netdev->priv;
95         
96         if (dev->op->poll)
97                 dev->op->poll(dev);
98 }
99
100 void net80211_netdev_irq(struct net_device *netdev, int enable)
101 {
102         struct net80211_device *dev = netdev->priv;
103         
104         if (dev->op->irq)
105                 dev->op->irq(dev, enable);
106 }
107
108 struct net_device_operations net80211_netdev_ops = {
109         .open = net80211_netdev_open,
110         .close = net80211_netdev_close,
111         .transmit = net80211_netdev_transmit,
112         .poll = net80211_netdev_poll,
113         .irq = net80211_netdev_irq,
114 };
115
116 /* ---------- 802.11 link-layer protocol ---------- */
117
118 static u8 net80211_ll_broadcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
119
120 /* Returns the time taken to transmit a packet of length `bytes' using
121    the current PHY parameters of `dev', measured in microseconds
122    starting immediately after reception of the previous packet is
123    complete. */
124 static u16 net80211_duration(struct net80211_device *dev, int bytes) 
125 {
126         struct net80211_channel *chan = &dev->channels[dev->channel];
127         u16 ratecode = dev->rates[dev->rate];
128         u32 kbps = NET80211_RATE_VALUE(ratecode) * 100;
129         
130         if (chan->band == NET80211_BAND_5GHZ || ratecode & NET80211_RATE_ERP) {
131                 /* OFDM encoding (802.11a/g) */
132                 int bits_per_symbol = (kbps * 4) / 1000; /* 4us/symbol */
133                 int bits = 22 + (bytes << 3); /* 22-bit PLCP */
134                 int symbols = (bits + bits_per_symbol - 1) / bits_per_symbol;
135                 return 16 + 20 + (symbols * 4); /* 16us SIFS, 20us preamble */
136         } else {
137                 /* CCK encoding (802.11b) */
138                 int phy_time = 144 + 48; /* preamble + PLCP */
139                 if (dev->erp_flags & NET80211_ERP_USE_SHORT_PREAMBLE)
140                         phy_time >>= 1;
141                 int bits = bytes << 3;
142                 int data_time = (bits * 1000) / kbps;
143                 return 10 + phy_time + data_time; /* 10us SIFS */
144         }
145 }
146
147 static int net80211_ll_push(struct net_device *netdev, struct io_buffer *iobuf,
148                             const void *ll_dest, const void *ll_source,
149                             uint16_t net_proto)
150 {
151         struct net80211_device *dev = netdev->priv;
152         struct ieee80211_frame *hdr = iob_push(iobuf, IEEE80211_LLC_HEADER_LEN +
153                                                IEEE80211_TYP_FRAME_HEADER_LEN);
154         struct ieee80211_llc_snap_header *lhdr = (struct ieee80211_llc_snap_header *)
155                 ((u8 *)hdr + IEEE80211_TYP_FRAME_HEADER_LEN);
156
157         hdr->fc = IEEE80211_THIS_VERSION | IEEE80211_TYPE_DATA |
158                   IEEE80211_STYPE_DATA | IEEE80211_FC_TODS;
159
160         /* We don't send fragmented frames, so duration is the time
161            for an SIFS + 10-byte ACK. */
162         hdr->duration = net80211_duration(dev, 10);
163
164         memcpy(hdr->addr1, dev->bssid, ETH_ALEN);
165         memcpy(hdr->addr2, ll_source, ETH_ALEN);
166         memcpy(hdr->addr3, ll_dest, ETH_ALEN);
167
168         hdr->seq = ++dev->last_tx_seqnr & 0x0FFF; /* fragment 0 */
169
170         lhdr->dsap = IEEE80211_LLC_DSAP;
171         lhdr->ssap = IEEE80211_LLC_SSAP;
172         lhdr->ctrl = IEEE80211_LLC_CTRL;
173         memset(lhdr->oui, 0x00, 3);
174         lhdr->ethertype = net_proto;
175
176         return 0;
177 }
178
179 static int net80211_ll_pull(struct net_device *netdev __unused,
180                             struct io_buffer *iobuf, const void **ll_dest,
181                             const void **ll_source, uint16_t *net_proto)
182 {
183         struct ieee80211_frame *hdr = iobuf->data;
184         struct ieee80211_llc_snap_header *lhdr = (struct ieee80211_llc_snap_header *)
185                 ((u8 *)hdr + IEEE80211_TYP_FRAME_HEADER_LEN);
186
187         /* Bunch of sanity checks */
188         if (iob_len(iobuf) < IEEE80211_TYP_FRAME_HEADER_LEN +
189                                 IEEE80211_LLC_HEADER_LEN) {
190                 DBG("802.11 packet too short (%zd bytes)\n", iob_len(iobuf));
191                 return -EINVAL;
192         }
193
194         if ((hdr->fc & IEEE80211_FC_VERSION) != IEEE80211_THIS_VERSION) {
195                 DBG("802.11 packet invalid version %04x\n",
196                     hdr->fc & IEEE80211_FC_VERSION);
197                 return -EINVAL;
198         }
199
200         if ((hdr->fc & IEEE80211_FC_TYPE) != IEEE80211_TYPE_DATA ||
201             (hdr->fc & IEEE80211_FC_SUBTYPE) != IEEE80211_STYPE_DATA) {
202                 DBG("802.11 packet not data/data (fc=%04x)\n", hdr->fc);
203                 return -EINVAL;
204         }
205
206         if ((hdr->fc & (IEEE80211_FC_TODS|IEEE80211_FC_FROMDS)) !=
207             IEEE80211_FC_FROMDS) {
208                 DBG("802.11 packet not from DS (fc=%04x)\n", hdr->fc);
209                 return -EINVAL;
210         }
211
212         if (lhdr->dsap != IEEE80211_LLC_DSAP || lhdr->ssap != IEEE80211_LLC_SSAP ||
213             lhdr->ctrl != IEEE80211_LLC_CTRL || lhdr->oui[0] || lhdr->oui[1] ||
214             lhdr->oui[2]) {
215                 DBG("802.11 LLC header is not plain EtherType encapsulator: "
216                     "%02x->%02x [%02x] %02x:%02x:%02x %04x\n",
217                     lhdr->dsap, lhdr->ssap, lhdr->ctrl, lhdr->oui[0],
218                     lhdr->oui[1], lhdr->oui[2], lhdr->ethertype);
219                 return -EINVAL;
220         }
221
222         iob_pull(iobuf, sizeof(*hdr) + sizeof(*lhdr));
223
224         *ll_dest = hdr->addr1;
225         *ll_source = hdr->addr3;
226         *net_proto = lhdr->ethertype;
227         return 0;
228 }
229
230 static int net80211_ll_mc_hash(unsigned int af __unused,
231                                const void *net_addr __unused,
232                                void *ll_addr __unused) 
233 {
234         return -ENOTSUP;
235 }
236
237 static struct ll_protocol net80211_ll_protocol __ll_protocol = {
238         .name           = "802.11",
239         .push           = net80211_ll_push,
240         .pull           = net80211_ll_pull,
241         .ntoa           = eth_ntoa,
242         .mc_hash        = net80211_ll_mc_hash,
243         .ll_proto       = htons(ARPHRD_ETHER), /* it's "encapsulated Ethernet" */
244         .ll_addr_len    = ETH_ALEN,
245         .ll_header_len  = IEEE80211_TYP_FRAME_HEADER_LEN +
246                           IEEE80211_LLC_HEADER_LEN,
247         .ll_broadcast   = net80211_ll_broadcast,
248 };
249
250 /* ---------- rest-of-gPXE 802.11 API ---------- */
251
252 struct net80211_device *net80211_get(struct net_device *netdev) 
253 {
254         struct net80211_device *dev;
255         
256         list_for_each_entry(dev, &net80211_devices, list) {
257                 if (netdev->priv == dev)
258                         return netdev->priv;
259         }
260
261         return NULL;
262 }
263
264 int net80211_keep_mgmt(struct net80211_device *dev, int enable) 
265 {
266         int oldenab = dev->keep_mgmt;
267         dev->keep_mgmt = enable;
268         return oldenab;
269 }
270
271 struct io_buffer *net80211_mgmt_dequeue(struct net80211_device *dev) 
272 {
273         struct io_buffer *iobuf;
274
275         list_for_each_entry(iobuf, &dev->mgmt_queue, list) {
276                 list_del(&iobuf->list);
277                 return iobuf;
278         }
279         return NULL;
280 }
281
282 /* ---------- driver API ---------- */
283
284 struct net80211_device *net80211_alloc(size_t priv_size) 
285 {
286         struct net80211_device *dev;
287         struct net_device *netdev = alloc_netdev(sizeof(*dev) + priv_size);
288
289         if (!netdev)
290                 return NULL;
291
292         netdev->ll_protocol = &net80211_ll_protocol;
293         netdev->max_pkt_len = IEEE80211_MAX_DATA_LEN;
294         netdev_init(netdev, &net80211_netdev_ops);
295
296         dev = netdev->priv;
297         dev->netdev = netdev;
298         dev->priv = (u8 *)dev + sizeof(*dev);
299         dev->op = &net80211_null_ops;
300         dev->last_rx_seq = -1;
301
302         INIT_LIST_HEAD(&dev->mgmt_queue);
303
304         return dev;
305 }
306
307 int net80211_register(struct net80211_device *dev,
308                       struct net80211_device_operations *ops,
309                       struct net80211_hw_info *hw) 
310 {
311         dev->op = ops;
312         dev->hw = malloc(sizeof(*hw));
313         if (!dev->hw)
314                 return -ENOMEM;
315
316         memcpy(dev->hw, hw, sizeof(*hw));
317         memcpy(dev->netdev->ll_addr, hw->hwaddr, ETH_ALEN);
318         
319         list_add_tail(&dev->list, &net80211_devices);
320         return register_netdev(dev->netdev);
321 }
322
323 void net80211_unregister(struct net80211_device *dev) 
324 {
325         unregister_netdev(dev->netdev);
326         list_del(&dev->list);
327         dev->op = &net80211_null_ops;
328 }
329
330 void net80211_free(struct net80211_device *dev) 
331 {
332         free(dev->hw);
333         netdev_nullify(dev->netdev);
334         netdev_put(dev->netdev);
335 }
336
337 /* ---------- packet handling ---------- */
338
339 /* Free the iob's for frag cache entry fcid and mark it unused. */
340 static void net80211_free_frags(struct net80211_device *dev, int fcid) 
341 {
342         int j;
343         struct net80211_frag_cache *frag = &dev->frags[fcid];
344
345         for (j = 0; j < 16; j++) {
346                 if (frag->iob[j]) {
347                         free_iob(frag->iob[j]);
348                         frag->iob[j] = NULL;
349                 }
350         }
351
352         frag->seqnr = 0;
353         frag->nfrags = 0;
354         frag->start_ticks = 0;
355         frag->state = NET80211_FRAG_AVAIL;
356 }
357
358 /* Accumulate fragments from frag cache entry fcid, of total size
359    `size' (headers included), into one iob and return it. */
360 static struct io_buffer *net80211_accum_frags(struct net80211_device *dev,
361                                               int fcid, int size)
362 {
363         struct net80211_frag_cache *frag = &dev->frags[fcid];
364         int hdrsize = IEEE80211_TYP_FRAME_HEADER_LEN;
365         int nfrags = frag->nfrags;
366         int nsize = size - hdrsize * (nfrags - 1);
367         int i;
368
369         struct io_buffer *niob = alloc_iob(nsize);
370         struct ieee80211_frame *hdr;
371
372         /* Add the header from the first one... */
373         memcpy(iob_put(niob, hdrsize), frag->iob[0]->data, hdrsize);
374
375         /* ... and all the data from all of them. */
376         for (i = 0; i < frag->nfrags; i++) {
377                 int len = iob_len(frag->iob[i]) - hdrsize;
378                 memcpy(iob_put(niob, len), frag->iob[i]->data + hdrsize, len);
379         }
380
381         /* Turn off the fragment bit. */
382         hdr = niob->data;
383         hdr->fc &= ~IEEE80211_FC_MORE_FRAG;
384
385         return niob;
386 }
387
388 static void net80211_rx_frag(struct net80211_device *dev, struct io_buffer *iob)
389 {
390         struct ieee80211_frame *hdr = iob->data;
391
392         if (IEEE80211_FRAG(hdr->seq) == 0 && (hdr->fc & IEEE80211_FC_MORE_FRAG)) {
393                 /* start a frag cache entry */
394                 int i, newest = -1;
395                 u32 curr_ticks = currticks(), newest_ticks = 0;
396                 u32 timeout = ticks_per_sec() * NET80211_FRAG_TIMEOUT;
397
398                 for (i = 0; i < NET80211_NR_CONCURRENT_FRAGS; i++) {
399                         if (dev->frags[i].state == NET80211_FRAG_AVAIL)
400                                 break;
401
402                         if (dev->frags[i].start_ticks + timeout >= curr_ticks) {
403                                 net80211_free_frags(dev, i);
404                                 break;
405                         }
406
407                         if (dev->frags[i].start_ticks > newest_ticks) {
408                                 newest = i;
409                                 newest_ticks = dev->frags[i].start_ticks;
410                         }
411                 }
412
413                 /* If we're being sent more concurrent fragmented
414                    packets than we can handle, drop the newest so the
415                    oldest has time to complete. */
416                 if (i == NET80211_NR_CONCURRENT_FRAGS) {
417                         i = newest;
418                         net80211_free_frags(dev, i);
419                 }
420
421                 dev->frags[i].state = NET80211_FRAG_WAITING;
422                 dev->frags[i].seqnr = IEEE80211_SEQNR(hdr->seq);
423                 dev->frags[i].start_ticks = currticks();
424                 dev->frags[i].iob[0] = iob;
425                 return;
426         } else {
427                 int i;
428                 for (i = 0; i < NET80211_NR_CONCURRENT_FRAGS; i++) {
429                         if (dev->frags[i].state != NET80211_FRAG_AVAIL &&
430                             dev->frags[i].seqnr == IEEE80211_SEQNR(hdr->seq))
431                                 break;
432                 }
433                 if (i == NET80211_NR_CONCURRENT_FRAGS)
434                         return; /* drop non-first not-in-cache fragments */
435
436                 dev->frags[i].iob[IEEE80211_FRAG(hdr->seq)] = iob;
437
438                 if (dev->frags[i].state == NET80211_FRAG_WAITING &&
439                     !(hdr->fc & IEEE80211_FC_MORE_FRAG)) {
440                         dev->frags[i].state = NET80211_FRAG_FINISHING;
441                         dev->frags[i].nfrags = IEEE80211_FRAG(hdr->seq) + 1;
442                 }
443                 
444                 if (dev->frags[i].state == NET80211_FRAG_FINISHING) {
445                         int j, size = 0;
446                         for (j = 0; j < dev->frags[i].nfrags; j++) {
447                                 size += iob_len(dev->frags[i].iob[j]);
448                                 if (dev->frags[i].iob[j] == NULL)
449                                         break;
450                         }
451                         if (j == dev->frags[i].nfrags) {
452                                 /* we've got everything! */
453                                 struct io_buffer *niob =
454                                         net80211_accum_frags(dev, i, size);
455                                 net80211_free_frags(dev, i);
456                                 net80211_rx(dev, niob);
457                         }
458                 }
459         }
460 }
461
462 void net80211_rx(struct net80211_device *dev, struct io_buffer *iob) 
463 {
464         struct ieee80211_frame *hdr = iob->data;
465         u16 type = hdr->fc & IEEE80211_FC_TYPE;
466         if ((hdr->fc & IEEE80211_FC_VERSION) != IEEE80211_THIS_VERSION)
467                 return;         /* drop invalid-version packets */
468
469         if (type == IEEE80211_TYPE_CTRL)
470                 return;         /* we don't handle control packets,
471                                    the hardware does */
472
473         if (dev->last_rx_seq == hdr->seq)
474                 return;         /* avoid duplicate packet */
475         dev->last_rx_seq = hdr->seq;
476
477         if (dev->hw->flags & NET80211_HW_RX_HAS_FCS) {
478                 /* discard the FCS */
479                 iob_unput(iob, 4);
480         }
481
482         if (hdr->fc & IEEE80211_FC_PROTECTED) {
483                 struct io_buffer *niob;
484                 if (!dev->crypto)
485                         return; /* can't decrypt packets on an open network */
486
487                 niob = dev->crypto->decrypt(dev, iob);
488                 if (!niob)
489                         return; /* drop failed decryption */
490                 free_iob(iob);
491                 iob = niob;
492         }
493
494         if (IEEE80211_FRAG(hdr->seq) != 0 || (hdr->fc & IEEE80211_FC_MORE_FRAG)) {
495                 net80211_rx_frag(dev, iob);
496                 return;
497         }
498
499         if (type == IEEE80211_TYPE_MGMT) {
500                 net80211_handle_mgmt(dev, iob);
501                 return;
502         } else {
503                 if ((hdr->fc & IEEE80211_FC_SUBTYPE) != IEEE80211_STYPE_DATA)
504                         return; /* drop QoS, CFP, or null data packets */
505
506                 if (dev->netdev->state & NETDEV_LINK_UP)
507                         netdev_rx(dev->netdev, iob);
508                 return;
509         }
510 }