aboutsummaryrefslogtreecommitdiffstats
path: root/package/network/services/hostapd/src
diff options
context:
space:
mode:
authorJohn Crispin <john@phrozen.org>2019-10-30 16:57:22 +0100
committerDaniel Golle <daniel@makrotopia.org>2019-11-12 11:52:26 +0100
commit60fb4c92b6b0d1582d31e02167b90b424185f3a2 (patch)
treef707a8fe5cc2e1abf21b51d38f9767f1b1d69996 /package/network/services/hostapd/src
parent155ede4f1fdb192b11f8ae2dbffda5f7ef4903bd (diff)
downloadupstream-60fb4c92b6b0d1582d31e02167b90b424185f3a2.tar.gz
upstream-60fb4c92b6b0d1582d31e02167b90b424185f3a2.tar.bz2
upstream-60fb4c92b6b0d1582d31e02167b90b424185f3a2.zip
hostapd: add ubus reload
Add ubus interface to hostapd and wpa_supplicant to allow dynamically reloading wiface configuration without having to restart the hostapd process. As a consequence, both hostapd and wpa_supplicant are now started persistently on boot for each wifi device in the system and then receive ubus calls adding, modifying or removing interface configuration. At a later stage it would be desirable to reduce the services to one single instance managing all radios. Signed-off-by: John Crispin <john@phrozen.org> Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Diffstat (limited to 'package/network/services/hostapd/src')
-rw-r--r--package/network/services/hostapd/src/src/ap/ubus.c131
-rw-r--r--package/network/services/hostapd/src/src/ap/ubus.h12
-rw-r--r--package/network/services/hostapd/src/wpa_supplicant/ubus.c176
-rw-r--r--package/network/services/hostapd/src/wpa_supplicant/ubus.h13
4 files changed, 328 insertions, 4 deletions
diff --git a/package/network/services/hostapd/src/src/ap/ubus.c b/package/network/services/hostapd/src/src/ap/ubus.c
index 3b768d0e8c..e25c3294ee 100644
--- a/package/network/services/hostapd/src/src/ap/ubus.c
+++ b/package/network/services/hostapd/src/src/ap/ubus.c
@@ -26,12 +26,16 @@ static struct ubus_context *ctx;
static struct blob_buf b;
static int ctx_ref;
+static inline struct hapd_interfaces *get_hapd_interfaces_from_object(struct ubus_object *obj)
+{
+ return container_of(obj, struct hapd_interfaces, ubus);
+}
+
static inline struct hostapd_data *get_hapd_from_object(struct ubus_object *obj)
{
return container_of(obj, struct hostapd_data, ubus.obj);
}
-
struct ubus_banned_client {
struct avl_node avl;
u8 addr[ETH_ALEN];
@@ -143,6 +147,16 @@ hostapd_bss_ban_client(struct hostapd_data *hapd, u8 *addr, int time)
}
static int
+hostapd_bss_reload(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
+ hostapd_reload_config(hapd->iface);
+ hostapd_reload_iface(hapd->iface);
+}
+
+static int
hostapd_bss_get_clients(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
@@ -380,6 +394,70 @@ hostapd_bss_update_beacon(struct ubus_context *ctx, struct ubus_object *obj,
}
enum {
+ CONFIG_IFACE,
+ CONFIG_FILE,
+ __CONFIG_MAX
+};
+
+static const struct blobmsg_policy config_add_policy[__CONFIG_MAX] = {
+ [CONFIG_IFACE] = { "iface", BLOBMSG_TYPE_STRING },
+ [CONFIG_FILE] = { "config", BLOBMSG_TYPE_STRING },
+};
+
+static int
+hostapd_config_add(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct blob_attr *tb[__CONFIG_MAX];
+ struct hapd_interfaces *interfaces = get_hapd_interfaces_from_object(obj);
+ char buf[128];
+
+ blobmsg_parse(config_add_policy, __CONFIG_MAX, tb, blob_data(msg), blob_len(msg));
+
+ if (!tb[CONFIG_FILE] || !tb[CONFIG_IFACE])
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ snprintf(buf, sizeof(buf), "bss_config=%s:%s",
+ blobmsg_get_string(tb[CONFIG_IFACE]),
+ blobmsg_get_string(tb[CONFIG_FILE]));
+
+ if (hostapd_add_iface(interfaces, buf))
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ return UBUS_STATUS_OK;
+}
+
+enum {
+ CONFIG_REM_IFACE,
+ __CONFIG_REM_MAX
+};
+
+static const struct blobmsg_policy config_remove_policy[__CONFIG_REM_MAX] = {
+ [CONFIG_REM_IFACE] = { "iface", BLOBMSG_TYPE_STRING },
+};
+
+static int
+hostapd_config_remove(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct blob_attr *tb[__CONFIG_REM_MAX];
+ struct hapd_interfaces *interfaces = get_hapd_interfaces_from_object(obj);
+ char buf[128];
+
+ blobmsg_parse(config_remove_policy, __CONFIG_REM_MAX, tb, blob_data(msg), blob_len(msg));
+
+ if (!tb[CONFIG_REM_IFACE])
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ if (hostapd_remove_iface(interfaces, blobmsg_get_string(tb[CONFIG_REM_IFACE])))
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ return UBUS_STATUS_OK;
+}
+
+enum {
CSA_FREQ,
CSA_BCN_COUNT,
CSA_CENTER_FREQ1,
@@ -949,6 +1027,7 @@ hostapd_wnm_disassoc_imminent(struct ubus_context *ctx, struct ubus_object *obj,
#endif
static const struct ubus_method bss_methods[] = {
+ UBUS_METHOD_NOARG("reload", hostapd_bss_reload),
UBUS_METHOD_NOARG("get_clients", hostapd_bss_get_clients),
UBUS_METHOD("del_client", hostapd_bss_del_client, del_policy),
UBUS_METHOD_NOARG("list_bans", hostapd_bss_list_bans),
@@ -1021,6 +1100,56 @@ void hostapd_ubus_free_bss(struct hostapd_data *hapd)
free(name);
}
+static const struct ubus_method daemon_methods[] = {
+ UBUS_METHOD("config_add", hostapd_config_add, config_add_policy),
+ UBUS_METHOD("config_remove", hostapd_config_remove, config_remove_policy),
+};
+
+static struct ubus_object_type daemon_object_type =
+ UBUS_OBJECT_TYPE("hostapd", daemon_methods);
+
+void hostapd_ubus_add(struct hapd_interfaces *interfaces)
+{
+ struct ubus_object *obj = &interfaces->ubus;
+ int name_len;
+ int ret;
+
+ if (!hostapd_ubus_init())
+ return;
+
+ name_len = strlen("hostapd") + 1;
+ if (interfaces->name)
+ name_len += strlen(interfaces->name) + 1;
+ obj->name = malloc(name_len);
+ strcpy(obj->name, "hostapd");
+ if (interfaces->name) {
+ strcat(obj->name, ".");
+ strcat(obj->name, interfaces->name);
+ }
+
+ obj->type = &daemon_object_type;
+ obj->methods = daemon_object_type.methods;
+ obj->n_methods = daemon_object_type.n_methods;
+ ret = ubus_add_object(ctx, obj);
+ hostapd_ubus_ref_inc();
+}
+
+void hostapd_ubus_free(struct hapd_interfaces *interfaces)
+{
+ struct ubus_object *obj = &interfaces->ubus;
+ char *name = (char *) obj->name;
+
+ if (!ctx)
+ return;
+
+ if (obj->id) {
+ ubus_remove_object(ctx, obj);
+ hostapd_ubus_ref_dec();
+ }
+
+ free(name);
+}
+
struct ubus_event_req {
struct ubus_notify_request nreq;
int resp;
diff --git a/package/network/services/hostapd/src/src/ap/ubus.h b/package/network/services/hostapd/src/src/ap/ubus.h
index 58ebe0e65b..27acd32659 100644
--- a/package/network/services/hostapd/src/src/ap/ubus.h
+++ b/package/network/services/hostapd/src/src/ap/ubus.h
@@ -25,6 +25,7 @@ struct hostapd_ubus_request {
struct hostapd_iface;
struct hostapd_data;
+struct hapd_interfaces;
#ifdef UBUS_SUPPORT
@@ -45,6 +46,9 @@ void hostapd_ubus_free_bss(struct hostapd_data *hapd);
int hostapd_ubus_handle_event(struct hostapd_data *hapd, struct hostapd_ubus_request *req);
void hostapd_ubus_notify(struct hostapd_data *hapd, const char *type, const u8 *mac);
+void hostapd_ubus_add(struct hapd_interfaces *interfaces);
+void hostapd_ubus_free(struct hapd_interfaces *interfaces);
+
#else
struct hostapd_ubus_bss {};
@@ -73,6 +77,14 @@ static inline int hostapd_ubus_handle_event(struct hostapd_data *hapd, struct ho
static inline void hostapd_ubus_notify(struct hostapd_data *hapd, const char *type, const u8 *mac)
{
}
+
+static inline void hostapd_ubus_add(struct hapd_interfaces *interfaces)
+{
+}
+
+static inline void hostapd_ubus_free(struct hapd_interfaces *interfaces)
+{
+}
#endif
#endif
diff --git a/package/network/services/hostapd/src/wpa_supplicant/ubus.c b/package/network/services/hostapd/src/wpa_supplicant/ubus.c
index 5fdb57be7a..9a98979e9a 100644
--- a/package/network/services/hostapd/src/wpa_supplicant/ubus.c
+++ b/package/network/services/hostapd/src/wpa_supplicant/ubus.c
@@ -20,6 +20,11 @@ static struct ubus_context *ctx;
static struct blob_buf b;
static int ctx_ref;
+static inline struct wpa_global *get_wpa_global_from_object(struct ubus_object *obj)
+{
+ return container_of(obj, struct wpa_global, ubus_global);
+}
+
static inline struct wpa_supplicant *get_wpas_from_object(struct ubus_object *obj)
{
return container_of(obj, struct wpa_supplicant, ubus.obj);
@@ -95,6 +100,19 @@ wpas_bss_get_features(struct ubus_context *ctx, struct ubus_object *obj,
return 0;
}
+static int
+wpas_bss_reload(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct wpa_supplicant *wpa_s = get_wpas_from_object(obj);
+
+ if (wpa_supplicant_reload_configuration(wpa_s))
+ return UBUS_STATUS_UNKNOWN_ERROR;
+ else
+ return 0;
+}
+
#ifdef CONFIG_WPS
enum {
WPS_START_MULTI_AP,
@@ -146,11 +164,12 @@ wpas_bss_wps_cancel(struct ubus_context *ctx, struct ubus_object *obj,
#endif
static const struct ubus_method bss_methods[] = {
+ UBUS_METHOD_NOARG("reload", wpas_bss_reload),
+ UBUS_METHOD_NOARG("get_features", wpas_bss_get_features),
#ifdef CONFIG_WPS
UBUS_METHOD_NOARG("wps_start", wpas_bss_wps_start),
UBUS_METHOD_NOARG("wps_cancel", wpas_bss_wps_cancel),
#endif
- UBUS_METHOD_NOARG("get_features", wpas_bss_get_features),
};
static struct ubus_object_type bss_object_type =
@@ -162,8 +181,6 @@ void wpas_ubus_add_bss(struct wpa_supplicant *wpa_s)
char *name;
int ret;
- if (!wpas_ubus_init())
- return;
if (asprintf(&name, "wpa_supplicant.%s", wpa_s->ifname) < 0)
return;
@@ -192,6 +209,159 @@ void wpas_ubus_free_bss(struct wpa_supplicant *wpa_s)
free(name);
}
+enum {
+ WPAS_CONFIG_DRIVER,
+ WPAS_CONFIG_IFACE,
+ WPAS_CONFIG_BRIDGE,
+ WPAS_CONFIG_HOSTAPD_CTRL,
+ WPAS_CONFIG_CTRL,
+ WPAS_CONFIG_FILE,
+ __WPAS_CONFIG_MAX
+};
+
+static const struct blobmsg_policy wpas_config_add_policy[__WPAS_CONFIG_MAX] = {
+ [WPAS_CONFIG_DRIVER] = { "driver", BLOBMSG_TYPE_STRING },
+ [WPAS_CONFIG_IFACE] = { "iface", BLOBMSG_TYPE_STRING },
+ [WPAS_CONFIG_BRIDGE] = { "bridge", BLOBMSG_TYPE_STRING },
+ [WPAS_CONFIG_HOSTAPD_CTRL] = { "hostapd_ctrl", BLOBMSG_TYPE_STRING },
+ [WPAS_CONFIG_CTRL] = { "ctrl", BLOBMSG_TYPE_STRING },
+ [WPAS_CONFIG_FILE] = { "config", BLOBMSG_TYPE_STRING },
+};
+
+static int
+wpas_config_add(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct blob_attr *tb[__WPAS_CONFIG_MAX];
+ struct wpa_global *global = get_wpa_global_from_object(obj);
+ struct wpa_interface *iface;
+
+ blobmsg_parse(wpas_config_add_policy, __WPAS_CONFIG_MAX, tb, blob_data(msg), blob_len(msg));
+
+ if (!tb[WPAS_CONFIG_FILE] || !tb[WPAS_CONFIG_IFACE] || !tb[WPAS_CONFIG_DRIVER])
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ iface = os_zalloc(sizeof(struct wpa_interface));
+ if (iface == NULL)
+ return UBUS_STATUS_UNKNOWN_ERROR;
+
+ iface->driver = blobmsg_get_string(tb[WPAS_CONFIG_DRIVER]);
+ iface->ifname = blobmsg_get_string(tb[WPAS_CONFIG_IFACE]);
+ iface->confname = blobmsg_get_string(tb[WPAS_CONFIG_FILE]);
+
+ if (tb[WPAS_CONFIG_BRIDGE])
+ iface->bridge_ifname = blobmsg_get_string(tb[WPAS_CONFIG_BRIDGE]);
+
+ if (tb[WPAS_CONFIG_CTRL])
+ iface->ctrl_interface = blobmsg_get_string(tb[WPAS_CONFIG_CTRL]);
+
+ if (tb[WPAS_CONFIG_HOSTAPD_CTRL])
+ iface->hostapd_ctrl = blobmsg_get_string(tb[WPAS_CONFIG_HOSTAPD_CTRL]);
+
+ if (!wpa_supplicant_add_iface(global, iface, NULL))
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ return UBUS_STATUS_OK;
+}
+
+enum {
+ WPAS_CONFIG_REM_IFACE,
+ __WPAS_CONFIG_REM_MAX
+};
+
+static const struct blobmsg_policy wpas_config_remove_policy[__WPAS_CONFIG_REM_MAX] = {
+ [WPAS_CONFIG_REM_IFACE] = { "iface", BLOBMSG_TYPE_STRING },
+};
+
+static int
+wpas_config_remove(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct blob_attr *tb[__WPAS_CONFIG_REM_MAX];
+ struct wpa_global *global = get_wpa_global_from_object(obj);
+ struct wpa_supplicant *wpa_s = NULL;
+ unsigned int found = 0;
+
+ blobmsg_parse(wpas_config_remove_policy, __WPAS_CONFIG_REM_MAX, tb, blob_data(msg), blob_len(msg));
+
+ if (!tb[WPAS_CONFIG_REM_IFACE])
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ /* find wpa_s object for to-be-removed interface */
+ for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
+ if (!strncmp(wpa_s->ifname,
+ blobmsg_get_string(tb[WPAS_CONFIG_REM_IFACE]),
+ sizeof(wpa_s->ifname)))
+ {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found)
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ if (wpa_supplicant_remove_iface(global, wpa_s, 0))
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ return UBUS_STATUS_OK;
+}
+
+static const struct ubus_method wpas_daemon_methods[] = {
+ UBUS_METHOD("config_add", wpas_config_add, wpas_config_add_policy),
+ UBUS_METHOD("config_remove", wpas_config_remove, wpas_config_remove_policy),
+};
+
+static struct ubus_object_type wpas_daemon_object_type =
+ UBUS_OBJECT_TYPE("wpa_supplicant", wpas_daemon_methods);
+
+void wpas_ubus_add(struct wpa_global *global)
+{
+ struct ubus_object *obj = &global->ubus_global;
+ int name_len;
+ int ret;
+
+ if (!wpas_ubus_init())
+ return;
+
+ name_len = strlen("wpa_supplicant") + 1;
+ if (global->params.name)
+ name_len += strlen(global->params.name) + 1;
+ obj->name = malloc(name_len);
+ strcpy(obj->name, "wpa_supplicant");
+
+ if (global->params.name)
+ {
+ strcat(obj->name, ".");
+ strcat(obj->name, global->params.name);
+ }
+
+ obj->type = &wpas_daemon_object_type;
+ obj->methods = wpas_daemon_object_type.methods;
+ obj->n_methods = wpas_daemon_object_type.n_methods;
+ ret = ubus_add_object(ctx, obj);
+ wpas_ubus_ref_inc();
+}
+
+void wpas_ubus_free(struct wpa_global *global)
+{
+ struct ubus_object *obj = &global->ubus_global;
+ char *name = (char *) obj->name;
+
+ if (!ctx)
+ return;
+
+ if (obj->id) {
+ ubus_remove_object(ctx, obj);
+ wpas_ubus_ref_dec();
+ }
+
+ free(name);
+}
+
+
#ifdef CONFIG_WPS
void wpas_ubus_notify(struct wpa_supplicant *wpa_s, const struct wps_credential *cred)
{
diff --git a/package/network/services/hostapd/src/wpa_supplicant/ubus.h b/package/network/services/hostapd/src/wpa_supplicant/ubus.h
index c37e743e73..bf92b98c01 100644
--- a/package/network/services/hostapd/src/wpa_supplicant/ubus.h
+++ b/package/network/services/hostapd/src/wpa_supplicant/ubus.h
@@ -10,6 +10,8 @@
#define __WPAS_UBUS_H
struct wpa_supplicant;
+struct wpa_global;
+
#include "wps_supplicant.h"
#ifdef UBUS_SUPPORT
@@ -22,6 +24,9 @@ struct wpas_ubus_bss {
void wpas_ubus_add_bss(struct wpa_supplicant *wpa_s);
void wpas_ubus_free_bss(struct wpa_supplicant *wpa_s);
+void wpas_ubus_add(struct wpa_global *global);
+void wpas_ubus_free(struct wpa_global *global);
+
#ifdef CONFIG_WPS
void wpas_ubus_notify(struct wpa_supplicant *wpa_s, const struct wps_credential *cred);
#endif
@@ -48,6 +53,14 @@ static inline void wpas_ubus_free_bss(struct wpa_supplicant *wpa_s)
static inline void wpas_ubus_notify(struct wpa_supplicant *wpa_s, struct wps_credential *cred)
{
}
+
+static inline void wpas_ubus_add(struct wpa_global *global)
+{
+}
+
+static inline void wpas_ubus_free(struct wpa_global *global)
+{
+}
#endif
#endif