blob: 5f81287792758d3fac70983cd0382f3258e3b587 [file] [log] [blame]
Simon Kelley2a8710a2020-01-05 16:40:06 +00001/* dnsmasq is Copyright (c) 2000-2020 Simon Kelley
Simon Kelley8c1b6a52018-07-21 22:12:32 +01002
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
15*/
16
17#include "dnsmasq.h"
18
19#ifdef HAVE_UBUS
20
21#include <libubus.h>
22
Simon Kelley8c1b6a52018-07-21 22:12:32 +010023static struct blob_buf b;
Jan Willem Janssena2b82202019-03-25 12:42:23 +010024static int notify;
25static int error_logged = 0;
Simon Kelley8c1b6a52018-07-21 22:12:32 +010026
27static int ubus_handle_metrics(struct ubus_context *ctx, struct ubus_object *obj,
Simon Kelley6f835ed2018-07-29 22:15:36 +010028 struct ubus_request_data *req, const char *method,
29 struct blob_attr *msg);
Jan Willem Janssena2b82202019-03-25 12:42:23 +010030
31static void ubus_subscribe_cb(struct ubus_context *ctx, struct ubus_object *obj);
32
33static const struct ubus_method ubus_object_methods[] = {
34 UBUS_METHOD_NOARG("metrics", ubus_handle_metrics),
Simon Kelley8c1b6a52018-07-21 22:12:32 +010035};
36
Jan Willem Janssena2b82202019-03-25 12:42:23 +010037static struct ubus_object_type ubus_object_type =
38 UBUS_OBJECT_TYPE("dnsmasq", ubus_object_methods);
Simon Kelley8c1b6a52018-07-21 22:12:32 +010039
40static struct ubus_object ubus_object = {
Oldřich Jedličkad162bee2020-03-20 22:18:57 +010041 .name = NULL,
Simon Kelley6f835ed2018-07-29 22:15:36 +010042 .type = &ubus_object_type,
43 .methods = ubus_object_methods,
44 .n_methods = ARRAY_SIZE(ubus_object_methods),
Jan Willem Janssena2b82202019-03-25 12:42:23 +010045 .subscribe_cb = ubus_subscribe_cb,
Simon Kelley8c1b6a52018-07-21 22:12:32 +010046};
47
Jan Willem Janssena2b82202019-03-25 12:42:23 +010048static void ubus_subscribe_cb(struct ubus_context *ctx, struct ubus_object *obj)
49{
50 (void)ctx;
51
52 my_syslog(LOG_DEBUG, _("UBus subscription callback: %s subscriber(s)"), obj->has_subscribers ? "1" : "0");
53 notify = obj->has_subscribers;
54}
55
56static void ubus_destroy(struct ubus_context *ubus)
57{
58 // Forces re-initialization when we're reusing the same definitions later on.
59 ubus_object.id = 0;
60 ubus_object_type.id = 0;
61
62 ubus_free(ubus);
63 daemon->ubus = NULL;
64}
65
66static void ubus_disconnect_cb(struct ubus_context *ubus)
67{
68 int ret;
69
70 ret = ubus_reconnect(ubus, NULL);
71 if (ret)
72 {
73 my_syslog(LOG_ERR, _("Cannot reconnect to UBus: %s"), ubus_strerror(ret));
74
75 ubus_destroy(ubus);
76 }
77}
78
79void ubus_init()
80{
81 struct ubus_context *ubus = NULL;
82 int ret = 0;
83
84 ubus = ubus_connect(NULL);
85 if (!ubus)
86 {
87 if (!error_logged)
88 {
89 my_syslog(LOG_ERR, _("Cannot initialize UBus: connection failed"));
90 error_logged = 1;
91 }
92
93 ubus_destroy(ubus);
94 return;
95 }
96
Oldřich Jedličkad162bee2020-03-20 22:18:57 +010097 ubus_object.name = daemon->ubus_name;
Jan Willem Janssena2b82202019-03-25 12:42:23 +010098 ret = ubus_add_object(ubus, &ubus_object);
99 if (ret)
100 {
101 if (!error_logged)
102 {
103 my_syslog(LOG_ERR, _("Cannot add object to UBus: %s"), ubus_strerror(ret));
104 error_logged = 1;
105 }
Oldřich Jedlička3f60ecd2020-03-18 22:24:55 +0100106 ubus_destroy(ubus);
Jan Willem Janssena2b82202019-03-25 12:42:23 +0100107 return;
108 }
109
110 ubus->connection_lost = ubus_disconnect_cb;
111 daemon->ubus = ubus;
112 error_logged = 0;
113
114 my_syslog(LOG_INFO, _("Connected to system UBus"));
115}
116
Simon Kelley8c1b6a52018-07-21 22:12:32 +0100117void set_ubus_listeners()
118{
Jan Willem Janssena2b82202019-03-25 12:42:23 +0100119 struct ubus_context *ubus = (struct ubus_context *)daemon->ubus;
Simon Kelley6f835ed2018-07-29 22:15:36 +0100120 if (!ubus)
Jan Willem Janssena2b82202019-03-25 12:42:23 +0100121 {
122 if (!error_logged)
123 {
124 my_syslog(LOG_ERR, _("Cannot set UBus listeners: no connection"));
125 error_logged = 1;
126 }
127 return;
128 }
129
130 error_logged = 0;
Simon Kelley8c1b6a52018-07-21 22:12:32 +0100131
Simon Kelley6f835ed2018-07-29 22:15:36 +0100132 poll_listen(ubus->sock.fd, POLLIN);
133 poll_listen(ubus->sock.fd, POLLERR);
134 poll_listen(ubus->sock.fd, POLLHUP);
Simon Kelley8c1b6a52018-07-21 22:12:32 +0100135}
136
137void check_ubus_listeners()
138{
Jan Willem Janssena2b82202019-03-25 12:42:23 +0100139 struct ubus_context *ubus = (struct ubus_context *)daemon->ubus;
Simon Kelley6f835ed2018-07-29 22:15:36 +0100140 if (!ubus)
141 {
Jan Willem Janssena2b82202019-03-25 12:42:23 +0100142 if (!error_logged)
143 {
144 my_syslog(LOG_ERR, _("Cannot poll UBus listeners: no connection"));
145 error_logged = 1;
146 }
147 return;
Simon Kelley6f835ed2018-07-29 22:15:36 +0100148 }
149
Jan Willem Janssena2b82202019-03-25 12:42:23 +0100150 error_logged = 0;
151
Simon Kelley6f835ed2018-07-29 22:15:36 +0100152 if (poll_check(ubus->sock.fd, POLLIN))
153 ubus_handle_event(ubus);
154
Jan Willem Janssena2b82202019-03-25 12:42:23 +0100155 if (poll_check(ubus->sock.fd, POLLHUP | POLLERR))
Simon Kelley6f835ed2018-07-29 22:15:36 +0100156 {
Jan Willem Janssena2b82202019-03-25 12:42:23 +0100157 my_syslog(LOG_INFO, _("Disconnecting from UBus"));
158
159 ubus_destroy(ubus);
Simon Kelley6f835ed2018-07-29 22:15:36 +0100160 }
Simon Kelley8c1b6a52018-07-21 22:12:32 +0100161}
162
Simon Kelley8c1b6a52018-07-21 22:12:32 +0100163static int ubus_handle_metrics(struct ubus_context *ctx, struct ubus_object *obj,
Simon Kelley6f835ed2018-07-29 22:15:36 +0100164 struct ubus_request_data *req, const char *method,
165 struct blob_attr *msg)
Simon Kelley8c1b6a52018-07-21 22:12:32 +0100166{
Simon Kelley1dfed162018-07-29 22:16:41 +0100167 int i;
Simon Kelley8c1b6a52018-07-21 22:12:32 +0100168
Jan Willem Janssena2b82202019-03-25 12:42:23 +0100169 (void)obj;
170 (void)method;
171 (void)msg;
172
173 blob_buf_init(&b, BLOBMSG_TYPE_TABLE);
174
175 for (i=0; i < __METRIC_MAX; i++)
Simon Kelley6f835ed2018-07-29 22:15:36 +0100176 blobmsg_add_u32(&b, get_metric_name(i), daemon->metrics[i]);
177
Jan Willem Janssena2b82202019-03-25 12:42:23 +0100178 return ubus_send_reply(ctx, req, b.head);
Simon Kelley8c1b6a52018-07-21 22:12:32 +0100179}
180
181void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name, const char *interface)
182{
Jan Willem Janssena2b82202019-03-25 12:42:23 +0100183 struct ubus_context *ubus = (struct ubus_context *)daemon->ubus;
184 int ret;
185
186 if (!ubus || !notify)
Simon Kelley6f835ed2018-07-29 22:15:36 +0100187 return;
Simon Kelley8c1b6a52018-07-21 22:12:32 +0100188
Jan Willem Janssena2b82202019-03-25 12:42:23 +0100189 blob_buf_init(&b, BLOBMSG_TYPE_TABLE);
Simon Kelley6f835ed2018-07-29 22:15:36 +0100190 if (mac)
191 blobmsg_add_string(&b, "mac", mac);
192 if (ip)
193 blobmsg_add_string(&b, "ip", ip);
194 if (name)
195 blobmsg_add_string(&b, "name", name);
196 if (interface)
197 blobmsg_add_string(&b, "interface", interface);
198
Jan Willem Janssena2b82202019-03-25 12:42:23 +0100199 ret = ubus_notify(ubus, &ubus_object, type, b.head, -1);
200 if (!ret)
201 my_syslog(LOG_ERR, _("Failed to send UBus event: %s"), ubus_strerror(ret));
Simon Kelley8c1b6a52018-07-21 22:12:32 +0100202}
203
204
205#endif /* HAVE_UBUS */