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