hostapd: Allow a single BSS to be added to an interface

The global control interface command "ADD
bss_config=<phyname>:<config file>" can now be used to add a single
virtual interface (BSS) to an interface.

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Kyeyoon Park 2013-10-23 00:10:22 -07:00 committed by Jouni Malinen
parent a1fb5692af
commit 2e2fff37e9

View file

@ -1212,6 +1212,23 @@ fail:
} }
static int ifname_in_use(struct hapd_interfaces *interfaces, const char *ifname)
{
size_t i, j;
for (i = 0; i < interfaces->count; i++) {
struct hostapd_iface *iface = interfaces->iface[i];
for (j = 0; j < iface->num_bss; j++) {
struct hostapd_data *hapd = iface->bss[j];
if (os_strcmp(ifname, hapd->conf->iface) == 0)
return 1;
}
}
return 0;
}
struct hostapd_iface * struct hostapd_iface *
hostapd_interface_init_bss(struct hapd_interfaces *interfaces, const char *phy, hostapd_interface_init_bss(struct hapd_interfaces *interfaces, const char *phy,
const char *config_fname, int debug) const char *config_fname, int debug)
@ -1238,6 +1255,7 @@ hostapd_interface_init_bss(struct hapd_interfaces *interfaces, const char *phy,
struct hostapd_bss_config **tmp_conf; struct hostapd_bss_config **tmp_conf;
struct hostapd_data **tmp_bss; struct hostapd_data **tmp_bss;
struct hostapd_bss_config *bss; struct hostapd_bss_config *bss;
const char *ifname;
/* Add new BSS to existing iface */ /* Add new BSS to existing iface */
conf = interfaces->config_read_cb(config_fname); conf = interfaces->config_read_cb(config_fname);
@ -1249,6 +1267,14 @@ hostapd_interface_init_bss(struct hapd_interfaces *interfaces, const char *phy,
return NULL; return NULL;
} }
ifname = conf->bss[0]->iface;
if (ifname[0] != '\0' && ifname_in_use(interfaces, ifname)) {
wpa_printf(MSG_ERROR,
"Interface name %s already in use", ifname);
hostapd_config_free(conf);
return NULL;
}
tmp_conf = os_realloc_array( tmp_conf = os_realloc_array(
iface->conf->bss, iface->conf->num_bss + 1, iface->conf->bss, iface->conf->num_bss + 1,
sizeof(struct hostapd_bss_config *)); sizeof(struct hostapd_bss_config *));
@ -1498,10 +1524,69 @@ static struct hostapd_iface * hostapd_data_alloc(
int hostapd_add_iface(struct hapd_interfaces *interfaces, char *buf) int hostapd_add_iface(struct hapd_interfaces *interfaces, char *buf)
{ {
struct hostapd_config *conf = NULL; struct hostapd_config *conf = NULL;
struct hostapd_iface *hapd_iface = NULL; struct hostapd_iface *hapd_iface = NULL, *new_iface = NULL;
struct hostapd_data *hapd;
char *ptr; char *ptr;
size_t i; size_t i, j;
const char *conf_file = NULL; const char *conf_file = NULL, *phy_name = NULL;
if (os_strncmp(buf, "bss_config=", 11) == 0) {
char *pos;
phy_name = buf + 11;
pos = os_strchr(phy_name, ':');
if (!pos)
return -1;
*pos++ = '\0';
conf_file = pos;
if (!os_strlen(conf_file))
return -1;
hapd_iface = hostapd_interface_init_bss(interfaces, phy_name,
conf_file, 0);
if (!hapd_iface)
return -1;
for (j = 0; j < interfaces->count; j++) {
if (interfaces->iface[j] == hapd_iface)
break;
}
if (j == interfaces->count) {
struct hostapd_iface **tmp;
tmp = os_realloc_array(interfaces->iface,
interfaces->count + 1,
sizeof(struct hostapd_iface *));
if (!tmp) {
hostapd_interface_deinit_free(hapd_iface);
return -1;
}
interfaces->iface = tmp;
interfaces->iface[interfaces->count++] = hapd_iface;
new_iface = hapd_iface;
}
if (new_iface) {
if (interfaces->driver_init(hapd_iface) ||
hostapd_setup_interface(hapd_iface)) {
interfaces->count--;
goto fail;
}
hapd_iface->init_done = 1;
} else {
/* Assign new BSS with bss[0]'s driver info */
hapd = hapd_iface->bss[hapd_iface->num_bss - 1];
hapd->driver = hapd_iface->bss[0]->driver;
hapd->drv_priv = hapd_iface->bss[0]->drv_priv;
os_memcpy(hapd->own_addr, hapd_iface->bss[0]->own_addr,
ETH_ALEN);
if (hostapd_setup_bss(hapd, 0)) {
hapd_iface->conf->num_bss--;
hapd_iface->num_bss--;
os_free(hapd);
return -1;
}
}
return 0;
}
ptr = os_strchr(buf, ' '); ptr = os_strchr(buf, ' ');
if (ptr == NULL) if (ptr == NULL)