[OpenWrt-Devel,1/5] hostapd: add ubus hostapd_iface object

Message ID 20181008124520.30040-1-yshvedov@wimarksystems.com
State New
Delegated to: Felix Fietkau
Headers show
Series
  • [OpenWrt-Devel,1/5] hostapd: add ubus hostapd_iface object
Related show

Commit Message

Yury Shvedov Oct. 8, 2018, 12:45 p.m.
Ubus hostapd_iface object has get_state and get_bss methods, this patch
additionally sends events with interfaces' states. This allows outer
system to watch interfaces prior they enabled and handle the errors.

This actually reverts the  f0ac9afe695ed297caf093f02144b2adf04bca87
patch and adds functionality using hostapd_ubus_iface struct.

Signed-off-by: Yury Shvedov <yshvedov@wimarksystems.com>
---
 .../hostapd/patches/600-ubus_support.patch    |  54 +++++++-
 .../services/hostapd/src/src/ap/ubus.c        | 127 ++++++++++++++++++
 .../services/hostapd/src/src/ap/ubus.h        |  13 ++
 3 files changed, 193 insertions(+), 1 deletion(-)

Patch

diff --git a/package/network/services/hostapd/patches/600-ubus_support.patch b/package/network/services/hostapd/patches/600-ubus_support.patch
index cb2c54d57c..c63b85c079 100644
--- a/package/network/services/hostapd/patches/600-ubus_support.patch
+++ b/package/network/services/hostapd/patches/600-ubus_support.patch
@@ -30,7 +30,16 @@ 
  	int interface_added; /* virtual interface added for this BSS */
  	unsigned int started:1;
  	unsigned int disabled:1;
-@@ -544,6 +546,7 @@ hostapd_alloc_bss_data(struct hostapd_if
+@@ -392,6 +394,8 @@ struct hostapd_iface {
+ 	struct hostapd_config *conf;
+ 	char phy[16]; /* Name of the PHY (radio) */
+ 
++	struct hostapd_ubus_iface ubus;
++
+ 	enum hostapd_iface_state {
+ 		HAPD_IFACE_UNINITIALIZED,
+ 		HAPD_IFACE_DISABLED,
+@@ -544,6 +548,7 @@ hostapd_alloc_bss_data(struct hostapd_if
  		       struct hostapd_bss_config *bss);
  int hostapd_setup_interface(struct hostapd_iface *iface);
  int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err);
@@ -90,6 +99,14 @@ 
  	hostapd_interface_deinit(iface);
  	wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit",
  		   __func__, driver, drv_priv);
+@@ -3114,6 +3120,7 @@ void hostapd_set_state(struct hostapd_if
+ 	wpa_printf(MSG_INFO, "%s: interface state %s->%s",
+ 		   iface->conf ? iface->conf->bss[0]->iface : "N/A",
+ 		   hostapd_state_text(iface->state), hostapd_state_text(s));
++	hostapd_ubus_event_iface_state(iface, s);
+ 	iface->state = s;
+ }
+ 
 --- a/src/ap/ieee802_11.c
 +++ b/src/ap/ieee802_11.c
 @@ -1712,12 +1712,13 @@ ieee802_11_set_radius_info(struct hostap
@@ -341,3 +358,38 @@ 
  }
  
  
+--- a/hostapd/config_file.c
++++ b/hostapd/config_file.c
+@@ -2663,6 +2663,11 @@ static int hostapd_config_fill(struct ho
+ 		   0) {
+ 		bss->radius_das_require_message_authenticator = atoi(pos);
+ #endif /* CONFIG_NO_RADIUS */
++#ifdef UBUS_SUPPORT
++	} else if (os_strcmp(buf, "uci_device") == 0) {
++		os_free(bss->uci_device);
++		bss->uci_device = os_strdup(pos);
++#endif /* UBUS_SUPPORT */
+ 	} else if (os_strcmp(buf, "auth_algs") == 0) {
+ 		bss->auth_algs = atoi(pos);
+ 		if (bss->auth_algs == 0) {
+--- a/src/ap/ap_config.c
++++ b/src/ap/ap_config.c
+@@ -587,6 +587,7 @@ void hostapd_config_free_bss(struct host
+ 	os_free(conf->model_description);
+ 	os_free(conf->model_url);
+ 	os_free(conf->upc);
++	os_free(conf->uci_device);
+ 	{
+ 		unsigned int i;
+ 
+--- a/src/ap/ap_config.h
++++ b/src/ap/ap_config.h
+@@ -470,6 +470,8 @@ struct hostapd_bss_config {
+ 	int pbc_in_m1;
+ 	char *server_id;
+ 
++	char *uci_device;
++
+ #define P2P_ENABLED BIT(0)
+ #define P2P_GROUP_OWNER BIT(1)
+ #define P2P_GROUP_FORMATION BIT(2)
diff --git a/package/network/services/hostapd/src/src/ap/ubus.c b/package/network/services/hostapd/src/src/ap/ubus.c
index 3375ac49f7..a393451af2 100644
--- a/package/network/services/hostapd/src/src/ap/ubus.c
+++ b/package/network/services/hostapd/src/src/ap/ubus.c
@@ -92,16 +92,109 @@  static void hostapd_ubus_ref_dec(void)
 	ctx = NULL;
 }
 
+static int
+hostapd_iface_get_state(struct ubus_context *ctx, struct ubus_object *obj,
+			struct ubus_request_data *req, const char *method,
+			struct blob_attr *msg)
+{
+	struct hostapd_iface *iface = container_of(obj, struct hostapd_iface,
+			ubus.obj);
+
+	blob_buf_init(&b, 0);
+	blobmsg_add_u32(&b, "state_num", iface->state);
+	blobmsg_add_string(&b, "state", hostapd_state_text(iface->state));
+	blobmsg_add_u32(&b, "freq", iface->freq);
+	if (iface->bss[0] && iface->bss[0]->conf->uci_device)
+		blobmsg_add_string(&b, "device", iface->bss[0]->conf->uci_device);
+	ubus_send_reply(ctx, req, b.head);
+
+	return 0;
+}
+static int
+hostapd_iface_get_bss(struct ubus_context *ctx, struct ubus_object *obj,
+			struct ubus_request_data *req, const char *method,
+			struct blob_attr *msg)
+{
+	struct hostapd_iface *iface = container_of(obj, struct hostapd_iface,
+			ubus.obj);
+	struct hostapd_data *bss;
+	void *a,*h;
+	int i;
+	const char *state = hostapd_state_text(iface->state);
+
+	blob_buf_init(&b, 0);
+	blobmsg_add_u32(&b, "state_num", iface->state);
+	blobmsg_add_string(&b, "state", state);
+	blobmsg_add_u32(&b, "freq", iface->freq);
+	if (iface->bss[0] && iface->bss[0]->conf->uci_device)
+		blobmsg_add_string(&b, "device", iface->bss[0]->conf->uci_device);
+	a = blobmsg_open_array(&b, "bss");
+	for (i=0; i<iface->num_bss; ++i) {
+		bss = iface->bss[i];
+		h = blobmsg_open_table(&b, NULL);
+		blobmsg_add_string(&b, "iface", bss->conf->iface);
+		blobmsg_add_string(&b, "state", state);
+		if (bss->conf->uci_device)
+			blobmsg_add_string(&b, "device", bss->conf->uci_device);
+		if (bss->ubus.obj.id)
+			blobmsg_add_string(&b, "uobject", bss->ubus.obj.name);
+		blobmsg_close_table(&b, h);
+	}
+	blobmsg_close_array(&b, a);
+	ubus_send_reply(ctx, req, b.head);
+
+	return 0;
+}
+static const struct ubus_method iface_methods[] = {
+	UBUS_METHOD_NOARG("get_state", hostapd_iface_get_state),
+	UBUS_METHOD_NOARG("get_bss", hostapd_iface_get_bss),
+};
+static struct ubus_object_type iface_object_type =
+	UBUS_OBJECT_TYPE("hostapd_iface", iface_methods);
+
 void hostapd_ubus_add_iface(struct hostapd_iface *iface)
 {
+	struct ubus_object *obj = &iface->ubus.obj;
+	char *name, *ifname = NULL;
+	int ret;
+
 	if (!hostapd_ubus_init())
 		return;
+
+	if (obj->id)
+		return;
+
+	if (iface->bss[0] && iface->bss[0]->conf->uci_device)
+		ifname = iface->bss[0]->conf->uci_device;
+	else
+		ifname = iface->phy;
+
+	if (asprintf(&name, "hostapd_iface.%s", ifname) < 0)
+		return;
+
+	obj->name = name;
+	obj->type = &iface_object_type;
+	obj->methods = iface_object_type.methods;
+	obj->n_methods = iface_object_type.n_methods;
+	ret = ubus_add_object(ctx, obj);
+	hostapd_ubus_ref_inc();
 }
 
 void hostapd_ubus_free_iface(struct hostapd_iface *iface)
 {
+	struct ubus_object *obj = &iface->ubus.obj;
+	char *name = (char *) obj->name;
+
 	if (!ctx)
 		return;
+
+	if (obj->id) {
+		ubus_remove_object(ctx, obj);
+		hostapd_ubus_ref_dec();
+	}
+
+	free(name);
+	obj->name = NULL;
 }
 
 static void
@@ -1019,6 +1112,7 @@  void hostapd_ubus_free_bss(struct hostapd_data *hapd)
 	}
 
 	free(name);
+	obj->name = NULL;
 }
 
 struct ubus_event_req {
@@ -1033,6 +1127,13 @@  ubus_event_cb(struct ubus_notify_request *req, int idx, int ret)
 
 	ureq->resp = ret;
 }
+static void blobmsg_add_hapd_id(struct blob_buf *buf, struct hostapd_data *hapd)
+{
+	if (hapd->conf->uci_device)
+		blobmsg_add_string(buf, "device", hapd->conf->uci_device);
+	blobmsg_add_macaddr(buf, "bssid", hapd->own_addr);
+	blobmsg_add_string(buf, "iface", hapd->conf->iface);
+}
 
 int hostapd_ubus_handle_event(struct hostapd_data *hapd, struct hostapd_ubus_request *req)
 {
@@ -1110,6 +1211,8 @@  int hostapd_ubus_handle_event(struct hostapd_data *hapd, struct hostapd_ubus_req
 		}
 	}
 
+	blobmsg_add_hapd_id(&b, hapd);
+
 	if (!hapd->ubus.notify_response) {
 		ubus_notify(ctx, &hapd->ubus.obj, type, b.head, -1);
 		return WLAN_STATUS_SUCCESS;
@@ -1138,5 +1241,29 @@  void hostapd_ubus_notify(struct hostapd_data *hapd, const char *type, const u8 *
 	blob_buf_init(&b, 0);
 	blobmsg_add_macaddr(&b, "address", addr);
 
+	blobmsg_add_hapd_id(&b, hapd);
 	ubus_notify(ctx, &hapd->ubus.obj, type, b.head, -1);
 }
+
+/* Send ubus event in case new event differs. */
+void hostapd_ubus_event_iface_state(struct hostapd_iface *iface, int s)
+{
+	struct hostapd_data *hapd = iface->bss[0];
+
+	if (!hostapd_ubus_init())
+		return;
+	hostapd_ubus_add_iface(iface);
+	if (iface->state == s) {
+		return;
+	}
+	blob_buf_init(&b, 0);
+	if (hapd && hapd->conf->uci_device)
+		blobmsg_add_string(&b, "device", hapd->conf->uci_device);
+	if (iface->ubus.obj.id)
+		blobmsg_add_string(&b, "uobject", iface->ubus.obj.name);
+	blobmsg_add_u32(&b, "oldstate_num", iface->state);
+	blobmsg_add_string(&b, "oldstate", hostapd_state_text(iface->state));
+	blobmsg_add_u32(&b, "state_num", s);
+	blobmsg_add_string(&b, "state", hostapd_state_text(s));
+	ubus_send_event(ctx, "hostapd.iface_state", b.head);
+}
diff --git a/package/network/services/hostapd/src/src/ap/ubus.h b/package/network/services/hostapd/src/src/ap/ubus.h
index 185af5a7f4..840b000180 100644
--- a/package/network/services/hostapd/src/src/ap/ubus.h
+++ b/package/network/services/hostapd/src/src/ap/ubus.h
@@ -8,6 +8,8 @@ 
 #ifndef __HOSTAPD_UBUS_H
 #define __HOSTAPD_UBUS_H
 
+#include "hostapd.h"
+
 enum hostapd_ubus_event_type {
 	HOSTAPD_UBUS_PROBE_REQ,
 	HOSTAPD_UBUS_AUTH_REQ,
@@ -31,6 +33,10 @@  struct hostapd_data;
 #include <libubox/avl.h>
 #include <libubus.h>
 
+struct hostapd_ubus_iface {
+	struct ubus_object obj;
+};
+
 struct hostapd_ubus_bss {
 	struct ubus_object obj;
 	struct avl_tree banned;
@@ -45,8 +51,12 @@  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_event_iface_state(struct hostapd_iface *iface, int s);
+
 #else
 
+struct hostapd_ubus_iface {};
+
 struct hostapd_ubus_bss {};
 
 static inline void hostapd_ubus_add_iface(struct hostapd_iface *iface)
@@ -73,6 +83,9 @@  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_event_iface_state(struct hostapd_iface *iface, int s)
+{
+}
 #endif
 
 #endif