$search
00001 /* 00002 * WPA Supplicant / dbus-based control interface 00003 * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc. 00004 * Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com> 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License version 2 as 00008 * published by the Free Software Foundation. 00009 * 00010 * Alternatively, this software may be distributed under the terms of BSD 00011 * license. 00012 * 00013 * See README and COPYING for more details. 00014 */ 00015 00016 #include "utils/includes.h" 00017 00018 #include "utils/common.h" 00019 #include "utils/eloop.h" 00020 #include "dbus_common.h" 00021 #include "dbus_common_i.h" 00022 #include "dbus_new.h" 00023 #include "dbus_new_helpers.h" 00024 00025 00035 static void recursive_iter_copy(DBusMessageIter *from, DBusMessageIter *to) 00036 { 00037 00038 char *subtype = NULL; 00039 int type; 00040 00041 /* iterate over iterator to copy */ 00042 while ((type = dbus_message_iter_get_arg_type(from)) != 00043 DBUS_TYPE_INVALID) { 00044 00045 /* simply copy basic type entries */ 00046 if (dbus_type_is_basic(type)) { 00047 if (dbus_type_is_fixed(type)) { 00048 /* 00049 * According to DBus documentation all 00050 * fixed-length types are guaranteed to fit 00051 * 8 bytes 00052 */ 00053 dbus_uint64_t v; 00054 dbus_message_iter_get_basic(from, &v); 00055 dbus_message_iter_append_basic(to, type, &v); 00056 } else { 00057 char *v; 00058 dbus_message_iter_get_basic(from, &v); 00059 dbus_message_iter_append_basic(to, type, &v); 00060 } 00061 } else { 00062 /* recursively copy container type entries */ 00063 DBusMessageIter write_subiter, read_subiter; 00064 00065 dbus_message_iter_recurse(from, &read_subiter); 00066 00067 if (type == DBUS_TYPE_VARIANT || 00068 type == DBUS_TYPE_ARRAY) { 00069 subtype = dbus_message_iter_get_signature( 00070 &read_subiter); 00071 } 00072 00073 dbus_message_iter_open_container(to, type, subtype, 00074 &write_subiter); 00075 00076 recursive_iter_copy(&read_subiter, &write_subiter); 00077 00078 dbus_message_iter_close_container(to, &write_subiter); 00079 if (subtype) 00080 dbus_free(subtype); 00081 } 00082 00083 dbus_message_iter_next(from); 00084 } 00085 } 00086 00087 00088 static unsigned int fill_dict_with_properties( 00089 DBusMessageIter *dict_iter, const struct wpa_dbus_property_desc *props, 00090 const char *interface, const void *user_data) 00091 { 00092 DBusMessage *reply; 00093 DBusMessageIter entry_iter, ret_iter; 00094 unsigned int counter = 0; 00095 const struct wpa_dbus_property_desc *dsc; 00096 00097 for (dsc = props; dsc && dsc->dbus_property; dsc++) { 00098 if (!os_strncmp(dsc->dbus_interface, interface, 00099 WPAS_DBUS_INTERFACE_MAX) && 00100 dsc->access != W && dsc->getter) { 00101 reply = dsc->getter(NULL, user_data); 00102 if (!reply) 00103 continue; 00104 00105 if (dbus_message_get_type(reply) == 00106 DBUS_MESSAGE_TYPE_ERROR) { 00107 dbus_message_unref(reply); 00108 continue; 00109 } 00110 00111 dbus_message_iter_init(reply, &ret_iter); 00112 00113 dbus_message_iter_open_container(dict_iter, 00114 DBUS_TYPE_DICT_ENTRY, 00115 NULL, &entry_iter); 00116 dbus_message_iter_append_basic( 00117 &entry_iter, DBUS_TYPE_STRING, 00118 &dsc->dbus_property); 00119 00120 recursive_iter_copy(&ret_iter, &entry_iter); 00121 00122 dbus_message_iter_close_container(dict_iter, 00123 &entry_iter); 00124 dbus_message_unref(reply); 00125 counter++; 00126 } 00127 } 00128 00129 return counter; 00130 } 00131 00132 00145 static DBusMessage * get_all_properties( 00146 DBusMessage *message, char *interface, 00147 struct wpa_dbus_object_desc *obj_dsc) 00148 { 00149 /* Create and initialize the return message */ 00150 DBusMessage *reply = dbus_message_new_method_return(message); 00151 DBusMessageIter iter, dict_iter; 00152 int props_num; 00153 00154 dbus_message_iter_init_append(reply, &iter); 00155 00156 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, 00157 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING 00158 DBUS_TYPE_STRING_AS_STRING 00159 DBUS_TYPE_VARIANT_AS_STRING 00160 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, 00161 &dict_iter); 00162 00163 props_num = fill_dict_with_properties(&dict_iter, obj_dsc->properties, 00164 interface, obj_dsc->user_data); 00165 00166 dbus_message_iter_close_container(&iter, &dict_iter); 00167 00168 if (props_num == 0) { 00169 dbus_message_unref(reply); 00170 reply = dbus_message_new_error(message, 00171 DBUS_ERROR_INVALID_ARGS, 00172 "No readable properties in " 00173 "this interface"); 00174 } 00175 00176 return reply; 00177 } 00178 00179 00180 static int is_signature_correct(DBusMessage *message, 00181 const struct wpa_dbus_method_desc *method_dsc) 00182 { 00183 /* According to DBus documentation max length of signature is 255 */ 00184 #define MAX_SIG_LEN 256 00185 char registered_sig[MAX_SIG_LEN], *pos; 00186 const char *sig = dbus_message_get_signature(message); 00187 int ret; 00188 const struct wpa_dbus_argument *arg; 00189 00190 pos = registered_sig; 00191 *pos = '\0'; 00192 00193 for (arg = method_dsc->args; arg && arg->name; arg++) { 00194 if (arg->dir == ARG_IN) { 00195 size_t blen = registered_sig + MAX_SIG_LEN - pos; 00196 ret = os_snprintf(pos, blen, "%s", arg->type); 00197 if (ret < 0 || (size_t) ret >= blen) 00198 return 0; 00199 pos += ret; 00200 } 00201 } 00202 00203 return !os_strncmp(registered_sig, sig, MAX_SIG_LEN); 00204 } 00205 00206 00207 static DBusMessage * properties_get_all(DBusMessage *message, char *interface, 00208 struct wpa_dbus_object_desc *obj_dsc) 00209 { 00210 if (os_strcmp(dbus_message_get_signature(message), "s") != 0) 00211 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, 00212 NULL); 00213 00214 return get_all_properties(message, interface, obj_dsc); 00215 } 00216 00217 00218 static DBusMessage * properties_get(DBusMessage *message, 00219 const struct wpa_dbus_property_desc *dsc, 00220 void *user_data) 00221 { 00222 if (os_strcmp(dbus_message_get_signature(message), "ss")) 00223 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, 00224 NULL); 00225 00226 if (dsc->access != W && dsc->getter) 00227 return dsc->getter(message, user_data); 00228 00229 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, 00230 "Property is write-only"); 00231 } 00232 00233 00234 static DBusMessage * properties_set(DBusMessage *message, 00235 const struct wpa_dbus_property_desc *dsc, 00236 void *user_data) 00237 { 00238 if (os_strcmp(dbus_message_get_signature(message), "ssv")) 00239 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, 00240 NULL); 00241 00242 if (dsc->access != R && dsc->setter) 00243 return dsc->setter(message, user_data); 00244 00245 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, 00246 "Property is read-only"); 00247 } 00248 00249 00250 static DBusMessage * 00251 properties_get_or_set(DBusMessage *message, DBusMessageIter *iter, 00252 char *interface, 00253 struct wpa_dbus_object_desc *obj_dsc) 00254 { 00255 const struct wpa_dbus_property_desc *property_dsc; 00256 char *property; 00257 const char *method; 00258 00259 method = dbus_message_get_member(message); 00260 property_dsc = obj_dsc->properties; 00261 00262 /* Second argument: property name (DBUS_TYPE_STRING) */ 00263 if (!dbus_message_iter_next(iter) || 00264 dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING) { 00265 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, 00266 NULL); 00267 } 00268 dbus_message_iter_get_basic(iter, &property); 00269 00270 while (property_dsc && property_dsc->dbus_property) { 00271 /* compare property names and 00272 * interfaces */ 00273 if (!os_strncmp(property_dsc->dbus_property, property, 00274 WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) && 00275 !os_strncmp(property_dsc->dbus_interface, interface, 00276 WPAS_DBUS_INTERFACE_MAX)) 00277 break; 00278 00279 property_dsc++; 00280 } 00281 if (property_dsc == NULL || property_dsc->dbus_property == NULL) { 00282 wpa_printf(MSG_DEBUG, "no property handler for %s.%s on %s", 00283 interface, property, 00284 dbus_message_get_path(message)); 00285 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, 00286 "No such property"); 00287 } 00288 00289 if (os_strncmp(WPA_DBUS_PROPERTIES_GET, method, 00290 WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) == 0) 00291 return properties_get(message, property_dsc, 00292 obj_dsc->user_data); 00293 00294 return properties_set(message, property_dsc, obj_dsc->user_data); 00295 } 00296 00297 00298 static DBusMessage * properties_handler(DBusMessage *message, 00299 struct wpa_dbus_object_desc *obj_dsc) 00300 { 00301 DBusMessageIter iter; 00302 char *interface; 00303 const char *method; 00304 00305 method = dbus_message_get_member(message); 00306 dbus_message_iter_init(message, &iter); 00307 00308 if (!os_strncmp(WPA_DBUS_PROPERTIES_GET, method, 00309 WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) || 00310 !os_strncmp(WPA_DBUS_PROPERTIES_SET, method, 00311 WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) || 00312 !os_strncmp(WPA_DBUS_PROPERTIES_GETALL, method, 00313 WPAS_DBUS_METHOD_SIGNAL_PROP_MAX)) { 00314 /* First argument: interface name (DBUS_TYPE_STRING) */ 00315 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) 00316 { 00317 return dbus_message_new_error(message, 00318 DBUS_ERROR_INVALID_ARGS, 00319 NULL); 00320 } 00321 00322 dbus_message_iter_get_basic(&iter, &interface); 00323 00324 if (!os_strncmp(WPA_DBUS_PROPERTIES_GETALL, method, 00325 WPAS_DBUS_METHOD_SIGNAL_PROP_MAX)) { 00326 /* GetAll */ 00327 return properties_get_all(message, interface, obj_dsc); 00328 } 00329 /* Get or Set */ 00330 return properties_get_or_set(message, &iter, interface, 00331 obj_dsc); 00332 } 00333 return dbus_message_new_error(message, DBUS_ERROR_UNKNOWN_METHOD, 00334 NULL); 00335 } 00336 00337 00338 static DBusMessage * msg_method_handler(DBusMessage *message, 00339 struct wpa_dbus_object_desc *obj_dsc) 00340 { 00341 const struct wpa_dbus_method_desc *method_dsc = obj_dsc->methods; 00342 const char *method; 00343 const char *msg_interface; 00344 00345 method = dbus_message_get_member(message); 00346 msg_interface = dbus_message_get_interface(message); 00347 00348 /* try match call to any registered method */ 00349 while (method_dsc && method_dsc->dbus_method) { 00350 /* compare method names and interfaces */ 00351 if (!os_strncmp(method_dsc->dbus_method, method, 00352 WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) && 00353 !os_strncmp(method_dsc->dbus_interface, msg_interface, 00354 WPAS_DBUS_INTERFACE_MAX)) 00355 break; 00356 00357 method_dsc++; 00358 } 00359 if (method_dsc == NULL || method_dsc->dbus_method == NULL) { 00360 wpa_printf(MSG_DEBUG, "no method handler for %s.%s on %s", 00361 msg_interface, method, 00362 dbus_message_get_path(message)); 00363 return dbus_message_new_error(message, 00364 DBUS_ERROR_UNKNOWN_METHOD, NULL); 00365 } 00366 00367 if (!is_signature_correct(message, method_dsc)) { 00368 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, 00369 NULL); 00370 } 00371 00372 return method_dsc->method_handler(message, 00373 obj_dsc->user_data); 00374 } 00375 00376 00392 static DBusHandlerResult message_handler(DBusConnection *connection, 00393 DBusMessage *message, void *user_data) 00394 { 00395 struct wpa_dbus_object_desc *obj_dsc = user_data; 00396 const char *method; 00397 const char *path; 00398 const char *msg_interface; 00399 DBusMessage *reply; 00400 00401 /* get method, interface and path the message is addressed to */ 00402 method = dbus_message_get_member(message); 00403 path = dbus_message_get_path(message); 00404 msg_interface = dbus_message_get_interface(message); 00405 if (!method || !path || !msg_interface) 00406 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 00407 00408 wpa_printf(MSG_MSGDUMP, "dbus: %s.%s (%s)", 00409 msg_interface, method, path); 00410 00411 /* if message is introspection method call */ 00412 if (!os_strncmp(WPA_DBUS_INTROSPECTION_METHOD, method, 00413 WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) && 00414 !os_strncmp(WPA_DBUS_INTROSPECTION_INTERFACE, msg_interface, 00415 WPAS_DBUS_INTERFACE_MAX)) { 00416 #ifdef CONFIG_CTRL_IFACE_DBUS_INTRO 00417 reply = wpa_dbus_introspect(message, obj_dsc); 00418 #else /* CONFIG_CTRL_IFACE_DBUS_INTRO */ 00419 reply = dbus_message_new_error( 00420 message, DBUS_ERROR_UNKNOWN_METHOD, 00421 "wpa_supplicant was compiled without " 00422 "introspection support."); 00423 #endif /* CONFIG_CTRL_IFACE_DBUS_INTRO */ 00424 } else if (!os_strncmp(WPA_DBUS_PROPERTIES_INTERFACE, msg_interface, 00425 WPAS_DBUS_INTERFACE_MAX)) { 00426 /* if message is properties method call */ 00427 reply = properties_handler(message, obj_dsc); 00428 } else { 00429 reply = msg_method_handler(message, obj_dsc); 00430 } 00431 00432 /* If handler succeed returning NULL, reply empty message */ 00433 if (!reply) 00434 reply = dbus_message_new_method_return(message); 00435 if (reply) { 00436 if (!dbus_message_get_no_reply(message)) 00437 dbus_connection_send(connection, reply, NULL); 00438 dbus_message_unref(reply); 00439 } 00440 00441 wpa_dbus_flush_all_changed_properties(connection); 00442 00443 return DBUS_HANDLER_RESULT_HANDLED; 00444 } 00445 00446 00455 void free_dbus_object_desc(struct wpa_dbus_object_desc *obj_dsc) 00456 { 00457 if (!obj_dsc) 00458 return; 00459 00460 /* free handler's argument */ 00461 if (obj_dsc->user_data_free_func) 00462 obj_dsc->user_data_free_func(obj_dsc->user_data); 00463 00464 os_free(obj_dsc->path); 00465 os_free(obj_dsc->prop_changed_flags); 00466 os_free(obj_dsc); 00467 } 00468 00469 00470 static void free_dbus_object_desc_cb(DBusConnection *connection, void *obj_dsc) 00471 { 00472 free_dbus_object_desc(obj_dsc); 00473 } 00474 00487 int wpa_dbus_ctrl_iface_init(struct wpas_dbus_priv *iface, 00488 char *dbus_path, char *dbus_service, 00489 struct wpa_dbus_object_desc *obj_desc) 00490 { 00491 DBusError error; 00492 int ret = -1; 00493 DBusObjectPathVTable wpa_vtable = { 00494 &free_dbus_object_desc_cb, &message_handler, 00495 NULL, NULL, NULL, NULL 00496 }; 00497 00498 obj_desc->connection = iface->con; 00499 obj_desc->path = os_strdup(dbus_path); 00500 00501 /* Register the message handler for the global dbus interface */ 00502 if (!dbus_connection_register_object_path(iface->con, 00503 dbus_path, &wpa_vtable, 00504 obj_desc)) { 00505 wpa_printf(MSG_ERROR, "dbus: Could not set up message " 00506 "handler"); 00507 return -1; 00508 } 00509 00510 /* Register our service with the message bus */ 00511 dbus_error_init(&error); 00512 switch (dbus_bus_request_name(iface->con, dbus_service, 00513 0, &error)) { 00514 case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER: 00515 ret = 0; 00516 break; 00517 case DBUS_REQUEST_NAME_REPLY_EXISTS: 00518 case DBUS_REQUEST_NAME_REPLY_IN_QUEUE: 00519 case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER: 00520 wpa_printf(MSG_ERROR, "dbus: Could not request service name: " 00521 "already registered"); 00522 break; 00523 default: 00524 wpa_printf(MSG_ERROR, "dbus: Could not request service name: " 00525 "%s %s", error.name, error.message); 00526 break; 00527 } 00528 dbus_error_free(&error); 00529 00530 if (ret != 0) 00531 return -1; 00532 00533 wpa_printf(MSG_DEBUG, "Providing DBus service '%s'.", dbus_service); 00534 00535 return 0; 00536 } 00537 00538 00549 int wpa_dbus_register_object_per_iface( 00550 struct wpas_dbus_priv *ctrl_iface, 00551 const char *path, const char *ifname, 00552 struct wpa_dbus_object_desc *obj_desc) 00553 { 00554 DBusConnection *con; 00555 00556 DBusObjectPathVTable vtable = { 00557 &free_dbus_object_desc_cb, &message_handler, 00558 NULL, NULL, NULL, NULL 00559 }; 00560 00561 /* Do nothing if the control interface is not turned on */ 00562 if (ctrl_iface == NULL) 00563 return 0; 00564 00565 con = ctrl_iface->con; 00566 obj_desc->connection = con; 00567 obj_desc->path = os_strdup(path); 00568 00569 /* Register the message handler for the interface functions */ 00570 if (!dbus_connection_register_object_path(con, path, &vtable, 00571 obj_desc)) { 00572 wpa_printf(MSG_ERROR, "dbus: Could not set up message " 00573 "handler for interface %s object %s", ifname, path); 00574 return -1; 00575 } 00576 00577 return 0; 00578 } 00579 00580 00581 static void flush_object_timeout_handler(void *eloop_ctx, void *timeout_ctx); 00582 00583 00592 int wpa_dbus_unregister_object_per_iface( 00593 struct wpas_dbus_priv *ctrl_iface, const char *path) 00594 { 00595 DBusConnection *con = ctrl_iface->con; 00596 struct wpa_dbus_object_desc *obj_desc = NULL; 00597 00598 dbus_connection_get_object_path_data(con, path, (void **) &obj_desc); 00599 if (!obj_desc) { 00600 wpa_printf(MSG_ERROR, "dbus: %s: Could not obtain object's " 00601 "private data: %s", __func__, path); 00602 } else { 00603 eloop_cancel_timeout(flush_object_timeout_handler, con, 00604 obj_desc); 00605 } 00606 00607 if (!dbus_connection_unregister_object_path(con, path)) 00608 return -1; 00609 00610 return 0; 00611 } 00612 00613 00614 static void put_changed_properties(const struct wpa_dbus_object_desc *obj_dsc, 00615 const char *interface, 00616 DBusMessageIter *dict_iter) 00617 { 00618 DBusMessage *getter_reply; 00619 DBusMessageIter prop_iter, entry_iter; 00620 const struct wpa_dbus_property_desc *dsc; 00621 int i; 00622 00623 for (dsc = obj_dsc->properties, i = 0; dsc && dsc->dbus_property; 00624 dsc++, i++) { 00625 if (obj_dsc->prop_changed_flags == NULL || 00626 !obj_dsc->prop_changed_flags[i]) 00627 continue; 00628 if (os_strcmp(dsc->dbus_interface, interface) != 0) 00629 continue; 00630 obj_dsc->prop_changed_flags[i] = 0; 00631 00632 getter_reply = dsc->getter(NULL, obj_dsc->user_data); 00633 if (!getter_reply || 00634 dbus_message_get_type(getter_reply) == 00635 DBUS_MESSAGE_TYPE_ERROR) { 00636 wpa_printf(MSG_ERROR, "dbus: %s: Cannot get new value " 00637 "of property %s", __func__, 00638 dsc->dbus_property); 00639 continue; 00640 } 00641 00642 if (!dbus_message_iter_init(getter_reply, &prop_iter) || 00643 !dbus_message_iter_open_container(dict_iter, 00644 DBUS_TYPE_DICT_ENTRY, 00645 NULL, &entry_iter) || 00646 !dbus_message_iter_append_basic(&entry_iter, 00647 DBUS_TYPE_STRING, 00648 &dsc->dbus_property)) 00649 goto err; 00650 00651 recursive_iter_copy(&prop_iter, &entry_iter); 00652 00653 if (!dbus_message_iter_close_container(dict_iter, &entry_iter)) 00654 goto err; 00655 00656 dbus_message_unref(getter_reply); 00657 } 00658 00659 return; 00660 00661 err: 00662 wpa_printf(MSG_ERROR, "dbus: %s: Cannot construct signal", __func__); 00663 } 00664 00665 00666 static void send_prop_changed_signal( 00667 DBusConnection *con, const char *path, const char *interface, 00668 const struct wpa_dbus_object_desc *obj_dsc) 00669 { 00670 DBusMessage *msg; 00671 DBusMessageIter signal_iter, dict_iter; 00672 00673 msg = dbus_message_new_signal(path, interface, "PropertiesChanged"); 00674 if (msg == NULL) 00675 return; 00676 00677 dbus_message_iter_init_append(msg, &signal_iter); 00678 00679 if (!dbus_message_iter_open_container(&signal_iter, DBUS_TYPE_ARRAY, 00680 "{sv}", &dict_iter)) 00681 goto err; 00682 00683 put_changed_properties(obj_dsc, interface, &dict_iter); 00684 00685 if (!dbus_message_iter_close_container(&signal_iter, &dict_iter)) 00686 goto err; 00687 00688 dbus_connection_send(con, msg, NULL); 00689 00690 out: 00691 dbus_message_unref(msg); 00692 return; 00693 00694 err: 00695 wpa_printf(MSG_DEBUG, "dbus: %s: Failed to construct signal", 00696 __func__); 00697 goto out; 00698 } 00699 00700 00701 static void flush_object_timeout_handler(void *eloop_ctx, void *timeout_ctx) 00702 { 00703 DBusConnection *con = eloop_ctx; 00704 struct wpa_dbus_object_desc *obj_desc = timeout_ctx; 00705 00706 wpa_printf(MSG_DEBUG, "dbus: %s: Timeout - sending changed properties " 00707 "of object %s", __func__, obj_desc->path); 00708 wpa_dbus_flush_object_changed_properties(con, obj_desc->path); 00709 } 00710 00711 00712 static void recursive_flush_changed_properties(DBusConnection *con, 00713 const char *path) 00714 { 00715 char **objects = NULL; 00716 char subobj_path[WPAS_DBUS_OBJECT_PATH_MAX]; 00717 int i; 00718 00719 wpa_dbus_flush_object_changed_properties(con, path); 00720 00721 if (!dbus_connection_list_registered(con, path, &objects)) 00722 goto out; 00723 00724 for (i = 0; objects[i]; i++) { 00725 os_snprintf(subobj_path, WPAS_DBUS_OBJECT_PATH_MAX, 00726 "%s/%s", path, objects[i]); 00727 recursive_flush_changed_properties(con, subobj_path); 00728 } 00729 00730 out: 00731 dbus_free_string_array(objects); 00732 } 00733 00734 00742 void wpa_dbus_flush_all_changed_properties(DBusConnection *con) 00743 { 00744 recursive_flush_changed_properties(con, WPAS_DBUS_NEW_PATH); 00745 } 00746 00747 00765 void wpa_dbus_flush_object_changed_properties(DBusConnection *con, 00766 const char *path) 00767 { 00768 struct wpa_dbus_object_desc *obj_desc = NULL; 00769 const struct wpa_dbus_property_desc *dsc; 00770 int i; 00771 00772 dbus_connection_get_object_path_data(con, path, (void **) &obj_desc); 00773 if (!obj_desc) 00774 return; 00775 eloop_cancel_timeout(flush_object_timeout_handler, con, obj_desc); 00776 00777 dsc = obj_desc->properties; 00778 for (dsc = obj_desc->properties, i = 0; dsc && dsc->dbus_property; 00779 dsc++, i++) { 00780 if (obj_desc->prop_changed_flags == NULL || 00781 !obj_desc->prop_changed_flags[i]) 00782 continue; 00783 send_prop_changed_signal(con, path, dsc->dbus_interface, 00784 obj_desc); 00785 } 00786 } 00787 00788 00789 #define WPA_DBUS_SEND_PROP_CHANGED_TIMEOUT 5000 00790 00791 00805 void wpa_dbus_mark_property_changed(struct wpas_dbus_priv *iface, 00806 const char *path, const char *interface, 00807 const char *property) 00808 { 00809 struct wpa_dbus_object_desc *obj_desc = NULL; 00810 const struct wpa_dbus_property_desc *dsc; 00811 int i = 0; 00812 00813 if (iface == NULL) 00814 return; 00815 00816 dbus_connection_get_object_path_data(iface->con, path, 00817 (void **) &obj_desc); 00818 if (!obj_desc) { 00819 wpa_printf(MSG_ERROR, "dbus: wpa_dbus_property_changed: " 00820 "could not obtain object's private data: %s", path); 00821 return; 00822 } 00823 00824 for (dsc = obj_desc->properties; dsc && dsc->dbus_property; dsc++, i++) 00825 if (os_strcmp(property, dsc->dbus_property) == 0 && 00826 os_strcmp(interface, dsc->dbus_interface) == 0) { 00827 if (obj_desc->prop_changed_flags) 00828 obj_desc->prop_changed_flags[i] = 1; 00829 break; 00830 } 00831 00832 if (!dsc || !dsc->dbus_property) { 00833 wpa_printf(MSG_ERROR, "dbus: wpa_dbus_property_changed: " 00834 "no property %s in object %s", property, path); 00835 return; 00836 } 00837 00838 if (!eloop_is_timeout_registered(flush_object_timeout_handler, 00839 iface->con, obj_desc->path)) { 00840 eloop_register_timeout(0, WPA_DBUS_SEND_PROP_CHANGED_TIMEOUT, 00841 flush_object_timeout_handler, 00842 iface->con, obj_desc); 00843 } 00844 } 00845 00846 00859 void wpa_dbus_get_object_properties(struct wpas_dbus_priv *iface, 00860 const char *path, const char *interface, 00861 DBusMessageIter *dict_iter) 00862 { 00863 struct wpa_dbus_object_desc *obj_desc = NULL; 00864 00865 dbus_connection_get_object_path_data(iface->con, path, 00866 (void **) &obj_desc); 00867 if (!obj_desc) { 00868 wpa_printf(MSG_ERROR, "dbus: wpa_dbus_get_object_properties: " 00869 "could not obtain object's private data: %s", path); 00870 return; 00871 } 00872 00873 fill_dict_with_properties(dict_iter, obj_desc->properties, 00874 interface, obj_desc->user_data); 00875 }