1 /* 2 * platform-cros.c - CrOS platform DBus integration 3 * Copyright (c) 2013 The Chromium OS Authors. All rights reserved. 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 #include "config.h" 8 9 #include <ctype.h> 10 #include <dbus/dbus.h> 11 #include <errno.h> 12 #include <signal.h> 13 #include <stdbool.h> 14 #include <stdint.h> 15 #include <string.h> 16 #include <time.h> 17 18 #include <event2/event.h> 19 20 #include "src/dbus.h" 21 #include "src/platform.h" 22 #include "src/tlsdate.h" 23 #include "src/util.h" 24 25 static const char kMatchFormatData[] = "interface='%s',member='%s',arg0='%s'"; 26 static const char *kMatchFormat = kMatchFormatData; 27 static const char kMatchNoArgFormatData[] = "interface='%s',member='%s'"; 28 static const char *kMatchNoArgFormat = kMatchNoArgFormatData; 29 30 static const char kLibCrosDestData[] = "org.chromium.LibCrosService"; 31 static const char *kLibCrosDest = kLibCrosDestData; 32 static const char kLibCrosInterfaceData[] = "org.chromium.LibCrosServiceInterface"; 33 static const char *kLibCrosInterface = kLibCrosInterfaceData; 34 static const char kLibCrosPathData[] = "/org/chromium/LibCrosService"; 35 static const char *kLibCrosPath = kLibCrosPathData; 36 static const char kResolveNetworkProxyData[] = "ResolveNetworkProxy"; 37 static const char *kResolveNetworkProxy = kResolveNetworkProxyData; 38 39 static const char kDBusInterfaceData[] = "org.freedesktop.DBus"; 40 static const char *kDBusInterface = kDBusInterfaceData; 41 static const char kNameOwnerChangedData[] = "NameOwnerChanged"; 42 static const char *kNameOwnerChanged = kNameOwnerChangedData; 43 static const char kNameAcquiredData[] = "NameAcquired"; 44 static const char *kNameAcquired = kNameAcquiredData; 45 46 static const char kManagerInterfaceData[] = "org.chromium.flimflam.Manager"; 47 static const char *kManagerInterface = kManagerInterfaceData; 48 49 static const char kServiceInterfaceData[] = "org.chromium.flimflam.Service"; 50 static const char *kServiceInterface = kServiceInterfaceData; 51 static const char kMemberData[] = "PropertyChanged"; 52 static const char *kMember = kMemberData; 53 54 static const char kProxyConfigData[] = "ProxyConfig"; 55 static const char *kProxyConfig = kProxyConfigData; 56 static const char kDefaultServiceData[] = "DefaultService"; 57 static const char *kDefaultService = kDefaultServiceData; 58 59 static const char kResolveInterfaceData[] = "org.torproject.tlsdate.Resolver"; 60 static const char *kResolveInterface = kResolveInterfaceData; 61 static const char kResolveMemberData[] = "ProxyChange"; 62 static const char *kResolveMember = kResolveMemberData; 63 64 /* TODO(wad) Integrate with cros_system_api/dbus/service_constants.h */ 65 static const char kPowerManagerInterfaceData[] = "org.chromium.PowerManager"; 66 static const char *kPowerManagerInterface = kPowerManagerInterfaceData; 67 static const char kSuspendDoneData[] = "SuspendDone"; 68 static const char *kSuspendDone = kSuspendDoneData; 69 70 static const char kErrorServiceUnknownData[] = "org.freedesktop.DBus.Error.ServiceUnknown"; 71 static const char *kErrorServiceUnknown = kErrorServiceUnknownData; 72 73 struct platform_state 74 { 75 struct event_base *base; 76 struct state *state; 77 DBusMessage **resolve_msg; 78 int resolve_msg_count; 79 uint32_t resolve_network_proxy_serial; 80 }; 81 82 static 83 bool 84 get_valid_hostport (const char *hostport, char *out, size_t len) 85 { 86 bool host = true; 87 const char *end = hostport + strlen (hostport); 88 const char *c; 89 *out = '\0'; 90 /* Hosts begin with alphanumeric only. */ 91 if (!isalnum (*hostport)) 92 { 93 info ("Host does not start with alnum"); 94 return false; 95 } 96 *out++ = *hostport; 97 for (c = hostport + 1; c < end && len > 0; ++c, ++out, --len) 98 { 99 *out = *c; 100 if (host) 101 { 102 if (isalnum (*c) || *c == '-' || *c == '.') 103 { 104 continue; 105 } 106 if (*c == ':') 107 { 108 host = false; 109 continue; 110 } 111 } 112 else 113 { 114 if (isdigit (*c)) 115 continue; 116 } 117 *out = '\0'; 118 return false; 119 } 120 *out = '\0'; 121 return true; 122 } 123 124 /* Convert PAC return format to tlsdated url format */ 125 /* TODO(wad) support multiple proxies when Chromium does: 126 * PROXY x.x.x.x:yyyy; PROXY z.z.z.z:aaaaa 127 */ 128 static 129 void 130 canonicalize_pac (const char *pac_fmt, char *proxy_url, size_t len) 131 { 132 size_t type_len; 133 int copied = 0; 134 const char *space; 135 /* host[255]:port[6]\0 */ 136 char hostport[6 + 255 + 2]; 137 proxy_url[0] = '\0'; 138 if (len < 1) 139 return; 140 if (!strcmp (pac_fmt, "DIRECT")) 141 { 142 return; 143 } 144 /* Find type */ 145 space = strchr (pac_fmt, ' '); 146 if (!space) 147 return; 148 type_len = space - pac_fmt; 149 if (!get_valid_hostport (space + 1, hostport, sizeof (hostport))) 150 { 151 error ("invalid host:port: %s", space + 1); 152 return; 153 } 154 proxy_url[0] = '\0'; 155 if (!strncmp (pac_fmt, "PROXY", type_len)) 156 { 157 copied = snprintf (proxy_url, len, "http://%s", hostport); 158 } 159 else if (!strncmp (pac_fmt, "SOCKS", type_len)) 160 { 161 copied = snprintf (proxy_url, len, "socks4://%s", hostport); 162 } 163 else if (!strncmp (pac_fmt, "SOCKS5", type_len)) 164 { 165 copied = snprintf (proxy_url, len, "socks5://%s", hostport); 166 } 167 else if (!strncmp (pac_fmt, "HTTPS", type_len)) 168 { 169 copied = snprintf (proxy_url, len, "https://%s", hostport); 170 } 171 else 172 { 173 error ("pac_fmt unmatched: '%s' %zu", pac_fmt, type_len); 174 } 175 if (copied < 0 || ((size_t) copied) >= len) 176 { 177 error ("canonicalize_pac: truncation '%s'", proxy_url); 178 proxy_url[0] = '\0'; 179 return; 180 } 181 } 182 183 static 184 DBusHandlerResult 185 handle_service_change (DBusConnection *connection, 186 DBusMessage *message, 187 struct platform_state *ctx) 188 { 189 DBusMessageIter iter, subiter; 190 DBusError error; 191 const char *pname; 192 const char *pval; 193 const char *service; 194 dbus_error_init (&error); 195 verb_debug ("[event:cros:%s]: fired", __func__); 196 /* TODO(wad) Track the current DefaultService only fire when it changes */ 197 service = dbus_message_get_path (message); 198 if (!service) 199 return DBUS_HANDLER_RESULT_HANDLED; 200 /* Shill emits string:ProxyConfig variant string:"..." */ 201 if (!dbus_message_iter_init (message, &iter)) 202 return DBUS_HANDLER_RESULT_HANDLED; 203 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING) 204 return DBUS_HANDLER_RESULT_HANDLED; 205 dbus_message_iter_get_basic (&iter, &pname); 206 /* Make sure we are only firing on a ProxyConfig property change. */ 207 if (strcmp (pname, kProxyConfig)) 208 return DBUS_HANDLER_RESULT_HANDLED; 209 if (!dbus_message_iter_next (&iter)) 210 return DBUS_HANDLER_RESULT_HANDLED; 211 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_VARIANT) 212 return DBUS_HANDLER_RESULT_HANDLED; 213 dbus_message_iter_recurse (&iter, &subiter); 214 if (dbus_message_iter_get_arg_type (&subiter) != DBUS_TYPE_STRING) 215 return DBUS_HANDLER_RESULT_HANDLED; 216 dbus_message_iter_get_basic (&subiter, &pval); 217 /* Right now, nothing is done with the Shill proxy value because 218 * Chromium handles .pac resolution. This may be more useful for 219 * ignoring incomplete proxy values sent while a user is typing. 220 */ 221 action_kickoff_time_sync (-1, EV_TIMEOUT, ctx->state); 222 return DBUS_HANDLER_RESULT_HANDLED; 223 } 224 225 static 226 DBusHandlerResult 227 handle_manager_change (DBusConnection *connection, 228 DBusMessage *message, 229 struct platform_state *ctx) 230 { 231 DBusMessageIter iter, subiter; 232 DBusError error; 233 const char *pname; 234 const char *pval; 235 verb_debug ("[event:cros:%s]: fired", __func__); 236 dbus_error_init (&error); 237 if (!dbus_message_iter_init (message, &iter)) 238 return DBUS_HANDLER_RESULT_HANDLED; 239 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING) 240 return DBUS_HANDLER_RESULT_HANDLED; 241 dbus_message_iter_get_basic (&iter, &pname); 242 /* Make sure we caught the right property. */ 243 if (strcmp (pname, kDefaultService)) 244 return DBUS_HANDLER_RESULT_HANDLED; 245 if (!dbus_message_iter_next (&iter)) 246 return DBUS_HANDLER_RESULT_HANDLED; 247 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_VARIANT) 248 return DBUS_HANDLER_RESULT_HANDLED; 249 dbus_message_iter_recurse (&iter, &subiter); 250 if (dbus_message_iter_get_arg_type (&subiter) != DBUS_TYPE_OBJECT_PATH) 251 return DBUS_HANDLER_RESULT_HANDLED; 252 dbus_message_iter_get_basic (&subiter, &pval); 253 /* TODO(wad) Filter on the currently active service in pval. */ 254 verb_debug ("[event:cros:%s] service change on path %s", 255 __func__, pval); 256 action_kickoff_time_sync (-1, EV_TIMEOUT, ctx->state); 257 return DBUS_HANDLER_RESULT_HANDLED; 258 } 259 260 static 261 DBusHandlerResult 262 handle_suspend_done (DBusConnection *connection, 263 DBusMessage *message, 264 struct platform_state *ctx) 265 { 266 verb_debug ("[event:cros:%s]: fired", __func__); 267 /* Coming back from resume, trigger a continuity and time 268 * check just in case none of the other events happen. 269 */ 270 action_kickoff_time_sync (-1, EV_TIMEOUT, ctx->state); 271 return DBUS_HANDLER_RESULT_HANDLED; 272 } 273 274 static 275 DBusHandlerResult 276 handle_proxy_change (DBusConnection *connection, 277 DBusMessage *message, 278 struct platform_state *ctx) 279 { 280 DBusMessageIter iter; 281 DBusError error; 282 const char *pname; 283 const char *pval; 284 char time_host[MAX_PROXY_URL]; 285 int url_len = 0; 286 struct source *src = ctx->state->opts.sources; 287 verb_debug ("[event:cros:%s]: fired", __func__); 288 if (ctx->state->opts.cur_source && ctx->state->opts.cur_source->next) 289 src = ctx->state->opts.cur_source->next; 290 if (!ctx->state->resolving) 291 { 292 info ("[event:cros:%s] Unexpected ResolveNetworkProxy signal seen", 293 __func__); 294 return DBUS_HANDLER_RESULT_HANDLED; 295 } 296 dbus_error_init (&error); 297 /* Shill emits string:ProxyConfig variant string:"..." */ 298 if (!dbus_message_iter_init (message, &iter)) 299 return DBUS_HANDLER_RESULT_HANDLED; 300 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING) 301 return DBUS_HANDLER_RESULT_HANDLED; 302 dbus_message_iter_get_basic (&iter, &pname); 303 /* Make sure this was the resolution we asked for */ 304 url_len = snprintf (time_host, sizeof (time_host), "https://%s:%s", 305 src->host, src->port); 306 if (url_len < 0 || ((size_t) url_len) >= sizeof (time_host)) 307 { 308 error ("[event:cros:%s]: current source url is too long", 309 __func__); 310 } 311 if (strcmp (pname, time_host)) 312 { 313 error ("[event:cros:%s]: resolved host mismatch: %s v %s", 314 __func__, pname, time_host); 315 return DBUS_HANDLER_RESULT_HANDLED; 316 } 317 if (!dbus_message_iter_next (&iter)) 318 return DBUS_HANDLER_RESULT_HANDLED; 319 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING) 320 return DBUS_HANDLER_RESULT_HANDLED; 321 dbus_message_iter_get_basic (&iter, &pval); 322 ctx->state->resolving = 0; 323 canonicalize_pac (pval, ctx->state->dynamic_proxy, sizeof (ctx->state->dynamic_proxy)); 324 trigger_event (ctx->state, E_TLSDATE, 1); 325 return DBUS_HANDLER_RESULT_HANDLED; 326 } 327 328 static 329 DBusHandlerResult 330 handle_dbus_change (DBusConnection *connection, 331 DBusMessage *message, 332 struct platform_state *ctx) 333 { 334 DBusMessageIter iter; 335 DBusError error; 336 const char *pname; 337 verb_debug ("[event:cros:%s]: fired", __func__); 338 dbus_error_init (&error); 339 if (!dbus_message_iter_init (message, &iter)) 340 return DBUS_HANDLER_RESULT_HANDLED; 341 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING) 342 return DBUS_HANDLER_RESULT_HANDLED; 343 dbus_message_iter_get_basic (&iter, &pname); 344 /* Make sure we caught the right property. */ 345 if (strcmp (pname, kLibCrosDest)) 346 return DBUS_HANDLER_RESULT_HANDLED; 347 action_kickoff_time_sync (-1, EV_TIMEOUT, ctx->state); 348 return DBUS_HANDLER_RESULT_HANDLED; 349 } 350 351 static 352 void 353 action_resolve_proxy (evutil_socket_t fd, short what, void *arg) 354 { 355 struct platform_state *ctx = arg; 356 struct dbus_state *dbus_state = ctx->state->dbus; 357 DBusConnection *conn = dbus_state->conn; 358 struct source *src = ctx->state->opts.sources; 359 verb_debug ("[event:%s] fired", __func__); 360 /* Emulate tlsdate-monitor.c:build_argv and choose the next source */ 361 if (ctx->state->opts.cur_source && ctx->state->opts.cur_source->next) 362 src = ctx->state->opts.cur_source->next; 363 if (ctx->state->resolving || ctx->resolve_network_proxy_serial) 364 { 365 /* Note, this is not the same as the response signal. It just avoids 366 * multiple requests in a single dispatch window. 367 */ 368 info ("[event:%s] no resolve_proxy sent; pending method_reply", 369 __func__); 370 return; 371 } 372 ctx->state->dynamic_proxy[0] = '\0'; 373 if (ctx->resolve_msg[src->id] == NULL) 374 { 375 info ("[event:%s] no dynamic proxy for %s:%s", __func__, 376 src->host, src->port); 377 trigger_event (ctx->state, E_TLSDATE, 1); 378 return; 379 } 380 info ("[event:%s] resolving proxy for %s:%s", __func__, 381 src->host, src->port); 382 ctx->state->resolving = 1; 383 if (!dbus_connection_send (conn, 384 ctx->resolve_msg[src->id], 385 &ctx->resolve_network_proxy_serial)) 386 { 387 error ("[event:%s] cannot send ResolveNetworkProxy query!", __func__); 388 return; 389 } 390 } 391 392 static 393 DBusHandlerResult 394 dbus_filter (DBusConnection *connection, DBusMessage *message, void *data) 395 { 396 struct platform_state *state = data; 397 /* Terminate gracefully if DBus goes away. */ 398 if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected")) 399 { 400 error ("[cros] DBus system bus has become inaccessible. Terminating."); 401 /* Trigger a graceful teardown. */ 402 kill (getpid(), SIGINT); 403 return DBUS_HANDLER_RESULT_HANDLED; 404 } 405 /* Hand it over to the service dispatcher. */ 406 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL) 407 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 408 409 /* Handle explicitly defined signals only. */ 410 if (dbus_message_is_signal (message, kDBusInterface, kNameAcquired)) 411 { 412 info ("[cros] DBus name acquired successfully"); 413 return DBUS_HANDLER_RESULT_HANDLED; 414 } 415 if (dbus_message_is_signal (message, kServiceInterface, kMember)) 416 return handle_service_change (connection, message, state); 417 if (dbus_message_is_signal (message, kManagerInterface, kMember)) 418 return handle_manager_change (connection, message, state); 419 if (dbus_message_is_signal (message, kResolveInterface, kResolveMember)) 420 return handle_proxy_change (connection, message, state); 421 if (dbus_message_is_signal (message, kDBusInterface, kNameOwnerChanged)) 422 return handle_dbus_change (connection, message, state); 423 if (dbus_message_is_signal (message, kPowerManagerInterface, kSuspendDone)) 424 return handle_suspend_done (connection, message, state); 425 if (dbus_message_is_error (message, kErrorServiceUnknown)) 426 { 427 info ("[cros] org.chromium.LibCrosService.ResolveNetworkProxy is missing"); 428 info ("[cros] skipping proxy resolution for now"); 429 /* Fire off tlsdate rather than letting it fail silently. */ 430 state->resolve_network_proxy_serial = 0; 431 state->state->resolving = 0; 432 trigger_event (state->state, E_TLSDATE, 1); 433 return DBUS_HANDLER_RESULT_HANDLED; 434 } 435 /* Indicates a successful resolve request was issued. */ 436 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN) 437 { 438 uint32_t serial = dbus_message_get_reply_serial (message); 439 if (serial == state->resolve_network_proxy_serial) 440 { 441 state->resolve_network_proxy_serial = 0; 442 return DBUS_HANDLER_RESULT_HANDLED; 443 } 444 info ("[cros] unknown DBus METHOD_RETURN seen: %u", serial); 445 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 446 } 447 verb_debug ("[cros] unknown message received: " 448 "type=%s dest=%s interface=%s member=%s path=%s sig=%s error_name=%s", 449 dbus_message_type_to_string (dbus_message_get_type (message)), 450 dbus_message_get_destination (message), 451 dbus_message_get_interface (message), 452 dbus_message_get_member (message), 453 dbus_message_get_path (message), 454 dbus_message_get_signature (message), 455 dbus_message_get_error_name (message)); 456 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 457 } 458 459 int 460 add_match (DBusConnection *conn, const char *interface, const char *member, 461 const char *arg0) 462 { 463 char match[1024]; 464 DBusError error; 465 int len; 466 dbus_error_init (&error); 467 if (arg0) 468 { 469 len = snprintf (match, sizeof (match), kMatchFormat, 470 interface, member, arg0); 471 } 472 else 473 { 474 len = snprintf (match, sizeof (match), kMatchNoArgFormat, 475 interface, member); 476 } 477 if (len < 0 || ((size_t) len) >= sizeof (match)) 478 { 479 error ("[dbus] match truncated for '%s,%s'", interface, member); 480 return 1; 481 } 482 dbus_bus_add_match (conn, match, &error); 483 if (dbus_error_is_set (&error)) 484 { 485 error ("[dbus] failed to add_match for '%s,%s'; error: %s, %s", 486 interface, member, error.name, error.message); 487 dbus_error_free (&error); 488 return 1; 489 } 490 return 0; 491 } 492 493 DBusMessage * 494 new_resolver_message(const struct source *src) 495 { 496 char time_host[MAX_PROXY_URL]; 497 void *time_host_ptr = &time_host; 498 int url_len; 499 DBusMessage *res; 500 DBusMessageIter args; 501 if (!src->proxy || strcmp (src->proxy, "dynamic")) 502 { 503 return NULL; 504 } 505 res = dbus_message_new_method_call (kLibCrosDest, kLibCrosPath, 506 kLibCrosInterface, kResolveNetworkProxy); 507 if (!res) 508 { 509 error ("[cros] could not setup dynamic proxy for source %d", src->id); 510 return NULL; 511 } 512 /* Build the time_host */ 513 url_len = snprintf (time_host, sizeof (time_host), "https://%s:%s", 514 src->host, src->port); 515 if (url_len < 0 || ((size_t) url_len) >= sizeof (time_host)) 516 { 517 fatal ("[cros] source %d url is too long! (%d)", src->id, url_len); 518 } 519 /* Finish the message */ 520 dbus_message_iter_init_append (res, &args); 521 if (!dbus_message_iter_append_basic (&args, DBUS_TYPE_STRING, &time_host_ptr) || 522 !dbus_message_iter_append_basic (&args, DBUS_TYPE_STRING, &kResolveInterface) || 523 !dbus_message_iter_append_basic (&args, DBUS_TYPE_STRING, &kResolveMember)) 524 { 525 fatal ("[cros could not append arguments for resolver message"); 526 } 527 return res; 528 } 529 530 int 531 platform_init_cros (struct state *state) 532 { 533 /* Watch for per-service ProxyConfig property changes */ 534 struct event_base *base = state->base; 535 struct dbus_state *dbus_state = state->dbus; 536 if (!dbus_state) 537 { 538 info ("[cros] DBus not connected, skipping platform initialization."); 539 return 0; 540 } 541 struct source *src = NULL; 542 int sources = 0; 543 DBusConnection *conn = dbus_state->conn; 544 DBusError error; 545 struct platform_state *platform_state = 546 calloc (1, sizeof (struct platform_state)); 547 if (!platform_state) 548 { 549 error ("[cros] could not allocate platform_state"); 550 return -1; 551 } 552 /* TODO(wad) Follow up with dbus_error_free() where needed. */ 553 dbus_error_init (&error); 554 /* Add watches for: proxy changes, default service changes, proxy resolution, 555 * LibCrosService ownership, and power state changes. 556 */ 557 if (add_match (conn, kServiceInterface, kMember, kProxyConfig) || 558 add_match (conn, kManagerInterface, kMember, kDefaultService) || 559 add_match (conn, kResolveInterface, kResolveMember, NULL) || 560 add_match (conn, kDBusInterface, kNameOwnerChanged, kLibCrosDest) || 561 add_match (conn, kPowerManagerInterface, kSuspendDone, NULL)) 562 return 1; 563 564 /* Allocate one per source */ 565 for (src = state->opts.sources; src; src = src->next, ++sources); 566 platform_state->resolve_msg_count = sources; 567 platform_state->resolve_msg = calloc (sources, sizeof (DBusMessage *)); 568 if (!platform_state->resolve_msg) 569 { 570 error ("[cros] cannot allocate resolver messages"); 571 free (platform_state); 572 return -1; 573 } 574 for (src = state->opts.sources; src; src = src->next) 575 { 576 if (src->id >= sources) 577 fatal ("Source ID is greater than available sources!"); 578 platform_state->resolve_msg[src->id] = new_resolver_message (src); 579 if (platform_state->resolve_msg[src->id]) 580 src->proxy = state->dynamic_proxy; 581 } 582 state->dynamic_proxy[0] = '\0'; 583 if (state->opts.proxy && !strcmp (state->opts.proxy, "dynamic")) 584 { 585 info ("[cros] default dynamic proxy support"); 586 state->opts.proxy = state->dynamic_proxy; 587 } 588 platform_state->base = base; 589 platform_state->state = state; 590 /* Add the dynamic resolver if tlsdate doesn't already have one. */ 591 if (!state->events[E_RESOLVER]) 592 { 593 state->events[E_RESOLVER] = event_new (base, -1, EV_TIMEOUT, 594 action_resolve_proxy, 595 platform_state); 596 if (!state->events[E_RESOLVER]) 597 /* Let's not clean up DBus. */ 598 fatal ("Could not allocated resolver event"); 599 /* Wake up as a NET event since it'll self-block until DBus has a chance 600 * to send it. 601 */ 602 event_priority_set (state->events[E_RESOLVER], PRI_NET); 603 } 604 /* Each platform can attach their own filter, but the filter func needs to be 605 * willing to DBUS_HANDLER_RESULT_NOT_YET_HANDLED on unexpected events. 606 */ 607 /* TODO(wad) add the clean up function as the callback. */ 608 if (!dbus_connection_add_filter (conn, 609 dbus_filter, platform_state, NULL)) 610 { 611 error ("Failed to register signal handler callback"); 612 return 1; 613 } 614 return 0; 615 } 616