Update b43 from compat-wireless-2008-05-26 codebase
[openwrt.git] / package / hostapd / patches / 002-add-nl80211-driver.patch
1 diff -urN hostapd.orig/driver_nl80211.c hostapd/driver_nl80211.c
2 --- a/hostapd/driver_nl80211.c  1970-01-01 01:00:00.000000000 +0100
3 +++ b/hostapd/driver_nl80211.c  2008-02-16 19:46:38.000000000 +0100
4 @@ -0,0 +1,2382 @@
5 +/*
6 + * hostapd / Kernel driver communication via nl80211
7 + * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
8 + * Copyright (c) 2003-2004, Instant802 Networks, Inc.
9 + * Copyright (c) 2005-2006, Devicescape Software, Inc.
10 + * Copyright (c) 2007, Johannes Berg <johannes@sipsolutions.net>
11 + *
12 + * This program is free software; you can redistribute it and/or modify
13 + * it under the terms of the GNU General Public License version 2 as
14 + * published by the Free Software Foundation.
15 + *
16 + * Alternatively, this software may be distributed under the terms of BSD
17 + * license.
18 + *
19 + * See README and COPYING for more details.
20 + */
21 +
22 +#include "includes.h"
23 +
24 +#include <sys/ioctl.h>
25 +#include <netlink/genl/genl.h>
26 +#include <netlink/genl/family.h>
27 +#include <netlink/genl/ctrl.h>
28 +#include <netlink/msg.h>
29 +#include <netlink/attr.h>
30 +#include <linux/nl80211.h>
31 +#include <net/if.h>
32 +#include <linux/if_packet.h>
33 +#include <linux/if_ether.h>   /* The L2 protocols */
34 +#include <linux/wireless.h>
35 +#include <net/if_arp.h>
36 +
37 +#include "hostapd.h"
38 +#include "driver.h"
39 +#include "ieee802_1x.h"
40 +#include "eloop.h"
41 +#include "ieee802_11.h"
42 +#include "sta_info.h"
43 +#include "hw_features.h"
44 +#include "mlme.h"
45 +#include "radiotap.h"
46 +#include "radiotap_iter.h"
47 +
48 +enum ieee80211_msg_type {
49 +       ieee80211_msg_normal = 0,
50 +       ieee80211_msg_tx_callback_ack = 1,
51 +       ieee80211_msg_tx_callback_fail = 2,
52 +};
53 +
54 +struct i802_driver_data {
55 +       struct hostapd_data *hapd;
56 +
57 +       char iface[IFNAMSIZ + 1];
58 +       int ioctl_sock; /* socket for ioctl() use */
59 +       int wext_sock; /* socket for wireless events */
60 +       int eapol_sock; /* socket for EAPOL frames */
61 +       int monitor_sock; /* socket for monitor */
62 +       int monitor_ifidx;
63 +
64 +       int default_if_indices[16];
65 +       int *if_indices;
66 +       int num_if_indices;
67 +
68 +       int we_version;
69 +       struct nl_handle *nl_handle;
70 +       struct nl_cache *nl_cache;
71 +       struct genl_family *nl80211;
72 +       int dtim_period;
73 +       unsigned int beacon_set:1;
74 +       unsigned int ieee802_1x_active:1;
75 +};
76 +
77 +
78 +static void add_ifidx(struct i802_driver_data *drv, int ifidx)
79 +{
80 +       int i;
81 +       int *old;
82 +
83 +       for (i = 0; i < drv->num_if_indices; i++) {
84 +               if (drv->if_indices[i] == 0) {
85 +                       drv->if_indices[i] = ifidx;
86 +                       return;
87 +               }
88 +       }
89 +
90 +       if (drv->if_indices != drv->default_if_indices)
91 +               old = drv->if_indices;
92 +       else
93 +               old = NULL;
94 +
95 +       drv->if_indices = realloc(old,
96 +                                 sizeof(int) * (drv->num_if_indices + 1));
97 +       if (!drv->if_indices) {
98 +               if (!old)
99 +                       drv->if_indices = drv->default_if_indices;
100 +               else
101 +                       drv->if_indices = old;
102 +               wpa_printf(MSG_ERROR, "Failed to reallocate memory for "
103 +                          "interfaces");
104 +               wpa_printf(MSG_ERROR, "Ignoring EAPOL on interface %d", ifidx);
105 +               return;
106 +       }
107 +       drv->if_indices[drv->num_if_indices] = ifidx;
108 +       drv->num_if_indices++;
109 +}
110 +
111 +
112 +static void del_ifidx(struct i802_driver_data *drv, int ifidx)
113 +{
114 +       int i;
115 +
116 +       for (i = 0; i < drv->num_if_indices; i++) {
117 +               if (drv->if_indices[i] == ifidx) {
118 +                       drv->if_indices[i] = 0;
119 +                       break;
120 +               }
121 +       }
122 +}
123 +
124 +
125 +static int have_ifidx(struct i802_driver_data *drv, int ifidx)
126 +{
127 +       int i;
128 +
129 +       for (i = 0; i < drv->num_if_indices; i++)
130 +               if (drv->if_indices[i] == ifidx)
131 +                       return 1;
132 +
133 +       return 0;
134 +}
135 +
136 +
137 +/* helper for netlink get routines */
138 +static int ack_wait_handler(struct nl_msg *msg, void *arg)
139 +{
140 +       int *finished = arg;
141 +
142 +       *finished = 1;
143 +       return NL_STOP;
144 +}
145 +
146 +
147 +static int hostapd_set_iface_flags(struct i802_driver_data *drv,
148 +                                  const char *ifname, int dev_up)
149 +{
150 +       struct ifreq ifr;
151 +
152 +       if (drv->ioctl_sock < 0)
153 +               return -1;
154 +
155 +       memset(&ifr, 0, sizeof(ifr));
156 +       os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
157 +
158 +       if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, &ifr) != 0) {
159 +               perror("ioctl[SIOCGIFFLAGS]");
160 +               wpa_printf(MSG_DEBUG, "Could not read interface flags (%s)",
161 +                          drv->iface);
162 +               return -1;
163 +       }
164 +
165 +       if (dev_up)
166 +               ifr.ifr_flags |= IFF_UP;
167 +       else
168 +               ifr.ifr_flags &= ~IFF_UP;
169 +
170 +       if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, &ifr) != 0) {
171 +               perror("ioctl[SIOCSIFFLAGS]");
172 +               return -1;
173 +       }
174 +
175 +       return 0;
176 +}
177 +
178 +
179 +static int i802_set_encryption(const char *iface, void *priv, const char *alg,
180 +                              const u8 *addr, int idx, const u8 *key,
181 +                              size_t key_len, int txkey)
182 +{
183 +       struct i802_driver_data *drv = priv;
184 +       struct nl_msg *msg;
185 +       int ret = -1;
186 +       int err = 0;
187 +
188 +       msg = nlmsg_alloc();
189 +       if (!msg)
190 +               goto out;
191 +
192 +       if (strcmp(alg, "none") == 0) {
193 +               genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
194 +                           0, NL80211_CMD_DEL_KEY, 0);
195 +       } else {
196 +               genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
197 +                           0, NL80211_CMD_NEW_KEY, 0);
198 +               NLA_PUT(msg, NL80211_ATTR_KEY_DATA, key_len, key);
199 +               if (strcmp(alg, "WEP") == 0) {
200 +                       if (key_len == 5)
201 +                               NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
202 +                                           0x000FAC01);
203 +                       else
204 +                               NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
205 +                                           0x000FAC05);
206 +               } else if (strcmp(alg, "TKIP") == 0)
207 +                       NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, 0x000FAC02);
208 +               else if (strcmp(alg, "CCMP") == 0)
209 +                       NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, 0x000FAC04);
210 +               else
211 +                       goto out;
212 +       }
213 +
214 +       if (addr)
215 +               NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
216 +       NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, idx);
217 +       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(iface));
218 +
219 +       if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
220 +           (err = nl_wait_for_ack(drv->nl_handle)) < 0) {
221 +               if (err != -ENOENT) {
222 +                       err = 0;
223 +                       goto out;
224 +               }
225 +       }
226 +
227 +       /*
228 +        * If we need to set the default TX key we do that below,
229 +        * otherwise we're done here.
230 +        */
231 +       if (!txkey || addr) {
232 +               ret = 0;
233 +               goto out;
234 +       }
235 +
236 +       nlmsg_free(msg);
237 +
238 +       msg = nlmsg_alloc();
239 +       if (!msg)
240 +               goto out;
241 +
242 +       genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
243 +                   0, NL80211_CMD_SET_KEY, 0);
244 +       NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, idx);
245 +       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(iface));
246 +       NLA_PUT_FLAG(msg, NL80211_ATTR_KEY_DEFAULT);
247 +
248 +       if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
249 +           (err = nl_wait_for_ack(drv->nl_handle)) < 0) {
250 +               if (err != -ENOENT) {
251 +                       err = 0;
252 +                       goto out;
253 +               }
254 +       }
255 +
256 +       ret = 0;
257 +
258 + out:
259 + nla_put_failure:
260 +       nlmsg_free(msg);
261 +       return ret;
262 +}
263 +
264 +
265 +static inline int min_int(int a, int b)
266 +{
267 +       if (a < b)
268 +               return a;
269 +       return b;
270 +}
271 +
272 +
273 +static int get_key_handler(struct nl_msg *msg, void *arg)
274 +{
275 +       struct nlattr *tb[NL80211_ATTR_MAX];
276 +       struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
277 +
278 +       nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
279 +                 genlmsg_attrlen(gnlh, 0), NULL);
280 +
281 +       /*
282 +        * TODO: validate the key index and mac address!
283 +        * Otherwise, there's a race condition as soon as
284 +        * the kernel starts sending key notifications.
285 +        */
286 +
287 +       if (tb[NL80211_ATTR_KEY_SEQ])
288 +               memcpy(arg, nla_data(tb[NL80211_ATTR_KEY_SEQ]),
289 +                      min_int(nla_len(tb[NL80211_ATTR_KEY_SEQ]), 6));
290 +       return NL_SKIP;
291 +}
292 +
293 +
294 +static int i802_get_seqnum(const char *iface, void *priv, const u8 *addr,
295 +                          int idx, u8 *seq)
296 +{
297 +       struct i802_driver_data *drv = priv;
298 +       struct nl_msg *msg;
299 +       struct nl_cb *cb = NULL;
300 +       int ret = -1;
301 +       int err = 0;
302 +       int finished = 0;
303 +
304 +       msg = nlmsg_alloc();
305 +       if (!msg)
306 +               goto out;
307 +
308 +       genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
309 +                   0, NL80211_CMD_GET_KEY, 0);
310 +
311 +       if (addr)
312 +               NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
313 +       NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, idx);
314 +       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(iface));
315 +
316 +       cb = nl_cb_alloc(NL_CB_CUSTOM);
317 +       if (!cb)
318 +               goto out;
319 +
320 +       memset(seq, 0, 6);
321 +
322 +       if (nl_send_auto_complete(drv->nl_handle, msg) < 0)
323 +               goto out;
324 +
325 +       nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, get_key_handler, seq);
326 +       nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_wait_handler, &finished);
327 +
328 +       err = nl_recvmsgs(drv->nl_handle, cb);
329 +
330 +       if (!finished)
331 +               err = nl_wait_for_ack(drv->nl_handle);
332 +
333 +       if (err < 0)
334 +               goto out;
335 +
336 +       ret = 0;
337 +
338 + out:
339 +       nl_cb_put(cb);
340 + nla_put_failure:
341 +       nlmsg_free(msg);
342 +       return ret;
343 +}
344 +
345 +
346 +static int i802_set_rate_sets(void *priv, int *supp_rates, int *basic_rates,
347 +                             int mode)
348 +{
349 +       return -1;
350 +}
351 +
352 +
353 +static int i802_set_ssid(const char *ifname, void *priv, const u8 *buf,
354 +                        int len)
355 +{
356 +       struct i802_driver_data *drv = priv;
357 +       struct iwreq iwr;
358 +
359 +       memset(&iwr, 0, sizeof(iwr));
360 +       os_strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
361 +       iwr.u.essid.flags = 1; /* SSID active */
362 +       iwr.u.essid.pointer = (caddr_t) buf;
363 +       iwr.u.essid.length = len;
364 +
365 +       if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0) {
366 +               perror("ioctl[SIOCSIWESSID]");
367 +               printf("len=%d\n", len);
368 +               return -1;
369 +       }
370 +
371 +       return 0;
372 +}
373 +
374 +
375 +static int i802_send_mgmt_frame(void *priv, const void *data, size_t len,
376 +                               int flags)
377 +{
378 +       struct ieee80211_hdr *hdr = (void*) data;
379 +       __u8 rtap_hdr[] = {
380 +               0x00, 0x00, /* radiotap version */
381 +               0x0e, 0x00, /* radiotap length */
382 +               0x02, 0xc0, 0x00, 0x00, /* bmap: flags, tx and rx flags */
383 +               0x0c,       /* F_WEP | F_FRAG (encrypt/fragment if required) */
384 +               0x00,       /* padding */
385 +               0x00, 0x00, /* RX and TX flags to indicate that */
386 +               0x00, 0x00, /* this is the injected frame directly */
387 +       };
388 +       struct i802_driver_data *drv = priv;
389 +       struct iovec iov[2] = {
390 +               {
391 +                       .iov_base = &rtap_hdr,
392 +                       .iov_len = sizeof(rtap_hdr),
393 +               },
394 +               {
395 +                       .iov_base = (void*)data,
396 +                       .iov_len = len,
397 +               }
398 +       };
399 +       struct msghdr msg = {
400 +               .msg_name = NULL,
401 +               .msg_namelen = 0,
402 +               .msg_iov = iov,
403 +               .msg_iovlen = 2,
404 +               .msg_control = NULL,
405 +               .msg_controllen = 0,
406 +               .msg_flags = 0,
407 +       };
408 +
409 +       /*
410 +        * ugh, guess what, the generic code sets one of the version
411 +        * bits to request tx callback
412 +        */
413 +       hdr->frame_control &= ~host_to_le16(BIT(1));
414 +       return sendmsg(drv->monitor_sock, &msg, flags);
415 +}
416 +
417 +
418 +/* Set kernel driver on given frequency (MHz) */
419 +static int i802_set_freq(void *priv, int mode, int freq)
420 +{
421 +       struct i802_driver_data *drv = priv;
422 +       struct iwreq iwr;
423 +
424 +       memset(&iwr, 0, sizeof(iwr));
425 +       os_strlcpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ);
426 +       iwr.u.freq.m = freq;
427 +       iwr.u.freq.e = 6;
428 +
429 +       if (ioctl(drv->ioctl_sock, SIOCSIWFREQ, &iwr) < 0) {
430 +               perror("ioctl[SIOCSIWFREQ]");
431 +               return -1;
432 +       }
433 +
434 +       return 0;
435 +}
436 +
437 +
438 +static int i802_set_rts(void *priv, int rts)
439 +{
440 +       struct i802_driver_data *drv = priv;
441 +       struct iwreq iwr;
442 +
443 +       memset(&iwr, 0, sizeof(iwr));
444 +       os_strlcpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ);
445 +       iwr.u.rts.value = rts;
446 +       iwr.u.rts.fixed = 1;
447 +
448 +       if (ioctl(drv->ioctl_sock, SIOCSIWRTS, &iwr) < 0) {
449 +               perror("ioctl[SIOCSIWRTS]");
450 +               return -1;
451 +       }
452 +
453 +       return 0;
454 +}
455 +
456 +
457 +static int i802_get_rts(void *priv, int *rts)
458 +{
459 +       struct i802_driver_data *drv = priv;
460 +       struct iwreq iwr;
461 +
462 +       memset(&iwr, 0, sizeof(iwr));
463 +       os_strlcpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ);
464 +
465 +       if (ioctl(drv->ioctl_sock, SIOCGIWRTS, &iwr) < 0) {
466 +               perror("ioctl[SIOCGIWRTS]");
467 +               return -1;
468 +       }
469 +
470 +       *rts = iwr.u.rts.value;
471 +
472 +       return 0;
473 +}
474 +
475 +
476 +static int i802_set_frag(void *priv, int frag)
477 +{
478 +       struct i802_driver_data *drv = priv;
479 +       struct iwreq iwr;
480 +
481 +       memset(&iwr, 0, sizeof(iwr));
482 +       os_strlcpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ);
483 +       iwr.u.frag.value = frag;
484 +       iwr.u.frag.fixed = 1;
485 +
486 +       if (ioctl(drv->ioctl_sock, SIOCSIWFRAG, &iwr) < 0) {
487 +               perror("ioctl[SIOCSIWFRAG]");
488 +               return -1;
489 +       }
490 +
491 +       return 0;
492 +}
493 +
494 +
495 +static int i802_get_frag(void *priv, int *frag)
496 +{
497 +       struct i802_driver_data *drv = priv;
498 +       struct iwreq iwr;
499 +
500 +       memset(&iwr, 0, sizeof(iwr));
501 +       os_strlcpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ);
502 +
503 +       if (ioctl(drv->ioctl_sock, SIOCGIWFRAG, &iwr) < 0) {
504 +               perror("ioctl[SIOCGIWFRAG]");
505 +               return -1;
506 +       }
507 +
508 +       *frag = iwr.u.frag.value;
509 +
510 +       return 0;
511 +}
512 +
513 +
514 +static int i802_set_retry(void *priv, int short_retry, int long_retry)
515 +{
516 +       struct i802_driver_data *drv = priv;
517 +       struct iwreq iwr;
518 +
519 +       memset(&iwr, 0, sizeof(iwr));
520 +       os_strlcpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ);
521 +
522 +       iwr.u.retry.value = short_retry;
523 +       iwr.u.retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN;
524 +       if (ioctl(drv->ioctl_sock, SIOCSIWFRAG, &iwr) < 0) {
525 +               perror("ioctl[SIOCSIWRETRY(short)]");
526 +               return -1;
527 +       }
528 +
529 +       iwr.u.retry.value = long_retry;
530 +       iwr.u.retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
531 +       if (ioctl(drv->ioctl_sock, SIOCSIWFRAG, &iwr) < 0) {
532 +               perror("ioctl[SIOCSIWRETRY(long)]");
533 +               return -1;
534 +       }
535 +
536 +       return 0;
537 +}
538 +
539 +
540 +static int i802_get_retry(void *priv, int *short_retry, int *long_retry)
541 +{
542 +       struct i802_driver_data *drv = priv;
543 +       struct iwreq iwr;
544 +
545 +       memset(&iwr, 0, sizeof(iwr));
546 +       os_strlcpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ);
547 +
548 +       iwr.u.retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN;
549 +       if (ioctl(drv->ioctl_sock, SIOCGIWRETRY, &iwr) < 0) {
550 +               perror("ioctl[SIOCGIWFRAG(short)]");
551 +               return -1;
552 +       }
553 +       *short_retry = iwr.u.retry.value;
554 +
555 +       iwr.u.retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
556 +       if (ioctl(drv->ioctl_sock, SIOCGIWRETRY, &iwr) < 0) {
557 +               perror("ioctl[SIOCGIWFRAG(long)]");
558 +               return -1;
559 +       }
560 +       *long_retry = iwr.u.retry.value;
561 +
562 +       return 0;
563 +}
564 +
565 +
566 +static int i802_flush(void *priv)
567 +{
568 +       struct i802_driver_data *drv = priv;
569 +       struct nl_msg *msg;
570 +       int ret = -1;
571 +
572 +       msg = nlmsg_alloc();
573 +       if (!msg)
574 +               goto out;
575 +
576 +       genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
577 +                   0, NL80211_CMD_NEW_STATION, 0);
578 +
579 +       /*
580 +        * XXX: FIX! this needs to flush all VLANs too
581 +        */
582 +       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
583 +                   if_nametoindex(drv->iface));
584 +
585 +       ret = 0;
586 +
587 +       if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
588 +           nl_wait_for_ack(drv->nl_handle) < 0) {
589 +               ret = -1;
590 +       }
591 +
592 + nla_put_failure:
593 +       nlmsg_free(msg);
594 +
595 + out:
596 +       return ret;
597 +}
598 +
599 +
600 +static int get_sta_handler(struct nl_msg *msg, void *arg)
601 +{
602 +       struct nlattr *tb[NL80211_ATTR_MAX + 1];
603 +       struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
604 +       struct hostap_sta_driver_data *data = arg;
605 +       struct nlattr *stats[NL80211_STA_STAT_MAX + 1];
606 +       static struct nla_policy stats_policy[NL80211_STA_STAT_MAX + 1] = {
607 +               [NL80211_STA_STAT_INACTIVE_TIME] = { .type = NLA_U32 },
608 +               [NL80211_STA_STAT_RX_BYTES] = { .type = NLA_U32 },
609 +               [NL80211_STA_STAT_TX_BYTES] = { .type = NLA_U32 },
610 +       };
611 +
612 +       nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
613 +                 genlmsg_attrlen(gnlh, 0), NULL);
614 +
615 +       /*
616 +        * TODO: validate the interface and mac address!
617 +        * Otherwise, there's a race condition as soon as
618 +        * the kernel starts sending station notifications.
619 +        */
620 +
621 +       if (!tb[NL80211_ATTR_STA_STATS]) {
622 +               wpa_printf(MSG_DEBUG, "sta stats missing!");
623 +               return NL_SKIP;
624 +       }
625 +       if (nla_parse_nested(stats, NL80211_STA_STAT_MAX,
626 +                            tb[NL80211_ATTR_STA_STATS],
627 +                            stats_policy)) {
628 +               wpa_printf(MSG_DEBUG, "failed to parse nested attributes!");
629 +               return NL_SKIP;
630 +       }
631 +
632 +       if (stats[NL80211_STA_STAT_INACTIVE_TIME])
633 +               data->inactive_msec =
634 +                       nla_get_u32(stats[NL80211_STA_STAT_INACTIVE_TIME]);
635 +       if (stats[NL80211_STA_STAT_RX_BYTES])
636 +               data->rx_bytes = nla_get_u32(stats[NL80211_STA_STAT_RX_BYTES]);
637 +       if (stats[NL80211_STA_STAT_TX_BYTES])
638 +               data->rx_bytes = nla_get_u32(stats[NL80211_STA_STAT_TX_BYTES]);
639 +
640 +       return NL_SKIP;
641 +}
642 +
643 +static int i802_read_sta_data(void *priv, struct hostap_sta_driver_data *data,
644 +                             const u8 *addr)
645 +{
646 +       struct i802_driver_data *drv = priv;
647 +       struct nl_msg *msg;
648 +       struct nl_cb *cb = NULL;
649 +       int ret = -1;
650 +       int err = 0;
651 +       int finished = 0;
652 +
653 +       msg = nlmsg_alloc();
654 +       if (!msg)
655 +               goto out;
656 +
657 +       genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
658 +                   0, NL80211_CMD_GET_STATION, 0);
659 +
660 +       NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
661 +       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface));
662 +
663 +       cb = nl_cb_alloc(NL_CB_CUSTOM);
664 +       if (!cb)
665 +               goto out;
666 +
667 +       if (nl_send_auto_complete(drv->nl_handle, msg) < 0)
668 +               goto out;
669 +
670 +       nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, get_sta_handler, data);
671 +       nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_wait_handler, &finished);
672 +
673 +       err = nl_recvmsgs(drv->nl_handle, cb);
674 +
675 +       if (!finished)
676 +               err = nl_wait_for_ack(drv->nl_handle);
677 +
678 +       if (err < 0)
679 +               goto out;
680 +
681 +       ret = 0;
682 +
683 + out:
684 +       nl_cb_put(cb);
685 + nla_put_failure:
686 +       nlmsg_free(msg);
687 +       return ret;
688 +
689 +}
690 +
691 +
692 +static int i802_send_eapol(void *priv, const u8 *addr, const u8 *data,
693 +                          size_t data_len, int encrypt, const u8 *own_addr)
694 +{
695 +       struct i802_driver_data *drv = priv;
696 +       struct ieee80211_hdr *hdr;
697 +       size_t len;
698 +       u8 *pos;
699 +       int res;
700 +#if 0 /* FIX */
701 +       int qos = sta->flags & WLAN_STA_WME;
702 +#else
703 +       int qos = 0;
704 +#endif
705 +
706 +       len = sizeof(*hdr) + (qos ? 2 : 0) + sizeof(rfc1042_header) + 2 +
707 +               data_len;
708 +       hdr = os_zalloc(len);
709 +       if (hdr == NULL) {
710 +               printf("malloc() failed for i802_send_data(len=%lu)\n",
711 +                      (unsigned long) len);
712 +               return -1;
713 +       }
714 +
715 +       hdr->frame_control =
716 +               IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA);
717 +       hdr->frame_control |= host_to_le16(WLAN_FC_FROMDS);
718 +       if (encrypt)
719 +               hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);
720 +#if 0 /* To be enabled if qos determination is added above */
721 +       if (qos) {
722 +               hdr->frame_control |=
723 +                       host_to_le16(WLAN_FC_STYPE_QOS_DATA << 4);
724 +       }
725 +#endif
726 +
727 +       memcpy(hdr->IEEE80211_DA_FROMDS, addr, ETH_ALEN);
728 +       memcpy(hdr->IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);
729 +       memcpy(hdr->IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
730 +       pos = (u8 *) (hdr + 1);
731 +
732 +#if 0 /* To be enabled if qos determination is added above */
733 +       if (qos) {
734 +               /* add an empty QoS header if needed */
735 +               pos[0] = 0;
736 +               pos[1] = 0;
737 +               pos += 2;
738 +       }
739 +#endif
740 +
741 +       memcpy(pos, rfc1042_header, sizeof(rfc1042_header));
742 +       pos += sizeof(rfc1042_header);
743 +       WPA_PUT_BE16(pos, ETH_P_PAE);
744 +       pos += 2;
745 +       memcpy(pos, data, data_len);
746 +
747 +       res = i802_send_mgmt_frame(drv, (u8 *) hdr, len, 0);
748 +       free(hdr);
749 +
750 +       if (res < 0) {
751 +               perror("i802_send_eapol: send");
752 +               printf("i802_send_eapol - packet len: %lu - failed\n",
753 +                      (unsigned long) len);
754 +       }
755 +
756 +       return res;
757 +}
758 +
759 +
760 +static int i802_sta_add(const char *ifname, void *priv, const u8 *addr,
761 +                       u16 aid, u16 capability, u8 *supp_rates,
762 +                       size_t supp_rates_len, int flags)
763 +{
764 +       struct i802_driver_data *drv = priv;
765 +       struct nl_msg *msg;
766 +       int ret = -1;
767 +
768 +       msg = nlmsg_alloc();
769 +       if (!msg)
770 +               goto out;
771 +
772 +       genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
773 +                   0, NL80211_CMD_NEW_STATION, 0);
774 +
775 +       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
776 +                   if_nametoindex(drv->iface));
777 +       NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
778 +       NLA_PUT_U16(msg, NL80211_ATTR_STA_AID, aid);
779 +       NLA_PUT(msg, NL80211_ATTR_STA_SUPPORTED_RATES, supp_rates_len,
780 +               supp_rates);
781 +       NLA_PUT_U16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL, 0);
782 +
783 +       ret = nl_send_auto_complete(drv->nl_handle, msg);
784 +       if (ret < 0)
785 +               goto nla_put_failure;
786 +
787 +       ret = nl_wait_for_ack(drv->nl_handle);
788 +       /* ignore EEXIST, this happens if a STA associates while associated */
789 +       if (ret == -EEXIST || ret >= 0)
790 +               ret = 0;
791 +
792 + nla_put_failure:
793 +       nlmsg_free(msg);
794 +
795 + out:
796 +       return ret;
797 +}
798 +
799 +
800 +static int i802_sta_remove(void *priv, const u8 *addr)
801 +{
802 +       struct i802_driver_data *drv = priv;
803 +       struct nl_msg *msg;
804 +       int ret = -1;
805 +
806 +       msg = nlmsg_alloc();
807 +       if (!msg)
808 +               goto out;
809 +
810 +       genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
811 +                   0, NL80211_CMD_DEL_STATION, 0);
812 +
813 +       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
814 +                   if_nametoindex(drv->iface));
815 +       NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
816 +
817 +       ret = 0;
818 +
819 +       if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
820 +           nl_wait_for_ack(drv->nl_handle) < 0) {
821 +               ret = -1;
822 +       }
823 +
824 + nla_put_failure:
825 +       nlmsg_free(msg);
826 +
827 + out:
828 +       return ret;
829 +}
830 +
831 +
832 +static int i802_sta_set_flags(void *priv, const u8 *addr,
833 +                             int total_flags, int flags_or, int flags_and)
834 +{
835 +       struct i802_driver_data *drv = priv;
836 +       struct nl_msg *msg, *flags = NULL;
837 +       int ret = -1;
838 +
839 +       msg = nlmsg_alloc();
840 +       if (!msg)
841 +               goto out;
842 +
843 +       flags = nlmsg_alloc();
844 +       if (!flags)
845 +               goto free_msg;
846 +
847 +       genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
848 +                   0, NL80211_CMD_SET_STATION, 0);
849 +
850 +       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
851 +                   if_nametoindex(drv->iface));
852 +       NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
853 +
854 +       if (total_flags & WLAN_STA_AUTHORIZED || !drv->ieee802_1x_active)
855 +               NLA_PUT_FLAG(flags, NL80211_STA_FLAG_AUTHORIZED);
856 +
857 +       if (total_flags & WLAN_STA_WME)
858 +               NLA_PUT_FLAG(flags, NL80211_STA_FLAG_WME);
859 +
860 +       if (total_flags & WLAN_STA_SHORT_PREAMBLE)
861 +               NLA_PUT_FLAG(flags, NL80211_STA_FLAG_SHORT_PREAMBLE);
862 +
863 +       if (nla_put_nested(msg, NL80211_ATTR_STA_FLAGS, flags))
864 +               goto nla_put_failure;
865 +
866 +       ret = 0;
867 +
868 +       if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
869 +           nl_wait_for_ack(drv->nl_handle) < 0) {
870 +               ret = -1;
871 +       }
872 +
873 + nla_put_failure:
874 +       nlmsg_free(flags);
875 +
876 + free_msg:
877 +       nlmsg_free(msg);
878 +
879 + out:
880 +       return ret;
881 +}
882 +
883 +
884 +static int i802_set_channel_flag(void *priv, int mode, int chan, int flag,
885 +                                unsigned char power_level,
886 +                                unsigned char antenna_max)
887 +{
888 +       return -1;
889 +}
890 +
891 +
892 +static int i802_set_regulatory_domain(void *priv, unsigned int rd)
893 +{
894 +       return -1;
895 +}
896 +
897 +
898 +static int i802_set_tx_queue_params(void *priv, int queue, int aifs,
899 +                                   int cw_min, int cw_max, int burst_time)
900 +{
901 +       return -1;
902 +}
903 +
904 +
905 +static void nl80211_remove_iface(struct i802_driver_data *drv, int ifidx)
906 +{
907 +       struct nl_msg *msg;
908 +
909 +       /* stop listening for EAPOL on this interface */
910 +       del_ifidx(drv, ifidx);
911 +
912 +       msg = nlmsg_alloc();
913 +       if (!msg)
914 +               goto nla_put_failure;
915 +
916 +       genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
917 +                   0, NL80211_CMD_DEL_INTERFACE, 0);
918 +       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifidx);
919 +       if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
920 +           nl_wait_for_ack(drv->nl_handle) < 0)
921 +       nla_put_failure:
922 +               printf("Failed to remove interface.\n");
923 +       nlmsg_free(msg);
924 +}
925 +
926 +
927 +static int nl80211_create_iface(struct i802_driver_data *drv,
928 +                               const char *ifname,
929 +                               enum nl80211_iftype iftype,
930 +                               const u8 *addr)
931 +{
932 +       struct nl_msg *msg, *flags = NULL;
933 +       int ifidx;
934 +       struct ifreq ifreq;
935 +       struct iwreq iwr;
936 +
937 +       msg = nlmsg_alloc();
938 +       if (!msg)
939 +               return -1;
940 +
941 +       genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
942 +                   0, NL80211_CMD_NEW_INTERFACE, 0);
943 +       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
944 +                   if_nametoindex(drv->hapd->conf->iface));
945 +       NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, ifname);
946 +       NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, iftype);
947 +
948 +       if (iftype == NL80211_IFTYPE_MONITOR) {
949 +               int err;
950 +
951 +               flags = nlmsg_alloc();
952 +               if (!flags)
953 +                       goto nla_put_failure;
954 +
955 +               NLA_PUT_FLAG(flags, NL80211_MNTR_FLAG_COOK_FRAMES);
956 +
957 +               err = nla_put_nested(msg, NL80211_ATTR_MNTR_FLAGS, flags);
958 +
959 +               nlmsg_free(flags);
960 +
961 +               if (err)
962 +                       goto nla_put_failure;
963 +       }
964 +
965 +       if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
966 +           nl_wait_for_ack(drv->nl_handle) < 0) {
967 + nla_put_failure:
968 +               printf("Failed to create interface %s.\n", ifname);
969 +               nlmsg_free(msg);
970 +               return -1;
971 +       }
972 +
973 +       nlmsg_free(msg);
974 +
975 +       ifidx = if_nametoindex(ifname);
976 +
977 +       if (ifidx <= 0)
978 +               return -1;
979 +
980 +       /* start listening for EAPOL on this interface */
981 +       add_ifidx(drv, ifidx);
982 +
983 +       if (addr) {
984 +               switch (iftype) {
985 +               case NL80211_IFTYPE_AP:
986 +                       os_strlcpy(ifreq.ifr_name, ifname, IFNAMSIZ);
987 +                       memcpy(ifreq.ifr_hwaddr.sa_data, addr, ETH_ALEN);
988 +                       ifreq.ifr_hwaddr.sa_family = ARPHRD_ETHER;
989 +
990 +                       if (ioctl(drv->ioctl_sock, SIOCSIFHWADDR, &ifreq)) {
991 +                               nl80211_remove_iface(drv, ifidx);
992 +                               return -1;
993 +                       }
994 +                       break;
995 +               case NL80211_IFTYPE_WDS:
996 +                       memset(&iwr, 0, sizeof(iwr));
997 +                       os_strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
998 +                       iwr.u.addr.sa_family = ARPHRD_ETHER;
999 +                       memcpy(iwr.u.addr.sa_data, addr, ETH_ALEN);
1000 +                       if (ioctl(drv->ioctl_sock, SIOCSIWAP, &iwr))
1001 +                               return -1;
1002 +                       break;
1003 +               default:
1004 +                       /* nothing */
1005 +                       break;
1006 +               }
1007 +       }
1008 +
1009 +       return ifidx;
1010 +}
1011 +
1012 +
1013 +static int i802_bss_add(void *priv, const char *ifname, const u8 *bssid)
1014 +{
1015 +       int ifidx;
1016 +
1017 +       /*
1018 +        * The kernel supports that when the low-level driver does,
1019 +        * but we currently don't because we need per-BSS data that
1020 +        * currently we can't handle easily.
1021 +        */
1022 +       return -1;
1023 +
1024 +       ifidx = nl80211_create_iface(priv, ifname, NL80211_IFTYPE_AP, bssid);
1025 +       if (ifidx < 0)
1026 +               return -1;
1027 +       if (hostapd_set_iface_flags(priv, ifname, 1)) {
1028 +               nl80211_remove_iface(priv, ifidx);
1029 +               return -1;
1030 +       }
1031 +       return 0;
1032 +}
1033 +
1034 +
1035 +static int i802_bss_remove(void *priv, const char *ifname)
1036 +{
1037 +       nl80211_remove_iface(priv, if_nametoindex(ifname));
1038 +       return 0;
1039 +}
1040 +
1041 +
1042 +static int i802_set_beacon(const char *iface, void *priv,
1043 +                          u8 *head, size_t head_len,
1044 +                          u8 *tail, size_t tail_len)
1045 +{
1046 +       struct i802_driver_data *drv = priv;
1047 +       struct nl_msg *msg;
1048 +       u8 cmd = NL80211_CMD_NEW_BEACON;
1049 +       int ret = -1;
1050 +
1051 +       msg = nlmsg_alloc();
1052 +       if (!msg)
1053 +               goto out;
1054 +
1055 +       if (drv->beacon_set)
1056 +               cmd = NL80211_CMD_SET_BEACON;
1057 +
1058 +       genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
1059 +                   0, cmd, 0);
1060 +       NLA_PUT(msg, NL80211_ATTR_BEACON_HEAD, head_len, head);
1061 +       NLA_PUT(msg, NL80211_ATTR_BEACON_TAIL, tail_len, tail);
1062 +       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(iface));
1063 +       NLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL, 1000);
1064 +
1065 +       if (!drv->dtim_period)
1066 +               drv->dtim_period = 2;
1067 +       NLA_PUT_U32(msg, NL80211_ATTR_DTIM_PERIOD, drv->dtim_period);
1068 +
1069 +       if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
1070 +           nl_wait_for_ack(drv->nl_handle) < 0)
1071 +               goto out;
1072 +
1073 +       ret = 0;
1074 +
1075 +       drv->beacon_set = 1;
1076 +
1077 + out:
1078 + nla_put_failure:
1079 +       nlmsg_free(msg);
1080 +       return ret;
1081 +}
1082 +
1083 +
1084 +static int i802_del_beacon(struct i802_driver_data *drv)
1085 +{
1086 +       struct nl_msg *msg;
1087 +       int ret = -1;
1088 +
1089 +       msg = nlmsg_alloc();
1090 +       if (!msg)
1091 +               goto out;
1092 +
1093 +       genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
1094 +                   0, NL80211_CMD_DEL_BEACON, 0);
1095 +       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface));
1096 +
1097 +       if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
1098 +           nl_wait_for_ack(drv->nl_handle) < 0)
1099 +               goto out;
1100 +
1101 +       ret = 0;
1102 +
1103 + out:
1104 + nla_put_failure:
1105 +       nlmsg_free(msg);
1106 +       return ret;
1107 +}
1108 +
1109 +
1110 +static int i802_set_ieee8021x(const char *ifname, void *priv, int enabled)
1111 +{
1112 +       struct i802_driver_data *drv = priv;
1113 +
1114 +       /*
1115 +        * FIXME: This needs to be per interface (BSS)
1116 +        */
1117 +       drv->ieee802_1x_active = enabled;
1118 +       return 0;
1119 +}
1120 +
1121 +
1122 +static int i802_set_privacy(const char *ifname, void *priv, int enabled)
1123 +{
1124 +       struct i802_driver_data *drv = priv;
1125 +       struct iwreq iwr;
1126 +
1127 +       memset(&iwr, 0, sizeof(iwr));
1128 +
1129 +       os_strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
1130 +       iwr.u.param.flags = IW_AUTH_PRIVACY_INVOKED;
1131 +       iwr.u.param.value = enabled;
1132 +
1133 +       ioctl(drv->ioctl_sock, SIOCSIWAUTH, &iwr);
1134 +
1135 +       /* ignore errors, the kernel/driver might not care */
1136 +       return 0;
1137 +}
1138 +
1139 +
1140 +static int i802_set_internal_bridge(void *priv, int value)
1141 +{
1142 +       return -1;
1143 +}
1144 +
1145 +
1146 +static int i802_set_beacon_int(void *priv, int value)
1147 +{
1148 +       struct i802_driver_data *drv = priv;
1149 +       struct nl_msg *msg;
1150 +       int ret = -1;
1151 +
1152 +       msg = nlmsg_alloc();
1153 +       if (!msg)
1154 +               goto out;
1155 +
1156 +       genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
1157 +                   0, NL80211_CMD_SET_BEACON, 0);
1158 +       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface));
1159 +
1160 +       NLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL, value);
1161 +
1162 +       if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
1163 +           nl_wait_for_ack(drv->nl_handle) < 0)
1164 +               goto out;
1165 +
1166 +       ret = 0;
1167 +
1168 + out:
1169 + nla_put_failure:
1170 +       nlmsg_free(msg);
1171 +       return ret;
1172 +}
1173 +
1174 +
1175 +static int i802_set_dtim_period(const char *iface, void *priv, int value)
1176 +{
1177 +       struct i802_driver_data *drv = priv;
1178 +       struct nl_msg *msg;
1179 +       int ret = -1;
1180 +
1181 +       msg = nlmsg_alloc();
1182 +       if (!msg)
1183 +               goto out;
1184 +
1185 +       genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
1186 +                   0, NL80211_CMD_SET_BEACON, 0);
1187 +       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(iface));
1188 +
1189 +       drv->dtim_period = value;
1190 +       NLA_PUT_U32(msg, NL80211_ATTR_DTIM_PERIOD, drv->dtim_period);
1191 +
1192 +       if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
1193 +           nl_wait_for_ack(drv->nl_handle) < 0)
1194 +               goto out;
1195 +
1196 +       ret = 0;
1197 +
1198 + out:
1199 + nla_put_failure:
1200 +       nlmsg_free(msg);
1201 +       return ret;
1202 +}
1203 +
1204 +
1205 +static int i802_set_cts_protect(void *priv, int value)
1206 +{
1207 +       return -1;
1208 +}
1209 +
1210 +
1211 +static int i802_set_preamble(void *priv, int value)
1212 +{
1213 +       return -1;
1214 +}
1215 +
1216 +
1217 +static int i802_set_short_slot_time(void *priv, int value)
1218 +{
1219 +       return -1;
1220 +}
1221 +
1222 +
1223 +static enum nl80211_iftype i802_if_type(enum hostapd_driver_if_type type)
1224 +{
1225 +       switch (type) {
1226 +       case HOSTAPD_IF_VLAN:
1227 +               return NL80211_IFTYPE_AP_VLAN;
1228 +       case HOSTAPD_IF_WDS:
1229 +               return NL80211_IFTYPE_WDS;
1230 +       }
1231 +       return -1;
1232 +}
1233 +
1234 +
1235 +static int i802_if_add(const char *iface, void *priv,
1236 +                      enum hostapd_driver_if_type type, char *ifname,
1237 +                      const u8 *addr)
1238 +{
1239 +       if (nl80211_create_iface(priv, ifname, i802_if_type(type), addr) < 0)
1240 +               return -1;
1241 +       return 0;
1242 +}
1243 +
1244 +
1245 +static int i802_if_update(void *priv, enum hostapd_driver_if_type type,
1246 +                         char *ifname, const u8 *addr)
1247 +{
1248 +       /* unused at the moment */
1249 +       return -1;
1250 +}
1251 +
1252 +
1253 +static int i802_if_remove(void *priv, enum hostapd_driver_if_type type,
1254 +                         const char *ifname, const u8 *addr)
1255 +{
1256 +       nl80211_remove_iface(priv, if_nametoindex(ifname));
1257 +       return 0;
1258 +}
1259 +
1260 +
1261 +struct phy_info_arg {
1262 +       u16 *num_modes;
1263 +       struct hostapd_hw_modes *modes;
1264 +       int error;
1265 +};
1266 +
1267 +static int phy_info_handler(struct nl_msg *msg, void *arg)
1268 +{
1269 +       struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
1270 +       struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
1271 +       struct phy_info_arg *phy_info = arg;
1272 +
1273 +       struct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1];
1274 +
1275 +       struct nlattr *tb_freq[NL80211_FREQUENCY_ATTR_MAX + 1];
1276 +       static struct nla_policy freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {
1277 +               [NL80211_FREQUENCY_ATTR_FREQ] = { .type = NLA_U32 },
1278 +               [NL80211_FREQUENCY_ATTR_DISABLED] = { .type = NLA_FLAG },
1279 +               [NL80211_FREQUENCY_ATTR_PASSIVE_SCAN] = { .type = NLA_FLAG },
1280 +               [NL80211_FREQUENCY_ATTR_NO_IBSS] = { .type = NLA_FLAG },
1281 +               [NL80211_FREQUENCY_ATTR_RADAR] = { .type = NLA_FLAG },
1282 +       };
1283 +
1284 +       struct nlattr *tb_rate[NL80211_BITRATE_ATTR_MAX + 1];
1285 +       static struct nla_policy rate_policy[NL80211_BITRATE_ATTR_MAX + 1] = {
1286 +               [NL80211_BITRATE_ATTR_RATE] = { .type = NLA_U32 },
1287 +               [NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE] = { .type = NLA_FLAG },
1288 +       };
1289 +
1290 +       struct nlattr *nl_band;
1291 +       struct nlattr *nl_freq;
1292 +       struct nlattr *nl_rate;
1293 +       int rem_band, rem_freq, rem_rate;
1294 +       struct hostapd_hw_modes *mode;
1295 +       int idx, mode_is_set;
1296 +
1297 +       nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
1298 +                 genlmsg_attrlen(gnlh, 0), NULL);
1299 +
1300 +       if (!tb_msg[NL80211_ATTR_WIPHY_BANDS])
1301 +               return NL_SKIP;
1302 +
1303 +       nla_for_each_nested(nl_band, tb_msg[NL80211_ATTR_WIPHY_BANDS], rem_band) {
1304 +               mode = realloc(phy_info->modes, (*phy_info->num_modes + 1) * sizeof(*mode));
1305 +               if (!mode)
1306 +                       return NL_SKIP;
1307 +               phy_info->modes = mode;
1308 +
1309 +               mode_is_set = 0;
1310 +
1311 +               mode = &phy_info->modes[*(phy_info->num_modes)];
1312 +               memset(mode, 0, sizeof(*mode));
1313 +               *(phy_info->num_modes) += 1;
1314 +
1315 +               nla_parse(tb_band, NL80211_BAND_ATTR_MAX, nla_data(nl_band),
1316 +                         nla_len(nl_band), NULL);
1317 +
1318 +               nla_for_each_nested(nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], rem_freq) {
1319 +                       nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, nla_data(nl_freq),
1320 +                                 nla_len(nl_freq), freq_policy);
1321 +                       if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])
1322 +                               continue;
1323 +                       mode->num_channels++;
1324 +               }
1325 +
1326 +               mode->channels = calloc(mode->num_channels, sizeof(struct hostapd_channel_data));
1327 +               if (!mode->channels)
1328 +                       return NL_SKIP;
1329 +
1330 +               idx = 0;
1331 +
1332 +               nla_for_each_nested(nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], rem_freq) {
1333 +                       nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, nla_data(nl_freq),
1334 +                                 nla_len(nl_freq), freq_policy);
1335 +                       if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ])
1336 +                               continue;
1337 +
1338 +                       mode->channels[idx].freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]);
1339 +                       mode->channels[idx].flag |= HOSTAPD_CHAN_W_SCAN |
1340 +                                                   HOSTAPD_CHAN_W_ACTIVE_SCAN |
1341 +                                                   HOSTAPD_CHAN_W_IBSS;
1342 +
1343 +                       if (!mode_is_set) {
1344 +                               /* crude heuristic */
1345 +                               if (mode->channels[idx].freq < 4000)
1346 +                                       mode->mode = HOSTAPD_MODE_IEEE80211B;
1347 +                               else
1348 +                                       mode->mode = HOSTAPD_MODE_IEEE80211A;
1349 +                               mode_is_set = 1;
1350 +                       }
1351 +
1352 +                       /* crude heuristic */
1353 +                       if (mode->channels[idx].freq < 4000)
1354 +                               if (mode->channels[idx].freq == 2848)
1355 +                                       mode->channels[idx].chan = 14;
1356 +                               else
1357 +                                       mode->channels[idx].chan = (mode->channels[idx].freq - 2407) / 5;
1358 +                       else
1359 +                               mode->channels[idx].chan = mode->channels[idx].freq/5 - 1000;
1360 +
1361 +                       if (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED])
1362 +                               mode->channels[idx].flag &= ~HOSTAPD_CHAN_W_SCAN;
1363 +                       if (tb_freq[NL80211_FREQUENCY_ATTR_PASSIVE_SCAN])
1364 +                               mode->channels[idx].flag &= ~HOSTAPD_CHAN_W_ACTIVE_SCAN;
1365 +                       if (tb_freq[NL80211_FREQUENCY_ATTR_NO_IBSS])
1366 +                               mode->channels[idx].flag &= ~HOSTAPD_CHAN_W_IBSS;
1367 +                       idx++;
1368 +               }
1369 +
1370 +               nla_for_each_nested(nl_rate, tb_band[NL80211_BAND_ATTR_RATES], rem_rate) {
1371 +                       nla_parse(tb_rate, NL80211_BITRATE_ATTR_MAX, nla_data(nl_rate),
1372 +                                 nla_len(nl_rate), rate_policy);
1373 +                       if (!tb_rate[NL80211_BITRATE_ATTR_RATE])
1374 +                               continue;
1375 +                       mode->num_rates++;
1376 +               }
1377 +
1378 +               mode->rates = calloc(mode->num_rates, sizeof(struct hostapd_rate_data));
1379 +               if (!mode->rates)
1380 +                       return NL_SKIP;
1381 +
1382 +               idx = 0;
1383 +
1384 +               nla_for_each_nested(nl_rate, tb_band[NL80211_BAND_ATTR_RATES], rem_rate) {
1385 +                       nla_parse(tb_rate, NL80211_BITRATE_ATTR_MAX, nla_data(nl_rate),
1386 +                                 nla_len(nl_rate), rate_policy);
1387 +                       if (!tb_rate[NL80211_BITRATE_ATTR_RATE])
1388 +                               continue;
1389 +                       mode->rates[idx].rate = nla_get_u32(tb_rate[NL80211_BITRATE_ATTR_RATE]);
1390 +
1391 +                       /* crude heuristic */
1392 +                       if (mode->mode == HOSTAPD_MODE_IEEE80211B &&
1393 +                           mode->rates[idx].rate > 200)
1394 +                               mode->mode = HOSTAPD_MODE_IEEE80211G;
1395 +
1396 +                       if (tb_rate[NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE])
1397 +                               mode->rates[idx].flags |= HOSTAPD_RATE_PREAMBLE2;
1398 +
1399 +                       idx++;
1400 +               }
1401 +       }
1402 +
1403 +       phy_info->error = 0;
1404 +
1405 +       return NL_SKIP;
1406 +}
1407 +
1408 +static struct hostapd_hw_modes *i802_get_hw_feature_data(void *priv,
1409 +                                                        u16 *num_modes,
1410 +                                                        u16 *flags)
1411 +{
1412 +       struct i802_driver_data *drv = priv;
1413 +       struct nl_msg *msg;
1414 +       int err = -1;
1415 +       struct nl_cb *cb = NULL;
1416 +       int finished;
1417 +       struct phy_info_arg result = {
1418 +               .num_modes = num_modes,
1419 +               .modes = NULL,
1420 +               .error = 1,
1421 +       };
1422 +
1423 +       *num_modes = 0;
1424 +       *flags = 0;
1425 +
1426 +       msg = nlmsg_alloc();
1427 +       if (!msg)
1428 +               return NULL;
1429 +
1430 +       genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
1431 +                   0, NL80211_CMD_GET_WIPHY, 0);
1432 +
1433 +       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface));
1434 +
1435 +       cb = nl_cb_alloc(NL_CB_CUSTOM);
1436 +       if (!cb)
1437 +               goto out;
1438 +
1439 +       if (nl_send_auto_complete(drv->nl_handle, msg) < 0)
1440 +               goto out;
1441 +
1442 +       nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, phy_info_handler, &result);
1443 +       nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_wait_handler, &finished);
1444 +
1445 +       err = nl_recvmsgs(drv->nl_handle, cb);
1446 +
1447 +       if (!finished)
1448 +               err = nl_wait_for_ack(drv->nl_handle);
1449 +
1450 +       if (err < 0 || result.error) {
1451 +               hostapd_free_hw_features(result.modes, *num_modes);
1452 +               result.modes = NULL;
1453 +       }
1454 +
1455 + out:
1456 +       nl_cb_put(cb);
1457 + nla_put_failure:
1458 +       if (err)
1459 +               fprintf(stderr, "failed to get information: %d\n", err);
1460 +       nlmsg_free(msg);
1461 +       return result.modes;
1462 +}
1463 +
1464 +
1465 +static int i802_set_sta_vlan(void *priv, const u8 *addr,
1466 +                            const char *ifname, int vlan_id)
1467 +{
1468 +       struct i802_driver_data *drv = priv;
1469 +       struct nl_msg *msg;
1470 +       int ret = -1;
1471 +
1472 +       msg = nlmsg_alloc();
1473 +       if (!msg)
1474 +               goto out;
1475 +
1476 +       genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
1477 +                   0, NL80211_CMD_SET_STATION, 0);
1478 +
1479 +       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
1480 +                   if_nametoindex(drv->iface));
1481 +       NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
1482 +       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
1483 +                   if_nametoindex(ifname));
1484 +
1485 +       ret = 0;
1486 +
1487 +       if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
1488 +           (errno = nl_wait_for_ack(drv->nl_handle) < 0)) {
1489 +               ret = -1;
1490 +       }
1491 +
1492 + nla_put_failure:
1493 +       nlmsg_free(msg);
1494 +
1495 + out:
1496 +       return ret;
1497 +}
1498 +
1499 +
1500 +static void handle_unknown_sta(struct hostapd_data *hapd, u8 *ta)
1501 +{
1502 +       struct sta_info *sta;
1503 +
1504 +       sta = ap_get_sta(hapd, ta);
1505 +       if (!sta || !(sta->flags & WLAN_STA_ASSOC)) {
1506 +               printf("Data/PS-poll frame from not associated STA "
1507 +                      MACSTR "\n", MAC2STR(ta));
1508 +               if (sta && (sta->flags & WLAN_STA_AUTH))
1509 +                       hostapd_sta_disassoc(
1510 +                               hapd, ta,
1511 +                               WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
1512 +               else
1513 +                       hostapd_sta_deauth(
1514 +                               hapd, ta,
1515 +                               WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
1516 +       }
1517 +}
1518 +
1519 +
1520 +static void handle_tx_callback(struct hostapd_data *hapd, u8 *buf, size_t len,
1521 +                              int ok)
1522 +{
1523 +       struct ieee80211_hdr *hdr;
1524 +       u16 fc, type, stype;
1525 +       struct sta_info *sta;
1526 +
1527 +       hdr = (struct ieee80211_hdr *) buf;
1528 +       fc = le_to_host16(hdr->frame_control);
1529 +
1530 +       type = WLAN_FC_GET_TYPE(fc);
1531 +       stype = WLAN_FC_GET_STYPE(fc);
1532 +
1533 +       switch (type) {
1534 +       case WLAN_FC_TYPE_MGMT:
1535 +               wpa_printf(MSG_DEBUG, "MGMT (TX callback) %s",
1536 +                          ok ? "ACK" : "fail");
1537 +               ieee802_11_mgmt_cb(hapd, buf, len, stype, ok);
1538 +               break;
1539 +       case WLAN_FC_TYPE_CTRL:
1540 +               wpa_printf(MSG_DEBUG, "CTRL (TX callback) %s",
1541 +                          ok ? "ACK" : "fail");
1542 +               break;
1543 +       case WLAN_FC_TYPE_DATA:
1544 +               wpa_printf(MSG_DEBUG, "DATA (TX callback) %s",
1545 +                          ok ? "ACK" : "fail");
1546 +               sta = ap_get_sta(hapd, hdr->addr1);
1547 +               if (sta && sta->flags & WLAN_STA_PENDING_POLL) {
1548 +                       wpa_printf(MSG_DEBUG, "STA " MACSTR " %s pending "
1549 +                                  "activity poll", MAC2STR(sta->addr),
1550 +                                  ok ? "ACKed" : "did not ACK");
1551 +                       if (ok)
1552 +                               sta->flags &= ~WLAN_STA_PENDING_POLL;
1553 +               }
1554 +               if (sta)
1555 +                       ieee802_1x_tx_status(hapd, sta, buf, len, ok);
1556 +               break;
1557 +       default:
1558 +               printf("unknown TX callback frame type %d\n", type);
1559 +               break;
1560 +       }
1561 +}
1562 +
1563 +
1564 +static void handle_frame(struct hostapd_iface *iface, u8 *buf, size_t len,
1565 +                        struct hostapd_frame_info *hfi,
1566 +                        enum ieee80211_msg_type msg_type)
1567 +{
1568 +       struct ieee80211_hdr *hdr;
1569 +       u16 fc, type, stype;
1570 +       size_t data_len = len;
1571 +       struct hostapd_data *hapd = NULL;
1572 +       int broadcast_bssid = 0;
1573 +       size_t i;
1574 +       u8 *bssid;
1575 +
1576 +       /*
1577 +        * PS-Poll frames are 16 bytes. All other frames are
1578 +        * 24 bytes or longer.
1579 +        */
1580 +       if (len < 16)
1581 +               return;
1582 +
1583 +       hdr = (struct ieee80211_hdr *) buf;
1584 +       fc = le_to_host16(hdr->frame_control);
1585 +
1586 +       type = WLAN_FC_GET_TYPE(fc);
1587 +       stype = WLAN_FC_GET_STYPE(fc);
1588 +
1589 +       switch (type) {
1590 +       case WLAN_FC_TYPE_DATA:
1591 +               if (len < 24)
1592 +                       return;
1593 +               switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
1594 +               case WLAN_FC_TODS:
1595 +                       bssid = hdr->addr1;
1596 +                       break;
1597 +               default:
1598 +                       /* discard */
1599 +                       return;
1600 +               }
1601 +               break;
1602 +       case WLAN_FC_TYPE_CTRL:
1603 +               /* discard non-ps-poll frames */
1604 +               if (stype != WLAN_FC_STYPE_PSPOLL)
1605 +                       return;
1606 +               bssid = hdr->addr1;
1607 +               break;
1608 +       case WLAN_FC_TYPE_MGMT:
1609 +               bssid = hdr->addr3;
1610 +               break;
1611 +       default:
1612 +               /* discard */
1613 +               return;
1614 +       }
1615 +
1616 +       /* find interface frame belongs to */
1617 +       for (i = 0; i < iface->num_bss; i++) {
1618 +               if (memcmp(bssid, iface->bss[i]->own_addr, ETH_ALEN) == 0) {
1619 +                       hapd = iface->bss[i];
1620 +                       break;
1621 +               }
1622 +       }
1623 +
1624 +       if (hapd == NULL) {
1625 +               hapd = iface->bss[0];
1626 +
1627 +               if (bssid[0] != 0xff || bssid[1] != 0xff ||
1628 +                   bssid[2] != 0xff || bssid[3] != 0xff ||
1629 +                   bssid[4] != 0xff || bssid[5] != 0xff) {
1630 +                       /*
1631 +                        * Unknown BSSID - drop frame if this is not from
1632 +                        * passive scanning or a beacon (at least ProbeReq
1633 +                        * frames to other APs may be allowed through RX
1634 +                        * filtering in the wlan hw/driver)
1635 +                        */
1636 +                       if ((type != WLAN_FC_TYPE_MGMT ||
1637 +                            stype != WLAN_FC_STYPE_BEACON))
1638 +                               return;
1639 +               } else
1640 +                       broadcast_bssid = 1;
1641 +       }
1642 +
1643 +       switch (msg_type) {
1644 +       case ieee80211_msg_normal:
1645 +               /* continue processing */
1646 +               break;
1647 +       case ieee80211_msg_tx_callback_ack:
1648 +               handle_tx_callback(hapd, buf, data_len, 1);
1649 +               return;
1650 +       case ieee80211_msg_tx_callback_fail:
1651 +               handle_tx_callback(hapd, buf, data_len, 0);
1652 +               return;
1653 +       }
1654 +
1655 +       switch (type) {
1656 +       case WLAN_FC_TYPE_MGMT:
1657 +               if (stype != WLAN_FC_STYPE_BEACON &&
1658 +                   stype != WLAN_FC_STYPE_PROBE_REQ)
1659 +                       wpa_printf(MSG_MSGDUMP, "MGMT");
1660 +               if (broadcast_bssid) {
1661 +                       for (i = 0; i < iface->num_bss; i++)
1662 +                               ieee802_11_mgmt(iface->bss[i], buf, data_len,
1663 +                                               stype, hfi);
1664 +               } else
1665 +                       ieee802_11_mgmt(hapd, buf, data_len, stype, hfi);
1666 +               break;
1667 +       case WLAN_FC_TYPE_CTRL:
1668 +               /* can only get here with PS-Poll frames */
1669 +               wpa_printf(MSG_DEBUG, "CTRL");
1670 +               handle_unknown_sta(hapd, hdr->addr2);
1671 +               break;
1672 +       case WLAN_FC_TYPE_DATA:
1673 +               wpa_printf(MSG_DEBUG, "DATA");
1674 +               handle_unknown_sta(hapd, hdr->addr2);
1675 +               break;
1676 +       }
1677 +}
1678 +
1679 +
1680 +static void handle_eapol(int sock, void *eloop_ctx, void *sock_ctx)
1681 +{
1682 +       struct i802_driver_data *drv = eloop_ctx;
1683 +       struct hostapd_data *hapd = drv->hapd;
1684 +       struct sockaddr_ll lladdr;
1685 +       unsigned char buf[3000];
1686 +       int len;
1687 +       socklen_t fromlen = sizeof(lladdr);
1688 +
1689 +       len = recvfrom(sock, buf, sizeof(buf), 0,
1690 +                      (struct sockaddr *)&lladdr, &fromlen);
1691 +       if (len < 0) {
1692 +               perror("recv");
1693 +               return;
1694 +       }
1695 +
1696 +       if (have_ifidx(drv, lladdr.sll_ifindex))
1697 +               ieee802_1x_receive(hapd, lladdr.sll_addr, buf, len);
1698 +}
1699 +
1700 +
1701 +static void handle_monitor_read(int sock, void *eloop_ctx, void *sock_ctx)
1702 +{
1703 +       struct i802_driver_data *drv = eloop_ctx;
1704 +       int len;
1705 +       unsigned char buf[3000];
1706 +       struct hostapd_data *hapd = drv->hapd;
1707 +       struct ieee80211_radiotap_iterator iter;
1708 +       int ret;
1709 +       struct hostapd_frame_info hfi;
1710 +       int injected = 0, failed = 0, msg_type, rxflags = 0;
1711 +
1712 +       len = recv(sock, buf, sizeof(buf), 0);
1713 +       if (len < 0) {
1714 +               perror("recv");
1715 +               return;
1716 +       }
1717 +
1718 +       if (ieee80211_radiotap_iterator_init(&iter, (void*)buf, len)) {
1719 +               printf("received invalid radiotap frame\n");
1720 +               return;
1721 +       }
1722 +
1723 +       memset(&hfi, 0, sizeof(hfi));
1724 +
1725 +       while (1) {
1726 +               ret = ieee80211_radiotap_iterator_next(&iter);
1727 +               if (ret == -ENOENT)
1728 +                       break;
1729 +               if (ret) {
1730 +                       printf("received invalid radiotap frame (%d)\n", ret);
1731 +                       return;
1732 +               }
1733 +               switch (iter.this_arg_index) {
1734 +               case IEEE80211_RADIOTAP_FLAGS:
1735 +                       if (*iter.this_arg & IEEE80211_RADIOTAP_F_FCS)
1736 +                               len -= 4;
1737 +                       break;
1738 +               case IEEE80211_RADIOTAP_RX_FLAGS:
1739 +                       rxflags = 1;
1740 +                       break;
1741 +               case IEEE80211_RADIOTAP_TX_FLAGS:
1742 +                       injected = 1;
1743 +                       failed = le_to_host16((*(uint16_t *) iter.this_arg)) &
1744 +                                       IEEE80211_RADIOTAP_F_TX_FAIL;
1745 +                       break;
1746 +               case IEEE80211_RADIOTAP_DATA_RETRIES:
1747 +                       break;
1748 +               case IEEE80211_RADIOTAP_CHANNEL:
1749 +                       /* TODO convert from freq/flags to channel number
1750 +                       hfi.channel = XXX;
1751 +                       hfi.phytype = XXX;
1752 +                        */
1753 +                       break;
1754 +               case IEEE80211_RADIOTAP_RATE:
1755 +                       hfi.datarate = *iter.this_arg * 5;
1756 +                       break;
1757 +               case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
1758 +                       hfi.ssi_signal = *iter.this_arg;
1759 +                       break;
1760 +               }
1761 +       }
1762 +
1763 +       if (rxflags && injected)
1764 +               return;
1765 +
1766 +       if (!injected)
1767 +               msg_type = ieee80211_msg_normal;
1768 +       else if (failed)
1769 +               msg_type = ieee80211_msg_tx_callback_fail;
1770 +       else
1771 +               msg_type = ieee80211_msg_tx_callback_ack;
1772 +
1773 +       handle_frame(hapd->iface, buf + iter.max_length,
1774 +                    len - iter.max_length, &hfi, msg_type);
1775 +}
1776 +
1777 +
1778 +static int nl80211_create_monitor_interface(struct i802_driver_data *drv)
1779 +{
1780 +       char buf[IFNAMSIZ];
1781 +       struct sockaddr_ll ll;
1782 +       int optval;
1783 +       socklen_t optlen;
1784 +
1785 +       snprintf(buf, IFNAMSIZ, "mon.%s", drv->iface);
1786 +       buf[IFNAMSIZ - 1] = '\0';
1787 +
1788 +       drv->monitor_ifidx =
1789 +               nl80211_create_iface(drv, buf, NL80211_IFTYPE_MONITOR, NULL);
1790 +
1791 +       if (drv->monitor_ifidx < 0)
1792 +               return -1;
1793 +
1794 +       if (hostapd_set_iface_flags(drv, buf, 1))
1795 +               goto error;
1796 +
1797 +       memset(&ll, 0, sizeof(ll));
1798 +       ll.sll_family = AF_PACKET;
1799 +       ll.sll_ifindex = drv->monitor_ifidx;
1800 +       drv->monitor_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
1801 +       if (drv->monitor_sock < 0) {
1802 +               perror("socket[PF_PACKET,SOCK_RAW]");
1803 +               goto error;
1804 +       }
1805 +
1806 +       if (bind(drv->monitor_sock, (struct sockaddr *) &ll,
1807 +                sizeof(ll)) < 0) {
1808 +               perror("monitor socket bind");
1809 +               goto error;
1810 +       }
1811 +
1812 +       optlen = sizeof(optval);
1813 +       optval = 20;
1814 +       if (setsockopt
1815 +           (drv->monitor_sock, SOL_SOCKET, SO_PRIORITY, &optval, optlen)) {
1816 +               perror("Failed to set socket priority");
1817 +               goto error;
1818 +       }
1819 +
1820 +       if (eloop_register_read_sock(drv->monitor_sock, handle_monitor_read,
1821 +                                    drv, NULL)) {
1822 +               printf("Could not register monitor read socket\n");
1823 +               goto error;
1824 +       }
1825 +
1826 +       return 0;
1827 + error:
1828 +       nl80211_remove_iface(drv, drv->monitor_ifidx);
1829 +       return -1;
1830 +}
1831 +
1832 +
1833 +static int nl80211_set_master_mode(struct i802_driver_data *drv,
1834 +                                  const char *ifname)
1835 +{
1836 +       struct nl_msg *msg;
1837 +
1838 +       msg = nlmsg_alloc();
1839 +       if (!msg)
1840 +               return -1;
1841 +
1842 +       genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
1843 +                   0, NL80211_CMD_SET_INTERFACE, 0);
1844 +       NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
1845 +                   if_nametoindex(ifname));
1846 +       NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_AP);
1847 +
1848 +       if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
1849 +           nl_wait_for_ack(drv->nl_handle) < 0) {
1850 + nla_put_failure:
1851 +               wpa_printf(MSG_ERROR, "Failed to set interface %s to master "
1852 +                          "mode.", ifname);
1853 +               nlmsg_free(msg);
1854 +               return -1;
1855 +       }
1856 +
1857 +       nlmsg_free(msg);
1858 +
1859 +       return 0;
1860 +}
1861 +  
1862 +
1863 +static int i802_init_sockets(struct i802_driver_data *drv, const u8 *bssid)
1864 +{
1865 +       struct ifreq ifr;
1866 +       struct sockaddr_ll addr;
1867 +
1868 +       drv->ioctl_sock = -1;
1869 +
1870 +       drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
1871 +       if (drv->ioctl_sock < 0) {
1872 +               perror("socket[PF_INET,SOCK_DGRAM]");
1873 +               return -1;
1874 +       }
1875 +
1876 +       /* start listening for EAPOL on the default AP interface */
1877 +       add_ifidx(drv, if_nametoindex(drv->iface));
1878 +
1879 +       if (hostapd_set_iface_flags(drv, drv->iface, 0))
1880 +               return -1;
1881 +
1882 +       if (bssid) {
1883 +               os_strlcpy(ifr.ifr_name, drv->iface, IFNAMSIZ);
1884 +               memcpy(ifr.ifr_hwaddr.sa_data, bssid, ETH_ALEN);
1885 +               ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
1886 +
1887 +               if (ioctl(drv->ioctl_sock, SIOCSIFHWADDR, &ifr)) {
1888 +                       perror("ioctl(SIOCSIFHWADDR)");
1889 +                       return -1;
1890 +               }
1891 +       }
1892 +
1893 +       /*
1894 +        * initialise generic netlink and nl80211
1895 +        */
1896 +       drv->nl_handle = nl_handle_alloc();
1897 +       if (!drv->nl_handle) {
1898 +               printf("Failed to allocate netlink handle.\n");
1899 +               return -1;
1900 +       }
1901 +
1902 +       if (genl_connect(drv->nl_handle)) {
1903 +               printf("Failed to connect to generic netlink.\n");
1904 +               return -1;
1905 +       }
1906 +
1907 +       drv->nl_cache = genl_ctrl_alloc_cache(drv->nl_handle);
1908 +       if (!drv->nl_cache) {
1909 +               printf("Failed to allocate generic netlink cache.\n");
1910 +               return -1;
1911 +       }
1912 +
1913 +       drv->nl80211 = genl_ctrl_search_by_name(drv->nl_cache, "nl80211");
1914 +       if (!drv->nl80211) {
1915 +               printf("nl80211 not found.\n");
1916 +               return -1;
1917 +       }
1918 +
1919 +       /* Initialise a monitor interface */
1920 +       if (nl80211_create_monitor_interface(drv))
1921 +               return -1;
1922 +
1923 +       if (nl80211_set_master_mode(drv, drv->iface))
1924 +               return -1;
1925 +
1926 +       if (hostapd_set_iface_flags(drv, drv->iface, 1))
1927 +               return -1;
1928 +
1929 +       memset(&addr, 0, sizeof(addr));
1930 +       addr.sll_family = AF_PACKET;
1931 +       addr.sll_ifindex = ifr.ifr_ifindex;
1932 +       wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d",
1933 +                  addr.sll_ifindex);
1934 +
1935 +       drv->eapol_sock = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_PAE));
1936 +       if (drv->eapol_sock < 0) {
1937 +               perror("socket(PF_PACKET, SOCK_DGRAM, ETH_P_PAE)");
1938 +               return -1;
1939 +       }
1940 +
1941 +       if (eloop_register_read_sock(drv->eapol_sock, handle_eapol, drv, NULL))
1942 +       {
1943 +               printf("Could not register read socket for eapol\n");
1944 +               return -1;
1945 +       }
1946 +
1947 +        memset(&ifr, 0, sizeof(ifr));
1948 +        os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name));
1949 +        if (ioctl(drv->ioctl_sock, SIOCGIFHWADDR, &ifr) != 0) {
1950 +               perror("ioctl(SIOCGIFHWADDR)");
1951 +               return -1;
1952 +        }
1953 +
1954 +       if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
1955 +               printf("Invalid HW-addr family 0x%04x\n",
1956 +                      ifr.ifr_hwaddr.sa_family);
1957 +               return -1;
1958 +       }
1959 +       memcpy(drv->hapd->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
1960 +
1961 +       return 0;
1962 +}
1963 +
1964 +
1965 +static int i802_get_inact_sec(void *priv, const u8 *addr)
1966 +{
1967 +       struct hostap_sta_driver_data data;
1968 +       int ret;
1969 +
1970 +       data.inactive_msec = (unsigned long) -1;
1971 +       ret = i802_read_sta_data(priv, &data, addr);
1972 +       if (ret || data.inactive_msec == (unsigned long) -1)
1973 +               return -1;
1974 +       return data.inactive_msec / 1000;
1975 +}
1976 +
1977 +
1978 +static int i802_sta_clear_stats(void *priv, const u8 *addr)
1979 +{
1980 +#if 0
1981 +       /* TODO */
1982 +#endif
1983 +       return 0;
1984 +}
1985 +
1986 +
1987 +static void
1988 +hostapd_wireless_event_wireless_custom(struct i802_driver_data *drv,
1989 +                                      char *custom)
1990 +{
1991 +       wpa_printf(MSG_DEBUG, "Custom wireless event: '%s'", custom);
1992 +
1993 +       if (strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) {
1994 +               char *pos;
1995 +               u8 addr[ETH_ALEN];
1996 +               pos = strstr(custom, "addr=");
1997 +               if (pos == NULL) {
1998 +                       wpa_printf(MSG_DEBUG,
1999 +                                  "MLME-MICHAELMICFAILURE.indication "
2000 +                                  "without sender address ignored");
2001 +                       return;
2002 +               }
2003 +               pos += 5;
2004 +               if (hwaddr_aton(pos, addr) == 0) {
2005 +                       ieee80211_michael_mic_failure(drv->hapd, addr, 1);
2006 +               } else {
2007 +                       wpa_printf(MSG_DEBUG,
2008 +                                  "MLME-MICHAELMICFAILURE.indication "
2009 +                                  "with invalid MAC address");
2010 +               }
2011 +       }
2012 +}
2013 +
2014 +
2015 +static void hostapd_wireless_event_wireless(struct i802_driver_data *drv,
2016 +                                           char *data, int len)
2017 +{
2018 +       struct iw_event iwe_buf, *iwe = &iwe_buf;
2019 +       char *pos, *end, *custom, *buf;
2020 +
2021 +       pos = data;
2022 +       end = data + len;
2023 +
2024 +       while (pos + IW_EV_LCP_LEN <= end) {
2025 +               /* Event data may be unaligned, so make a local, aligned copy
2026 +                * before processing. */
2027 +               memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
2028 +               wpa_printf(MSG_DEBUG, "Wireless event: cmd=0x%x len=%d",
2029 +                          iwe->cmd, iwe->len);
2030 +               if (iwe->len <= IW_EV_LCP_LEN)
2031 +                       return;
2032 +
2033 +               custom = pos + IW_EV_POINT_LEN;
2034 +               if (drv->we_version > 18 &&
2035 +                   (iwe->cmd == IWEVMICHAELMICFAILURE ||
2036 +                    iwe->cmd == IWEVCUSTOM)) {
2037 +                       /* WE-19 removed the pointer from struct iw_point */
2038 +                       char *dpos = (char *) &iwe_buf.u.data.length;
2039 +                       int dlen = dpos - (char *) &iwe_buf;
2040 +                       memcpy(dpos, pos + IW_EV_LCP_LEN,
2041 +                              sizeof(struct iw_event) - dlen);
2042 +               } else {
2043 +                       memcpy(&iwe_buf, pos, sizeof(struct iw_event));
2044 +                       custom += IW_EV_POINT_OFF;
2045 +               }
2046 +
2047 +               switch (iwe->cmd) {
2048 +               case IWEVCUSTOM:
2049 +                       if (custom + iwe->u.data.length > end)
2050 +                               return;
2051 +                       buf = malloc(iwe->u.data.length + 1);
2052 +                       if (buf == NULL)
2053 +                               return;
2054 +                       memcpy(buf, custom, iwe->u.data.length);
2055 +                       buf[iwe->u.data.length] = '\0';
2056 +                       hostapd_wireless_event_wireless_custom(drv, buf);
2057 +                       free(buf);
2058 +                       break;
2059 +               }
2060 +
2061 +               pos += iwe->len;
2062 +       }
2063 +}
2064 +
2065 +
2066 +static void hostapd_wireless_event_rtm_newlink(struct i802_driver_data *drv,
2067 +                                              struct nlmsghdr *h, int len)
2068 +{
2069 +       struct ifinfomsg *ifi;
2070 +       int attrlen, nlmsg_len, rta_len;
2071 +       struct rtattr *attr;
2072 +
2073 +       if (len < (int) sizeof(*ifi))
2074 +               return;
2075 +
2076 +       ifi = NLMSG_DATA(h);
2077 +
2078 +       /* TODO: use ifi->ifi_index to filter out wireless events from other
2079 +        * interfaces */
2080 +
2081 +       nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
2082 +
2083 +       attrlen = h->nlmsg_len - nlmsg_len;
2084 +       if (attrlen < 0)
2085 +               return;
2086 +
2087 +       attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);
2088 +
2089 +       rta_len = RTA_ALIGN(sizeof(struct rtattr));
2090 +       while (RTA_OK(attr, attrlen)) {
2091 +               if (attr->rta_type == IFLA_WIRELESS) {
2092 +                       hostapd_wireless_event_wireless(
2093 +                               drv, ((char *) attr) + rta_len,
2094 +                               attr->rta_len - rta_len);
2095 +               }
2096 +               attr = RTA_NEXT(attr, attrlen);
2097 +       }
2098 +}
2099 +
2100 +
2101 +static void hostapd_wireless_event_receive(int sock, void *eloop_ctx,
2102 +                                          void *sock_ctx)
2103 +{
2104 +       char buf[256];
2105 +       int left;
2106 +       struct sockaddr_nl from;
2107 +       socklen_t fromlen;
2108 +       struct nlmsghdr *h;
2109 +       struct i802_driver_data *drv = eloop_ctx;
2110 +
2111 +       fromlen = sizeof(from);
2112 +       left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT,
2113 +                       (struct sockaddr *) &from, &fromlen);
2114 +       if (left < 0) {
2115 +               if (errno != EINTR && errno != EAGAIN)
2116 +                       perror("recvfrom(netlink)");
2117 +               return;
2118 +       }
2119 +
2120 +       h = (struct nlmsghdr *) buf;
2121 +       while (left >= (int) sizeof(*h)) {
2122 +               int len, plen;
2123 +
2124 +               len = h->nlmsg_len;
2125 +               plen = len - sizeof(*h);
2126 +               if (len > left || plen < 0) {
2127 +                       printf("Malformed netlink message: "
2128 +                              "len=%d left=%d plen=%d\n",
2129 +                              len, left, plen);
2130 +                       break;
2131 +               }
2132 +
2133 +               switch (h->nlmsg_type) {
2134 +               case RTM_NEWLINK:
2135 +                       hostapd_wireless_event_rtm_newlink(drv, h, plen);
2136 +                       break;
2137 +               }
2138 +
2139 +               len = NLMSG_ALIGN(len);
2140 +               left -= len;
2141 +               h = (struct nlmsghdr *) ((char *) h + len);
2142 +       }
2143 +
2144 +       if (left > 0) {
2145 +               printf("%d extra bytes in the end of netlink message\n", left);
2146 +       }
2147 +}
2148 +
2149 +
2150 +static int hostap_get_we_version(struct i802_driver_data *drv)
2151 +{
2152 +       struct iw_range *range;
2153 +       struct iwreq iwr;
2154 +       int minlen;
2155 +       size_t buflen;
2156 +
2157 +       drv->we_version = 0;
2158 +
2159 +       /*
2160 +        * Use larger buffer than struct iw_range in order to allow the
2161 +        * structure to grow in the future.
2162 +        */
2163 +       buflen = sizeof(struct iw_range) + 500;
2164 +       range = os_zalloc(buflen);
2165 +       if (range == NULL)
2166 +               return -1;
2167 +
2168 +       memset(&iwr, 0, sizeof(iwr));
2169 +       os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
2170 +       iwr.u.data.pointer = (caddr_t) range;
2171 +       iwr.u.data.length = buflen;
2172 +
2173 +       minlen = ((char *) &range->enc_capa) - (char *) range +
2174 +               sizeof(range->enc_capa);
2175 +
2176 +       if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) {
2177 +               perror("ioctl[SIOCGIWRANGE]");
2178 +               free(range);
2179 +               return -1;
2180 +       } else if (iwr.u.data.length >= minlen &&
2181 +                  range->we_version_compiled >= 18) {
2182 +               wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: WE(compiled)=%d "
2183 +                          "WE(source)=%d enc_capa=0x%x",
2184 +                          range->we_version_compiled,
2185 +                          range->we_version_source,
2186 +                          range->enc_capa);
2187 +               drv->we_version = range->we_version_compiled;
2188 +       }
2189 +
2190 +       free(range);
2191 +       return 0;
2192 +}
2193 +
2194 +
2195 +static int i802_wireless_event_init(void *priv)
2196 +{
2197 +       struct i802_driver_data *drv = priv;
2198 +       int s;
2199 +       struct sockaddr_nl local;
2200 +
2201 +       hostap_get_we_version(drv);
2202 +
2203 +       drv->wext_sock = -1;
2204 +
2205 +       s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
2206 +       if (s < 0) {
2207 +               perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)");
2208 +               return -1;
2209 +       }
2210 +
2211 +       memset(&local, 0, sizeof(local));
2212 +       local.nl_family = AF_NETLINK;
2213 +       local.nl_groups = RTMGRP_LINK;
2214 +       if (bind(s, (struct sockaddr *) &local, sizeof(local)) < 0) {
2215 +               perror("bind(netlink)");
2216 +               close(s);
2217 +               return -1;
2218 +       }
2219 +
2220 +       eloop_register_read_sock(s, hostapd_wireless_event_receive, drv,
2221 +                                NULL);
2222 +       drv->wext_sock = s;
2223 +
2224 +       return 0;
2225 +}
2226 +
2227 +
2228 +static void i802_wireless_event_deinit(void *priv)
2229 +{
2230 +       struct i802_driver_data *drv = priv;
2231 +       if (drv->wext_sock < 0)
2232 +               return;
2233 +       eloop_unregister_read_sock(drv->wext_sock);
2234 +       close(drv->wext_sock);
2235 +}
2236 +
2237 +
2238 +static int i802_sta_deauth(void *priv, const u8 *addr, int reason)
2239 +{
2240 +       struct i802_driver_data *drv = priv;
2241 +       struct ieee80211_mgmt mgmt;
2242 +
2243 +       memset(&mgmt, 0, sizeof(mgmt));
2244 +       mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
2245 +                                         WLAN_FC_STYPE_DEAUTH);
2246 +       memcpy(mgmt.da, addr, ETH_ALEN);
2247 +       memcpy(mgmt.sa, drv->hapd->own_addr, ETH_ALEN);
2248 +       memcpy(mgmt.bssid, drv->hapd->own_addr, ETH_ALEN);
2249 +       mgmt.u.deauth.reason_code = host_to_le16(reason);
2250 +       return i802_send_mgmt_frame(drv, &mgmt, IEEE80211_HDRLEN +
2251 +                                     sizeof(mgmt.u.deauth), 0);
2252 +}
2253 +
2254 +
2255 +static int i802_sta_disassoc(void *priv, const u8 *addr, int reason)
2256 +{
2257 +       struct i802_driver_data *drv = priv;
2258 +       struct ieee80211_mgmt mgmt;
2259 +
2260 +       memset(&mgmt, 0, sizeof(mgmt));
2261 +       mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
2262 +                                         WLAN_FC_STYPE_DISASSOC);
2263 +       memcpy(mgmt.da, addr, ETH_ALEN);
2264 +       memcpy(mgmt.sa, drv->hapd->own_addr, ETH_ALEN);
2265 +       memcpy(mgmt.bssid, drv->hapd->own_addr, ETH_ALEN);
2266 +       mgmt.u.disassoc.reason_code = host_to_le16(reason);
2267 +       return  i802_send_mgmt_frame(drv, &mgmt, IEEE80211_HDRLEN +
2268 +                                      sizeof(mgmt.u.disassoc), 0);
2269 +}
2270 +
2271 +
2272 +static void *i802_init_bssid(struct hostapd_data *hapd, const u8 *bssid)
2273 +{
2274 +       struct i802_driver_data *drv;
2275 +
2276 +       drv = os_zalloc(sizeof(struct i802_driver_data));
2277 +       if (drv == NULL) {
2278 +               printf("Could not allocate memory for i802 driver data\n");
2279 +               return NULL;
2280 +       }
2281 +
2282 +       drv->hapd = hapd;
2283 +       memcpy(drv->iface, hapd->conf->iface, sizeof(drv->iface));
2284 +
2285 +       drv->num_if_indices = sizeof(drv->default_if_indices) / sizeof(int);
2286 +       drv->if_indices = drv->default_if_indices;
2287 +
2288 +       if (i802_init_sockets(drv, bssid))
2289 +               goto failed;
2290 +
2291 +       return drv;
2292 +
2293 +failed:
2294 +       free(drv);
2295 +       return NULL;
2296 +}
2297 +
2298 +
2299 +static void *i802_init(struct hostapd_data *hapd)
2300 +{
2301 +       return i802_init_bssid(hapd, NULL);
2302 +}
2303 +
2304 +
2305 +static void i802_deinit(void *priv)
2306 +{
2307 +       struct i802_driver_data *drv = priv;
2308 +
2309 +       i802_del_beacon(drv);
2310 +
2311 +       /* remove monitor interface */
2312 +       nl80211_remove_iface(drv, drv->monitor_ifidx);
2313 +
2314 +       (void) hostapd_set_iface_flags(drv, drv->iface, 0);
2315 +
2316 +       if (drv->monitor_sock >= 0) {
2317 +               eloop_unregister_read_sock(drv->monitor_sock);
2318 +               close(drv->monitor_sock);
2319 +       }
2320 +       if (drv->ioctl_sock >= 0)
2321 +               close(drv->ioctl_sock);
2322 +       if (drv->eapol_sock >= 0) {
2323 +               eloop_unregister_read_sock(drv->eapol_sock);
2324 +               close(drv->eapol_sock);
2325 +       }
2326 +
2327 +       genl_family_put(drv->nl80211);
2328 +       nl_cache_free(drv->nl_cache);
2329 +       nl_handle_destroy(drv->nl_handle);
2330 +
2331 +       if (drv->if_indices != drv->default_if_indices)
2332 +               free(drv->if_indices);
2333 +
2334 +       free(drv);
2335 +}
2336 +
2337 +
2338 +const struct wpa_driver_ops wpa_driver_nl80211_ops = {
2339 +       .name = "nl80211",
2340 +       .init = i802_init,
2341 +//     .init_bssid = i802_init_bssid,
2342 +       .deinit = i802_deinit,
2343 +       .wireless_event_init = i802_wireless_event_init,
2344 +       .wireless_event_deinit = i802_wireless_event_deinit,
2345 +       .set_ieee8021x = i802_set_ieee8021x,
2346 +       .set_privacy = i802_set_privacy,
2347 +       .set_encryption = i802_set_encryption,
2348 +       .get_seqnum = i802_get_seqnum,
2349 +       .flush = i802_flush,
2350 +       .read_sta_data = i802_read_sta_data,
2351 +       .send_eapol = i802_send_eapol,
2352 +       .sta_set_flags = i802_sta_set_flags,
2353 +       .sta_deauth = i802_sta_deauth,
2354 +       .sta_disassoc = i802_sta_disassoc,
2355 +       .sta_remove = i802_sta_remove,
2356 +       .set_ssid = i802_set_ssid,
2357 +       .send_mgmt_frame = i802_send_mgmt_frame,
2358 +       .sta_add = i802_sta_add,
2359 +       .get_inact_sec = i802_get_inact_sec,
2360 +       .sta_clear_stats = i802_sta_clear_stats,
2361 +       .set_freq = i802_set_freq,
2362 +       .set_rts = i802_set_rts,
2363 +       .get_rts = i802_get_rts,
2364 +       .set_frag = i802_set_frag,
2365 +       .get_frag = i802_get_frag,
2366 +       .set_retry = i802_set_retry,
2367 +       .get_retry = i802_get_retry,
2368 +       .set_rate_sets = i802_set_rate_sets,
2369 +       .set_channel_flag = i802_set_channel_flag,
2370 +       .set_regulatory_domain = i802_set_regulatory_domain,
2371 +       .set_beacon = i802_set_beacon,
2372 +       .set_internal_bridge = i802_set_internal_bridge,
2373 +       .set_beacon_int = i802_set_beacon_int,
2374 +       .set_dtim_period = i802_set_dtim_period,
2375 +       .set_cts_protect = i802_set_cts_protect,
2376 +       .set_preamble = i802_set_preamble,
2377 +       .set_short_slot_time = i802_set_short_slot_time,
2378 +       .set_tx_queue_params = i802_set_tx_queue_params,
2379 +       .bss_add = i802_bss_add,
2380 +       .bss_remove = i802_bss_remove,
2381 +       .if_add = i802_if_add,
2382 +       .if_update = i802_if_update,
2383 +       .if_remove = i802_if_remove,
2384 +       .get_hw_feature_data = i802_get_hw_feature_data,
2385 +       .set_sta_vlan = i802_set_sta_vlan,
2386 +};
2387 diff -urN hostapd.orig/radiotap.c hostapd/radiotap.c
2388 --- a/hostapd/radiotap.c        1970-01-01 01:00:00.000000000 +0100
2389 +++ b/hostapd/radiotap.c        2008-02-15 23:05:17.000000000 +0100
2390 @@ -0,0 +1,287 @@
2391 +/*
2392 + * Radiotap parser
2393 + *
2394 + * Copyright 2007              Andy Green <andy@warmcat.com>
2395 + *
2396 + * This program is free software; you can redistribute it and/or modify
2397 + * it under the terms of the GNU General Public License version 2 as
2398 + * published by the Free Software Foundation.
2399 + *
2400 + * Alternatively, this software may be distributed under the terms of BSD
2401 + * license.
2402 + *
2403 + * See README and COPYING for more details.
2404 + *
2405 + *
2406 + * Modified for userspace by Johannes Berg <johannes@sipsolutions.net>
2407 + * I only modified some things on top to ease syncing should bugs be found.
2408 + */
2409 +
2410 +#include "includes.h"
2411 +
2412 +#include "common.h"
2413 +#include "radiotap_iter.h"
2414 +
2415 +#define le16_to_cpu            le_to_host16
2416 +#define le32_to_cpu            le_to_host32
2417 +#define __le32                 uint32_t
2418 +#define ulong                  unsigned long
2419 +#define unlikely(cond)         (cond)
2420 +#define get_unaligned(p)                                       \
2421 +({                                                             \
2422 +       struct packed_dummy_struct {                            \
2423 +               typeof(*(p)) __val;                             \
2424 +       } __attribute__((packed)) *__ptr = (void *) (p);        \
2425 +                                                               \
2426 +       __ptr->__val;                                           \
2427 +})
2428 +
2429 +/* function prototypes and related defs are in radiotap_iter.h */
2430 +
2431 +/**
2432 + * ieee80211_radiotap_iterator_init - radiotap parser iterator initialization
2433 + * @iterator: radiotap_iterator to initialize
2434 + * @radiotap_header: radiotap header to parse
2435 + * @max_length: total length we can parse into (eg, whole packet length)
2436 + *
2437 + * Returns: 0 or a negative error code if there is a problem.
2438 + *
2439 + * This function initializes an opaque iterator struct which can then
2440 + * be passed to ieee80211_radiotap_iterator_next() to visit every radiotap
2441 + * argument which is present in the header.  It knows about extended
2442 + * present headers and handles them.
2443 + *
2444 + * How to use:
2445 + * call __ieee80211_radiotap_iterator_init() to init a semi-opaque iterator
2446 + * struct ieee80211_radiotap_iterator (no need to init the struct beforehand)
2447 + * checking for a good 0 return code.  Then loop calling
2448 + * __ieee80211_radiotap_iterator_next()... it returns either 0,
2449 + * -ENOENT if there are no more args to parse, or -EINVAL if there is a problem.
2450 + * The iterator's @this_arg member points to the start of the argument
2451 + * associated with the current argument index that is present, which can be
2452 + * found in the iterator's @this_arg_index member.  This arg index corresponds
2453 + * to the IEEE80211_RADIOTAP_... defines.
2454 + *
2455 + * Radiotap header length:
2456 + * You can find the CPU-endian total radiotap header length in
2457 + * iterator->max_length after executing ieee80211_radiotap_iterator_init()
2458 + * successfully.
2459 + *
2460 + * Alignment Gotcha:
2461 + * You must take care when dereferencing iterator.this_arg
2462 + * for multibyte types... the pointer is not aligned.  Use
2463 + * get_unaligned((type *)iterator.this_arg) to dereference
2464 + * iterator.this_arg for type "type" safely on all arches.
2465 + *
2466 + * Example code:
2467 + * See Documentation/networking/radiotap-headers.txt
2468 + */
2469 +
2470 +int ieee80211_radiotap_iterator_init(
2471 +    struct ieee80211_radiotap_iterator *iterator,
2472 +    struct ieee80211_radiotap_header *radiotap_header,
2473 +    int max_length)
2474 +{
2475 +       /* Linux only supports version 0 radiotap format */
2476 +       if (radiotap_header->it_version)
2477 +               return -EINVAL;
2478 +
2479 +       /* sanity check for allowed length and radiotap length field */
2480 +       if (max_length < le16_to_cpu(get_unaligned(&radiotap_header->it_len)))
2481 +               return -EINVAL;
2482 +
2483 +       iterator->rtheader = radiotap_header;
2484 +       iterator->max_length = le16_to_cpu(get_unaligned(
2485 +                                               &radiotap_header->it_len));
2486 +       iterator->arg_index = 0;
2487 +       iterator->bitmap_shifter = le32_to_cpu(get_unaligned(
2488 +                                               &radiotap_header->it_present));
2489 +       iterator->arg = (u8 *)radiotap_header + sizeof(*radiotap_header);
2490 +       iterator->this_arg = NULL;
2491 +
2492 +       /* find payload start allowing for extended bitmap(s) */
2493 +
2494 +       if (unlikely(iterator->bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT))) {
2495 +               while (le32_to_cpu(get_unaligned((__le32 *)iterator->arg)) &
2496 +                                  (1<<IEEE80211_RADIOTAP_EXT)) {
2497 +                       iterator->arg += sizeof(u32);
2498 +
2499 +                       /*
2500 +                        * check for insanity where the present bitmaps
2501 +                        * keep claiming to extend up to or even beyond the
2502 +                        * stated radiotap header length
2503 +                        */
2504 +
2505 +                       if (((ulong)iterator->arg - (ulong)iterator->rtheader)
2506 +                           > (ulong)iterator->max_length)
2507 +                               return -EINVAL;
2508 +               }
2509 +
2510 +               iterator->arg += sizeof(u32);
2511 +
2512 +               /*
2513 +                * no need to check again for blowing past stated radiotap
2514 +                * header length, because ieee80211_radiotap_iterator_next
2515 +                * checks it before it is dereferenced
2516 +                */
2517 +       }
2518 +
2519 +       /* we are all initialized happily */
2520 +
2521 +       return 0;
2522 +}
2523 +
2524 +
2525 +/**
2526 + * ieee80211_radiotap_iterator_next - return next radiotap parser iterator arg
2527 + * @iterator: radiotap_iterator to move to next arg (if any)
2528 + *
2529 + * Returns: 0 if there is an argument to handle,
2530 + * -ENOENT if there are no more args or -EINVAL
2531 + * if there is something else wrong.
2532 + *
2533 + * This function provides the next radiotap arg index (IEEE80211_RADIOTAP_*)
2534 + * in @this_arg_index and sets @this_arg to point to the
2535 + * payload for the field.  It takes care of alignment handling and extended
2536 + * present fields.  @this_arg can be changed by the caller (eg,
2537 + * incremented to move inside a compound argument like
2538 + * IEEE80211_RADIOTAP_CHANNEL).  The args pointed to are in
2539 + * little-endian format whatever the endianess of your CPU.
2540 + *
2541 + * Alignment Gotcha:
2542 + * You must take care when dereferencing iterator.this_arg
2543 + * for multibyte types... the pointer is not aligned.  Use
2544 + * get_unaligned((type *)iterator.this_arg) to dereference
2545 + * iterator.this_arg for type "type" safely on all arches.
2546 + */
2547 +
2548 +int ieee80211_radiotap_iterator_next(
2549 +    struct ieee80211_radiotap_iterator *iterator)
2550 +{
2551 +
2552 +       /*
2553 +        * small length lookup table for all radiotap types we heard of
2554 +        * starting from b0 in the bitmap, so we can walk the payload
2555 +        * area of the radiotap header
2556 +        *
2557 +        * There is a requirement to pad args, so that args
2558 +        * of a given length must begin at a boundary of that length
2559 +        * -- but note that compound args are allowed (eg, 2 x u16
2560 +        * for IEEE80211_RADIOTAP_CHANNEL) so total arg length is not
2561 +        * a reliable indicator of alignment requirement.
2562 +        *
2563 +        * upper nybble: content alignment for arg
2564 +        * lower nybble: content length for arg
2565 +        */
2566 +
2567 +       static const u8 rt_sizes[] = {
2568 +               [IEEE80211_RADIOTAP_TSFT] = 0x88,
2569 +               [IEEE80211_RADIOTAP_FLAGS] = 0x11,
2570 +               [IEEE80211_RADIOTAP_RATE] = 0x11,
2571 +               [IEEE80211_RADIOTAP_CHANNEL] = 0x24,
2572 +               [IEEE80211_RADIOTAP_FHSS] = 0x22,
2573 +               [IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = 0x11,
2574 +               [IEEE80211_RADIOTAP_DBM_ANTNOISE] = 0x11,
2575 +               [IEEE80211_RADIOTAP_LOCK_QUALITY] = 0x22,
2576 +               [IEEE80211_RADIOTAP_TX_ATTENUATION] = 0x22,
2577 +               [IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = 0x22,
2578 +               [IEEE80211_RADIOTAP_DBM_TX_POWER] = 0x11,
2579 +               [IEEE80211_RADIOTAP_ANTENNA] = 0x11,
2580 +               [IEEE80211_RADIOTAP_DB_ANTSIGNAL] = 0x11,
2581 +               [IEEE80211_RADIOTAP_DB_ANTNOISE] = 0x11,
2582 +               [IEEE80211_RADIOTAP_RX_FLAGS] = 0x22,
2583 +               [IEEE80211_RADIOTAP_TX_FLAGS] = 0x22,
2584 +               [IEEE80211_RADIOTAP_RTS_RETRIES] = 0x11,
2585 +               [IEEE80211_RADIOTAP_DATA_RETRIES] = 0x11,
2586 +               /*
2587 +                * add more here as they are defined in
2588 +                * include/net/ieee80211_radiotap.h
2589 +                */
2590 +       };
2591 +
2592 +       /*
2593 +        * for every radiotap entry we can at
2594 +        * least skip (by knowing the length)...
2595 +        */
2596 +
2597 +       while (iterator->arg_index < (int) sizeof(rt_sizes)) {
2598 +               int hit = 0;
2599 +               int pad;
2600 +
2601 +               if (!(iterator->bitmap_shifter & 1))
2602 +                       goto next_entry; /* arg not present */
2603 +
2604 +               /*
2605 +                * arg is present, account for alignment padding
2606 +                *  8-bit args can be at any alignment
2607 +                * 16-bit args must start on 16-bit boundary
2608 +                * 32-bit args must start on 32-bit boundary
2609 +                * 64-bit args must start on 64-bit boundary
2610 +                *
2611 +                * note that total arg size can differ from alignment of
2612 +                * elements inside arg, so we use upper nybble of length
2613 +                * table to base alignment on
2614 +                *
2615 +                * also note: these alignments are ** relative to the
2616 +                * start of the radiotap header **.  There is no guarantee
2617 +                * that the radiotap header itself is aligned on any
2618 +                * kind of boundary.
2619 +                *
2620 +                * the above is why get_unaligned() is used to dereference
2621 +                * multibyte elements from the radiotap area
2622 +                */
2623 +
2624 +               pad = (((ulong)iterator->arg) -
2625 +                       ((ulong)iterator->rtheader)) &
2626 +                       ((rt_sizes[iterator->arg_index] >> 4) - 1);
2627 +
2628 +               if (pad)
2629 +                       iterator->arg +=
2630 +                               (rt_sizes[iterator->arg_index] >> 4) - pad;
2631 +
2632 +               /*
2633 +                * this is what we will return to user, but we need to
2634 +                * move on first so next call has something fresh to test
2635 +                */
2636 +               iterator->this_arg_index = iterator->arg_index;
2637 +               iterator->this_arg = iterator->arg;
2638 +               hit = 1;
2639 +
2640 +               /* internally move on the size of this arg */
2641 +               iterator->arg += rt_sizes[iterator->arg_index] & 0x0f;
2642 +
2643 +               /*
2644 +                * check for insanity where we are given a bitmap that
2645 +                * claims to have more arg content than the length of the
2646 +                * radiotap section.  We will normally end up equalling this
2647 +                * max_length on the last arg, never exceeding it.
2648 +                */
2649 +
2650 +               if (((ulong)iterator->arg - (ulong)iterator->rtheader) >
2651 +                   (ulong) iterator->max_length)
2652 +                       return -EINVAL;
2653 +
2654 +       next_entry:
2655 +               iterator->arg_index++;
2656 +               if (unlikely((iterator->arg_index & 31) == 0)) {
2657 +                       /* completed current u32 bitmap */
2658 +                       if (iterator->bitmap_shifter & 1) {
2659 +                               /* b31 was set, there is more */
2660 +                               /* move to next u32 bitmap */
2661 +                               iterator->bitmap_shifter = le32_to_cpu(
2662 +                                       get_unaligned(iterator->next_bitmap));
2663 +                               iterator->next_bitmap++;
2664 +                       } else
2665 +                               /* no more bitmaps: end */
2666 +                               iterator->arg_index = sizeof(rt_sizes);
2667 +               } else /* just try the next bit */
2668 +                       iterator->bitmap_shifter >>= 1;
2669 +
2670 +               /* if we found a valid arg earlier, return it now */
2671 +               if (hit)
2672 +                       return 0;
2673 +       }
2674 +
2675 +       /* we don't know how to handle any more args, we're done */
2676 +       return -ENOENT;
2677 +}
2678 diff -urN hostapd.orig/radiotap.h hostapd/radiotap.h
2679 --- a/hostapd/radiotap.h        1970-01-01 01:00:00.000000000 +0100
2680 +++ b/hostapd/radiotap.h        2008-02-15 23:05:17.000000000 +0100
2681 @@ -0,0 +1,242 @@
2682 +/* $FreeBSD: src/sys/net80211/ieee80211_radiotap.h,v 1.5 2005/01/22 20:12:05 sam Exp $ */
2683 +/* $NetBSD: ieee80211_radiotap.h,v 1.11 2005/06/22 06:16:02 dyoung Exp $ */
2684 +
2685 +/*-
2686 + * Copyright (c) 2003, 2004 David Young.  All rights reserved.
2687 + *
2688 + * Redistribution and use in source and binary forms, with or without
2689 + * modification, are permitted provided that the following conditions
2690 + * are met:
2691 + * 1. Redistributions of source code must retain the above copyright
2692 + *    notice, this list of conditions and the following disclaimer.
2693 + * 2. Redistributions in binary form must reproduce the above copyright
2694 + *    notice, this list of conditions and the following disclaimer in the
2695 + *    documentation and/or other materials provided with the distribution.
2696 + * 3. The name of David Young may not be used to endorse or promote
2697 + *    products derived from this software without specific prior
2698 + *    written permission.
2699 + *
2700 + * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY
2701 + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
2702 + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
2703 + * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DAVID
2704 + * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2705 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
2706 + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2707 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
2708 + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2709 + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2710 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
2711 + * OF SUCH DAMAGE.
2712 + */
2713 +
2714 +/*
2715 + * Modifications to fit into the linux IEEE 802.11 stack,
2716 + * Mike Kershaw (dragorn@kismetwireless.net)
2717 + */
2718 +
2719 +#ifndef IEEE80211RADIOTAP_H
2720 +#define IEEE80211RADIOTAP_H
2721 +
2722 +#include <stdint.h>
2723 +
2724 +/* Base version of the radiotap packet header data */
2725 +#define PKTHDR_RADIOTAP_VERSION                0
2726 +
2727 +/* A generic radio capture format is desirable. There is one for
2728 + * Linux, but it is neither rigidly defined (there were not even
2729 + * units given for some fields) nor easily extensible.
2730 + *
2731 + * I suggest the following extensible radio capture format. It is
2732 + * based on a bitmap indicating which fields are present.
2733 + *
2734 + * I am trying to describe precisely what the application programmer
2735 + * should expect in the following, and for that reason I tell the
2736 + * units and origin of each measurement (where it applies), or else I
2737 + * use sufficiently weaselly language ("is a monotonically nondecreasing
2738 + * function of...") that I cannot set false expectations for lawyerly
2739 + * readers.
2740 + */
2741 +
2742 +/* The radio capture header precedes the 802.11 header.
2743 + * All data in the header is little endian on all platforms.
2744 + */
2745 +struct ieee80211_radiotap_header {
2746 +       uint8_t it_version;     /* Version 0. Only increases
2747 +                                * for drastic changes,
2748 +                                * introduction of compatible
2749 +                                * new fields does not count.
2750 +                                */
2751 +       uint8_t it_pad;
2752 +       uint16_t it_len;        /* length of the whole
2753 +                                * header in bytes, including
2754 +                                * it_version, it_pad,
2755 +                                * it_len, and data fields.
2756 +                                */
2757 +       uint32_t it_present;    /* A bitmap telling which
2758 +                                * fields are present. Set bit 31
2759 +                                * (0x80000000) to extend the
2760 +                                * bitmap by another 32 bits.
2761 +                                * Additional extensions are made
2762 +                                * by setting bit 31.
2763 +                                */
2764 +};
2765 +
2766 +/* Name                                 Data type    Units
2767 + * ----                                 ---------    -----
2768 + *
2769 + * IEEE80211_RADIOTAP_TSFT              __le64       microseconds
2770 + *
2771 + *      Value in microseconds of the MAC's 64-bit 802.11 Time
2772 + *      Synchronization Function timer when the first bit of the
2773 + *      MPDU arrived at the MAC. For received frames, only.
2774 + *
2775 + * IEEE80211_RADIOTAP_CHANNEL           2 x uint16_t   MHz, bitmap
2776 + *
2777 + *      Tx/Rx frequency in MHz, followed by flags (see below).
2778 + *
2779 + * IEEE80211_RADIOTAP_FHSS              uint16_t       see below
2780 + *
2781 + *      For frequency-hopping radios, the hop set (first byte)
2782 + *      and pattern (second byte).
2783 + *
2784 + * IEEE80211_RADIOTAP_RATE              u8           500kb/s
2785 + *
2786 + *      Tx/Rx data rate
2787 + *
2788 + * IEEE80211_RADIOTAP_DBM_ANTSIGNAL     s8           decibels from
2789 + *                                                   one milliwatt (dBm)
2790 + *
2791 + *      RF signal power at the antenna, decibel difference from
2792 + *      one milliwatt.
2793 + *
2794 + * IEEE80211_RADIOTAP_DBM_ANTNOISE      s8           decibels from
2795 + *                                                   one milliwatt (dBm)
2796 + *
2797 + *      RF noise power at the antenna, decibel difference from one
2798 + *      milliwatt.
2799 + *
2800 + * IEEE80211_RADIOTAP_DB_ANTSIGNAL      u8           decibel (dB)
2801 + *
2802 + *      RF signal power at the antenna, decibel difference from an
2803 + *      arbitrary, fixed reference.
2804 + *
2805 + * IEEE80211_RADIOTAP_DB_ANTNOISE       u8           decibel (dB)
2806 + *
2807 + *      RF noise power at the antenna, decibel difference from an
2808 + *      arbitrary, fixed reference point.
2809 + *
2810 + * IEEE80211_RADIOTAP_LOCK_QUALITY      uint16_t       unitless
2811 + *
2812 + *      Quality of Barker code lock. Unitless. Monotonically
2813 + *      nondecreasing with "better" lock strength. Called "Signal
2814 + *      Quality" in datasheets.  (Is there a standard way to measure
2815 + *      this?)
2816 + *
2817 + * IEEE80211_RADIOTAP_TX_ATTENUATION    uint16_t       unitless
2818 + *
2819 + *      Transmit power expressed as unitless distance from max
2820 + *      power set at factory calibration.  0 is max power.
2821 + *      Monotonically nondecreasing with lower power levels.
2822 + *
2823 + * IEEE80211_RADIOTAP_DB_TX_ATTENUATION uint16_t       decibels (dB)
2824 + *
2825 + *      Transmit power expressed as decibel distance from max power
2826 + *      set at factory calibration.  0 is max power.  Monotonically
2827 + *      nondecreasing with lower power levels.
2828 + *
2829 + * IEEE80211_RADIOTAP_DBM_TX_POWER      s8           decibels from
2830 + *                                                   one milliwatt (dBm)
2831 + *
2832 + *      Transmit power expressed as dBm (decibels from a 1 milliwatt
2833 + *      reference). This is the absolute power level measured at
2834 + *      the antenna port.
2835 + *
2836 + * IEEE80211_RADIOTAP_FLAGS             u8           bitmap
2837 + *
2838 + *      Properties of transmitted and received frames. See flags
2839 + *      defined below.
2840 + *
2841 + * IEEE80211_RADIOTAP_ANTENNA           u8           antenna index
2842 + *
2843 + *      Unitless indication of the Rx/Tx antenna for this packet.
2844 + *      The first antenna is antenna 0.
2845 + *
2846 + * IEEE80211_RADIOTAP_RX_FLAGS          uint16_t       bitmap
2847 + *
2848 + *     Properties of received frames. See flags defined below.
2849 + *
2850 + * IEEE80211_RADIOTAP_TX_FLAGS          uint16_t       bitmap
2851 + *
2852 + *     Properties of transmitted frames. See flags defined below.
2853 + *
2854 + * IEEE80211_RADIOTAP_RTS_RETRIES       u8           data
2855 + *
2856 + *     Number of rts retries a transmitted frame used.
2857 + *
2858 + * IEEE80211_RADIOTAP_DATA_RETRIES      u8           data
2859 + *
2860 + *     Number of unicast retries a transmitted frame used.
2861 + *
2862 + */
2863 +enum ieee80211_radiotap_type {
2864 +       IEEE80211_RADIOTAP_TSFT = 0,
2865 +       IEEE80211_RADIOTAP_FLAGS = 1,
2866 +       IEEE80211_RADIOTAP_RATE = 2,
2867 +       IEEE80211_RADIOTAP_CHANNEL = 3,
2868 +       IEEE80211_RADIOTAP_FHSS = 4,
2869 +       IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
2870 +       IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
2871 +       IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
2872 +       IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
2873 +       IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
2874 +       IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
2875 +       IEEE80211_RADIOTAP_ANTENNA = 11,
2876 +       IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
2877 +       IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
2878 +       IEEE80211_RADIOTAP_RX_FLAGS = 14,
2879 +       IEEE80211_RADIOTAP_TX_FLAGS = 15,
2880 +       IEEE80211_RADIOTAP_RTS_RETRIES = 16,
2881 +       IEEE80211_RADIOTAP_DATA_RETRIES = 17,
2882 +       IEEE80211_RADIOTAP_EXT = 31
2883 +};
2884 +
2885 +/* Channel flags. */
2886 +#define        IEEE80211_CHAN_TURBO    0x0010  /* Turbo channel */
2887 +#define        IEEE80211_CHAN_CCK      0x0020  /* CCK channel */
2888 +#define        IEEE80211_CHAN_OFDM     0x0040  /* OFDM channel */
2889 +#define        IEEE80211_CHAN_2GHZ     0x0080  /* 2 GHz spectrum channel. */
2890 +#define        IEEE80211_CHAN_5GHZ     0x0100  /* 5 GHz spectrum channel */
2891 +#define        IEEE80211_CHAN_PASSIVE  0x0200  /* Only passive scan allowed */
2892 +#define        IEEE80211_CHAN_DYN      0x0400  /* Dynamic CCK-OFDM channel */
2893 +#define        IEEE80211_CHAN_GFSK     0x0800  /* GFSK channel (FHSS PHY) */
2894 +
2895 +/* For IEEE80211_RADIOTAP_FLAGS */
2896 +#define        IEEE80211_RADIOTAP_F_CFP        0x01    /* sent/received
2897 +                                                * during CFP
2898 +                                                */
2899 +#define        IEEE80211_RADIOTAP_F_SHORTPRE   0x02    /* sent/received
2900 +                                                * with short
2901 +                                                * preamble
2902 +                                                */
2903 +#define        IEEE80211_RADIOTAP_F_WEP        0x04    /* sent/received
2904 +                                                * with WEP encryption
2905 +                                                */
2906 +#define        IEEE80211_RADIOTAP_F_FRAG       0x08    /* sent/received
2907 +                                                * with fragmentation
2908 +                                                */
2909 +#define        IEEE80211_RADIOTAP_F_FCS        0x10    /* frame includes FCS */
2910 +#define        IEEE80211_RADIOTAP_F_DATAPAD    0x20    /* frame has padding between
2911 +                                                * 802.11 header and payload
2912 +                                                * (to 32-bit boundary)
2913 +                                                */
2914 +/* For IEEE80211_RADIOTAP_RX_FLAGS */
2915 +#define IEEE80211_RADIOTAP_F_RX_BADFCS 0x0001  /* frame failed crc check */
2916 +
2917 +/* For IEEE80211_RADIOTAP_TX_FLAGS */
2918 +#define IEEE80211_RADIOTAP_F_TX_FAIL   0x0001  /* failed due to excessive
2919 +                                                * retries */
2920 +#define IEEE80211_RADIOTAP_F_TX_CTS    0x0002  /* used cts 'protection' */
2921 +#define IEEE80211_RADIOTAP_F_TX_RTS    0x0004  /* used rts/cts handshake */
2922 +
2923 +#endif                         /* IEEE80211_RADIOTAP_H */
2924 diff -urN hostapd.orig/radiotap_iter.h hostapd/radiotap_iter.h
2925 --- a/hostapd/radiotap_iter.h   1970-01-01 01:00:00.000000000 +0100
2926 +++ b/hostapd/radiotap_iter.h   2008-02-15 23:05:17.000000000 +0100
2927 @@ -0,0 +1,41 @@
2928 +#ifndef __RADIOTAP_ITER_H
2929 +#define __RADIOTAP_ITER_H
2930 +
2931 +#include "radiotap.h"
2932 +
2933 +/* Radiotap header iteration
2934 + *   implemented in radiotap.c
2935 + */
2936 +/**
2937 + * struct ieee80211_radiotap_iterator - tracks walk thru present radiotap args
2938 + * @rtheader: pointer to the radiotap header we are walking through
2939 + * @max_length: length of radiotap header in cpu byte ordering
2940 + * @this_arg_index: IEEE80211_RADIOTAP_... index of current arg
2941 + * @this_arg: pointer to current radiotap arg
2942 + * @arg_index: internal next argument index
2943 + * @arg: internal next argument pointer
2944 + * @next_bitmap: internal pointer to next present u32
2945 + * @bitmap_shifter: internal shifter for curr u32 bitmap, b0 set == arg present
2946 + */
2947 +
2948 +struct ieee80211_radiotap_iterator {
2949 +       struct ieee80211_radiotap_header *rtheader;
2950 +       int max_length;
2951 +       int this_arg_index;
2952 +       unsigned char *this_arg;
2953 +
2954 +       int arg_index;
2955 +       unsigned char *arg;
2956 +       uint32_t *next_bitmap;
2957 +       uint32_t bitmap_shifter;
2958 +};
2959 +
2960 +extern int ieee80211_radiotap_iterator_init(
2961 +   struct ieee80211_radiotap_iterator *iterator,
2962 +   struct ieee80211_radiotap_header *radiotap_header,
2963 +   int max_length);
2964 +
2965 +extern int ieee80211_radiotap_iterator_next(
2966 +   struct ieee80211_radiotap_iterator *iterator);
2967 +
2968 +#endif /* __RADIOTAP_ITER_H */