hostapd: do not store data in object prototype

It cannot be properly cloned, since it is attached to the resource type.
Use a separate registry for data. Fixes object confusion issues

Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
Felix Fietkau 2023-08-12 00:36:13 +02:00
parent f1c4751ba6
commit a0a5b97674
6 changed files with 44 additions and 53 deletions
package/network/services/hostapd

@ -125,13 +125,18 @@ function iface_reload_config(phy, config, old_config)
if (config.bss[0].ifname != old_config.bss[0].ifname)
return false;
let iface = hostapd.interfaces[config.bss[0].ifname];
let iface_name = config.bss[0].ifname;
let iface = hostapd.interfaces[iface_name];
if (!iface)
return false;
let first_bss = hostapd.bss[iface_name];
if (!first_bss)
return false;
let config_inline = iface_gen_config(phy, config);
bss_reload_psk(iface.bss[0], config.bss[0], old_config.bss[0]);
bss_reload_psk(first_bss, config.bss[0], old_config.bss[0]);
if (!is_equal(config.bss[0], old_config.bss[0])) {
if (phy_is_fullmac(phy))
return false;
@ -140,18 +145,17 @@ function iface_reload_config(phy, config, old_config)
return false;
hostapd.printf(`Reload config for bss '${config.bss[0].ifname}' on phy '${phy}'`);
if (iface.bss[0].set_config(config_inline, 0) < 0) {
if (first_bss.set_config(config_inline, 0) < 0) {
hostapd.printf(`Failed to set config`);
return false;
}
}
let bss_list = array_to_obj(iface.bss, "name", 1);
let new_cfg = array_to_obj(config.bss, "ifname", 1);
let old_cfg = array_to_obj(old_config.bss, "ifname", 1);
for (let name in old_cfg) {
let bss = bss_list[name];
let bss = hostapd.bss[name];
if (!bss) {
hostapd.printf(`bss '${name}' not found`);
return false;

@ -92,11 +92,16 @@ let main_obj = {
if (!phy)
return libubus.STATUS_NOT_FOUND;
if (req.args.stop) {
for (let ifname in phy.data)
iface_stop(phy.data[ifname]);
} else {
start_pending(req.args.phy);
try {
if (req.args.stop) {
for (let ifname in phy.data)
iface_stop(phy.data[ifname]);
} else {
start_pending(req.args.phy);
}
} catch (e) {
wpas.printf(`Error chaging state: ${e}\n${e.stacktrace[0].context}`);
return libubus.STATUS_INVALID_ARGUMENT;
}
return 0;
}
@ -221,14 +226,12 @@ return {
wpas.ubus.disconnect();
},
iface_add: function(name, obj) {
obj.data.name = name;
iface_event("add", name);
},
iface_remove: function(name, obj) {
iface_event("remove", name);
},
state: function(iface, state) {
let ifname = iface.data.name;
state: function(ifname, iface, state) {
let phy = wpas.data.iface_phy[ifname];
if (!phy) {
wpas.printf(`no PHY for ifname ${ifname}`);
@ -237,8 +240,7 @@ return {
iface_hostapd_notify(phy, ifname, iface, state);
},
event: function(iface, ev, info) {
let ifname = iface.data.name;
event: function(ifname, iface, ev, info) {
let phy = wpas.data.iface_phy[ifname];
if (!phy) {
wpas.printf(`no PHY for ifname ${ifname}`);

@ -23,7 +23,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 +37,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 +199,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 +252,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:

@ -271,21 +271,7 @@ uc_value_t *wpa_ucode_global_init(const char *name, uc_resource_type_t *global_t
return global;
}
static uc_value_t *wpa_ucode_prototype_clone(uc_value_t *uval)
{
uc_value_t *proto, *proto_new;
proto = ucv_prototype_get(uval);
proto_new = ucv_object_new(&vm);
ucv_object_foreach(proto, key, val)
ucv_object_add(proto_new, key, ucv_get(val));
ucv_prototype_set(uval, ucv_get(proto));
return proto;
}
void wpa_ucode_registry_add(uc_value_t *reg, uc_value_t *val, int *idx)
int wpa_ucode_registry_add(uc_value_t *reg, uc_value_t *val)
{
uc_value_t *data;
int i = 0;
@ -295,10 +281,7 @@ void wpa_ucode_registry_add(uc_value_t *reg, uc_value_t *val, int *idx)
ucv_array_set(reg, i, ucv_get(val));
data = ucv_object_new(&vm);
ucv_object_add(wpa_ucode_prototype_clone(val), "data", ucv_get(data));
*idx = i + 1;
return i + 1;
}
uc_value_t *wpa_ucode_registry_get(uc_value_t *reg, int idx)

@ -17,7 +17,7 @@ void wpa_ucode_free_vm(void);
uc_value_t *wpa_ucode_global_init(const char *name, uc_resource_type_t *global_type);
void wpa_ucode_registry_add(uc_value_t *reg, uc_value_t *val, int *idx);
int wpa_ucode_registry_add(uc_value_t *reg, uc_value_t *val);
uc_value_t *wpa_ucode_registry_get(uc_value_t *reg, int idx);
uc_value_t *wpa_ucode_registry_remove(uc_value_t *reg, int idx);

@ -21,7 +21,7 @@ wpas_ucode_iface_get_uval(struct wpa_supplicant *wpa_s)
return wpa_ucode_registry_get(iface_registry, wpa_s->ucode.idx);
val = uc_resource_new(iface_type, wpa_s);
wpa_ucode_registry_add(iface_registry, val, &wpa_s->ucode.idx);
wpa_s->ucode.idx = wpa_ucode_registry_add(iface_registry, val);
return val;
}
@ -84,9 +84,10 @@ void wpas_ucode_update_state(struct wpa_supplicant *wpa_s)
return;
state = wpa_supplicant_state_txt(wpa_s->wpa_state);
uc_value_push(ucv_get(ucv_string_new(wpa_s->ifname)));
uc_value_push(ucv_get(val));
uc_value_push(ucv_get(ucv_string_new(state)));
ucv_put(wpa_ucode_call(2));
ucv_put(wpa_ucode_call(3));
ucv_gc(vm);
}
@ -105,6 +106,7 @@ void wpas_ucode_event(struct wpa_supplicant *wpa_s, int event, union wpa_event_d
if (wpa_ucode_call_prepare("event"))
return;
uc_value_push(ucv_get(ucv_string_new(wpa_s->ifname)));
uc_value_push(ucv_get(val));
uc_value_push(ucv_get(ucv_string_new(event_to_string(event))));
val = ucv_object_new(vm);
@ -118,7 +120,7 @@ void wpas_ucode_event(struct wpa_supplicant *wpa_s, int event, union wpa_event_d
ucv_object_add(val, "center_freq2", ucv_int64_new(data->ch_switch.cf2));
}
ucv_put(wpa_ucode_call(3));
ucv_put(wpa_ucode_call(4));
ucv_gc(vm);
}
@ -245,7 +247,7 @@ int wpas_ucode_init(struct wpa_global *gl)
iface_type = uc_type_declare(vm, "wpas.iface", iface_fns, NULL);
iface_registry = ucv_array_new(vm);
uc_vm_registry_set(vm, "hostap.iface_registry", iface_registry);
uc_vm_registry_set(vm, "wpas.iface_registry", iface_registry);
global = wpa_ucode_global_init("wpas", global_type);