hostapd: Allow a single BSS to be added to an interface
authorKyeyoon Park <kyeyoonp@qca.qualcomm.com>
Wed, 23 Oct 2013 07:10:22 +0000 (00:10 -0700)
committerJouni Malinen <j@w1.fi>
Thu, 31 Oct 2013 20:30:15 +0000 (22:30 +0200)
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>

src/ap/hostapd.c

index 88e44f5..732d109 100644 (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 *
 hostapd_interface_init_bss(struct hapd_interfaces *interfaces, const char *phy,
                           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_data **tmp_bss;
                struct hostapd_bss_config *bss;
+               const char *ifname;
 
                /* Add new BSS to existing iface */
                conf = interfaces->config_read_cb(config_fname);
@@ -1249,6 +1267,14 @@ hostapd_interface_init_bss(struct hapd_interfaces *interfaces, const char *phy,
                        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(
                        iface->conf->bss, iface->conf->num_bss + 1,
                        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)
 {
        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;
-       size_t i;
-       const char *conf_file = NULL;
+       size_t i, j;
+       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, ' ');
        if (ptr == NULL)