diff options
author | Felix Fietkau <nbd@nbd.name> | 2023-09-14 19:08:34 +0200 |
---|---|---|
committer | Felix Fietkau <nbd@nbd.name> | 2023-09-14 19:13:36 +0200 |
commit | 4acbe4e336fabbe6011485b3f37f4941f75b5072 (patch) | |
tree | 03ca014e5fa1fe371b6da243bb96c38f0000b386 | |
parent | a63e118f7765735ec676f49c528be296eb55f7ad (diff) | |
download | openwrt-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.uc | 1 | ||||
-rw-r--r-- | package/network/services/hostapd/src/src/ap/ucode.c | 45 |
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: |