X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=src%2Fdrivers%2Fdriver_test.c;h=c630e4c2c932c5d88e4e49a79a9e63b2728cf599;hb=0e2e565a44ab7b073491cab00847f7bc62731483;hp=d2aaf1f6a7b2a4f015f68590ef64e0e0a5e4768a;hpb=0b55b934ee6243f2682524b0a733cc1468e20050;p=libeap.git diff --git a/src/drivers/driver_test.c b/src/drivers/driver_test.c index d2aaf1f..c630e4c 100644 --- a/src/drivers/driver_test.c +++ b/src/drivers/driver_test.c @@ -1,6 +1,6 @@ /* - * WPA Supplicant - testing driver interface - * Copyright (c) 2004-2008, Jouni Malinen + * Testing driver interface for a simulated network driver + * Copyright (c) 2004-2010, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -18,7 +18,7 @@ #include #endif /* CONFIG_NATIVE_WINDOWS */ -#include "includes.h" +#include "utils/includes.h" #ifndef CONFIG_NATIVE_WINDOWS #include @@ -27,16 +27,14 @@ #define DRIVER_TEST_UNIX #endif /* CONFIG_NATIVE_WINDOWS */ -#include "common.h" -#include "driver.h" +#include "utils/common.h" +#include "utils/eloop.h" +#include "utils/list.h" +#include "utils/trace.h" +#include "common/ieee802_11_defs.h" +#include "crypto/sha1.h" #include "l2_packet/l2_packet.h" -#include "eloop.h" -#include "sha1.h" -#include "ieee802_11_defs.h" - -#include "../../hostapd/hostapd.h" -#include "../../hostapd/wpa.h" -#include "../../hostapd/hw_features.h" +#include "driver.h" struct test_client_socket { @@ -48,8 +46,10 @@ struct test_client_socket { }; struct test_driver_bss { - struct test_driver_bss *next; - char ifname[IFNAMSIZ + 1]; + struct wpa_driver_test_data *drv; + struct dl_list list; + void *bss_ctx; + char ifname[IFNAMSIZ]; u8 bssid[ETH_ALEN]; u8 *ie; size_t ielen; @@ -63,12 +63,14 @@ struct test_driver_bss { }; struct wpa_driver_test_global { - int dummy; + int bss_add_used; + u8 req_addr[ETH_ALEN]; }; struct wpa_driver_test_data { struct wpa_driver_test_global *global; void *ctx; + WPA_TRACE_REF(ctx); u8 own_addr[ETH_ALEN]; int test_socket; #ifdef DRIVER_TEST_UNIX @@ -79,9 +81,6 @@ struct wpa_driver_test_data { int hostapd_addr_udp_set; char *own_socket_path; char *test_dir; - u8 bssid[ETH_ALEN]; - u8 ssid[32]; - size_t ssid_len; #define MAX_SCAN_RESULTS 30 struct wpa_scan_res *scanres[MAX_SCAN_RESULTS]; size_t num_scanres; @@ -92,14 +91,22 @@ struct wpa_driver_test_data { int associated; u8 *probe_req_ie; size_t probe_req_ie_len; + u8 probe_req_ssid[32]; + size_t probe_req_ssid_len; int ibss; - int privacy; int ap; - struct hostapd_data *hapd; struct test_client_socket *cli; - struct test_driver_bss *bss; + struct dl_list bss; int udp_port; + + int alloc_iface_idx; + + int probe_req_report; + unsigned int remain_on_channel_freq; + unsigned int remain_on_channel_duration; + + int current_freq; }; @@ -108,33 +115,27 @@ static int wpa_driver_test_attach(struct wpa_driver_test_data *drv, const char *dir, int ap); static void wpa_driver_test_close_test_socket( struct wpa_driver_test_data *drv); +static void test_remain_on_channel_timeout(void *eloop_ctx, void *timeout_ctx); -#ifdef CONFIG_AP -void ap_mgmt_rx(void *ctx, u8 *buf, size_t len, u16 stype, - struct hostapd_frame_info *fi); -void ap_mgmt_tx_cb(void *ctx, u8 *buf, size_t len, u16 stype, int ok); - -#else /* CONFIG_AP */ -#ifndef HOSTAPD -static inline void ap_mgmt_rx(void *ctx, u8 *buf, size_t len, u16 stype, - struct hostapd_frame_info *fi) -{ -} -static inline void ap_mgmt_tx_cb(void *ctx, u8 *buf, size_t len, u16 stype, - int ok) +static void test_driver_free_bss(struct test_driver_bss *bss) { + os_free(bss->ie); + os_free(bss->wps_beacon_ie); + os_free(bss->wps_probe_resp_ie); + os_free(bss); } -#endif /* HOSTAPD */ -#endif /* CONFIG_AP */ -static void test_driver_free_bss(struct test_driver_bss *bss) +static void test_driver_free_bsses(struct wpa_driver_test_data *drv) { - free(bss->ie); - free(bss->wps_beacon_ie); - free(bss->wps_probe_resp_ie); - free(bss); + struct test_driver_bss *bss, *tmp; + + dl_list_for_each_safe(bss, tmp, &drv->bss, struct test_driver_bss, + list) { + dl_list_del(&bss->list); + test_driver_free_bss(bss); + } } @@ -160,7 +161,8 @@ static int test_driver_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len, int encrypt, const u8 *own_addr) { - struct wpa_driver_test_data *drv = priv; + struct test_driver_bss *dbss = priv; + struct wpa_driver_test_data *drv = dbss->drv; struct test_client_socket *cli; struct msghdr msg; struct iovec io[3]; @@ -205,7 +207,8 @@ static int test_driver_send_eapol(void *priv, const u8 *addr, const u8 *data, static int test_driver_send_ether(void *priv, const u8 *dst, const u8 *src, u16 proto, const u8 *data, size_t data_len) { - struct wpa_driver_test_data *drv = priv; + struct test_driver_bss *dbss = priv; + struct wpa_driver_test_data *drv = dbss->drv; struct msghdr msg; struct iovec io[3]; struct l2_ethhdr eth; @@ -292,7 +295,8 @@ static int test_driver_send_ether(void *priv, const u8 *dst, const u8 *src, static int wpa_driver_test_send_mlme(void *priv, const u8 *data, size_t data_len) { - struct wpa_driver_test_data *drv = priv; + struct test_driver_bss *dbss = priv; + struct wpa_driver_test_data *drv = dbss->drv; struct msghdr msg; struct iovec io[2]; const u8 *dest; @@ -303,9 +307,12 @@ static int wpa_driver_test_send_mlme(void *priv, const u8 *data, int ret = 0; struct ieee80211_hdr *hdr; u16 fc; + char cmd[50]; + int freq; #ifdef HOSTAPD char desttxt[30]; #endif /* HOSTAPD */ + union wpa_event_data event; wpa_hexdump(MSG_MSGDUMP, "test_send_mlme", data, data_len); if (drv->test_socket < 0 || data_len < 10) { @@ -324,8 +331,15 @@ static int wpa_driver_test_send_mlme(void *priv, const u8 *data, snprintf(desttxt, sizeof(desttxt), MACSTR, MAC2STR(dest)); #endif /* HOSTAPD */ - io[0].iov_base = "MLME "; - io[0].iov_len = 5; + if (drv->remain_on_channel_freq) + freq = drv->remain_on_channel_freq; + else + freq = drv->current_freq; + wpa_printf(MSG_DEBUG, "test_driver(%s): MLME TX on freq %d MHz", + dbss->ifname, freq); + os_snprintf(cmd, sizeof(cmd), "MLME freq=%d ", freq); + io[0].iov_base = cmd; + io[0].iov_len = os_strlen(cmd); io[1].iov_base = (void *) data; io[1].iov_len = data_len; @@ -378,7 +392,7 @@ static int wpa_driver_test_send_mlme(void *priv, const u8 *data, closedir(dir); #else /* HOSTAPD */ - if (os_memcmp(dest, drv->bssid, ETH_ALEN) == 0 || + if (os_memcmp(dest, dbss->bssid, ETH_ALEN) == 0 || drv->test_dir == NULL) { if (drv->hostapd_addr_udp_set) { msg.msg_name = &drv->hostapd_addr_udp; @@ -445,15 +459,15 @@ static int wpa_driver_test_send_mlme(void *priv, const u8 *data, hdr = (struct ieee80211_hdr *) data; fc = le_to_host16(hdr->frame_control); -#ifdef HOSTAPD - hostapd_mgmt_tx_cb(drv->hapd, (u8 *) data, data_len, - WLAN_FC_GET_STYPE(fc), ret >= 0); -#else /* HOSTAPD */ - if (drv->ap) { - ap_mgmt_tx_cb(drv->ctx, (u8 *) data, data_len, - WLAN_FC_GET_STYPE(fc), ret >= 0); - } -#endif /* HOSTAPD */ + + os_memset(&event, 0, sizeof(event)); + event.tx_status.type = WLAN_FC_GET_TYPE(fc); + event.tx_status.stype = WLAN_FC_GET_STYPE(fc); + event.tx_status.dst = hdr->addr1; + event.tx_status.data = data; + event.tx_status.data_len = data_len; + event.tx_status.ack = ret >= 0; + wpa_supplicant_event(drv->ctx, EVENT_TX_STATUS, &event); return ret; } @@ -469,6 +483,7 @@ static void test_driver_scan(struct wpa_driver_test_data *drv, u8 sa[ETH_ALEN]; u8 ie[512]; size_t ielen; + union wpa_event_data event; /* data: optional [ ' ' | STA-addr | ' ' | IEs(hex) ] */ @@ -495,12 +510,14 @@ static void test_driver_scan(struct wpa_driver_test_data *drv, MAC2STR(sa)); wpa_hexdump(MSG_MSGDUMP, "test_driver: scan IEs", ie, ielen); -#ifdef HOSTAPD - hostapd_probe_req_rx(drv->hapd, sa, ie, ielen); -#endif /* HOSTAPD */ + os_memset(&event, 0, sizeof(event)); + event.rx_probe_req.sa = sa; + event.rx_probe_req.ie = ie; + event.rx_probe_req.ie_len = ielen; + wpa_supplicant_event(drv->ctx, EVENT_RX_PROBE_REQ, &event); } - for (bss = drv->bss; bss; bss = bss->next) { + dl_list_for_each(bss, &drv->bss, struct test_driver_bss, list) { pos = buf; end = buf + sizeof(buf); @@ -533,56 +550,6 @@ static void test_driver_scan(struct wpa_driver_test_data *drv, } -static struct hostapd_data * -test_driver_get_hapd(struct wpa_driver_test_data *drv, - struct test_driver_bss *bss) -{ -#ifdef HOSTAPD - struct hostapd_iface *iface = drv->hapd->iface; - struct hostapd_data *hapd = NULL; - size_t i; - - if (bss == NULL) { - wpa_printf(MSG_DEBUG, "%s: bss == NULL", __func__); - return NULL; - } - - for (i = 0; i < iface->num_bss; i++) { - hapd = iface->bss[i]; - if (memcmp(hapd->own_addr, bss->bssid, ETH_ALEN) == 0) - break; - } - if (i == iface->num_bss) { - wpa_printf(MSG_DEBUG, "%s: no matching interface entry found " - "for BSSID " MACSTR, __func__, MAC2STR(bss->bssid)); - return NULL; - } - - return hapd; -#else /* HOSTAPD */ - return NULL; -#endif /* HOSTAPD */ -} - - -static int test_driver_new_sta(struct wpa_driver_test_data *drv, - struct test_driver_bss *bss, const u8 *addr, - const u8 *ie, size_t ielen) -{ - struct hostapd_data *hapd; - - hapd = test_driver_get_hapd(drv, bss); - if (hapd == NULL) - return -1; - -#ifdef HOSTAPD - return hostapd_notif_assoc(hapd, addr, ie, ielen); -#else /* HOSTAPD */ - return -1; -#endif /* HOSTAPD */ -} - - static void test_driver_assoc(struct wpa_driver_test_data *drv, struct sockaddr_un *from, socklen_t fromlen, char *data) @@ -591,7 +558,7 @@ static void test_driver_assoc(struct wpa_driver_test_data *drv, u8 ie[256], ssid[32]; size_t ielen, ssid_len = 0; char *pos, *pos2, cmd[50]; - struct test_driver_bss *bss; + struct test_driver_bss *bss, *tmp; /* data: STA-addr SSID(hex) IEs(hex) */ @@ -602,7 +569,7 @@ static void test_driver_assoc(struct wpa_driver_test_data *drv, if (hwaddr_aton(data, cli->addr)) { printf("test_socket: Invalid MAC address '%s' in ASSOC\n", data); - free(cli); + os_free(cli); return; } pos = data + 17; @@ -614,7 +581,7 @@ static void test_driver_assoc(struct wpa_driver_test_data *drv, ssid_len = (pos2 - pos) / 2; if (hexstr2bin(pos, ssid, ssid_len) < 0) { wpa_printf(MSG_DEBUG, "%s: Invalid SSID", __func__); - free(cli); + os_free(cli); return; } wpa_hexdump_ascii(MSG_DEBUG, "test_driver_assoc: SSID", @@ -628,15 +595,18 @@ static void test_driver_assoc(struct wpa_driver_test_data *drv, ielen = 0; } - for (bss = drv->bss; bss; bss = bss->next) { - if (bss->ssid_len == ssid_len && - memcmp(bss->ssid, ssid, ssid_len) == 0) + bss = NULL; + dl_list_for_each(tmp, &drv->bss, struct test_driver_bss, list) { + if (tmp->ssid_len == ssid_len && + os_memcmp(tmp->ssid, ssid, ssid_len) == 0) { + bss = tmp; break; + } } if (bss == NULL) { wpa_printf(MSG_DEBUG, "%s: No matching SSID found from " "configured BSSes", __func__); - free(cli); + os_free(cli); return; } @@ -654,9 +624,7 @@ static void test_driver_assoc(struct wpa_driver_test_data *drv, sendto(drv->test_socket, cmd, strlen(cmd), 0, (struct sockaddr *) from, fromlen); - if (test_driver_new_sta(drv, bss, cli->addr, ie, ielen) < 0) { - wpa_printf(MSG_DEBUG, "test_driver: failed to add new STA"); - } + drv_event_assoc(bss->bss_ctx, cli->addr, ie, ielen); } @@ -669,9 +637,7 @@ static void test_driver_disassoc(struct wpa_driver_test_data *drv, if (!cli) return; -#ifdef HOSTAPD - hostapd_notif_disassoc(drv->hapd, cli->addr); -#endif /* HOSTAPD */ + drv_event_disassoc(drv->ctx, cli->addr); } @@ -694,21 +660,19 @@ static void test_driver_eapol(struct wpa_driver_test_data *drv, data += 14; datalen -= 14; } + #ifdef HOSTAPD cli = test_driver_get_cli(drv, from, fromlen); if (cli) { - struct hostapd_data *hapd; - hapd = test_driver_get_hapd(drv, cli->bss); - if (hapd == NULL) - return; - hostapd_eapol_receive(hapd, cli->addr, data, datalen); + drv_event_eapol_rx(cli->bss->bss_ctx, cli->addr, data, + datalen); } else { wpa_printf(MSG_DEBUG, "test_socket: EAPOL from unknown " "client"); } #else /* HOSTAPD */ if (src) - wpa_supplicant_rx_eapol(drv->ctx, src, data, datalen); + drv_event_eapol_rx(drv->ctx, src, data, datalen); #endif /* HOSTAPD */ } @@ -730,10 +694,11 @@ static void test_driver_ether(struct wpa_driver_test_data *drv, #ifdef CONFIG_IEEE80211R if (be_to_host16(eth->h_proto) == ETH_P_RRB) { -#ifdef HOSTAPD - wpa_ft_rrb_rx(drv->hapd->wpa_auth, eth->h_source, - data + sizeof(*eth), datalen - sizeof(*eth)); -#endif /* HOSTAPD */ + union wpa_event_data ev; + os_memset(&ev, 0, sizeof(ev)); + ev.ft_rrb_rx.src = eth->h_source; + ev.ft_rrb_rx.data = data + sizeof(*eth); + ev.ft_rrb_rx.data_len = datalen - sizeof(*eth); } #endif /* CONFIG_IEEE80211R */ } @@ -745,6 +710,39 @@ static void test_driver_mlme(struct wpa_driver_test_data *drv, { struct ieee80211_hdr *hdr; u16 fc; + union wpa_event_data event; + int freq = 0, own_freq; + struct test_driver_bss *bss; + + bss = dl_list_first(&drv->bss, struct test_driver_bss, list); + + if (datalen > 6 && os_memcmp(data, "freq=", 5) == 0) { + size_t pos; + for (pos = 5; pos < datalen; pos++) { + if (data[pos] == ' ') + break; + } + if (pos < datalen) { + freq = atoi((const char *) &data[5]); + wpa_printf(MSG_DEBUG, "test_driver(%s): MLME RX on " + "freq %d MHz", bss->ifname, freq); + pos++; + data += pos; + datalen -= pos; + } + } + + if (drv->remain_on_channel_freq) + own_freq = drv->remain_on_channel_freq; + else + own_freq = drv->current_freq; + + if (freq && own_freq && freq != own_freq) { + wpa_printf(MSG_DEBUG, "test_driver(%s): Ignore MLME RX on " + "another frequency %d MHz (own %d MHz)", + bss->ifname, freq, own_freq); + return; + } hdr = (struct ieee80211_hdr *) data; @@ -770,11 +768,11 @@ static void test_driver_mlme(struct wpa_driver_test_data *drv, __func__); return; } -#ifdef HOSTAPD - hostapd_mgmt_rx(drv->hapd, data, datalen, WLAN_FC_GET_STYPE(fc), NULL); -#else /* HOSTAPD */ - ap_mgmt_rx(drv->ctx, data, datalen, WLAN_FC_GET_STYPE(fc), NULL); -#endif /* HOSTAPD */ + + os_memset(&event, 0, sizeof(event)); + event.rx_mgmt.frame = data; + event.rx_mgmt.frame_len = datalen; + wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event); } @@ -817,30 +815,12 @@ static void test_driver_receive_unix(int sock, void *eloop_ctx, void *sock_ctx) } -static struct test_driver_bss * -test_driver_get_bss(struct wpa_driver_test_data *drv, const char *ifname) -{ - struct test_driver_bss *bss; - - for (bss = drv->bss; bss; bss = bss->next) { - if (strcmp(bss->ifname, ifname) == 0) - return bss; - } - return NULL; -} - - -static int test_driver_set_generic_elem(const char *ifname, void *priv, +static int test_driver_set_generic_elem(void *priv, const u8 *elem, size_t elem_len) { - struct wpa_driver_test_data *drv = priv; - struct test_driver_bss *bss; - - bss = test_driver_get_bss(drv, ifname); - if (bss == NULL) - return -1; + struct test_driver_bss *bss = priv; - free(bss->ie); + os_free(bss->ie); if (elem == NULL) { bss->ie = NULL; @@ -848,7 +828,7 @@ static int test_driver_set_generic_elem(const char *ifname, void *priv, return 0; } - bss->ie = malloc(elem_len); + bss->ie = os_malloc(elem_len); if (bss->ie == NULL) { bss->ielen = 0; return -1; @@ -860,64 +840,59 @@ static int test_driver_set_generic_elem(const char *ifname, void *priv, } -static int test_driver_set_wps_beacon_ie(const char *ifname, void *priv, - const u8 *ie, size_t len) +static int test_driver_set_ap_wps_ie(void *priv, const struct wpabuf *beacon, + const struct wpabuf *proberesp, + const struct wpabuf *assocresp) { - struct wpa_driver_test_data *drv = priv; - struct test_driver_bss *bss; + struct test_driver_bss *bss = priv; - wpa_hexdump(MSG_DEBUG, "test_driver: Beacon WPS IE", ie, len); - bss = test_driver_get_bss(drv, ifname); - if (bss == NULL) - return -1; + if (beacon == NULL) + wpa_printf(MSG_DEBUG, "test_driver: Clear Beacon WPS IE"); + else + wpa_hexdump_buf(MSG_DEBUG, "test_driver: Beacon WPS IE", + beacon); - free(bss->wps_beacon_ie); + os_free(bss->wps_beacon_ie); - if (ie == NULL) { + if (beacon == NULL) { bss->wps_beacon_ie = NULL; bss->wps_beacon_ie_len = 0; - return 0; - } + } else { + bss->wps_beacon_ie = os_malloc(wpabuf_len(beacon)); + if (bss->wps_beacon_ie == NULL) { + bss->wps_beacon_ie_len = 0; + return -1; + } - bss->wps_beacon_ie = malloc(len); - if (bss->wps_beacon_ie == NULL) { - bss->wps_beacon_ie_len = 0; - return -1; + os_memcpy(bss->wps_beacon_ie, wpabuf_head(beacon), + wpabuf_len(beacon)); + bss->wps_beacon_ie_len = wpabuf_len(beacon); } - memcpy(bss->wps_beacon_ie, ie, len); - bss->wps_beacon_ie_len = len; - return 0; -} - - -static int test_driver_set_wps_probe_resp_ie(const char *ifname, void *priv, - const u8 *ie, size_t len) -{ - struct wpa_driver_test_data *drv = priv; - struct test_driver_bss *bss; - - wpa_hexdump(MSG_DEBUG, "test_driver: ProbeResp WPS IE", ie, len); - bss = test_driver_get_bss(drv, ifname); - if (bss == NULL) - return -1; + if (proberesp == NULL) + wpa_printf(MSG_DEBUG, "test_driver: Clear Probe Response WPS " + "IE"); + else + wpa_hexdump_buf(MSG_DEBUG, "test_driver: Probe Response WPS " + "IE", proberesp); - free(bss->wps_probe_resp_ie); + os_free(bss->wps_probe_resp_ie); - if (ie == NULL) { + if (proberesp == NULL) { bss->wps_probe_resp_ie = NULL; bss->wps_probe_resp_ie_len = 0; - return 0; - } + } else { + bss->wps_probe_resp_ie = os_malloc(wpabuf_len(proberesp)); + if (bss->wps_probe_resp_ie == NULL) { + bss->wps_probe_resp_ie_len = 0; + return -1; + } - bss->wps_probe_resp_ie = malloc(len); - if (bss->wps_probe_resp_ie == NULL) { - bss->wps_probe_resp_ie_len = 0; - return -1; + os_memcpy(bss->wps_probe_resp_ie, wpabuf_head(proberesp), + wpabuf_len(proberesp)); + bss->wps_probe_resp_ie_len = wpabuf_len(proberesp); } - memcpy(bss->wps_probe_resp_ie, ie, len); - bss->wps_probe_resp_ie_len = len; return 0; } @@ -925,7 +900,8 @@ static int test_driver_set_wps_probe_resp_ie(const char *ifname, void *priv, static int test_driver_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, int reason) { - struct wpa_driver_test_data *drv = priv; + struct test_driver_bss *dbss = priv; + struct wpa_driver_test_data *drv = dbss->drv; struct test_client_socket *cli; if (drv->test_socket < 0) @@ -949,7 +925,8 @@ static int test_driver_sta_deauth(void *priv, const u8 *own_addr, static int test_driver_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr, int reason) { - struct wpa_driver_test_data *drv = priv; + struct test_driver_bss *dbss = priv; + struct wpa_driver_test_data *drv = dbss->drv; struct test_client_socket *cli; if (drv->test_socket < 0) @@ -970,9 +947,11 @@ static int test_driver_sta_disassoc(void *priv, const u8 *own_addr, } -static int test_driver_bss_add(void *priv, const char *ifname, const u8 *bssid) +static int test_driver_bss_add(void *priv, const char *ifname, const u8 *bssid, + void *bss_ctx, void **drv_priv) { - struct wpa_driver_test_data *drv = priv; + struct test_driver_bss *dbss = priv; + struct wpa_driver_test_data *drv = dbss->drv; struct test_driver_bss *bss; wpa_printf(MSG_DEBUG, "%s(ifname=%s bssid=" MACSTR ")", @@ -982,11 +961,19 @@ static int test_driver_bss_add(void *priv, const char *ifname, const u8 *bssid) if (bss == NULL) return -1; + bss->bss_ctx = bss_ctx; + bss->drv = drv; os_strlcpy(bss->ifname, ifname, IFNAMSIZ); - memcpy(bss->bssid, bssid, ETH_ALEN); + os_memcpy(bss->bssid, bssid, ETH_ALEN); - bss->next = drv->bss; - drv->bss = bss; + dl_list_add(&drv->bss, &bss->list); + if (drv->global) { + drv->global->bss_add_used = 1; + os_memcpy(drv->global->req_addr, bssid, ETH_ALEN); + } + + if (drv_priv) + *drv_priv = bss; return 0; } @@ -994,21 +981,17 @@ static int test_driver_bss_add(void *priv, const char *ifname, const u8 *bssid) static int test_driver_bss_remove(void *priv, const char *ifname) { - struct wpa_driver_test_data *drv = priv; - struct test_driver_bss *bss, *prev; + struct test_driver_bss *dbss = priv; + struct wpa_driver_test_data *drv = dbss->drv; + struct test_driver_bss *bss; struct test_client_socket *cli, *prev_c; wpa_printf(MSG_DEBUG, "%s(ifname=%s)", __func__, ifname); - for (prev = NULL, bss = drv->bss; bss; prev = bss, bss = bss->next) { + dl_list_for_each(bss, &drv->bss, struct test_driver_bss, list) { if (strcmp(bss->ifname, ifname) != 0) continue; - if (prev) - prev->next = bss->next; - else - drv->bss = bss->next; - for (prev_c = NULL, cli = drv->cli; cli; prev_c = cli, cli = cli->next) { if (cli->bss != bss) @@ -1017,10 +1000,11 @@ static int test_driver_bss_remove(void *priv, const char *ifname) prev_c->next = cli->next; else drv->cli = cli->next; - free(cli); + os_free(cli); break; } + dl_list_del(&bss->list); test_driver_free_bss(bss); return 0; } @@ -1029,28 +1013,42 @@ static int test_driver_bss_remove(void *priv, const char *ifname) } -static int test_driver_if_add(const char *iface, void *priv, - enum hostapd_driver_if_type type, char *ifname, - const u8 *addr) +static int test_driver_if_add(void *priv, enum wpa_driver_if_type type, + const char *ifname, const u8 *addr, + void *bss_ctx, void **drv_priv, + char *force_ifname, u8 *if_addr) { - wpa_printf(MSG_DEBUG, "%s(iface=%s type=%d ifname=%s)", - __func__, iface, type, ifname); - return 0; -} - + struct test_driver_bss *dbss = priv; + struct wpa_driver_test_data *drv = dbss->drv; -static int test_driver_if_update(void *priv, enum hostapd_driver_if_type type, - char *ifname, const u8 *addr) -{ - wpa_printf(MSG_DEBUG, "%s(type=%d ifname=%s)", __func__, type, ifname); + wpa_printf(MSG_DEBUG, "%s(type=%d ifname=%s bss_ctx=%p)", + __func__, type, ifname, bss_ctx); + if (addr) + os_memcpy(if_addr, addr, ETH_ALEN); + else { + drv->alloc_iface_idx++; + if_addr[0] = 0x02; /* locally administered */ + sha1_prf(drv->own_addr, ETH_ALEN, + "hostapd test addr generation", + (const u8 *) &drv->alloc_iface_idx, + sizeof(drv->alloc_iface_idx), + if_addr + 1, ETH_ALEN - 1); + } + if (type == WPA_IF_AP_BSS || type == WPA_IF_P2P_GO || + type == WPA_IF_P2P_CLIENT || type == WPA_IF_P2P_GROUP) + return test_driver_bss_add(priv, ifname, if_addr, bss_ctx, + drv_priv); return 0; } -static int test_driver_if_remove(void *priv, enum hostapd_driver_if_type type, - const char *ifname, const u8 *addr) +static int test_driver_if_remove(void *priv, enum wpa_driver_if_type type, + const char *ifname) { wpa_printf(MSG_DEBUG, "%s(type=%d ifname=%s)", __func__, type, ifname); + if (type == WPA_IF_AP_BSS || type == WPA_IF_P2P_GO || + type == WPA_IF_P2P_CLIENT || type == WPA_IF_P2P_GROUP) + return test_driver_bss_remove(priv, ifname); return 0; } @@ -1062,64 +1060,30 @@ static int test_driver_valid_bss_mask(void *priv, const u8 *addr, } -static int test_driver_set_ssid(const char *ifname, void *priv, const u8 *buf, - int len) +static int test_driver_set_ssid(void *priv, const u8 *buf, int len) { - struct wpa_driver_test_data *drv = priv; - struct test_driver_bss *bss; + struct test_driver_bss *bss = priv; - wpa_printf(MSG_DEBUG, "%s(ifname=%s)", __func__, ifname); + wpa_printf(MSG_DEBUG, "%s(ifname=%s)", __func__, bss->ifname); wpa_hexdump_ascii(MSG_DEBUG, "test_driver_set_ssid: SSID", buf, len); - for (bss = drv->bss; bss; bss = bss->next) { - if (strcmp(bss->ifname, ifname) != 0) - continue; - - if (len < 0 || (size_t) len > sizeof(bss->ssid)) - return -1; - - memcpy(bss->ssid, buf, len); - bss->ssid_len = len; + if (len < 0 || (size_t) len > sizeof(bss->ssid)) + return -1; - return 0; - } + os_memcpy(bss->ssid, buf, len); + bss->ssid_len = len; - return -1; + return 0; } -static int test_driver_set_privacy(const char *ifname, void *priv, int enabled) +static int test_driver_set_privacy(void *priv, int enabled) { - struct wpa_driver_test_data *drv = priv; - struct test_driver_bss *bss; - - wpa_printf(MSG_DEBUG, "%s(ifname=%s enabled=%d)", - __func__, ifname, enabled); + struct test_driver_bss *dbss = priv; - for (bss = drv->bss; bss; bss = bss->next) { - if (strcmp(bss->ifname, ifname) != 0) - continue; + wpa_printf(MSG_DEBUG, "%s(enabled=%d)", __func__, enabled); + dbss->privacy = enabled; - bss->privacy = enabled; - - return 0; - } - - return -1; -} - - -static int test_driver_set_key(const char *iface, void *priv, wpa_alg alg, - const u8 *addr, int key_idx, int set_tx, - const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) -{ - wpa_printf(MSG_DEBUG, "%s(iface=%s alg=%d idx=%d set_tx=%d)", - __func__, iface, alg, key_idx, set_tx); - if (addr) - wpa_printf(MSG_DEBUG, " addr=" MACSTR, MAC2STR(addr)); - if (key) - wpa_hexdump_key(MSG_DEBUG, " key", key, key_len); return 0; } @@ -1133,18 +1097,17 @@ static int test_driver_set_sta_vlan(void *priv, const u8 *addr, } -static int test_driver_sta_add(const char *ifname, void *priv, +static int test_driver_sta_add(void *priv, struct hostapd_sta_add_params *params) { - struct wpa_driver_test_data *drv = priv; + struct test_driver_bss *bss = priv; + struct wpa_driver_test_data *drv = bss->drv; struct test_client_socket *cli; - struct test_driver_bss *bss; wpa_printf(MSG_DEBUG, "%s(ifname=%s addr=" MACSTR " aid=%d " - "capability=0x%x flags=0x%x listen_interval=%d)", - __func__, ifname, MAC2STR(params->addr), params->aid, - params->capability, params->flags, - params->listen_interval); + "capability=0x%x listen_interval=%d)", + __func__, bss->ifname, MAC2STR(params->addr), params->aid, + params->capability, params->listen_interval); wpa_hexdump(MSG_DEBUG, "test_driver_sta_add - supp_rates", params->supp_rates, params->supp_rates_len); @@ -1160,19 +1123,46 @@ static int test_driver_sta_add(const char *ifname, void *priv, return -1; } - for (bss = drv->bss; bss; bss = bss->next) { - if (strcmp(ifname, bss->ifname) == 0) - break; + cli->bss = bss; + + return 0; +} + + +static struct wpa_driver_test_data * test_alloc_data(void *ctx, + const char *ifname) +{ + struct wpa_driver_test_data *drv; + struct test_driver_bss *bss; + + drv = os_zalloc(sizeof(struct wpa_driver_test_data)); + if (drv == NULL) { + wpa_printf(MSG_ERROR, "Could not allocate memory for test " + "driver data"); + return NULL; } + + bss = os_zalloc(sizeof(struct test_driver_bss)); if (bss == NULL) { - wpa_printf(MSG_DEBUG, "%s: No matching interface found from " - "configured BSSes", __func__); - return -1; + os_free(drv); + return NULL; } - cli->bss = bss; + drv->ctx = ctx; + wpa_trace_add_ref(drv, ctx, ctx); + dl_list_init(&drv->bss); + dl_list_add(&drv->bss, &bss->list); + os_strlcpy(bss->ifname, ifname, IFNAMSIZ); + bss->bss_ctx = ctx; + bss->drv = drv; - return 0; + /* Generate a MAC address to help testing with multiple STAs */ + drv->own_addr[0] = 0x02; /* locally administered */ + sha1_prf((const u8 *) ifname, os_strlen(ifname), + "test mac addr generation", + NULL, 0, drv->own_addr + 1, ETH_ALEN - 1); + + return drv; } @@ -1184,42 +1174,29 @@ static void * test_driver_init(struct hostapd_data *hapd, struct sockaddr_in addr_in; struct sockaddr *addr; socklen_t alen; + struct test_driver_bss *bss; - drv = os_zalloc(sizeof(struct wpa_driver_test_data)); - if (drv == NULL) { - printf("Could not allocate memory for test driver data\n"); - return NULL; - } - drv->bss = os_zalloc(sizeof(*drv->bss)); - if (drv->bss == NULL) { - printf("Could not allocate memory for test driver BSS data\n"); - free(drv); + drv = test_alloc_data(hapd, params->ifname); + if (drv == NULL) return NULL; - } + drv->ap = 1; + bss = dl_list_first(&drv->bss, struct test_driver_bss, list); - drv->hapd = hapd; - - /* Generate a MAC address to help testing with multiple APs */ - params->own_addr[0] = 0x02; /* locally administered */ - sha1_prf((const u8 *) params->ifname, strlen(params->ifname), - "hostapd test bssid generation", - params->ssid, params->ssid_len, - params->own_addr + 1, ETH_ALEN - 1); - - os_strlcpy(drv->bss->ifname, params->ifname, IFNAMSIZ); - memcpy(drv->bss->bssid, params->own_addr, ETH_ALEN); + bss->bss_ctx = hapd; + os_memcpy(bss->bssid, drv->own_addr, ETH_ALEN); + os_memcpy(params->own_addr, drv->own_addr, ETH_ALEN); if (params->test_socket) { if (os_strlen(params->test_socket) >= sizeof(addr_un.sun_path)) { printf("Too long test_socket path\n"); - wpa_driver_test_deinit(drv); + wpa_driver_test_deinit(bss); return NULL; } if (strncmp(params->test_socket, "DIR:", 4) == 0) { size_t len = strlen(params->test_socket) + 30; - drv->test_dir = strdup(params->test_socket + 4); - drv->own_socket_path = malloc(len); + drv->test_dir = os_strdup(params->test_socket + 4); + drv->own_socket_path = os_malloc(len); if (drv->own_socket_path) { snprintf(drv->own_socket_path, len, "%s/AP-" MACSTR, @@ -1229,10 +1206,10 @@ static void * test_driver_init(struct hostapd_data *hapd, } else if (strncmp(params->test_socket, "UDP:", 4) == 0) { drv->udp_port = atoi(params->test_socket + 4); } else { - drv->own_socket_path = strdup(params->test_socket); + drv->own_socket_path = os_strdup(params->test_socket); } if (drv->own_socket_path == NULL && drv->udp_port == 0) { - wpa_driver_test_deinit(drv); + wpa_driver_test_deinit(bss); return NULL; } @@ -1240,7 +1217,7 @@ static void * test_driver_init(struct hostapd_data *hapd, SOCK_DGRAM, 0); if (drv->test_socket < 0) { perror("socket"); - wpa_driver_test_deinit(drv); + wpa_driver_test_deinit(bss); return NULL; } @@ -1263,7 +1240,7 @@ static void * test_driver_init(struct hostapd_data *hapd, close(drv->test_socket); if (drv->own_socket_path) unlink(drv->own_socket_path); - wpa_driver_test_deinit(drv); + wpa_driver_test_deinit(bss); return NULL; } eloop_register_read_sock(drv->test_socket, @@ -1271,7 +1248,7 @@ static void * test_driver_init(struct hostapd_data *hapd, } else drv->test_socket = -1; - return drv; + return bss; } @@ -1295,13 +1272,6 @@ static void wpa_driver_test_poll(void *eloop_ctx, void *timeout_ctx) } -static int wpa_driver_test_set_wpa(void *priv, int enabled) -{ - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); - return 0; -} - - static void wpa_driver_test_scan_timeout(void *eloop_ctx, void *timeout_ctx) { wpa_printf(MSG_DEBUG, "Scan timeout - try to get results"); @@ -1336,6 +1306,16 @@ static void wpa_driver_scan_dir(struct wpa_driver_test_data *drv, pos += wpa_snprintf_hex(pos, end - pos, drv->probe_req_ie, drv->probe_req_ie_len); } + if (drv->probe_req_ssid_len) { + /* Add SSID IE */ + ret = os_snprintf(pos, end - pos, "%02x%02x", + WLAN_EID_SSID, + (unsigned int) drv->probe_req_ssid_len); + if (ret >= 0 && ret < end - pos) + pos += ret; + pos += wpa_snprintf_hex(pos, end - pos, drv->probe_req_ssid, + drv->probe_req_ssid_len); + } end[-1] = '\0'; while ((dent = readdir(dir))) { @@ -1371,13 +1351,36 @@ static void wpa_driver_scan_dir(struct wpa_driver_test_data *drv, static int wpa_driver_test_scan(void *priv, struct wpa_driver_scan_params *params) { - struct wpa_driver_test_data *drv = priv; + struct test_driver_bss *dbss = priv; + struct wpa_driver_test_data *drv = dbss->drv; size_t i; wpa_printf(MSG_DEBUG, "%s: priv=%p", __func__, priv); + + os_free(drv->probe_req_ie); + if (params->extra_ies) { + drv->probe_req_ie = os_malloc(params->extra_ies_len); + if (drv->probe_req_ie == NULL) { + drv->probe_req_ie_len = 0; + return -1; + } + os_memcpy(drv->probe_req_ie, params->extra_ies, + params->extra_ies_len); + drv->probe_req_ie_len = params->extra_ies_len; + } else { + drv->probe_req_ie = NULL; + drv->probe_req_ie_len = 0; + } + for (i = 0; i < params->num_ssids; i++) wpa_hexdump(MSG_DEBUG, "Scan SSID", params->ssids[i].ssid, params->ssids[i].ssid_len); + drv->probe_req_ssid_len = 0; + if (params->num_ssids) { + os_memcpy(drv->probe_req_ssid, params->ssids[0].ssid, + params->ssids[0].ssid_len); + drv->probe_req_ssid_len = params->ssids[0].ssid_len; + } wpa_hexdump(MSG_DEBUG, "Scan extra IE(s)", params->extra_ies, params->extra_ies_len); @@ -1411,7 +1414,8 @@ static int wpa_driver_test_scan(void *priv, static struct wpa_scan_results * wpa_driver_test_get_scan_results2(void *priv) { - struct wpa_driver_test_data *drv = priv; + struct test_driver_bss *dbss = priv; + struct wpa_driver_test_data *drv = dbss->drv; struct wpa_scan_results *res; size_t i; @@ -1441,22 +1445,21 @@ static struct wpa_scan_results * wpa_driver_test_get_scan_results2(void *priv) } -static int wpa_driver_test_set_key(void *priv, wpa_alg alg, const u8 *addr, +static int wpa_driver_test_set_key(const char *ifname, void *priv, + enum wpa_alg alg, const u8 *addr, int key_idx, int set_tx, const u8 *seq, size_t seq_len, const u8 *key, size_t key_len) { - wpa_printf(MSG_DEBUG, "%s: priv=%p alg=%d key_idx=%d set_tx=%d", - __func__, priv, alg, key_idx, set_tx); - if (addr) { + wpa_printf(MSG_DEBUG, "%s: ifname=%s priv=%p alg=%d key_idx=%d " + "set_tx=%d", + __func__, ifname, priv, alg, key_idx, set_tx); + if (addr) wpa_printf(MSG_DEBUG, " addr=" MACSTR, MAC2STR(addr)); - } - if (seq) { + if (seq) wpa_hexdump(MSG_DEBUG, " seq", seq, seq_len); - } - if (key) { - wpa_hexdump(MSG_DEBUG, " key", key, key_len); - } + if (key) + wpa_hexdump_key(MSG_DEBUG, " key", key, key_len); return 0; } @@ -1480,12 +1483,14 @@ static int wpa_driver_update_mode(struct wpa_driver_test_data *drv, int ap) static int wpa_driver_test_associate( void *priv, struct wpa_driver_associate_params *params) { - struct wpa_driver_test_data *drv = priv; + struct test_driver_bss *dbss = priv; + struct wpa_driver_test_data *drv = dbss->drv; wpa_printf(MSG_DEBUG, "%s: priv=%p freq=%d pairwise_suite=%d " "group_suite=%d key_mgmt_suite=%d auth_alg=%d mode=%d", __func__, priv, params->freq, params->pairwise_suite, params->group_suite, params->key_mgmt_suite, params->auth_alg, params->mode); + wpa_driver_update_mode(drv, params->mode == IEEE80211_MODE_AP); if (params->bssid) { wpa_printf(MSG_DEBUG, " bssid=" MACSTR, MAC2STR(params->bssid)); @@ -1508,7 +1513,7 @@ static int wpa_driver_test_associate( wpa_driver_update_mode(drv, params->mode == IEEE80211_MODE_AP); drv->ibss = params->mode == IEEE80211_MODE_IBSS; - drv->privacy = params->key_mgmt_suite & + dbss->privacy = params->key_mgmt_suite & (WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_WPA_NONE | @@ -1517,7 +1522,7 @@ static int wpa_driver_test_associate( WPA_KEY_MGMT_IEEE8021X_SHA256 | WPA_KEY_MGMT_PSK_SHA256); if (params->wep_key_len[params->wep_tx_keyidx]) - drv->privacy = 1; + dbss->privacy = 1; #ifdef DRIVER_TEST_UNIX if (drv->test_dir && params->bssid && @@ -1532,8 +1537,20 @@ static int wpa_driver_test_associate( } #endif /* DRIVER_TEST_UNIX */ - if (drv->test_socket >= 0 && - (drv->hostapd_addr_set || drv->hostapd_addr_udp_set)) { + if (params->mode == IEEE80211_MODE_AP) { + os_memcpy(dbss->ssid, params->ssid, params->ssid_len); + dbss->ssid_len = params->ssid_len; + os_memcpy(dbss->bssid, drv->own_addr, ETH_ALEN); + if (params->wpa_ie && params->wpa_ie_len) { + dbss->ie = os_malloc(params->wpa_ie_len); + if (dbss->ie) { + os_memcpy(dbss->ie, params->wpa_ie, + params->wpa_ie_len); + dbss->ielen = params->wpa_ie_len; + } + } + } else if (drv->test_socket >= 0 && + (drv->hostapd_addr_set || drv->hostapd_addr_udp_set)) { char cmd[200], *pos, *end; int ret; end = cmd + sizeof(cmd); @@ -1567,19 +1584,20 @@ static int wpa_driver_test_associate( return -1; } - os_memcpy(drv->ssid, params->ssid, params->ssid_len); - drv->ssid_len = params->ssid_len; + os_memcpy(dbss->ssid, params->ssid, params->ssid_len); + dbss->ssid_len = params->ssid_len; } else { drv->associated = 1; if (params->mode == IEEE80211_MODE_IBSS) { - os_memcpy(drv->ssid, params->ssid, params->ssid_len); - drv->ssid_len = params->ssid_len; + os_memcpy(dbss->ssid, params->ssid, params->ssid_len); + dbss->ssid_len = params->ssid_len; if (params->bssid) - os_memcpy(drv->bssid, params->bssid, ETH_ALEN); + os_memcpy(dbss->bssid, params->bssid, + ETH_ALEN); else { - os_get_random(drv->bssid, ETH_ALEN); - drv->bssid[0] &= ~0x01; - drv->bssid[0] |= 0x02; + os_get_random(dbss->bssid, ETH_ALEN); + dbss->bssid[0] &= ~0x01; + dbss->bssid[0] |= 0x02; } } wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL); @@ -1591,17 +1609,17 @@ static int wpa_driver_test_associate( static int wpa_driver_test_get_bssid(void *priv, u8 *bssid) { - struct wpa_driver_test_data *drv = priv; - os_memcpy(bssid, drv->bssid, ETH_ALEN); + struct test_driver_bss *dbss = priv; + os_memcpy(bssid, dbss->bssid, ETH_ALEN); return 0; } static int wpa_driver_test_get_ssid(void *priv, u8 *ssid) { - struct wpa_driver_test_data *drv = priv; - os_memcpy(ssid, drv->ssid, 32); - return drv->ssid_len; + struct test_driver_bss *dbss = priv; + os_memcpy(ssid, dbss->ssid, 32); + return dbss->ssid_len; } @@ -1630,10 +1648,11 @@ static int wpa_driver_test_send_disassoc(struct wpa_driver_test_data *drv) static int wpa_driver_test_deauthenticate(void *priv, const u8 *addr, int reason_code) { - struct wpa_driver_test_data *drv = priv; + struct test_driver_bss *dbss = priv; + struct wpa_driver_test_data *drv = dbss->drv; wpa_printf(MSG_DEBUG, "%s addr=" MACSTR " reason_code=%d", __func__, MAC2STR(addr), reason_code); - os_memset(drv->bssid, 0, ETH_ALEN); + os_memset(dbss->bssid, 0, ETH_ALEN); drv->associated = 0; wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); return wpa_driver_test_send_disassoc(drv); @@ -1643,16 +1662,36 @@ static int wpa_driver_test_deauthenticate(void *priv, const u8 *addr, static int wpa_driver_test_disassociate(void *priv, const u8 *addr, int reason_code) { - struct wpa_driver_test_data *drv = priv; + struct test_driver_bss *dbss = priv; + struct wpa_driver_test_data *drv = dbss->drv; wpa_printf(MSG_DEBUG, "%s addr=" MACSTR " reason_code=%d", __func__, MAC2STR(addr), reason_code); - os_memset(drv->bssid, 0, ETH_ALEN); + os_memset(dbss->bssid, 0, ETH_ALEN); drv->associated = 0; wpa_supplicant_event(drv->ctx, EVENT_DISASSOC, NULL); return wpa_driver_test_send_disassoc(drv); } +static const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie) +{ + const u8 *end, *pos; + + pos = (const u8 *) (res + 1); + end = pos + res->ie_len; + + while (pos + 1 < end) { + if (pos + 2 + pos[1] > end) + break; + if (pos[0] == ie) + return pos; + pos += 2 + pos[1]; + } + + return NULL; +} + + static void wpa_driver_test_scanresp(struct wpa_driver_test_data *drv, struct sockaddr *from, socklen_t fromlen, @@ -1663,6 +1702,7 @@ static void wpa_driver_test_scanresp(struct wpa_driver_test_data *drv, size_t len; u8 *ie_pos, *ie_start, *ie_end; #define MAX_IE_LEN 1000 + const u8 *ds_params; wpa_printf(MSG_DEBUG, "test_driver: SCANRESP %s", data); if (drv->num_scanres >= MAX_SCAN_RESULTS) { @@ -1737,6 +1777,12 @@ static void wpa_driver_test_scanresp(struct wpa_driver_test_data *drv, res->caps |= IEEE80211_CAP_IBSS; } + ds_params = wpa_scan_get_ie(res, WLAN_EID_DS_PARAMS); + if (ds_params && ds_params[1] > 0) { + if (ds_params[2] >= 1 && ds_params[2] <= 13) + res->freq = 2407 + ds_params[2] * 5; + } + os_free(drv->scanres[drv->num_scanres]); drv->scanres[drv->num_scanres++] = res; } @@ -1747,8 +1793,12 @@ static void wpa_driver_test_assocresp(struct wpa_driver_test_data *drv, socklen_t fromlen, const char *data) { + struct test_driver_bss *bss; + + bss = dl_list_first(&drv->bss, struct test_driver_bss, list); + /* ASSOCRESP BSSID */ - if (hwaddr_aton(data, drv->bssid)) { + if (hwaddr_aton(data, bss->bssid)) { wpa_printf(MSG_DEBUG, "test_driver: invalid BSSID in " "assocresp"); } @@ -1778,17 +1828,20 @@ static void wpa_driver_test_eapol(struct wpa_driver_test_data *drv, socklen_t fromlen, const u8 *data, size_t data_len) { - const u8 *src = drv->bssid; + const u8 *src; + struct test_driver_bss *bss; + + bss = dl_list_first(&drv->bss, struct test_driver_bss, list); if (data_len > 14) { /* Skip Ethernet header */ src = data + ETH_ALEN; data += 14; data_len -= 14; - } -#ifndef HOSTAPD - wpa_supplicant_rx_eapol(drv->ctx, src, data, data_len); -#endif /* HOSTAPD */ + } else + src = bss->bssid; + + drv_event_eapol_rx(drv->ctx, src, data, data_len); } @@ -1797,11 +1850,62 @@ static void wpa_driver_test_mlme(struct wpa_driver_test_data *drv, socklen_t fromlen, const u8 *data, size_t data_len) { -#ifdef CONFIG_CLIENT_MLME - struct ieee80211_rx_status rx_status; - os_memset(&rx_status, 0, sizeof(rx_status)); - wpa_supplicant_sta_rx(drv->ctx, data, data_len, &rx_status); -#endif /* CONFIG_CLIENT_MLME */ + int freq = 0, own_freq; + union wpa_event_data event; + struct test_driver_bss *bss; + + bss = dl_list_first(&drv->bss, struct test_driver_bss, list); + if (data_len > 6 && os_memcmp(data, "freq=", 5) == 0) { + size_t pos; + for (pos = 5; pos < data_len; pos++) { + if (data[pos] == ' ') + break; + } + if (pos < data_len) { + freq = atoi((const char *) &data[5]); + wpa_printf(MSG_DEBUG, "test_driver(%s): MLME RX on " + "freq %d MHz", bss->ifname, freq); + pos++; + data += pos; + data_len -= pos; + } + } + + if (drv->remain_on_channel_freq) + own_freq = drv->remain_on_channel_freq; + else + own_freq = drv->current_freq; + + if (freq && own_freq && freq != own_freq) { + wpa_printf(MSG_DEBUG, "test_driver(%s): Ignore MLME RX on " + "another frequency %d MHz (own %d MHz)", + bss->ifname, freq, own_freq); + return; + } + + os_memset(&event, 0, sizeof(event)); + event.mlme_rx.buf = data; + event.mlme_rx.len = data_len; + event.mlme_rx.freq = freq; + wpa_supplicant_event(drv->ctx, EVENT_MLME_RX, &event); + + if (drv->probe_req_report && data_len >= 24) { + const struct ieee80211_mgmt *mgmt; + u16 fc; + + mgmt = (const struct ieee80211_mgmt *) data; + fc = le_to_host16(mgmt->frame_control); + if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && + WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_REQ) { + os_memset(&event, 0, sizeof(event)); + event.rx_probe_req.sa = mgmt->sa; + event.rx_probe_req.ie = mgmt->u.probe_req.variable; + event.rx_probe_req.ie_len = + data_len - (mgmt->u.probe_req.variable - data); + wpa_supplicant_event(drv->ctx, EVENT_RX_PROBE_REQ, + &event); + } + } } @@ -1812,6 +1916,9 @@ static void wpa_driver_test_scan_cmd(struct wpa_driver_test_data *drv, { char buf[512], *pos, *end; int ret; + struct test_driver_bss *bss; + + bss = dl_list_first(&drv->bss, struct test_driver_bss, list); /* data: optional [ STA-addr | ' ' | IEs(hex) ] */ @@ -1823,12 +1930,12 @@ static void wpa_driver_test_scan_cmd(struct wpa_driver_test_data *drv, /* reply: SCANRESP BSSID SSID IEs */ ret = snprintf(pos, end - pos, "SCANRESP " MACSTR " ", - MAC2STR(drv->bssid)); + MAC2STR(bss->bssid)); if (ret < 0 || ret >= end - pos) return; pos += ret; pos += wpa_snprintf_hex(pos, end - pos, - drv->ssid, drv->ssid_len); + bss->ssid, bss->ssid_len); ret = snprintf(pos, end - pos, " "); if (ret < 0 || ret >= end - pos) return; @@ -1836,7 +1943,7 @@ static void wpa_driver_test_scan_cmd(struct wpa_driver_test_data *drv, pos += wpa_snprintf_hex(pos, end - pos, drv->assoc_wpa_ie, drv->assoc_wpa_ie_len); - if (drv->privacy) { + if (bss->privacy) { ret = snprintf(pos, end - pos, " PRIVACY"); if (ret < 0 || ret >= end - pos) return; @@ -1916,32 +2023,34 @@ static void * wpa_driver_test_init2(void *ctx, const char *ifname, void *global_priv) { struct wpa_driver_test_data *drv; + struct wpa_driver_test_global *global = global_priv; + struct test_driver_bss *bss; - drv = os_zalloc(sizeof(*drv)); + drv = test_alloc_data(ctx, ifname); if (drv == NULL) return NULL; + bss = dl_list_first(&drv->bss, struct test_driver_bss, list); drv->global = global_priv; - drv->ctx = ctx; drv->test_socket = -1; /* Set dummy BSSID and SSID for testing. */ - drv->bssid[0] = 0x02; - drv->bssid[1] = 0x00; - drv->bssid[2] = 0x00; - drv->bssid[3] = 0x00; - drv->bssid[4] = 0x00; - drv->bssid[5] = 0x01; - os_memcpy(drv->ssid, "test", 5); - drv->ssid_len = 4; + bss->bssid[0] = 0x02; + bss->bssid[1] = 0x00; + bss->bssid[2] = 0x00; + bss->bssid[3] = 0x00; + bss->bssid[4] = 0x00; + bss->bssid[5] = 0x01; + os_memcpy(bss->ssid, "test", 5); + bss->ssid_len = 4; + + if (global->bss_add_used) { + os_memcpy(drv->own_addr, global->req_addr, ETH_ALEN); + global->bss_add_used = 0; + } - /* Generate a MAC address to help testing with multiple STAs */ - drv->own_addr[0] = 0x02; /* locally administered */ - sha1_prf((const u8 *) ifname, os_strlen(ifname), - "wpa_supplicant test mac addr generation", - NULL, 0, drv->own_addr + 1, ETH_ALEN - 1); eloop_register_timeout(1, 0, wpa_driver_test_poll, drv, NULL); - return drv; + return bss; } @@ -1963,9 +2072,9 @@ static void wpa_driver_test_close_test_socket(struct wpa_driver_test_data *drv) static void wpa_driver_test_deinit(void *priv) { - struct wpa_driver_test_data *drv = priv; + struct test_driver_bss *dbss = priv; + struct wpa_driver_test_data *drv = dbss->drv; struct test_client_socket *cli, *prev; - struct test_driver_bss *bss, *prev_bss; int i; cli = drv->cli; @@ -1977,26 +2086,22 @@ static void wpa_driver_test_deinit(void *priv) #ifdef HOSTAPD /* There should be only one BSS remaining at this point. */ - if (drv->bss == NULL) - wpa_printf(MSG_ERROR, "%s: drv->bss == NULL", __func__); - else if (drv->bss->next) - wpa_printf(MSG_ERROR, "%s: drv->bss->next != NULL", __func__); + if (dl_list_len(&drv->bss) != 1) + wpa_printf(MSG_ERROR, "%s: %u remaining BSS entries", + __func__, dl_list_len(&drv->bss)); #endif /* HOSTAPD */ - bss = drv->bss; - while (bss) { - prev_bss = bss; - bss = bss->next; - test_driver_free_bss(prev_bss); - } + test_driver_free_bsses(drv); wpa_driver_test_close_test_socket(drv); eloop_cancel_timeout(wpa_driver_test_scan_timeout, drv, drv->ctx); eloop_cancel_timeout(wpa_driver_test_poll, drv, NULL); + eloop_cancel_timeout(test_remain_on_channel_timeout, drv, NULL); os_free(drv->test_dir); for (i = 0; i < MAX_SCAN_RESULTS; i++) os_free(drv->scanres[i]); os_free(drv->probe_req_ie); + wpa_trace_remove_ref(drv, ctx, drv->ctx); os_free(drv); } @@ -2103,7 +2208,8 @@ static int wpa_driver_test_attach_udp(struct wpa_driver_test_data *drv, static int wpa_driver_test_set_param(void *priv, const char *param) { - struct wpa_driver_test_data *drv = priv; + struct test_driver_bss *dbss = priv; + struct wpa_driver_test_data *drv = dbss->drv; const char *pos; wpa_printf(MSG_DEBUG, "%s: param='%s'", __func__, param); @@ -2180,7 +2286,8 @@ static int wpa_driver_test_set_param(void *priv, const char *param) static const u8 * wpa_driver_test_get_mac_addr(void *priv) { - struct wpa_driver_test_data *drv = priv; + struct test_driver_bss *dbss = priv; + struct wpa_driver_test_data *drv = dbss->drv; wpa_printf(MSG_DEBUG, "%s", __func__); return drv->own_addr; } @@ -2189,7 +2296,8 @@ static const u8 * wpa_driver_test_get_mac_addr(void *priv) static int wpa_driver_test_send_eapol(void *priv, const u8 *dest, u16 proto, const u8 *data, size_t data_len) { - struct wpa_driver_test_data *drv = priv; + struct test_driver_bss *dbss = priv; + struct wpa_driver_test_data *drv = dbss->drv; char *msg; size_t msg_len; struct l2_ethhdr eth; @@ -2214,7 +2322,7 @@ static int wpa_driver_test_send_eapol(void *priv, const u8 *dest, u16 proto, os_memcpy(msg + 6, ð, sizeof(eth)); os_memcpy(msg + 6 + sizeof(eth), data, data_len); - if (os_memcmp(dest, drv->bssid, ETH_ALEN) == 0 || + if (os_memcmp(dest, dbss->bssid, ETH_ALEN) == 0 || drv->test_dir == NULL) { if (drv->hostapd_addr_udp_set) { addr = (struct sockaddr *) &drv->hostapd_addr_udp; @@ -2261,7 +2369,8 @@ static int wpa_driver_test_send_eapol(void *priv, const u8 *dest, u16 proto, static int wpa_driver_test_get_capa(void *priv, struct wpa_driver_capa *capa) { - struct wpa_driver_test_data *drv = priv; + struct test_driver_bss *dbss = priv; + struct wpa_driver_test_data *drv = dbss->drv; os_memset(capa, 0, sizeof(*capa)); capa->key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA | WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | @@ -2280,7 +2389,11 @@ static int wpa_driver_test_get_capa(void *priv, struct wpa_driver_capa *capa) if (drv->use_mlme) capa->flags |= WPA_DRIVER_FLAGS_USER_SPACE_MLME; capa->flags |= WPA_DRIVER_FLAGS_AP; + capa->flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT; + capa->flags |= WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE; + capa->flags |= WPA_DRIVER_FLAGS_P2P_CAPABLE; capa->max_scan_ssids = 2; + capa->max_remain_on_chan = 60000; return 0; } @@ -2302,11 +2415,15 @@ static int wpa_driver_test_mlme_setprotection(void *priv, const u8 *addr, } -static int wpa_driver_test_set_channel(void *priv, hostapd_hw_mode phymode, +static int wpa_driver_test_set_channel(void *priv, + enum hostapd_hw_mode phymode, int chan, int freq) { + struct test_driver_bss *dbss = priv; + struct wpa_driver_test_data *drv = dbss->drv; wpa_printf(MSG_DEBUG, "%s: phymode=%d chan=%d freq=%d", __func__, phymode, chan, freq); + drv->current_freq = freq; return 0; } @@ -2342,28 +2459,6 @@ static int wpa_driver_test_set_bssid(void *priv, const u8 *bssid) } -static int wpa_driver_test_set_probe_req_ie(void *priv, const u8 *ies, - size_t ies_len) -{ - struct wpa_driver_test_data *drv = priv; - - os_free(drv->probe_req_ie); - if (ies) { - drv->probe_req_ie = os_malloc(ies_len); - if (drv->probe_req_ie == NULL) { - drv->probe_req_ie_len = 0; - return -1; - } - os_memcpy(drv->probe_req_ie, ies, ies_len); - drv->probe_req_ie_len = ies_len; - } else { - drv->probe_req_ie = NULL; - drv->probe_req_ie_len = 0; - } - return 0; -} - - static void * wpa_driver_test_global_init(void) { struct wpa_driver_test_global *global; @@ -2407,6 +2502,7 @@ static struct hostapd_hw_modes * wpa_driver_test_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags) { struct hostapd_hw_modes *modes; + size_t i; *num_modes = 3; *flags = 0; @@ -2414,52 +2510,72 @@ wpa_driver_test_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags) if (modes == NULL) return NULL; modes[0].mode = HOSTAPD_MODE_IEEE80211G; - modes[0].num_channels = 1; - modes[0].num_rates = 1; - modes[0].channels = os_zalloc(sizeof(struct hostapd_channel_data)); - modes[0].rates = os_zalloc(sizeof(struct hostapd_rate_data)); + modes[0].num_channels = 11; + modes[0].num_rates = 12; + modes[0].channels = + os_zalloc(11 * sizeof(struct hostapd_channel_data)); + modes[0].rates = os_zalloc(modes[0].num_rates * sizeof(int)); if (modes[0].channels == NULL || modes[0].rates == NULL) goto fail; - modes[0].channels[0].chan = 1; - modes[0].channels[0].freq = 2412; - modes[0].channels[0].flag = 0; - modes[0].rates[0].rate = 10; - modes[0].rates[0].flags = HOSTAPD_RATE_BASIC | HOSTAPD_RATE_SUPPORTED | - HOSTAPD_RATE_CCK | HOSTAPD_RATE_MANDATORY; + for (i = 0; i < 11; i++) { + modes[0].channels[i].chan = i + 1; + modes[0].channels[i].freq = 2412 + 5 * i; + modes[0].channels[i].flag = 0; + } + modes[0].rates[0] = 10; + modes[0].rates[1] = 20; + modes[0].rates[2] = 55; + modes[0].rates[3] = 110; + modes[0].rates[4] = 60; + modes[0].rates[5] = 90; + modes[0].rates[6] = 120; + modes[0].rates[7] = 180; + modes[0].rates[8] = 240; + modes[0].rates[9] = 360; + modes[0].rates[10] = 480; + modes[0].rates[11] = 540; modes[1].mode = HOSTAPD_MODE_IEEE80211B; - modes[1].num_channels = 1; - modes[1].num_rates = 1; - modes[1].channels = os_zalloc(sizeof(struct hostapd_channel_data)); - modes[1].rates = os_zalloc(sizeof(struct hostapd_rate_data)); + modes[1].num_channels = 11; + modes[1].num_rates = 4; + modes[1].channels = + os_zalloc(11 * sizeof(struct hostapd_channel_data)); + modes[1].rates = os_zalloc(modes[1].num_rates * sizeof(int)); if (modes[1].channels == NULL || modes[1].rates == NULL) goto fail; - modes[1].channels[0].chan = 1; - modes[1].channels[0].freq = 2412; - modes[1].channels[0].flag = 0; - modes[1].rates[0].rate = 10; - modes[1].rates[0].flags = HOSTAPD_RATE_BASIC | HOSTAPD_RATE_SUPPORTED | - HOSTAPD_RATE_CCK | HOSTAPD_RATE_MANDATORY; + for (i = 0; i < 11; i++) { + modes[1].channels[i].chan = i + 1; + modes[1].channels[i].freq = 2412 + 5 * i; + modes[1].channels[i].flag = 0; + } + modes[1].rates[0] = 10; + modes[1].rates[1] = 20; + modes[1].rates[2] = 55; + modes[1].rates[3] = 110; modes[2].mode = HOSTAPD_MODE_IEEE80211A; modes[2].num_channels = 1; - modes[2].num_rates = 1; + modes[2].num_rates = 8; modes[2].channels = os_zalloc(sizeof(struct hostapd_channel_data)); - modes[2].rates = os_zalloc(sizeof(struct hostapd_rate_data)); + modes[2].rates = os_zalloc(modes[2].num_rates * sizeof(int)); if (modes[2].channels == NULL || modes[2].rates == NULL) goto fail; modes[2].channels[0].chan = 60; modes[2].channels[0].freq = 5300; modes[2].channels[0].flag = 0; - modes[2].rates[0].rate = 60; - modes[2].rates[0].flags = HOSTAPD_RATE_BASIC | HOSTAPD_RATE_SUPPORTED | - HOSTAPD_RATE_MANDATORY; + modes[2].rates[0] = 60; + modes[2].rates[1] = 90; + modes[2].rates[2] = 120; + modes[2].rates[3] = 180; + modes[2].rates[4] = 240; + modes[2].rates[5] = 360; + modes[2].rates[6] = 480; + modes[2].rates[7] = 540; return modes; fail: if (modes) { - size_t i; for (i = 0; i < *num_modes; i++) { os_free(modes[i].channels); os_free(modes[i].rates); @@ -2470,10 +2586,126 @@ fail: } -static int wpa_driver_test_set_mode(void *priv, int mode) +static int wpa_driver_test_set_freq(void *priv, + struct hostapd_freq_params *freq) +{ + struct test_driver_bss *dbss = priv; + struct wpa_driver_test_data *drv = dbss->drv; + wpa_printf(MSG_DEBUG, "test: set_freq %u MHz", freq->freq); + drv->current_freq = freq->freq; + return 0; +} + + +static int wpa_driver_test_send_action(void *priv, unsigned int freq, + const u8 *dst, const u8 *src, + const u8 *bssid, + const u8 *data, size_t data_len) +{ + struct test_driver_bss *dbss = priv; + struct wpa_driver_test_data *drv = dbss->drv; + int ret = -1; + u8 *buf; + struct ieee80211_hdr *hdr; + + wpa_printf(MSG_DEBUG, "test: Send Action frame"); + + if ((drv->remain_on_channel_freq && + freq != drv->remain_on_channel_freq) || + (drv->remain_on_channel_freq == 0 && + freq != (unsigned int) drv->current_freq)) { + wpa_printf(MSG_DEBUG, "test: Reject Action frame TX on " + "unexpected channel: freq=%u MHz (current_freq=%u " + "MHz, remain-on-channel freq=%u MHz)", + freq, drv->current_freq, + drv->remain_on_channel_freq); + return -1; + } + + buf = os_zalloc(24 + data_len); + if (buf == NULL) + return ret; + os_memcpy(buf + 24, data, data_len); + hdr = (struct ieee80211_hdr *) buf; + hdr->frame_control = + IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_ACTION); + os_memcpy(hdr->addr1, dst, ETH_ALEN); + os_memcpy(hdr->addr2, src, ETH_ALEN); + os_memcpy(hdr->addr3, bssid, ETH_ALEN); + + ret = wpa_driver_test_send_mlme(priv, buf, 24 + data_len); + os_free(buf); + return ret; +} + + +static void test_remain_on_channel_timeout(void *eloop_ctx, void *timeout_ctx) { - struct wpa_driver_test_data *drv = priv; - return wpa_driver_update_mode(drv, mode == IEEE80211_MODE_AP); + struct wpa_driver_test_data *drv = eloop_ctx; + union wpa_event_data data; + + wpa_printf(MSG_DEBUG, "test: Remain-on-channel timeout"); + + os_memset(&data, 0, sizeof(data)); + data.remain_on_channel.freq = drv->remain_on_channel_freq; + data.remain_on_channel.duration = drv->remain_on_channel_duration; + wpa_supplicant_event(drv->ctx, EVENT_CANCEL_REMAIN_ON_CHANNEL, &data); + + drv->remain_on_channel_freq = 0; +} + + +static int wpa_driver_test_remain_on_channel(void *priv, unsigned int freq, + unsigned int duration) +{ + struct test_driver_bss *dbss = priv; + struct wpa_driver_test_data *drv = dbss->drv; + union wpa_event_data data; + + wpa_printf(MSG_DEBUG, "%s(freq=%u, duration=%u)", + __func__, freq, duration); + if (drv->remain_on_channel_freq && + drv->remain_on_channel_freq != freq) { + wpa_printf(MSG_DEBUG, "test: Refuse concurrent " + "remain_on_channel request"); + return -1; + } + + drv->remain_on_channel_freq = freq; + drv->remain_on_channel_duration = duration; + eloop_cancel_timeout(test_remain_on_channel_timeout, drv, NULL); + eloop_register_timeout(duration / 1000, (duration % 1000) * 1000, + test_remain_on_channel_timeout, drv, NULL); + + os_memset(&data, 0, sizeof(data)); + data.remain_on_channel.freq = freq; + data.remain_on_channel.duration = duration; + wpa_supplicant_event(drv->ctx, EVENT_REMAIN_ON_CHANNEL, &data); + + return 0; +} + + +static int wpa_driver_test_cancel_remain_on_channel(void *priv) +{ + struct test_driver_bss *dbss = priv; + struct wpa_driver_test_data *drv = dbss->drv; + wpa_printf(MSG_DEBUG, "%s", __func__); + if (!drv->remain_on_channel_freq) + return -1; + drv->remain_on_channel_freq = 0; + eloop_cancel_timeout(test_remain_on_channel_timeout, drv, NULL); + return 0; +} + + +static int wpa_driver_test_probe_req_report(void *priv, int report) +{ + struct test_driver_bss *dbss = priv; + struct wpa_driver_test_data *drv = dbss->drv; + wpa_printf(MSG_DEBUG, "%s(report=%d)", __func__, report); + drv->probe_req_report = report; + return 0; } @@ -2488,23 +2720,17 @@ const struct wpa_driver_ops wpa_driver_test_ops = { .sta_deauth = test_driver_sta_deauth, .sta_disassoc = test_driver_sta_disassoc, .get_hw_feature_data = wpa_driver_test_get_hw_feature_data, - .bss_add = test_driver_bss_add, - .bss_remove = test_driver_bss_remove, .if_add = test_driver_if_add, - .if_update = test_driver_if_update, .if_remove = test_driver_if_remove, .valid_bss_mask = test_driver_valid_bss_mask, .hapd_set_ssid = test_driver_set_ssid, .set_privacy = test_driver_set_privacy, - .hapd_set_key = test_driver_set_key, .set_sta_vlan = test_driver_set_sta_vlan, .sta_add = test_driver_sta_add, .send_ether = test_driver_send_ether, - .set_wps_beacon_ie = test_driver_set_wps_beacon_ie, - .set_wps_probe_resp_ie = test_driver_set_wps_probe_resp_ie, + .set_ap_wps_ie = test_driver_set_ap_wps_ie, .get_bssid = wpa_driver_test_get_bssid, .get_ssid = wpa_driver_test_get_ssid, - .set_wpa = wpa_driver_test_set_wpa, .set_key = wpa_driver_test_set_key, .deinit = wpa_driver_test_deinit, .set_param = wpa_driver_test_set_param, @@ -2521,11 +2747,14 @@ const struct wpa_driver_ops wpa_driver_test_ops = { .mlme_add_sta = wpa_driver_test_mlme_add_sta, .mlme_remove_sta = wpa_driver_test_mlme_remove_sta, .get_scan_results2 = wpa_driver_test_get_scan_results2, - .set_probe_req_ie = wpa_driver_test_set_probe_req_ie, .global_init = wpa_driver_test_global_init, .global_deinit = wpa_driver_test_global_deinit, .init2 = wpa_driver_test_init2, .get_interfaces = wpa_driver_test_get_interfaces, .scan2 = wpa_driver_test_scan, - .set_mode = wpa_driver_test_set_mode, + .set_freq = wpa_driver_test_set_freq, + .send_action = wpa_driver_test_send_action, + .remain_on_channel = wpa_driver_test_remain_on_channel, + .cancel_remain_on_channel = wpa_driver_test_cancel_remain_on_channel, + .probe_req_report = wpa_driver_test_probe_req_report, };