aboutsummaryrefslogtreecommitdiffstats
path: root/hostapd/driver_nl80211.c
diff options
context:
space:
mode:
Diffstat (limited to 'hostapd/driver_nl80211.c')
-rw-r--r--hostapd/driver_nl80211.c557
1 files changed, 240 insertions, 317 deletions
diff --git a/hostapd/driver_nl80211.c b/hostapd/driver_nl80211.c
index 34bf8d8..61b3132 100644
--- a/hostapd/driver_nl80211.c
+++ b/hostapd/driver_nl80211.c
@@ -38,6 +38,8 @@
#include "sta_info.h"
#include "hw_features.h"
#include "mlme.h"
+#include "radiotap.h"
+#include "radiotap_iter.h"
/*
* old definitions from the prism2/hostap driver interface that
@@ -49,7 +51,6 @@
#define PRISM2_PARAM_AP_BRIDGE_PACKETS 10
#define PRISM2_PARAM_IEEE_802_1X 23
-#define PRISM2_PARAM_MGMT_IF 1046
#define PRISM2_HOSTAPD_GET_HW_FEATURES 1002
#define PRISM2_HOSTAPD_MAX_BUF_SIZE 2048
@@ -116,40 +117,10 @@ struct hostapd_ioctl_hw_modes_hdr {
int num_rates;
};
-/*
- * frame format for the management interface that is slated
- * to be replaced by "cooked monitor" with radiotap
- */
-#define IEEE80211_FI_VERSION 0x80211001
-struct ieee80211_frame_info {
- __be32 version;
- __be32 length;
- __be64 mactime;
- __be64 hosttime;
- __be32 phytype;
- __be32 channel;
- __be32 datarate;
- __be32 antenna;
- __be32 priority;
- __be32 ssi_type;
- __be32 ssi_signal;
- __be32 ssi_noise;
- __be32 preamble;
- __be32 encoding;
-
- /* Note: this structure is otherwise identical to capture format used
- * in linux-wlan-ng, but this additional field is used to provide meta
- * data about the frame to hostapd. This was the easiest method for
- * providing this information, but this might change in the future. */
- __be32 msg_type;
-} __attribute__ ((packed));
-
enum ieee80211_msg_type {
ieee80211_msg_normal = 0,
ieee80211_msg_tx_callback_ack = 1,
ieee80211_msg_tx_callback_fail = 2,
- ieee80211_msg_passive_scan = 3,
- ieee80211_msg_sta_not_assoc = 7,
};
/* old mode definitions */
@@ -167,12 +138,11 @@ struct i802_driver_data {
struct hostapd_data *hapd;
char iface[IFNAMSIZ + 1];
- char mgmt_iface[IFNAMSIZ + 1];
- int mgmt_ifindex;
- int sock; /* raw packet socket for driver access */
int ioctl_sock; /* socket for ioctl() use */
int wext_sock; /* socket for wireless events */
int eapol_sock; /* socket for EAPOL frames */
+ int monitor_sock; /* socket for monitor */
+ int monitor_ifidx;
int default_if_indices[16];
int *if_indices;
@@ -270,7 +240,7 @@ static int hostapd_set_iface_flags(struct i802_driver_data *drv,
if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, &ifr) != 0) {
perror("ioctl[SIOCGIFFLAGS]");
wpa_printf(MSG_DEBUG, "Could not read interface flags (%s)",
- drv->mgmt_iface);
+ drv->iface);
return -1;
}
@@ -284,17 +254,6 @@ static int hostapd_set_iface_flags(struct i802_driver_data *drv,
return -1;
}
- if (dev_up) {
- memset(&ifr, 0, sizeof(ifr));
- os_strlcpy(ifr.ifr_name, drv->mgmt_iface, IFNAMSIZ);
- ifr.ifr_mtu = HOSTAPD_MTU;
- if (ioctl(drv->ioctl_sock, SIOCSIFMTU, &ifr) != 0) {
- perror("ioctl[SIOCSIFMTU]");
- printf("Setting MTU failed - trying to survive with "
- "current value\n");
- }
- }
-
return 0;
}
@@ -579,37 +538,6 @@ static int hostap_ioctl_prism2param(struct i802_driver_data *drv, int param,
}
-static int hostap_ioctl_get_prism2param_iface(const char *iface,
- struct i802_driver_data *drv,
- int param)
-{
- struct iwreq iwr;
- int *i;
-
- memset(&iwr, 0, sizeof(iwr));
- os_strlcpy(iwr.ifr_name, iface, IFNAMSIZ);
- i = (int *) iwr.u.name;
- *i = param;
-
- if (ioctl(drv->ioctl_sock, PRISM2_IOCTL_GET_PRISM2_PARAM, &iwr) < 0) {
- char buf[128];
- snprintf(buf, sizeof(buf),
- "%s: ioctl[PRISM2_IOCTL_GET_PRISM2_PARAM]", iface);
- perror(buf);
- return -1;
- }
-
- return *i;
-}
-
-
-static int hostap_ioctl_get_prism2param(struct i802_driver_data *drv,
- int param)
-{
- return hostap_ioctl_get_prism2param_iface(drv->iface, drv, param);
-}
-
-
static int i802_set_ssid(const char *ifname, void *priv, const u8 *buf,
int len)
{
@@ -632,12 +560,46 @@ static int i802_set_ssid(const char *ifname, void *priv, const u8 *buf,
}
-static int i802_send_mgmt_frame(void *priv, const void *msg, size_t len,
+static int i802_send_mgmt_frame(void *priv, const void *data, size_t len,
int flags)
{
+ struct ieee80211_hdr *hdr = (void*) data;
+ __u8 rtap_hdr[] = {
+ 0x00, 0x00, /* radiotap version */
+ 0x0e, 0x00, /* radiotap length */
+ 0x02, 0xc0, 0x00, 0x00, /* bmap: flags, tx and rx flags */
+ 0x0c, /* F_WEP | F_FRAG (encrypt/fragment if required) */
+ 0x00, /* padding */
+ 0x00, 0x00, /* RX and TX flags to indicate that */
+ 0x00, 0x00, /* this is the injected frame directly */
+ };
struct i802_driver_data *drv = priv;
+ struct iovec iov[2] = {
+ {
+ .iov_base = &rtap_hdr,
+ .iov_len = sizeof(rtap_hdr),
+ },
+ {
+ .iov_base = (void*)data,
+ .iov_len = len,
+ }
+ };
+ struct msghdr msg = {
+ .msg_name = NULL,
+ .msg_namelen = 0,
+ .msg_iov = iov,
+ .msg_iovlen = 2,
+ .msg_control = NULL,
+ .msg_controllen = 0,
+ .msg_flags = 0,
+ };
- return send(drv->sock, msg, len, flags);
+ /*
+ * ugh, guess what, the generic code sets one of the version
+ * bits to request tx callback
+ */
+ hdr->frame_control &= ~host_to_le16(BIT(1));
+ return sendmsg(drv->monitor_sock, &msg, flags);
}
@@ -955,8 +917,6 @@ static int i802_send_eapol(void *priv, const u8 *addr, const u8 *data,
hdr->frame_control =
IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA);
hdr->frame_control |= host_to_le16(WLAN_FC_FROMDS);
- /* Request TX callback */
- hdr->frame_control |= host_to_le16(BIT(1));
if (encrypt)
hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);
#if 0 /* To be enabled if qos determination is added above */
@@ -1225,7 +1185,7 @@ static int nl80211_create_iface(struct i802_driver_data *drv,
enum nl80211_iftype iftype,
const u8 *addr)
{
- struct nl_msg *msg;
+ struct nl_msg *msg, *flags = NULL;
int ifidx;
struct ifreq ifreq;
struct iwreq iwr;
@@ -1241,6 +1201,23 @@ static int nl80211_create_iface(struct i802_driver_data *drv,
NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, ifname);
NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, iftype);
+ if (iftype == NL80211_IFTYPE_MONITOR) {
+ int err;
+
+ flags = nlmsg_alloc();
+ if (!flags)
+ goto nla_put_failure;
+
+ NLA_PUT_FLAG(flags, NL80211_MNTR_FLAG_COOK_FRAMES);
+
+ err = nla_put_nested(msg, NL80211_ATTR_MNTR_FLAGS, flags);
+
+ nlmsg_free(flags);
+
+ if (err)
+ goto nla_put_failure;
+ }
+
if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
nl_wait_for_ack(drv->nl_handle) < 0) {
nla_put_failure:
@@ -1665,73 +1642,22 @@ static int i802_set_sta_vlan(void *priv, const u8 *addr,
}
-static void handle_data(struct hostapd_data *hapd, u8 *buf, size_t len,
- u16 stype, struct ieee80211_frame_info *fi)
+static void handle_unknown_sta(struct hostapd_data *hapd, u8 *ta)
{
- struct ieee80211_hdr *hdr;
- u16 fc, ethertype;
- u8 *pos, *sa;
- size_t left;
struct sta_info *sta;
- if (len < sizeof(struct ieee80211_hdr))
- return;
-
- hdr = (struct ieee80211_hdr *) buf;
- fc = le_to_host16(hdr->frame_control);
-
- if ((fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) != WLAN_FC_TODS) {
- printf("Not ToDS data frame (fc=0x%04x)\n", fc);
- return;
- }
-
- sa = hdr->addr2;
- sta = ap_get_sta(hapd, sa);
+ sta = ap_get_sta(hapd, ta);
if (!sta || !(sta->flags & WLAN_STA_ASSOC)) {
- printf("Data frame from not associated STA " MACSTR "\n",
- MAC2STR(sa));
+ printf("Data/PS-poll frame from not associated STA "
+ MACSTR "\n", MAC2STR(ta));
if (sta && (sta->flags & WLAN_STA_AUTH))
hostapd_sta_disassoc(
- hapd, sa,
+ hapd, ta,
WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
else
hostapd_sta_deauth(
- hapd, sa,
+ hapd, ta,
WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
- return;
- }
-
- pos = (u8 *) (hdr + 1);
- left = len - sizeof(*hdr);
-
- if (left < sizeof(rfc1042_header)) {
- printf("Too short data frame\n");
- return;
- }
-
- if (memcmp(pos, rfc1042_header, sizeof(rfc1042_header)) != 0) {
- printf("Data frame with no RFC1042 header\n");
- return;
- }
- pos += sizeof(rfc1042_header);
- left -= sizeof(rfc1042_header);
-
- if (left < 2) {
- printf("No ethertype in data frame\n");
- return;
- }
-
- ethertype = WPA_GET_BE16(pos);
- pos += 2;
- left -= 2;
- switch (ethertype) {
- case ETH_P_PAE:
- ieee802_1x_receive(hapd, sa, pos, left);
- break;
-
- default:
- printf("Unknown ethertype 0x%04x in data frame\n", ethertype);
- break;
}
}
@@ -1780,34 +1706,9 @@ static void handle_tx_callback(struct hostapd_data *hapd, u8 *buf, size_t len,
}
-static void dump_frame_info(struct ieee80211_frame_info *fi, size_t len)
-{
- u64 ts, tus;
-
- tus = ts = be_to_host64(fi->hosttime);
- ts /= 1000000;
- tus -= ts * 1000000;
- wpa_hexdump(MSG_DEBUG, "Frame info dump", (u8 *) fi, len);
- printf("version:\t0x%08x\n", ntohl(fi->version));
- printf("length:\t%d\n", ntohl(fi->length));
- printf("mactime:\t%lld\n", be_to_host64(fi->mactime));
- printf("hosttime:\t%lld.%06lld\n", ts, tus);
- printf("phytype:\t%d\n", ntohl(fi->phytype));
- printf("channel:\t%d\n", ntohl(fi->channel));
- printf("datarate:\t%d\n", ntohl(fi->datarate));
- printf("antenna:\t%d\n", ntohl(fi->antenna));
- printf("priority\t%d\n", ntohl(fi->priority));
- printf("ssi_type:\t%d\n", ntohl(fi->ssi_type));
- printf("ssi_signal:\t%d\n", ntohl(fi->ssi_signal));
- printf("ssi_noise:\t%d\n", ntohl(fi->ssi_noise));
- printf("preamble:\t%d\n", ntohl(fi->preamble));
- printf("encoding:\t%d\n", ntohl(fi->encoding));
- printf("msg_type:\t%d\n", ntohl(fi->msg_type));
-}
-
-
static void handle_frame(struct hostapd_iface *iface, u8 *buf, size_t len,
- struct ieee80211_frame_info *fi)
+ struct hostapd_frame_info *hfi,
+ enum ieee80211_msg_type msg_type)
{
struct ieee80211_hdr *hdr;
u16 fc, type, stype;
@@ -1816,77 +1717,68 @@ static void handle_frame(struct hostapd_iface *iface, u8 *buf, size_t len,
int broadcast_bssid = 0;
size_t i;
u8 *bssid;
- int msg_type = ntohl(fi->msg_type);
- struct hostapd_frame_info hfi;
-#if 0 /* TODO */
- /* special handling for message types without IEEE 802.11 header */
- if (msg_type == ieee80211_msg_set_aid_for_sta) {
- ieee802_11_set_aid_for_sta(iface->bss[0], buf, data_len);
- return;
- }
-#endif
-# if 0
-/* TODO
- * get key notification from kernel again... it doesn't give one now
- * because this code doesn't care
- */
- if (msg_type == ieee80211_msg_key_threshold_notification) {
- ieee802_11_key_threshold_notification(iface->bss[0], buf,
- data_len);
- return;
- }
-#endif
-
- /* PS-Poll frame from not associated is 16 bytes. All other frames
- * passed to hostapd are 24 bytes or longer.
- * Right now, the kernel doesn't send us any frames from not-associated
- * because the code here doesn't care. TODO: add support to kernel
- * and send DEAUTH/DISASSOC to them...
+ /*
+ * PS-Poll frames are 16 bytes. All other frames are
+ * 24 bytes or longer.
*/
- if (len < 24) {
- printf("handle_frame: too short (%lu), type %d\n",
- (unsigned long) len, msg_type);
+ if (len < 16)
return;
- }
hdr = (struct ieee80211_hdr *) buf;
fc = le_to_host16(hdr->frame_control);
- bssid = hdr->addr3;
type = WLAN_FC_GET_TYPE(fc);
stype = WLAN_FC_GET_STYPE(fc);
- if (type == WLAN_FC_TYPE_DATA) {
+ switch (type) {
+ case WLAN_FC_TYPE_DATA:
+ if (len < 24)
+ return;
switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
case WLAN_FC_TODS:
bssid = hdr->addr1;
break;
- case WLAN_FC_FROMDS:
- bssid = hdr->addr2;
- break;
+ default:
+ /* discard */
+ return;
}
+ break;
+ case WLAN_FC_TYPE_CTRL:
+ /* discard non-ps-poll frames */
+ if (stype != WLAN_FC_STYPE_PSPOLL)
+ return;
+ bssid = hdr->addr1;
+ break;
+ case WLAN_FC_TYPE_MGMT:
+ bssid = hdr->addr3;
+ break;
+ default:
+ /* discard */
+ return;
}
+ /* find interface frame belongs to */
for (i = 0; i < iface->num_bss; i++) {
if (memcmp(bssid, iface->bss[i]->own_addr, ETH_ALEN) == 0) {
hapd = iface->bss[i];
break;
}
}
+
if (hapd == NULL) {
hapd = iface->bss[0];
if (bssid[0] != 0xff || bssid[1] != 0xff ||
bssid[2] != 0xff || bssid[3] != 0xff ||
bssid[4] != 0xff || bssid[5] != 0xff) {
- /* Unknown BSSID - drop frame if this is not from
- * passive scanning or a beacon
- * (at least ProbeReq frames to other APs may be
- * allowed through RX filtering in the wlan hw/driver)
+ /*
+ * Unknown BSSID - drop frame if this is not from
+ * passive scanning or a beacon (at least ProbeReq
+ * frames to other APs may be allowed through RX
+ * filtering in the wlan hw/driver)
*/
- if (msg_type != ieee80211_msg_passive_scan &&
- (type != WLAN_FC_TYPE_MGMT ||
+ if ((type != WLAN_FC_TYPE_MGMT ||
stype != WLAN_FC_STYPE_BEACON))
return;
} else
@@ -1895,7 +1787,6 @@ static void handle_frame(struct hostapd_iface *iface, u8 *buf, size_t len,
switch (msg_type) {
case ieee80211_msg_normal:
- case ieee80211_msg_passive_scan:
/* continue processing */
break;
case ieee80211_msg_tx_callback_ack:
@@ -1904,27 +1795,6 @@ static void handle_frame(struct hostapd_iface *iface, u8 *buf, size_t len,
case ieee80211_msg_tx_callback_fail:
handle_tx_callback(hapd, buf, data_len, 0);
return;
-/*
- * TODO
- * the kernel never sends this any more, add new nl80211
- * notification if you need this.
-
- case ieee80211_msg_wep_frame_unknown_key:
- ieee802_11_rx_unknown_key(hapd, buf, data_len);
- return;
- */
-/*
- * TODO
- * We should be telling them to go away. But we don't support that now.
- * See also below and above for other TODO items related to this.
-
- case ieee80211_msg_sta_not_assoc:
- ieee802_11_rx_sta_not_assoc(hapd, buf, data_len);
- return;
- */
- default:
- printf("handle_frame: unknown msg_type %d\n", msg_type);
- return;
}
switch (type) {
@@ -1932,88 +1802,176 @@ static void handle_frame(struct hostapd_iface *iface, u8 *buf, size_t len,
if (stype != WLAN_FC_STYPE_BEACON &&
stype != WLAN_FC_STYPE_PROBE_REQ)
wpa_printf(MSG_MSGDUMP, "MGMT");
- memset(&hfi, 0, sizeof(hfi));
- hfi.phytype = ntohl(fi->phytype);
- hfi.channel = ntohl(fi->channel);
- hfi.datarate = ntohl(fi->datarate);
- hfi.ssi_signal = ntohl(fi->ssi_signal);
- hfi.passive_scan = ntohl(fi->msg_type) ==
- ieee80211_msg_passive_scan;
if (broadcast_bssid) {
for (i = 0; i < iface->num_bss; i++)
ieee802_11_mgmt(iface->bss[i], buf, data_len,
- stype, &hfi);
+ stype, hfi);
} else
- ieee802_11_mgmt(hapd, buf, data_len, stype, &hfi);
+ ieee802_11_mgmt(hapd, buf, data_len, stype, hfi);
break;
case WLAN_FC_TYPE_CTRL:
- /* TODO: send deauth/disassoc if not associated STA sends
- * PS-Poll */
+ /* can only get here with PS-Poll frames */
wpa_printf(MSG_DEBUG, "CTRL");
+ handle_unknown_sta(hapd, hdr->addr2);
break;
case WLAN_FC_TYPE_DATA:
wpa_printf(MSG_DEBUG, "DATA");
- handle_data(hapd, buf, data_len, stype, fi);
- break;
- default:
- printf("unknown frame type %d\n", type);
+ handle_unknown_sta(hapd, hdr->addr2);
break;
}
}
-static void handle_read(int sock, void *eloop_ctx, void *sock_ctx)
+static void handle_eapol(int sock, void *eloop_ctx, void *sock_ctx)
+{
+ struct i802_driver_data *drv = eloop_ctx;
+ struct hostapd_data *hapd = drv->hapd;
+ struct sockaddr_ll lladdr;
+ unsigned char buf[3000];
+ int len;
+ socklen_t fromlen = sizeof(lladdr);
+
+ len = recvfrom(sock, buf, sizeof(buf), 0,
+ (struct sockaddr *)&lladdr, &fromlen);
+ if (len < 0) {
+ perror("recv");
+ return;
+ }
+
+ if (have_ifidx(drv, lladdr.sll_ifindex))
+ ieee802_1x_receive(hapd, lladdr.sll_addr, buf, len);
+}
+
+
+static void handle_monitor_read(int sock, void *eloop_ctx, void *sock_ctx)
{
- struct hostapd_iface *iface = eloop_ctx;
+ struct i802_driver_data *drv = eloop_ctx;
int len;
unsigned char buf[3000];
- struct ieee80211_frame_info *fi;
+ struct hostapd_data *hapd = drv->hapd;
+ struct ieee80211_radiotap_iterator iter;
+ int ret;
+ struct hostapd_frame_info hfi;
+ int injected = 0, failed = 0, msg_type, rxflags = 0;
len = recv(sock, buf, sizeof(buf), 0);
if (len < 0) {
perror("recv");
return;
}
- wpa_hexdump(MSG_MSGDUMP, "Received management frame", buf, len);
- if (len < (int) sizeof(struct ieee80211_frame_info)) {
- printf("handle_read: too short (%d)\n", len);
+ if (ieee80211_radiotap_iterator_init(&iter, (void*)buf, len)) {
+ printf("received invalid radiotap frame\n");
return;
}
- fi = (struct ieee80211_frame_info *) buf;
+ memset(&hfi, 0, sizeof(hfi));
- if (ntohl(fi->version) != IEEE80211_FI_VERSION) {
- printf("Invalid frame info version!\n");
- dump_frame_info(fi, len);
- return;
+ while (1) {
+ ret = ieee80211_radiotap_iterator_next(&iter);
+ if (ret == -ENOENT)
+ break;
+ if (ret) {
+ printf("received invalid radiotap frame (%d)\n", ret);
+ return;
+ }
+ switch (iter.this_arg_index) {
+ case IEEE80211_RADIOTAP_FLAGS:
+ if (*iter.this_arg & IEEE80211_RADIOTAP_F_FCS)
+ len -= 4;
+ break;
+ case IEEE80211_RADIOTAP_RX_FLAGS:
+ rxflags = 1;
+ break;
+ case IEEE80211_RADIOTAP_TX_FLAGS:
+ injected = 1;
+ failed = le_to_host16((*(uint16_t *) iter.this_arg)) &
+ IEEE80211_RADIOTAP_F_TX_FAIL;
+ break;
+ case IEEE80211_RADIOTAP_DATA_RETRIES:
+ break;
+ case IEEE80211_RADIOTAP_CHANNEL:
+ /* TODO convert from freq/flags to channel number
+ hfi.channel = XXX;
+ hfi.phytype = XXX;
+ */
+ break;
+ case IEEE80211_RADIOTAP_RATE:
+ hfi.datarate = *iter.this_arg * 5;
+ break;
+ case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
+ hfi.ssi_signal = *iter.this_arg;
+ break;
+ }
}
- handle_frame(iface,
- buf + sizeof(struct ieee80211_frame_info),
- len - sizeof(struct ieee80211_frame_info),
- fi);
+ if (rxflags && injected)
+ return;
+
+ if (!injected)
+ msg_type = ieee80211_msg_normal;
+ else if (failed)
+ msg_type = ieee80211_msg_tx_callback_fail;
+ else
+ msg_type = ieee80211_msg_tx_callback_ack;
+
+ handle_frame(hapd->iface, buf + iter.max_length,
+ len - iter.max_length, &hfi, msg_type);
}
-static void handle_eapol(int sock, void *eloop_ctx, void *sock_ctx)
+static int nl80211_create_monitor_interface(struct i802_driver_data *drv)
{
- struct i802_driver_data *drv = eloop_ctx;
- struct hostapd_data *hapd = drv->hapd;
- struct sockaddr_ll lladdr;
- unsigned char buf[3000];
- int len;
- socklen_t fromlen = sizeof(lladdr);
+ char buf[IFNAMSIZ];
+ struct sockaddr_ll ll;
+ int optval;
+ socklen_t optlen;
- len = recvfrom(sock, buf, sizeof(buf), 0,
- (struct sockaddr *) &lladdr, &fromlen);
- if (len < 0) {
- perror("recv");
- return;
+ snprintf(buf, IFNAMSIZ, "mon.%s", drv->iface);
+ buf[IFNAMSIZ - 1] = '\0';
+
+ drv->monitor_ifidx =
+ nl80211_create_iface(drv, buf, NL80211_IFTYPE_MONITOR, NULL);
+
+ if (drv->monitor_ifidx < 0)
+ return -1;
+
+ if (hostapd_set_iface_flags(drv, buf, 1))
+ goto error;
+
+ memset(&ll, 0, sizeof(ll));
+ ll.sll_family = AF_PACKET;
+ ll.sll_ifindex = drv->monitor_ifidx;
+ drv->monitor_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+ if (drv->monitor_sock < 0) {
+ perror("socket[PF_PACKET,SOCK_RAW]");
+ goto error;
}
- if (have_ifidx(drv, lladdr.sll_ifindex))
- ieee802_1x_receive(hapd, lladdr.sll_addr, buf, len);
+ if (bind(drv->monitor_sock, (struct sockaddr *) &ll,
+ sizeof(ll)) < 0) {
+ perror("monitor socket bind");
+ goto error;
+ }
+
+ optlen = sizeof(optval);
+ optval = 20;
+ if (setsockopt
+ (drv->monitor_sock, SOL_SOCKET, SO_PRIORITY, &optval, optlen)) {
+ perror("Failed to set socket priority");
+ goto error;
+ }
+
+ if (eloop_register_read_sock(drv->monitor_sock, handle_monitor_read,
+ drv, NULL)) {
+ printf("Could not register monitor read socket\n");
+ goto error;
+ }
+
+ return 0;
+ error:
+ nl80211_remove_iface(drv, drv->monitor_ifidx);
+ return -1;
}
@@ -2049,12 +2007,10 @@ static int nl80211_set_master_mode(struct i802_driver_data *drv,
static int i802_init_sockets(struct i802_driver_data *drv, const u8 *bssid)
{
- struct hostapd_data *hapd = drv->hapd;
- struct hostapd_iface *iface = hapd->iface;
struct ifreq ifr;
struct sockaddr_ll addr;
- drv->sock = drv->ioctl_sock = -1;
+ drv->ioctl_sock = -1;
drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
if (drv->ioctl_sock < 0) {
@@ -2105,26 +2061,9 @@ static int i802_init_sockets(struct i802_driver_data *drv, const u8 *bssid)
return -1;
}
- /* Enable management interface */
- if (hostap_ioctl_prism2param(drv, PRISM2_PARAM_MGMT_IF, 1) < 0) {
- printf("Failed to enable management interface.\n");
- return -1;
- }
- drv->mgmt_ifindex =
- hostap_ioctl_get_prism2param(drv, PRISM2_PARAM_MGMT_IF);
- if (drv->mgmt_ifindex < 0) {
- printf("Failed to get ifindex for the management "
- "interface.\n");
+ /* Initialise a monitor interface */
+ if (nl80211_create_monitor_interface(drv))
return -1;
- }
-
- memset(&ifr, 0, sizeof(ifr));
- ifr.ifr_ifindex = drv->mgmt_ifindex;
- if (ioctl(drv->ioctl_sock, SIOCGIFNAME, &ifr) != 0) {
- perror("ioctl(SIOCGIFNAME)");
- return -1;
- }
- os_strlcpy(drv->mgmt_iface, ifr.ifr_name, sizeof(drv->mgmt_iface));
if (nl80211_set_master_mode(drv, drv->iface))
return -1;
@@ -2138,22 +2077,6 @@ static int i802_init_sockets(struct i802_driver_data *drv, const u8 *bssid)
wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d",
addr.sll_ifindex);
- drv->sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
- if (drv->sock < 0) {
- perror("socket[PF_PACKET,SOCK_RAW]");
- return -1;
- }
-
- if (bind(drv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- perror(__FILE__ ":bind");
- return -1;
- }
-
- if (eloop_register_read_sock(drv->sock, handle_read, iface, NULL)) {
- printf("Could not register read socket\n");
- return -1;
- }
-
drv->eapol_sock = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_PAE));
if (drv->eapol_sock < 0) {
perror("socket(PF_PACKET, SOCK_DGRAM, ETH_P_PAE)");
@@ -2168,7 +2091,7 @@ static int i802_init_sockets(struct i802_driver_data *drv, const u8 *bssid)
memset(&ifr, 0, sizeof(ifr));
os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name));
- if (ioctl(drv->sock, SIOCGIFHWADDR, &ifr) != 0) {
+ if (ioctl(drv->ioctl_sock, SIOCGIFHWADDR, &ifr) != 0) {
perror("ioctl(SIOCGIFHWADDR)");
return -1;
}
@@ -2530,14 +2453,14 @@ static void i802_deinit(void *priv)
i802_del_beacon(drv);
- /* Disable management interface */
- (void) hostap_ioctl_prism2param(drv, PRISM2_PARAM_MGMT_IF, 0);
+ /* remove monitor interface */
+ nl80211_remove_iface(drv, drv->monitor_ifidx);
(void) hostapd_set_iface_flags(drv, drv->iface, 0);
- if (drv->sock >= 0) {
- eloop_unregister_read_sock(drv->sock);
- close(drv->sock);
+ if (drv->monitor_sock >= 0) {
+ eloop_unregister_read_sock(drv->monitor_sock);
+ close(drv->monitor_sock);
}
if (drv->ioctl_sock >= 0)
close(drv->ioctl_sock);