hostapd: allow adding initial AP without breaking STA interface connection
[openwrt/openwrt.git] / package / network / services / hostapd / src / src / ap / ucode.c
index a41eee3fe5e0c02335a24312a97c1b0617448324..0326f6fc82dc9f8aa2f74ae695f7c4605247e87d 100644 (file)
@@ -7,6 +7,7 @@
 #include "beacon.h"
 #include "hw_features.h"
 #include "ap_drv_ops.h"
+#include "dfs.h"
 #include <libubox/uloop.h>
 
 static uc_resource_type_t *global_type, *bss_type, *iface_type;
@@ -23,7 +24,7 @@ hostapd_ucode_bss_get_uval(struct hostapd_data *hapd)
                return wpa_ucode_registry_get(bss_registry, hapd->ucode.idx);
 
        val = uc_resource_new(bss_type, hapd);
-       wpa_ucode_registry_add(bss_registry, val, &hapd->ucode.idx);
+       hapd->ucode.idx = wpa_ucode_registry_add(bss_registry, val);
 
        return val;
 }
@@ -37,46 +38,46 @@ hostapd_ucode_iface_get_uval(struct hostapd_iface *hapd)
                return wpa_ucode_registry_get(iface_registry, hapd->ucode.idx);
 
        val = uc_resource_new(iface_type, hapd);
-       wpa_ucode_registry_add(iface_registry, val, &hapd->ucode.idx);
+       hapd->ucode.idx = wpa_ucode_registry_add(iface_registry, val);
 
        return val;
 }
 
 static void
-hostapd_ucode_update_bss_list(struct hostapd_iface *iface)
+hostapd_ucode_update_bss_list(struct hostapd_iface *iface, uc_value_t *if_bss, uc_value_t *bss)
 {
-       uc_value_t *ifval, *list;
+       uc_value_t *list;
        int i;
 
        list = ucv_array_new(vm);
        for (i = 0; i < iface->num_bss; i++) {
                struct hostapd_data *hapd = iface->bss[i];
                uc_value_t *val = hostapd_ucode_bss_get_uval(hapd);
-               uc_value_t *proto = ucv_prototype_get(val);
 
-               ucv_object_add(proto, "name", ucv_get(ucv_string_new(hapd->conf->iface)));
-               ucv_object_add(proto, "index", ucv_int64_new(i));
-               ucv_array_set(list, i, ucv_get(val));
+               ucv_array_set(list, i, ucv_get(ucv_string_new(hapd->conf->iface)));
+               ucv_object_add(bss, hapd->conf->iface, ucv_get(val));
        }
-
-       ifval = hostapd_ucode_iface_get_uval(iface);
-       ucv_object_add(ucv_prototype_get(ifval), "bss", ucv_get(list));
+       ucv_object_add(if_bss, iface->phy, ucv_get(list));
 }
 
 static void
 hostapd_ucode_update_interfaces(void)
 {
        uc_value_t *ifs = ucv_object_new(vm);
+       uc_value_t *if_bss = ucv_array_new(vm);
+       uc_value_t *bss = ucv_object_new(vm);
        int i;
 
        for (i = 0; i < interfaces->count; i++) {
                struct hostapd_iface *iface = interfaces->iface[i];
 
                ucv_object_add(ifs, iface->phy, ucv_get(hostapd_ucode_iface_get_uval(iface)));
-               hostapd_ucode_update_bss_list(iface);
+               hostapd_ucode_update_bss_list(iface, if_bss, bss);
        }
 
        ucv_object_add(ucv_prototype_get(global), "interfaces", ucv_get(ifs));
+       ucv_object_add(ucv_prototype_get(global), "interface_bss", ucv_get(if_bss));
+       ucv_object_add(ucv_prototype_get(global), "bss", ucv_get(bss));
        ucv_gc(vm);
 }
 
@@ -199,7 +200,7 @@ uc_hostapd_bss_delete(uc_vm_t *vm, size_t nargs)
        hostapd_config_free_bss(hapd->conf);
        os_free(hapd);
 
-       hostapd_ucode_update_bss_list(iface);
+       hostapd_ucode_update_interfaces();
        ucv_gc(vm);
 
        return NULL;
@@ -252,7 +253,7 @@ uc_hostapd_iface_add_bss(uc_vm_t *vm, size_t nargs)
        iface->conf->bss[iface->conf->num_bss] = bss;
        conf->bss[idx] = NULL;
        ret = hostapd_ucode_bss_get_uval(hapd);
-       hostapd_ucode_update_bss_list(iface);
+       hostapd_ucode_update_interfaces();
        goto out;
 
 deinit_ctrl:
@@ -332,38 +333,36 @@ uc_hostapd_iface_start(uc_vm_t *vm, size_t nargs)
                conf->channel = intval;
        if ((intval = ucv_int64_get(ucv_object_get(info, "sec_channel", NULL))) && !errno)
                conf->secondary_channel = intval;
-       if ((intval = ucv_int64_get(ucv_object_get(info, "center_seg0_idx", NULL))) && !errno) {
-               conf->vht_oper_centr_freq_seg0_idx = intval;
-               conf->he_oper_centr_freq_seg0_idx = intval;
-#ifdef CONFIG_IEEE80211BE
-               conf->eht_oper_centr_freq_seg0_idx = intval;
-#endif
-       }
-       if ((intval = ucv_int64_get(ucv_object_get(info, "center_seg1_idx", NULL))) && !errno) {
-               conf->vht_oper_centr_freq_seg1_idx = intval;
-               conf->he_oper_centr_freq_seg1_idx = intval;
-#ifdef CONFIG_IEEE80211BE
-               conf->eht_oper_centr_freq_seg1_idx = intval;
-#endif
-       }
+
+       intval = ucv_int64_get(ucv_object_get(info, "center_seg0_idx", NULL));
+       if (!errno)
+               hostapd_set_oper_centr_freq_seg0_idx(conf, intval);
+
+       intval = ucv_int64_get(ucv_object_get(info, "center_seg1_idx", NULL));
+       if (!errno)
+               hostapd_set_oper_centr_freq_seg1_idx(conf, intval);
+
        intval = ucv_int64_get(ucv_object_get(info, "oper_chwidth", NULL));
-       if (!errno) {
-               conf->vht_oper_chwidth = intval;
-               conf->he_oper_chwidth = intval;
-#ifdef CONFIG_IEEE80211BE
-               conf->eht_oper_chwidth = intval;
-#endif
-       }
+       if (!errno)
+               hostapd_set_oper_chwidth(conf, intval);
 
 out:
        if (conf->channel)
                iface->freq = hostapd_hw_get_freq(iface->bss[0], conf->channel);
 
+       if (hostapd_is_dfs_required(iface) && !hostapd_is_dfs_chan_available(iface)) {
+               wpa_printf(MSG_INFO, "DFS CAC required on new channel, restart interface");
+               hostapd_disable_iface(iface);
+               hostapd_enable_iface(iface);
+               return ucv_boolean_new(true);
+       }
+
        for (i = 0; i < iface->num_bss; i++) {
                struct hostapd_data *hapd = iface->bss[i];
                int ret;
 
                hapd->started = 1;
+               hapd->conf->start_disabled = 0;
                hostapd_set_freq(hapd, conf->hw_mode, iface->freq,
                                 conf->channel,
                                 conf->enable_edmg,