diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index 09d4b1dbe..b03a54154 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -31,27 +31,6 @@ #include "ap_config.h" -static int hostapd_notif_new_sta(struct hostapd_data *hapd, const u8 *addr) -{ - struct sta_info *sta = ap_get_sta(hapd, addr); - if (sta) - return 0; - - wpa_printf(MSG_DEBUG, "Data frame from unknown STA " MACSTR - " - adding a new STA", MAC2STR(addr)); - sta = ap_sta_add(hapd, addr); - if (sta) { - hostapd_new_assoc_sta(hapd, sta, 0); - } else { - wpa_printf(MSG_DEBUG, "Failed to add STA entry for " MACSTR, - MAC2STR(addr)); - return -1; - } - - return 0; -} - - int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, const u8 *ie, size_t ielen) { @@ -166,29 +145,6 @@ void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr) } -void hostapd_eapol_receive(struct hostapd_data *hapd, const u8 *sa, - const u8 *buf, size_t len) -{ - ieee802_1x_receive(hapd, sa, buf, len); -} - - -struct hostapd_data * hostapd_sta_get_bss(struct hostapd_data *hapd, - const u8 *addr) -{ - struct hostapd_iface *iface = hapd->iface; - size_t j; - - for (j = 0; j < iface->num_bss; j++) { - hapd = iface->bss[j]; - if (ap_get_sta(hapd, addr)) - return hapd; - } - - return NULL; -} - - #ifdef HOSTAPD #ifdef NEED_AP_MLME @@ -343,6 +299,44 @@ static int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, } +static int hostapd_event_new_sta(struct hostapd_data *hapd, const u8 *addr) +{ + struct sta_info *sta = ap_get_sta(hapd, addr); + if (sta) + return 0; + + wpa_printf(MSG_DEBUG, "Data frame from unknown STA " MACSTR + " - adding a new STA", MAC2STR(addr)); + sta = ap_sta_add(hapd, addr); + if (sta) { + hostapd_new_assoc_sta(hapd, sta, 0); + } else { + wpa_printf(MSG_DEBUG, "Failed to add STA entry for " MACSTR, + MAC2STR(addr)); + return -1; + } + + return 0; +} + + +static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src, + const u8 *data, size_t data_len) +{ + struct hostapd_iface *iface = hapd->iface; + size_t j; + + for (j = 0; j < iface->num_bss; j++) { + if (ap_get_sta(iface->bss[j], src)) { + hapd = iface->bss[j]; + break; + } + } + + ieee802_1x_receive(hapd, src, data, data_len); +} + + void wpa_supplicant_event(void *ctx, enum wpa_event_type event, union wpa_event_data *data) { @@ -396,7 +390,13 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, data->rx_probe_req.ie_len); break; case EVENT_NEW_STA: - hostapd_notif_new_sta(hapd, data->new_sta.addr); + hostapd_event_new_sta(hapd, data->new_sta.addr); + break; + case EVENT_EAPOL_RX: + hostapd_event_eapol_rx(hapd, data->eapol_rx.src, + data->eapol_rx.data, + data->eapol_rx.data_len); + break; default: wpa_printf(MSG_DEBUG, "Unknown event %d", event); break; diff --git a/src/drivers/driver.h b/src/drivers/driver.h index d467eb208..77263b578 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -795,9 +795,9 @@ struct wpa_driver_ops { * with driver specific functionality. If this function pointer is set, * l2_packet module is not used at all and the driver interface code is * responsible for receiving and sending all EAPOL packets. The - * received EAPOL packets are sent to core code by calling - * wpa_supplicant_rx_eapol(). The driver interface is required to - * implement get_mac_addr() handler if send_eapol() is used. + * received EAPOL packets are sent to core code with EVENT_EAPOL_RX + * event. The driver interface is required to implement get_mac_addr() + * handler if send_eapol() is used. */ int (*send_eapol)(void *priv, const u8 *dest, u16 proto, const u8 *data, size_t data_len); @@ -1882,7 +1882,17 @@ enum wpa_event_type { * authenticator when receiving a frame from a device. The address of * the device is included in union wpa_event_data::new_sta. */ - EVENT_NEW_STA + EVENT_NEW_STA, + + /** + * EVENT_EAPOL_RX - Report received EAPOL frame + * + * When in AP mode with hostapd, this event is required to be used to + * deliver the receive EAPOL frames from the driver. With + * %wpa_supplicant, this event is used only if the send_eapol() handler + * is used to override the use of l2_packet for EAPOL frame TX. + */ + EVENT_EAPOL_RX }; @@ -2210,6 +2220,15 @@ union wpa_event_data { struct new_sta { const u8 *addr; } new_sta; + + /** + * struct eapol_rx - Data for EVENT_EAPOL_RX events + */ + struct eapol_rx { + const u8 *src; + const u8 *data; + size_t data_len; + } eapol_rx; }; /** @@ -2225,23 +2244,6 @@ union wpa_event_data { void wpa_supplicant_event(void *ctx, enum wpa_event_type event, union wpa_event_data *data); -/** - * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant - * @ctx: Context pointer (wpa_s); this is the ctx variable registered - * with struct wpa_driver_ops::init() - * @src_addr: Source address of the EAPOL frame - * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header) - * @len: Length of the EAPOL data - * - * This function is called for each received EAPOL frame. Most driver - * interfaces rely on more generic OS mechanism for receiving frames through - * l2_packet, but if such a mechanism is not available, the driver wrapper may - * take care of received EAPOL frames and deliver them to the core supplicant - * code by calling this function. - */ -void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len); - const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie); const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res, u32 vendor_type); @@ -2256,10 +2258,5 @@ void wpa_scan_sort_results(struct wpa_scan_results *res); int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, const u8 *ie, size_t ielen); void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr); -void hostapd_eapol_receive(struct hostapd_data *hapd, const u8 *sa, - const u8 *buf, size_t len); - -struct hostapd_data * hostapd_sta_get_bss(struct hostapd_data *hapd, - const u8 *addr); #endif /* DRIVER_H */ diff --git a/src/drivers/driver_atheros.c b/src/drivers/driver_atheros.c index 58834b4c7..e3a7e7d2f 100644 --- a/src/drivers/driver_atheros.c +++ b/src/drivers/driver_atheros.c @@ -1073,9 +1073,12 @@ static void handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len) { struct madwifi_driver_data *drv = ctx; - hostapd_eapol_receive(drv->hapd, src_addr, - buf + sizeof(struct l2_ethhdr), - len - sizeof(struct l2_ethhdr)); + union wpa_event_data event; + os_memset(&event, 0, sizeof(event)); + event.eapol_rx.src = src_addr; + event.eapol_rx.data = buf + sizeof(struct l2_ethhdr); + event.eapol_rx.data_len = len - sizeof(struct l2_ethhdr); + wpa_supplicant_event(drv->hapd, EVENT_EAPOL_RX, &event); } static void * diff --git a/src/drivers/driver_bsd.c b/src/drivers/driver_bsd.c index 2b8361899..5b232fd69 100644 --- a/src/drivers/driver_bsd.c +++ b/src/drivers/driver_bsd.c @@ -736,9 +736,12 @@ static void handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len) { struct bsd_driver_data *drv = ctx; - hostapd_eapol_receive(drv->hapd, src_addr, - buf + sizeof(struct l2_ethhdr), - len - sizeof(struct l2_ethhdr)); + union wpa_event_data event; + os_memset(&event, 0, sizeof(event)); + event.eapol_rx.src = src_addr; + event.eapol_rx.data = buf + sizeof(struct l2_ethhdr); + event.eapol_rx.data_len = len - sizeof(struct l2_ethhdr); + wpa_supplicant_event(drv->hapd, EVENT_EAPOL_RX, &event); } static int diff --git a/src/drivers/driver_hostap.c b/src/drivers/driver_hostap.c index c0f36b894..1aa52e838 100644 --- a/src/drivers/driver_hostap.c +++ b/src/drivers/driver_hostap.c @@ -112,7 +112,11 @@ static void handle_data(struct hostap_driver_data *drv, u8 *buf, size_t len, left -= 2; switch (ethertype) { case ETH_P_PAE: - hostapd_eapol_receive(drv->hapd, sa, pos, left); + os_memset(&event, 0, sizeof(event)); + event.eapol_rx.src = sa; + event.eapol_rx.data = pos; + event.eapol_rx.data_len = left; + wpa_supplicant_event(drv->hapd, EVENT_EAPOL_RX, &event); break; default: diff --git a/src/drivers/driver_madwifi.c b/src/drivers/driver_madwifi.c index 02852fe11..5c25ee3a9 100644 --- a/src/drivers/driver_madwifi.c +++ b/src/drivers/driver_madwifi.c @@ -1143,9 +1143,12 @@ static void handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len) { struct madwifi_driver_data *drv = ctx; - hostapd_eapol_receive(drv->hapd, src_addr, - buf + sizeof(struct l2_ethhdr), - len - sizeof(struct l2_ethhdr)); + union wpa_event_data event; + os_memset(&event, 0, sizeof(event)); + event.eapol_rx.src = src_addr; + event.eapol_rx.data = buf + sizeof(struct l2_ethhdr); + event.eapol_rx.data_len = len - sizeof(struct l2_ethhdr); + wpa_supplicant_event(drv->hapd, EVENT_EAPOL_RX, &event); } static void * diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 24e5b5c1c..5a36cf8ec 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -4234,11 +4234,12 @@ static void handle_eapol(int sock, void *eloop_ctx, void *sock_ctx) } if (have_ifidx(drv, lladdr.sll_ifindex)) { - void *ctx; - ctx = hostapd_sta_get_bss(drv->ctx, lladdr.sll_addr); - if (!ctx) - return; - hostapd_eapol_receive(ctx, lladdr.sll_addr, buf, len); + union wpa_event_data event; + os_memset(&event, 0, sizeof(event)); + event.eapol_rx.src = lladdr.sll_addr; + event.eapol_rx.data = buf; + event.eapol_rx.data_len = len; + wpa_supplicant_event(drv->ctx, EVENT_EAPOL_RX, &event); } } diff --git a/src/drivers/driver_privsep.c b/src/drivers/driver_privsep.c index d9911e98f..223695a53 100644 --- a/src/drivers/driver_privsep.c +++ b/src/drivers/driver_privsep.c @@ -321,7 +321,8 @@ static int wpa_driver_privsep_disassociate(void *priv, const u8 *addr, } -static void wpa_driver_privsep_event_assoc(void *ctx, wpa_event_type event, +static void wpa_driver_privsep_event_assoc(void *ctx, + enum wpa_event_type event, u8 *buf, size_t len) { union wpa_event_data data; @@ -431,10 +432,16 @@ static void wpa_driver_privsep_event_ft_response(void *ctx, u8 *buf, static void wpa_driver_privsep_event_rx_eapol(void *ctx, u8 *buf, size_t len) { + union wpa_event_data event; + if (len < ETH_ALEN) return; - wpa_supplicant_rx_eapol(ctx, buf, buf + ETH_ALEN, len - ETH_ALEN); + os_memset(&event, 0, sizeof(event)); + event.eapol_rx.src = buf; + event.eapol_rx.data = buf + ETH_ALEN; + event.eapol_rx.data_len = len - ETH_ALEN; + wpa_supplicant_event(ctx, EVENT_EAPOL_RX, &event); } diff --git a/src/drivers/driver_roboswitch.c b/src/drivers/driver_roboswitch.c index aab6bc00d..fe63bc193 100644 --- a/src/drivers/driver_roboswitch.c +++ b/src/drivers/driver_roboswitch.c @@ -180,8 +180,12 @@ static void wpa_driver_roboswitch_receive(void *priv, const u8 *src_addr, if (len > 14 && WPA_GET_BE16(buf + 12) == ETH_P_EAPOL && os_memcmp(buf, drv->own_addr, ETH_ALEN) == 0) { - wpa_supplicant_rx_eapol(drv->ctx, src_addr, buf + 14, - len - 14); + union wpa_event_data event; + os_memset(&event, 0, sizeof(event)); + event.eapol_rx.src = src_addr; + event.eapol_rx.data = buf + 14; + event.eapol_rx.data_len = len - 14; + wpa_supplicant_event(drv->ctx, EVENT_EAPOL_RX, &event); } } diff --git a/src/drivers/driver_test.c b/src/drivers/driver_test.c index 205744e30..c61535ea7 100644 --- a/src/drivers/driver_test.c +++ b/src/drivers/driver_test.c @@ -652,6 +652,8 @@ static void test_driver_eapol(struct wpa_driver_test_data *drv, struct test_client_socket *cli; #endif /* HOSTAPD */ const u8 *src = NULL; + union wpa_event_data event; + void *ctx; if (datalen > 14) { /* Skip Ethernet header */ @@ -663,19 +665,30 @@ static void test_driver_eapol(struct wpa_driver_test_data *drv, data += 14; datalen -= 14; } + + os_memset(&event, 0, sizeof(event)); + event.eapol_rx.data = data; + event.eapol_rx.data_len = datalen; + #ifdef HOSTAPD cli = test_driver_get_cli(drv, from, fromlen); if (cli) { - hostapd_eapol_receive(cli->bss->bss_ctx, cli->addr, data, - datalen); + event.eapol_rx.src = cli->addr; + ctx = cli->bss->bss_ctx; } else { wpa_printf(MSG_DEBUG, "test_socket: EAPOL from unknown " "client"); + return; } #else /* HOSTAPD */ - if (src) - wpa_supplicant_rx_eapol(drv->ctx, src, data, datalen); + if (src) { + event.eapol_rx.src = src; + ctx = drv->ctx; + } else + return; #endif /* HOSTAPD */ + + wpa_supplicant_event(ctx, EVENT_EAPOL_RX, &event); } @@ -1803,6 +1816,7 @@ static void wpa_driver_test_eapol(struct wpa_driver_test_data *drv, const u8 *data, size_t data_len) { const u8 *src = drv->bssid; + union wpa_event_data event; if (data_len > 14) { /* Skip Ethernet header */ @@ -1810,9 +1824,12 @@ static void wpa_driver_test_eapol(struct wpa_driver_test_data *drv, data += 14; data_len -= 14; } -#ifndef HOSTAPD - wpa_supplicant_rx_eapol(drv->ctx, src, data, data_len); -#endif /* HOSTAPD */ + + os_memset(&event, 0, sizeof(event)); + event.eapol_rx.src = src; + event.eapol_rx.data = data; + event.eapol_rx.data_len = data_len; + wpa_supplicant_event(drv->ctx, EVENT_EAPOL_RX, &event); } diff --git a/src/drivers/driver_wired.c b/src/drivers/driver_wired.c index 4a596a1c6..ba6ae0087 100644 --- a/src/drivers/driver_wired.c +++ b/src/drivers/driver_wired.c @@ -141,7 +141,11 @@ static void handle_data(void *ctx, unsigned char *buf, size_t len) pos = (u8 *) (hdr + 1); left = len - sizeof(*hdr); - hostapd_eapol_receive(ctx, sa, pos, left); + os_memset(&event, 0, sizeof(event)); + event.eapol_rx.src = sa; + event.eapol_rx.data = pos; + event.eapol_rx.data_len = left; + wpa_supplicant_event(ctx, EVENT_EAPOL_RX, &event); break; default: diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index 0f89aaacd..ff07d60e0 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -22,6 +22,7 @@ #ifdef NEED_AP_MLME #include "ap/ieee802_11.h" #endif /* NEED_AP_MLME */ +#include "ap/ieee802_1x.h" #include "ap/wps_hostapd.h" #include "ap/ctrl_iface_ap.h" #include "eap_common/eap_defs.h" @@ -289,7 +290,7 @@ void ap_mgmt_tx_cb(void *ctx, const u8 *buf, size_t len, u16 stype, int ok) void wpa_supplicant_ap_rx_eapol(struct wpa_supplicant *wpa_s, const u8 *src_addr, const u8 *buf, size_t len) { - hostapd_eapol_receive(wpa_s->ap_iface->bss[0], src_addr, buf, len); + ieee802_1x_receive(wpa_s->ap_iface->bss[0], src_addr, buf, len); } diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 4bd9da810..050ca1eba 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -1515,7 +1515,11 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, break; } #endif /* CONFIG_CLIENT_MLME */ - + case EVENT_EAPOL_RX: + wpa_supplicant_rx_eapol(wpa_s, data->eapol_rx.src, + data->eapol_rx.data, + data->eapol_rx.data_len); + break; default: wpa_printf(MSG_INFO, "Unknown event %d", event); break; diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index fc42d2939..7e56bb70f 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1722,6 +1722,20 @@ static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s, } +/** + * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant + * @ctx: Context pointer (wpa_s); this is the ctx variable registered + * with struct wpa_driver_ops::init() + * @src_addr: Source address of the EAPOL frame + * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header) + * @len: Length of the EAPOL data + * + * This function is called for each received EAPOL frame. Most driver + * interfaces rely on more generic OS mechanism for receiving frames through + * l2_packet, but if such a mechanism is not available, the driver wrapper may + * take care of received EAPOL frames and deliver them to the core supplicant + * code by calling this function. + */ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr, const u8 *buf, size_t len) { diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index f86a172b5..677925f66 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -487,6 +487,8 @@ void wpa_supplicant_deinit(struct wpa_global *global); int wpa_supplicant_scard_init(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); void wpa_supplicant_terminate_proc(struct wpa_global *global); +void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr, + const u8 *buf, size_t len); /* scan.c */ int wpa_supplicant_enabled_networks(struct wpa_config *conf);