blob: c2cca224d30df9c3c7f4b372028f02ce7cad19f3 [file] [log] [blame]
Simon Kelley8c1b6a52018-07-21 22:12:32 +01001/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
2
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 = {
Simon Kelley6f835ed2018-07-29 22:15:36 +010041 .name = "dnsmasq",
42 .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
97 ret = ubus_add_object(ubus, &ubus_object);
98 if (ret)
99 {
100 if (!error_logged)
101 {
102 my_syslog(LOG_ERR, _("Cannot add object to UBus: %s"), ubus_strerror(ret));
103 error_logged = 1;
104 }
105 return;
106 }
107
108 ubus->connection_lost = ubus_disconnect_cb;
109 daemon->ubus = ubus;
110 error_logged = 0;
111
112 my_syslog(LOG_INFO, _("Connected to system UBus"));
113}
114
Simon Kelley8c1b6a52018-07-21 22:12:32 +0100115void set_ubus_listeners()
116{
Jan Willem Janssena2b82202019-03-25 12:42:23 +0100117 struct ubus_context *ubus = (struct ubus_context *)daemon->ubus;
Simon Kelley6f835ed2018-07-29 22:15:36 +0100118 if (!ubus)
Jan Willem Janssena2b82202019-03-25 12:42:23 +0100119 {
120 if (!error_logged)
121 {
122 my_syslog(LOG_ERR, _("Cannot set UBus listeners: no connection"));
123 error_logged = 1;
124 }
125 return;
126 }
127
128 error_logged = 0;
Simon Kelley8c1b6a52018-07-21 22:12:32 +0100129
Simon Kelley6f835ed2018-07-29 22:15:36 +0100130 poll_listen(ubus->sock.fd, POLLIN);
131 poll_listen(ubus->sock.fd, POLLERR);
132 poll_listen(ubus->sock.fd, POLLHUP);
Simon Kelley8c1b6a52018-07-21 22:12:32 +0100133}
134
135void check_ubus_listeners()
136{
Jan Willem Janssena2b82202019-03-25 12:42:23 +0100137 struct ubus_context *ubus = (struct ubus_context *)daemon->ubus;
Simon Kelley6f835ed2018-07-29 22:15:36 +0100138 if (!ubus)
139 {
Jan Willem Janssena2b82202019-03-25 12:42:23 +0100140 if (!error_logged)
141 {
142 my_syslog(LOG_ERR, _("Cannot poll UBus listeners: no connection"));
143 error_logged = 1;
144 }
145 return;
Simon Kelley6f835ed2018-07-29 22:15:36 +0100146 }
147
Jan Willem Janssena2b82202019-03-25 12:42:23 +0100148 error_logged = 0;
149
Simon Kelley6f835ed2018-07-29 22:15:36 +0100150 if (poll_check(ubus->sock.fd, POLLIN))
151 ubus_handle_event(ubus);
152
Jan Willem Janssena2b82202019-03-25 12:42:23 +0100153 if (poll_check(ubus->sock.fd, POLLHUP | POLLERR))
Simon Kelley6f835ed2018-07-29 22:15:36 +0100154 {
Jan Willem Janssena2b82202019-03-25 12:42:23 +0100155 my_syslog(LOG_INFO, _("Disconnecting from UBus"));
156
157 ubus_destroy(ubus);
Simon Kelley6f835ed2018-07-29 22:15:36 +0100158 }
Simon Kelley8c1b6a52018-07-21 22:12:32 +0100159}
160
Simon Kelley8c1b6a52018-07-21 22:12:32 +0100161static int ubus_handle_metrics(struct ubus_context *ctx, struct ubus_object *obj,
Simon Kelley6f835ed2018-07-29 22:15:36 +0100162 struct ubus_request_data *req, const char *method,
163 struct blob_attr *msg)
Simon Kelley8c1b6a52018-07-21 22:12:32 +0100164{
Simon Kelley1dfed162018-07-29 22:16:41 +0100165 int i;
Simon Kelley8c1b6a52018-07-21 22:12:32 +0100166
Jan Willem Janssena2b82202019-03-25 12:42:23 +0100167 (void)obj;
168 (void)method;
169 (void)msg;
170
171 blob_buf_init(&b, BLOBMSG_TYPE_TABLE);
172
173 for (i=0; i < __METRIC_MAX; i++)
Simon Kelley6f835ed2018-07-29 22:15:36 +0100174 blobmsg_add_u32(&b, get_metric_name(i), daemon->metrics[i]);
175
Jan Willem Janssena2b82202019-03-25 12:42:23 +0100176 return ubus_send_reply(ctx, req, b.head);
Simon Kelley8c1b6a52018-07-21 22:12:32 +0100177}
178
179void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name, const char *interface)
180{
Jan Willem Janssena2b82202019-03-25 12:42:23 +0100181 struct ubus_context *ubus = (struct ubus_context *)daemon->ubus;
182 int ret;
183
184 if (!ubus || !notify)
Simon Kelley6f835ed2018-07-29 22:15:36 +0100185 return;
Simon Kelley8c1b6a52018-07-21 22:12:32 +0100186
Jan Willem Janssena2b82202019-03-25 12:42:23 +0100187 blob_buf_init(&b, BLOBMSG_TYPE_TABLE);
Simon Kelley6f835ed2018-07-29 22:15:36 +0100188 if (mac)
189 blobmsg_add_string(&b, "mac", mac);
190 if (ip)
191 blobmsg_add_string(&b, "ip", ip);
192 if (name)
193 blobmsg_add_string(&b, "name", name);
194 if (interface)
195 blobmsg_add_string(&b, "interface", interface);
196
Jan Willem Janssena2b82202019-03-25 12:42:23 +0100197 ret = ubus_notify(ubus, &ubus_object, type, b.head, -1);
198 if (!ret)
199 my_syslog(LOG_ERR, _("Failed to send UBus event: %s"), ubus_strerror(ret));
Simon Kelley8c1b6a52018-07-21 22:12:32 +0100200}
201
202
203#endif /* HAVE_UBUS */