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>
This commit is contained in:
Felix Fietkau 2023-09-14 19:08:34 +02:00
parent a63e118f77
commit 4acbe4e336
2 changed files with 34 additions and 14 deletions

View file

@ -688,7 +688,6 @@ let main_obj = {
freq_info.csa_count = req.args.csa_count ?? 10; freq_info.csa_count = req.args.csa_count ?? 10;
ret = iface.switch_channel(freq_info); ret = iface.switch_channel(freq_info);
} else { } else {
iface.stop();
ret = iface.start(freq_info); ret = iface.start(freq_info);
} }
if (!ret) if (!ret)

View file

@ -382,13 +382,23 @@ uc_hostapd_iface_stop(uc_vm_t *vm, size_t nargs)
struct hostapd_iface *iface = uc_fn_thisval("hostapd.iface"); struct hostapd_iface *iface = uc_fn_thisval("hostapd.iface");
int i; int i;
switch (iface->state) {
case HAPD_IFACE_ENABLED:
case HAPD_IFACE_DISABLED:
break;
#ifdef CONFIG_ACS #ifdef CONFIG_ACS
if (iface->state == HAPD_IFACE_ACS) { case HAPD_IFACE_ACS:
acs_cleanup(iface); acs_cleanup(iface);
iface->scan_cb = NULL; iface->scan_cb = NULL;
hostapd_disable_iface(iface); /* fallthrough */
}
#endif #endif
default:
hostapd_disable_iface(iface);
break;
}
if (iface->state != HAPD_IFACE_ENABLED)
hostapd_disable_iface(iface);
for (i = 0; i < iface->num_bss; i++) { for (i = 0; i < iface->num_bss; i++) {
struct hostapd_data *hapd = iface->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"); struct hostapd_iface *iface = uc_fn_thisval("hostapd.iface");
uc_value_t *info = uc_fn_arg(0); uc_value_t *info = uc_fn_arg(0);
struct hostapd_config *conf; struct hostapd_config *conf;
bool changed = false;
uint64_t intval; uint64_t intval;
int i; int i;
if (!iface) if (!iface)
return NULL; return NULL;
iface->freq = 0; if (!info) {
if (!info) iface->freq = 0;
goto out; goto out;
}
if (ucv_type(info) != UC_OBJECT) if (ucv_type(info) != UC_OBJECT)
return NULL; 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; conf = iface->conf;
if ((intval = ucv_int64_get(ucv_object_get(info, "op_class", NULL))) && !errno) UPDATE_VAL(op_class, "op_class");
conf->op_class = intval; UPDATE_VAL(hw_mode, "hw_mode");
if ((intval = ucv_int64_get(ucv_object_get(info, "hw_mode", NULL))) && !errno) UPDATE_VAL(channel, "channel");
conf->hw_mode = intval; UPDATE_VAL(secondary_channel, "sec_channel");
if ((intval = ucv_int64_get(ucv_object_get(info, "channel", NULL))) && !errno) if (!changed &&
conf->channel = intval; (iface->bss[0]->beacon_set_done ||
if ((intval = ucv_int64_get(ucv_object_get(info, "sec_channel", NULL))) && !errno) iface->state == HAPD_IFACE_DFS))
conf->secondary_channel = intval; return ucv_boolean_new(true);
intval = ucv_int64_get(ucv_object_get(info, "center_seg0_idx", NULL)); intval = ucv_int64_get(ucv_object_get(info, "center_seg0_idx", NULL));
if (!errno) 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)); intval = ucv_int64_get(ucv_object_get(info, "frequency", NULL));
if (!errno) if (!errno)
iface->freq = intval; iface->freq = intval;
else
iface->freq = 0;
conf->acs = 0; conf->acs = 0;
out: out: