summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@nbd.name>2023-09-14 19:08:34 +0200
committerFelix Fietkau <nbd@nbd.name>2023-09-14 19:13:36 +0200
commit4acbe4e336fabbe6011485b3f37f4941f75b5072 (patch)
tree03ca014e5fa1fe371b6da243bb96c38f0000b386
parenta63e118f7765735ec676f49c528be296eb55f7ad (diff)
downloadopenwrt-4acbe4e336fabbe6011485b3f37f4941f75b5072.tar.gz
openwrt-4acbe4e336fabbe6011485b3f37f4941f75b5072.tar.bz2
openwrt-4acbe4e336fabbe6011485b3f37f4941f75b5072.zip
hostapd: fix more AP+STA issues
When STA is disconnected, ensure that the interface is in a cleanly stopped state: - if in regular enable/disable state, stop beacons if necessary - in any other state, disable the interface When the STA is up, ignore repeated start commands for the same channel, in order to avoid unnecessary AP restarts Signed-off-by: Felix Fietkau <nbd@nbd.name>
-rw-r--r--package/network/services/hostapd/files/hostapd.uc1
-rw-r--r--package/network/services/hostapd/src/src/ap/ucode.c45
2 files changed, 33 insertions, 13 deletions
diff --git a/package/network/services/hostapd/files/hostapd.uc b/package/network/services/hostapd/files/hostapd.uc
index 9b356dcc30..6b6e41b6f7 100644
--- a/package/network/services/hostapd/files/hostapd.uc
+++ b/package/network/services/hostapd/files/hostapd.uc
@@ -688,7 +688,6 @@ let main_obj = {
freq_info.csa_count = req.args.csa_count ?? 10;
ret = iface.switch_channel(freq_info);
} else {
- iface.stop();
ret = iface.start(freq_info);
}
if (!ret)
diff --git a/package/network/services/hostapd/src/src/ap/ucode.c b/package/network/services/hostapd/src/src/ap/ucode.c
index ba081d87c2..7bc797acfc 100644
--- a/package/network/services/hostapd/src/src/ap/ucode.c
+++ b/package/network/services/hostapd/src/src/ap/ucode.c
@@ -382,13 +382,23 @@ uc_hostapd_iface_stop(uc_vm_t *vm, size_t nargs)
struct hostapd_iface *iface = uc_fn_thisval("hostapd.iface");
int i;
+ switch (iface->state) {
+ case HAPD_IFACE_ENABLED:
+ case HAPD_IFACE_DISABLED:
+ break;
#ifdef CONFIG_ACS
- if (iface->state == HAPD_IFACE_ACS) {
+ case HAPD_IFACE_ACS:
acs_cleanup(iface);
iface->scan_cb = NULL;
+ /* fallthrough */
+#endif
+ default:
hostapd_disable_iface(iface);
+ break;
}
-#endif
+
+ if (iface->state != HAPD_IFACE_ENABLED)
+ hostapd_disable_iface(iface);
for (i = 0; i < iface->num_bss; i++) {
struct hostapd_data *hapd = iface->bss[i];
@@ -406,28 +416,37 @@ uc_hostapd_iface_start(uc_vm_t *vm, size_t nargs)
struct hostapd_iface *iface = uc_fn_thisval("hostapd.iface");
uc_value_t *info = uc_fn_arg(0);
struct hostapd_config *conf;
+ bool changed = false;
uint64_t intval;
int i;
if (!iface)
return NULL;
- iface->freq = 0;
- if (!info)
+ if (!info) {
+ iface->freq = 0;
goto out;
+ }
if (ucv_type(info) != UC_OBJECT)
return NULL;
+#define UPDATE_VAL(field, name) \
+ if ((intval = ucv_int64_get(ucv_object_get(info, name, NULL))) && \
+ !errno && intval != conf->field) do { \
+ conf->field = intval; \
+ changed = true; \
+ } while(0)
+
conf = iface->conf;
- if ((intval = ucv_int64_get(ucv_object_get(info, "op_class", NULL))) && !errno)
- conf->op_class = intval;
- if ((intval = ucv_int64_get(ucv_object_get(info, "hw_mode", NULL))) && !errno)
- conf->hw_mode = intval;
- if ((intval = ucv_int64_get(ucv_object_get(info, "channel", NULL))) && !errno)
- conf->channel = intval;
- if ((intval = ucv_int64_get(ucv_object_get(info, "sec_channel", NULL))) && !errno)
- conf->secondary_channel = intval;
+ UPDATE_VAL(op_class, "op_class");
+ UPDATE_VAL(hw_mode, "hw_mode");
+ UPDATE_VAL(channel, "channel");
+ UPDATE_VAL(secondary_channel, "sec_channel");
+ if (!changed &&
+ (iface->bss[0]->beacon_set_done ||
+ iface->state == HAPD_IFACE_DFS))
+ return ucv_boolean_new(true);
intval = ucv_int64_get(ucv_object_get(info, "center_seg0_idx", NULL));
if (!errno)
@@ -444,6 +463,8 @@ uc_hostapd_iface_start(uc_vm_t *vm, size_t nargs)
intval = ucv_int64_get(ucv_object_get(info, "frequency", NULL));
if (!errno)
iface->freq = intval;
+ else
+ iface->freq = 0;
conf->acs = 0;
out: