hostapd: use patches to add the nl80211 driver instead of copying the files.
[openwrt/svn-archive/archive.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 */