dbus_new_helpers.c (214501) | dbus_new_helpers.c (252190) |
---|---|
1/* 2 * WPA Supplicant / dbus-based control interface 3 * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc. 4 * Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com> 5 * | 1/* 2 * WPA Supplicant / dbus-based control interface 3 * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc. 4 * Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com> 5 * |
6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 * 10 * Alternatively, this software may be distributed under the terms of BSD 11 * license. 12 * 13 * See README and COPYING for more details. | 6 * This software may be distributed under the terms of the BSD license. 7 * See README for more details. |
14 */ 15 16#include "utils/includes.h" 17 18#include "utils/common.h" 19#include "utils/eloop.h" 20#include "dbus_common.h" 21#include "dbus_common_i.h" 22#include "dbus_new.h" 23#include "dbus_new_helpers.h" | 8 */ 9 10#include "utils/includes.h" 11 12#include "utils/common.h" 13#include "utils/eloop.h" 14#include "dbus_common.h" 15#include "dbus_common_i.h" 16#include "dbus_new.h" 17#include "dbus_new_helpers.h" |
18#include "dbus_dict_helpers.h" |
|
24 25 | 19 20 |
26/** 27 * recursive_iter_copy - Reads arguments from one iterator and 28 * writes to another recursively 29 * @from: iterator to read from 30 * @to: iterator to write to 31 * 32 * Copies one iterator's elements to another. If any element in 33 * iterator is of container type, its content is copied recursively 34 */ 35static void recursive_iter_copy(DBusMessageIter *from, DBusMessageIter *to) | 21static dbus_bool_t fill_dict_with_properties( 22 DBusMessageIter *dict_iter, 23 const struct wpa_dbus_property_desc *props, 24 const char *interface, void *user_data, DBusError *error) |
36{ | 25{ |
37 38 char *subtype = NULL; 39 int type; 40 41 /* iterate over iterator to copy */ 42 while ((type = dbus_message_iter_get_arg_type(from)) != 43 DBUS_TYPE_INVALID) { 44 45 /* simply copy basic type entries */ 46 if (dbus_type_is_basic(type)) { 47 if (dbus_type_is_fixed(type)) { 48 /* 49 * According to DBus documentation all 50 * fixed-length types are guaranteed to fit 51 * 8 bytes 52 */ 53 dbus_uint64_t v; 54 dbus_message_iter_get_basic(from, &v); 55 dbus_message_iter_append_basic(to, type, &v); 56 } else { 57 char *v; 58 dbus_message_iter_get_basic(from, &v); 59 dbus_message_iter_append_basic(to, type, &v); 60 } 61 } else { 62 /* recursively copy container type entries */ 63 DBusMessageIter write_subiter, read_subiter; 64 65 dbus_message_iter_recurse(from, &read_subiter); 66 67 if (type == DBUS_TYPE_VARIANT || 68 type == DBUS_TYPE_ARRAY) { 69 subtype = dbus_message_iter_get_signature( 70 &read_subiter); 71 } 72 73 dbus_message_iter_open_container(to, type, subtype, 74 &write_subiter); 75 76 recursive_iter_copy(&read_subiter, &write_subiter); 77 78 dbus_message_iter_close_container(to, &write_subiter); 79 if (subtype) 80 dbus_free(subtype); 81 } 82 83 dbus_message_iter_next(from); 84 } 85} 86 87 88static unsigned int fill_dict_with_properties( 89 DBusMessageIter *dict_iter, const struct wpa_dbus_property_desc *props, 90 const char *interface, const void *user_data) 91{ 92 DBusMessage *reply; 93 DBusMessageIter entry_iter, ret_iter; 94 unsigned int counter = 0; | 26 DBusMessageIter entry_iter; |
95 const struct wpa_dbus_property_desc *dsc; 96 97 for (dsc = props; dsc && dsc->dbus_property; dsc++) { | 27 const struct wpa_dbus_property_desc *dsc; 28 29 for (dsc = props; dsc && dsc->dbus_property; dsc++) { |
98 if (!os_strncmp(dsc->dbus_interface, interface, 99 WPAS_DBUS_INTERFACE_MAX) && 100 dsc->access != W && dsc->getter) { 101 reply = dsc->getter(NULL, user_data); 102 if (!reply) 103 continue; | 30 /* Only return properties for the requested D-Bus interface */ 31 if (os_strncmp(dsc->dbus_interface, interface, 32 WPAS_DBUS_INTERFACE_MAX) != 0) 33 continue; |
104 | 34 |
105 if (dbus_message_get_type(reply) == 106 DBUS_MESSAGE_TYPE_ERROR) { 107 dbus_message_unref(reply); 108 continue; 109 } | 35 /* Skip write-only properties */ 36 if (dsc->getter == NULL) 37 continue; |
110 | 38 |
111 dbus_message_iter_init(reply, &ret_iter); | 39 if (!dbus_message_iter_open_container(dict_iter, 40 DBUS_TYPE_DICT_ENTRY, 41 NULL, &entry_iter)) { 42 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, 43 "no memory"); 44 return FALSE; 45 } 46 if (!dbus_message_iter_append_basic(&entry_iter, 47 DBUS_TYPE_STRING, 48 &dsc->dbus_property)) { 49 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, 50 "no memory"); 51 return FALSE; 52 } |
112 | 53 |
113 dbus_message_iter_open_container(dict_iter, 114 DBUS_TYPE_DICT_ENTRY, 115 NULL, &entry_iter); 116 dbus_message_iter_append_basic( 117 &entry_iter, DBUS_TYPE_STRING, 118 &dsc->dbus_property); | 54 /* An error getting a property fails the request entirely */ 55 if (!dsc->getter(&entry_iter, error, user_data)) 56 return FALSE; |
119 | 57 |
120 recursive_iter_copy(&ret_iter, &entry_iter); 121 122 dbus_message_iter_close_container(dict_iter, 123 &entry_iter); 124 dbus_message_unref(reply); 125 counter++; 126 } | 58 dbus_message_iter_close_container(dict_iter, &entry_iter); |
127 } 128 | 59 } 60 |
129 return counter; | 61 return TRUE; |
130} 131 132 133/** 134 * get_all_properties - Responds for GetAll properties calls on object 135 * @message: Message with GetAll call 136 * @interface: interface name which properties will be returned 137 * @property_dsc: list of object's properties 138 * Returns: Message with dict of variants as argument with properties values 139 * 140 * Iterates over all properties registered with object and execute getters 141 * of those, which are readable and which interface matches interface 142 * specified as argument. Returned message contains one dict argument 143 * with properties names as keys and theirs values as values. 144 */ | 62} 63 64 65/** 66 * get_all_properties - Responds for GetAll properties calls on object 67 * @message: Message with GetAll call 68 * @interface: interface name which properties will be returned 69 * @property_dsc: list of object's properties 70 * Returns: Message with dict of variants as argument with properties values 71 * 72 * Iterates over all properties registered with object and execute getters 73 * of those, which are readable and which interface matches interface 74 * specified as argument. Returned message contains one dict argument 75 * with properties names as keys and theirs values as values. 76 */ |
145static DBusMessage * get_all_properties( 146 DBusMessage *message, char *interface, 147 struct wpa_dbus_object_desc *obj_dsc) | 77static DBusMessage * get_all_properties(DBusMessage *message, char *interface, 78 struct wpa_dbus_object_desc *obj_dsc) |
148{ | 79{ |
149 /* Create and initialize the return message */ 150 DBusMessage *reply = dbus_message_new_method_return(message); | 80 DBusMessage *reply; |
151 DBusMessageIter iter, dict_iter; | 81 DBusMessageIter iter, dict_iter; |
152 int props_num; | 82 DBusError error; |
153 | 83 |
84 reply = dbus_message_new_method_return(message); 85 if (reply == NULL) { 86 wpa_printf(MSG_ERROR, "%s: out of memory creating dbus reply", 87 __func__); 88 return NULL; 89 } 90 |
|
154 dbus_message_iter_init_append(reply, &iter); | 91 dbus_message_iter_init_append(reply, &iter); |
92 if (!wpa_dbus_dict_open_write(&iter, &dict_iter)) { 93 wpa_printf(MSG_ERROR, "%s: out of memory creating reply", 94 __func__); 95 dbus_message_unref(reply); 96 reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, 97 "out of memory"); 98 return reply; 99 } |
|
155 | 100 |
156 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, 157 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING 158 DBUS_TYPE_STRING_AS_STRING 159 DBUS_TYPE_VARIANT_AS_STRING 160 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, 161 &dict_iter); 162 163 props_num = fill_dict_with_properties(&dict_iter, obj_dsc->properties, 164 interface, obj_dsc->user_data); 165 166 dbus_message_iter_close_container(&iter, &dict_iter); 167 168 if (props_num == 0) { | 101 dbus_error_init(&error); 102 if (!fill_dict_with_properties(&dict_iter, obj_dsc->properties, 103 interface, obj_dsc->user_data, &error)) 104 { |
169 dbus_message_unref(reply); | 105 dbus_message_unref(reply); |
170 reply = dbus_message_new_error(message, 171 DBUS_ERROR_INVALID_ARGS, 172 "No readable properties in " 173 "this interface"); | 106 reply = wpas_dbus_reply_new_from_error(message, &error, 107 DBUS_ERROR_INVALID_ARGS, 108 "No readable properties" 109 " in this interface"); 110 dbus_error_free(&error); 111 return reply; |
174 } 175 | 112 } 113 |
114 wpa_dbus_dict_close_write(&iter, &dict_iter); |
|
176 return reply; 177} 178 179 180static int is_signature_correct(DBusMessage *message, 181 const struct wpa_dbus_method_desc *method_dsc) 182{ 183 /* According to DBus documentation max length of signature is 255 */ --- 30 unchanged lines hidden (view full) --- 214 return get_all_properties(message, interface, obj_dsc); 215} 216 217 218static DBusMessage * properties_get(DBusMessage *message, 219 const struct wpa_dbus_property_desc *dsc, 220 void *user_data) 221{ | 115 return reply; 116} 117 118 119static int is_signature_correct(DBusMessage *message, 120 const struct wpa_dbus_method_desc *method_dsc) 121{ 122 /* According to DBus documentation max length of signature is 255 */ --- 30 unchanged lines hidden (view full) --- 153 return get_all_properties(message, interface, obj_dsc); 154} 155 156 157static DBusMessage * properties_get(DBusMessage *message, 158 const struct wpa_dbus_property_desc *dsc, 159 void *user_data) 160{ |
222 if (os_strcmp(dbus_message_get_signature(message), "ss")) | 161 DBusMessage *reply; 162 DBusMessageIter iter; 163 DBusError error; 164 165 if (os_strcmp(dbus_message_get_signature(message), "ss")) { |
223 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, 224 NULL); | 166 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, 167 NULL); |
168 } |
|
225 | 169 |
226 if (dsc->access != W && dsc->getter) 227 return dsc->getter(message, user_data); | 170 if (dsc->getter == NULL) { 171 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, 172 "Property is write-only"); 173 } |
228 | 174 |
229 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, 230 "Property is write-only"); | 175 reply = dbus_message_new_method_return(message); 176 dbus_message_iter_init_append(reply, &iter); 177 178 dbus_error_init(&error); 179 if (dsc->getter(&iter, &error, user_data) == FALSE) { 180 dbus_message_unref(reply); 181 reply = wpas_dbus_reply_new_from_error( 182 message, &error, DBUS_ERROR_FAILED, 183 "Failed to read property"); 184 dbus_error_free(&error); 185 } 186 187 return reply; |
231} 232 233 234static DBusMessage * properties_set(DBusMessage *message, 235 const struct wpa_dbus_property_desc *dsc, 236 void *user_data) 237{ | 188} 189 190 191static DBusMessage * properties_set(DBusMessage *message, 192 const struct wpa_dbus_property_desc *dsc, 193 void *user_data) 194{ |
238 if (os_strcmp(dbus_message_get_signature(message), "ssv")) | 195 DBusMessage *reply; 196 DBusMessageIter iter; 197 DBusError error; 198 199 if (os_strcmp(dbus_message_get_signature(message), "ssv")) { |
239 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, 240 NULL); | 200 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, 201 NULL); |
202 } |
|
241 | 203 |
242 if (dsc->access != R && dsc->setter) 243 return dsc->setter(message, user_data); | 204 if (dsc->setter == NULL) { 205 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, 206 "Property is read-only"); 207 } |
244 | 208 |
245 return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, 246 "Property is read-only"); | 209 dbus_message_iter_init(message, &iter); 210 /* Skip the interface name and the property name */ 211 dbus_message_iter_next(&iter); 212 dbus_message_iter_next(&iter); 213 214 /* Iter will now point to the property's new value */ 215 dbus_error_init(&error); 216 if (dsc->setter(&iter, &error, user_data) == TRUE) { 217 /* Success */ 218 reply = dbus_message_new_method_return(message); 219 } else { 220 reply = wpas_dbus_reply_new_from_error( 221 message, &error, DBUS_ERROR_FAILED, 222 "Failed to set property"); 223 dbus_error_free(&error); 224 } 225 226 return reply; |
247} 248 249 250static DBusMessage * 251properties_get_or_set(DBusMessage *message, DBusMessageIter *iter, 252 char *interface, 253 struct wpa_dbus_object_desc *obj_dsc) 254{ --- 292 unchanged lines hidden (view full) --- 547 * Registers a new interface with dbus and assigns it a dbus object path. 548 */ 549int wpa_dbus_register_object_per_iface( 550 struct wpas_dbus_priv *ctrl_iface, 551 const char *path, const char *ifname, 552 struct wpa_dbus_object_desc *obj_desc) 553{ 554 DBusConnection *con; | 227} 228 229 230static DBusMessage * 231properties_get_or_set(DBusMessage *message, DBusMessageIter *iter, 232 char *interface, 233 struct wpa_dbus_object_desc *obj_dsc) 234{ --- 292 unchanged lines hidden (view full) --- 527 * Registers a new interface with dbus and assigns it a dbus object path. 528 */ 529int wpa_dbus_register_object_per_iface( 530 struct wpas_dbus_priv *ctrl_iface, 531 const char *path, const char *ifname, 532 struct wpa_dbus_object_desc *obj_desc) 533{ 534 DBusConnection *con; |
535 DBusError error; |
|
555 556 DBusObjectPathVTable vtable = { 557 &free_dbus_object_desc_cb, &message_handler, 558 NULL, NULL, NULL, NULL 559 }; 560 561 /* Do nothing if the control interface is not turned on */ 562 if (ctrl_iface == NULL) 563 return 0; 564 565 con = ctrl_iface->con; 566 obj_desc->connection = con; 567 obj_desc->path = os_strdup(path); 568 | 536 537 DBusObjectPathVTable vtable = { 538 &free_dbus_object_desc_cb, &message_handler, 539 NULL, NULL, NULL, NULL 540 }; 541 542 /* Do nothing if the control interface is not turned on */ 543 if (ctrl_iface == NULL) 544 return 0; 545 546 con = ctrl_iface->con; 547 obj_desc->connection = con; 548 obj_desc->path = os_strdup(path); 549 |
550 dbus_error_init(&error); |
|
569 /* Register the message handler for the interface functions */ | 551 /* Register the message handler for the interface functions */ |
570 if (!dbus_connection_register_object_path(con, path, &vtable, 571 obj_desc)) { 572 wpa_printf(MSG_ERROR, "dbus: Could not set up message " 573 "handler for interface %s object %s", ifname, path); | 552 if (!dbus_connection_try_register_object_path(con, path, &vtable, 553 obj_desc, &error)) { 554 if (!os_strcmp(error.name, DBUS_ERROR_OBJECT_PATH_IN_USE)) { 555 wpa_printf(MSG_DEBUG, "dbus: %s", error.message); 556 } else { 557 wpa_printf(MSG_ERROR, "dbus: Could not set up message " 558 "handler for interface %s object %s", 559 ifname, path); 560 wpa_printf(MSG_ERROR, "dbus error: %s", error.name); 561 wpa_printf(MSG_ERROR, "dbus: %s", error.message); 562 } 563 dbus_error_free(&error); |
574 return -1; 575 } 576 | 564 return -1; 565 } 566 |
567 dbus_error_free(&error); |
|
577 return 0; 578} 579 580 581static void flush_object_timeout_handler(void *eloop_ctx, void *timeout_ctx); 582 583 584/** --- 21 unchanged lines hidden (view full) --- 606 607 if (!dbus_connection_unregister_object_path(con, path)) 608 return -1; 609 610 return 0; 611} 612 613 | 568 return 0; 569} 570 571 572static void flush_object_timeout_handler(void *eloop_ctx, void *timeout_ctx); 573 574 575/** --- 21 unchanged lines hidden (view full) --- 597 598 if (!dbus_connection_unregister_object_path(con, path)) 599 return -1; 600 601 return 0; 602} 603 604 |
614static void put_changed_properties(const struct wpa_dbus_object_desc *obj_dsc, 615 const char *interface, 616 DBusMessageIter *dict_iter) | 605static dbus_bool_t put_changed_properties( 606 const struct wpa_dbus_object_desc *obj_dsc, const char *interface, 607 DBusMessageIter *dict_iter, int clear_changed) |
617{ | 608{ |
618 DBusMessage *getter_reply; 619 DBusMessageIter prop_iter, entry_iter; | 609 DBusMessageIter entry_iter; |
620 const struct wpa_dbus_property_desc *dsc; 621 int i; | 610 const struct wpa_dbus_property_desc *dsc; 611 int i; |
612 DBusError error; |
|
622 623 for (dsc = obj_dsc->properties, i = 0; dsc && dsc->dbus_property; 624 dsc++, i++) { 625 if (obj_dsc->prop_changed_flags == NULL || 626 !obj_dsc->prop_changed_flags[i]) 627 continue; 628 if (os_strcmp(dsc->dbus_interface, interface) != 0) 629 continue; | 613 614 for (dsc = obj_dsc->properties, i = 0; dsc && dsc->dbus_property; 615 dsc++, i++) { 616 if (obj_dsc->prop_changed_flags == NULL || 617 !obj_dsc->prop_changed_flags[i]) 618 continue; 619 if (os_strcmp(dsc->dbus_interface, interface) != 0) 620 continue; |
630 obj_dsc->prop_changed_flags[i] = 0; | 621 if (clear_changed) 622 obj_dsc->prop_changed_flags[i] = 0; |
631 | 623 |
632 getter_reply = dsc->getter(NULL, obj_dsc->user_data); 633 if (!getter_reply || 634 dbus_message_get_type(getter_reply) == 635 DBUS_MESSAGE_TYPE_ERROR) { 636 wpa_printf(MSG_ERROR, "dbus: %s: Cannot get new value " 637 "of property %s", __func__, 638 dsc->dbus_property); 639 continue; 640 } 641 642 if (!dbus_message_iter_init(getter_reply, &prop_iter) || 643 !dbus_message_iter_open_container(dict_iter, | 624 if (!dbus_message_iter_open_container(dict_iter, |
644 DBUS_TYPE_DICT_ENTRY, | 625 DBUS_TYPE_DICT_ENTRY, |
645 NULL, &entry_iter) || 646 !dbus_message_iter_append_basic(&entry_iter, | 626 NULL, &entry_iter)) 627 return FALSE; 628 629 if (!dbus_message_iter_append_basic(&entry_iter, |
647 DBUS_TYPE_STRING, 648 &dsc->dbus_property)) | 630 DBUS_TYPE_STRING, 631 &dsc->dbus_property)) |
649 goto err; | 632 return FALSE; |
650 | 633 |
651 recursive_iter_copy(&prop_iter, &entry_iter); | 634 dbus_error_init(&error); 635 if (!dsc->getter(&entry_iter, &error, obj_dsc->user_data)) { 636 if (dbus_error_is_set (&error)) { 637 wpa_printf(MSG_ERROR, "dbus: %s: Cannot get " 638 "new value of property %s: (%s) %s", 639 __func__, dsc->dbus_property, 640 error.name, error.message); 641 } else { 642 wpa_printf(MSG_ERROR, "dbus: %s: Cannot get " 643 "new value of property %s", 644 __func__, dsc->dbus_property); 645 } 646 dbus_error_free(&error); 647 return FALSE; 648 } |
652 653 if (!dbus_message_iter_close_container(dict_iter, &entry_iter)) | 649 650 if (!dbus_message_iter_close_container(dict_iter, &entry_iter)) |
654 goto err; 655 656 dbus_message_unref(getter_reply); | 651 return FALSE; |
657 } 658 | 652 } 653 |
654 return TRUE; 655} 656 657 658static void do_send_prop_changed_signal( 659 DBusConnection *con, const char *path, const char *interface, 660 const struct wpa_dbus_object_desc *obj_dsc) 661{ 662 DBusMessage *msg; 663 DBusMessageIter signal_iter, dict_iter; 664 665 msg = dbus_message_new_signal(path, DBUS_INTERFACE_PROPERTIES, 666 "PropertiesChanged"); 667 if (msg == NULL) 668 return; 669 670 dbus_message_iter_init_append(msg, &signal_iter); 671 672 if (!dbus_message_iter_append_basic(&signal_iter, DBUS_TYPE_STRING, 673 &interface)) 674 goto err; 675 676 /* Changed properties dict */ 677 if (!dbus_message_iter_open_container(&signal_iter, DBUS_TYPE_ARRAY, 678 "{sv}", &dict_iter)) 679 goto err; 680 681 if (!put_changed_properties(obj_dsc, interface, &dict_iter, 0)) 682 goto err; 683 684 if (!dbus_message_iter_close_container(&signal_iter, &dict_iter)) 685 goto err; 686 687 /* Invalidated properties array (empty) */ 688 if (!dbus_message_iter_open_container(&signal_iter, DBUS_TYPE_ARRAY, 689 "s", &dict_iter)) 690 goto err; 691 692 if (!dbus_message_iter_close_container(&signal_iter, &dict_iter)) 693 goto err; 694 695 dbus_connection_send(con, msg, NULL); 696 697out: 698 dbus_message_unref(msg); |
|
659 return; 660 661err: | 699 return; 700 701err: |
662 wpa_printf(MSG_ERROR, "dbus: %s: Cannot construct signal", __func__); | 702 wpa_printf(MSG_DEBUG, "dbus: %s: Failed to construct signal", 703 __func__); 704 goto out; |
663} 664 665 | 705} 706 707 |
666static void send_prop_changed_signal( | 708static void do_send_deprecated_prop_changed_signal( |
667 DBusConnection *con, const char *path, const char *interface, 668 const struct wpa_dbus_object_desc *obj_dsc) 669{ 670 DBusMessage *msg; 671 DBusMessageIter signal_iter, dict_iter; 672 673 msg = dbus_message_new_signal(path, interface, "PropertiesChanged"); 674 if (msg == NULL) 675 return; 676 677 dbus_message_iter_init_append(msg, &signal_iter); 678 679 if (!dbus_message_iter_open_container(&signal_iter, DBUS_TYPE_ARRAY, 680 "{sv}", &dict_iter)) 681 goto err; 682 | 709 DBusConnection *con, const char *path, const char *interface, 710 const struct wpa_dbus_object_desc *obj_dsc) 711{ 712 DBusMessage *msg; 713 DBusMessageIter signal_iter, dict_iter; 714 715 msg = dbus_message_new_signal(path, interface, "PropertiesChanged"); 716 if (msg == NULL) 717 return; 718 719 dbus_message_iter_init_append(msg, &signal_iter); 720 721 if (!dbus_message_iter_open_container(&signal_iter, DBUS_TYPE_ARRAY, 722 "{sv}", &dict_iter)) 723 goto err; 724 |
683 put_changed_properties(obj_dsc, interface, &dict_iter); | 725 if (!put_changed_properties(obj_dsc, interface, &dict_iter, 1)) 726 goto err; |
684 685 if (!dbus_message_iter_close_container(&signal_iter, &dict_iter)) 686 goto err; 687 688 dbus_connection_send(con, msg, NULL); 689 690out: 691 dbus_message_unref(msg); 692 return; 693 694err: 695 wpa_printf(MSG_DEBUG, "dbus: %s: Failed to construct signal", 696 __func__); 697 goto out; 698} 699 700 | 727 728 if (!dbus_message_iter_close_container(&signal_iter, &dict_iter)) 729 goto err; 730 731 dbus_connection_send(con, msg, NULL); 732 733out: 734 dbus_message_unref(msg); 735 return; 736 737err: 738 wpa_printf(MSG_DEBUG, "dbus: %s: Failed to construct signal", 739 __func__); 740 goto out; 741} 742 743 |
744static void send_prop_changed_signal( 745 DBusConnection *con, const char *path, const char *interface, 746 const struct wpa_dbus_object_desc *obj_dsc) 747{ 748 /* 749 * First, send property change notification on the standardized 750 * org.freedesktop.DBus.Properties interface. This call will not 751 * clear the property change bits, so that they are preserved for 752 * the call that follows. 753 */ 754 do_send_prop_changed_signal(con, path, interface, obj_dsc); 755 756 /* 757 * Now send PropertiesChanged on our own interface for backwards 758 * compatibility. This is deprecated and will be removed in a future 759 * release. 760 */ 761 do_send_deprecated_prop_changed_signal(con, path, interface, obj_dsc); 762 763 /* Property change bits have now been cleared. */ 764} 765 766 |
|
701static void flush_object_timeout_handler(void *eloop_ctx, void *timeout_ctx) 702{ 703 DBusConnection *con = eloop_ctx; 704 struct wpa_dbus_object_desc *obj_desc = timeout_ctx; 705 706 wpa_printf(MSG_DEBUG, "dbus: %s: Timeout - sending changed properties " 707 "of object %s", __func__, obj_desc->path); 708 wpa_dbus_flush_object_changed_properties(con, obj_desc->path); --- 135 unchanged lines hidden (view full) --- 844} 845 846 847/** 848 * wpa_dbus_get_object_properties - Put object's properties into dictionary 849 * @iface: dbus priv struct 850 * @path: path to DBus object which properties will be obtained 851 * @interface: interface name which properties will be obtained | 767static void flush_object_timeout_handler(void *eloop_ctx, void *timeout_ctx) 768{ 769 DBusConnection *con = eloop_ctx; 770 struct wpa_dbus_object_desc *obj_desc = timeout_ctx; 771 772 wpa_printf(MSG_DEBUG, "dbus: %s: Timeout - sending changed properties " 773 "of object %s", __func__, obj_desc->path); 774 wpa_dbus_flush_object_changed_properties(con, obj_desc->path); --- 135 unchanged lines hidden (view full) --- 910} 911 912 913/** 914 * wpa_dbus_get_object_properties - Put object's properties into dictionary 915 * @iface: dbus priv struct 916 * @path: path to DBus object which properties will be obtained 917 * @interface: interface name which properties will be obtained |
852 * @dict_iter: correct, open DBus dictionary iterator. | 918 * @iter: DBus message iter at which to append property dictionary. |
853 * 854 * Iterates over all properties registered with object and execute getters 855 * of those, which are readable and which interface matches interface 856 * specified as argument. Obtained properties values are stored in 857 * dict_iter dictionary. 858 */ | 919 * 920 * Iterates over all properties registered with object and execute getters 921 * of those, which are readable and which interface matches interface 922 * specified as argument. Obtained properties values are stored in 923 * dict_iter dictionary. 924 */ |
859void wpa_dbus_get_object_properties(struct wpas_dbus_priv *iface, 860 const char *path, const char *interface, 861 DBusMessageIter *dict_iter) | 925dbus_bool_t wpa_dbus_get_object_properties(struct wpas_dbus_priv *iface, 926 const char *path, 927 const char *interface, 928 DBusMessageIter *iter) |
862{ 863 struct wpa_dbus_object_desc *obj_desc = NULL; | 929{ 930 struct wpa_dbus_object_desc *obj_desc = NULL; |
931 DBusMessageIter dict_iter; 932 DBusError error; |
|
864 865 dbus_connection_get_object_path_data(iface->con, path, 866 (void **) &obj_desc); 867 if (!obj_desc) { | 933 934 dbus_connection_get_object_path_data(iface->con, path, 935 (void **) &obj_desc); 936 if (!obj_desc) { |
868 wpa_printf(MSG_ERROR, "dbus: wpa_dbus_get_object_properties: " 869 "could not obtain object's private data: %s", path); 870 return; | 937 wpa_printf(MSG_ERROR, "dbus: %s: could not obtain object's " 938 "private data: %s", __func__, path); 939 return FALSE; |
871 } 872 | 940 } 941 |
873 fill_dict_with_properties(dict_iter, obj_desc->properties, 874 interface, obj_desc->user_data); | 942 if (!wpa_dbus_dict_open_write(iter, &dict_iter)) { 943 wpa_printf(MSG_ERROR, "dbus: %s: failed to open message dict", 944 __func__); 945 return FALSE; 946 } 947 948 dbus_error_init(&error); 949 if (!fill_dict_with_properties(&dict_iter, obj_desc->properties, 950 interface, obj_desc->user_data, 951 &error)) { 952 wpa_printf(MSG_ERROR, "dbus: %s: failed to get object" 953 " properties: (%s) %s", __func__, 954 dbus_error_is_set(&error) ? error.name : "none", 955 dbus_error_is_set(&error) ? error.message : "none"); 956 dbus_error_free(&error); 957 return FALSE; 958 } 959 960 return wpa_dbus_dict_close_write(iter, &dict_iter); |
875} | 961} |
962 963/** 964 * wpas_dbus_new_decompose_object_path - Decompose an interface object path into parts 965 * @path: The dbus object path 966 * @p2p_persistent_group: indicates whether to parse the path as a P2P 967 * persistent group object 968 * @network: (out) the configured network this object path refers to, if any 969 * @bssid: (out) the scanned bssid this object path refers to, if any 970 * Returns: The object path of the network interface this path refers to 971 * 972 * For a given object path, decomposes the object path into object id, network, 973 * and BSSID parts, if those parts exist. 974 */ 975char *wpas_dbus_new_decompose_object_path(const char *path, 976 int p2p_persistent_group, 977 char **network, 978 char **bssid) 979{ 980 const unsigned int dev_path_prefix_len = 981 os_strlen(WPAS_DBUS_NEW_PATH_INTERFACES "/"); 982 char *obj_path_only; 983 char *next_sep; 984 985 /* Be a bit paranoid about path */ 986 if (!path || os_strncmp(path, WPAS_DBUS_NEW_PATH_INTERFACES "/", 987 dev_path_prefix_len)) 988 return NULL; 989 990 /* Ensure there's something at the end of the path */ 991 if ((path + dev_path_prefix_len)[0] == '\0') 992 return NULL; 993 994 obj_path_only = os_strdup(path); 995 if (obj_path_only == NULL) 996 return NULL; 997 998 next_sep = os_strchr(obj_path_only + dev_path_prefix_len, '/'); 999 if (next_sep != NULL) { 1000 const char *net_part = os_strstr( 1001 next_sep, p2p_persistent_group ? 1002 WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART "/" : 1003 WPAS_DBUS_NEW_NETWORKS_PART "/"); 1004 const char *bssid_part = os_strstr( 1005 next_sep, WPAS_DBUS_NEW_BSSIDS_PART "/"); 1006 1007 if (network && net_part) { 1008 /* Deal with a request for a configured network */ 1009 const char *net_name = net_part + 1010 os_strlen(p2p_persistent_group ? 1011 WPAS_DBUS_NEW_PERSISTENT_GROUPS_PART 1012 "/" : 1013 WPAS_DBUS_NEW_NETWORKS_PART "/"); 1014 *network = NULL; 1015 if (os_strlen(net_name)) 1016 *network = os_strdup(net_name); 1017 } else if (bssid && bssid_part) { 1018 /* Deal with a request for a scanned BSSID */ 1019 const char *bssid_name = bssid_part + 1020 os_strlen(WPAS_DBUS_NEW_BSSIDS_PART "/"); 1021 if (os_strlen(bssid_name)) 1022 *bssid = os_strdup(bssid_name); 1023 else 1024 *bssid = NULL; 1025 } 1026 1027 /* Cut off interface object path before "/" */ 1028 *next_sep = '\0'; 1029 } 1030 1031 return obj_path_only; 1032} 1033 1034 1035/** 1036 * wpas_dbus_reply_new_from_error - Create a new D-Bus error message from a 1037 * dbus error structure 1038 * @message: The original request message for which the error is a reply 1039 * @error: The error containing a name and a descriptive error cause 1040 * @fallback_name: A generic error name if @error was not set 1041 * @fallback_string: A generic error string if @error was not set 1042 * Returns: A new D-Bus error message 1043 * 1044 * Given a DBusMessage structure, creates a new D-Bus error message using 1045 * the error name and string contained in that structure. 1046 */ 1047DBusMessage * wpas_dbus_reply_new_from_error(DBusMessage *message, 1048 DBusError *error, 1049 const char *fallback_name, 1050 const char *fallback_string) 1051{ 1052 if (error && error->name && error->message) { 1053 return dbus_message_new_error(message, error->name, 1054 error->message); 1055 } 1056 if (fallback_name && fallback_string) { 1057 return dbus_message_new_error(message, fallback_name, 1058 fallback_string); 1059 } 1060 return NULL; 1061} |
|