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
