Browse Source

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:<listen port>
wpa_supplicant configuration: driver_param=test_udp=<dst IP addr>:<port>
Jouni Malinen 16 years ago
parent
commit
e33bbd8f4d
4 changed files with 123 additions and 20 deletions
  1. 1 0
      hostapd/ChangeLog
  2. 32 13
      hostapd/driver_test.c
  3. 89 7
      src/drivers/driver_test.c
  4. 1 0
      wpa_supplicant/ChangeLog

+ 1 - 0
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

+ 32 - 13
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. */

+ 89 - 7
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));

+ 1 - 0
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