]> git.meshlink.io Git - catta/blob - avahi-daemon/dbus-protocol.c
* remove some --disable in boostrap.sh for osx
[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 <netinet/in.h>
29 #include <net/if.h>
30 #include <errno.h>
31 #include <unistd.h>
32 #include <assert.h>
33 #include <sys/stat.h>
34 #include <fcntl.h>
35 #include <stdio.h>
36 #include <signal.h>
37 #include <stdlib.h>
38
39 #include <dbus/dbus.h>
40
41 #include <avahi-common/dbus.h>
42 #include <avahi-common/llist.h>
43 #include <avahi-common/malloc.h>
44 #include <avahi-common/dbus.h>
45 #include <avahi-common/dbus-watch-glue.h>
46 #include <avahi-common/alternative.h>
47 #include <avahi-common/error.h>
48
49 #include <avahi-core/log.h>
50 #include <avahi-core/core.h>
51 #include <avahi-core/lookup.h>
52 #include <avahi-core/publish.h>
53
54 #include "dbus-protocol.h"
55 #include "main.h"
56
57 typedef struct Server Server;
58 typedef struct Client Client;
59 typedef struct EntryGroupInfo EntryGroupInfo;
60 typedef struct SyncHostNameResolverInfo SyncHostNameResolverInfo;
61 typedef struct AsyncHostNameResolverInfo AsyncHostNameResolverInfo;
62 typedef struct SyncAddressResolverInfo SyncAddressResolverInfo;
63 typedef struct AsyncAddressResolverInfo AsyncAddressResolverInfo;
64 typedef struct DomainBrowserInfo DomainBrowserInfo;
65 typedef struct ServiceTypeBrowserInfo ServiceTypeBrowserInfo;
66 typedef struct ServiceBrowserInfo ServiceBrowserInfo;
67 typedef struct SyncServiceResolverInfo SyncServiceResolverInfo;
68 typedef struct AsyncServiceResolverInfo AsyncServiceResolverInfo;
69
70 #define MAX_CLIENTS 20
71 #define MAX_OBJECTS_PER_CLIENT 50
72 #define MAX_ENTRIES_PER_ENTRY_GROUP 20
73
74 /* #define VALGRIND_WORKAROUND 1 */
75
76 struct EntryGroupInfo {
77     unsigned id;
78     Client *client;
79     AvahiSEntryGroup *entry_group;
80     char *path;
81
82     int n_entries;
83     
84     AVAHI_LLIST_FIELDS(EntryGroupInfo, entry_groups);
85 };
86
87 struct SyncHostNameResolverInfo {
88     Client *client;
89     AvahiSHostNameResolver *host_name_resolver;
90     DBusMessage *message;
91
92     AVAHI_LLIST_FIELDS(SyncHostNameResolverInfo, sync_host_name_resolvers);
93 };
94
95 struct AsyncHostNameResolverInfo {
96     unsigned id;
97     Client *client;
98     AvahiSHostNameResolver *host_name_resolver;
99     char *path;
100
101     AVAHI_LLIST_FIELDS(AsyncHostNameResolverInfo, async_host_name_resolvers);
102 };
103
104 struct SyncAddressResolverInfo {
105     Client *client;
106     AvahiSAddressResolver *address_resolver;
107     DBusMessage *message;
108
109     AVAHI_LLIST_FIELDS(SyncAddressResolverInfo, sync_address_resolvers);
110 };
111
112 struct AsyncAddressResolverInfo {
113     unsigned id;
114     Client *client;
115     AvahiSAddressResolver *address_resolver;
116     char *path;
117
118     AVAHI_LLIST_FIELDS(AsyncAddressResolverInfo, async_address_resolvers);
119 };
120
121 struct DomainBrowserInfo {
122     unsigned id;
123     Client *client;
124     AvahiSDomainBrowser *domain_browser;
125     char *path;
126
127     AVAHI_LLIST_FIELDS(DomainBrowserInfo, domain_browsers);
128 };
129
130 struct ServiceTypeBrowserInfo {
131     unsigned id;
132     Client *client;
133     AvahiSServiceTypeBrowser *service_type_browser;
134     char *path;
135
136     AVAHI_LLIST_FIELDS(ServiceTypeBrowserInfo, service_type_browsers);
137 };
138
139 struct ServiceBrowserInfo {
140     unsigned id;
141     Client *client;
142     AvahiSServiceBrowser *service_browser;
143     char *path;
144
145     AVAHI_LLIST_FIELDS(ServiceBrowserInfo, service_browsers);
146 };
147
148 struct SyncServiceResolverInfo {
149     Client *client;
150     AvahiSServiceResolver *service_resolver;
151     DBusMessage *message;
152
153     AVAHI_LLIST_FIELDS(SyncServiceResolverInfo, sync_service_resolvers);
154 };
155
156 struct AsyncServiceResolverInfo {
157     unsigned id;
158     Client *client;
159     AvahiSServiceResolver *service_resolver;
160     char *path;
161
162     AVAHI_LLIST_FIELDS(AsyncServiceResolverInfo, async_service_resolvers);
163 };
164
165 struct Client {
166     unsigned id;
167     char *name;
168     unsigned current_id;
169     int n_objects;
170     
171     AVAHI_LLIST_FIELDS(Client, clients);
172     AVAHI_LLIST_HEAD(EntryGroupInfo, entry_groups);
173     AVAHI_LLIST_HEAD(SyncHostNameResolverInfo, sync_host_name_resolvers);
174     AVAHI_LLIST_HEAD(AsyncHostNameResolverInfo, async_host_name_resolvers);
175     AVAHI_LLIST_HEAD(SyncAddressResolverInfo, sync_address_resolvers);
176     AVAHI_LLIST_HEAD(AsyncAddressResolverInfo, async_address_resolvers);
177     AVAHI_LLIST_HEAD(DomainBrowserInfo, domain_browsers);
178     AVAHI_LLIST_HEAD(ServiceTypeBrowserInfo, service_type_browsers);
179     AVAHI_LLIST_HEAD(ServiceBrowserInfo, service_browsers);
180     AVAHI_LLIST_HEAD(SyncServiceResolverInfo, sync_service_resolvers);
181     AVAHI_LLIST_HEAD(AsyncServiceResolverInfo, async_service_resolvers);
182 };
183
184 struct Server {
185     DBusConnection *bus;
186     AVAHI_LLIST_HEAD(Client, clients);
187     int n_clients;
188     unsigned current_id;
189 };
190
191 static Server *server = NULL;
192
193 static void entry_group_free(EntryGroupInfo *i) {
194     assert(i);
195
196     if (i->entry_group)
197         avahi_s_entry_group_free(i->entry_group);
198     dbus_connection_unregister_object_path(server->bus, i->path);
199     avahi_free(i->path);
200     AVAHI_LLIST_REMOVE(EntryGroupInfo, entry_groups, i->client->entry_groups, i);
201
202     i->client->n_objects--;
203     assert(i->client->n_objects >= 0);
204     
205     avahi_free(i);
206 }
207
208 static void sync_host_name_resolver_free(SyncHostNameResolverInfo *i) {
209     assert(i);
210
211     if (i->host_name_resolver)
212         avahi_s_host_name_resolver_free(i->host_name_resolver);
213     dbus_message_unref(i->message);
214     AVAHI_LLIST_REMOVE(SyncHostNameResolverInfo, sync_host_name_resolvers, i->client->sync_host_name_resolvers, i);
215
216     i->client->n_objects--;
217     assert(i->client->n_objects >= 0);
218
219     avahi_free(i);
220 }
221
222 static void async_host_name_resolver_free(AsyncHostNameResolverInfo *i) {
223     assert(i);
224
225     if (i->host_name_resolver)
226         avahi_s_host_name_resolver_free(i->host_name_resolver);
227     dbus_connection_unregister_object_path(server->bus, i->path);
228     AVAHI_LLIST_REMOVE(AsyncHostNameResolverInfo, async_host_name_resolvers, i->client->async_host_name_resolvers, i);
229
230     i->client->n_objects--;
231     assert(i->client->n_objects >= 0);
232
233     avahi_free(i);
234 }
235
236 static void sync_address_resolver_free(SyncAddressResolverInfo *i) {
237     assert(i);
238
239     if (i->address_resolver)
240         avahi_s_address_resolver_free(i->address_resolver);
241     dbus_message_unref(i->message);
242     AVAHI_LLIST_REMOVE(SyncAddressResolverInfo, sync_address_resolvers, i->client->sync_address_resolvers, i);
243
244     i->client->n_objects--;
245     assert(i->client->n_objects >= 0);
246
247     avahi_free(i);
248 }
249
250 static void async_address_resolver_free(AsyncAddressResolverInfo *i) {
251     assert(i);
252
253     if (i->address_resolver)
254         avahi_s_address_resolver_free(i->address_resolver);
255     dbus_connection_unregister_object_path(server->bus, i->path);
256     AVAHI_LLIST_REMOVE(AsyncAddressResolverInfo, async_address_resolvers, i->client->async_address_resolvers, i);
257
258     i->client->n_objects--;
259     assert(i->client->n_objects >= 0);
260
261     avahi_free(i);
262 }
263
264 static void domain_browser_free(DomainBrowserInfo *i) {
265     assert(i);
266
267     if (i->domain_browser)
268         avahi_s_domain_browser_free(i->domain_browser);
269     dbus_connection_unregister_object_path(server->bus, i->path);
270     avahi_free(i->path);
271     AVAHI_LLIST_REMOVE(DomainBrowserInfo, domain_browsers, i->client->domain_browsers, i);
272
273     i->client->n_objects--;
274     assert(i->client->n_objects >= 0);
275
276     avahi_free(i);
277 }
278
279 static void service_type_browser_free(ServiceTypeBrowserInfo *i) {
280     assert(i);
281
282     if (i->service_type_browser)
283         avahi_s_service_type_browser_free(i->service_type_browser);
284     dbus_connection_unregister_object_path(server->bus, i->path);
285     avahi_free(i->path);
286     AVAHI_LLIST_REMOVE(ServiceTypeBrowserInfo, service_type_browsers, i->client->service_type_browsers, i);
287
288     i->client->n_objects--;
289     assert(i->client->n_objects >= 0);
290
291     avahi_free(i);
292 }
293
294 static void service_browser_free(ServiceBrowserInfo *i) {
295     assert(i);
296
297     if (i->service_browser)
298         avahi_s_service_browser_free(i->service_browser);
299     dbus_connection_unregister_object_path(server->bus, i->path);
300     avahi_free(i->path);
301     AVAHI_LLIST_REMOVE(ServiceBrowserInfo, service_browsers, i->client->service_browsers, i);
302
303     i->client->n_objects--;
304     assert(i->client->n_objects >= 0);
305
306     avahi_free(i);
307 }
308
309 static void sync_service_resolver_free(SyncServiceResolverInfo *i) {
310     assert(i);
311
312     if (i->service_resolver)
313         avahi_s_service_resolver_free(i->service_resolver);
314     dbus_message_unref(i->message);
315     AVAHI_LLIST_REMOVE(SyncServiceResolverInfo, sync_service_resolvers, i->client->sync_service_resolvers, i);
316
317     i->client->n_objects--;
318     assert(i->client->n_objects >= 0);
319
320     avahi_free(i);
321 }
322
323 static void async_service_resolver_free(AsyncServiceResolverInfo *i) {
324     assert(i);
325
326     if (i->service_resolver)
327         avahi_s_service_resolver_free(i->service_resolver);
328
329     dbus_connection_unregister_object_path(server->bus, i->path);
330     AVAHI_LLIST_REMOVE(AsyncServiceResolverInfo, async_service_resolvers, i->client->async_service_resolvers, i);
331
332     i->client->n_objects--;
333     assert(i->client->n_objects >= 0);
334
335     avahi_free(i);
336 }
337
338 static void client_free(Client *c) {
339     
340     assert(server);
341     assert(c);
342
343     while (c->entry_groups)
344         entry_group_free(c->entry_groups);
345
346     while (c->sync_host_name_resolvers)
347         sync_host_name_resolver_free(c->sync_host_name_resolvers);
348
349     while (c->async_host_name_resolvers)
350         async_host_name_resolver_free(c->async_host_name_resolvers);
351     
352     while (c->sync_address_resolvers)
353         sync_address_resolver_free(c->sync_address_resolvers);
354
355     while (c->async_address_resolvers)
356         async_address_resolver_free(c->async_address_resolvers);
357
358     while (c->domain_browsers)
359         domain_browser_free(c->domain_browsers);
360
361     while (c->service_type_browsers)
362         service_type_browser_free(c->service_type_browsers);
363
364     while (c->service_browsers)
365         service_browser_free(c->service_browsers);
366
367     while (c->sync_service_resolvers)
368         sync_service_resolver_free(c->sync_service_resolvers);
369
370     while (c->async_service_resolvers)
371         async_service_resolver_free(c->async_service_resolvers);
372
373     assert(c->n_objects == 0);
374     
375     avahi_free(c->name);
376     AVAHI_LLIST_REMOVE(Client, clients, server->clients, c);
377     avahi_free(c);
378
379     server->n_clients --;
380     assert(server->n_clients >= 0);
381 }
382
383 static Client *client_get(const char *name, int create) {
384     Client *client;
385
386     assert(server);
387     assert(name);
388
389     for (client = server->clients; client; client = client->clients_next)
390         if (!strcmp(name, client->name))
391             return client;
392
393     if (!create)
394         return NULL;
395
396     if (server->n_clients >= MAX_CLIENTS)
397         return NULL;
398     
399     /* If not existant yet, create a new entry */
400     client = avahi_new(Client, 1);
401     client->id = server->current_id++;
402     client->name = avahi_strdup(name);
403     client->current_id = 0;
404     client->n_objects = 0;
405     
406     AVAHI_LLIST_HEAD_INIT(EntryGroupInfo, client->entry_groups);
407     AVAHI_LLIST_HEAD_INIT(SyncHostNameResolverInfo, client->sync_host_name_resolvers);
408     AVAHI_LLIST_HEAD_INIT(AsyncHostNameResolverInfo, client->async_host_name_resolvers);
409     AVAHI_LLIST_HEAD_INIT(SyncAddressResolverInfo, client->sync_address_resolvers);
410     AVAHI_LLIST_HEAD_INIT(AsyncAddressResolverInfo, client->async_address_resolvers);
411     AVAHI_LLIST_HEAD_INIT(DomainBrowserInfo, client->domain_browsers);
412     AVAHI_LLIST_HEAD_INIT(ServiceTypeBrowserInfo, client->service_type_browsers);
413     AVAHI_LLIST_HEAD_INIT(ServiceBrowserInfo, client->service_browsers);
414     AVAHI_LLIST_HEAD_INIT(SyncServiceResolverInfo, client->sync_service_resolvers);
415     AVAHI_LLIST_HEAD_INIT(AsyncServiceResolverInfo, client->async_service_resolvers);
416
417     AVAHI_LLIST_PREPEND(Client, clients, server->clients, client);
418
419     server->n_clients++;
420     assert(server->n_clients > 0);
421     
422     return client;
423 }
424
425 static DBusHandlerResult respond_error(DBusConnection *c, DBusMessage *m, int error, const char *text) {
426     DBusMessage *reply;
427
428     assert(-error > -AVAHI_OK);
429     assert(-error < -AVAHI_ERR_MAX);
430
431     if (!text)
432         text = avahi_strerror(error);
433     
434     reply = dbus_message_new_error(m, avahi_error_number_to_dbus(error), text);
435     dbus_connection_send(c, reply, NULL);
436     dbus_message_unref(reply);
437
438     avahi_log_debug(__FILE__": Responding error '%s' (%i)", text, error);
439     
440     return DBUS_HANDLER_RESULT_HANDLED;
441 }
442
443 static DBusHandlerResult respond_string(DBusConnection *c, DBusMessage *m, const char *text) {
444     DBusMessage *reply;
445
446     reply = dbus_message_new_method_return(m);
447     dbus_message_append_args(reply, DBUS_TYPE_STRING, &text, DBUS_TYPE_INVALID);
448     dbus_connection_send(c, reply, NULL);
449     dbus_message_unref(reply);
450     
451     return DBUS_HANDLER_RESULT_HANDLED;
452 }
453
454 static DBusHandlerResult respond_int32(DBusConnection *c, DBusMessage *m, int32_t i) {
455     DBusMessage *reply;
456
457     reply = dbus_message_new_method_return(m);
458     dbus_message_append_args(reply, DBUS_TYPE_INT32, &i, DBUS_TYPE_INVALID);
459     dbus_connection_send(c, reply, NULL);
460     dbus_message_unref(reply);
461     
462     return DBUS_HANDLER_RESULT_HANDLED;
463 }
464
465 static DBusHandlerResult respond_uint32(DBusConnection *c, DBusMessage *m, uint32_t u) {
466     DBusMessage *reply;
467
468     reply = dbus_message_new_method_return(m);
469     dbus_message_append_args(reply, DBUS_TYPE_UINT32, &u, DBUS_TYPE_INVALID);
470     dbus_connection_send(c, reply, NULL);
471     dbus_message_unref(reply);
472     
473     return DBUS_HANDLER_RESULT_HANDLED;
474 }
475
476 static DBusHandlerResult respond_boolean(DBusConnection *c, DBusMessage *m, int b) {
477     DBusMessage *reply;
478
479     reply = dbus_message_new_method_return(m);
480     dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &b, DBUS_TYPE_INVALID);
481     dbus_connection_send(c, reply, NULL);
482     dbus_message_unref(reply);
483     
484     return DBUS_HANDLER_RESULT_HANDLED;
485 }
486
487 static DBusHandlerResult respond_ok(DBusConnection *c, DBusMessage *m) {
488     DBusMessage *reply;
489
490     reply = dbus_message_new_method_return(m);
491     dbus_connection_send(c, reply, NULL);
492     dbus_message_unref(reply);
493     
494     return DBUS_HANDLER_RESULT_HANDLED;
495 }
496
497 static DBusHandlerResult respond_path(DBusConnection *c, DBusMessage *m, const char *path) {
498     DBusMessage *reply;
499
500     reply = dbus_message_new_method_return(m);
501     dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID);
502     dbus_connection_send(c, reply, NULL);
503     dbus_message_unref(reply);
504     
505     return DBUS_HANDLER_RESULT_HANDLED;
506 }
507
508 static void append_server_error(DBusMessage *reply) {
509     const char *t;
510
511     t = avahi_error_number_to_dbus(avahi_server_errno(avahi_server));
512     
513     dbus_message_append_args(
514         reply,
515         DBUS_TYPE_STRING, &t,
516         DBUS_TYPE_INVALID);
517 }
518
519 static char *file_get_contents(char *fname) {
520     int fd = -1;
521     struct stat st;
522     ssize_t size;
523     char *buf = NULL;
524     
525     assert(fname);
526
527     if (!(fd = open(fname, O_RDONLY))) {
528         avahi_log_error("Failed to open %s: %s", fname, strerror(errno));
529         goto fail;
530     }
531
532     if (fstat(fd, &st) < 0) {
533         avahi_log_error("stat(%s) failed: %s", fname, strerror(errno));
534         goto fail;
535     }
536
537     if (!(S_ISREG(st.st_mode))) {
538         avahi_log_error("Invalid file %s", fname);
539         goto fail;
540     }
541
542     if (st.st_size > 1024*1024) { /** 1MB */
543         avahi_log_error("File too large %s", fname);
544         goto fail;
545     }
546
547     buf = avahi_new(char, st.st_size+1);
548
549     if ((size = read(fd, buf, st.st_size)) < 0) {
550         avahi_log_error("read() failed: %s\n", strerror(errno));
551         goto fail;
552     }
553
554     buf[size] = 0;
555
556     close(fd);
557     return buf;
558     
559 fail:
560     if (fd >= 0)
561         close(fd);
562
563     if (buf)
564         avahi_free(buf);
565
566     return NULL;
567         
568 }
569
570 static const char *map_browse_signal_name(AvahiBrowserEvent e) {
571     switch (e) {
572         case AVAHI_BROWSER_NEW : return "ItemNew";
573         case AVAHI_BROWSER_REMOVE : return "ItemRemove";
574         case AVAHI_BROWSER_FAILURE : return "Failure";
575         case AVAHI_BROWSER_CACHE_EXHAUSTED : return "CacheExhausted";
576         case AVAHI_BROWSER_ALL_FOR_NOW : return "AllForNow";
577     }
578
579     abort();
580 }
581
582 static const char *map_resolve_signal_name(AvahiResolverEvent e) {
583     switch (e) {
584         case AVAHI_RESOLVER_FOUND : return "Found";
585         case AVAHI_RESOLVER_FAILURE : return "Failure";
586     }
587
588     abort();
589 }
590
591
592 static DBusHandlerResult handle_introspect(DBusConnection *c, DBusMessage *m, const char *fname) {
593     char *path, *contents;
594     DBusError error;
595     
596     assert(c);
597     assert(m);
598     assert(fname);
599
600     dbus_error_init(&error);
601
602     if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
603         avahi_log_error("Error parsing Introspect message: %s", error.message);
604         goto fail;
605     }
606     
607     path = avahi_strdup_printf("%s/%s", AVAHI_DBUS_INTROSPECTION_DIR, fname);
608     contents = file_get_contents(path);
609     avahi_free(path);
610     
611     if (!contents) {
612         avahi_log_error("Failed to load introspection data.");
613         goto fail;
614     }
615     
616     respond_string(c, m, contents);
617     avahi_free(contents);
618     
619     return DBUS_HANDLER_RESULT_HANDLED;
620
621 fail:
622     if (dbus_error_is_set(&error))
623         dbus_error_free(&error);
624     
625     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
626
627 }
628
629 static DBusHandlerResult msg_signal_filter_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
630     DBusError error;
631
632     dbus_error_init(&error);
633
634 /*     avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s", */
635 /*                     dbus_message_get_interface(m), */
636 /*                     dbus_message_get_path(m), */
637 /*                     dbus_message_get_member(m)); */
638
639     if (dbus_message_is_signal(m, DBUS_INTERFACE_LOCAL, "Disconnected")) {
640         /* No, we shouldn't quit, but until we get somewhere
641          * usefull such that we can restore our state, we will */
642         avahi_log_warn("Disconnnected from D-BUS, terminating...");
643         
644         raise(SIGQUIT); /* The signal handler will catch this and terminate the process cleanly*/
645         
646         return DBUS_HANDLER_RESULT_HANDLED;
647         
648     } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameAcquired")) {
649         char *name;
650
651         if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)) {
652             avahi_log_warn("Error parsing NameAcquired message");
653             goto fail;
654         }
655
656 /*         avahi_log_info(__FILE__": name acquired (%s)", name); */
657         return DBUS_HANDLER_RESULT_HANDLED;
658         
659     } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
660         char *name, *old, *new;
661
662         if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &old, DBUS_TYPE_STRING, &new, DBUS_TYPE_INVALID)) {
663             avahi_log_warn("Error parsing NameOwnerChanged message");
664             goto fail;
665         }
666
667         if (!*new) {
668             Client *client;
669
670             if ((client = client_get(name, FALSE))) {
671                 avahi_log_debug(__FILE__": client %s vanished.", name); 
672                 client_free(client);
673             }
674         }
675     }
676
677 fail:
678     if (dbus_error_is_set(&error))
679         dbus_error_free(&error);
680     
681     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
682 }
683
684 static void entry_group_callback(AvahiServer *s, AvahiSEntryGroup *g, AvahiEntryGroupState state, void* userdata) {
685     EntryGroupInfo *i = userdata;
686     DBusMessage *m;
687     int32_t t;
688     
689     assert(s);
690     assert(g);
691     assert(i);
692
693     m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "StateChanged");
694     t = (int32_t) state;
695     dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
696     dbus_message_set_destination(m, i->client->name);  
697     dbus_connection_send(server->bus, m, NULL);
698     dbus_message_unref(m);
699 }
700
701 static int read_strlst(DBusMessage *m, int idx, AvahiStringList **l) {
702     DBusMessageIter iter, sub;
703     int j;
704     AvahiStringList *strlst = NULL;
705
706     assert(m);
707     assert(l);
708     
709     dbus_message_iter_init(m, &iter);
710
711     for (j = 0; j < idx; j++)
712         dbus_message_iter_next(&iter);
713     
714     if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
715         dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_ARRAY)
716         goto fail;
717
718     dbus_message_iter_recurse(&iter, &sub);
719         
720     for (;;) {
721         DBusMessageIter sub2;
722         int at, n;
723         uint8_t *k;
724         
725         if ((at = dbus_message_iter_get_arg_type(&sub)) == DBUS_TYPE_INVALID)
726             break;
727         
728         assert(at == DBUS_TYPE_ARRAY);
729         
730         if (dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_BYTE)
731             goto fail;
732
733         dbus_message_iter_recurse(&sub, &sub2);
734         dbus_message_iter_get_fixed_array(&sub2, &k, &n);
735         strlst = avahi_string_list_add_arbitrary(strlst, k, n);
736         
737         dbus_message_iter_next(&sub);
738     }
739
740     *l = strlst;
741     
742     return 0;
743     
744 fail:
745     avahi_log_warn("Error parsing TXT data");
746
747     avahi_string_list_free(strlst);
748     *l = NULL;
749     return -1;
750 }
751
752
753 static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
754     DBusError error;
755     EntryGroupInfo *i = userdata;
756
757     assert(c);
758     assert(m);
759     assert(i);
760     
761     dbus_error_init(&error);
762
763     avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
764                     dbus_message_get_interface(m),
765                     dbus_message_get_path(m),
766                     dbus_message_get_member(m));
767
768     /* Introspection */
769     if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
770         return handle_introspect(c, m, "EntryGroup.introspect");
771     
772     /* Access control */
773     if (strcmp(dbus_message_get_sender(m), i->client->name)) 
774         return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
775     
776     if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Free")) {
777
778         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
779             avahi_log_warn("Error parsing EntryGroup::Free message");
780             goto fail;
781         }
782
783         entry_group_free(i);
784         return respond_ok(c, m);
785         
786     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Commit")) {
787
788         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
789             avahi_log_warn("Error parsing EntryGroup::Commit message");
790             goto fail;
791         }
792
793         avahi_s_entry_group_commit(i->entry_group);
794         return respond_ok(c, m);
795         
796         
797     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Reset")) {
798         
799         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
800             avahi_log_warn("Error parsing EntryGroup::Reset message");
801             goto fail;
802         }
803
804         avahi_s_entry_group_reset(i->entry_group);
805         i->n_entries = 0;
806         return respond_ok(c, m);
807         
808     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "IsEmpty")) {
809
810         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
811             avahi_log_warn("Error parsing EntryGroup::IsEmpty message");
812             goto fail;
813         }
814
815         return respond_boolean(c, m, !!avahi_s_entry_group_is_empty(i->entry_group));
816         
817     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "GetState")) {
818         AvahiEntryGroupState state;
819         
820         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
821             avahi_log_warn("Error parsing EntryGroup::GetState message");
822             goto fail;
823         }
824
825         state = avahi_s_entry_group_get_state(i->entry_group);
826         return respond_int32(c, m, (int32_t) state);
827         
828     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddService")) {
829         int32_t interface, protocol;
830         uint32_t flags;
831         char *type, *name, *domain, *host;
832         uint16_t port;
833         AvahiStringList *strlst = NULL;
834         
835         if (!dbus_message_get_args(
836                 m, &error,
837                 DBUS_TYPE_INT32, &interface,
838                 DBUS_TYPE_INT32, &protocol,
839                 DBUS_TYPE_UINT32, &flags,
840                 DBUS_TYPE_STRING, &name,
841                 DBUS_TYPE_STRING, &type,
842                 DBUS_TYPE_STRING, &domain,
843                 DBUS_TYPE_STRING, &host,
844                 DBUS_TYPE_UINT16, &port, 
845                 DBUS_TYPE_INVALID) ||
846             !type || !name ||
847             read_strlst(m, 8, &strlst) < 0) {
848             avahi_log_warn("Error parsing EntryGroup::AddService message");
849             goto fail;
850         }
851
852         if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
853             avahi_string_list_free(strlst);
854             return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
855         }
856
857         if (domain && !*domain)
858             domain = NULL;
859
860         if (host && !*host)
861             host = NULL;
862
863         if (avahi_server_add_service_strlst(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, host, port, strlst) < 0) {
864             avahi_string_list_free(strlst);
865             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
866         }
867
868         if (!(flags & AVAHI_PUBLISH_UPDATE))
869             i->n_entries ++;
870             
871         avahi_string_list_free(strlst);
872         
873         return respond_ok(c, m);
874         
875     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddServiceSubtype")) {
876
877         int32_t interface, protocol;
878         uint32_t flags;
879         char *type, *name, *domain, *subtype;
880         
881         if (!dbus_message_get_args(
882                 m, &error,
883                 DBUS_TYPE_INT32, &interface,
884                 DBUS_TYPE_INT32, &protocol,
885                 DBUS_TYPE_UINT32, &flags,
886                 DBUS_TYPE_STRING, &name,
887                 DBUS_TYPE_STRING, &type,
888                 DBUS_TYPE_STRING, &domain,
889                 DBUS_TYPE_STRING, &subtype,
890                 DBUS_TYPE_INVALID) || !type || !name || !subtype) {
891             avahi_log_warn("Error parsing EntryGroup::AddServiceSubtype message");
892             goto fail;
893         }
894
895         if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP)
896             return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
897
898         if (domain && !*domain)
899             domain = NULL;
900
901         if (avahi_server_add_service_subtype(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, subtype) < 0) 
902             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
903
904         if (!(flags & AVAHI_PUBLISH_UPDATE))
905             i->n_entries ++;
906         
907         return respond_ok(c, m);
908
909     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "UpdateServiceTxt")) {
910         int32_t interface, protocol;
911         uint32_t flags;
912         char *type, *name, *domain;
913         AvahiStringList *strlst;
914         
915         if (!dbus_message_get_args(
916                 m, &error,
917                 DBUS_TYPE_INT32, &interface,
918                 DBUS_TYPE_INT32, &protocol,
919                 DBUS_TYPE_UINT32, &flags,
920                 DBUS_TYPE_STRING, &name,
921                 DBUS_TYPE_STRING, &type,
922                 DBUS_TYPE_STRING, &domain,
923                 DBUS_TYPE_INVALID) ||
924             !type || !name ||
925             read_strlst(m, 6, &strlst)) {
926             avahi_log_warn("Error parsing EntryGroup::UpdateServiceTxt message");
927             goto fail;
928         }
929
930         if (domain && !*domain)
931             domain = NULL;
932
933         if (avahi_server_update_service_txt_strlst(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, strlst) < 0) {
934             avahi_string_list_free(strlst);
935             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
936         }
937
938         avahi_string_list_free(strlst);
939         
940         return respond_ok(c, m);
941         
942     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddAddress")) {
943         int32_t interface, protocol;
944         uint32_t flags;
945         char *name, *address;
946         AvahiAddress a;
947         
948         if (!dbus_message_get_args(
949                 m, &error,
950                 DBUS_TYPE_INT32, &interface,
951                 DBUS_TYPE_INT32, &protocol,
952                 DBUS_TYPE_UINT32, &flags,
953                 DBUS_TYPE_STRING, &name,
954                 DBUS_TYPE_STRING, &address,
955                 DBUS_TYPE_INVALID) || !name || !address) {
956             avahi_log_warn("Error parsing EntryGroup::AddAddress message");
957             goto fail;
958         }
959
960         if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP)
961             return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
962         
963         if (!(avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a)))
964             return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
965
966         if (avahi_server_add_address(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, &a) < 0)
967             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
968
969         if (!(flags & AVAHI_PUBLISH_UPDATE))
970             i->n_entries ++;
971         
972         return respond_ok(c, m);
973     } 
974     
975     avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
976
977 fail:
978     if (dbus_error_is_set(&error))
979         dbus_error_free(&error);
980     
981     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
982 }
983
984 static void sync_host_name_resolver_callback(AvahiSHostNameResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const char *host_name, const AvahiAddress *a, AvahiLookupResultFlags flags, void* userdata) {
985     SyncHostNameResolverInfo *i = userdata;
986     
987     assert(r);
988     assert(host_name);
989     assert(i);
990
991     if (event == AVAHI_RESOLVER_FOUND) {
992         char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
993         int32_t i_interface, i_protocol, i_aprotocol;
994         uint32_t u_flags;
995         DBusMessage *reply;
996
997         assert(a);
998         avahi_address_snprint(t, sizeof(t), a);
999
1000         i_interface = (int32_t) interface;
1001         i_protocol = (int32_t) protocol;
1002         i_aprotocol = (int32_t) a->proto;
1003         u_flags = (uint32_t) flags;
1004         
1005         reply = dbus_message_new_method_return(i->message);
1006         dbus_message_append_args(
1007             reply,
1008             DBUS_TYPE_INT32, &i_interface,
1009             DBUS_TYPE_INT32, &i_protocol,
1010             DBUS_TYPE_STRING, &host_name,
1011             DBUS_TYPE_INT32, &i_aprotocol,
1012             DBUS_TYPE_STRING, &pt,
1013             DBUS_TYPE_UINT32, &u_flags,
1014             DBUS_TYPE_INVALID);
1015
1016         dbus_connection_send(server->bus, reply, NULL);
1017         dbus_message_unref(reply);
1018     } else {
1019         assert(event == AVAHI_RESOLVER_FAILURE);
1020         respond_error(server->bus, i->message, avahi_server_errno(avahi_server), NULL);
1021     }
1022
1023     sync_host_name_resolver_free(i);
1024 }
1025
1026 static void sync_address_resolver_callback(AvahiSAddressResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const AvahiAddress *address, const char *host_name, AvahiLookupResultFlags flags, void* userdata) {
1027     SyncAddressResolverInfo *i = userdata;
1028     
1029     assert(r);
1030     assert(address);
1031     assert(i);
1032
1033     if (event == AVAHI_RESOLVER_FOUND) {
1034         char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1035         int32_t i_interface, i_protocol, i_aprotocol;
1036         uint32_t u_flags;
1037         DBusMessage *reply;
1038
1039         assert(host_name);
1040         avahi_address_snprint(t, sizeof(t), address);
1041
1042         i_interface = (int32_t) interface;
1043         i_protocol = (int32_t) protocol;
1044         i_aprotocol = (int32_t) address->proto;
1045         u_flags = (uint32_t) flags;
1046         
1047         reply = dbus_message_new_method_return(i->message);
1048         dbus_message_append_args(
1049             reply,
1050             DBUS_TYPE_INT32, &i_interface,
1051             DBUS_TYPE_INT32, &i_protocol,
1052             DBUS_TYPE_INT32, &i_aprotocol,
1053             DBUS_TYPE_STRING, &pt,
1054             DBUS_TYPE_STRING, &host_name,
1055             DBUS_TYPE_UINT32, &u_flags,
1056             DBUS_TYPE_INVALID);
1057
1058         dbus_connection_send(server->bus, reply, NULL);
1059         dbus_message_unref(reply);
1060     } else {
1061         assert(event == AVAHI_RESOLVER_FAILURE);
1062         respond_error(server->bus, i->message, avahi_server_errno(avahi_server), NULL);
1063     }
1064
1065     sync_address_resolver_free(i);
1066 }
1067
1068 static DBusHandlerResult msg_domain_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1069     DBusError error;
1070     DomainBrowserInfo *i = userdata;
1071
1072     assert(c);
1073     assert(m);
1074     assert(i);
1075     
1076     dbus_error_init(&error);
1077
1078     avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1079                     dbus_message_get_interface(m),
1080                     dbus_message_get_path(m),
1081                     dbus_message_get_member(m));
1082
1083     /* Introspection */
1084     if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1085         return handle_introspect(c, m, "DomainBrowser.introspect");
1086     
1087     /* Access control */
1088     if (strcmp(dbus_message_get_sender(m), i->client->name)) 
1089         return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1090     
1091     if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, "Free")) {
1092
1093         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1094             avahi_log_warn("Error parsing DomainBrowser::Free message");
1095             goto fail;
1096         }
1097
1098         domain_browser_free(i);
1099         return respond_ok(c, m);
1100         
1101     }
1102     
1103     avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1104
1105 fail:
1106     if (dbus_error_is_set(&error))
1107         dbus_error_free(&error);
1108     
1109     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1110 }
1111
1112 static void domain_browser_callback(AvahiSDomainBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *domain, AvahiLookupResultFlags flags,  void* userdata) {
1113     DomainBrowserInfo *i = userdata;
1114     DBusMessage *m;
1115     int32_t i_interface, i_protocol;
1116     uint32_t u_flags;
1117     
1118     assert(b);
1119     assert(i);
1120
1121     i_interface = (int32_t) interface;
1122     i_protocol = (int32_t) protocol;
1123     u_flags = (uint32_t) flags;
1124
1125     m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, map_browse_signal_name(event));
1126
1127     if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1128         assert(domain);
1129         dbus_message_append_args(
1130             m,
1131             DBUS_TYPE_INT32, &i_interface,
1132             DBUS_TYPE_INT32, &i_protocol,
1133             DBUS_TYPE_STRING, &domain,
1134             DBUS_TYPE_UINT32, &u_flags,
1135             DBUS_TYPE_INVALID);
1136     } else if (event == AVAHI_BROWSER_FAILURE)
1137         append_server_error(m);
1138     
1139     dbus_message_set_destination(m, i->client->name);   
1140     dbus_connection_send(server->bus, m, NULL);
1141     dbus_message_unref(m);
1142 }
1143
1144 static DBusHandlerResult msg_service_type_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1145     DBusError error;
1146     ServiceTypeBrowserInfo *i = userdata;
1147
1148     assert(c);
1149     assert(m);
1150     assert(i);
1151     
1152     dbus_error_init(&error);
1153
1154     avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1155                     dbus_message_get_interface(m),
1156                     dbus_message_get_path(m),
1157                     dbus_message_get_member(m));
1158
1159     /* Introspection */
1160     if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1161         return handle_introspect(c, m, "ServiceTypeBrowser.introspect");
1162     
1163     /* Access control */
1164     if (strcmp(dbus_message_get_sender(m), i->client->name)) 
1165         return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1166     
1167     if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, "Free")) {
1168
1169         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1170             avahi_log_warn("Error parsing ServiceTypeBrowser::Free message");
1171             goto fail;
1172         }
1173
1174         service_type_browser_free(i);
1175         return respond_ok(c, m);
1176         
1177     }
1178     
1179     avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1180
1181 fail:
1182     if (dbus_error_is_set(&error))
1183         dbus_error_free(&error);
1184     
1185     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1186 }
1187
1188 static void service_type_browser_callback(AvahiSServiceTypeBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *type, const char *domain, AvahiLookupResultFlags flags, void* userdata) {
1189     ServiceTypeBrowserInfo *i = userdata;
1190     DBusMessage *m;
1191     int32_t i_interface, i_protocol;
1192     uint32_t u_flags;
1193     
1194     assert(b);
1195     assert(i);
1196
1197     i_interface = (int32_t) interface;
1198     i_protocol = (int32_t) protocol;
1199     u_flags = (uint32_t) flags;
1200
1201     m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, map_browse_signal_name(event));
1202
1203     if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1204         assert(type);
1205         assert(domain);
1206         dbus_message_append_args(
1207             m,
1208             DBUS_TYPE_INT32, &i_interface,
1209             DBUS_TYPE_INT32, &i_protocol,
1210             DBUS_TYPE_STRING, &type,
1211             DBUS_TYPE_STRING, &domain,
1212             DBUS_TYPE_UINT32, &u_flags,
1213             DBUS_TYPE_INVALID);
1214     } else if (event == AVAHI_BROWSER_FAILURE)
1215         append_server_error(m);
1216         
1217     dbus_message_set_destination(m, i->client->name);   
1218     dbus_connection_send(server->bus, m, NULL);
1219     dbus_message_unref(m);
1220 }
1221
1222 static DBusHandlerResult msg_service_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1223     DBusError error;
1224     ServiceBrowserInfo *i = userdata;
1225
1226     assert(c);
1227     assert(m);
1228     assert(i);
1229     
1230     dbus_error_init(&error);
1231
1232     avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1233                     dbus_message_get_interface(m),
1234                     dbus_message_get_path(m),
1235                     dbus_message_get_member(m));
1236
1237     /* Introspection */
1238     if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1239         return handle_introspect(c, m, "ServiceBrowser.Introspect");
1240     
1241     /* Access control */
1242     if (strcmp(dbus_message_get_sender(m), i->client->name)) 
1243         return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1244     
1245     if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, "Free")) {
1246
1247         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1248             avahi_log_warn("Error parsing ServiceBrowser::Free message");
1249             goto fail;
1250         }
1251
1252         service_browser_free(i);
1253         return respond_ok(c, m);
1254         
1255     }
1256     
1257     avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1258
1259 fail:
1260     if (dbus_error_is_set(&error))
1261         dbus_error_free(&error);
1262     
1263     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1264 }
1265
1266 static int is_our_own_service(Client *c, AvahiIfIndex interface, AvahiProtocol protocol, const char *name, const char *type, const char *domain) {
1267     AvahiSEntryGroup *g;
1268         
1269
1270     if (avahi_server_get_group_of_service(avahi_server, interface, protocol, name, type, domain, &g) == AVAHI_OK) {
1271         EntryGroupInfo *egi;
1272
1273         for (egi = c->entry_groups; egi; egi = egi->entry_groups_next)
1274             if (egi->entry_group == g)
1275                 return 1;
1276     }
1277
1278     return 0;
1279 }
1280
1281 static void service_browser_callback(AvahiSServiceBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AvahiLookupResultFlags flags, void* userdata) {
1282     ServiceBrowserInfo *i = userdata;
1283     DBusMessage *m;
1284     int32_t i_interface, i_protocol;
1285     uint32_t u_flags;
1286     
1287     assert(b);
1288     assert(i);
1289
1290     i_interface = (int32_t) interface;
1291     i_protocol = (int32_t) protocol;
1292     u_flags = (uint32_t) flags;
1293
1294     m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, map_browse_signal_name(event));
1295
1296     if (event == AVAHI_BROWSER_NEW) {
1297         /* Patch in AVAHI_LOOKUP_RESULT_OUR_OWN */
1298
1299         if (is_our_own_service(i->client, interface, protocol, name, type, domain) > 0)
1300             flags |= AVAHI_LOOKUP_RESULT_OUR_OWN;
1301     }
1302     
1303     if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1304         assert(name);
1305         assert(type);
1306         assert(domain);
1307         
1308         dbus_message_append_args(
1309             m,
1310             DBUS_TYPE_INT32, &i_interface,
1311             DBUS_TYPE_INT32, &i_protocol,
1312             DBUS_TYPE_STRING, &name,
1313             DBUS_TYPE_STRING, &type,
1314             DBUS_TYPE_STRING, &domain,
1315             DBUS_TYPE_UINT32, &u_flags,
1316             DBUS_TYPE_INVALID);
1317     } else if (event == AVAHI_BROWSER_FAILURE)
1318         append_server_error(m);
1319     
1320     dbus_message_set_destination(m, i->client->name);   
1321     dbus_connection_send(server->bus, m, NULL);
1322     dbus_message_unref(m);
1323 }
1324
1325 static void append_string_list(DBusMessage *reply, AvahiStringList *txt) {
1326     AvahiStringList *p;
1327     DBusMessageIter iter, sub;
1328     
1329     assert(reply);
1330
1331     dbus_message_iter_init_append(reply, &iter);
1332     dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "ay", &sub);
1333     
1334     for (p = txt; p; p = p->next) {
1335         DBusMessageIter sub2;
1336         const uint8_t *data = p->text;
1337         
1338         dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "y", &sub2);
1339         dbus_message_iter_append_fixed_array(&sub2, DBUS_TYPE_BYTE, &data, p->size); 
1340         dbus_message_iter_close_container(&sub, &sub2);
1341         
1342     }
1343     dbus_message_iter_close_container(&iter, &sub);
1344 }
1345
1346 static void sync_service_resolver_callback(
1347     AvahiSServiceResolver *r,
1348     AvahiIfIndex interface,
1349     AvahiProtocol protocol,
1350     AvahiResolverEvent event,
1351     const char *name,
1352     const char *type,
1353     const char *domain,
1354     const char *host_name,
1355     const AvahiAddress *a,
1356     uint16_t port,
1357     AvahiStringList *txt,
1358     AvahiLookupResultFlags flags, 
1359     void* userdata) {
1360     
1361     SyncServiceResolverInfo *i = userdata;
1362     
1363     assert(r);
1364     assert(i);
1365
1366     if (event == AVAHI_RESOLVER_FOUND) {
1367         char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1368         int32_t i_interface, i_protocol, i_aprotocol;
1369         uint32_t u_flags;
1370         DBusMessage *reply;
1371     
1372         assert(host_name);
1373
1374         if (!name)
1375             name = "";
1376
1377         if (a) 
1378             avahi_address_snprint(t, sizeof(t), a);
1379         else
1380             t[0] = 0;
1381
1382         /* Patch in AVAHI_LOOKUP_RESULT_OUR_OWN */
1383
1384         if (is_our_own_service(i->client, interface, protocol, name, type, domain) > 0)
1385             flags |= AVAHI_LOOKUP_RESULT_OUR_OWN;
1386         
1387         i_interface = (int32_t) interface;
1388         i_protocol = (int32_t) protocol;
1389         if (a) 
1390             i_aprotocol = (int32_t) a->proto;
1391         else 
1392             i_aprotocol = AVAHI_PROTO_UNSPEC;
1393         u_flags = (uint32_t) flags;
1394
1395         reply = dbus_message_new_method_return(i->message);
1396         dbus_message_append_args(
1397             reply,
1398             DBUS_TYPE_INT32, &i_interface,
1399             DBUS_TYPE_INT32, &i_protocol,
1400             DBUS_TYPE_STRING, &name,
1401             DBUS_TYPE_STRING, &type,
1402             DBUS_TYPE_STRING, &domain,
1403             DBUS_TYPE_STRING, &host_name,
1404             DBUS_TYPE_INT32, &i_aprotocol,
1405             DBUS_TYPE_STRING, &pt,
1406             DBUS_TYPE_UINT16, &port,
1407             DBUS_TYPE_INVALID);
1408
1409         append_string_list(reply, txt);
1410                 
1411         dbus_message_append_args(
1412             reply,
1413             DBUS_TYPE_UINT32, &u_flags,
1414             DBUS_TYPE_INVALID);
1415
1416         dbus_connection_send(server->bus, reply, NULL);
1417         dbus_message_unref(reply);
1418     } else {
1419         assert(event == AVAHI_RESOLVER_FAILURE);
1420         
1421         respond_error(server->bus, i->message, avahi_server_errno(avahi_server), NULL);
1422     }
1423
1424     sync_service_resolver_free(i);
1425 }
1426
1427 static void async_address_resolver_callback(AvahiSAddressResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const AvahiAddress *address, const char *host_name, AvahiLookupResultFlags flags, void* userdata) {
1428     AsyncAddressResolverInfo *i = userdata;
1429     DBusMessage *reply;
1430     
1431     assert(r);
1432     assert(i);
1433
1434     reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, map_resolve_signal_name(event));
1435     
1436     if (event == AVAHI_RESOLVER_FOUND) {
1437         char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1438         int32_t i_interface, i_protocol, i_aprotocol;
1439         uint32_t u_flags;
1440
1441         assert(address);
1442         assert(host_name);
1443         avahi_address_snprint(t, sizeof(t), address);
1444
1445         i_interface = (int32_t) interface;
1446         i_protocol = (int32_t) protocol;
1447         i_aprotocol = (int32_t) address->proto;
1448         u_flags = (uint32_t) flags;
1449         
1450         dbus_message_append_args(
1451             reply,
1452             DBUS_TYPE_INT32, &i_interface,
1453             DBUS_TYPE_INT32, &i_protocol,
1454             DBUS_TYPE_INT32, &i_aprotocol,
1455             DBUS_TYPE_STRING, &pt,
1456             DBUS_TYPE_STRING, &host_name,
1457             DBUS_TYPE_UINT32, &u_flags,
1458             DBUS_TYPE_INVALID);
1459
1460     }  else {
1461         assert(event == AVAHI_RESOLVER_FAILURE);
1462         append_server_error(reply);
1463     }
1464
1465     dbus_message_set_destination(reply, i->client->name);  
1466     dbus_connection_send(server->bus, reply, NULL);
1467     dbus_message_unref(reply);
1468 }
1469
1470 static DBusHandlerResult msg_async_address_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1471     DBusError error;
1472     AsyncAddressResolverInfo *i = userdata;
1473
1474     assert(c);
1475     assert(m);
1476     assert(i);
1477     
1478     dbus_error_init(&error);
1479
1480     avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1481                     dbus_message_get_interface(m),
1482                     dbus_message_get_path(m),
1483                     dbus_message_get_member(m));
1484
1485     /* Introspection */
1486     if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1487         return handle_introspect(c, m, "AddressResolver.Introspect");
1488     
1489     /* Access control */
1490     if (strcmp(dbus_message_get_sender(m), i->client->name)) 
1491         return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1492     
1493     if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, "Free")) {
1494
1495         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1496             avahi_log_warn("Error parsing AddressResolver::Free message");
1497             goto fail;
1498         }
1499
1500         async_address_resolver_free(i);
1501         return respond_ok(c, m);
1502         
1503     }
1504     
1505     avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1506
1507 fail:
1508     if (dbus_error_is_set(&error))
1509         dbus_error_free(&error);
1510     
1511     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1512 }
1513
1514 static void async_host_name_resolver_callback(AvahiSHostNameResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const char *host_name, const AvahiAddress *a, AvahiLookupResultFlags flags, void* userdata) {
1515     AsyncHostNameResolverInfo *i = userdata;
1516     DBusMessage *reply;
1517     
1518     assert(r);
1519     assert(i);
1520
1521     reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_HOST_NAME_RESOLVER, map_resolve_signal_name(event));
1522     
1523     if (event == AVAHI_RESOLVER_FOUND) {
1524         char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1525         int32_t i_interface, i_protocol, i_aprotocol;
1526         uint32_t u_flags;
1527
1528         assert(a);
1529         assert(host_name);
1530         avahi_address_snprint(t, sizeof(t), a);
1531
1532         i_interface = (int32_t) interface;
1533         i_protocol = (int32_t) protocol;
1534         i_aprotocol = (int32_t) a->proto;
1535         u_flags = (uint32_t) flags;
1536         
1537         dbus_message_append_args(
1538             reply,
1539             DBUS_TYPE_INT32, &i_interface,
1540             DBUS_TYPE_INT32, &i_protocol,
1541             DBUS_TYPE_STRING, &host_name,
1542             DBUS_TYPE_INT32, &i_aprotocol,
1543             DBUS_TYPE_STRING, &pt,
1544             DBUS_TYPE_UINT32, &u_flags,
1545             DBUS_TYPE_INVALID);
1546     }  else {
1547         assert(event == AVAHI_RESOLVER_FAILURE);
1548         append_server_error(reply);
1549     }
1550
1551     dbus_message_set_destination(reply, i->client->name);  
1552     dbus_connection_send(server->bus, reply, NULL);
1553     dbus_message_unref(reply);
1554 }
1555
1556 static DBusHandlerResult msg_async_host_name_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1557     DBusError error;
1558     AsyncHostNameResolverInfo *i = userdata;
1559
1560     assert(c);
1561     assert(m);
1562     assert(i);
1563     
1564     dbus_error_init(&error);
1565
1566     avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1567                     dbus_message_get_interface(m),
1568                     dbus_message_get_path(m),
1569                     dbus_message_get_member(m));
1570
1571     /* Introspection */
1572     if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1573         return handle_introspect(c, m, "HostNameResolver.Introspect");
1574     
1575     /* Access control */
1576     if (strcmp(dbus_message_get_sender(m), i->client->name)) 
1577         return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1578     
1579     if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_HOST_NAME_RESOLVER, "Free")) {
1580
1581         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1582             avahi_log_warn("Error parsing HostNameResolver::Free message");
1583             goto fail;
1584         }
1585
1586         async_host_name_resolver_free(i);
1587         return respond_ok(c, m);
1588     }
1589     
1590     avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1591
1592 fail:
1593     if (dbus_error_is_set(&error))
1594         dbus_error_free(&error);
1595     
1596     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1597 }
1598
1599 static void async_service_resolver_callback(
1600     AvahiSServiceResolver *r,
1601     AvahiIfIndex interface,
1602     AvahiProtocol protocol,
1603     AvahiResolverEvent event,
1604     const char *name,
1605     const char *type,
1606     const char *domain,
1607     const char *host_name,
1608     const AvahiAddress *a,
1609     uint16_t port,
1610     AvahiStringList *txt,
1611     AvahiLookupResultFlags flags, 
1612     void* userdata) {
1613
1614     AsyncServiceResolverInfo *i = userdata;
1615     DBusMessage *reply;
1616     
1617     assert(r);
1618     assert(i);
1619
1620     reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_RESOLVER, map_resolve_signal_name(event));
1621     
1622     if (event == AVAHI_RESOLVER_FOUND) {
1623         char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1624         int32_t i_interface, i_protocol, i_aprotocol;
1625         uint32_t u_flags;
1626     
1627         assert(host_name);
1628
1629 /*         avahi_log_debug(__FILE__": [%s] Successfully resolved service <%s.%s.%s>", i->path, name, type, domain); */
1630         
1631         if (a)
1632             avahi_address_snprint(t, sizeof(t), a);
1633         else
1634             t[0] = 0;
1635
1636         if (!name)
1637             name = "";
1638
1639         if (is_our_own_service(i->client, interface, protocol, name, type, domain) > 0)
1640             flags |= AVAHI_LOOKUP_RESULT_OUR_OWN;
1641
1642         i_interface = (int32_t) interface;
1643         i_protocol = (int32_t) protocol;
1644         if (a) 
1645             i_aprotocol = (int32_t) a->proto;
1646         else 
1647             i_aprotocol = AVAHI_PROTO_UNSPEC;
1648         u_flags = (uint32_t) flags;
1649
1650         dbus_message_append_args(
1651             reply,
1652             DBUS_TYPE_INT32, &i_interface,
1653             DBUS_TYPE_INT32, &i_protocol,
1654             DBUS_TYPE_STRING, &name,
1655             DBUS_TYPE_STRING, &type,
1656             DBUS_TYPE_STRING, &domain,
1657             DBUS_TYPE_STRING, &host_name,
1658             DBUS_TYPE_INT32, &i_aprotocol,
1659             DBUS_TYPE_STRING, &pt,
1660             DBUS_TYPE_UINT16, &port,
1661             DBUS_TYPE_INVALID);
1662
1663         append_string_list(reply, txt);
1664
1665         dbus_message_append_args(
1666             reply,
1667             DBUS_TYPE_UINT32, &u_flags,
1668             DBUS_TYPE_INVALID);
1669     }  else {
1670         assert(event == AVAHI_RESOLVER_FAILURE);
1671         append_server_error(reply);
1672     }
1673
1674     dbus_message_set_destination(reply, i->client->name);  
1675     dbus_connection_send(server->bus, reply, NULL);
1676     dbus_message_unref(reply);
1677 }
1678
1679 static DBusHandlerResult msg_async_service_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1680     DBusError error;
1681     AsyncServiceResolverInfo *i = userdata;
1682
1683     assert(c);
1684     assert(m);
1685     assert(i);
1686     
1687     dbus_error_init(&error);
1688
1689     avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1690                     dbus_message_get_interface(m),
1691                     dbus_message_get_path(m),
1692                     dbus_message_get_member(m));
1693
1694     /* Introspection */
1695     if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1696         return handle_introspect(c, m, "ServiceResolver.Introspect");
1697     
1698     /* Access control */
1699     if (strcmp(dbus_message_get_sender(m), i->client->name)) 
1700         return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1701     
1702     if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_RESOLVER, "Free")) {
1703
1704         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1705             avahi_log_warn("Error parsing ServiceResolver::Free message");
1706             goto fail;
1707         }
1708
1709         async_service_resolver_free(i);
1710         return respond_ok(c, m);
1711     }
1712     
1713     avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1714
1715 fail:
1716     if (dbus_error_is_set(&error))
1717         dbus_error_free(&error);
1718     
1719     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1720 }
1721
1722 static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1723     DBusError error;
1724
1725     dbus_error_init(&error);
1726
1727     avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1728                     dbus_message_get_interface(m),
1729                     dbus_message_get_path(m),
1730                     dbus_message_get_member(m));
1731
1732     if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1733         return handle_introspect(c, m, "Server.introspect");
1734         
1735     else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostName")) {
1736
1737         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1738             avahi_log_warn("Error parsing Server::GetHostName message");
1739             goto fail;
1740         }
1741
1742         return respond_string(c, m, avahi_server_get_host_name(avahi_server));
1743         
1744     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetDomainName")) {
1745
1746         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1747             avahi_log_warn("Error parsing Server::GetDomainName message");
1748             goto fail;
1749         }
1750
1751         return respond_string(c, m, avahi_server_get_domain_name(avahi_server));
1752
1753     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostNameFqdn")) {
1754
1755         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1756             avahi_log_warn("Error parsing Server::GetHostNameFqdn message");
1757             goto fail;
1758         }
1759     
1760         return respond_string(c, m, avahi_server_get_host_name_fqdn(avahi_server));
1761         
1762     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetVersionString")) {
1763
1764         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1765             avahi_log_warn("Error parsing Server::GetVersionString message");
1766             goto fail;
1767         }
1768     
1769         return respond_string(c, m, PACKAGE_STRING);
1770
1771     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetState")) {
1772         AvahiServerState state;
1773         
1774         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1775             avahi_log_warn("Error parsing Server::GetState message");
1776             goto fail;
1777         }
1778         
1779         state = avahi_server_get_state(avahi_server);
1780         return respond_int32(c, m, (int32_t) state);
1781
1782     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetLocalServiceCookie")) {
1783
1784         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1785             avahi_log_warn("Error parsing Server::GetLocalServiceCookie message");
1786             goto fail;
1787         }
1788         
1789         return respond_uint32(c, m, avahi_server_get_local_service_cookie(avahi_server));
1790
1791     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceNameByIndex")) {
1792         int32_t idx;
1793         int fd;
1794         struct ifreq ifr;
1795         
1796         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INT32, &idx, DBUS_TYPE_INVALID))) {
1797             avahi_log_warn("Error parsing Server::GetNetworkInterfaceNameByIndex message");
1798             goto fail;
1799         }
1800
1801 #ifdef VALGRIND_WORKAROUND
1802         return respond_string(c, m, "blah");
1803 #else
1804         
1805         if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 
1806             if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1807                 char txt[256];
1808                 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1809                 return respond_error(c, m, AVAHI_ERR_OS, txt);
1810             }
1811
1812         memset(&ifr, 0, sizeof(ifr));
1813
1814         ifr.ifr_ifindex = idx;
1815
1816         if (ioctl(fd, SIOCGIFNAME, &ifr) < 0) {
1817             char txt[256];
1818             snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1819             close(fd);
1820             return respond_error(c, m, AVAHI_ERR_OS, txt);
1821         }
1822
1823         close(fd);
1824         
1825         return respond_string(c, m, ifr.ifr_name);
1826 #endif
1827         
1828     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceIndexByName")) {
1829         char *n;
1830         int fd;
1831         struct ifreq ifr;
1832         
1833         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1834             avahi_log_warn("Error parsing Server::GetNetworkInterfaceIndexByName message");
1835             goto fail;
1836         }
1837
1838 #ifdef VALGRIND_WORKAROUND
1839         return respond_int32(c, m, 1);
1840 #else
1841         if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 
1842             if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1843                 char txt[256];
1844                 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1845                 return respond_error(c, m, AVAHI_ERR_OS, txt);
1846             }
1847
1848         memset(&ifr, 0, sizeof(ifr));
1849         snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", n);
1850
1851         if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
1852             char txt[256];
1853             snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1854             close(fd);
1855             return respond_error(c, m, AVAHI_ERR_OS, txt);
1856         }
1857
1858         close(fd);
1859         
1860         return respond_int32(c, m, ifr.ifr_ifindex);
1861 #endif
1862
1863     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeHostName")) {
1864         char *n, * t;
1865         
1866         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1867             avahi_log_warn("Error parsing Server::GetAlternativeHostName message");
1868             goto fail;
1869         }
1870
1871         t = avahi_alternative_host_name(n);
1872         respond_string(c, m, t);
1873         avahi_free(t);
1874
1875         return DBUS_HANDLER_RESULT_HANDLED;
1876
1877     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeServiceName")) {
1878         char *n, *t;
1879         
1880         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1881             avahi_log_warn("Error parsing Server::GetAlternativeServiceName message");
1882             goto fail;
1883         }
1884
1885         t = avahi_alternative_service_name(n);
1886         respond_string(c, m, t);
1887         avahi_free(t);
1888
1889         return DBUS_HANDLER_RESULT_HANDLED;
1890         
1891     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "EntryGroupNew")) {
1892         Client *client;
1893         EntryGroupInfo *i;
1894         static const DBusObjectPathVTable vtable = {
1895             NULL,
1896             msg_entry_group_impl,
1897             NULL,
1898             NULL,
1899             NULL,
1900             NULL
1901         };
1902
1903         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1904             avahi_log_warn("Error parsing Server::EntryGroupNew message");
1905             goto fail;
1906         }
1907
1908         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1909             avahi_log_warn("Too many clients, client request failed.");
1910             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1911         }
1912
1913         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1914             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1915             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1916         }
1917
1918         i = avahi_new(EntryGroupInfo, 1);
1919         i->id = ++client->current_id;
1920         i->client = client;
1921         i->path = avahi_strdup_printf("/Client%u/EntryGroup%u", client->id, i->id);
1922         i->n_entries = 0;
1923         AVAHI_LLIST_PREPEND(EntryGroupInfo, entry_groups, client->entry_groups, i);
1924         client->n_objects++;
1925         
1926         if (!(i->entry_group = avahi_s_entry_group_new(avahi_server, entry_group_callback, i))) {
1927             entry_group_free(i);
1928             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1929         }
1930
1931         dbus_connection_register_object_path(c, i->path, &vtable, i);
1932         return respond_path(c, m, i->path);
1933         
1934     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveHostName")) {
1935         Client *client;
1936         int32_t interface, protocol, aprotocol;
1937         uint32_t flags;
1938         char *name;
1939         SyncHostNameResolverInfo *i;
1940             
1941         if (!dbus_message_get_args(
1942                 m, &error,
1943                 DBUS_TYPE_INT32, &interface,
1944                 DBUS_TYPE_INT32, &protocol,
1945                 DBUS_TYPE_STRING, &name,
1946                 DBUS_TYPE_INT32, &aprotocol,
1947                 DBUS_TYPE_UINT32, &flags,
1948                 DBUS_TYPE_INVALID) || !name) {
1949             avahi_log_warn("Error parsing Server::ResolveHostName message");
1950             goto fail;
1951         }
1952
1953         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1954             avahi_log_warn("Too many clients, client request failed.");
1955             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1956         }
1957
1958         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1959             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1960             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1961         }
1962
1963         i = avahi_new(SyncHostNameResolverInfo, 1);
1964         i->client = client;
1965         i->message = dbus_message_ref(m);
1966         AVAHI_LLIST_PREPEND(SyncHostNameResolverInfo, sync_host_name_resolvers, client->sync_host_name_resolvers, i);
1967         client->n_objects++;
1968
1969         if (!(i->host_name_resolver = avahi_s_host_name_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, (AvahiProtocol) aprotocol, (AvahiLookupFlags) flags, sync_host_name_resolver_callback, i))) {
1970             sync_host_name_resolver_free(i);
1971             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1972         }
1973         
1974         return DBUS_HANDLER_RESULT_HANDLED;
1975         
1976     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveAddress")) {
1977         Client *client;
1978         int32_t interface, protocol;
1979         uint32_t flags;
1980         char *address;
1981         SyncAddressResolverInfo *i;
1982         AvahiAddress a;
1983             
1984         if (!dbus_message_get_args(
1985                 m, &error,
1986                 DBUS_TYPE_INT32, &interface,
1987                 DBUS_TYPE_INT32, &protocol,
1988                 DBUS_TYPE_STRING, &address,
1989                 DBUS_TYPE_UINT32, &flags, 
1990                 DBUS_TYPE_INVALID) || !address) {
1991             avahi_log_warn("Error parsing Server::ResolveAddress message");
1992             goto fail;
1993         }
1994
1995         if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
1996             return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
1997
1998         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1999             avahi_log_warn("Too many clients, client request failed.");
2000             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2001         }
2002
2003         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2004             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2005             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2006         }
2007
2008         i = avahi_new(SyncAddressResolverInfo, 1);
2009         i->client = client;
2010         i->message = dbus_message_ref(m);
2011         AVAHI_LLIST_PREPEND(SyncAddressResolverInfo, sync_address_resolvers, client->sync_address_resolvers, i);
2012         client->n_objects++;
2013
2014         if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, sync_address_resolver_callback, i))) {
2015             sync_address_resolver_free(i);
2016             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2017         }
2018         
2019         return DBUS_HANDLER_RESULT_HANDLED;
2020         
2021     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "DomainBrowserNew")) {
2022         Client *client;
2023         DomainBrowserInfo *i;
2024         static const DBusObjectPathVTable vtable = {
2025             NULL,
2026             msg_domain_browser_impl,
2027             NULL,
2028             NULL,
2029             NULL,
2030             NULL
2031         };
2032         int32_t interface, protocol, type;
2033         uint32_t flags;
2034         char *domain;
2035         
2036         if (!dbus_message_get_args(
2037                 m, &error,
2038                 DBUS_TYPE_INT32, &interface,
2039                 DBUS_TYPE_INT32, &protocol,
2040                 DBUS_TYPE_STRING, &domain,
2041                 DBUS_TYPE_INT32, &type,
2042                 DBUS_TYPE_UINT32, &flags,
2043                 DBUS_TYPE_INVALID) || type < 0 || type >= AVAHI_DOMAIN_BROWSER_MAX) {
2044             avahi_log_warn("Error parsing Server::DomainBrowserNew message");
2045             goto fail;
2046         }
2047
2048         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2049             avahi_log_warn("Too many clients, client request failed.");
2050             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2051         }
2052
2053         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2054             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2055             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2056         }
2057
2058         if (!*domain)
2059             domain = NULL;
2060
2061         i = avahi_new(DomainBrowserInfo, 1);
2062         i->id = ++client->current_id;
2063         i->client = client;
2064         i->path = avahi_strdup_printf("/Client%u/DomainBrowser%u", client->id, i->id);
2065         AVAHI_LLIST_PREPEND(DomainBrowserInfo, domain_browsers, client->domain_browsers, i);
2066         client->n_objects++;
2067
2068         if (!(i->domain_browser = avahi_s_domain_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, (AvahiDomainBrowserType) type, (AvahiLookupFlags) flags, domain_browser_callback, i))) {
2069             domain_browser_free(i);
2070             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2071         }
2072         
2073         dbus_connection_register_object_path(c, i->path, &vtable, i);
2074         return respond_path(c, m, i->path);
2075
2076     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceTypeBrowserNew")) {
2077         Client *client;
2078         ServiceTypeBrowserInfo *i;
2079         static const DBusObjectPathVTable vtable = {
2080             NULL,
2081             msg_service_type_browser_impl,
2082             NULL,
2083             NULL,
2084             NULL,
2085             NULL
2086         };
2087         int32_t interface, protocol;
2088         uint32_t flags;
2089         char *domain;
2090         
2091         if (!dbus_message_get_args(
2092                 m, &error,
2093                 DBUS_TYPE_INT32, &interface,
2094                 DBUS_TYPE_INT32, &protocol,
2095                 DBUS_TYPE_STRING, &domain,
2096                 DBUS_TYPE_UINT32, &flags,
2097                 DBUS_TYPE_INVALID)) {
2098             avahi_log_warn("Error parsing Server::ServiceTypeBrowserNew message");
2099             goto fail;
2100         }
2101
2102         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2103             avahi_log_warn("Too many clients, client request failed.");
2104             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2105         }
2106
2107
2108         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2109             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2110             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2111         }
2112
2113         if (!*domain)
2114             domain = NULL;
2115
2116         i = avahi_new(ServiceTypeBrowserInfo, 1);
2117         i->id = ++client->current_id;
2118         i->client = client;
2119         i->path = avahi_strdup_printf("/Client%u/ServiceTypeBrowser%u", client->id, i->id);
2120         AVAHI_LLIST_PREPEND(ServiceTypeBrowserInfo, service_type_browsers, client->service_type_browsers, i);
2121         client->n_objects++;
2122
2123         if (!(i->service_type_browser = avahi_s_service_type_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, (AvahiLookupFlags) flags, service_type_browser_callback, i))) {
2124             service_type_browser_free(i);
2125             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2126         }
2127         
2128         dbus_connection_register_object_path(c, i->path, &vtable, i);
2129         return respond_path(c, m, i->path);
2130         
2131     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceBrowserNew")) {
2132         Client *client;
2133         ServiceBrowserInfo *i;
2134         static const DBusObjectPathVTable vtable = {
2135             NULL,
2136             msg_service_browser_impl,
2137             NULL,
2138             NULL,
2139             NULL,
2140             NULL
2141         };
2142         int32_t interface, protocol;
2143         uint32_t flags;
2144         char *domain, *type;
2145         
2146         if (!dbus_message_get_args(
2147                 m, &error,
2148                 DBUS_TYPE_INT32, &interface,
2149                 DBUS_TYPE_INT32, &protocol,
2150                 DBUS_TYPE_STRING, &type,
2151                 DBUS_TYPE_STRING, &domain,
2152                 DBUS_TYPE_UINT32, &flags,
2153                 DBUS_TYPE_INVALID) || !type) {
2154             avahi_log_warn("Error parsing Server::ServiceBrowserNew message");
2155             goto fail;
2156         }
2157
2158         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2159             avahi_log_warn("Too many clients, client request failed.");
2160             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2161         }
2162
2163
2164         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2165             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2166             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2167         }
2168
2169         if (!*domain)
2170             domain = NULL;
2171
2172         i = avahi_new(ServiceBrowserInfo, 1);
2173         i->id = ++client->current_id;
2174         i->client = client;
2175         i->path = avahi_strdup_printf("/Client%u/ServiceBrowser%u", client->id, i->id);
2176         AVAHI_LLIST_PREPEND(ServiceBrowserInfo, service_browsers, client->service_browsers, i);
2177         client->n_objects++;
2178
2179         if (!(i->service_browser = avahi_s_service_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, type, domain, (AvahiLookupFlags) flags, service_browser_callback, i))) {
2180             service_browser_free(i);
2181             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2182         }
2183         
2184         dbus_connection_register_object_path(c, i->path, &vtable, i);
2185         return respond_path(c, m, i->path);
2186         
2187     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveService")) {
2188         Client *client;
2189         int32_t interface, protocol, aprotocol;
2190         uint32_t flags;
2191         char *name, *type, *domain;
2192         SyncServiceResolverInfo *i;
2193             
2194         if (!dbus_message_get_args(
2195                 m, &error,
2196                 DBUS_TYPE_INT32, &interface,
2197                 DBUS_TYPE_INT32, &protocol,
2198                 DBUS_TYPE_STRING, &name,
2199                 DBUS_TYPE_STRING, &type,
2200                 DBUS_TYPE_STRING, &domain,
2201                 DBUS_TYPE_INT32, &aprotocol,
2202                 DBUS_TYPE_UINT32, &flags,
2203                 DBUS_TYPE_INVALID) || !type) {
2204             avahi_log_warn("Error parsing Server::ResolveService message");
2205             goto fail;
2206         }
2207
2208         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2209             avahi_log_warn("Too many clients, client request failed.");
2210             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2211         }
2212         
2213         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2214             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2215             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2216         }
2217
2218         if (!*domain)
2219             domain = NULL;
2220
2221         if (!*name)
2222             name = NULL;
2223         
2224         i = avahi_new(SyncServiceResolverInfo, 1);
2225         i->client = client;
2226         i->message = dbus_message_ref(m);
2227         AVAHI_LLIST_PREPEND(SyncServiceResolverInfo, sync_service_resolvers, client->sync_service_resolvers, i);
2228         client->n_objects++;
2229
2230         if (!(i->service_resolver = avahi_s_service_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, type, domain, (AvahiProtocol) aprotocol, (AvahiLookupFlags) flags, sync_service_resolver_callback, i))) {
2231             sync_service_resolver_free(i);
2232             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2233         }
2234         
2235         return DBUS_HANDLER_RESULT_HANDLED;
2236         
2237     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceResolverNew")) {
2238         Client *client;
2239         int32_t interface, protocol, aprotocol;
2240         uint32_t flags;
2241         char *name, *type, *domain;
2242         AsyncServiceResolverInfo *i;
2243         static const DBusObjectPathVTable vtable = {
2244             NULL,
2245             msg_async_service_resolver_impl,
2246             NULL,
2247             NULL,
2248             NULL,
2249             NULL
2250         };
2251
2252         if (!dbus_message_get_args(
2253                 m, &error,
2254                 DBUS_TYPE_INT32, &interface,
2255                 DBUS_TYPE_INT32, &protocol,
2256                 DBUS_TYPE_STRING, &name,
2257                 DBUS_TYPE_STRING, &type,
2258                 DBUS_TYPE_STRING, &domain,
2259                 DBUS_TYPE_INT32, &aprotocol,
2260                 DBUS_TYPE_UINT32, &flags,
2261                 DBUS_TYPE_INVALID) || !type) {
2262             avahi_log_warn("Error parsing Server::ServiceResolverNew message");
2263             goto fail;
2264         }
2265             
2266         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2267             avahi_log_warn(__FILE__": Too many clients, client request failed.");
2268             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2269         }
2270
2271         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2272             avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2273             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2274         }
2275
2276         if (!*domain)
2277             domain = NULL;
2278
2279         if (!*name)
2280             name = NULL;
2281         
2282         i = avahi_new(AsyncServiceResolverInfo, 1);
2283         i->id = ++client->current_id;
2284         i->client = client;
2285         i->path = avahi_strdup_printf("/Client%u/ServiceResolver%u", client->id, i->id);
2286         AVAHI_LLIST_PREPEND(AsyncServiceResolverInfo, async_service_resolvers, client->async_service_resolvers, i);
2287         client->n_objects++;
2288
2289         if (!(i->service_resolver = avahi_s_service_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, type, domain, (AvahiProtocol) aprotocol, (AvahiLookupFlags) flags, async_service_resolver_callback, i))) {
2290             async_service_resolver_free(i);
2291             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2292         }
2293
2294 /*         avahi_log_debug(__FILE__": [%s], new service resolver for <%s.%s.%s>", i->path, name, type, domain); */
2295         
2296         dbus_connection_register_object_path(c, i->path, &vtable, i);
2297         return respond_path(c, m, i->path);
2298
2299     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "HostNameResolverNew")) {
2300         Client *client;
2301         int32_t interface, protocol, aprotocol;
2302         uint32_t flags;
2303         char *name;
2304         AsyncHostNameResolverInfo *i;
2305         static const DBusObjectPathVTable vtable = {
2306             NULL,
2307             msg_async_host_name_resolver_impl,
2308             NULL,
2309             NULL,
2310             NULL,
2311             NULL
2312         };
2313             
2314         if (!dbus_message_get_args(
2315                 m, &error,
2316                 DBUS_TYPE_INT32, &interface,
2317                 DBUS_TYPE_INT32, &protocol,
2318                 DBUS_TYPE_STRING, &name,
2319                 DBUS_TYPE_INT32, &aprotocol,
2320                 DBUS_TYPE_UINT32, &flags,
2321                 DBUS_TYPE_INVALID) || !name) {
2322             avahi_log_warn("Error parsing Server::HostNameResolverNew message");
2323             goto fail;
2324         }
2325             
2326         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2327             avahi_log_warn(__FILE__": Too many clients, client request failed.");
2328             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2329         }
2330
2331         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2332             avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2333             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2334         }
2335
2336         i = avahi_new(AsyncHostNameResolverInfo, 1);
2337         i->id = ++client->current_id;
2338         i->client = client;
2339         i->path = avahi_strdup_printf("/Client%u/HostNameResolver%u", client->id, i->id);
2340         AVAHI_LLIST_PREPEND(AsyncHostNameResolverInfo, async_host_name_resolvers, client->async_host_name_resolvers, i);
2341         client->n_objects++;
2342
2343         if (!(i->host_name_resolver = avahi_s_host_name_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, aprotocol, (AvahiLookupFlags) flags, async_host_name_resolver_callback, i))) {
2344             async_host_name_resolver_free(i);
2345             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2346         }
2347         
2348         dbus_connection_register_object_path(c, i->path, &vtable, i);
2349         return respond_path(c, m, i->path);
2350
2351     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "AddressResolverNew")) {
2352         Client *client;
2353         int32_t interface, protocol;
2354         uint32_t flags;
2355         char *address;
2356         AsyncAddressResolverInfo *i;
2357         AvahiAddress a;
2358         static const DBusObjectPathVTable vtable = {
2359             NULL,
2360             msg_async_address_resolver_impl,
2361             NULL,
2362             NULL,
2363             NULL,
2364             NULL
2365         };
2366             
2367         if (!dbus_message_get_args(
2368                 m, &error,
2369                 DBUS_TYPE_INT32, &interface,
2370                 DBUS_TYPE_INT32, &protocol,
2371                 DBUS_TYPE_STRING, &address,
2372                 DBUS_TYPE_UINT32, &flags,
2373                 DBUS_TYPE_INVALID) || !address) {
2374             avahi_log_warn("Error parsing Server::AddressResolverNew message");
2375             goto fail;
2376         }
2377
2378         if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
2379             return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
2380
2381         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2382             avahi_log_warn(__FILE__": Too many clients, client request failed.");
2383             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2384         }
2385
2386         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2387             avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2388             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2389         }
2390
2391         i = avahi_new(AsyncAddressResolverInfo, 1);
2392         i->id = ++client->current_id;
2393         i->client = client;
2394         i->path = avahi_strdup_printf("/Client%u/AddressResolver%u", client->id, i->id);
2395         AVAHI_LLIST_PREPEND(AsyncAddressResolverInfo, async_address_resolvers, client->async_address_resolvers, i);
2396         client->n_objects++;
2397
2398         if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, async_address_resolver_callback, i))) {
2399             async_address_resolver_free(i);
2400             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2401         }
2402         
2403         dbus_connection_register_object_path(c, i->path, &vtable, i);
2404         return respond_path(c, m, i->path);
2405     }
2406
2407     avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
2408
2409 fail:
2410     if (dbus_error_is_set(&error))
2411         dbus_error_free(&error);
2412     
2413     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2414 }
2415
2416 void dbus_protocol_server_state_changed(AvahiServerState state) {
2417     DBusMessage *m;
2418     int32_t t;
2419     
2420     if (!server)
2421         return;
2422
2423     m = dbus_message_new_signal(AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "StateChanged");
2424     t = (int32_t) state;
2425     dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
2426     dbus_connection_send(server->bus, m, NULL);
2427     dbus_message_unref(m);
2428 }
2429
2430 int dbus_protocol_setup(const AvahiPoll *poll_api) {
2431     DBusError error;
2432
2433     static const DBusObjectPathVTable server_vtable = {
2434         NULL,
2435         msg_server_impl,
2436         NULL,
2437         NULL,
2438         NULL,
2439         NULL
2440     };
2441
2442     dbus_error_init(&error);
2443
2444     server = avahi_new(Server, 1);
2445     AVAHI_LLIST_HEAD_INIT(Clients, server->clients);
2446     server->current_id = 0;
2447     server->n_clients = 0;
2448
2449     if (!(server->bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
2450         assert(dbus_error_is_set(&error));
2451         avahi_log_error("dbus_bus_get(): %s", error.message);
2452         goto fail;
2453     }
2454
2455     if (avahi_dbus_connection_glue(server->bus, poll_api) < 0) {
2456         avahi_log_error("avahi_dbus_connection_glue() failed");
2457         goto fail;
2458     }
2459
2460     if (dbus_bus_request_name(server->bus, AVAHI_DBUS_NAME, DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT, &error) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
2461         if (dbus_error_is_set(&error)) {
2462             avahi_log_error("dbus_bus_request_name(): %s", error.message);
2463             goto fail;
2464         }
2465
2466         avahi_log_error("Failed to acquire DBUS name '"AVAHI_DBUS_NAME"'");
2467         goto fail;
2468     }
2469
2470     if (!(dbus_connection_add_filter(server->bus, msg_signal_filter_impl, (void*) poll_api, NULL))) {
2471         avahi_log_error("dbus_connection_add_filter() failed");
2472         goto fail;
2473     }
2474     
2475     dbus_bus_add_match(server->bus, "type='signal',""interface='" DBUS_INTERFACE_DBUS  "'", &error);
2476
2477     if (dbus_error_is_set(&error)) {
2478         avahi_log_error("dbus_bus_add_match(): %s", error.message);
2479         goto fail;
2480     }
2481     
2482     if (!(dbus_connection_register_object_path(server->bus, AVAHI_DBUS_PATH_SERVER, &server_vtable, NULL))) {
2483         avahi_log_error("dbus_connection_register_object_path() failed");
2484         goto fail;
2485     }
2486
2487     return 0;
2488
2489 fail:
2490     if (server->bus) {
2491         dbus_connection_disconnect(server->bus);
2492         dbus_connection_unref(server->bus);
2493     }
2494
2495     if (dbus_error_is_set(&error))
2496         dbus_error_free(&error);
2497         
2498     avahi_free(server);
2499     server = NULL;
2500     return -1;
2501 }
2502
2503 void dbus_protocol_shutdown(void) {
2504
2505     if (server) {
2506     
2507         while (server->clients)
2508             client_free(server->clients);
2509
2510         assert(server->n_clients == 0);
2511
2512         if (server->bus) {
2513             dbus_connection_disconnect(server->bus);
2514             dbus_connection_unref(server->bus);
2515         }
2516
2517         avahi_free(server);
2518         server = NULL;
2519     }
2520 }