mirror of
https://github.com/vanhoefm/fragattacks.git
synced 2024-11-29 02:38:22 -05:00
nl80211: Use socket error queue for EAPOL TX status
This will allow getting TX status for EAPOL frames sent as data frames if the driver supports it. Signed-hostap: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
204dd3f420
commit
32ab485503
@ -28,6 +28,7 @@
|
|||||||
#include <linux/rtnetlink.h>
|
#include <linux/rtnetlink.h>
|
||||||
#include <netpacket/packet.h>
|
#include <netpacket/packet.h>
|
||||||
#include <linux/filter.h>
|
#include <linux/filter.h>
|
||||||
|
#include <linux/errqueue.h>
|
||||||
#include "nl80211_copy.h"
|
#include "nl80211_copy.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
@ -43,6 +44,26 @@
|
|||||||
#include "rfkill.h"
|
#include "rfkill.h"
|
||||||
#include "driver.h"
|
#include "driver.h"
|
||||||
|
|
||||||
|
#ifndef SO_WIFI_STATUS
|
||||||
|
# if defined(__sparc__)
|
||||||
|
# define SO_WIFI_STATUS 0x0025
|
||||||
|
# elif defined(__parisc__)
|
||||||
|
# define SO_WIFI_STATUS 0x4022
|
||||||
|
# else
|
||||||
|
# define SO_WIFI_STATUS 41
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# define SCM_WIFI_STATUS SO_WIFI_STATUS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SO_EE_ORIGIN_TXSTATUS
|
||||||
|
#define SO_EE_ORIGIN_TXSTATUS 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PACKET_TX_TIMESTAMP
|
||||||
|
#define PACKET_TX_TIMESTAMP 16
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
#include "android_drv.h"
|
#include "android_drv.h"
|
||||||
#endif /* ANDROID */
|
#endif /* ANDROID */
|
||||||
@ -211,6 +232,7 @@ struct wpa_driver_nl80211_data {
|
|||||||
unsigned int in_interface_list:1;
|
unsigned int in_interface_list:1;
|
||||||
unsigned int device_ap_sme:1;
|
unsigned int device_ap_sme:1;
|
||||||
unsigned int poll_command_supported:1;
|
unsigned int poll_command_supported:1;
|
||||||
|
unsigned int data_tx_status:1;
|
||||||
|
|
||||||
u64 remain_on_chan_cookie;
|
u64 remain_on_chan_cookie;
|
||||||
u64 send_action_cookie;
|
u64 send_action_cookie;
|
||||||
@ -223,9 +245,7 @@ struct wpa_driver_nl80211_data {
|
|||||||
|
|
||||||
struct i802_bss first_bss;
|
struct i802_bss first_bss;
|
||||||
|
|
||||||
#ifdef CONFIG_AP
|
|
||||||
int eapol_tx_sock;
|
int eapol_tx_sock;
|
||||||
#endif /* CONFIG_AP */
|
|
||||||
|
|
||||||
#ifdef HOSTAPD
|
#ifdef HOSTAPD
|
||||||
int eapol_sock; /* socket for EAPOL frames */
|
int eapol_sock; /* socket for EAPOL frames */
|
||||||
@ -1898,6 +1918,7 @@ struct wiphy_info_data {
|
|||||||
unsigned int error:1;
|
unsigned int error:1;
|
||||||
unsigned int device_ap_sme:1;
|
unsigned int device_ap_sme:1;
|
||||||
unsigned int poll_command_supported:1;
|
unsigned int poll_command_supported:1;
|
||||||
|
unsigned int data_tx_status:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -2085,6 +2106,13 @@ broken_combination:
|
|||||||
if (tb[NL80211_ATTR_DEVICE_AP_SME])
|
if (tb[NL80211_ATTR_DEVICE_AP_SME])
|
||||||
info->device_ap_sme = 1;
|
info->device_ap_sme = 1;
|
||||||
|
|
||||||
|
if (tb[NL80211_ATTR_FEATURE_FLAGS]) {
|
||||||
|
u32 flags = nla_get_u32(tb[NL80211_ATTR_FEATURE_FLAGS]);
|
||||||
|
|
||||||
|
if (flags & NL80211_FEATURE_SK_TX_STATUS)
|
||||||
|
info->data_tx_status = 1;
|
||||||
|
}
|
||||||
|
|
||||||
return NL_SKIP;
|
return NL_SKIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2144,6 +2172,7 @@ static int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv)
|
|||||||
|
|
||||||
drv->device_ap_sme = info.device_ap_sme;
|
drv->device_ap_sme = info.device_ap_sme;
|
||||||
drv->poll_command_supported = info.poll_command_supported;
|
drv->poll_command_supported = info.poll_command_supported;
|
||||||
|
drv->data_tx_status = info.data_tx_status;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2282,6 +2311,68 @@ static void nl80211_get_phy_name(struct wpa_driver_nl80211_data *drv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wpa_driver_nl80211_handle_eapol_tx_status(int sock,
|
||||||
|
void *eloop_ctx,
|
||||||
|
void *handle)
|
||||||
|
{
|
||||||
|
struct wpa_driver_nl80211_data *drv = eloop_ctx;
|
||||||
|
u8 data[2048];
|
||||||
|
struct msghdr msg;
|
||||||
|
struct iovec entry;
|
||||||
|
struct {
|
||||||
|
struct cmsghdr cm;
|
||||||
|
char control[512];
|
||||||
|
} control;
|
||||||
|
struct cmsghdr *cmsg;
|
||||||
|
int res, found_ee = 0, found_wifi = 0, acked = 0;
|
||||||
|
union wpa_event_data event;
|
||||||
|
|
||||||
|
memset(&msg, 0, sizeof(msg));
|
||||||
|
msg.msg_iov = &entry;
|
||||||
|
msg.msg_iovlen = 1;
|
||||||
|
entry.iov_base = data;
|
||||||
|
entry.iov_len = sizeof(data);
|
||||||
|
msg.msg_control = &control;
|
||||||
|
msg.msg_controllen = sizeof(control);
|
||||||
|
|
||||||
|
res = recvmsg(sock, &msg, MSG_ERRQUEUE);
|
||||||
|
/* if error or not fitting 802.3 header, return */
|
||||||
|
if (res < 14)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
|
||||||
|
{
|
||||||
|
if (cmsg->cmsg_level == SOL_SOCKET &&
|
||||||
|
cmsg->cmsg_type == SCM_WIFI_STATUS) {
|
||||||
|
int *ack;
|
||||||
|
|
||||||
|
found_wifi = 1;
|
||||||
|
ack = (void *)CMSG_DATA(cmsg);
|
||||||
|
acked = *ack;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmsg->cmsg_level == SOL_PACKET &&
|
||||||
|
cmsg->cmsg_type == PACKET_TX_TIMESTAMP) {
|
||||||
|
struct sock_extended_err *err =
|
||||||
|
(struct sock_extended_err *)CMSG_DATA(cmsg);
|
||||||
|
|
||||||
|
if (err->ee_origin == SO_EE_ORIGIN_TXSTATUS)
|
||||||
|
found_ee = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found_ee || !found_wifi)
|
||||||
|
return;
|
||||||
|
|
||||||
|
memset(&event, 0, sizeof(event));
|
||||||
|
event.eapol_tx_status.dst = data;
|
||||||
|
event.eapol_tx_status.data = data + 14;
|
||||||
|
event.eapol_tx_status.data_len = res - 14;
|
||||||
|
event.eapol_tx_status.ack = acked;
|
||||||
|
wpa_supplicant_event(drv->ctx, EVENT_EAPOL_TX_STATUS, &event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wpa_driver_nl80211_init - Initialize nl80211 driver interface
|
* wpa_driver_nl80211_init - Initialize nl80211 driver interface
|
||||||
* @ctx: context to be used when calling wpa_supplicant functions,
|
* @ctx: context to be used when calling wpa_supplicant functions,
|
||||||
@ -2309,9 +2400,7 @@ static void * wpa_driver_nl80211_init(void *ctx, const char *ifname,
|
|||||||
os_strlcpy(bss->ifname, ifname, sizeof(bss->ifname));
|
os_strlcpy(bss->ifname, ifname, sizeof(bss->ifname));
|
||||||
drv->monitor_ifidx = -1;
|
drv->monitor_ifidx = -1;
|
||||||
drv->monitor_sock = -1;
|
drv->monitor_sock = -1;
|
||||||
#ifdef CONFIG_AP
|
|
||||||
drv->eapol_tx_sock = -1;
|
drv->eapol_tx_sock = -1;
|
||||||
#endif /* CONFIG_AP */
|
|
||||||
drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
|
drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
|
||||||
|
|
||||||
if (wpa_driver_nl80211_init_nl(drv)) {
|
if (wpa_driver_nl80211_init_nl(drv)) {
|
||||||
@ -2337,9 +2426,24 @@ static void * wpa_driver_nl80211_init(void *ctx, const char *ifname,
|
|||||||
if (wpa_driver_nl80211_finish_drv_init(drv))
|
if (wpa_driver_nl80211_finish_drv_init(drv))
|
||||||
goto failed;
|
goto failed;
|
||||||
|
|
||||||
#ifdef CONFIG_AP
|
|
||||||
drv->eapol_tx_sock = socket(PF_PACKET, SOCK_DGRAM, 0);
|
drv->eapol_tx_sock = socket(PF_PACKET, SOCK_DGRAM, 0);
|
||||||
#endif /* CONFIG_AP */
|
if (drv->eapol_tx_sock < 0)
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
if (drv->data_tx_status) {
|
||||||
|
int enabled = 1;
|
||||||
|
|
||||||
|
if (setsockopt(drv->eapol_tx_sock, SOL_SOCKET, SO_WIFI_STATUS,
|
||||||
|
&enabled, sizeof(enabled)) < 0) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"nl80211: wifi status sockopt failed\n");
|
||||||
|
drv->data_tx_status = 0;
|
||||||
|
} else {
|
||||||
|
eloop_register_read_sock(drv->eapol_tx_sock,
|
||||||
|
wpa_driver_nl80211_handle_eapol_tx_status,
|
||||||
|
drv, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (drv->global) {
|
if (drv->global) {
|
||||||
dl_list_add(&drv->global->interfaces, &drv->list);
|
dl_list_add(&drv->global->interfaces, &drv->list);
|
||||||
@ -2555,10 +2659,10 @@ static void wpa_driver_nl80211_deinit(void *priv)
|
|||||||
struct i802_bss *bss = priv;
|
struct i802_bss *bss = priv;
|
||||||
struct wpa_driver_nl80211_data *drv = bss->drv;
|
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||||
|
|
||||||
#ifdef CONFIG_AP
|
if (drv->data_tx_status)
|
||||||
|
eloop_unregister_read_sock(drv->eapol_tx_sock);
|
||||||
if (drv->eapol_tx_sock >= 0)
|
if (drv->eapol_tx_sock >= 0)
|
||||||
close(drv->eapol_tx_sock);
|
close(drv->eapol_tx_sock);
|
||||||
#endif /* CONFIG_AP */
|
|
||||||
|
|
||||||
if (bss->nl_preq.handle)
|
if (bss->nl_preq.handle)
|
||||||
wpa_driver_nl80211_probe_req_report(bss, 0);
|
wpa_driver_nl80211_probe_req_report(bss, 0);
|
||||||
@ -5151,7 +5255,6 @@ nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_AP
|
|
||||||
static int nl80211_send_eapol_data(struct i802_bss *bss,
|
static int nl80211_send_eapol_data(struct i802_bss *bss,
|
||||||
const u8 *addr, const u8 *data,
|
const u8 *addr, const u8 *data,
|
||||||
size_t data_len)
|
size_t data_len)
|
||||||
@ -5178,7 +5281,6 @@ static int nl80211_send_eapol_data(struct i802_bss *bss,
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_AP */
|
|
||||||
|
|
||||||
|
|
||||||
static const u8 rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
|
static const u8 rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
|
||||||
@ -5195,10 +5297,8 @@ static int wpa_driver_nl80211_hapd_send_eapol(
|
|||||||
int res;
|
int res;
|
||||||
int qos = flags & WPA_STA_WMM;
|
int qos = flags & WPA_STA_WMM;
|
||||||
|
|
||||||
#ifdef CONFIG_AP
|
if (drv->device_ap_sme || drv->data_tx_status)
|
||||||
if (drv->device_ap_sme)
|
|
||||||
return nl80211_send_eapol_data(bss, addr, data, data_len);
|
return nl80211_send_eapol_data(bss, addr, data, data_len);
|
||||||
#endif /* CONFIG_AP */
|
|
||||||
|
|
||||||
len = sizeof(*hdr) + (qos ? 2 : 0) + sizeof(rfc1042_header) + 2 +
|
len = sizeof(*hdr) + (qos ? 2 : 0) + sizeof(rfc1042_header) + 2 +
|
||||||
data_len;
|
data_len;
|
||||||
|
Loading…
Reference in New Issue
Block a user