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