From f10bfc9adb38d51f4bf6084eb3213c00eaadf5e6 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 9 Aug 2011 14:04:53 +0300 Subject: [PATCH] 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. --- src/drivers/driver_nl80211.c | 44 ++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 37869b015..972a15e70 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -34,6 +34,7 @@ #include "eloop.h" #include "utils/list.h" #include "common/ieee802_11_defs.h" +#include "l2_packet/l2_packet.h" #include "netlink.h" #include "linux_ioctl.h" #include "radiotap.h" @@ -174,6 +175,10 @@ struct wpa_driver_nl80211_data { struct i802_bss first_bss; +#ifdef CONFIG_AP + struct l2_packet_data *l2; +#endif /* CONFIG_AP */ + #ifdef HOSTAPD 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 * @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)) 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) 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 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) wpa_driver_nl80211_probe_req_report(bss, 0); 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 int wpa_driver_nl80211_hapd_send_eapol( @@ -4494,6 +4534,10 @@ static int wpa_driver_nl80211_hapd_send_eapol( int res; 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 + data_len; hdr = os_zalloc(len);