nl80211: Add l2_packet for AP mode EAPOL TX without monitor iface

This can be used with drivers that do not support monitor interface
when transmitting EAPOL frames in AP mode.
This commit is contained in:
Jouni Malinen 2011-08-09 14:04:53 +03:00 committed by Jouni Malinen
parent 9db931ed6d
commit f10bfc9adb

View file

@ -34,6 +34,7 @@
#include "eloop.h" #include "eloop.h"
#include "utils/list.h" #include "utils/list.h"
#include "common/ieee802_11_defs.h" #include "common/ieee802_11_defs.h"
#include "l2_packet/l2_packet.h"
#include "netlink.h" #include "netlink.h"
#include "linux_ioctl.h" #include "linux_ioctl.h"
#include "radiotap.h" #include "radiotap.h"
@ -174,6 +175,10 @@ struct wpa_driver_nl80211_data {
struct i802_bss first_bss; struct i802_bss first_bss;
#ifdef CONFIG_AP
struct l2_packet_data *l2;
#endif /* CONFIG_AP */
#ifdef HOSTAPD #ifdef HOSTAPD
int eapol_sock; /* socket for EAPOL frames */ int eapol_sock; /* socket for EAPOL frames */
@ -1954,6 +1959,16 @@ static void nl80211_get_phy_name(struct wpa_driver_nl80211_data *drv)
} }
#ifdef CONFIG_AP
static void nl80211_l2_read(void *ctx, const u8 *src_addr, const u8 *buf,
size_t len)
{
wpa_printf(MSG_DEBUG, "nl80211: l2_packet read %u",
(unsigned int) len);
}
#endif /* CONFIG_AP */
/** /**
* 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,
@ -2024,6 +2039,11 @@ 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->l2 = l2_packet_init(ifname, NULL, ETH_P_EAPOL,
nl80211_l2_read, drv, 0);
#endif /* CONFIG_AP */
if (drv->global) if (drv->global)
dl_list_add(&drv->global->interfaces, &drv->list); dl_list_add(&drv->global->interfaces, &drv->list);
@ -2234,6 +2254,11 @@ 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->l2)
l2_packet_deinit(drv->l2);
#endif /* CONFIG_AP */
if (drv->nl_handle_preq) if (drv->nl_handle_preq)
wpa_driver_nl80211_probe_req_report(bss, 0); wpa_driver_nl80211_probe_req_report(bss, 0);
if (bss->added_if_into_bridge) { if (bss->added_if_into_bridge) {
@ -4480,6 +4505,21 @@ nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv)
} }
static int nl80211_send_eapol_data(struct i802_bss *bss,
const u8 *addr, const u8 *data,
size_t data_len, const u8 *own_addr)
{
if (bss->drv->l2 == NULL) {
wpa_printf(MSG_DEBUG, "nl80211: No l2_packet to send EAPOL");
return -1;
}
if (l2_packet_send(bss->drv->l2, addr, ETH_P_EAPOL, data, data_len) <
0)
return -1;
return 0;
}
static const u8 rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; static const u8 rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
static int wpa_driver_nl80211_hapd_send_eapol( static int wpa_driver_nl80211_hapd_send_eapol(
@ -4494,6 +4534,10 @@ static int wpa_driver_nl80211_hapd_send_eapol(
int res; int res;
int qos = flags & WPA_STA_WMM; int qos = flags & WPA_STA_WMM;
if (drv->no_monitor_iface_capab)
return nl80211_send_eapol_data(bss, addr, data, data_len,
own_addr);
len = sizeof(*hdr) + (qos ? 2 : 0) + sizeof(rfc1042_header) + 2 + len = sizeof(*hdr) + (qos ? 2 : 0) + sizeof(rfc1042_header) + 2 +
data_len; data_len;
hdr = os_zalloc(len); hdr = os_zalloc(len);