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
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>
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.
16 + * Alternatively, this software may be distributed under the terms of BSD
19 + * See README and COPYING for more details.
22 +#include "includes.h"
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>
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>
39 +#include "ieee802_1x.h"
41 +#include "ieee802_11.h"
42 +#include "sta_info.h"
43 +#include "hw_features.h"
45 +#include "radiotap.h"
46 +#include "radiotap_iter.h"
48 +enum ieee80211_msg_type {
49 + ieee80211_msg_normal = 0,
50 + ieee80211_msg_tx_callback_ack = 1,
51 + ieee80211_msg_tx_callback_fail = 2,
54 +struct i802_driver_data {
55 + struct hostapd_data *hapd;
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 */
64 + int default_if_indices[16];
69 + struct nl_handle *nl_handle;
70 + struct nl_cache *nl_cache;
71 + struct genl_family *nl80211;
73 + unsigned int beacon_set:1;
74 + unsigned int ieee802_1x_active:1;
78 +static void add_ifidx(struct i802_driver_data *drv, int ifidx)
83 + for (i = 0; i < drv->num_if_indices; i++) {
84 + if (drv->if_indices[i] == 0) {
85 + drv->if_indices[i] = ifidx;
90 + if (drv->if_indices != drv->default_if_indices)
91 + old = drv->if_indices;
95 + drv->if_indices = realloc(old,
96 + sizeof(int) * (drv->num_if_indices + 1));
97 + if (!drv->if_indices) {
99 + drv->if_indices = drv->default_if_indices;
101 + drv->if_indices = old;
102 + wpa_printf(MSG_ERROR, "Failed to reallocate memory for "
104 + wpa_printf(MSG_ERROR, "Ignoring EAPOL on interface %d", ifidx);
107 + drv->if_indices[drv->num_if_indices] = ifidx;
108 + drv->num_if_indices++;
112 +static void del_ifidx(struct i802_driver_data *drv, int ifidx)
116 + for (i = 0; i < drv->num_if_indices; i++) {
117 + if (drv->if_indices[i] == ifidx) {
118 + drv->if_indices[i] = 0;
125 +static int have_ifidx(struct i802_driver_data *drv, int ifidx)
129 + for (i = 0; i < drv->num_if_indices; i++)
130 + if (drv->if_indices[i] == ifidx)
137 +/* helper for netlink get routines */
138 +static int ack_wait_handler(struct nl_msg *msg, void *arg)
140 + int *finished = arg;
147 +static int hostapd_set_iface_flags(struct i802_driver_data *drv,
148 + const char *ifname, int dev_up)
152 + if (drv->ioctl_sock < 0)
155 + memset(&ifr, 0, sizeof(ifr));
156 + os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
158 + if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, &ifr) != 0) {
159 + perror("ioctl[SIOCGIFFLAGS]");
160 + wpa_printf(MSG_DEBUG, "Could not read interface flags (%s)",
166 + ifr.ifr_flags |= IFF_UP;
168 + ifr.ifr_flags &= ~IFF_UP;
170 + if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, &ifr) != 0) {
171 + perror("ioctl[SIOCSIFFLAGS]");
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)
183 + struct i802_driver_data *drv = priv;
184 + struct nl_msg *msg;
188 + msg = nlmsg_alloc();
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);
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) {
201 + NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
204 + NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER,
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);
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));
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) {
228 + * If we need to set the default TX key we do that below,
229 + * otherwise we're done here.
231 + if (!txkey || addr) {
238 + msg = nlmsg_alloc();
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);
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) {
265 +static inline int min_int(int a, int b)
273 +static int get_key_handler(struct nl_msg *msg, void *arg)
275 + struct nlattr *tb[NL80211_ATTR_MAX];
276 + struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
278 + nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
279 + genlmsg_attrlen(gnlh, 0), NULL);
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.
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));
294 +static int i802_get_seqnum(const char *iface, void *priv, const u8 *addr,
297 + struct i802_driver_data *drv = priv;
298 + struct nl_msg *msg;
299 + struct nl_cb *cb = NULL;
304 + msg = nlmsg_alloc();
308 + genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
309 + 0, NL80211_CMD_GET_KEY, 0);
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));
316 + cb = nl_cb_alloc(NL_CB_CUSTOM);
322 + if (nl_send_auto_complete(drv->nl_handle, msg) < 0)
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);
328 + err = nl_recvmsgs(drv->nl_handle, cb);
331 + err = nl_wait_for_ack(drv->nl_handle);
346 +static int i802_set_rate_sets(void *priv, int *supp_rates, int *basic_rates,
353 +static int i802_set_ssid(const char *ifname, void *priv, const u8 *buf,
356 + struct i802_driver_data *drv = priv;
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;
365 + if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0) {
366 + perror("ioctl[SIOCSIWESSID]");
367 + printf("len=%d\n", len);
375 +static int i802_send_mgmt_frame(void *priv, const void *data, size_t len,
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 */
388 + struct i802_driver_data *drv = priv;
389 + struct iovec iov[2] = {
391 + .iov_base = &rtap_hdr,
392 + .iov_len = sizeof(rtap_hdr),
395 + .iov_base = (void*)data,
399 + struct msghdr msg = {
404 + .msg_control = NULL,
405 + .msg_controllen = 0,
410 + * ugh, guess what, the generic code sets one of the version
411 + * bits to request tx callback
413 + hdr->frame_control &= ~host_to_le16(BIT(1));
414 + return sendmsg(drv->monitor_sock, &msg, flags);
418 +/* Set kernel driver on given frequency (MHz) */
419 +static int i802_set_freq(void *priv, int mode, int freq)
421 + struct i802_driver_data *drv = priv;
424 + memset(&iwr, 0, sizeof(iwr));
425 + os_strlcpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ);
426 + iwr.u.freq.m = freq;
429 + if (ioctl(drv->ioctl_sock, SIOCSIWFREQ, &iwr) < 0) {
430 + perror("ioctl[SIOCSIWFREQ]");
438 +static int i802_set_rts(void *priv, int rts)
440 + struct i802_driver_data *drv = priv;
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;
448 + if (ioctl(drv->ioctl_sock, SIOCSIWRTS, &iwr) < 0) {
449 + perror("ioctl[SIOCSIWRTS]");
457 +static int i802_get_rts(void *priv, int *rts)
459 + struct i802_driver_data *drv = priv;
462 + memset(&iwr, 0, sizeof(iwr));
463 + os_strlcpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ);
465 + if (ioctl(drv->ioctl_sock, SIOCGIWRTS, &iwr) < 0) {
466 + perror("ioctl[SIOCGIWRTS]");
470 + *rts = iwr.u.rts.value;
476 +static int i802_set_frag(void *priv, int frag)
478 + struct i802_driver_data *drv = priv;
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;
486 + if (ioctl(drv->ioctl_sock, SIOCSIWFRAG, &iwr) < 0) {
487 + perror("ioctl[SIOCSIWFRAG]");
495 +static int i802_get_frag(void *priv, int *frag)
497 + struct i802_driver_data *drv = priv;
500 + memset(&iwr, 0, sizeof(iwr));
501 + os_strlcpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ);
503 + if (ioctl(drv->ioctl_sock, SIOCGIWFRAG, &iwr) < 0) {
504 + perror("ioctl[SIOCGIWFRAG]");
508 + *frag = iwr.u.frag.value;
514 +static int i802_set_retry(void *priv, int short_retry, int long_retry)
516 + struct i802_driver_data *drv = priv;
519 + memset(&iwr, 0, sizeof(iwr));
520 + os_strlcpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ);
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)]");
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)]");
540 +static int i802_get_retry(void *priv, int *short_retry, int *long_retry)
542 + struct i802_driver_data *drv = priv;
545 + memset(&iwr, 0, sizeof(iwr));
546 + os_strlcpy(iwr.ifr_name, drv->hapd->conf->iface, IFNAMSIZ);
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)]");
553 + *short_retry = iwr.u.retry.value;
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)]");
560 + *long_retry = iwr.u.retry.value;
566 +static int i802_flush(void *priv)
568 + struct i802_driver_data *drv = priv;
569 + struct nl_msg *msg;
572 + msg = nlmsg_alloc();
576 + genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
577 + 0, NL80211_CMD_NEW_STATION, 0);
580 + * XXX: FIX! this needs to flush all VLANs too
582 + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
583 + if_nametoindex(drv->iface));
587 + if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
588 + nl_wait_for_ack(drv->nl_handle) < 0) {
600 +static int get_sta_handler(struct nl_msg *msg, void *arg)
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 },
612 + nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
613 + genlmsg_attrlen(gnlh, 0), NULL);
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.
621 + if (!tb[NL80211_ATTR_STA_STATS]) {
622 + wpa_printf(MSG_DEBUG, "sta stats missing!");
625 + if (nla_parse_nested(stats, NL80211_STA_STAT_MAX,
626 + tb[NL80211_ATTR_STA_STATS],
628 + wpa_printf(MSG_DEBUG, "failed to parse nested attributes!");
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]);
643 +static int i802_read_sta_data(void *priv, struct hostap_sta_driver_data *data,
646 + struct i802_driver_data *drv = priv;
647 + struct nl_msg *msg;
648 + struct nl_cb *cb = NULL;
653 + msg = nlmsg_alloc();
657 + genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
658 + 0, NL80211_CMD_GET_STATION, 0);
660 + NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
661 + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface));
663 + cb = nl_cb_alloc(NL_CB_CUSTOM);
667 + if (nl_send_auto_complete(drv->nl_handle, msg) < 0)
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);
673 + err = nl_recvmsgs(drv->nl_handle, cb);
676 + err = nl_wait_for_ack(drv->nl_handle);
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)
695 + struct i802_driver_data *drv = priv;
696 + struct ieee80211_hdr *hdr;
701 + int qos = sta->flags & WLAN_STA_WME;
706 + len = sizeof(*hdr) + (qos ? 2 : 0) + sizeof(rfc1042_header) + 2 +
708 + hdr = os_zalloc(len);
710 + printf("malloc() failed for i802_send_data(len=%lu)\n",
711 + (unsigned long) len);
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);
719 + hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);
720 +#if 0 /* To be enabled if qos determination is added above */
722 + hdr->frame_control |=
723 + host_to_le16(WLAN_FC_STYPE_QOS_DATA << 4);
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);
732 +#if 0 /* To be enabled if qos determination is added above */
734 + /* add an empty QoS header if needed */
741 + memcpy(pos, rfc1042_header, sizeof(rfc1042_header));
742 + pos += sizeof(rfc1042_header);
743 + WPA_PUT_BE16(pos, ETH_P_PAE);
745 + memcpy(pos, data, data_len);
747 + res = i802_send_mgmt_frame(drv, (u8 *) hdr, len, 0);
751 + perror("i802_send_eapol: send");
752 + printf("i802_send_eapol - packet len: %lu - failed\n",
753 + (unsigned long) len);
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)
764 + struct i802_driver_data *drv = priv;
765 + struct nl_msg *msg;
768 + msg = nlmsg_alloc();
772 + genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
773 + 0, NL80211_CMD_NEW_STATION, 0);
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,
781 + NLA_PUT_U16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL, 0);
783 + ret = nl_send_auto_complete(drv->nl_handle, msg);
785 + goto nla_put_failure;
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)
800 +static int i802_sta_remove(void *priv, const u8 *addr)
802 + struct i802_driver_data *drv = priv;
803 + struct nl_msg *msg;
806 + msg = nlmsg_alloc();
810 + genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
811 + 0, NL80211_CMD_DEL_STATION, 0);
813 + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
814 + if_nametoindex(drv->iface));
815 + NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
819 + if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
820 + nl_wait_for_ack(drv->nl_handle) < 0) {
832 +static int i802_sta_set_flags(void *priv, const u8 *addr,
833 + int total_flags, int flags_or, int flags_and)
835 + struct i802_driver_data *drv = priv;
836 + struct nl_msg *msg, *flags = NULL;
839 + msg = nlmsg_alloc();
843 + flags = nlmsg_alloc();
847 + genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
848 + 0, NL80211_CMD_SET_STATION, 0);
850 + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
851 + if_nametoindex(drv->iface));
852 + NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
854 + if (total_flags & WLAN_STA_AUTHORIZED || !drv->ieee802_1x_active)
855 + NLA_PUT_FLAG(flags, NL80211_STA_FLAG_AUTHORIZED);
857 + if (total_flags & WLAN_STA_WME)
858 + NLA_PUT_FLAG(flags, NL80211_STA_FLAG_WME);
860 + if (total_flags & WLAN_STA_SHORT_PREAMBLE)
861 + NLA_PUT_FLAG(flags, NL80211_STA_FLAG_SHORT_PREAMBLE);
863 + if (nla_put_nested(msg, NL80211_ATTR_STA_FLAGS, flags))
864 + goto nla_put_failure;
868 + if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
869 + nl_wait_for_ack(drv->nl_handle) < 0) {
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)
892 +static int i802_set_regulatory_domain(void *priv, unsigned int rd)
898 +static int i802_set_tx_queue_params(void *priv, int queue, int aifs,
899 + int cw_min, int cw_max, int burst_time)
905 +static void nl80211_remove_iface(struct i802_driver_data *drv, int ifidx)
907 + struct nl_msg *msg;
909 + /* stop listening for EAPOL on this interface */
910 + del_ifidx(drv, ifidx);
912 + msg = nlmsg_alloc();
914 + goto nla_put_failure;
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)
922 + printf("Failed to remove interface.\n");
927 +static int nl80211_create_iface(struct i802_driver_data *drv,
928 + const char *ifname,
929 + enum nl80211_iftype iftype,
932 + struct nl_msg *msg, *flags = NULL;
934 + struct ifreq ifreq;
937 + msg = nlmsg_alloc();
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);
948 + if (iftype == NL80211_IFTYPE_MONITOR) {
951 + flags = nlmsg_alloc();
953 + goto nla_put_failure;
955 + NLA_PUT_FLAG(flags, NL80211_MNTR_FLAG_COOK_FRAMES);
957 + err = nla_put_nested(msg, NL80211_ATTR_MNTR_FLAGS, flags);
962 + goto nla_put_failure;
965 + if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
966 + nl_wait_for_ack(drv->nl_handle) < 0) {
968 + printf("Failed to create interface %s.\n", ifname);
975 + ifidx = if_nametoindex(ifname);
980 + /* start listening for EAPOL on this interface */
981 + add_ifidx(drv, ifidx);
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;
990 + if (ioctl(drv->ioctl_sock, SIOCSIFHWADDR, &ifreq)) {
991 + nl80211_remove_iface(drv, ifidx);
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))
1013 +static int i802_bss_add(void *priv, const char *ifname, const u8 *bssid)
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.
1024 + ifidx = nl80211_create_iface(priv, ifname, NL80211_IFTYPE_AP, bssid);
1027 + if (hostapd_set_iface_flags(priv, ifname, 1)) {
1028 + nl80211_remove_iface(priv, ifidx);
1035 +static int i802_bss_remove(void *priv, const char *ifname)
1037 + nl80211_remove_iface(priv, if_nametoindex(ifname));
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)
1046 + struct i802_driver_data *drv = priv;
1047 + struct nl_msg *msg;
1048 + u8 cmd = NL80211_CMD_NEW_BEACON;
1051 + msg = nlmsg_alloc();
1055 + if (drv->beacon_set)
1056 + cmd = NL80211_CMD_SET_BEACON;
1058 + genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 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);
1065 + if (!drv->dtim_period)
1066 + drv->dtim_period = 2;
1067 + NLA_PUT_U32(msg, NL80211_ATTR_DTIM_PERIOD, drv->dtim_period);
1069 + if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
1070 + nl_wait_for_ack(drv->nl_handle) < 0)
1075 + drv->beacon_set = 1;
1084 +static int i802_del_beacon(struct i802_driver_data *drv)
1086 + struct nl_msg *msg;
1089 + msg = nlmsg_alloc();
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));
1097 + if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
1098 + nl_wait_for_ack(drv->nl_handle) < 0)
1110 +static int i802_set_ieee8021x(const char *ifname, void *priv, int enabled)
1112 + struct i802_driver_data *drv = priv;
1115 + * FIXME: This needs to be per interface (BSS)
1117 + drv->ieee802_1x_active = enabled;
1122 +static int i802_set_privacy(const char *ifname, void *priv, int enabled)
1124 + struct i802_driver_data *drv = priv;
1127 + memset(&iwr, 0, sizeof(iwr));
1129 + os_strlcpy(iwr.ifr_name, ifname, IFNAMSIZ);
1130 + iwr.u.param.flags = IW_AUTH_PRIVACY_INVOKED;
1131 + iwr.u.param.value = enabled;
1133 + ioctl(drv->ioctl_sock, SIOCSIWAUTH, &iwr);
1135 + /* ignore errors, the kernel/driver might not care */
1140 +static int i802_set_internal_bridge(void *priv, int value)
1146 +static int i802_set_beacon_int(void *priv, int value)
1148 + struct i802_driver_data *drv = priv;
1149 + struct nl_msg *msg;
1152 + msg = nlmsg_alloc();
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));
1160 + NLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL, value);
1162 + if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
1163 + nl_wait_for_ack(drv->nl_handle) < 0)
1175 +static int i802_set_dtim_period(const char *iface, void *priv, int value)
1177 + struct i802_driver_data *drv = priv;
1178 + struct nl_msg *msg;
1181 + msg = nlmsg_alloc();
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));
1189 + drv->dtim_period = value;
1190 + NLA_PUT_U32(msg, NL80211_ATTR_DTIM_PERIOD, drv->dtim_period);
1192 + if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
1193 + nl_wait_for_ack(drv->nl_handle) < 0)
1205 +static int i802_set_cts_protect(void *priv, int value)
1211 +static int i802_set_preamble(void *priv, int value)
1217 +static int i802_set_short_slot_time(void *priv, int value)
1223 +static enum nl80211_iftype i802_if_type(enum hostapd_driver_if_type type)
1226 + case HOSTAPD_IF_VLAN:
1227 + return NL80211_IFTYPE_AP_VLAN;
1228 + case HOSTAPD_IF_WDS:
1229 + return NL80211_IFTYPE_WDS;
1235 +static int i802_if_add(const char *iface, void *priv,
1236 + enum hostapd_driver_if_type type, char *ifname,
1239 + if (nl80211_create_iface(priv, ifname, i802_if_type(type), addr) < 0)
1245 +static int i802_if_update(void *priv, enum hostapd_driver_if_type type,
1246 + char *ifname, const u8 *addr)
1248 + /* unused at the moment */
1253 +static int i802_if_remove(void *priv, enum hostapd_driver_if_type type,
1254 + const char *ifname, const u8 *addr)
1256 + nl80211_remove_iface(priv, if_nametoindex(ifname));
1261 +struct phy_info_arg {
1263 + struct hostapd_hw_modes *modes;
1267 +static int phy_info_handler(struct nl_msg *msg, void *arg)
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;
1273 + struct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1];
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 },
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 },
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;
1297 + nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
1298 + genlmsg_attrlen(gnlh, 0), NULL);
1300 + if (!tb_msg[NL80211_ATTR_WIPHY_BANDS])
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));
1307 + phy_info->modes = mode;
1311 + mode = &phy_info->modes[*(phy_info->num_modes)];
1312 + memset(mode, 0, sizeof(*mode));
1313 + *(phy_info->num_modes) += 1;
1315 + nla_parse(tb_band, NL80211_BAND_ATTR_MAX, nla_data(nl_band),
1316 + nla_len(nl_band), NULL);
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])
1323 + mode->num_channels++;
1326 + mode->channels = calloc(mode->num_channels, sizeof(struct hostapd_channel_data));
1327 + if (!mode->channels)
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])
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;
1343 + if (!mode_is_set) {
1344 + /* crude heuristic */
1345 + if (mode->channels[idx].freq < 4000)
1346 + mode->mode = HOSTAPD_MODE_IEEE80211B;
1348 + mode->mode = HOSTAPD_MODE_IEEE80211A;
1352 + /* crude heuristic */
1353 + if (mode->channels[idx].freq < 4000)
1354 + if (mode->channels[idx].freq == 2848)
1355 + mode->channels[idx].chan = 14;
1357 + mode->channels[idx].chan = (mode->channels[idx].freq - 2407) / 5;
1359 + mode->channels[idx].chan = mode->channels[idx].freq/5 - 1000;
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;
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])
1375 + mode->num_rates++;
1378 + mode->rates = calloc(mode->num_rates, sizeof(struct hostapd_rate_data));
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])
1389 + mode->rates[idx].rate = nla_get_u32(tb_rate[NL80211_BITRATE_ATTR_RATE]);
1391 + /* crude heuristic */
1392 + if (mode->mode == HOSTAPD_MODE_IEEE80211B &&
1393 + mode->rates[idx].rate > 200)
1394 + mode->mode = HOSTAPD_MODE_IEEE80211G;
1396 + if (tb_rate[NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE])
1397 + mode->rates[idx].flags |= HOSTAPD_RATE_PREAMBLE2;
1403 + phy_info->error = 0;
1408 +static struct hostapd_hw_modes *i802_get_hw_feature_data(void *priv,
1412 + struct i802_driver_data *drv = priv;
1413 + struct nl_msg *msg;
1415 + struct nl_cb *cb = NULL;
1417 + struct phy_info_arg result = {
1418 + .num_modes = num_modes,
1426 + msg = nlmsg_alloc();
1430 + genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
1431 + 0, NL80211_CMD_GET_WIPHY, 0);
1433 + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface));
1435 + cb = nl_cb_alloc(NL_CB_CUSTOM);
1439 + if (nl_send_auto_complete(drv->nl_handle, msg) < 0)
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);
1445 + err = nl_recvmsgs(drv->nl_handle, cb);
1448 + err = nl_wait_for_ack(drv->nl_handle);
1450 + if (err < 0 || result.error) {
1451 + hostapd_free_hw_features(result.modes, *num_modes);
1452 + result.modes = NULL;
1459 + fprintf(stderr, "failed to get information: %d\n", err);
1461 + return result.modes;
1465 +static int i802_set_sta_vlan(void *priv, const u8 *addr,
1466 + const char *ifname, int vlan_id)
1468 + struct i802_driver_data *drv = priv;
1469 + struct nl_msg *msg;
1472 + msg = nlmsg_alloc();
1476 + genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
1477 + 0, NL80211_CMD_SET_STATION, 0);
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));
1487 + if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
1488 + (errno = nl_wait_for_ack(drv->nl_handle) < 0)) {
1500 +static void handle_unknown_sta(struct hostapd_data *hapd, u8 *ta)
1502 + struct sta_info *sta;
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(
1511 + WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
1513 + hostapd_sta_deauth(
1515 + WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
1520 +static void handle_tx_callback(struct hostapd_data *hapd, u8 *buf, size_t len,
1523 + struct ieee80211_hdr *hdr;
1524 + u16 fc, type, stype;
1525 + struct sta_info *sta;
1527 + hdr = (struct ieee80211_hdr *) buf;
1528 + fc = le_to_host16(hdr->frame_control);
1530 + type = WLAN_FC_GET_TYPE(fc);
1531 + stype = WLAN_FC_GET_STYPE(fc);
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);
1539 + case WLAN_FC_TYPE_CTRL:
1540 + wpa_printf(MSG_DEBUG, "CTRL (TX callback) %s",
1541 + ok ? "ACK" : "fail");
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");
1552 + sta->flags &= ~WLAN_STA_PENDING_POLL;
1555 + ieee802_1x_tx_status(hapd, sta, buf, len, ok);
1558 + printf("unknown TX callback frame type %d\n", type);
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)
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;
1577 + * PS-Poll frames are 16 bytes. All other frames are
1578 + * 24 bytes or longer.
1583 + hdr = (struct ieee80211_hdr *) buf;
1584 + fc = le_to_host16(hdr->frame_control);
1586 + type = WLAN_FC_GET_TYPE(fc);
1587 + stype = WLAN_FC_GET_STYPE(fc);
1590 + case WLAN_FC_TYPE_DATA:
1593 + switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
1594 + case WLAN_FC_TODS:
1595 + bssid = hdr->addr1;
1602 + case WLAN_FC_TYPE_CTRL:
1603 + /* discard non-ps-poll frames */
1604 + if (stype != WLAN_FC_STYPE_PSPOLL)
1606 + bssid = hdr->addr1;
1608 + case WLAN_FC_TYPE_MGMT:
1609 + bssid = hdr->addr3;
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];
1624 + if (hapd == NULL) {
1625 + hapd = iface->bss[0];
1627 + if (bssid[0] != 0xff || bssid[1] != 0xff ||
1628 + bssid[2] != 0xff || bssid[3] != 0xff ||
1629 + bssid[4] != 0xff || bssid[5] != 0xff) {
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)
1636 + if ((type != WLAN_FC_TYPE_MGMT ||
1637 + stype != WLAN_FC_STYPE_BEACON))
1640 + broadcast_bssid = 1;
1643 + switch (msg_type) {
1644 + case ieee80211_msg_normal:
1645 + /* continue processing */
1647 + case ieee80211_msg_tx_callback_ack:
1648 + handle_tx_callback(hapd, buf, data_len, 1);
1650 + case ieee80211_msg_tx_callback_fail:
1651 + handle_tx_callback(hapd, buf, data_len, 0);
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,
1665 + ieee802_11_mgmt(hapd, buf, data_len, stype, hfi);
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);
1672 + case WLAN_FC_TYPE_DATA:
1673 + wpa_printf(MSG_DEBUG, "DATA");
1674 + handle_unknown_sta(hapd, hdr->addr2);
1680 +static void handle_eapol(int sock, void *eloop_ctx, void *sock_ctx)
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];
1687 + socklen_t fromlen = sizeof(lladdr);
1689 + len = recvfrom(sock, buf, sizeof(buf), 0,
1690 + (struct sockaddr *)&lladdr, &fromlen);
1696 + if (have_ifidx(drv, lladdr.sll_ifindex))
1697 + ieee802_1x_receive(hapd, lladdr.sll_addr, buf, len);
1701 +static void handle_monitor_read(int sock, void *eloop_ctx, void *sock_ctx)
1703 + struct i802_driver_data *drv = eloop_ctx;
1705 + unsigned char buf[3000];
1706 + struct hostapd_data *hapd = drv->hapd;
1707 + struct ieee80211_radiotap_iterator iter;
1709 + struct hostapd_frame_info hfi;
1710 + int injected = 0, failed = 0, msg_type, rxflags = 0;
1712 + len = recv(sock, buf, sizeof(buf), 0);
1718 + if (ieee80211_radiotap_iterator_init(&iter, (void*)buf, len)) {
1719 + printf("received invalid radiotap frame\n");
1723 + memset(&hfi, 0, sizeof(hfi));
1726 + ret = ieee80211_radiotap_iterator_next(&iter);
1727 + if (ret == -ENOENT)
1730 + printf("received invalid radiotap frame (%d)\n", ret);
1733 + switch (iter.this_arg_index) {
1734 + case IEEE80211_RADIOTAP_FLAGS:
1735 + if (*iter.this_arg & IEEE80211_RADIOTAP_F_FCS)
1738 + case IEEE80211_RADIOTAP_RX_FLAGS:
1741 + case IEEE80211_RADIOTAP_TX_FLAGS:
1743 + failed = le_to_host16((*(uint16_t *) iter.this_arg)) &
1744 + IEEE80211_RADIOTAP_F_TX_FAIL;
1746 + case IEEE80211_RADIOTAP_DATA_RETRIES:
1748 + case IEEE80211_RADIOTAP_CHANNEL:
1749 + /* TODO convert from freq/flags to channel number
1750 + hfi.channel = XXX;
1751 + hfi.phytype = XXX;
1754 + case IEEE80211_RADIOTAP_RATE:
1755 + hfi.datarate = *iter.this_arg * 5;
1757 + case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
1758 + hfi.ssi_signal = *iter.this_arg;
1763 + if (rxflags && injected)
1767 + msg_type = ieee80211_msg_normal;
1769 + msg_type = ieee80211_msg_tx_callback_fail;
1771 + msg_type = ieee80211_msg_tx_callback_ack;
1773 + handle_frame(hapd->iface, buf + iter.max_length,
1774 + len - iter.max_length, &hfi, msg_type);
1778 +static int nl80211_create_monitor_interface(struct i802_driver_data *drv)
1780 + char buf[IFNAMSIZ];
1781 + struct sockaddr_ll ll;
1785 + snprintf(buf, IFNAMSIZ, "mon.%s", drv->iface);
1786 + buf[IFNAMSIZ - 1] = '\0';
1788 + drv->monitor_ifidx =
1789 + nl80211_create_iface(drv, buf, NL80211_IFTYPE_MONITOR, NULL);
1791 + if (drv->monitor_ifidx < 0)
1794 + if (hostapd_set_iface_flags(drv, buf, 1))
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]");
1806 + if (bind(drv->monitor_sock, (struct sockaddr *) &ll,
1807 + sizeof(ll)) < 0) {
1808 + perror("monitor socket bind");
1812 + optlen = sizeof(optval);
1815 + (drv->monitor_sock, SOL_SOCKET, SO_PRIORITY, &optval, optlen)) {
1816 + perror("Failed to set socket priority");
1820 + if (eloop_register_read_sock(drv->monitor_sock, handle_monitor_read,
1822 + printf("Could not register monitor read socket\n");
1828 + nl80211_remove_iface(drv, drv->monitor_ifidx);
1833 +static int nl80211_set_master_mode(struct i802_driver_data *drv,
1834 + const char *ifname)
1836 + struct nl_msg *msg;
1838 + msg = nlmsg_alloc();
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);
1848 + if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
1849 + nl_wait_for_ack(drv->nl_handle) < 0) {
1851 + wpa_printf(MSG_ERROR, "Failed to set interface %s to master "
1863 +static int i802_init_sockets(struct i802_driver_data *drv, const u8 *bssid)
1866 + struct sockaddr_ll addr;
1868 + drv->ioctl_sock = -1;
1870 + drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
1871 + if (drv->ioctl_sock < 0) {
1872 + perror("socket[PF_INET,SOCK_DGRAM]");
1876 + /* start listening for EAPOL on the default AP interface */
1877 + add_ifidx(drv, if_nametoindex(drv->iface));
1879 + if (hostapd_set_iface_flags(drv, drv->iface, 0))
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;
1887 + if (ioctl(drv->ioctl_sock, SIOCSIFHWADDR, &ifr)) {
1888 + perror("ioctl(SIOCSIFHWADDR)");
1894 + * initialise generic netlink and nl80211
1896 + drv->nl_handle = nl_handle_alloc();
1897 + if (!drv->nl_handle) {
1898 + printf("Failed to allocate netlink handle.\n");
1902 + if (genl_connect(drv->nl_handle)) {
1903 + printf("Failed to connect to generic netlink.\n");
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");
1913 + drv->nl80211 = genl_ctrl_search_by_name(drv->nl_cache, "nl80211");
1914 + if (!drv->nl80211) {
1915 + printf("nl80211 not found.\n");
1919 + /* Initialise a monitor interface */
1920 + if (nl80211_create_monitor_interface(drv))
1923 + if (nl80211_set_master_mode(drv, drv->iface))
1926 + if (hostapd_set_iface_flags(drv, drv->iface, 1))
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);
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)");
1941 + if (eloop_register_read_sock(drv->eapol_sock, handle_eapol, drv, NULL))
1943 + printf("Could not register read socket for eapol\n");
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)");
1954 + if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
1955 + printf("Invalid HW-addr family 0x%04x\n",
1956 + ifr.ifr_hwaddr.sa_family);
1959 + memcpy(drv->hapd->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
1965 +static int i802_get_inact_sec(void *priv, const u8 *addr)
1967 + struct hostap_sta_driver_data data;
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)
1974 + return data.inactive_msec / 1000;
1978 +static int i802_sta_clear_stats(void *priv, const u8 *addr)
1988 +hostapd_wireless_event_wireless_custom(struct i802_driver_data *drv,
1991 + wpa_printf(MSG_DEBUG, "Custom wireless event: '%s'", custom);
1993 + if (strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) {
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");
2004 + if (hwaddr_aton(pos, addr) == 0) {
2005 + ieee80211_michael_mic_failure(drv->hapd, addr, 1);
2007 + wpa_printf(MSG_DEBUG,
2008 + "MLME-MICHAELMICFAILURE.indication "
2009 + "with invalid MAC address");
2015 +static void hostapd_wireless_event_wireless(struct i802_driver_data *drv,
2016 + char *data, int len)
2018 + struct iw_event iwe_buf, *iwe = &iwe_buf;
2019 + char *pos, *end, *custom, *buf;
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)
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);
2043 + memcpy(&iwe_buf, pos, sizeof(struct iw_event));
2044 + custom += IW_EV_POINT_OFF;
2047 + switch (iwe->cmd) {
2049 + if (custom + iwe->u.data.length > end)
2051 + buf = malloc(iwe->u.data.length + 1);
2054 + memcpy(buf, custom, iwe->u.data.length);
2055 + buf[iwe->u.data.length] = '\0';
2056 + hostapd_wireless_event_wireless_custom(drv, buf);
2066 +static void hostapd_wireless_event_rtm_newlink(struct i802_driver_data *drv,
2067 + struct nlmsghdr *h, int len)
2069 + struct ifinfomsg *ifi;
2070 + int attrlen, nlmsg_len, rta_len;
2071 + struct rtattr *attr;
2073 + if (len < (int) sizeof(*ifi))
2076 + ifi = NLMSG_DATA(h);
2078 + /* TODO: use ifi->ifi_index to filter out wireless events from other
2081 + nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
2083 + attrlen = h->nlmsg_len - nlmsg_len;
2087 + attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);
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);
2096 + attr = RTA_NEXT(attr, attrlen);
2101 +static void hostapd_wireless_event_receive(int sock, void *eloop_ctx,
2106 + struct sockaddr_nl from;
2107 + socklen_t fromlen;
2108 + struct nlmsghdr *h;
2109 + struct i802_driver_data *drv = eloop_ctx;
2111 + fromlen = sizeof(from);
2112 + left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT,
2113 + (struct sockaddr *) &from, &fromlen);
2115 + if (errno != EINTR && errno != EAGAIN)
2116 + perror("recvfrom(netlink)");
2120 + h = (struct nlmsghdr *) buf;
2121 + while (left >= (int) sizeof(*h)) {
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",
2133 + switch (h->nlmsg_type) {
2135 + hostapd_wireless_event_rtm_newlink(drv, h, plen);
2139 + len = NLMSG_ALIGN(len);
2141 + h = (struct nlmsghdr *) ((char *) h + len);
2145 + printf("%d extra bytes in the end of netlink message\n", left);
2150 +static int hostap_get_we_version(struct i802_driver_data *drv)
2152 + struct iw_range *range;
2157 + drv->we_version = 0;
2160 + * Use larger buffer than struct iw_range in order to allow the
2161 + * structure to grow in the future.
2163 + buflen = sizeof(struct iw_range) + 500;
2164 + range = os_zalloc(buflen);
2165 + if (range == NULL)
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;
2173 + minlen = ((char *) &range->enc_capa) - (char *) range +
2174 + sizeof(range->enc_capa);
2176 + if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) {
2177 + perror("ioctl[SIOCGIWRANGE]");
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,
2187 + drv->we_version = range->we_version_compiled;
2195 +static int i802_wireless_event_init(void *priv)
2197 + struct i802_driver_data *drv = priv;
2199 + struct sockaddr_nl local;
2201 + hostap_get_we_version(drv);
2203 + drv->wext_sock = -1;
2205 + s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
2207 + perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)");
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)");
2220 + eloop_register_read_sock(s, hostapd_wireless_event_receive, drv,
2222 + drv->wext_sock = s;
2228 +static void i802_wireless_event_deinit(void *priv)
2230 + struct i802_driver_data *drv = priv;
2231 + if (drv->wext_sock < 0)
2233 + eloop_unregister_read_sock(drv->wext_sock);
2234 + close(drv->wext_sock);
2238 +static int i802_sta_deauth(void *priv, const u8 *addr, int reason)
2240 + struct i802_driver_data *drv = priv;
2241 + struct ieee80211_mgmt mgmt;
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);
2255 +static int i802_sta_disassoc(void *priv, const u8 *addr, int reason)
2257 + struct i802_driver_data *drv = priv;
2258 + struct ieee80211_mgmt mgmt;
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);
2272 +static void *i802_init_bssid(struct hostapd_data *hapd, const u8 *bssid)
2274 + struct i802_driver_data *drv;
2276 + drv = os_zalloc(sizeof(struct i802_driver_data));
2277 + if (drv == NULL) {
2278 + printf("Could not allocate memory for i802 driver data\n");
2283 + memcpy(drv->iface, hapd->conf->iface, sizeof(drv->iface));
2285 + drv->num_if_indices = sizeof(drv->default_if_indices) / sizeof(int);
2286 + drv->if_indices = drv->default_if_indices;
2288 + if (i802_init_sockets(drv, bssid))
2299 +static void *i802_init(struct hostapd_data *hapd)
2301 + return i802_init_bssid(hapd, NULL);
2305 +static void i802_deinit(void *priv)
2307 + struct i802_driver_data *drv = priv;
2309 + i802_del_beacon(drv);
2311 + /* remove monitor interface */
2312 + nl80211_remove_iface(drv, drv->monitor_ifidx);
2314 + (void) hostapd_set_iface_flags(drv, drv->iface, 0);
2316 + if (drv->monitor_sock >= 0) {
2317 + eloop_unregister_read_sock(drv->monitor_sock);
2318 + close(drv->monitor_sock);
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);
2327 + genl_family_put(drv->nl80211);
2328 + nl_cache_free(drv->nl_cache);
2329 + nl_handle_destroy(drv->nl_handle);
2331 + if (drv->if_indices != drv->default_if_indices)
2332 + free(drv->if_indices);
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,
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
2394 + * Copyright 2007 Andy Green <andy@warmcat.com>
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.
2400 + * Alternatively, this software may be distributed under the terms of BSD
2403 + * See README and COPYING for more details.
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.
2410 +#include "includes.h"
2412 +#include "common.h"
2413 +#include "radiotap_iter.h"
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) \
2422 + struct packed_dummy_struct { \
2423 + typeof(*(p)) __val; \
2424 + } __attribute__((packed)) *__ptr = (void *) (p); \
2429 +/* function prototypes and related defs are in radiotap_iter.h */
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)
2437 + * Returns: 0 or a negative error code if there is a problem.
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.
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.
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()
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.
2467 + * See Documentation/networking/radiotap-headers.txt
2470 +int ieee80211_radiotap_iterator_init(
2471 + struct ieee80211_radiotap_iterator *iterator,
2472 + struct ieee80211_radiotap_header *radiotap_header,
2475 + /* Linux only supports version 0 radiotap format */
2476 + if (radiotap_header->it_version)
2479 + /* sanity check for allowed length and radiotap length field */
2480 + if (max_length < le16_to_cpu(get_unaligned(&radiotap_header->it_len)))
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;
2492 + /* find payload start allowing for extended bitmap(s) */
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);
2500 + * check for insanity where the present bitmaps
2501 + * keep claiming to extend up to or even beyond the
2502 + * stated radiotap header length
2505 + if (((ulong)iterator->arg - (ulong)iterator->rtheader)
2506 + > (ulong)iterator->max_length)
2510 + iterator->arg += sizeof(u32);
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
2519 + /* we are all initialized happily */
2526 + * ieee80211_radiotap_iterator_next - return next radiotap parser iterator arg
2527 + * @iterator: radiotap_iterator to move to next arg (if any)
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.
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.
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.
2548 +int ieee80211_radiotap_iterator_next(
2549 + struct ieee80211_radiotap_iterator *iterator)
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
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.
2563 + * upper nybble: content alignment for arg
2564 + * lower nybble: content length for arg
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,
2587 + * add more here as they are defined in
2588 + * include/net/ieee80211_radiotap.h
2593 + * for every radiotap entry we can at
2594 + * least skip (by knowing the length)...
2597 + while (iterator->arg_index < (int) sizeof(rt_sizes)) {
2601 + if (!(iterator->bitmap_shifter & 1))
2602 + goto next_entry; /* arg not present */
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
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
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.
2620 + * the above is why get_unaligned() is used to dereference
2621 + * multibyte elements from the radiotap area
2624 + pad = (((ulong)iterator->arg) -
2625 + ((ulong)iterator->rtheader)) &
2626 + ((rt_sizes[iterator->arg_index] >> 4) - 1);
2630 + (rt_sizes[iterator->arg_index] >> 4) - pad;
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
2636 + iterator->this_arg_index = iterator->arg_index;
2637 + iterator->this_arg = iterator->arg;
2640 + /* internally move on the size of this arg */
2641 + iterator->arg += rt_sizes[iterator->arg_index] & 0x0f;
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.
2650 + if (((ulong)iterator->arg - (ulong)iterator->rtheader) >
2651 + (ulong) iterator->max_length)
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++;
2665 + /* no more bitmaps: end */
2666 + iterator->arg_index = sizeof(rt_sizes);
2667 + } else /* just try the next bit */
2668 + iterator->bitmap_shifter >>= 1;
2670 + /* if we found a valid arg earlier, return it now */
2675 + /* we don't know how to handle any more args, we're done */
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
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 $ */
2686 + * Copyright (c) 2003, 2004 David Young. All rights reserved.
2688 + * Redistribution and use in source and binary forms, with or without
2689 + * modification, are permitted provided that the following conditions
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.
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
2715 + * Modifications to fit into the linux IEEE 802.11 stack,
2716 + * Mike Kershaw (dragorn@kismetwireless.net)
2719 +#ifndef IEEE80211RADIOTAP_H
2720 +#define IEEE80211RADIOTAP_H
2722 +#include <stdint.h>
2724 +/* Base version of the radiotap packet header data */
2725 +#define PKTHDR_RADIOTAP_VERSION 0
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.
2731 + * I suggest the following extensible radio capture format. It is
2732 + * based on a bitmap indicating which fields are present.
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
2742 +/* The radio capture header precedes the 802.11 header.
2743 + * All data in the header is little endian on all platforms.
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.
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.
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.
2766 +/* Name Data type Units
2767 + * ---- --------- -----
2769 + * IEEE80211_RADIOTAP_TSFT __le64 microseconds
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.
2775 + * IEEE80211_RADIOTAP_CHANNEL 2 x uint16_t MHz, bitmap
2777 + * Tx/Rx frequency in MHz, followed by flags (see below).
2779 + * IEEE80211_RADIOTAP_FHSS uint16_t see below
2781 + * For frequency-hopping radios, the hop set (first byte)
2782 + * and pattern (second byte).
2784 + * IEEE80211_RADIOTAP_RATE u8 500kb/s
2788 + * IEEE80211_RADIOTAP_DBM_ANTSIGNAL s8 decibels from
2789 + * one milliwatt (dBm)
2791 + * RF signal power at the antenna, decibel difference from
2794 + * IEEE80211_RADIOTAP_DBM_ANTNOISE s8 decibels from
2795 + * one milliwatt (dBm)
2797 + * RF noise power at the antenna, decibel difference from one
2800 + * IEEE80211_RADIOTAP_DB_ANTSIGNAL u8 decibel (dB)
2802 + * RF signal power at the antenna, decibel difference from an
2803 + * arbitrary, fixed reference.
2805 + * IEEE80211_RADIOTAP_DB_ANTNOISE u8 decibel (dB)
2807 + * RF noise power at the antenna, decibel difference from an
2808 + * arbitrary, fixed reference point.
2810 + * IEEE80211_RADIOTAP_LOCK_QUALITY uint16_t unitless
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
2817 + * IEEE80211_RADIOTAP_TX_ATTENUATION uint16_t unitless
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.
2823 + * IEEE80211_RADIOTAP_DB_TX_ATTENUATION uint16_t decibels (dB)
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.
2829 + * IEEE80211_RADIOTAP_DBM_TX_POWER s8 decibels from
2830 + * one milliwatt (dBm)
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.
2836 + * IEEE80211_RADIOTAP_FLAGS u8 bitmap
2838 + * Properties of transmitted and received frames. See flags
2841 + * IEEE80211_RADIOTAP_ANTENNA u8 antenna index
2843 + * Unitless indication of the Rx/Tx antenna for this packet.
2844 + * The first antenna is antenna 0.
2846 + * IEEE80211_RADIOTAP_RX_FLAGS uint16_t bitmap
2848 + * Properties of received frames. See flags defined below.
2850 + * IEEE80211_RADIOTAP_TX_FLAGS uint16_t bitmap
2852 + * Properties of transmitted frames. See flags defined below.
2854 + * IEEE80211_RADIOTAP_RTS_RETRIES u8 data
2856 + * Number of rts retries a transmitted frame used.
2858 + * IEEE80211_RADIOTAP_DATA_RETRIES u8 data
2860 + * Number of unicast retries a transmitted frame used.
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
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) */
2895 +/* For IEEE80211_RADIOTAP_FLAGS */
2896 +#define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received
2899 +#define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 /* sent/received
2903 +#define IEEE80211_RADIOTAP_F_WEP 0x04 /* sent/received
2904 + * with WEP encryption
2906 +#define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received
2907 + * with fragmentation
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)
2914 +/* For IEEE80211_RADIOTAP_RX_FLAGS */
2915 +#define IEEE80211_RADIOTAP_F_RX_BADFCS 0x0001 /* frame failed crc check */
2917 +/* For IEEE80211_RADIOTAP_TX_FLAGS */
2918 +#define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive
2920 +#define IEEE80211_RADIOTAP_F_TX_CTS 0x0002 /* used cts 'protection' */
2921 +#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */
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
2928 +#ifndef __RADIOTAP_ITER_H
2929 +#define __RADIOTAP_ITER_H
2931 +#include "radiotap.h"
2933 +/* Radiotap header iteration
2934 + * implemented in radiotap.c
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
2948 +struct ieee80211_radiotap_iterator {
2949 + struct ieee80211_radiotap_header *rtheader;
2951 + int this_arg_index;
2952 + unsigned char *this_arg;
2955 + unsigned char *arg;
2956 + uint32_t *next_bitmap;
2957 + uint32_t bitmap_shifter;
2960 +extern int ieee80211_radiotap_iterator_init(
2961 + struct ieee80211_radiotap_iterator *iterator,
2962 + struct ieee80211_radiotap_header *radiotap_header,
2965 +extern int ieee80211_radiotap_iterator_next(
2966 + struct ieee80211_radiotap_iterator *iterator);
2968 +#endif /* __RADIOTAP_ITER_H */