1
/* dnsmasq is Copyright (c) 2000-2005 Simon Kelley
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.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
17
#define DBUS_API_SUBJECT_TO_CHANGE
18
#include <dbus/dbus.h>
26
static dbus_bool_t add_watch(DBusWatch *watch, void *data)
28
struct daemon *daemon = data;
31
for (w = daemon->watches; w; w = w->next)
32
if (w->watch == watch)
35
if (!(w = malloc(sizeof(struct watch))))
39
w->next = daemon->watches;
42
dbus_watch_set_data (watch, (void *)daemon, NULL);
47
static void remove_watch(DBusWatch *watch, void *data)
49
struct daemon *daemon = data;
50
struct watch **up, *w;
52
for (up = &(daemon->watches), w = daemon->watches; w; w = w->next)
53
if (w->watch == watch)
62
static void dbus_read_servers(struct daemon *daemon, DBusMessage *message)
64
struct server *serv, *tmp, **up;
66
union mysockaddr addr, source_addr;
69
dbus_message_iter_init(message, &iter);
71
/* mark everything from DBUS */
72
for (serv = daemon->servers; serv; serv = serv->next)
73
if (serv->flags & SERV_FROM_DBUS)
74
serv->flags |= SERV_MARK;
80
if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_UINT32)
84
dbus_message_iter_get_basic(&iter, &a);
85
dbus_message_iter_next (&iter);
87
#ifdef HAVE_SOCKADDR_SA_LEN
88
source_addr.in.sin_len = addr.in.sin_len = sizeof(struct sockaddr_in);
90
addr.in.sin_addr.s_addr = ntohl(a);
91
source_addr.in.sin_family = addr.in.sin_family = AF_INET;
92
addr.in.sin_port = htons(NAMESERVER_PORT);
93
source_addr.in.sin_addr.s_addr = INADDR_ANY;
94
source_addr.in.sin_port = htons(daemon->query_port);
96
else if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_BYTE)
98
unsigned char p[sizeof(struct in6_addr)];
103
for(i = 0; i < sizeof(struct in6_addr); i++)
105
dbus_message_iter_get_basic(&iter, &p[i]);
106
dbus_message_iter_next (&iter);
107
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BYTE)
112
syslog(LOG_WARNING, _("attempt to set an IPv6 server address via DBus - no IPv6 support"));
114
if (i == sizeof(struct in6_addr)-1)
116
memcpy(&addr.in6.sin6_addr, p, sizeof(struct in6_addr));
117
#ifdef HAVE_SOCKADDR_SA_LEN
118
source_addr.in6.sin6_len = addr.in6.sin6_len = sizeof(struct sockaddr_in6);
120
source_addr.in6.sin6_family = addr.in6.sin6_family = AF_INET6;
121
addr.in6.sin6_port = htons(NAMESERVER_PORT);
122
source_addr.in6.sin6_flowinfo = addr.in6.sin6_flowinfo = htonl(0);
123
source_addr.in6.sin6_addr = in6addr_any;
124
source_addr.in6.sin6_port = htons(daemon->query_port);
134
if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING)
136
dbus_message_iter_get_basic(&iter, &domain);
137
dbus_message_iter_next (&iter);
144
/* See if this is already there, and unmark */
145
for (serv = daemon->servers; serv; serv = serv->next)
146
if ((serv->flags & SERV_FROM_DBUS) &&
147
(serv->flags & SERV_MARK))
149
if (!(serv->flags & SERV_HAS_DOMAIN) && !domain)
151
serv->flags &= ~SERV_MARK;
154
if ((serv->flags & SERV_HAS_DOMAIN) &&
156
hostname_isequal(domain, serv->domain))
158
serv->flags &= ~SERV_MARK;
163
if (!serv && (serv = malloc(sizeof (struct server))))
165
/* Not found, create a new one. */
167
serv->domain = malloc(strlen(domain)+1);
168
if (domain && !serv->domain)
175
serv->next = daemon->servers;
176
daemon->servers = serv;
177
serv->flags = SERV_FROM_DBUS;
181
strcpy(serv->domain, domain);
182
serv->flags |= SERV_HAS_DOMAIN;
189
if (source_addr.in.sin_family == AF_INET &&
190
addr.in.sin_addr.s_addr == 0 &&
192
serv->flags |= SERV_NO_ADDR;
195
serv->flags &= ~SERV_NO_ADDR;
197
serv->source_addr = source_addr;
201
} while (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING);
204
/* unlink and free anything still marked. */
205
for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
208
if (serv->flags & SERV_MARK)
219
DBusHandlerResult message_handler (DBusConnection *connection,
220
DBusMessage *message,
223
char *method = (char *)dbus_message_get_member(message);
224
struct daemon *daemon = (struct daemon *)user_data;
226
if (strcmp(method, "GetVersion") == 0)
229
DBusMessage *reply = dbus_message_new_method_return(message);
231
dbus_message_append_args(reply, DBUS_TYPE_STRING, &v, DBUS_TYPE_INVALID);
232
dbus_connection_send (connection, reply, NULL);
233
dbus_message_unref (reply);
235
else if (strcmp(method, "SetServers") == 0)
237
syslog(LOG_INFO, _("setting upstream servers from DBus"));
238
dbus_read_servers(daemon, message);
239
check_servers(daemon);
241
else if (strcmp(method, "ClearCache") == 0)
242
clear_cache_and_reload(daemon, dnsmasq_time(daemon->uptime_fd));
244
return (DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
246
return (DBUS_HANDLER_RESULT_HANDLED);
251
/* returns NULL or error message, may fail silently if dbus daemon not yet up. */
252
char *dbus_init(struct daemon *daemon)
254
DBusConnection *connection = NULL;
255
DBusObjectPathVTable dnsmasq_vtable = {NULL, &message_handler, NULL, NULL, NULL, NULL };
256
DBusError dbus_error;
257
DBusMessage *message;
259
dbus_error_init (&dbus_error);
260
if (!(connection = dbus_bus_get (DBUS_BUS_SYSTEM, &dbus_error)))
263
dbus_connection_set_exit_on_disconnect(connection, FALSE);
264
dbus_connection_set_watch_functions(connection, add_watch, remove_watch,
265
NULL, (void *)daemon, NULL);
266
dbus_error_init (&dbus_error);
267
dbus_bus_request_name (connection, DNSMASQ_SERVICE, 0, &dbus_error);
268
if (dbus_error_is_set (&dbus_error))
269
return (char *)dbus_error.message;
271
if (!dbus_connection_register_object_path(connection, DNSMASQ_PATH,
272
&dnsmasq_vtable, daemon))
273
return _("could not register a DBus message handler");
275
daemon->dbus = connection;
277
if ((message = dbus_message_new_signal(DNSMASQ_PATH, DNSMASQ_SERVICE, "Up")))
278
dbus_connection_send(connection, message, NULL);
284
int set_dbus_listeners(struct daemon *daemon, int maxfd,
285
fd_set *rset, fd_set *wset, fd_set *eset)
289
for (w = daemon->watches; w; w = w->next)
290
if (dbus_watch_get_enabled(w->watch))
292
unsigned int flags = dbus_watch_get_flags(w->watch);
293
int fd = dbus_watch_get_fd(w->watch);
298
if (flags & DBUS_WATCH_READABLE)
301
if (flags & DBUS_WATCH_WRITABLE)
309
void check_dbus_listeners(struct daemon *daemon,
310
fd_set *rset, fd_set *wset, fd_set *eset)
312
DBusConnection *connection = (DBusConnection *)daemon->dbus;
315
for (w = daemon->watches; w; w = w->next)
316
if (dbus_watch_get_enabled(w->watch))
318
unsigned int flags = 0;
319
int fd = dbus_watch_get_fd(w->watch);
321
if (FD_ISSET(fd, rset))
322
flags |= DBUS_WATCH_READABLE;
324
if (FD_ISSET(fd, wset))
325
flags |= DBUS_WATCH_WRITABLE;
327
if (FD_ISSET(fd, eset))
328
flags |= DBUS_WATCH_ERROR;
331
dbus_watch_handle(w->watch, flags);
336
dbus_connection_ref (connection);
337
while (dbus_connection_dispatch (connection) == DBUS_DISPATCH_DATA_REMAINS);
338
dbus_connection_unref (connection);