aboutsummaryrefslogtreecommitdiffstats
path: root/package/network/services/dnsmasq/patches/0052-Improved-UBus-supported.patch
diff options
context:
space:
mode:
Diffstat (limited to 'package/network/services/dnsmasq/patches/0052-Improved-UBus-supported.patch')
-rw-r--r--package/network/services/dnsmasq/patches/0052-Improved-UBus-supported.patch320
1 files changed, 320 insertions, 0 deletions
diff --git a/package/network/services/dnsmasq/patches/0052-Improved-UBus-supported.patch b/package/network/services/dnsmasq/patches/0052-Improved-UBus-supported.patch
new file mode 100644
index 0000000000..f844c0af17
--- /dev/null
+++ b/package/network/services/dnsmasq/patches/0052-Improved-UBus-supported.patch
@@ -0,0 +1,320 @@
+From a2b8220f4e82e454bbc0013ee83ea3220111d92e Mon Sep 17 00:00:00 2001
+From: Jan Willem Janssen <j.w.janssen@lxtreme.nl>
+Date: Mon, 25 Mar 2019 12:42:23 +0100
+Subject: [PATCH 52/57] Improved UBus supported
+
+- aligned the handling of UBus connections with the DBus code as it
+makes it a bit easier to comprehend;
+- added logging to the various UBus calls to aid debugging from an
+enduser point of view, but be careful to not flood the logs;
+- show the (lack of) support for UBus in the configuration string.
+
+Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
+---
+ src/config.h | 4 ++
+ src/dnsmasq.c | 32 +++++++++++-
+ src/dnsmasq.h | 6 +++
+ src/ubus.c | 138 ++++++++++++++++++++++++++++++++++++++++++--------
+ 4 files changed, 157 insertions(+), 23 deletions(-)
+
+--- a/src/config.h
++++ b/src/config.h
+@@ -362,6 +362,10 @@ static char *compile_opts =
+ "no-"
+ #endif
+ "DBus "
++#ifndef HAVE_UBUS
++"no-"
++#endif
++"UBus "
+ #ifndef LOCALEDIR
+ "no-"
+ #endif
+--- a/src/dnsmasq.c
++++ b/src/dnsmasq.c
+@@ -420,6 +420,16 @@ int main (int argc, char **argv)
+ die(_("DBus not available: set HAVE_DBUS in src/config.h"), NULL, EC_BADCONF);
+ #endif
+
++ if (option_bool(OPT_UBUS))
++#ifdef HAVE_UBUS
++ {
++ daemon->ubus = NULL;
++ ubus_init();
++ }
++#else
++ die(_("UBus not available: set HAVE_UBUS in src/config.h"), NULL, EC_BADCONF);
++#endif
++
+ if (daemon->port != 0)
+ pre_allocate_sfds();
+
+@@ -811,6 +821,16 @@ int main (int argc, char **argv)
+ }
+ #endif
+
++#ifdef HAVE_UBUS
++ if (option_bool(OPT_UBUS))
++ {
++ if (daemon->ubus)
++ my_syslog(LOG_INFO, _("UBus support enabled: connected to system bus"));
++ else
++ my_syslog(LOG_INFO, _("UBus support enabled: bus connection pending"));
++ }
++#endif
++
+ #ifdef HAVE_DNSSEC
+ if (option_bool(OPT_DNSSEC_VALID))
+ {
+@@ -999,7 +1019,7 @@ int main (int argc, char **argv)
+
+ #ifdef HAVE_UBUS
+ if (option_bool(OPT_UBUS))
+- set_ubus_listeners();
++ set_ubus_listeners();
+ #endif
+
+ #ifdef HAVE_DHCP
+@@ -1134,7 +1154,15 @@ int main (int argc, char **argv)
+
+ #ifdef HAVE_UBUS
+ if (option_bool(OPT_UBUS))
+- check_ubus_listeners();
++ {
++ /* if we didn't create a UBus connection, retry now. */
++ if (!daemon->ubus)
++ {
++ ubus_init();
++ }
++
++ check_ubus_listeners();
++ }
+ #endif
+
+ check_dns_listeners(now);
+--- a/src/dnsmasq.h
++++ b/src/dnsmasq.h
+@@ -1130,6 +1130,11 @@ extern struct daemon {
+ #ifdef HAVE_DBUS
+ struct watch *watches;
+ #endif
++ /* UBus stuff */
++#ifdef HAVE_UBUS
++ /* void * here to avoid depending on ubus headers outside ubus.c */
++ void *ubus;
++#endif
+
+ /* TFTP stuff */
+ struct tftp_transfer *tftp_trans, *tftp_done_trans;
+@@ -1467,6 +1472,7 @@ void emit_dbus_signal(int action, struct
+
+ /* ubus.c */
+ #ifdef HAVE_UBUS
++void ubus_init(void);
+ void set_ubus_listeners(void);
+ void check_ubus_listeners(void);
+ void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name, const char *interface);
+--- a/src/ubus.c
++++ b/src/ubus.c
+@@ -20,29 +20,112 @@
+
+ #include <libubus.h>
+
+-static struct ubus_context *ubus = NULL;
+ static struct blob_buf b;
++static int notify;
++static int error_logged = 0;
+
+ static int ubus_handle_metrics(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg);
+-static struct ubus_method ubus_object_methods[] = {
+- {.name = "metrics", .handler = ubus_handle_metrics},
++
++static void ubus_subscribe_cb(struct ubus_context *ctx, struct ubus_object *obj);
++
++static const struct ubus_method ubus_object_methods[] = {
++ UBUS_METHOD_NOARG("metrics", ubus_handle_metrics),
+ };
+
+-static struct ubus_object_type ubus_object_type = UBUS_OBJECT_TYPE("dnsmasq", ubus_object_methods);
++static struct ubus_object_type ubus_object_type =
++ UBUS_OBJECT_TYPE("dnsmasq", ubus_object_methods);
+
+ static struct ubus_object ubus_object = {
+ .name = "dnsmasq",
+ .type = &ubus_object_type,
+ .methods = ubus_object_methods,
+ .n_methods = ARRAY_SIZE(ubus_object_methods),
++ .subscribe_cb = ubus_subscribe_cb,
+ };
+
++static void ubus_subscribe_cb(struct ubus_context *ctx, struct ubus_object *obj)
++{
++ (void)ctx;
++
++ my_syslog(LOG_DEBUG, _("UBus subscription callback: %s subscriber(s)"), obj->has_subscribers ? "1" : "0");
++ notify = obj->has_subscribers;
++}
++
++static void ubus_destroy(struct ubus_context *ubus)
++{
++ // Forces re-initialization when we're reusing the same definitions later on.
++ ubus_object.id = 0;
++ ubus_object_type.id = 0;
++
++ ubus_free(ubus);
++ daemon->ubus = NULL;
++}
++
++static void ubus_disconnect_cb(struct ubus_context *ubus)
++{
++ int ret;
++
++ ret = ubus_reconnect(ubus, NULL);
++ if (ret)
++ {
++ my_syslog(LOG_ERR, _("Cannot reconnect to UBus: %s"), ubus_strerror(ret));
++
++ ubus_destroy(ubus);
++ }
++}
++
++void ubus_init()
++{
++ struct ubus_context *ubus = NULL;
++ int ret = 0;
++
++ ubus = ubus_connect(NULL);
++ if (!ubus)
++ {
++ if (!error_logged)
++ {
++ my_syslog(LOG_ERR, _("Cannot initialize UBus: connection failed"));
++ error_logged = 1;
++ }
++
++ ubus_destroy(ubus);
++ return;
++ }
++
++ ret = ubus_add_object(ubus, &ubus_object);
++ if (ret)
++ {
++ if (!error_logged)
++ {
++ my_syslog(LOG_ERR, _("Cannot add object to UBus: %s"), ubus_strerror(ret));
++ error_logged = 1;
++ }
++ return;
++ }
++
++ ubus->connection_lost = ubus_disconnect_cb;
++ daemon->ubus = ubus;
++ error_logged = 0;
++
++ my_syslog(LOG_INFO, _("Connected to system UBus"));
++}
++
+ void set_ubus_listeners()
+ {
++ struct ubus_context *ubus = (struct ubus_context *)daemon->ubus;
+ if (!ubus)
+- return;
++ {
++ if (!error_logged)
++ {
++ my_syslog(LOG_ERR, _("Cannot set UBus listeners: no connection"));
++ error_logged = 1;
++ }
++ return;
++ }
++
++ error_logged = 0;
+
+ poll_listen(ubus->sock.fd, POLLIN);
+ poll_listen(ubus->sock.fd, POLLERR);
+@@ -51,46 +134,57 @@ void set_ubus_listeners()
+
+ void check_ubus_listeners()
+ {
++ struct ubus_context *ubus = (struct ubus_context *)daemon->ubus;
+ if (!ubus)
+ {
+- ubus = ubus_connect(NULL);
+- if (!ubus)
+- return;
+- ubus_add_object(ubus, &ubus_object);
++ if (!error_logged)
++ {
++ my_syslog(LOG_ERR, _("Cannot poll UBus listeners: no connection"));
++ error_logged = 1;
++ }
++ return;
+ }
+
++ error_logged = 0;
++
+ if (poll_check(ubus->sock.fd, POLLIN))
+ ubus_handle_event(ubus);
+
+- if (poll_check(ubus->sock.fd, POLLHUP))
++ if (poll_check(ubus->sock.fd, POLLHUP | POLLERR))
+ {
+- ubus_free(ubus);
+- ubus = NULL;
++ my_syslog(LOG_INFO, _("Disconnecting from UBus"));
++
++ ubus_destroy(ubus);
+ }
+ }
+
+-
+ static int ubus_handle_metrics(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+ {
+ int i;
+- blob_buf_init(&b, 0);
+
+- for(i=0; i < __METRIC_MAX; i++)
++ (void)obj;
++ (void)method;
++ (void)msg;
++
++ blob_buf_init(&b, BLOBMSG_TYPE_TABLE);
++
++ for (i=0; i < __METRIC_MAX; i++)
+ blobmsg_add_u32(&b, get_metric_name(i), daemon->metrics[i]);
+
+- ubus_send_reply(ctx, req, b.head);
+-
+- return 0;
++ return ubus_send_reply(ctx, req, b.head);
+ }
+
+ void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name, const char *interface)
+ {
+- if (!ubus || !ubus_object.has_subscribers)
++ struct ubus_context *ubus = (struct ubus_context *)daemon->ubus;
++ int ret;
++
++ if (!ubus || !notify)
+ return;
+
+- blob_buf_init(&b, 0);
++ blob_buf_init(&b, BLOBMSG_TYPE_TABLE);
+ if (mac)
+ blobmsg_add_string(&b, "mac", mac);
+ if (ip)
+@@ -100,7 +194,9 @@ void ubus_event_bcast(const char *type,
+ if (interface)
+ blobmsg_add_string(&b, "interface", interface);
+
+- ubus_notify(ubus, &ubus_object, type, b.head, -1);
++ ret = ubus_notify(ubus, &ubus_object, type, b.head, -1);
++ if (!ret)
++ my_syslog(LOG_ERR, _("Failed to send UBus event: %s"), ubus_strerror(ret));
+ }
+
+