dbus_new_helpers.c
Go to the documentation of this file.
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 }


wpa_supplicant_node
Author(s): Package maintained by Blaise Gassend
autogenerated on Thu Jan 2 2014 11:25:12