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