]> git.meshlink.io Git - catta/blob - avahi-daemon/dbus-protocol.c
don't remove static services from the avahi daemon on SIGHUP. Add static hosts proper...
[catta] / avahi-daemon / dbus-protocol.c
1 /* $Id$ */
2
3 /***
4   This file is part of avahi.
5  
6   avahi is free software; you can redistribute it and/or modify it
7   under the terms of the GNU Lesser General Public License as
8   published by the Free Software Foundation; either version 2.1 of the
9   License, or (at your option) any later version.
10  
11   avahi is distributed in the hope that it will be useful, but WITHOUT
12   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13   or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
14   Public License for more details.
15  
16   You should have received a copy of the GNU Lesser General Public
17   License along with avahi; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19   USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <string.h>
27 #include <sys/ioctl.h>
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <net/if.h>
32 #include <errno.h>
33 #include <unistd.h>
34 #include <assert.h>
35 #include <sys/stat.h>
36 #include <fcntl.h>
37 #include <stdio.h>
38 #include <signal.h>
39 #include <stdlib.h>
40
41 #include <dbus/dbus.h>
42
43 #include <avahi-common/dbus.h>
44 #include <avahi-common/llist.h>
45 #include <avahi-common/malloc.h>
46 #include <avahi-common/dbus.h>
47 #include <avahi-common/dbus-watch-glue.h>
48 #include <avahi-common/alternative.h>
49 #include <avahi-common/error.h>
50 #include <avahi-common/domain.h>
51 #include <avahi-common/timeval.h>
52
53 #include <avahi-core/log.h>
54 #include <avahi-core/core.h>
55 #include <avahi-core/lookup.h>
56 #include <avahi-core/publish.h>
57
58 #include "dbus-protocol.h"
59 #include "dbus-util.h"
60 #include "dbus-internal.h"
61 #include "main.h"
62
63 /* #define VALGRIND_WORKAROUND 1 */
64
65 #define RECONNECT_MSEC 3000
66
67 Server *server = NULL;
68
69 static int disable_user_service_publishing = 0;
70
71 static int dbus_connect(void);
72 static void dbus_disconnect(void);
73
74 static void client_free(Client *c) {
75     
76     assert(server);
77     assert(c);
78
79     while (c->entry_groups)
80         avahi_dbus_entry_group_free(c->entry_groups);
81
82     while (c->sync_host_name_resolvers)
83         avahi_dbus_sync_host_name_resolver_free(c->sync_host_name_resolvers);
84
85     while (c->async_host_name_resolvers)
86         avahi_dbus_async_host_name_resolver_free(c->async_host_name_resolvers);
87     
88     while (c->sync_address_resolvers)
89         avahi_dbus_sync_address_resolver_free(c->sync_address_resolvers);
90
91     while (c->async_address_resolvers)
92         avahi_dbus_async_address_resolver_free(c->async_address_resolvers);
93
94     while (c->domain_browsers)
95         avahi_dbus_domain_browser_free(c->domain_browsers);
96
97     while (c->service_type_browsers)
98         avahi_dbus_service_type_browser_free(c->service_type_browsers);
99
100     while (c->service_browsers)
101         avahi_dbus_service_browser_free(c->service_browsers);
102
103     while (c->sync_service_resolvers)
104         avahi_dbus_sync_service_resolver_free(c->sync_service_resolvers);
105
106     while (c->async_service_resolvers)
107         avahi_dbus_async_service_resolver_free(c->async_service_resolvers);
108
109     while (c->record_browsers)
110         avahi_dbus_record_browser_free(c->record_browsers);
111
112     assert(c->n_objects == 0);
113     
114     avahi_free(c->name);
115     AVAHI_LLIST_REMOVE(Client, clients, server->clients, c);
116     avahi_free(c);
117
118     server->n_clients --;
119     assert(server->n_clients >= 0);
120 }
121
122 static Client *client_get(const char *name, int create) {
123     Client *client;
124
125     assert(server);
126     assert(name);
127
128     for (client = server->clients; client; client = client->clients_next)
129         if (!strcmp(name, client->name))
130             return client;
131
132     if (!create)
133         return NULL;
134
135     if (server->n_clients >= CLIENTS_MAX)
136         return NULL;
137     
138     /* If not existant yet, create a new entry */
139     client = avahi_new(Client, 1);
140     client->id = server->current_id++;
141     client->name = avahi_strdup(name);
142     client->current_id = 0;
143     client->n_objects = 0;
144     
145     AVAHI_LLIST_HEAD_INIT(EntryGroupInfo, client->entry_groups);
146     AVAHI_LLIST_HEAD_INIT(SyncHostNameResolverInfo, client->sync_host_name_resolvers);
147     AVAHI_LLIST_HEAD_INIT(AsyncHostNameResolverInfo, client->async_host_name_resolvers);
148     AVAHI_LLIST_HEAD_INIT(SyncAddressResolverInfo, client->sync_address_resolvers);
149     AVAHI_LLIST_HEAD_INIT(AsyncAddressResolverInfo, client->async_address_resolvers);
150     AVAHI_LLIST_HEAD_INIT(DomainBrowserInfo, client->domain_browsers);
151     AVAHI_LLIST_HEAD_INIT(ServiceTypeBrowserInfo, client->service_type_browsers);
152     AVAHI_LLIST_HEAD_INIT(ServiceBrowserInfo, client->service_browsers);
153     AVAHI_LLIST_HEAD_INIT(SyncServiceResolverInfo, client->sync_service_resolvers);
154     AVAHI_LLIST_HEAD_INIT(AsyncServiceResolverInfo, client->async_service_resolvers);
155     AVAHI_LLIST_HEAD_INIT(RecordBrowserInfo, client->record_browsers);
156
157     AVAHI_LLIST_PREPEND(Client, clients, server->clients, client);
158
159     server->n_clients++;
160     assert(server->n_clients > 0);
161     
162     return client;
163 }
164
165 static void reconnect_callback(AvahiTimeout *t, AVAHI_GCC_UNUSED void *userdata) {
166     assert(!server->bus);
167
168     if (dbus_connect() < 0) {
169         struct timeval tv;
170         avahi_log_debug(__FILE__": Connection failed, retrying in %ims...", RECONNECT_MSEC);
171         avahi_elapse_time(&tv, RECONNECT_MSEC, 0);
172         server->poll_api->timeout_update(t, &tv);
173     } else {
174         avahi_log_debug(__FILE__": Successfully reconnected.");
175         server->poll_api->timeout_update(t, NULL);
176     }
177 }
178
179 static DBusHandlerResult msg_signal_filter_impl(AVAHI_GCC_UNUSED DBusConnection *c, DBusMessage *m, AVAHI_GCC_UNUSED void *userdata) {
180     DBusError error;
181
182     dbus_error_init(&error);
183
184 /*     avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s", */
185 /*                     dbus_message_get_interface(m), */
186 /*                     dbus_message_get_path(m), */
187 /*                     dbus_message_get_member(m)); */
188
189     if (dbus_message_is_signal(m, DBUS_INTERFACE_LOCAL, "Disconnected")) {
190         struct timeval tv;
191
192         if (server->reconnect) {
193             avahi_log_warn("Disconnnected from D-BUS, trying to reconnect in %ims...", RECONNECT_MSEC);
194             
195             dbus_disconnect();
196             
197             avahi_elapse_time(&tv, RECONNECT_MSEC, 0);
198             
199             if (server->reconnect_timeout)
200                 server->poll_api->timeout_update(server->reconnect_timeout, &tv);
201             else
202                 server->reconnect_timeout = server->poll_api->timeout_new(server->poll_api, &tv, reconnect_callback, NULL);
203         } else {
204             avahi_log_warn("Disconnnected from D-BUS, exiting.");
205             raise(SIGQUIT);
206         }
207             
208         return DBUS_HANDLER_RESULT_HANDLED;
209         
210     } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameAcquired")) {
211         char *name;
212
213         if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)) {
214             avahi_log_warn("Error parsing NameAcquired message");
215             goto fail;
216         }
217
218 /*         avahi_log_info(__FILE__": name acquired (%s)", name); */
219         return DBUS_HANDLER_RESULT_HANDLED;
220         
221     } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
222         char *name, *old, *new;
223
224         if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &old, DBUS_TYPE_STRING, &new, DBUS_TYPE_INVALID)) {
225             avahi_log_warn("Error parsing NameOwnerChanged message");
226             goto fail;
227         }
228
229         if (!*new) {
230             Client *client;
231
232             if ((client = client_get(name, FALSE))) {
233                 avahi_log_debug(__FILE__": client %s vanished.", name); 
234                 client_free(client);
235             }
236         }
237     }
238
239 fail:
240     if (dbus_error_is_set(&error))
241         dbus_error_free(&error);
242     
243     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
244 }
245
246 static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAHI_GCC_UNUSED void *userdata) {
247     DBusError error;
248
249     dbus_error_init(&error);
250
251     avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
252                     dbus_message_get_interface(m),
253                     dbus_message_get_path(m),
254                     dbus_message_get_member(m));
255
256     if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
257         return avahi_dbus_handle_introspect(c, m, "Server.introspect");
258         
259     else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostName")) {
260
261         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
262             avahi_log_warn("Error parsing Server::GetHostName message");
263             goto fail;
264         }
265
266         return avahi_dbus_respond_string(c, m, avahi_server_get_host_name(avahi_server));
267         
268     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetDomainName")) {
269
270         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
271             avahi_log_warn("Error parsing Server::GetDomainName message");
272             goto fail;
273         }
274
275         return avahi_dbus_respond_string(c, m, avahi_server_get_domain_name(avahi_server));
276
277     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostNameFqdn")) {
278
279         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
280             avahi_log_warn("Error parsing Server::GetHostNameFqdn message");
281             goto fail;
282         }
283     
284         return avahi_dbus_respond_string(c, m, avahi_server_get_host_name_fqdn(avahi_server));
285         
286     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "IsNSSSupportAvailable")) {
287         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
288             avahi_log_warn("Error parsing Server::IsNSSSupportAvailable message");
289             goto fail;
290         }
291
292         return avahi_dbus_respond_boolean(c, m, nss_support);
293         
294     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetVersionString")) {
295
296         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
297             avahi_log_warn("Error parsing Server::GetVersionString message");
298             goto fail;
299         }
300     
301         return avahi_dbus_respond_string(c, m, PACKAGE_STRING);
302
303     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAPIVersion")) {
304
305         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
306             avahi_log_warn("Error parsing Server::GetAPIVersion message");
307             goto fail;
308         }
309     
310         return avahi_dbus_respond_uint32(c, m, AVAHI_DBUS_API_VERSION);
311
312     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetState")) {
313         AvahiServerState state;
314         
315         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
316             avahi_log_warn("Error parsing Server::GetState message");
317             goto fail;
318         }
319         
320         state = avahi_server_get_state(avahi_server);
321         return avahi_dbus_respond_int32(c, m, (int32_t) state);
322
323     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetLocalServiceCookie")) {
324
325         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
326             avahi_log_warn("Error parsing Server::GetLocalServiceCookie message");
327             goto fail;
328         }
329         
330         return avahi_dbus_respond_uint32(c, m, avahi_server_get_local_service_cookie(avahi_server));
331
332     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceNameByIndex")) {
333         int32_t idx;
334         int fd;
335         char name[IF_NAMESIZE];
336
337         
338         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INT32, &idx, DBUS_TYPE_INVALID))) {
339             avahi_log_warn("Error parsing Server::GetNetworkInterfaceNameByIndex message");
340             goto fail;
341         }
342
343 #ifdef VALGRIND_WORKAROUND
344         return respond_string(c, m, "blah");
345 #else
346         
347         if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 
348             if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
349                 char txt[256];
350                 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
351                 return avahi_dbus_respond_error(c, m, AVAHI_ERR_OS, txt);
352             }
353
354         if ((!if_indextoname(idx, name))) {
355             char txt[256];
356             snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
357             close(fd);
358             return avahi_dbus_respond_error(c, m, AVAHI_ERR_OS, txt);
359         }
360
361         close(fd);
362         
363         return avahi_dbus_respond_string(c, m, name);
364 #endif
365         
366     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceIndexByName")) {
367         char *n;
368         int fd;
369         int32_t idx;
370         
371         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
372             avahi_log_warn("Error parsing Server::GetNetworkInterfaceIndexByName message");
373             goto fail;
374         }
375
376 #ifdef VALGRIND_WORKAROUND
377         return respond_int32(c, m, 1);
378 #else
379         if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 
380             if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
381                 char txt[256];
382                 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
383                 return avahi_dbus_respond_error(c, m, AVAHI_ERR_OS, txt);
384             }
385
386         if (!(idx = if_nametoindex(n))) {
387             char txt[256];
388             snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
389             close(fd);
390             return avahi_dbus_respond_error(c, m, AVAHI_ERR_OS, txt);
391         }
392
393         close(fd);
394         
395         return avahi_dbus_respond_int32(c, m, idx);
396 #endif
397
398     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeHostName")) {
399         char *n, * t;
400         
401         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
402             avahi_log_warn("Error parsing Server::GetAlternativeHostName message");
403             goto fail;
404         }
405
406         t = avahi_alternative_host_name(n);
407         avahi_dbus_respond_string(c, m, t);
408         avahi_free(t);
409
410         return DBUS_HANDLER_RESULT_HANDLED;
411
412     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeServiceName")) {
413         char *n, *t;
414         
415         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
416             avahi_log_warn("Error parsing Server::GetAlternativeServiceName message");
417             goto fail;
418         }
419
420         t = avahi_alternative_service_name(n);
421         avahi_dbus_respond_string(c, m, t);
422         avahi_free(t);
423
424         return DBUS_HANDLER_RESULT_HANDLED;
425         
426     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "EntryGroupNew")) {
427         Client *client;
428         EntryGroupInfo *i;
429         static const DBusObjectPathVTable vtable = {
430             NULL,
431             avahi_dbus_msg_entry_group_impl,
432             NULL,
433             NULL,
434             NULL,
435             NULL
436         };
437
438         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
439             avahi_log_warn("Error parsing Server::EntryGroupNew message");
440             goto fail;
441         }
442
443         if (disable_user_service_publishing)
444             return avahi_dbus_respond_error(c, m, AVAHI_ERR_NOT_PERMITTED, NULL);
445         
446         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
447             avahi_log_warn("Too many clients, client request failed.");
448             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
449         }
450
451         if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
452             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
453             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
454         }
455
456         i = avahi_new(EntryGroupInfo, 1);
457         i->id = ++client->current_id;
458         i->client = client;
459         i->path = NULL;
460         i->n_entries = 0;
461         AVAHI_LLIST_PREPEND(EntryGroupInfo, entry_groups, client->entry_groups, i);
462         client->n_objects++;
463         
464         if (!(i->entry_group = avahi_s_entry_group_new(avahi_server, avahi_dbus_entry_group_callback, i))) {
465             avahi_dbus_entry_group_free(i);
466             return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL);
467         }
468
469         i->path = avahi_strdup_printf("/Client%u/EntryGroup%u", client->id, i->id);
470         dbus_connection_register_object_path(c, i->path, &vtable, i);
471         return avahi_dbus_respond_path(c, m, i->path);
472         
473     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveHostName")) {
474         Client *client;
475         int32_t interface, protocol, aprotocol;
476         uint32_t flags;
477         char *name;
478         SyncHostNameResolverInfo *i;
479             
480         if (!dbus_message_get_args(
481                 m, &error,
482                 DBUS_TYPE_INT32, &interface,
483                 DBUS_TYPE_INT32, &protocol,
484                 DBUS_TYPE_STRING, &name,
485                 DBUS_TYPE_INT32, &aprotocol,
486                 DBUS_TYPE_UINT32, &flags,
487                 DBUS_TYPE_INVALID) || !name) {
488             avahi_log_warn("Error parsing Server::ResolveHostName message");
489             goto fail;
490         }
491
492         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
493             avahi_log_warn("Too many clients, client request failed.");
494             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
495         }
496
497         if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
498             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
499             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
500         }
501
502         i = avahi_new(SyncHostNameResolverInfo, 1);
503         i->client = client;
504         i->message = dbus_message_ref(m);
505         AVAHI_LLIST_PREPEND(SyncHostNameResolverInfo, sync_host_name_resolvers, client->sync_host_name_resolvers, i);
506         client->n_objects++;
507
508         if (!(i->host_name_resolver = avahi_s_host_name_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, (AvahiProtocol) aprotocol, (AvahiLookupFlags) flags, avahi_dbus_sync_host_name_resolver_callback, i))) {
509             avahi_dbus_sync_host_name_resolver_free(i);
510             return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL);
511         }
512         
513         return DBUS_HANDLER_RESULT_HANDLED;
514         
515     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveAddress")) {
516         Client *client;
517         int32_t interface, protocol;
518         uint32_t flags;
519         char *address;
520         SyncAddressResolverInfo *i;
521         AvahiAddress a;
522             
523         if (!dbus_message_get_args(
524                 m, &error,
525                 DBUS_TYPE_INT32, &interface,
526                 DBUS_TYPE_INT32, &protocol,
527                 DBUS_TYPE_STRING, &address,
528                 DBUS_TYPE_UINT32, &flags, 
529                 DBUS_TYPE_INVALID) || !address) {
530             avahi_log_warn("Error parsing Server::ResolveAddress message");
531             goto fail;
532         }
533
534         if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
535             return avahi_dbus_respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
536
537         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
538             avahi_log_warn("Too many clients, client request failed.");
539             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
540         }
541
542         if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
543             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
544             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
545         }
546
547         i = avahi_new(SyncAddressResolverInfo, 1);
548         i->client = client;
549         i->message = dbus_message_ref(m);
550         AVAHI_LLIST_PREPEND(SyncAddressResolverInfo, sync_address_resolvers, client->sync_address_resolvers, i);
551         client->n_objects++;
552
553         if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, avahi_dbus_sync_address_resolver_callback, i))) {
554             avahi_dbus_sync_address_resolver_free(i);
555             return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL);
556         }
557         
558         return DBUS_HANDLER_RESULT_HANDLED;
559         
560     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "DomainBrowserNew")) {
561         Client *client;
562         DomainBrowserInfo *i;
563         static const DBusObjectPathVTable vtable = {
564             NULL,
565             avahi_dbus_msg_domain_browser_impl,
566             NULL,
567             NULL,
568             NULL,
569             NULL
570         };
571         int32_t interface, protocol, type;
572         uint32_t flags;
573         char *domain;
574         
575         if (!dbus_message_get_args(
576                 m, &error,
577                 DBUS_TYPE_INT32, &interface,
578                 DBUS_TYPE_INT32, &protocol,
579                 DBUS_TYPE_STRING, &domain,
580                 DBUS_TYPE_INT32, &type,
581                 DBUS_TYPE_UINT32, &flags,
582                 DBUS_TYPE_INVALID) || type < 0 || type >= AVAHI_DOMAIN_BROWSER_MAX) {
583             avahi_log_warn("Error parsing Server::DomainBrowserNew message");
584             goto fail;
585         }
586
587         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
588             avahi_log_warn("Too many clients, client request failed.");
589             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
590         }
591
592         if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
593             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
594             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
595         }
596
597         if (!*domain)
598             domain = NULL;
599
600         i = avahi_new(DomainBrowserInfo, 1);
601         i->id = ++client->current_id;
602         i->client = client;
603         i->path = NULL;
604         AVAHI_LLIST_PREPEND(DomainBrowserInfo, domain_browsers, client->domain_browsers, i);
605         client->n_objects++;
606
607         if (!(i->domain_browser = avahi_s_domain_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, (AvahiDomainBrowserType) type, (AvahiLookupFlags) flags, avahi_dbus_domain_browser_callback, i))) {
608             avahi_dbus_domain_browser_free(i);
609             return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL);
610         }
611
612         i->path = avahi_strdup_printf("/Client%u/DomainBrowser%u", client->id, i->id);
613         dbus_connection_register_object_path(c, i->path, &vtable, i);
614         return avahi_dbus_respond_path(c, m, i->path);
615
616     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceTypeBrowserNew")) {
617         Client *client;
618         ServiceTypeBrowserInfo *i;
619         static const DBusObjectPathVTable vtable = {
620             NULL,
621             avahi_dbus_msg_service_type_browser_impl,
622             NULL,
623             NULL,
624             NULL,
625             NULL
626         };
627         int32_t interface, protocol;
628         uint32_t flags;
629         char *domain;
630         
631         if (!dbus_message_get_args(
632                 m, &error,
633                 DBUS_TYPE_INT32, &interface,
634                 DBUS_TYPE_INT32, &protocol,
635                 DBUS_TYPE_STRING, &domain,
636                 DBUS_TYPE_UINT32, &flags,
637                 DBUS_TYPE_INVALID)) {
638             avahi_log_warn("Error parsing Server::ServiceTypeBrowserNew message");
639             goto fail;
640         }
641
642         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
643             avahi_log_warn("Too many clients, client request failed.");
644             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
645         }
646
647         if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
648             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
649             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
650         }
651
652         if (!*domain)
653             domain = NULL;
654
655         i = avahi_new(ServiceTypeBrowserInfo, 1);
656         i->id = ++client->current_id;
657         i->client = client;
658         i->path = NULL;
659         AVAHI_LLIST_PREPEND(ServiceTypeBrowserInfo, service_type_browsers, client->service_type_browsers, i);
660         client->n_objects++;
661
662         if (!(i->service_type_browser = avahi_s_service_type_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, (AvahiLookupFlags) flags, avahi_dbus_service_type_browser_callback, i))) {
663             avahi_dbus_service_type_browser_free(i);
664             return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL);
665         }
666         
667         i->path = avahi_strdup_printf("/Client%u/ServiceTypeBrowser%u", client->id, i->id);
668         dbus_connection_register_object_path(c, i->path, &vtable, i);
669         return avahi_dbus_respond_path(c, m, i->path);
670         
671     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceBrowserNew")) {
672         Client *client;
673         ServiceBrowserInfo *i;
674         static const DBusObjectPathVTable vtable = {
675             NULL,
676             avahi_dbus_msg_service_browser_impl,
677             NULL,
678             NULL,
679             NULL,
680             NULL
681         };
682         int32_t interface, protocol;
683         uint32_t flags;
684         char *domain, *type;
685         
686         if (!dbus_message_get_args(
687                 m, &error,
688                 DBUS_TYPE_INT32, &interface,
689                 DBUS_TYPE_INT32, &protocol,
690                 DBUS_TYPE_STRING, &type,
691                 DBUS_TYPE_STRING, &domain,
692                 DBUS_TYPE_UINT32, &flags,
693                 DBUS_TYPE_INVALID) || !type) {
694             avahi_log_warn("Error parsing Server::ServiceBrowserNew message");
695             goto fail;
696         }
697
698         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
699             avahi_log_warn("Too many clients, client request failed.");
700             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
701         }
702
703         if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
704             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
705             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
706         }
707
708         if (!*domain)
709             domain = NULL;
710
711         i = avahi_new(ServiceBrowserInfo, 1);
712         i->id = ++client->current_id;
713         i->client = client;
714         i->path = NULL;
715         AVAHI_LLIST_PREPEND(ServiceBrowserInfo, service_browsers, client->service_browsers, i);
716         client->n_objects++;
717
718         if (!(i->service_browser = avahi_s_service_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, type, domain, (AvahiLookupFlags) flags, avahi_dbus_service_browser_callback, i))) {
719             avahi_dbus_service_browser_free(i);
720             return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL);
721         }
722
723         i->path = avahi_strdup_printf("/Client%u/ServiceBrowser%u", client->id, i->id);
724         dbus_connection_register_object_path(c, i->path, &vtable, i);
725         return avahi_dbus_respond_path(c, m, i->path);
726         
727     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveService")) {
728         Client *client;
729         int32_t interface, protocol, aprotocol;
730         uint32_t flags;
731         char *name, *type, *domain;
732         SyncServiceResolverInfo *i;
733             
734         if (!dbus_message_get_args(
735                 m, &error,
736                 DBUS_TYPE_INT32, &interface,
737                 DBUS_TYPE_INT32, &protocol,
738                 DBUS_TYPE_STRING, &name,
739                 DBUS_TYPE_STRING, &type,
740                 DBUS_TYPE_STRING, &domain,
741                 DBUS_TYPE_INT32, &aprotocol,
742                 DBUS_TYPE_UINT32, &flags,
743                 DBUS_TYPE_INVALID) || !type) {
744             avahi_log_warn("Error parsing Server::ResolveService message");
745             goto fail;
746         }
747
748         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
749             avahi_log_warn("Too many clients, client request failed.");
750             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
751         }
752         
753         if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
754             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
755             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
756         }
757
758         if (!*domain)
759             domain = NULL;
760
761         if (!*name)
762             name = NULL;
763         
764         i = avahi_new(SyncServiceResolverInfo, 1);
765         i->client = client;
766         i->message = dbus_message_ref(m);
767         AVAHI_LLIST_PREPEND(SyncServiceResolverInfo, sync_service_resolvers, client->sync_service_resolvers, i);
768         client->n_objects++;
769
770         if (!(i->service_resolver = avahi_s_service_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, type, domain, (AvahiProtocol) aprotocol, (AvahiLookupFlags) flags, avahi_dbus_sync_service_resolver_callback, i))) {
771             avahi_dbus_sync_service_resolver_free(i);
772             return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL);
773         }
774         
775         return DBUS_HANDLER_RESULT_HANDLED;
776         
777     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceResolverNew")) {
778         Client *client;
779         int32_t interface, protocol, aprotocol;
780         uint32_t flags;
781         char *name, *type, *domain;
782         AsyncServiceResolverInfo *i;
783         static const DBusObjectPathVTable vtable = {
784             NULL,
785             avahi_dbus_msg_async_service_resolver_impl,
786             NULL,
787             NULL,
788             NULL,
789             NULL
790         };
791
792         if (!dbus_message_get_args(
793                 m, &error,
794                 DBUS_TYPE_INT32, &interface,
795                 DBUS_TYPE_INT32, &protocol,
796                 DBUS_TYPE_STRING, &name,
797                 DBUS_TYPE_STRING, &type,
798                 DBUS_TYPE_STRING, &domain,
799                 DBUS_TYPE_INT32, &aprotocol,
800                 DBUS_TYPE_UINT32, &flags,
801                 DBUS_TYPE_INVALID) || !type) {
802             avahi_log_warn("Error parsing Server::ServiceResolverNew message");
803             goto fail;
804         }
805             
806         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
807             avahi_log_warn(__FILE__": Too many clients, client request failed.");
808             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
809         }
810
811         if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
812             avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
813             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
814         }
815
816         if (!*domain)
817             domain = NULL;
818
819         if (!*name)
820             name = NULL;
821         
822         i = avahi_new(AsyncServiceResolverInfo, 1);
823         i->id = ++client->current_id;
824         i->client = client;
825         i->path = NULL;
826         AVAHI_LLIST_PREPEND(AsyncServiceResolverInfo, async_service_resolvers, client->async_service_resolvers, i);
827         client->n_objects++;
828
829         if (!(i->service_resolver = avahi_s_service_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, type, domain, (AvahiProtocol) aprotocol, (AvahiLookupFlags) flags, avahi_dbus_async_service_resolver_callback, i))) {
830             avahi_dbus_async_service_resolver_free(i);
831             return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL);
832         }
833
834 /*         avahi_log_debug(__FILE__": [%s], new service resolver for <%s.%s.%s>", i->path, name, type, domain); */
835         
836         i->path = avahi_strdup_printf("/Client%u/ServiceResolver%u", client->id, i->id);
837         dbus_connection_register_object_path(c, i->path, &vtable, i);
838         return avahi_dbus_respond_path(c, m, i->path);
839
840     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "HostNameResolverNew")) {
841         Client *client;
842         int32_t interface, protocol, aprotocol;
843         uint32_t flags;
844         char *name;
845         AsyncHostNameResolverInfo *i;
846         static const DBusObjectPathVTable vtable = {
847             NULL,
848             avahi_dbus_msg_async_host_name_resolver_impl,
849             NULL,
850             NULL,
851             NULL,
852             NULL
853         };
854             
855         if (!dbus_message_get_args(
856                 m, &error,
857                 DBUS_TYPE_INT32, &interface,
858                 DBUS_TYPE_INT32, &protocol,
859                 DBUS_TYPE_STRING, &name,
860                 DBUS_TYPE_INT32, &aprotocol,
861                 DBUS_TYPE_UINT32, &flags,
862                 DBUS_TYPE_INVALID) || !name) {
863             avahi_log_warn("Error parsing Server::HostNameResolverNew message");
864             goto fail;
865         }
866             
867         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
868             avahi_log_warn(__FILE__": Too many clients, client request failed.");
869             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
870         }
871
872         if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
873             avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
874             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
875         }
876
877         i = avahi_new(AsyncHostNameResolverInfo, 1);
878         i->id = ++client->current_id;
879         i->client = client;
880         i->path = NULL;
881         AVAHI_LLIST_PREPEND(AsyncHostNameResolverInfo, async_host_name_resolvers, client->async_host_name_resolvers, i);
882         client->n_objects++;
883
884         if (!(i->host_name_resolver = avahi_s_host_name_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, aprotocol, (AvahiLookupFlags) flags, avahi_dbus_async_host_name_resolver_callback, i))) {
885             avahi_dbus_async_host_name_resolver_free(i);
886             return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL);
887         }
888
889         i->path = avahi_strdup_printf("/Client%u/HostNameResolver%u", client->id, i->id);
890         dbus_connection_register_object_path(c, i->path, &vtable, i);
891         return avahi_dbus_respond_path(c, m, i->path);
892
893     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "AddressResolverNew")) {
894         Client *client;
895         int32_t interface, protocol;
896         uint32_t flags;
897         char *address;
898         AsyncAddressResolverInfo *i;
899         AvahiAddress a;
900         static const DBusObjectPathVTable vtable = {
901             NULL,
902             avahi_dbus_msg_async_address_resolver_impl,
903             NULL,
904             NULL,
905             NULL,
906             NULL
907         };
908             
909         if (!dbus_message_get_args(
910                 m, &error,
911                 DBUS_TYPE_INT32, &interface,
912                 DBUS_TYPE_INT32, &protocol,
913                 DBUS_TYPE_STRING, &address,
914                 DBUS_TYPE_UINT32, &flags,
915                 DBUS_TYPE_INVALID) || !address) {
916             avahi_log_warn("Error parsing Server::AddressResolverNew message");
917             goto fail;
918         }
919
920         if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
921             return avahi_dbus_respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
922
923         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
924             avahi_log_warn(__FILE__": Too many clients, client request failed.");
925             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
926         }
927
928         if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
929             avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
930             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
931         }
932
933         i = avahi_new(AsyncAddressResolverInfo, 1);
934         i->id = ++client->current_id;
935         i->client = client;
936         i->path = NULL;
937         AVAHI_LLIST_PREPEND(AsyncAddressResolverInfo, async_address_resolvers, client->async_address_resolvers, i);
938         client->n_objects++;
939
940         if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, avahi_dbus_async_address_resolver_callback, i))) {
941             avahi_dbus_async_address_resolver_free(i);
942             return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL);
943         }
944
945         i->path = avahi_strdup_printf("/Client%u/AddressResolver%u", client->id, i->id);
946         dbus_connection_register_object_path(c, i->path, &vtable, i);
947         return avahi_dbus_respond_path(c, m, i->path);
948         
949     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "RecordBrowserNew")) {
950         Client *client;
951         RecordBrowserInfo *i;
952         static const DBusObjectPathVTable vtable = {
953             NULL,
954             avahi_dbus_msg_record_browser_impl,
955             NULL,
956             NULL,
957             NULL,
958             NULL
959         };
960         int32_t interface, protocol;
961         uint32_t flags;
962         char *name;
963         uint16_t type, clazz;
964         AvahiKey *key;
965         
966         if (!dbus_message_get_args(
967                 m, &error,
968                 DBUS_TYPE_INT32, &interface,
969                 DBUS_TYPE_INT32, &protocol,
970                 DBUS_TYPE_STRING, &name,
971                 DBUS_TYPE_UINT16, &clazz,
972                 DBUS_TYPE_UINT16, &type,
973                 DBUS_TYPE_UINT32, &flags,
974                 DBUS_TYPE_INVALID) || !name) {
975             avahi_log_warn("Error parsing Server::RecordBrowserNew message");
976             goto fail;
977         }
978
979         if (!avahi_is_valid_domain_name(name)) 
980             return avahi_dbus_respond_error(c, m, AVAHI_ERR_INVALID_DOMAIN_NAME, NULL);
981
982         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
983             avahi_log_warn("Too many clients, client request failed.");
984             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
985         }
986
987         if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
988             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
989             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
990         }
991
992         i = avahi_new(RecordBrowserInfo, 1);
993         i->id = ++client->current_id;
994         i->client = client;
995         i->path = NULL;
996         AVAHI_LLIST_PREPEND(RecordBrowserInfo, record_browsers, client->record_browsers, i);
997         client->n_objects++;
998
999         key = avahi_key_new(name, clazz, type);
1000         assert(key);
1001
1002         if (!(i->record_browser = avahi_s_record_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, key, (AvahiLookupFlags) flags, avahi_dbus_record_browser_callback, i))) {
1003             avahi_key_unref(key);
1004             avahi_dbus_record_browser_free(i);
1005             return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1006         }
1007
1008         avahi_key_unref(key);
1009         
1010         i->path = avahi_strdup_printf("/Client%u/RecordBrowser%u", client->id, i->id);
1011         dbus_connection_register_object_path(c, i->path, &vtable, i);
1012         return avahi_dbus_respond_path(c, m, i->path);
1013     }
1014
1015     avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1016
1017 fail:
1018     if (dbus_error_is_set(&error))
1019         dbus_error_free(&error);
1020     
1021     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1022 }
1023
1024 void dbus_protocol_server_state_changed(AvahiServerState state) {
1025     DBusMessage *m;
1026     int32_t t;
1027     const char *e;
1028     
1029     if (!server || !server->bus)
1030         return;
1031
1032     m = dbus_message_new_signal(AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "StateChanged");
1033     t = (int32_t) state;
1034
1035     if (state == AVAHI_SERVER_COLLISION)
1036         e = AVAHI_DBUS_ERR_COLLISION;
1037     else if (state == AVAHI_SERVER_FAILURE)
1038         e = avahi_error_number_to_dbus(avahi_server_errno(avahi_server));
1039     else
1040         e = AVAHI_DBUS_ERR_OK;
1041     
1042     dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_STRING, &e, DBUS_TYPE_INVALID);
1043     dbus_connection_send(server->bus, m, NULL);
1044     dbus_message_unref(m);
1045 }
1046
1047 static int dbus_connect(void) {
1048     DBusError error;
1049
1050     static const DBusObjectPathVTable server_vtable = {
1051         NULL,
1052         msg_server_impl,
1053         NULL,
1054         NULL,
1055         NULL,
1056         NULL
1057     };
1058
1059     assert(server);
1060     assert(!server->bus);
1061
1062     dbus_error_init(&error);
1063     
1064     if (!(server->bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
1065         assert(dbus_error_is_set(&error));
1066         avahi_log_error("dbus_bus_get(): %s", error.message);
1067         goto fail;
1068     }
1069     if (avahi_dbus_connection_glue(server->bus, server->poll_api) < 0) {
1070         avahi_log_error("avahi_dbus_connection_glue() failed");
1071         goto fail;
1072     }
1073
1074     dbus_connection_set_exit_on_disconnect(server->bus, FALSE);
1075     
1076     if (dbus_bus_request_name(
1077             server->bus,
1078             AVAHI_DBUS_NAME,
1079 #if (DBUS_VERSION_MAJOR == 0) && (DBUS_VERSION_MINOR >= 60)
1080             DBUS_NAME_FLAG_DO_NOT_QUEUE,
1081 #else
1082             DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT,
1083 #endif
1084             &error) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
1085         if (dbus_error_is_set(&error)) {
1086             avahi_log_error("dbus_bus_request_name(): %s", error.message);
1087             goto fail;
1088         }
1089
1090         avahi_log_error("Failed to acquire DBUS name '"AVAHI_DBUS_NAME"'");
1091         goto fail;
1092     }
1093
1094     if (!(dbus_connection_add_filter(server->bus, msg_signal_filter_impl, (void*) server->poll_api, NULL))) {
1095         avahi_log_error("dbus_connection_add_filter() failed");
1096         goto fail;
1097     }
1098     
1099     dbus_bus_add_match(server->bus, "type='signal',""interface='" DBUS_INTERFACE_DBUS  "'", &error);
1100
1101     if (dbus_error_is_set(&error)) {
1102         avahi_log_error("dbus_bus_add_match(): %s", error.message);
1103         goto fail;
1104     }
1105     
1106     if (!(dbus_connection_register_object_path(server->bus, AVAHI_DBUS_PATH_SERVER, &server_vtable, NULL))) {
1107         avahi_log_error("dbus_connection_register_object_path() failed");
1108         goto fail;
1109     }
1110
1111     return 0;
1112 fail:
1113
1114     if (dbus_error_is_set(&error))
1115         dbus_error_free(&error);
1116
1117     if (server->bus) {
1118 #if (DBUS_VERSION_MAJOR == 0) && (DBUS_VERSION_MINOR >= 62)
1119         dbus_connection_close(server->bus);
1120 #else
1121         dbus_connection_disconnect(server->bus);
1122 #endif
1123         dbus_connection_unref(server->bus);
1124         server->bus = NULL;
1125     }
1126
1127     return -1;
1128 }
1129
1130 static void dbus_disconnect(void) {
1131     assert(server);
1132
1133     while (server->clients)
1134         client_free(server->clients);
1135     
1136     assert(server->n_clients == 0);
1137
1138     if (server->bus) {
1139 #if (DBUS_VERSION_MAJOR == 0) && (DBUS_VERSION_MINOR >= 62)
1140         dbus_connection_close(server->bus);
1141 #else
1142         dbus_connection_disconnect(server->bus);
1143 #endif
1144         dbus_connection_unref(server->bus);
1145         server->bus = NULL;
1146     }
1147 }
1148
1149 int dbus_protocol_setup(const AvahiPoll *poll_api, int _disable_user_service_publishing, int force) {
1150
1151     disable_user_service_publishing = _disable_user_service_publishing;
1152
1153     server = avahi_new(Server, 1);
1154     AVAHI_LLIST_HEAD_INIT(Clients, server->clients);
1155     server->current_id = 0;
1156     server->n_clients = 0;
1157     server->bus = NULL;
1158     server->poll_api = poll_api;
1159     server->reconnect_timeout = NULL;
1160     server->reconnect = force;
1161
1162     if (dbus_connect() < 0) {
1163         struct timeval tv;
1164
1165         if (!force)
1166             goto fail;
1167
1168         avahi_log_warn("WARNING: Failed to contact D-BUS daemon, retrying in %ims.", RECONNECT_MSEC);
1169         
1170         avahi_elapse_time(&tv, RECONNECT_MSEC, 0);
1171         server->reconnect_timeout = server->poll_api->timeout_new(server->poll_api, &tv, reconnect_callback, NULL);
1172     }
1173         
1174     return 0;
1175
1176 fail:
1177     if (server->bus) {
1178 #if (DBUS_VERSION_MAJOR == 0) && (DBUS_VERSION_MINOR >= 62)
1179         dbus_connection_close(server->bus);
1180 #else
1181         dbus_connection_disconnect(server->bus);
1182 #endif
1183         dbus_connection_unref(server->bus);
1184     }
1185
1186     avahi_free(server);
1187     server = NULL;
1188     return -1;
1189 }
1190
1191 void dbus_protocol_shutdown(void) {
1192
1193     if (server) {
1194         dbus_disconnect();
1195
1196         if (server->reconnect_timeout)
1197             server->poll_api->timeout_free(server->reconnect_timeout);
1198         
1199         avahi_free(server);
1200         server = NULL;
1201     }
1202 }