[PATCH]: wait_for_interface poll on driver interface initialization

Kel Modderman kel at otaku42.de
Sun Jan 13 04:41:21 EST 2008


The attached patch attempts to fix the wait_for_interface option by
reorganizing wpa_supplicant_driver_init() and wpa_supplicant_init_iface2() so
that polling is done before the driver interface is prepared for work.

Currently, the driver interface is prepared before wait_for_interface is
considered, resulting in broken -w command line option, and ignoring any driver
parameters. See the following debug output that was captured with an atheros
cardbus card using madwifi driver:

# wext driver interface - not correctly setup for scanning when network
# interface exists after waiting.
#
# /sbin/wpa_supplicant -w -dd -P /var/run/wpa_supplicant.ath0.pid -i ath0 -D wext -c /etc/wpa_supplicant/conf.ath0
<snip>
Initializing interface (2) 'ath0'
EAPOL: SUPP_PAE entering state DISCONNECTED
EAPOL: KEY_RX entering state NO_KEY_RECEIVE
EAPOL: SUPP_BE entering state INITIALIZE
EAP: EAP entering state DISABLED
EAPOL: External notification - portEnabled=0
EAPOL: External notification - portValid=0
ioctl[SIOCGIFFLAGS]: No such device
Could not get interface 'ath0' flags
ioctl[SIOCSIWPMKSA]: No such device
ioctl[SIOCSIWMODE]: No such device
Could not configure driver to use managed mode
ioctl[SIOCGIWRANGE]: No such device
WEXT: Operstate: linkmode=1, operstate=5
ioctl[SIOCGIFINDEX]: No such device
Waiting for interface..
ioctl[SIOCGIFINDEX]: No such device
Waiting for interface..
ioctl[SIOCGIFINDEX]: No such device
Waiting for interface..
Own MAC address: 00:0f:b5:a4:8d:01
wpa_driver_wext_set_wpa
wpa_driver_wext_set_key: alg=0 key_idx=0 set_tx=0 seq_len=0 key_len=0
wpa_driver_wext_set_key: alg=0 key_idx=1 set_tx=0 seq_len=0 key_len=0
wpa_driver_wext_set_key: alg=0 key_idx=2 set_tx=0 seq_len=0 key_len=0
wpa_driver_wext_set_key: alg=0 key_idx=3 set_tx=0 seq_len=0 key_len=0
wpa_driver_wext_set_countermeasures
wpa_driver_wext_set_drop_unencrypted
RSN: flushing PMKID list in the driver
Setting scan request: 0 sec 100000 usec
Using existing control interface directory.
ctrl_interface_group=108 (from group name 'netdev')
Added interface ath0
EAPOL: disable timer tick
Ignore event for foreign ifindex 6
Ignore event for foreign ifindex 7
l2_packet_receive - recvfrom: Network is down
State: DISCONNECTED -> SCANNING
Starting AP scan (broadcast SSID)
Trying to get current scan results first without requesting a new scan to speed up initial association
Received 0 bytes of scan results (0 BSSes)
Selecting BSS from priority group 0
Try to find WPA-enabled AP
Try to find non-WPA AP
No suitable AP found.
Setting scan request: 0 sec 0 usec
Starting AP scan (broadcast SSID)
ioctl[SIOCSIWSCAN]: Network is down
Scan requested (ret=-1) - scan timeout 5 seconds
Failed to initiate AP scan.
Setting scan request: 10 sec 0 usec
Scan timeout - try to get results
Received 0 bytes of scan results (0 BSSes)
Selecting BSS from priority group 0
Try to find WPA-enabled AP
Try to find non-WPA AP
No suitable AP found.
Setting scan request: 5 sec 0 usec
Starting AP scan (broadcast SSID)
ioctl[SIOCSIWSCAN]: Network is down
Scan requested (ret=-1) - scan timeout 5 seconds
Failed to initiate AP scan.
Setting scan request: 10 sec 0 usec
Scan timeout - try to get results
Received 0 bytes of scan results (0 BSSes)
Selecting BSS from priority group 0
Try to find WPA-enabled AP
Try to find non-WPA AP
No suitable AP found.
Setting scan request: 5 sec 0 usec
Starting AP scan (broadcast SSID)
ioctl[SIOCSIWSCAN]: Network is down
Scan requested (ret=-1) - scan timeout 5 seconds
Failed to initiate AP scan.
Setting scan request: 10 sec 0 usec
Scan timeout - try to get results
Received 0 bytes of scan results (0 BSSes)
Selecting BSS from priority group 0
Try to find WPA-enabled AP
Try to find non-WPA AP
No suitable AP found.
Setting scan request: 5 sec 0 usec
CTRL-EVENT-TERMINATING - signal 2 received
Removing interface ath0
State: SCANNING -> DISCONNECTED
wpa_driver_wext_set_operstate: operstate 0->0 (DORMANT)
WEXT: Operstate: linkmode=-1, operstate=5
No keys have been configured - skip key clearing
EAPOL: External notification - portEnabled=0
EAPOL: External notification - portValid=0
wpa_driver_wext_set_wpa
wpa_driver_wext_set_drop_unencrypted
wpa_driver_wext_set_countermeasures
No keys have been configured - skip key clearing
Control interface directory not empty - leaving it behind
Cancelling scan request
Cancelling authentication timeout
WEXT: Operstate: linkmode=0, operstate=6

# madwifi driver interface fails to initialize, no polling occurs
#
# /sbin/wpa_supplicant -w -dd -P /var/run/wpa_supplicant.ath0.pid -i ath0 -D madwifi -c /etc/wpa_supplicant/conf.ath0
<snip>
Initializing interface (2) 'ath0'
EAPOL: SUPP_PAE entering state DISCONNECTED
EAPOL: KEY_RX entering state NO_KEY_RECEIVE
EAPOL: SUPP_BE entering state INITIALIZE
EAP: EAP entering state DISABLED
EAPOL: External notification - portEnabled=0
EAPOL: External notification - portValid=0
ioctl[SIOCGIFFLAGS]: No such device
Could not get interface 'ath0' flags
ioctl[SIOCSIWPMKSA]: No such device
ioctl[SIOCSIWMODE]: No such device
Could not configure driver to use managed mode
ioctl[SIOCGIWRANGE]: No such device
WEXT: Operstate: linkmode=1, operstate=5
ioctl[IEEE80211_IOCTL_SETPARAM]: No such device
wpa_driver_madwifi_init: failed to set wpa_supplicant-based roaming
ioctl[SIOCSIWAP]: No such device
WEXT: Operstate: linkmode=0, operstate=6
ioctl[SIOCGIFFLAGS]: No such device
Failed to initialize driver interface
Failed to add interface ath0
Cancelling scan request
Cancelling authentication timeout


Most drivers either use wpa_driver_wext_init() or fail when interface
properties cannot be determined in their init function. If polling on driver
initialization is to succeed, the wpa_driver_*_init() function must return
NULL when no interface exists. This patch modifies wpa_driver_wext_init()
to return NULL when interface flags cannot be determined.

I'd be just as happy to see the wait_for_interface stuff completely removed,
as any distro should have some hotplug agent or similar support in their
networking toolset. Therefore, I see no need for this option to exist at all,
but while it does exist and does not work, I'll have a go at fixing it ;-)

Signed-off-by: Kel Modderman <kel at otaku42.de>
---
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1469,38 +1469,104 @@
 
 
 /**
- * wpa_supplicant_driver_init - Initialize driver interface parameters
+ * wpa_supplicant_driver_init - Initialize driver interface
  * @wpa_s: Pointer to wpa_supplicant data
  * @wait_for_interface: 0 = do not wait for the interface (reports a failure if
  * the interface is not present), 1 = wait until the interface is available
  * Returns: 0 on success, -1 on failure
  *
- * This function is called to initialize driver interface parameters.
- * wpa_drv_init() must have been called before this function to initialize the
- * driver interface.
+ * This function is called to initialize driver interface and driver interface
+ * parameters.
  */
 int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s,
 			       int wait_for_interface)
 {
+	const char *ifname;
 	static int interface_count = 0;
 
+	/* Initialize driver interface and register driver event handler before
+	 * L2 receive handler so that association events are processed before
+	 * EAPOL-Key packets if both become available for the same select()
+	 * call. */
 	for (;;) {
-		if (wpa_s->driver->send_eapol) {
-			const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
-			if (addr)
-				os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
-			break;
+		wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
+		if (wpa_s->drv_priv == NULL) {
+			if (wait_for_interface) {
+				wpa_printf(MSG_DEBUG, "Waiting for interface "
+					   "'%s'...", wpa_s->ifname);
+				os_sleep(5, 0);
+			} else {
+				wpa_printf(MSG_ERROR, "Failed to initialize "
+					   "driver interface for '%s'",
+					   wpa_s->ifname);
+				return -1;
+			}
 		}
+		else
+			break;
+	}
+
+	if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
+		wpa_printf(MSG_ERROR, "Driver interface rejected "
+			   "driver_param '%s'", wpa_s->conf->driver_param);
+		return -1;
+	}
+
+	ifname = wpa_drv_get_ifname(wpa_s);
+	if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
+		wpa_printf(MSG_DEBUG, "Driver interface replaced interface "
+			   "name with '%s'", ifname);
+		os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
+	}
+
+	if (wpa_supplicant_init_wpa(wpa_s) < 0)
+		return -1;
+
+	wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
+			  wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
+			  NULL);
+	wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
+	wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
+
+	if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
+	    wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
+			     wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
+		wpa_printf(MSG_ERROR, "Invalid WPA parameter value for "
+			   "dot11RSNAConfigPMKLifetime");
+		return -1;
+	}
+
+	if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
+	    wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
+			     wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
+		wpa_printf(MSG_ERROR, "Invalid WPA parameter value for "
+			"dot11RSNAConfigPMKReauthThreshold");
+		return -1;
+	}
+
+	if (wpa_s->conf->dot11RSNAConfigSATimeout &&
+	    wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
+			     wpa_s->conf->dot11RSNAConfigSATimeout)) {
+		wpa_printf(MSG_ERROR, "Invalid WPA parameter value for "
+			   "dot11RSNAConfigSATimeout");
+		return -1;
+	}
+
+	if (wpa_s->driver->send_eapol) {
+		const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
+		if (addr)
+			os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
+	} else {
 		wpa_s->l2 = l2_packet_init(wpa_s->ifname,
 					   wpa_drv_get_mac_addr(wpa_s),
 					   ETH_P_EAPOL,
 					   wpa_supplicant_rx_eapol, wpa_s, 0);
-		if (wpa_s->l2)
-			break;
-		else if (!wait_for_interface)
+		if (wpa_s->l2 == NULL) {
+			wpa_printf(MSG_ERROR, "Failed to open l2_packet "
+				   "connection for interface '%s'",
+				   wpa_s->ifname);
 			return -1;
-		wpa_printf(MSG_DEBUG, "Waiting for interface..");
-		os_sleep(5, 0);
+		}
 	}
 
 	if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
@@ -1671,7 +1737,6 @@
 static int wpa_supplicant_init_iface2(struct wpa_supplicant *wpa_s,
 				      int wait_for_interface)
 {
-	const char *ifname;
 	struct wpa_driver_capa capa;
 
 	wpa_printf(MSG_DEBUG, "Initializing interface (2) '%s'",
@@ -1684,61 +1749,6 @@
 	eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
 	eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
 
-	/* Initialize driver interface and register driver event handler before
-	 * L2 receive handler so that association events are processed before
-	 * EAPOL-Key packets if both become available for the same select()
-	 * call. */
-	wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
-	if (wpa_s->drv_priv == NULL) {
-		wpa_printf(MSG_ERROR, "Failed to initialize driver interface");
-		return -1;
-	}
-	if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
-		wpa_printf(MSG_ERROR, "Driver interface rejected "
-			   "driver_param '%s'", wpa_s->conf->driver_param);
-		return -1;
-	}
-
-	ifname = wpa_drv_get_ifname(wpa_s);
-	if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
-		wpa_printf(MSG_DEBUG, "Driver interface replaced interface "
-			   "name with '%s'", ifname);
-		os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
-	}
-
-	if (wpa_supplicant_init_wpa(wpa_s) < 0)
-		return -1;
-
-	wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
-			  wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
-			  NULL);
-	wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
-	wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
-
-	if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
-	    wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
-			     wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
-		wpa_printf(MSG_ERROR, "Invalid WPA parameter value for "
-			   "dot11RSNAConfigPMKLifetime");
-		return -1;
-	}
-
-	if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
-	    wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
-			     wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
-		wpa_printf(MSG_ERROR, "Invalid WPA parameter value for "
-			"dot11RSNAConfigPMKReauthThreshold");
-		return -1;
-	}
-
-	if (wpa_s->conf->dot11RSNAConfigSATimeout &&
-	    wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
-			     wpa_s->conf->dot11RSNAConfigSATimeout)) {
-		wpa_printf(MSG_ERROR, "Invalid WPA parameter value for "
-			   "dot11RSNAConfigSATimeout");
-		return -1;
-	}
-
 	if (wpa_supplicant_driver_init(wpa_s, wait_for_interface) < 0) {
 		return -1;
 	}
--- a/src/drivers/driver_wext.c
+++ b/src/drivers/driver_wext.c
@@ -924,9 +924,7 @@
 	s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
 	if (s < 0) {
 		perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)");
-		close(drv->ioctl_sock);
-		os_free(drv);
-		return NULL;
+		goto fail;
 	}
 
 	os_memset(&local, 0, sizeof(local));
@@ -934,10 +932,7 @@
 	local.nl_groups = RTMGRP_LINK;
 	if (bind(s, (struct sockaddr *) &local, sizeof(local)) < 0) {
 		perror("bind(netlink)");
-		close(s);
-		close(drv->ioctl_sock);
-		os_free(drv);
-		return NULL;
+		goto fail2;
 	}
 
 	eloop_register_read_sock(s, wpa_driver_wext_event_receive, drv, ctx);
@@ -945,9 +940,10 @@
 
 	drv->mlme_sock = -1;
 
-	if (wpa_driver_wext_get_ifflags(drv, &flags) != 0)
+	if (wpa_driver_wext_get_ifflags(drv, &flags) != 0) {
 		printf("Could not get interface '%s' flags\n", drv->ifname);
-	else if (!(flags & IFF_UP)) {
+		goto fail3;
+	} else if (!(flags & IFF_UP)) {
 		if (wpa_driver_wext_set_ifflags(drv, flags | IFF_UP) != 0) {
 			printf("Could not set interface '%s' UP\n",
 			       drv->ifname);
@@ -996,6 +992,16 @@
 	wpa_driver_wext_send_oper_ifla(drv, 1, IF_OPER_DORMANT);
 
 	return drv;
+
+fail3:
+	close(drv->event_sock);
+	eloop_unregister_read_sock(s);
+fail2:
+	close(s);
+fail:
+	close(drv->ioctl_sock);
+	os_free(drv);
+	return NULL;
 }
 
 
---


More information about the HostAP mailing list