Browse Source

hostapd: Allow a single BSS to be removed from an interface

The global control interface command "REMOVE <ifname>" can now be used
to remove a single virtual interface (BSS) without affecting other
virtual interfaces on the same radio.

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
Jouni Malinen 11 years ago
parent
commit
5592065850
3 changed files with 39 additions and 3 deletions
  1. 1 1
      src/ap/ap_config.c
  2. 1 0
      src/ap/ap_config.h
  3. 37 2
      src/ap/hostapd.c

+ 1 - 1
src/ap/ap_config.c

@@ -403,7 +403,7 @@ static void hostapd_config_free_wep(struct hostapd_wep_keys *keys)
 }
 
 
-static void hostapd_config_free_bss(struct hostapd_bss_config *conf)
+void hostapd_config_free_bss(struct hostapd_bss_config *conf)
 {
 	struct hostapd_wpa_psk *psk, *prev;
 	struct hostapd_eap_user *user, *prev_user;

+ 1 - 0
src/ap/ap_config.h

@@ -555,6 +555,7 @@ int hostapd_mac_comp(const void *a, const void *b);
 int hostapd_mac_comp_empty(const void *a);
 struct hostapd_config * hostapd_config_defaults(void);
 void hostapd_config_defaults_bss(struct hostapd_bss_config *bss);
+void hostapd_config_free_bss(struct hostapd_bss_config *conf);
 void hostapd_config_free(struct hostapd_config *conf);
 int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
 			  const u8 *addr, int *vlan_id);

+ 37 - 2
src/ap/hostapd.c

@@ -1658,16 +1658,46 @@ fail:
 }
 
 
+static int hostapd_remove_bss(struct hostapd_iface *iface, unsigned int idx)
+{
+	struct hostapd_data *hapd;
+	size_t i;
+
+	if (idx > iface->num_bss || idx > iface->conf->num_bss)
+		return -1;
+	hapd = iface->bss[idx];
+	wpa_printf(MSG_INFO, "Remove BSS '%s'", hapd->conf->iface);
+
+	hostapd_free_stas(hapd);
+	hostapd_flush_old_stations(hapd, WLAN_REASON_DEAUTH_LEAVING);
+	hostapd_clear_wep(hapd);
+	hostapd_cleanup(hapd);
+	hostapd_config_free_bss(hapd->conf);
+	os_free(hapd);
+
+	iface->num_bss--;
+	for (i = idx; i < iface->num_bss; i++)
+		iface->bss[i] = iface->bss[i + 1];
+
+	iface->conf->num_bss--;
+	for (i = idx; i < iface->num_bss; i++)
+		iface->conf->bss[i] = iface->conf->bss[i + 1];
+
+	return 0;
+}
+
+
 int hostapd_remove_iface(struct hapd_interfaces *interfaces, char *buf)
 {
 	struct hostapd_iface *hapd_iface;
-	size_t i, k = 0;
+	size_t i, j, k = 0;
 
 	for (i = 0; i < interfaces->count; i++) {
 		hapd_iface = interfaces->iface[i];
 		if (hapd_iface == NULL)
 			return -1;
-		if (!os_strcmp(hapd_iface->conf->bss[0]->iface, buf)) {
+		if (hapd_iface->conf->num_bss == 1 &&
+		    !os_strcmp(hapd_iface->conf->bss[0]->iface, buf)) {
 			wpa_printf(MSG_INFO, "Remove interface '%s'", buf);
 			hostapd_interface_deinit_free(hapd_iface);
 			k = i;
@@ -1679,6 +1709,11 @@ int hostapd_remove_iface(struct hapd_interfaces *interfaces, char *buf)
 			interfaces->count--;
 			return 0;
 		}
+
+		for (j = 0; j < hapd_iface->conf->num_bss; j++) {
+			if (!os_strcmp(hapd_iface->conf->bss[j]->iface, buf))
+				return hostapd_remove_bss(hapd_iface, j);
+		}
 	}
 	return -1;
 }