aboutsummaryrefslogtreecommitdiffstats
path: root/hostapd/main.c
diff options
context:
space:
mode:
authorJouni Malinen <jouni@qca.qualcomm.com>2013-10-17 14:41:26 (GMT)
committerJouni Malinen <j@w1.fi>2013-10-29 14:58:21 (GMT)
commit5afaa067d93b4b68cb64a092069c31d81fa44077 (patch)
tree78fcd83371a57e440201e88afa4f8b8677433add /hostapd/main.c
parentebd79f07c47b02b71c0ac7744a6a94a2bae92fcf (diff)
downloadhostap-5afaa067d93b4b68cb64a092069c31d81fa44077.zip
hostap-5afaa067d93b4b68cb64a092069c31d81fa44077.tar.gz
hostap-5afaa067d93b4b68cb64a092069c31d81fa44077.tar.bz2
hostapd: Allow per-BSS (vif) configuration files
This provides a new option for configuring multiple virtual interfaces (BSS) that share a single radio. The new command line parameter -b<phyname>:<config file name> is used to define one or more virtual interfaces for each PHY. The first such entry for a new PHY is used to initialize the interface structure and all consecutive parameters that have the same PHY name will be added as virtual BSS entries to that interface. The radio parameters in the configuration files have to be identical. This can be used as an alternative for the bss=<ifname> separator and multiple BSSes in a single configuration file design while still allowing hostapd to control the PHY (struct hostapd_iface) as a group of virtual interfaces (struct hostapd_data) so that common radio operations like OLBC detection and HT40 co-ex scans can be done only once per real radio. Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
Diffstat (limited to 'hostapd/main.c')
-rw-r--r--hostapd/main.c177
1 files changed, 172 insertions, 5 deletions
diff --git a/hostapd/main.c b/hostapd/main.c
index ab75b5f..23eef1a 100644
--- a/hostapd/main.c
+++ b/hostapd/main.c
@@ -327,10 +327,123 @@ hostapd_interface_init(struct hapd_interfaces *interfaces,
return NULL;
}
+ iface->init_done = 1;
+
return iface;
}
+static struct hostapd_iface *
+hostapd_interface_init_bss(struct hapd_interfaces *interfaces, const char *phy,
+ const char *config_fname, int debug)
+{
+ struct hostapd_iface *new_iface = NULL, *iface = NULL;
+ struct hostapd_data *hapd;
+ int k;
+ size_t i, bss_idx;
+
+ if (!phy || !*phy)
+ return NULL;
+
+ for (i = 0; i < interfaces->count; i++) {
+ if (os_strcmp(interfaces->iface[i]->phy, phy) == 0) {
+ iface = interfaces->iface[i];
+ break;
+ }
+ }
+
+ wpa_printf(MSG_ERROR, "Configuration file: %s (phy %s)%s",
+ config_fname, phy, iface ? "" : " --> new PHY");
+ if (iface) {
+ struct hostapd_config *conf;
+ struct hostapd_bss_config **tmp_conf;
+ struct hostapd_data **tmp_bss;
+ struct hostapd_bss_config *bss;
+
+ /* Add new BSS to existing iface */
+ conf = hostapd_config_read(config_fname);
+ if (conf == NULL)
+ return NULL;
+ if (conf->num_bss > 1) {
+ wpa_printf(MSG_ERROR, "Multiple BSSes specified in BSS-config");
+ hostapd_config_free(conf);
+ return NULL;
+ }
+
+ tmp_conf = os_realloc_array(
+ iface->conf->bss, iface->conf->num_bss + 1,
+ sizeof(struct hostapd_bss_config *));
+ tmp_bss = os_realloc_array(iface->bss, iface->num_bss + 1,
+ sizeof(struct hostapd_data *));
+ if (tmp_bss)
+ iface->bss = tmp_bss;
+ if (tmp_conf) {
+ iface->conf->bss = tmp_conf;
+ iface->conf->last_bss = tmp_conf[0];
+ }
+ if (tmp_bss == NULL || tmp_conf == NULL) {
+ hostapd_config_free(conf);
+ return NULL;
+ }
+ bss = iface->conf->bss[iface->conf->num_bss] = conf->bss[0];
+ iface->conf->num_bss++;
+
+ hapd = hostapd_alloc_bss_data(iface, iface->conf, bss);
+ if (hapd == NULL) {
+ iface->conf->num_bss--;
+ hostapd_config_free(conf);
+ return NULL;
+ }
+ iface->conf->last_bss = bss;
+ iface->bss[iface->num_bss] = hapd;
+ hapd->msg_ctx = hapd;
+
+ bss_idx = iface->num_bss++;
+ conf->num_bss--;
+ conf->bss[0] = NULL;
+ hostapd_config_free(conf);
+ } else {
+ /* Add a new iface with the first BSS */
+ new_iface = iface = hostapd_init(config_fname);
+ if (!iface)
+ return NULL;
+ os_strlcpy(iface->phy, phy, sizeof(iface->phy));
+ iface->interfaces = interfaces;
+ bss_idx = 0;
+ }
+
+ for (k = 0; k < debug; k++) {
+ if (iface->bss[bss_idx]->conf->logger_stdout_level > 0)
+ iface->bss[bss_idx]->conf->logger_stdout_level--;
+ }
+
+ if (iface->conf->bss[bss_idx]->iface[0] == '\0' &&
+ !hostapd_drv_none(iface->bss[bss_idx])) {
+ wpa_printf(MSG_ERROR, "Interface name not specified in %s",
+ config_fname);
+ if (new_iface)
+ hostapd_interface_deinit_free(new_iface);
+ return NULL;
+ }
+
+ return iface;
+}
+
+
+static int hostapd_interface_init2(struct hostapd_iface *iface)
+{
+ if (iface->init_done)
+ return 0;
+
+ if (hostapd_driver_init(iface) ||
+ hostapd_setup_interface(iface))
+ return -1;
+ iface->init_done = 1;
+
+ return 0;
+}
+
+
/**
* handle_term - SIGINT and SIGTERM handler to terminate hostapd process
*/
@@ -577,11 +690,13 @@ int main(int argc, char *argv[])
{
struct hapd_interfaces interfaces;
int ret = 1;
- size_t i;
+ size_t i, j;
int c, debug = 0, daemonize = 0;
char *pid_file = NULL;
const char *log_file = NULL;
const char *entropy_file = NULL;
+ char **bss_config = NULL, **tmp_bss;
+ size_t num_bss_configs = 0;
if (os_program_init())
return -1;
@@ -598,7 +713,7 @@ int main(int argc, char *argv[])
interfaces.global_ctrl_sock = -1;
for (;;) {
- c = getopt(argc, argv, "Bde:f:hKP:tvg:G:");
+ c = getopt(argc, argv, "b:Bde:f:hKP:tvg:G:");
if (c < 0)
break;
switch (c) {
@@ -641,13 +756,23 @@ int main(int argc, char *argv[])
if (hostapd_get_ctrl_iface_group(&interfaces, optarg))
return -1;
break;
+ case 'b':
+ tmp_bss = os_realloc_array(bss_config,
+ num_bss_configs + 1,
+ sizeof(char *));
+ if (tmp_bss == NULL)
+ goto out;
+ bss_config = tmp_bss;
+ bss_config[num_bss_configs++] = optarg;
+ break;
default:
usage();
break;
}
}
- if (optind == argc && interfaces.global_iface_path == NULL)
+ if (optind == argc && interfaces.global_iface_path == NULL &&
+ num_bss_configs == 0)
usage();
wpa_msg_register_ifname_cb(hostapd_msg_ifname_cb);
@@ -656,8 +781,8 @@ int main(int argc, char *argv[])
wpa_debug_open_file(log_file);
interfaces.count = argc - optind;
- if (interfaces.count) {
- interfaces.iface = os_calloc(interfaces.count,
+ if (interfaces.count || num_bss_configs) {
+ interfaces.iface = os_calloc(interfaces.count + num_bss_configs,
sizeof(struct hostapd_iface *));
if (interfaces.iface == NULL) {
wpa_printf(MSG_ERROR, "malloc failed");
@@ -681,6 +806,46 @@ int main(int argc, char *argv[])
}
}
+ for (i = 0; i < num_bss_configs; i++) {
+ struct hostapd_iface *iface;
+ char *fname;
+
+ wpa_printf(MSG_INFO, "BSS config: %s", bss_config[i]);
+ fname = os_strchr(bss_config[i], ':');
+ if (fname == NULL) {
+ wpa_printf(MSG_ERROR,
+ "Invalid BSS config identifier '%s'",
+ bss_config[i]);
+ goto out;
+ }
+ *fname++ = '\0';
+ iface = hostapd_interface_init_bss(&interfaces, bss_config[i],
+ fname, debug);
+ if (iface == NULL)
+ goto out;
+ for (j = 0; j < interfaces.count; j++) {
+ if (interfaces.iface[j] == 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 == NULL) {
+ hostapd_interface_deinit_free(iface);
+ goto out;
+ }
+ interfaces.iface = tmp;
+ interfaces.iface[interfaces.count++] = iface;
+ }
+ }
+
+ for (i = 0; i < interfaces.count; i++) {
+ if (hostapd_interface_init2(interfaces.iface[i]) < 0)
+ goto out;
+ }
+
hostapd_global_ctrl_iface_init(&interfaces);
if (hostapd_global_run(&interfaces, daemonize, pid_file)) {
@@ -703,6 +868,8 @@ int main(int argc, char *argv[])
if (log_file)
wpa_debug_close_file();
+ os_free(bss_config);
+
os_program_deinit();
return ret;