diff --git a/wireless/wifictld/files/etc/init.d/wifictld b/wireless/wifictld/files/etc/init.d/wifictld index 6990313..fb42f08 100644 --- a/wireless/wifictld/files/etc/init.d/wifictld +++ b/wireless/wifictld/files/etc/init.d/wifictld @@ -14,9 +14,14 @@ start_service () { procd_set_param stderr 1 procd_set_param respawn ${respawn_threshold:-3660} ${respawn_timeout:-5} ${respawn_retry:-0} procd_set_param command "$PROG" + procd_set_param watch network.wireless procd_close_instance } +reload_service () { + ubus call wifictld rebind > /dev/null +} + service_triggers() { local script=$(readlink "$initscript") local name=$(basename "${script:-$initscript}") diff --git a/wireless/wifictld/src/include.h b/wireless/wifictld/src/include.h index 1eee0fc..1428e47 100644 --- a/wireless/wifictld/src/include.h +++ b/wireless/wifictld/src/include.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include diff --git a/wireless/wifictld/src/ubus.c b/wireless/wifictld/src/ubus.c index 7d8a48e..b3c12bd 100644 --- a/wireless/wifictld/src/ubus.c +++ b/wireless/wifictld/src/ubus.c @@ -48,6 +48,7 @@ int wifictld_ubus_init() // close ubus connection void wifictld_ubus_close() { + wifictld_ubus_unbind_events(ctx); ubus_free(ctx); } diff --git a/wireless/wifictld/src/ubus_events.c b/wireless/wifictld/src/ubus_events.c index 357984b..886ad84 100644 --- a/wireless/wifictld/src/ubus_events.c +++ b/wireless/wifictld/src/ubus_events.c @@ -3,6 +3,10 @@ #include "log.h" #include "wifi_clients.h" +#include "ubus_events.h" + +struct avl_tree ubus_hostapd_binds = {}; + // bind on every hostapd by receive all ubus registered services static void recieve_interfaces(struct ubus_context *ctx, struct ubus_object_data *obj, void *priv); @@ -23,6 +27,8 @@ struct ubus_subscriber sub = { */ int wifictld_ubus_bind_events(struct ubus_context *ctx) { + avl_init(&ubus_hostapd_binds, avl_blobcmp, false, NULL); + // register subscriber on ubus int ret = ubus_register_subscriber(ctx, &sub); if (ret) { @@ -36,6 +42,15 @@ int wifictld_ubus_bind_events(struct ubus_context *ctx) return 0; } +int wifictld_ubus_unbind_events(struct ubus_context *ctx) +{ + struct ubus_hostapd_bind *el, *ptr; + avl_remove_all_elements(&ubus_hostapd_binds, el, avl, ptr) { + ubus_unsubscribe(ctx, &sub, el->id); + log_info("unsubscribe %s\n", el->path); + } +} + static void recieve_interfaces(struct ubus_context *ctx, struct ubus_object_data *obj, void *priv) { int ret = 0; @@ -77,6 +92,15 @@ static void recieve_interfaces(struct ubus_context *ctx, struct ubus_object_data log_error("Error while register subscribe for event '%s': %s\n", path, ubus_strerror(ret)); } + // store binding for unsubscribe (reload) + struct ubus_hostapd_bind *bind; + bind = malloc(sizeof(*bind)); + bind->path = path; + bind->id = id; + bind->avl.key = &bind->id; + + avl_insert(&ubus_hostapd_binds, &bind->avl); + log_info("subscribe %s\n", path); } diff --git a/wireless/wifictld/src/ubus_events.h b/wireless/wifictld/src/ubus_events.h index 52c43c9..c17e87b 100644 --- a/wireless/wifictld/src/ubus_events.h +++ b/wireless/wifictld/src/ubus_events.h @@ -3,6 +3,16 @@ #include "include.h" +extern struct avl_tree ubus_hostapd_binds; + + +struct ubus_hostapd_bind { + struct avl_node avl; + int id; + char *path; +}; + int wifictld_ubus_bind_events(struct ubus_context *ctx); +int wifictld_ubus_unbind_events(struct ubus_context *ctx); #endif diff --git a/wireless/wifictld/src/ubus_service.c b/wireless/wifictld/src/ubus_service.c index 254064f..f0a3af4 100644 --- a/wireless/wifictld/src/ubus_service.c +++ b/wireless/wifictld/src/ubus_service.c @@ -4,6 +4,8 @@ #include "data.h" #include "wifi_clients.h" +#include "ubus_events.h" + static struct blob_buf b = {}; static int ubus_get_clients(struct ubus_context *ctx, struct ubus_object *obj, @@ -164,6 +166,59 @@ static int ubus_set_config(struct ubus_context *ctx, struct ubus_object *obj, } +static int ubus_bind(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, struct blob_attr *msg) +{ + void *array; + struct ubus_hostapd_bind *el; + + blob_buf_init(&b, 0); + + array = blobmsg_open_array(&b, "current"); + avl_for_each_element(&ubus_hostapd_binds, el, avl) { + blobmsg_add_string(&b, el->path , el->path); + } + blobmsg_close_array(&b, array); + + // end + ubus_send_reply(ctx, req, b.head); + + return 0; +} + +static int ubus_rebind(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, struct blob_attr *msg) +{ + void *array; + struct ubus_hostapd_bind *el; + + blob_buf_init(&b, 0); + + // list state before + array = blobmsg_open_array(&b, "before"); + avl_for_each_element(&ubus_hostapd_binds, el, avl) { + blobmsg_add_string(&b, el->path , el->path); + } + blobmsg_close_array(&b, array); + + // remove bind + wifictld_ubus_unbind_events(ctx); + + // new bind + wifictld_ubus_bind_events(ctx); + + // list state after + array = blobmsg_open_array(&b, "current"); + avl_for_each_element(&ubus_hostapd_binds, el, avl) { + blobmsg_add_string(&b, el->path , el->path); + } + blobmsg_close_array(&b, array); + // end + + ubus_send_reply(ctx, req, b.head); + + return 0; +} static const struct ubus_method wifictld_ubus_methods[] = { @@ -174,6 +229,9 @@ static const struct ubus_method wifictld_ubus_methods[] = { // config threasholds UBUS_METHOD_NOARG("get_config", ubus_get_config), UBUS_METHOD("set_config", ubus_set_config, ubus_set_config_policy), + + UBUS_METHOD_NOARG("bind", ubus_bind), + UBUS_METHOD_NOARG("rebind", ubus_rebind), }; static struct ubus_object_type bss_object_type =