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