Files
wifimngr/ubus.c
2025-11-06 12:20:04 +01:00

684 lines
19 KiB
C

/* SPDX-License-Identifier: GPL-2.0-only */
/*
* ubus.c - provides wifimngr UBUS commands.
*
* Copyright (C) 2024 Iopsys Software Solutions AB. All rights reserved.
* Copyright (C) 2025 Genexis AB.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <limits.h>
#include <net/if.h>
#include <libubox/blobmsg.h>
#include <libubox/blobmsg_json.h>
#include <libubox/uloop.h>
#include <libubox/ustream.h>
#include <libubox/utils.h>
#include <libubus.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <easy/easy.h>
#include <wifi.h>
#include <wifidefs.h>
#include "wifimngr.h"
#include "debug.h"
#include "policy.c"
extern void *libsta_ratings;
int wifimngr_add_object(struct wifimngr *w, const char *objname,
int (*add_methods)(struct wifimngr *w, struct ubus_object *o),
struct ubus_object *object)
{
struct ubus_object_type *obj_type;
struct ubus_object *obj;
int ret;
obj = object;
memset(obj, 0, sizeof(*obj));
obj_type = calloc(1, sizeof(struct ubus_object_type));
if (!obj_type)
return -ENOMEM;
obj->name = strdup(objname);
if (add_methods)
add_methods(w, obj);
obj_type->name = obj->name;
obj_type->n_methods = obj->n_methods;
obj_type->methods = obj->methods;
obj->type = obj_type;
ret = ubus_add_object(w->ubus_ctx, obj);
if (ret) {
wifimngr_dbg("Failed to add '%s' object\n", obj->name);
free((void *)obj->methods);
free((void *)obj->name);
free(obj_type);
}
return ret;
}
#define MAX_RADIO_METHODS 16
static int add_radio_methods(struct wifimngr *w, struct ubus_object *radio_obj,
const char *radioname)
{
struct wifimngr_device *wdev = wifimngr_lookup_wifi_device(w, radioname);
struct ubus_method *radio_methods;
enum wifi_band band;
int n_methods = 0;
char *phyname;
if (!wdev)
return -1;
radio_methods = calloc(MAX_RADIO_METHODS, sizeof(struct ubus_method));
if (!radio_methods)
return -ENOMEM;
phyname = wdev->phy;
band = wdev->band;
UBUS_METHOD_ADD(radio_methods, n_methods,
UBUS_METHOD_NOARG("help", wl_radio_help));
UBUS_METHOD_ADD(radio_methods, n_methods,
UBUS_METHOD_NOARG("status", wl_radio_status));
UBUS_METHOD_ADD(radio_methods, n_methods,
UBUS_METHOD_NOARG("stats", wl_radio_stats));
UBUS_METHOD_ADD(radio_methods, n_methods,
UBUS_METHOD("get", wl_radio_get_param, radio_get_param_policy));
//UBUS_METHOD_ADD(radio_methods, n_methods,
// UBUS_METHOD_NOARG("temperature", wl_temperature));
UBUS_METHOD_ADD(radio_methods, n_methods,
UBUS_METHOD("scan", wl_scan, wl_scan_policy));
if (libwifi_supports(phyname, "wifi_scan_ex")) {
UBUS_METHOD_ADD(radio_methods, n_methods,
UBUS_METHOD("scan_ex", wl_scan_ex, wl_scan_ex_policy));
}
UBUS_METHOD_ADD(radio_methods, n_methods,
UBUS_METHOD("scanresults", wl_scanresults, wl_scanres_policy));
UBUS_METHOD_ADD(radio_methods, n_methods,
UBUS_METHOD("autochannel", wl_autochannel, wl_acs_policy));
if (libwifi_supports(phyname, "wifi_start_cac")) {
UBUS_METHOD_ADD(radio_methods, n_methods,
UBUS_METHOD("start_cac", wl_start_cac, wl_cac_policy));
UBUS_METHOD_ADD(radio_methods, n_methods,
UBUS_METHOD("stop_cac", wl_stop_cac, wl_cac_policy));
}
if (libwifi_supports(phyname, "wifi_add_iface")) {
UBUS_METHOD_ADD(radio_methods, n_methods,
UBUS_METHOD("add_iface", wl_add_iface, add_iface_policy));
}
if (libwifi_supports(phyname, "wifi_del_iface")) {
UBUS_METHOD_ADD(radio_methods, n_methods,
UBUS_METHOD("del_iface", wl_del_iface, del_iface_policy));
}
if (libwifi_supports(phyname, "wifi_channels_info")) {
UBUS_METHOD_ADD(radio_methods, n_methods,
UBUS_METHOD_NOARG("channels_info", wl_channels_info));
}
UBUS_METHOD_ADD(radio_methods, n_methods,
UBUS_METHOD("channels", wl_channels, wl_dump_channels_policy));
if (libwifi_supports(phyname, "wifi_get_opclass_preferences")) {
UBUS_METHOD_ADD(radio_methods, n_methods,
UBUS_METHOD_NOARG("opclass_preferences", wl_opclass_preferences));
}
if (libwifi_supports(phyname, "wifi_simulate_radar") &&
(band == BAND_5 || band == BAND_DUAL || band == BAND_UNKNOWN)) {
UBUS_METHOD_ADD(radio_methods, n_methods,
UBUS_METHOD("simulate_radar", wl_simulate_radar, wl_radar_policy));
}
radio_obj->methods = radio_methods;
radio_obj->n_methods = n_methods;
return 0;
}
#define MAX_WIFI_METHODS 8
int add_wifi_methods(struct wifimngr *w, struct ubus_object *wifi_obj)
{
int n_methods = 0;
struct ubus_method *wifi_methods;
wifi_methods = calloc(MAX_WIFI_METHODS, sizeof(struct ubus_method));
if (!wifi_methods)
return -ENOMEM;
UBUS_METHOD_ADD(wifi_methods, n_methods,
UBUS_METHOD_NOARG("status", wl_status));
UBUS_METHOD_ADD(wifi_methods, n_methods,
UBUS_METHOD_NOARG("help", wl_help));
UBUS_METHOD_ADD(wifi_methods, n_methods,
UBUS_METHOD("debug", wifi_set_debug, wifi_set_debug_policy));
wifi_obj->methods = wifi_methods;
wifi_obj->n_methods = n_methods;
return 0;
}
int wifimngr_lookup_object(struct wifimngr *w, const char *objname)
{
uint32_t id;
int ret;
ret = ubus_lookup_id(w->ubus_ctx, objname, &id);
if (ret == UBUS_STATUS_OK)
return id;
return ret == UBUS_STATUS_OK ? id : -1;
}
int wifimngr_add_radio_object(struct wifimngr *w, struct wifimngr_device *wdev)
{
char *radioname = wdev->device;
struct wifi_ubus_object *wobj;
char objname[64] = {0};
uint32_t id;
int ret;
snprintf(objname, 63, "%s.%s", WIFI_RADIO_OBJECT, radioname);
/* Already added */
if (ubus_lookup_id(w->ubus_ctx, objname, &id) == UBUS_STATUS_OK) {
wdev->object_id = id;
return 0;
}
if (w->num_wifi_device_obj == WIFI_DEV_MAX_NUM) {
wifimngr_dbg("Cannot add more than %d wifi-device objects\n", w->num_wifi_device_obj);
return -1;
}
wobj = calloc(1, sizeof(struct wifi_ubus_object));
if (!wobj)
return -ENOMEM;
wobj->priv = wdev;
wobj->obj.name = strdup(objname);
add_radio_methods(w, &wobj->obj, radioname);
wobj->obj_type.name = wobj->obj.name;
wobj->obj_type.n_methods = wobj->obj.n_methods;
wobj->obj_type.methods = wobj->obj.methods;
wobj->obj.type = &wobj->obj_type;
ret = ubus_add_object(w->ubus_ctx, &wobj->obj);
if (ret) {
free((void *)wobj->obj.methods);
free((void *)wobj->obj.name);
free(wobj);
return ret;
}
w->num_wifi_device_obj++;
wifimngr_dbg("Added '%s' radio obj\n", wobj->obj.name);
wdev->object_id = wobj->obj.id;
list_add_tail(&wobj->list, &w->radiolist);
return 0;
}
#define MAX_AP_METHODS 48
static int add_ap_methods(struct wifimngr *w, struct ubus_object *interface_obj,
const char *ifname)
{
struct ubus_method *ap_methods;
int n_methods = 0;
ap_methods = calloc(MAX_AP_METHODS, sizeof(struct ubus_method));
if (!ap_methods)
return -ENOMEM;
UBUS_METHOD_ADD(ap_methods, n_methods,
UBUS_METHOD_NOARG("help", wl_ap_help));
UBUS_METHOD_ADD(ap_methods, n_methods,
UBUS_METHOD_NOARG("status", wl_ap_status));
UBUS_METHOD_ADD(ap_methods, n_methods,
UBUS_METHOD_NOARG("stats", wl_ap_stats));
UBUS_METHOD_ADD(ap_methods, n_methods,
UBUS_METHOD_NOARG("assoclist", wl_assoclist));
UBUS_METHOD_ADD(ap_methods, n_methods,
UBUS_METHOD("stations", wl_stations, stainfo_policy));
if (libsta_ratings) {
UBUS_METHOD_ADD(ap_methods, n_methods,
UBUS_METHOD("sta_ratings", wl_sta_ratings, stainfo_policy));
}
if (libwifi_supports(ifname, "wifi_get_blocked_stas")) {
UBUS_METHOD_ADD(ap_methods, n_methods,
UBUS_METHOD_NOARG("blocked_stas", wl_blocked_stas));
}
if (libwifi_supports(ifname, "wifi_block_sta")) {
UBUS_METHOD_ADD(ap_methods, n_methods,
UBUS_METHOD("block_sta", wl_block_sta, block_station_policy));
}
if (libwifi_supports(ifname, "wifi_disconnect_sta")) {
UBUS_METHOD_ADD(ap_methods, n_methods,
UBUS_METHOD("disconnect", sta_disconnect, sta_disconnect_policy));
}
if (libwifi_supports(ifname, "wifi_probe_sta")) {
UBUS_METHOD_ADD(ap_methods, n_methods,
UBUS_METHOD("probe_sta", sta_probe, sta_monitor_policy));
}
if (libwifi_supports(ifname, "wifi_monitor_sta")) {
UBUS_METHOD_ADD(ap_methods, n_methods,
UBUS_METHOD("monitor_add", sta_monitor_add, sta_monitor_policy));
UBUS_METHOD_ADD(ap_methods, n_methods,
UBUS_METHOD("monitor_del", sta_monitor_del, sta_monitor_policy));
UBUS_METHOD_ADD(ap_methods, n_methods,
UBUS_METHOD("monitor_get", sta_monitor_get, sta_monitor_policy));
}
if (libwifi_supports(ifname, "wifi_subscribe_frame"))
UBUS_METHOD_ADD(ap_methods, n_methods,
UBUS_METHOD("subscribe_frame", subscribe_frame, subscribe_frame_policy));
if (libwifi_supports(ifname, "wifi_unsubscribe_frame"))
UBUS_METHOD_ADD(ap_methods, n_methods,
UBUS_METHOD("unsubscribe_frame", unsubscribe_frame, subscribe_frame_policy));
if (libwifi_supports(ifname, "wifi_add_neighbor"))
UBUS_METHOD_ADD(ap_methods, n_methods,
UBUS_METHOD("add_neighbor", nbr_add, nbr_add_policy));
if (libwifi_supports(ifname, "wifi_del_neighbor"))
UBUS_METHOD_ADD(ap_methods, n_methods,
UBUS_METHOD("del_neighbor", nbr_del, nbr_del_policy));
if (libwifi_supports(ifname, "wifi_get_neighbor_list"))
UBUS_METHOD_ADD(ap_methods, n_methods,
UBUS_METHOD("list_neighbor", nbr_list, nbr_list_policy));
if (libwifi_supports(ifname, "wifi_req_beacon_report"))
UBUS_METHOD_ADD(ap_methods, n_methods,
UBUS_METHOD("request_neighbor", nbr_request, nbr_req_policy));
if (libwifi_supports(ifname, "wifi_req_btm"))
UBUS_METHOD_ADD(ap_methods, n_methods,
UBUS_METHOD("request_btm", btm_request, btmreq_policy));
if (libwifi_supports(ifname, "wifi_restrict_sta"))
UBUS_METHOD_ADD(ap_methods, n_methods,
UBUS_METHOD("assoc_control", assoc_control, assoc_cntrl_policy));
if (libwifi_supports(ifname, "wifi_add_vendor_ie"))
UBUS_METHOD_ADD(ap_methods, n_methods,
UBUS_METHOD("add_vendor_ie", vsie_add, vsie_policy));
if (libwifi_supports(ifname, "wifi_del_vendor_ie"))
UBUS_METHOD_ADD(ap_methods, n_methods,
UBUS_METHOD("del_vendor_ie", vsie_del, vsie_policy));
if (libwifi_supports(ifname, "wifi_get_beacon_ies"))
UBUS_METHOD_ADD(ap_methods, n_methods,
UBUS_METHOD_NOARG("dump_beacon", wl_ap_dump_beacon));
if (libwifi_supports(ifname, "wifi_chan_switch"))
UBUS_METHOD_ADD(ap_methods, n_methods,
UBUS_METHOD("chan_switch", ap_chan_switch, chan_switch_policy));
if (libwifi_supports(ifname, "wifi_link_measure"))
UBUS_METHOD_ADD(ap_methods, n_methods,
UBUS_METHOD("measure_link", ap_measure_link, linkmeas_policy));
if (libwifi_supports(ifname, "wifi_mbo_disallow_assoc"))
UBUS_METHOD_ADD(ap_methods, n_methods,
UBUS_METHOD("mbo_disallow_assoc", ap_mbo_disallow_assoc, mbo_disallow_assoc_policy));
if (libwifi_supports(ifname, "wifi_ap_set_state")) {
UBUS_METHOD_ADD(ap_methods, n_methods,
UBUS_METHOD_NOARG("up", ap_bss_up));
UBUS_METHOD_ADD(ap_methods, n_methods,
UBUS_METHOD_NOARG("down", ap_bss_down));
}
if (libwifi_supports(ifname, "wifi_send_action_frame")) {
UBUS_METHOD_ADD(ap_methods, n_methods,
UBUS_METHOD("send_action", ap_send_action, send_action_policy));
}
if (libwifi_supports(ifname, "wifi_ap_set_qos_map")) {
UBUS_METHOD_ADD(ap_methods, n_methods,
UBUS_METHOD("set_qos_map", set_qos_map,
ap_set_qos_map_policy));
}
if (libwifi_supports(ifname, "wifi_ap_send_qos_map_conf")) {
UBUS_METHOD_ADD(ap_methods, n_methods,
UBUS_METHOD("send_qos_map_conf", send_qos_map_conf,
ap_send_qos_map_conf_policy));
}
interface_obj->methods = ap_methods;
interface_obj->n_methods = n_methods;
return 0;
}
#define MAX_STA_METHODS 8
static int add_sta_methods(struct wifimngr *w, struct ubus_object *interface_obj,
const char *ifname)
{
int n_methods = 0;
struct ubus_method *sta_methods;
sta_methods = calloc(MAX_STA_METHODS, sizeof(struct ubus_method));
if (!sta_methods)
return -ENOMEM;
UBUS_METHOD_ADD(sta_methods, n_methods,
UBUS_METHOD_NOARG("status", wl_sta_status));
UBUS_METHOD_ADD(sta_methods, n_methods,
UBUS_METHOD_NOARG("stats", wl_sta_stats));
if (libwifi_supports(ifname, "wifi_sta_disconnect_ap")) {
UBUS_METHOD_ADD(sta_methods, n_methods,
UBUS_METHOD("disconnect", wl_sta_disconnect_ap,
ap_disconnect_policy));
}
if (libwifi_supports(ifname, "wifi_set_4addr")) {
UBUS_METHOD_ADD(sta_methods, n_methods,
UBUS_METHOD("4addr", wl_sta_4addr,
sta_4addr_policy));
}
if (libwifi_supports(ifname, "wifi_send_action_frame")) {
UBUS_METHOD_ADD(sta_methods, n_methods,
UBUS_METHOD("send_action", ap_send_action, send_action_policy));
}
if (libwifi_supports(ifname, "wifi_dpp_listen")) {
UBUS_METHOD_ADD(sta_methods, n_methods,
UBUS_METHOD("dpp_listen", wl_sta_dpp_listen, dpp_listen_policy));
}
if (libwifi_supports(ifname, "wifi_dpp_stop_listen")) {
UBUS_METHOD_ADD(sta_methods, n_methods,
UBUS_METHOD_NOARG("dpp_stop_listen", wl_sta_dpp_stop_listen));
}
interface_obj->methods = sta_methods;
interface_obj->n_methods = n_methods;
return 0;
}
int wifimngr_add_interface_object(struct wifimngr *w, struct wifimngr_iface *iface)
{
struct wifi_ubus_object *wobj;
char objname[64] = {0};
uint32_t id;
int ret;
if (iface->mode == WIFI_MODE_AP) {
snprintf(objname, 63, "%s.%s", WIFI_AP_OBJECT, iface->iface);
} else if (iface->mode == WIFI_MODE_STA) {
snprintf(objname, 63, "%s.%s", WIFI_BSTA_OBJECT, iface->iface);
} else {
/* unhandled wifi mode */
return -EINVAL;
}
/* Already added */
if (ubus_lookup_id(w->ubus_ctx, objname, &id) == UBUS_STATUS_OK) {
iface->object_id = id;
return 0;
}
wobj = calloc(1, sizeof(struct wifi_ubus_object));
if (!wobj)
return -ENOMEM;
wobj->priv = iface;
if (iface->mode == WIFI_MODE_AP)
add_ap_methods(w, &wobj->obj, iface->iface);
else
add_sta_methods(w, &wobj->obj, iface->iface);
wobj->obj.name = strdup(objname);
wobj->obj_type.name = wobj->obj.name;
wobj->obj_type.n_methods = wobj->obj.n_methods;
wobj->obj_type.methods = wobj->obj.methods;
wobj->obj.type = &wobj->obj_type;
ret = ubus_add_object(w->ubus_ctx, &wobj->obj);
if (!ret) {
iface->object_id = wobj->obj.id;
list_add_tail(&wobj->list, &w->iflist);
} else {
free((void *)wobj->obj.methods);
free((void *)wobj->obj.name);
free(wobj);
}
return ret;
}
#define MAX_APMLD_METHODS 16
static int add_apmld_methods(struct wifimngr *w,
struct ubus_object *interface_obj,
const char *ifname)
{
struct ubus_method *apmld_methods;
int n_methods = 0;
apmld_methods = calloc(MAX_APMLD_METHODS, sizeof(struct ubus_method));
if (!apmld_methods)
return -ENOMEM;
UBUS_METHOD_ADD(apmld_methods, n_methods,
UBUS_METHOD_NOARG("help", wl_apmld_help));
UBUS_METHOD_ADD(apmld_methods, n_methods,
UBUS_METHOD_NOARG("status", wl_apmld_status));
UBUS_METHOD_ADD(apmld_methods, n_methods,
UBUS_METHOD_NOARG("stats", wl_apmld_stats));
UBUS_METHOD_ADD(apmld_methods, n_methods,
UBUS_METHOD_NOARG("assoclist", wl_apmld_assoclist));
UBUS_METHOD_ADD(apmld_methods, n_methods,
UBUS_METHOD("stations", wl_apmld_stations, stainfo_policy));
if (libsta_ratings) {
UBUS_METHOD_ADD(apmld_methods, n_methods,
UBUS_METHOD("sta_ratings", wl_apmld_sta_ratings, stainfo_policy));
}
if (libwifi_supports(ifname, "wifi_disconnect_sta")) {
UBUS_METHOD_ADD(apmld_methods, n_methods,
UBUS_METHOD("disconnect", wl_apmld_disconnect_sta, sta_disconnect_policy));
}
if (libwifi_supports(ifname, "wifi_block_sta")) {
UBUS_METHOD_ADD(apmld_methods, n_methods,
UBUS_METHOD("block_sta", wl_apmld_block_sta, apmld_block_station_policy));
}
if (libwifi_supports(ifname, "wifi_get_blocked_stas")) {
UBUS_METHOD_ADD(apmld_methods, n_methods,
UBUS_METHOD("blocked_stas", wl_apmld_blocked_stas, apmld_blocked_maclist_policy));
}
if (libwifi_supports(ifname, "wifi_get_beacon_ies")) {
UBUS_METHOD_ADD(apmld_methods, n_methods,
UBUS_METHOD("dump_beacon", wl_apmld_dump_beacon, dump_beacon_policy));
}
interface_obj->methods = apmld_methods;
interface_obj->n_methods = n_methods;
return 0;
}
#define MAX_MLDSTA_METHODS 8
static int add_mldsta_methods(struct wifimngr *w,
struct ubus_object *interface_obj,
const char *ifname)
{
struct ubus_method *mldsta_methods;
int n_methods = 0;
mldsta_methods = calloc(MAX_MLDSTA_METHODS, sizeof(struct ubus_method));
if (!mldsta_methods)
return -ENOMEM;
UBUS_METHOD_ADD(mldsta_methods, n_methods,
UBUS_METHOD_NOARG("status", wl_mldsta_status));
UBUS_METHOD_ADD(mldsta_methods, n_methods,
UBUS_METHOD_NOARG("stats", wl_mldsta_stats));
if (libwifi_supports(ifname, "wifi_sta_disconnect_ap")) {
UBUS_METHOD_ADD(mldsta_methods, n_methods,
UBUS_METHOD("disconnect", wl_mldsta_disconnect_ap,
ap_disconnect_policy));
}
if (libwifi_supports(ifname, "wifi_set_4addr")) {
UBUS_METHOD_ADD(mldsta_methods, n_methods,
UBUS_METHOD("4addr", wl_sta_4addr,
sta_4addr_policy));
}
interface_obj->methods = mldsta_methods;
interface_obj->n_methods = n_methods;
return 0;
}
int wifimngr_add_mld_interface_object(struct wifimngr *w, struct wifimngr_mld *mldif)
{
struct wifi_ubus_object *wobj;
char objname[64] = {0};
uint32_t id;
int ret;
if (mldif->mode == WIFI_MODE_AP)
snprintf(objname, 63, "%s.%s", WIFI_APMLD_OBJECT, mldif->ifname);
else if (mldif->mode == WIFI_MODE_STA)
snprintf(objname, 63, "%s.%s", WIFI_BSTAMLD_OBJECT, mldif->ifname);
else
return -EINVAL;
/* Already added */
if (ubus_lookup_id(w->ubus_ctx, objname, &id) == UBUS_STATUS_OK) {
mldif->object_id = id;
return 0;
}
wobj = calloc(1, sizeof(struct wifi_ubus_object));
if (!wobj)
return -ENOMEM;
wobj->priv = mldif;
if (mldif->mode == WIFI_MODE_AP)
add_apmld_methods(w, &wobj->obj, mldif->ifname);
else
add_mldsta_methods(w, &wobj->obj, mldif->ifname);
wobj->obj.name = strdup(objname);
wobj->obj_type.name = wobj->obj.name;
wobj->obj_type.n_methods = wobj->obj.n_methods;
wobj->obj_type.methods = wobj->obj.methods;
wobj->obj.type = &wobj->obj_type;
ret = ubus_add_object(w->ubus_ctx, &wobj->obj);
if (!ret) {
mldif->object_id = wobj->obj.id;
list_add_tail(&wobj->list, &w->iflist);
} else {
free((void *)wobj->obj.methods);
free((void *)wobj->obj.name);
free(wobj);
}
return ret;
}
void wifimngr_del_object(struct wifimngr *w, struct ubus_object *obj, bool remove_from_ubus)
{
/* Remove from ubus before freeing memory to avoid use-after-free.
* Skip removal only during final cleanup when ubus_free() will handle it. */
if (remove_from_ubus && w->ubus_ctx && obj->id)
ubus_remove_object(w->ubus_ctx, obj);
if (obj->methods)
free((void *)obj->methods);
if (obj->name)
free((void *)obj->name);
}
int wifimngr_add_objects(struct wifimngr *w)
{
int ret;
ret = wifimngr_add_object(w, WIFI_OBJECT, add_wifi_methods, &w->wifi_obj);
if (ret) {
wifimngr_err("Failed to add '%s' ubus object: %s\n",
WIFI_OBJECT, ubus_strerror(ret));
goto out_exit;
}
ret = wifimngr_add_object(w, WIFI_WPS_OBJECT, add_wps_methods, &w->wifi_wps_obj);
if (ret) {
wifimngr_err("Failed to add '%s' ubus object: %s\n",
WIFI_WPS_OBJECT, ubus_strerror(ret));
goto out_exit;
}
wifimngr_reconfig(w);
return 0;
out_exit:
return -1;
}