dnsmasq: backport latest patches
[openwrt/staging/mkresin.git] / package / network / services / dnsmasq / patches / 0052-Improved-UBus-supported.patch
1 From a2b8220f4e82e454bbc0013ee83ea3220111d92e Mon Sep 17 00:00:00 2001
2 From: Jan Willem Janssen <j.w.janssen@lxtreme.nl>
3 Date: Mon, 25 Mar 2019 12:42:23 +0100
4 Subject: [PATCH 52/57] Improved UBus supported
5
6 - aligned the handling of UBus connections with the DBus code as it
7 makes it a bit easier to comprehend;
8 - added logging to the various UBus calls to aid debugging from an
9 enduser point of view, but be careful to not flood the logs;
10 - show the (lack of) support for UBus in the configuration string.
11
12 Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
13 ---
14 src/config.h | 4 ++
15 src/dnsmasq.c | 32 +++++++++++-
16 src/dnsmasq.h | 6 +++
17 src/ubus.c | 138 ++++++++++++++++++++++++++++++++++++++++++--------
18 4 files changed, 157 insertions(+), 23 deletions(-)
19
20 --- a/src/config.h
21 +++ b/src/config.h
22 @@ -362,6 +362,10 @@ static char *compile_opts =
23 "no-"
24 #endif
25 "DBus "
26 +#ifndef HAVE_UBUS
27 +"no-"
28 +#endif
29 +"UBus "
30 #ifndef LOCALEDIR
31 "no-"
32 #endif
33 --- a/src/dnsmasq.c
34 +++ b/src/dnsmasq.c
35 @@ -420,6 +420,16 @@ int main (int argc, char **argv)
36 die(_("DBus not available: set HAVE_DBUS in src/config.h"), NULL, EC_BADCONF);
37 #endif
38
39 + if (option_bool(OPT_UBUS))
40 +#ifdef HAVE_UBUS
41 + {
42 + daemon->ubus = NULL;
43 + ubus_init();
44 + }
45 +#else
46 + die(_("UBus not available: set HAVE_UBUS in src/config.h"), NULL, EC_BADCONF);
47 +#endif
48 +
49 if (daemon->port != 0)
50 pre_allocate_sfds();
51
52 @@ -811,6 +821,16 @@ int main (int argc, char **argv)
53 }
54 #endif
55
56 +#ifdef HAVE_UBUS
57 + if (option_bool(OPT_UBUS))
58 + {
59 + if (daemon->ubus)
60 + my_syslog(LOG_INFO, _("UBus support enabled: connected to system bus"));
61 + else
62 + my_syslog(LOG_INFO, _("UBus support enabled: bus connection pending"));
63 + }
64 +#endif
65 +
66 #ifdef HAVE_DNSSEC
67 if (option_bool(OPT_DNSSEC_VALID))
68 {
69 @@ -999,7 +1019,7 @@ int main (int argc, char **argv)
70
71 #ifdef HAVE_UBUS
72 if (option_bool(OPT_UBUS))
73 - set_ubus_listeners();
74 + set_ubus_listeners();
75 #endif
76
77 #ifdef HAVE_DHCP
78 @@ -1134,7 +1154,15 @@ int main (int argc, char **argv)
79
80 #ifdef HAVE_UBUS
81 if (option_bool(OPT_UBUS))
82 - check_ubus_listeners();
83 + {
84 + /* if we didn't create a UBus connection, retry now. */
85 + if (!daemon->ubus)
86 + {
87 + ubus_init();
88 + }
89 +
90 + check_ubus_listeners();
91 + }
92 #endif
93
94 check_dns_listeners(now);
95 --- a/src/dnsmasq.h
96 +++ b/src/dnsmasq.h
97 @@ -1130,6 +1130,11 @@ extern struct daemon {
98 #ifdef HAVE_DBUS
99 struct watch *watches;
100 #endif
101 + /* UBus stuff */
102 +#ifdef HAVE_UBUS
103 + /* void * here to avoid depending on ubus headers outside ubus.c */
104 + void *ubus;
105 +#endif
106
107 /* TFTP stuff */
108 struct tftp_transfer *tftp_trans, *tftp_done_trans;
109 @@ -1467,6 +1472,7 @@ void emit_dbus_signal(int action, struct
110
111 /* ubus.c */
112 #ifdef HAVE_UBUS
113 +void ubus_init(void);
114 void set_ubus_listeners(void);
115 void check_ubus_listeners(void);
116 void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name, const char *interface);
117 --- a/src/ubus.c
118 +++ b/src/ubus.c
119 @@ -20,29 +20,112 @@
120
121 #include <libubus.h>
122
123 -static struct ubus_context *ubus = NULL;
124 static struct blob_buf b;
125 +static int notify;
126 +static int error_logged = 0;
127
128 static int ubus_handle_metrics(struct ubus_context *ctx, struct ubus_object *obj,
129 struct ubus_request_data *req, const char *method,
130 struct blob_attr *msg);
131 -static struct ubus_method ubus_object_methods[] = {
132 - {.name = "metrics", .handler = ubus_handle_metrics},
133 +
134 +static void ubus_subscribe_cb(struct ubus_context *ctx, struct ubus_object *obj);
135 +
136 +static const struct ubus_method ubus_object_methods[] = {
137 + UBUS_METHOD_NOARG("metrics", ubus_handle_metrics),
138 };
139
140 -static struct ubus_object_type ubus_object_type = UBUS_OBJECT_TYPE("dnsmasq", ubus_object_methods);
141 +static struct ubus_object_type ubus_object_type =
142 + UBUS_OBJECT_TYPE("dnsmasq", ubus_object_methods);
143
144 static struct ubus_object ubus_object = {
145 .name = "dnsmasq",
146 .type = &ubus_object_type,
147 .methods = ubus_object_methods,
148 .n_methods = ARRAY_SIZE(ubus_object_methods),
149 + .subscribe_cb = ubus_subscribe_cb,
150 };
151
152 +static void ubus_subscribe_cb(struct ubus_context *ctx, struct ubus_object *obj)
153 +{
154 + (void)ctx;
155 +
156 + my_syslog(LOG_DEBUG, _("UBus subscription callback: %s subscriber(s)"), obj->has_subscribers ? "1" : "0");
157 + notify = obj->has_subscribers;
158 +}
159 +
160 +static void ubus_destroy(struct ubus_context *ubus)
161 +{
162 + // Forces re-initialization when we're reusing the same definitions later on.
163 + ubus_object.id = 0;
164 + ubus_object_type.id = 0;
165 +
166 + ubus_free(ubus);
167 + daemon->ubus = NULL;
168 +}
169 +
170 +static void ubus_disconnect_cb(struct ubus_context *ubus)
171 +{
172 + int ret;
173 +
174 + ret = ubus_reconnect(ubus, NULL);
175 + if (ret)
176 + {
177 + my_syslog(LOG_ERR, _("Cannot reconnect to UBus: %s"), ubus_strerror(ret));
178 +
179 + ubus_destroy(ubus);
180 + }
181 +}
182 +
183 +void ubus_init()
184 +{
185 + struct ubus_context *ubus = NULL;
186 + int ret = 0;
187 +
188 + ubus = ubus_connect(NULL);
189 + if (!ubus)
190 + {
191 + if (!error_logged)
192 + {
193 + my_syslog(LOG_ERR, _("Cannot initialize UBus: connection failed"));
194 + error_logged = 1;
195 + }
196 +
197 + ubus_destroy(ubus);
198 + return;
199 + }
200 +
201 + ret = ubus_add_object(ubus, &ubus_object);
202 + if (ret)
203 + {
204 + if (!error_logged)
205 + {
206 + my_syslog(LOG_ERR, _("Cannot add object to UBus: %s"), ubus_strerror(ret));
207 + error_logged = 1;
208 + }
209 + return;
210 + }
211 +
212 + ubus->connection_lost = ubus_disconnect_cb;
213 + daemon->ubus = ubus;
214 + error_logged = 0;
215 +
216 + my_syslog(LOG_INFO, _("Connected to system UBus"));
217 +}
218 +
219 void set_ubus_listeners()
220 {
221 + struct ubus_context *ubus = (struct ubus_context *)daemon->ubus;
222 if (!ubus)
223 - return;
224 + {
225 + if (!error_logged)
226 + {
227 + my_syslog(LOG_ERR, _("Cannot set UBus listeners: no connection"));
228 + error_logged = 1;
229 + }
230 + return;
231 + }
232 +
233 + error_logged = 0;
234
235 poll_listen(ubus->sock.fd, POLLIN);
236 poll_listen(ubus->sock.fd, POLLERR);
237 @@ -51,46 +134,57 @@ void set_ubus_listeners()
238
239 void check_ubus_listeners()
240 {
241 + struct ubus_context *ubus = (struct ubus_context *)daemon->ubus;
242 if (!ubus)
243 {
244 - ubus = ubus_connect(NULL);
245 - if (!ubus)
246 - return;
247 - ubus_add_object(ubus, &ubus_object);
248 + if (!error_logged)
249 + {
250 + my_syslog(LOG_ERR, _("Cannot poll UBus listeners: no connection"));
251 + error_logged = 1;
252 + }
253 + return;
254 }
255
256 + error_logged = 0;
257 +
258 if (poll_check(ubus->sock.fd, POLLIN))
259 ubus_handle_event(ubus);
260
261 - if (poll_check(ubus->sock.fd, POLLHUP))
262 + if (poll_check(ubus->sock.fd, POLLHUP | POLLERR))
263 {
264 - ubus_free(ubus);
265 - ubus = NULL;
266 + my_syslog(LOG_INFO, _("Disconnecting from UBus"));
267 +
268 + ubus_destroy(ubus);
269 }
270 }
271
272 -
273 static int ubus_handle_metrics(struct ubus_context *ctx, struct ubus_object *obj,
274 struct ubus_request_data *req, const char *method,
275 struct blob_attr *msg)
276 {
277 int i;
278 - blob_buf_init(&b, 0);
279
280 - for(i=0; i < __METRIC_MAX; i++)
281 + (void)obj;
282 + (void)method;
283 + (void)msg;
284 +
285 + blob_buf_init(&b, BLOBMSG_TYPE_TABLE);
286 +
287 + for (i=0; i < __METRIC_MAX; i++)
288 blobmsg_add_u32(&b, get_metric_name(i), daemon->metrics[i]);
289
290 - ubus_send_reply(ctx, req, b.head);
291 -
292 - return 0;
293 + return ubus_send_reply(ctx, req, b.head);
294 }
295
296 void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name, const char *interface)
297 {
298 - if (!ubus || !ubus_object.has_subscribers)
299 + struct ubus_context *ubus = (struct ubus_context *)daemon->ubus;
300 + int ret;
301 +
302 + if (!ubus || !notify)
303 return;
304
305 - blob_buf_init(&b, 0);
306 + blob_buf_init(&b, BLOBMSG_TYPE_TABLE);
307 if (mac)
308 blobmsg_add_string(&b, "mac", mac);
309 if (ip)
310 @@ -100,7 +194,9 @@ void ubus_event_bcast(const char *type,
311 if (interface)
312 blobmsg_add_string(&b, "interface", interface);
313
314 - ubus_notify(ubus, &ubus_object, type, b.head, -1);
315 + ret = ubus_notify(ubus, &ubus_object, type, b.head, -1);
316 + if (!ret)
317 + my_syslog(LOG_ERR, _("Failed to send UBus event: %s"), ubus_strerror(ret));
318 }
319
320