Browse Source

hostapd: Fix ENABLE failure to not remove interface

Previously, ENABLE command ended up freeing the hostapd_iface context on
initialization failures, but did not even remove the interface from the
list of available interfaces. This resulted in use of freed memory with
any following operation on the same interface. In addition, removing the
interface on initialization failure does not seem like the best
approach. Fix both of these issues by leaving the interface instance in
memory, but in disabled state so that the configuration can be fixed and
ENABLE used again to enable the interface or REMOVE used to remove the
interface.

Signed-hostap: Jouni Malinen <j@w1.fi>
Jouni Malinen 11 years ago
parent
commit
71cdf6b624
2 changed files with 16 additions and 4 deletions
  1. 2 1
      src/ap/ap_drv_ops.c
  2. 14 3
      src/ap/hostapd.c

+ 2 - 1
src/ap/ap_drv_ops.c

@@ -430,7 +430,8 @@ int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
 int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type,
 		      const char *ifname)
 {
-	if (hapd->driver == NULL || hapd->driver->if_remove == NULL)
+	if (hapd->driver == NULL || hapd->drv_priv == NULL ||
+	    hapd->driver->if_remove == NULL)
 		return -1;
 	return hapd->driver->if_remove(hapd->drv_priv, type, ifname);
 }

+ 14 - 3
src/ap/hostapd.c

@@ -1364,11 +1364,22 @@ int hostapd_enable_iface(struct hostapd_iface *hapd_iface)
 
 	if (hapd_iface->interfaces == NULL ||
 	    hapd_iface->interfaces->driver_init == NULL ||
-	    hapd_iface->interfaces->driver_init(hapd_iface) ||
-	    hostapd_setup_interface(hapd_iface)) {
-		hostapd_interface_deinit_free(hapd_iface);
+	    hapd_iface->interfaces->driver_init(hapd_iface))
+		return -1;
+
+	if (hostapd_setup_interface(hapd_iface)) {
+		const struct wpa_driver_ops *driver;
+		void *drv_priv;
+
+		driver = hapd_iface->bss[0]->driver;
+		drv_priv = hapd_iface->bss[0]->drv_priv;
+		if (driver && driver->hapd_deinit && drv_priv) {
+			driver->hapd_deinit(drv_priv);
+			hapd_iface->bss[0]->drv_priv = NULL;
+		}
 		return -1;
 	}
+
 	return 0;
 }