From e33bbd8f4d4ffb69eeb7347764895abb9b8cd115 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 12 Dec 2008 21:35:22 +0200 Subject: [PATCH] driver_test: Optional support for using UDP socket driver_test can now be used either over UNIX domain socket or UDP socket. This makes it possible to run the test over network and makes it easier to port driver_test to Windows. hostapd configuration: test_socket=UDP: wpa_supplicant configuration: driver_param=test_udp=: --- hostapd/ChangeLog | 1 + hostapd/driver_test.c | 45 ++++++++++++------ src/drivers/driver_test.c | 96 ++++++++++++++++++++++++++++++++++++--- wpa_supplicant/ChangeLog | 1 + 4 files changed, 123 insertions(+), 20 deletions(-) diff --git a/hostapd/ChangeLog b/hostapd/ChangeLog index 586eb5e97..7ffe9c668 100644 --- a/hostapd/ChangeLog +++ b/hostapd/ChangeLog @@ -16,6 +16,7 @@ ChangeLog for hostapd * fixed WEP authentication (both Open System and Shared Key) with mac80211 * added support for EAP-AKA' (draft-arkko-eap-aka-kdf) + * added support for using driver_test over UDP socket 2008-11-23 - v0.6.6 * added a new configuration option, wpa_ptk_rekey, that can be used to diff --git a/hostapd/driver_test.c b/hostapd/driver_test.c index 397539ebb..bb4224b84 100644 --- a/hostapd/driver_test.c +++ b/hostapd/driver_test.c @@ -61,6 +61,7 @@ struct test_driver_data { struct test_driver_bss *bss; char *socket_dir; char *own_socket_path; + int udp_port; }; @@ -1142,7 +1143,10 @@ static int test_driver_sta_add(const char *ifname, void *priv, const u8 *addr, static void * test_driver_init(struct hostapd_data *hapd) { struct test_driver_data *drv; - struct sockaddr_un addr; + struct sockaddr_un addr_un; + struct sockaddr_in addr_in; + struct sockaddr *addr; + socklen_t alen; drv = os_zalloc(sizeof(struct test_driver_data)); if (drv == NULL) { @@ -1169,7 +1173,8 @@ static void * test_driver_init(struct hostapd_data *hapd) memcpy(drv->bss->bssid, hapd->own_addr, ETH_ALEN); if (hapd->conf->test_socket) { - if (strlen(hapd->conf->test_socket) >= sizeof(addr.sun_path)) { + if (strlen(hapd->conf->test_socket) >= + sizeof(addr_un.sun_path)) { printf("Too long test_socket path\n"); test_driver_free_priv(drv); return NULL; @@ -1184,30 +1189,43 @@ static void * test_driver_init(struct hostapd_data *hapd) hapd->conf->test_socket + 4, MAC2STR(hapd->own_addr)); } + } else if (strncmp(hapd->conf->test_socket, "UDP:", 4) == 0) { + drv->udp_port = atoi(hapd->conf->test_socket + 4); } else { drv->own_socket_path = strdup(hapd->conf->test_socket); } - if (drv->own_socket_path == NULL) { + if (drv->own_socket_path == NULL && drv->udp_port == 0) { test_driver_free_priv(drv); return NULL; } - drv->test_socket = socket(PF_UNIX, SOCK_DGRAM, 0); + drv->test_socket = socket(drv->udp_port ? PF_INET : PF_UNIX, + SOCK_DGRAM, 0); if (drv->test_socket < 0) { - perror("socket(PF_UNIX)"); + perror("socket"); test_driver_free_priv(drv); return NULL; } - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - os_strlcpy(addr.sun_path, drv->own_socket_path, - sizeof(addr.sun_path)); - if (bind(drv->test_socket, (struct sockaddr *) &addr, - sizeof(addr)) < 0) { + if (drv->udp_port) { + os_memset(&addr_in, 0, sizeof(addr_in)); + addr_in.sin_family = AF_INET; + addr_in.sin_port = htons(drv->udp_port); + addr = (struct sockaddr *) &addr_in; + alen = sizeof(addr_in); + } else { + os_memset(&addr_un, 0, sizeof(addr_un)); + addr_un.sun_family = AF_UNIX; + os_strlcpy(addr_un.sun_path, drv->own_socket_path, + sizeof(addr_un.sun_path)); + addr = (struct sockaddr *) &addr_un; + alen = sizeof(addr_un); + } + if (bind(drv->test_socket, addr, alen) < 0) { perror("bind(PF_UNIX)"); close(drv->test_socket); - unlink(drv->own_socket_path); + if (drv->own_socket_path) + unlink(drv->own_socket_path); test_driver_free_priv(drv); return NULL; } @@ -1235,7 +1253,8 @@ static void test_driver_deinit(void *priv) if (drv->test_socket >= 0) { eloop_unregister_read_sock(drv->test_socket); close(drv->test_socket); - unlink(drv->own_socket_path); + if (drv->own_socket_path) + unlink(drv->own_socket_path); } /* There should be only one BSS remaining at this point. */ diff --git a/src/drivers/driver_test.c b/src/drivers/driver_test.c index f10c06201..01c57d1d1 100644 --- a/src/drivers/driver_test.c +++ b/src/drivers/driver_test.c @@ -31,6 +31,8 @@ struct wpa_driver_test_data { int test_socket; struct sockaddr_un hostapd_addr; int hostapd_addr_set; + struct sockaddr_in hostapd_addr_udp; + int hostapd_addr_udp_set; char *own_socket_path; char *test_dir; u8 bssid[ETH_ALEN]; @@ -145,6 +147,13 @@ static int wpa_driver_test_scan(void *priv, const u8 *ssid, size_t ssid_len) perror("sendto(test_socket)"); } + if (drv->test_socket >= 0 && drv->hostapd_addr_udp_set && + sendto(drv->test_socket, "SCAN", 4, 0, + (struct sockaddr *) &drv->hostapd_addr_udp, + sizeof(drv->hostapd_addr_udp)) < 0) { + perror("sendto(test_socket)"); + } + eloop_cancel_timeout(wpa_driver_test_scan_timeout, drv, drv->ctx); eloop_register_timeout(1, 0, wpa_driver_test_scan_timeout, drv, drv->ctx); @@ -242,7 +251,8 @@ static int wpa_driver_test_associate( drv->hostapd_addr_set = 1; } - if (drv->test_socket >= 0 && drv->hostapd_addr_set) { + 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); @@ -259,12 +269,20 @@ static int wpa_driver_test_associate( pos += wpa_snprintf_hex(pos, end - pos, params->wpa_ie, params->wpa_ie_len); end[-1] = '\0'; - if (sendto(drv->test_socket, cmd, os_strlen(cmd), 0, + if (drv->hostapd_addr_set && + sendto(drv->test_socket, cmd, os_strlen(cmd), 0, (struct sockaddr *) &drv->hostapd_addr, sizeof(drv->hostapd_addr)) < 0) { perror("sendto(test_socket)"); return -1; } + if (drv->hostapd_addr_udp_set && + sendto(drv->test_socket, cmd, os_strlen(cmd), 0, + (struct sockaddr *) &drv->hostapd_addr_udp, + sizeof(drv->hostapd_addr_udp)) < 0) { + perror("sendto(test_socket)"); + return -1; + } os_memcpy(drv->ssid, params->ssid, params->ssid_len); drv->ssid_len = params->ssid_len; @@ -640,6 +658,50 @@ static int wpa_driver_test_attach(struct wpa_driver_test_data *drv, } +static int wpa_driver_test_attach_udp(struct wpa_driver_test_data *drv, + char *dst) +{ + char *pos; + + pos = os_strchr(dst, ':'); + if (pos == NULL) + return -1; + *pos++ = '\0'; + wpa_printf(MSG_DEBUG, "%s: addr=%s port=%s", __func__, dst, pos); + + drv->test_socket = socket(PF_INET, SOCK_DGRAM, 0); + if (drv->test_socket < 0) { + perror("socket(PF_INET)"); + return -1; + } + + os_memset(&drv->hostapd_addr_udp, 0, sizeof(drv->hostapd_addr_udp)); + drv->hostapd_addr_udp.sin_family = AF_INET; +#if defined(CONFIG_NATIVE_WINDOWS) || defined(CONFIG_ANSI_C_EXTRA) + { + int a[4]; + u8 *pos; + sscanf(dst, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]); + pos = (u8 *) &drv->hostapd_addr_udp.sin_addr; + *pos++ = a[0]; + *pos++ = a[1]; + *pos++ = a[2]; + *pos++ = a[3]; + } +#else /* CONFIG_NATIVE_WINDOWS or CONFIG_ANSI_C_EXTRA */ + inet_aton(dst, &drv->hostapd_addr_udp.sin_addr); +#endif /* CONFIG_NATIVE_WINDOWS or CONFIG_ANSI_C_EXTRA */ + drv->hostapd_addr_udp.sin_port = htons(atoi(pos)); + + drv->hostapd_addr_udp_set = 1; + + eloop_register_read_sock(drv->test_socket, + wpa_driver_test_receive_unix, drv, NULL); + + return 0; +} + + static int wpa_driver_test_set_param(void *priv, const char *param) { struct wpa_driver_test_data *drv = priv; @@ -677,9 +739,24 @@ static int wpa_driver_test_set_param(void *priv, const char *param) end = os_strchr(drv->test_dir, ' '); if (end) *end = '\0'; - wpa_driver_test_attach(drv, drv->test_dir); - } else - wpa_driver_test_attach(drv, NULL); + if (wpa_driver_test_attach(drv, drv->test_dir)) + return -1; + } else { + pos = os_strstr(param, "test_udp="); + if (pos) { + char *dst, *epos; + dst = os_strdup(pos + 9); + if (dst == NULL) + return -1; + epos = os_strchr(dst, ' '); + if (epos) + *epos = '\0'; + if (wpa_driver_test_attach_udp(drv, dst)) + return -1; + os_free(dst); + } else if (wpa_driver_test_attach(drv, NULL)) + return -1; + } if (os_strstr(param, "use_associnfo=1")) { wpa_printf(MSG_DEBUG, "test_driver: Use AssocInfo events"); @@ -733,8 +810,13 @@ static int wpa_driver_test_send_eapol(void *priv, const u8 *dest, u16 proto, msg.msg_iovlen = 3; if (os_memcmp(dest, drv->bssid, ETH_ALEN) == 0 || drv->test_dir == NULL) { - msg.msg_name = &drv->hostapd_addr; - msg.msg_namelen = sizeof(drv->hostapd_addr); + if (drv->hostapd_addr_udp_set) { + msg.msg_name = &drv->hostapd_addr_udp; + msg.msg_namelen = sizeof(drv->hostapd_addr_udp); + } else { + msg.msg_name = &drv->hostapd_addr; + msg.msg_namelen = sizeof(drv->hostapd_addr); + } } else { struct stat st; os_memset(&addr, 0, sizeof(addr)); diff --git a/wpa_supplicant/ChangeLog b/wpa_supplicant/ChangeLog index 34dc8e442..2ba86a506 100644 --- a/wpa_supplicant/ChangeLog +++ b/wpa_supplicant/ChangeLog @@ -11,6 +11,7 @@ ChangeLog for wpa_supplicant file); new wpa_cli commands wps_pin, wps_pbc, and wps_reg are used to manage WPS negotiation; see README-WPS for more details * added support for EAP-AKA' (draft-arkko-eap-aka-kdf) + * added support for using driver_test over UDP socket 2008-11-23 - v0.6.6 * added Milenage SIM/USIM emulator for EAP-SIM/EAP-AKA