mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 10:18:25 +00:00
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.
This commit is contained in:
committed by
Simon Kelley
parent
5c464ef62e
commit
a2b8220f4e
@@ -362,6 +362,10 @@ static char *compile_opts =
|
|||||||
"no-"
|
"no-"
|
||||||
#endif
|
#endif
|
||||||
"DBus "
|
"DBus "
|
||||||
|
#ifndef HAVE_UBUS
|
||||||
|
"no-"
|
||||||
|
#endif
|
||||||
|
"UBus "
|
||||||
#ifndef LOCALEDIR
|
#ifndef LOCALEDIR
|
||||||
"no-"
|
"no-"
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -420,6 +420,16 @@ int main (int argc, char **argv)
|
|||||||
die(_("DBus not available: set HAVE_DBUS in src/config.h"), NULL, EC_BADCONF);
|
die(_("DBus not available: set HAVE_DBUS in src/config.h"), NULL, EC_BADCONF);
|
||||||
#endif
|
#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)
|
if (daemon->port != 0)
|
||||||
pre_allocate_sfds();
|
pre_allocate_sfds();
|
||||||
|
|
||||||
@@ -811,6 +821,16 @@ int main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
#endif
|
#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
|
#ifdef HAVE_DNSSEC
|
||||||
if (option_bool(OPT_DNSSEC_VALID))
|
if (option_bool(OPT_DNSSEC_VALID))
|
||||||
{
|
{
|
||||||
@@ -999,7 +1019,7 @@ int main (int argc, char **argv)
|
|||||||
|
|
||||||
#ifdef HAVE_UBUS
|
#ifdef HAVE_UBUS
|
||||||
if (option_bool(OPT_UBUS))
|
if (option_bool(OPT_UBUS))
|
||||||
set_ubus_listeners();
|
set_ubus_listeners();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
@@ -1134,7 +1154,15 @@ int main (int argc, char **argv)
|
|||||||
|
|
||||||
#ifdef HAVE_UBUS
|
#ifdef HAVE_UBUS
|
||||||
if (option_bool(OPT_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
|
#endif
|
||||||
|
|
||||||
check_dns_listeners(now);
|
check_dns_listeners(now);
|
||||||
|
|||||||
@@ -1130,6 +1130,11 @@ extern struct daemon {
|
|||||||
#ifdef HAVE_DBUS
|
#ifdef HAVE_DBUS
|
||||||
struct watch *watches;
|
struct watch *watches;
|
||||||
#endif
|
#endif
|
||||||
|
/* UBus stuff */
|
||||||
|
#ifdef HAVE_UBUS
|
||||||
|
/* void * here to avoid depending on ubus headers outside ubus.c */
|
||||||
|
void *ubus;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* TFTP stuff */
|
/* TFTP stuff */
|
||||||
struct tftp_transfer *tftp_trans, *tftp_done_trans;
|
struct tftp_transfer *tftp_trans, *tftp_done_trans;
|
||||||
@@ -1467,6 +1472,7 @@ void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname);
|
|||||||
|
|
||||||
/* ubus.c */
|
/* ubus.c */
|
||||||
#ifdef HAVE_UBUS
|
#ifdef HAVE_UBUS
|
||||||
|
void ubus_init(void);
|
||||||
void set_ubus_listeners(void);
|
void set_ubus_listeners(void);
|
||||||
void check_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);
|
void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name, const char *interface);
|
||||||
|
|||||||
138
src/ubus.c
138
src/ubus.c
@@ -20,29 +20,112 @@
|
|||||||
|
|
||||||
#include <libubus.h>
|
#include <libubus.h>
|
||||||
|
|
||||||
static struct ubus_context *ubus = NULL;
|
|
||||||
static struct blob_buf b;
|
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,
|
static int ubus_handle_metrics(struct ubus_context *ctx, struct ubus_object *obj,
|
||||||
struct ubus_request_data *req, const char *method,
|
struct ubus_request_data *req, const char *method,
|
||||||
struct blob_attr *msg);
|
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 = {
|
static struct ubus_object ubus_object = {
|
||||||
.name = "dnsmasq",
|
.name = "dnsmasq",
|
||||||
.type = &ubus_object_type,
|
.type = &ubus_object_type,
|
||||||
.methods = ubus_object_methods,
|
.methods = ubus_object_methods,
|
||||||
.n_methods = ARRAY_SIZE(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()
|
void set_ubus_listeners()
|
||||||
{
|
{
|
||||||
|
struct ubus_context *ubus = (struct ubus_context *)daemon->ubus;
|
||||||
if (!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, POLLIN);
|
||||||
poll_listen(ubus->sock.fd, POLLERR);
|
poll_listen(ubus->sock.fd, POLLERR);
|
||||||
@@ -51,46 +134,57 @@ void set_ubus_listeners()
|
|||||||
|
|
||||||
void check_ubus_listeners()
|
void check_ubus_listeners()
|
||||||
{
|
{
|
||||||
|
struct ubus_context *ubus = (struct ubus_context *)daemon->ubus;
|
||||||
if (!ubus)
|
if (!ubus)
|
||||||
{
|
{
|
||||||
ubus = ubus_connect(NULL);
|
if (!error_logged)
|
||||||
if (!ubus)
|
{
|
||||||
return;
|
my_syslog(LOG_ERR, _("Cannot poll UBus listeners: no connection"));
|
||||||
ubus_add_object(ubus, &ubus_object);
|
error_logged = 1;
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
error_logged = 0;
|
||||||
|
|
||||||
if (poll_check(ubus->sock.fd, POLLIN))
|
if (poll_check(ubus->sock.fd, POLLIN))
|
||||||
ubus_handle_event(ubus);
|
ubus_handle_event(ubus);
|
||||||
|
|
||||||
if (poll_check(ubus->sock.fd, POLLHUP))
|
if (poll_check(ubus->sock.fd, POLLHUP | POLLERR))
|
||||||
{
|
{
|
||||||
ubus_free(ubus);
|
my_syslog(LOG_INFO, _("Disconnecting from UBus"));
|
||||||
ubus = NULL;
|
|
||||||
|
ubus_destroy(ubus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int ubus_handle_metrics(struct ubus_context *ctx, struct ubus_object *obj,
|
static int ubus_handle_metrics(struct ubus_context *ctx, struct ubus_object *obj,
|
||||||
struct ubus_request_data *req, const char *method,
|
struct ubus_request_data *req, const char *method,
|
||||||
struct blob_attr *msg)
|
struct blob_attr *msg)
|
||||||
{
|
{
|
||||||
int i;
|
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]);
|
blobmsg_add_u32(&b, get_metric_name(i), daemon->metrics[i]);
|
||||||
|
|
||||||
ubus_send_reply(ctx, req, b.head);
|
return ubus_send_reply(ctx, req, b.head);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name, const char *interface)
|
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;
|
return;
|
||||||
|
|
||||||
blob_buf_init(&b, 0);
|
blob_buf_init(&b, BLOBMSG_TYPE_TABLE);
|
||||||
if (mac)
|
if (mac)
|
||||||
blobmsg_add_string(&b, "mac", mac);
|
blobmsg_add_string(&b, "mac", mac);
|
||||||
if (ip)
|
if (ip)
|
||||||
@@ -100,7 +194,9 @@ void ubus_event_bcast(const char *type, const char *mac, const char *ip, const c
|
|||||||
if (interface)
|
if (interface)
|
||||||
blobmsg_add_string(&b, "interface", 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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user