13ff40c12SJohn Marino /*
23ff40c12SJohn Marino * WPA Supplicant / dbus-based control interface
33ff40c12SJohn Marino * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
43ff40c12SJohn Marino *
53ff40c12SJohn Marino * This software may be distributed under the terms of the BSD license.
63ff40c12SJohn Marino * See README for more details.
73ff40c12SJohn Marino */
83ff40c12SJohn Marino
93ff40c12SJohn Marino #include "includes.h"
103ff40c12SJohn Marino #include <dbus/dbus.h>
113ff40c12SJohn Marino
123ff40c12SJohn Marino #include "common.h"
133ff40c12SJohn Marino #include "wpabuf.h"
143ff40c12SJohn Marino #include "dbus_dict_helpers.h"
153ff40c12SJohn Marino
163ff40c12SJohn Marino
173ff40c12SJohn Marino /**
183ff40c12SJohn Marino * Start a dict in a dbus message. Should be paired with a call to
193ff40c12SJohn Marino * wpa_dbus_dict_close_write().
203ff40c12SJohn Marino *
213ff40c12SJohn Marino * @param iter A valid dbus message iterator
223ff40c12SJohn Marino * @param iter_dict (out) A dict iterator to pass to further dict functions
233ff40c12SJohn Marino * @return TRUE on success, FALSE on failure
243ff40c12SJohn Marino *
253ff40c12SJohn Marino */
wpa_dbus_dict_open_write(DBusMessageIter * iter,DBusMessageIter * iter_dict)263ff40c12SJohn Marino dbus_bool_t wpa_dbus_dict_open_write(DBusMessageIter *iter,
273ff40c12SJohn Marino DBusMessageIter *iter_dict)
283ff40c12SJohn Marino {
293ff40c12SJohn Marino dbus_bool_t result;
303ff40c12SJohn Marino
313ff40c12SJohn Marino if (!iter || !iter_dict)
323ff40c12SJohn Marino return FALSE;
333ff40c12SJohn Marino
343ff40c12SJohn Marino result = dbus_message_iter_open_container(
353ff40c12SJohn Marino iter,
363ff40c12SJohn Marino DBUS_TYPE_ARRAY,
373ff40c12SJohn Marino DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
383ff40c12SJohn Marino DBUS_TYPE_STRING_AS_STRING
393ff40c12SJohn Marino DBUS_TYPE_VARIANT_AS_STRING
403ff40c12SJohn Marino DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
413ff40c12SJohn Marino iter_dict);
423ff40c12SJohn Marino return result;
433ff40c12SJohn Marino }
443ff40c12SJohn Marino
453ff40c12SJohn Marino
463ff40c12SJohn Marino /**
473ff40c12SJohn Marino * End a dict element in a dbus message. Should be paired with
483ff40c12SJohn Marino * a call to wpa_dbus_dict_open_write().
493ff40c12SJohn Marino *
503ff40c12SJohn Marino * @param iter valid dbus message iterator, same as passed to
513ff40c12SJohn Marino * wpa_dbus_dict_open_write()
523ff40c12SJohn Marino * @param iter_dict a dbus dict iterator returned from
533ff40c12SJohn Marino * wpa_dbus_dict_open_write()
543ff40c12SJohn Marino * @return TRUE on success, FALSE on failure
553ff40c12SJohn Marino *
563ff40c12SJohn Marino */
wpa_dbus_dict_close_write(DBusMessageIter * iter,DBusMessageIter * iter_dict)573ff40c12SJohn Marino dbus_bool_t wpa_dbus_dict_close_write(DBusMessageIter *iter,
583ff40c12SJohn Marino DBusMessageIter *iter_dict)
593ff40c12SJohn Marino {
603ff40c12SJohn Marino if (!iter || !iter_dict)
613ff40c12SJohn Marino return FALSE;
623ff40c12SJohn Marino
633ff40c12SJohn Marino return dbus_message_iter_close_container(iter, iter_dict);
643ff40c12SJohn Marino }
653ff40c12SJohn Marino
663ff40c12SJohn Marino
wpa_dbus_type_as_string(const int type)673ff40c12SJohn Marino const char * wpa_dbus_type_as_string(const int type)
683ff40c12SJohn Marino {
693ff40c12SJohn Marino switch (type) {
703ff40c12SJohn Marino case DBUS_TYPE_BYTE:
713ff40c12SJohn Marino return DBUS_TYPE_BYTE_AS_STRING;
723ff40c12SJohn Marino case DBUS_TYPE_BOOLEAN:
733ff40c12SJohn Marino return DBUS_TYPE_BOOLEAN_AS_STRING;
743ff40c12SJohn Marino case DBUS_TYPE_INT16:
753ff40c12SJohn Marino return DBUS_TYPE_INT16_AS_STRING;
763ff40c12SJohn Marino case DBUS_TYPE_UINT16:
773ff40c12SJohn Marino return DBUS_TYPE_UINT16_AS_STRING;
783ff40c12SJohn Marino case DBUS_TYPE_INT32:
793ff40c12SJohn Marino return DBUS_TYPE_INT32_AS_STRING;
803ff40c12SJohn Marino case DBUS_TYPE_UINT32:
813ff40c12SJohn Marino return DBUS_TYPE_UINT32_AS_STRING;
823ff40c12SJohn Marino case DBUS_TYPE_INT64:
833ff40c12SJohn Marino return DBUS_TYPE_INT64_AS_STRING;
843ff40c12SJohn Marino case DBUS_TYPE_UINT64:
853ff40c12SJohn Marino return DBUS_TYPE_UINT64_AS_STRING;
863ff40c12SJohn Marino case DBUS_TYPE_DOUBLE:
873ff40c12SJohn Marino return DBUS_TYPE_DOUBLE_AS_STRING;
883ff40c12SJohn Marino case DBUS_TYPE_STRING:
893ff40c12SJohn Marino return DBUS_TYPE_STRING_AS_STRING;
903ff40c12SJohn Marino case DBUS_TYPE_OBJECT_PATH:
913ff40c12SJohn Marino return DBUS_TYPE_OBJECT_PATH_AS_STRING;
923ff40c12SJohn Marino case DBUS_TYPE_ARRAY:
933ff40c12SJohn Marino return DBUS_TYPE_ARRAY_AS_STRING;
943ff40c12SJohn Marino default:
953ff40c12SJohn Marino return NULL;
963ff40c12SJohn Marino }
973ff40c12SJohn Marino }
983ff40c12SJohn Marino
993ff40c12SJohn Marino
_wpa_dbus_add_dict_entry_start(DBusMessageIter * iter_dict,DBusMessageIter * iter_dict_entry,const char * key,const int value_type)1003ff40c12SJohn Marino static dbus_bool_t _wpa_dbus_add_dict_entry_start(
1013ff40c12SJohn Marino DBusMessageIter *iter_dict, DBusMessageIter *iter_dict_entry,
1023ff40c12SJohn Marino const char *key, const int value_type)
1033ff40c12SJohn Marino {
1043ff40c12SJohn Marino if (!dbus_message_iter_open_container(iter_dict,
1053ff40c12SJohn Marino DBUS_TYPE_DICT_ENTRY, NULL,
1063ff40c12SJohn Marino iter_dict_entry))
1073ff40c12SJohn Marino return FALSE;
1083ff40c12SJohn Marino
109*a1157835SDaniel Fojt return dbus_message_iter_append_basic(iter_dict_entry, DBUS_TYPE_STRING,
110*a1157835SDaniel Fojt &key);
1113ff40c12SJohn Marino }
1123ff40c12SJohn Marino
1133ff40c12SJohn Marino
_wpa_dbus_add_dict_entry_end(DBusMessageIter * iter_dict,DBusMessageIter * iter_dict_entry,DBusMessageIter * iter_dict_val)1143ff40c12SJohn Marino static dbus_bool_t _wpa_dbus_add_dict_entry_end(
1153ff40c12SJohn Marino DBusMessageIter *iter_dict, DBusMessageIter *iter_dict_entry,
1163ff40c12SJohn Marino DBusMessageIter *iter_dict_val)
1173ff40c12SJohn Marino {
1183ff40c12SJohn Marino if (!dbus_message_iter_close_container(iter_dict_entry, iter_dict_val))
1193ff40c12SJohn Marino return FALSE;
1203ff40c12SJohn Marino
121*a1157835SDaniel Fojt return dbus_message_iter_close_container(iter_dict, iter_dict_entry);
1223ff40c12SJohn Marino }
1233ff40c12SJohn Marino
1243ff40c12SJohn Marino
_wpa_dbus_add_dict_entry_basic(DBusMessageIter * iter_dict,const char * key,const int value_type,const void * value)1253ff40c12SJohn Marino static dbus_bool_t _wpa_dbus_add_dict_entry_basic(DBusMessageIter *iter_dict,
1263ff40c12SJohn Marino const char *key,
1273ff40c12SJohn Marino const int value_type,
1283ff40c12SJohn Marino const void *value)
1293ff40c12SJohn Marino {
1303ff40c12SJohn Marino DBusMessageIter iter_dict_entry, iter_dict_val;
1313ff40c12SJohn Marino const char *type_as_string = NULL;
1323ff40c12SJohn Marino
1333ff40c12SJohn Marino if (key == NULL)
1343ff40c12SJohn Marino return FALSE;
1353ff40c12SJohn Marino
1363ff40c12SJohn Marino type_as_string = wpa_dbus_type_as_string(value_type);
1373ff40c12SJohn Marino if (!type_as_string)
1383ff40c12SJohn Marino return FALSE;
1393ff40c12SJohn Marino
1403ff40c12SJohn Marino if (!_wpa_dbus_add_dict_entry_start(iter_dict, &iter_dict_entry,
141*a1157835SDaniel Fojt key, value_type) ||
142*a1157835SDaniel Fojt !dbus_message_iter_open_container(&iter_dict_entry,
1433ff40c12SJohn Marino DBUS_TYPE_VARIANT,
144*a1157835SDaniel Fojt type_as_string, &iter_dict_val) ||
145*a1157835SDaniel Fojt !dbus_message_iter_append_basic(&iter_dict_val, value_type, value))
1463ff40c12SJohn Marino return FALSE;
1473ff40c12SJohn Marino
148*a1157835SDaniel Fojt return _wpa_dbus_add_dict_entry_end(iter_dict, &iter_dict_entry,
149*a1157835SDaniel Fojt &iter_dict_val);
1503ff40c12SJohn Marino }
1513ff40c12SJohn Marino
1523ff40c12SJohn Marino
_wpa_dbus_add_dict_entry_byte_array(DBusMessageIter * iter_dict,const char * key,const char * value,const dbus_uint32_t value_len)1533ff40c12SJohn Marino static dbus_bool_t _wpa_dbus_add_dict_entry_byte_array(
1543ff40c12SJohn Marino DBusMessageIter *iter_dict, const char *key,
1553ff40c12SJohn Marino const char *value, const dbus_uint32_t value_len)
1563ff40c12SJohn Marino {
1573ff40c12SJohn Marino DBusMessageIter iter_dict_entry, iter_dict_val, iter_array;
1583ff40c12SJohn Marino dbus_uint32_t i;
1593ff40c12SJohn Marino
1603ff40c12SJohn Marino if (!_wpa_dbus_add_dict_entry_start(iter_dict, &iter_dict_entry,
161*a1157835SDaniel Fojt key, DBUS_TYPE_ARRAY) ||
162*a1157835SDaniel Fojt !dbus_message_iter_open_container(&iter_dict_entry,
1633ff40c12SJohn Marino DBUS_TYPE_VARIANT,
1643ff40c12SJohn Marino DBUS_TYPE_ARRAY_AS_STRING
1653ff40c12SJohn Marino DBUS_TYPE_BYTE_AS_STRING,
166*a1157835SDaniel Fojt &iter_dict_val) ||
167*a1157835SDaniel Fojt !dbus_message_iter_open_container(&iter_dict_val, DBUS_TYPE_ARRAY,
1683ff40c12SJohn Marino DBUS_TYPE_BYTE_AS_STRING,
1693ff40c12SJohn Marino &iter_array))
1703ff40c12SJohn Marino return FALSE;
1713ff40c12SJohn Marino
1723ff40c12SJohn Marino for (i = 0; i < value_len; i++) {
1733ff40c12SJohn Marino if (!dbus_message_iter_append_basic(&iter_array,
1743ff40c12SJohn Marino DBUS_TYPE_BYTE,
1753ff40c12SJohn Marino &(value[i])))
1763ff40c12SJohn Marino return FALSE;
1773ff40c12SJohn Marino }
1783ff40c12SJohn Marino
1793ff40c12SJohn Marino if (!dbus_message_iter_close_container(&iter_dict_val, &iter_array))
1803ff40c12SJohn Marino return FALSE;
1813ff40c12SJohn Marino
182*a1157835SDaniel Fojt return _wpa_dbus_add_dict_entry_end(iter_dict, &iter_dict_entry,
183*a1157835SDaniel Fojt &iter_dict_val);
1843ff40c12SJohn Marino }
1853ff40c12SJohn Marino
1863ff40c12SJohn Marino
1873ff40c12SJohn Marino /**
1883ff40c12SJohn Marino * Add a string entry to the dict.
1893ff40c12SJohn Marino *
1903ff40c12SJohn Marino * @param iter_dict A valid DBusMessageIter returned from
1913ff40c12SJohn Marino * wpa_dbus_dict_open_write()
1923ff40c12SJohn Marino * @param key The key of the dict item
1933ff40c12SJohn Marino * @param value The string value
1943ff40c12SJohn Marino * @return TRUE on success, FALSE on failure
1953ff40c12SJohn Marino *
1963ff40c12SJohn Marino */
wpa_dbus_dict_append_string(DBusMessageIter * iter_dict,const char * key,const char * value)1973ff40c12SJohn Marino dbus_bool_t wpa_dbus_dict_append_string(DBusMessageIter *iter_dict,
1983ff40c12SJohn Marino const char *key, const char *value)
1993ff40c12SJohn Marino {
2003ff40c12SJohn Marino if (!value)
2013ff40c12SJohn Marino return FALSE;
2023ff40c12SJohn Marino return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_STRING,
2033ff40c12SJohn Marino &value);
2043ff40c12SJohn Marino }
2053ff40c12SJohn Marino
2063ff40c12SJohn Marino
2073ff40c12SJohn Marino /**
2083ff40c12SJohn Marino * Add a boolean entry to the dict.
2093ff40c12SJohn Marino *
2103ff40c12SJohn Marino * @param iter_dict A valid DBusMessageIter returned from
2113ff40c12SJohn Marino * wpa_dbus_dict_open_write()
2123ff40c12SJohn Marino * @param key The key of the dict item
2133ff40c12SJohn Marino * @param value The boolean value
2143ff40c12SJohn Marino * @return TRUE on success, FALSE on failure
2153ff40c12SJohn Marino *
2163ff40c12SJohn Marino */
wpa_dbus_dict_append_bool(DBusMessageIter * iter_dict,const char * key,const dbus_bool_t value)2173ff40c12SJohn Marino dbus_bool_t wpa_dbus_dict_append_bool(DBusMessageIter *iter_dict,
2183ff40c12SJohn Marino const char *key, const dbus_bool_t value)
2193ff40c12SJohn Marino {
2203ff40c12SJohn Marino return _wpa_dbus_add_dict_entry_basic(iter_dict, key,
2213ff40c12SJohn Marino DBUS_TYPE_BOOLEAN, &value);
2223ff40c12SJohn Marino }
2233ff40c12SJohn Marino
2243ff40c12SJohn Marino
2253ff40c12SJohn Marino /**
2263ff40c12SJohn Marino * Add a 16-bit signed integer entry to the dict.
2273ff40c12SJohn Marino *
2283ff40c12SJohn Marino * @param iter_dict A valid DBusMessageIter returned from
2293ff40c12SJohn Marino * wpa_dbus_dict_open_write()
2303ff40c12SJohn Marino * @param key The key of the dict item
2313ff40c12SJohn Marino * @param value The 16-bit signed integer value
2323ff40c12SJohn Marino * @return TRUE on success, FALSE on failure
2333ff40c12SJohn Marino *
2343ff40c12SJohn Marino */
wpa_dbus_dict_append_int16(DBusMessageIter * iter_dict,const char * key,const dbus_int16_t value)2353ff40c12SJohn Marino dbus_bool_t wpa_dbus_dict_append_int16(DBusMessageIter *iter_dict,
2363ff40c12SJohn Marino const char *key,
2373ff40c12SJohn Marino const dbus_int16_t value)
2383ff40c12SJohn Marino {
2393ff40c12SJohn Marino return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_INT16,
2403ff40c12SJohn Marino &value);
2413ff40c12SJohn Marino }
2423ff40c12SJohn Marino
2433ff40c12SJohn Marino
2443ff40c12SJohn Marino /**
2453ff40c12SJohn Marino * Add a 16-bit unsigned integer entry to the dict.
2463ff40c12SJohn Marino *
2473ff40c12SJohn Marino * @param iter_dict A valid DBusMessageIter returned from
2483ff40c12SJohn Marino * wpa_dbus_dict_open_write()
2493ff40c12SJohn Marino * @param key The key of the dict item
2503ff40c12SJohn Marino * @param value The 16-bit unsigned integer value
2513ff40c12SJohn Marino * @return TRUE on success, FALSE on failure
2523ff40c12SJohn Marino *
2533ff40c12SJohn Marino */
wpa_dbus_dict_append_uint16(DBusMessageIter * iter_dict,const char * key,const dbus_uint16_t value)2543ff40c12SJohn Marino dbus_bool_t wpa_dbus_dict_append_uint16(DBusMessageIter *iter_dict,
2553ff40c12SJohn Marino const char *key,
2563ff40c12SJohn Marino const dbus_uint16_t value)
2573ff40c12SJohn Marino {
2583ff40c12SJohn Marino return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_UINT16,
2593ff40c12SJohn Marino &value);
2603ff40c12SJohn Marino }
2613ff40c12SJohn Marino
2623ff40c12SJohn Marino
2633ff40c12SJohn Marino /**
2643ff40c12SJohn Marino * Add a 32-bit signed integer to the dict.
2653ff40c12SJohn Marino *
2663ff40c12SJohn Marino * @param iter_dict A valid DBusMessageIter returned from
2673ff40c12SJohn Marino * wpa_dbus_dict_open_write()
2683ff40c12SJohn Marino * @param key The key of the dict item
2693ff40c12SJohn Marino * @param value The 32-bit signed integer value
2703ff40c12SJohn Marino * @return TRUE on success, FALSE on failure
2713ff40c12SJohn Marino *
2723ff40c12SJohn Marino */
wpa_dbus_dict_append_int32(DBusMessageIter * iter_dict,const char * key,const dbus_int32_t value)2733ff40c12SJohn Marino dbus_bool_t wpa_dbus_dict_append_int32(DBusMessageIter *iter_dict,
2743ff40c12SJohn Marino const char *key,
2753ff40c12SJohn Marino const dbus_int32_t value)
2763ff40c12SJohn Marino {
2773ff40c12SJohn Marino return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_INT32,
2783ff40c12SJohn Marino &value);
2793ff40c12SJohn Marino }
2803ff40c12SJohn Marino
2813ff40c12SJohn Marino
2823ff40c12SJohn Marino /**
2833ff40c12SJohn Marino * Add a 32-bit unsigned integer entry to the dict.
2843ff40c12SJohn Marino *
2853ff40c12SJohn Marino * @param iter_dict A valid DBusMessageIter returned from
2863ff40c12SJohn Marino * wpa_dbus_dict_open_write()
2873ff40c12SJohn Marino * @param key The key of the dict item
2883ff40c12SJohn Marino * @param value The 32-bit unsigned integer value
2893ff40c12SJohn Marino * @return TRUE on success, FALSE on failure
2903ff40c12SJohn Marino *
2913ff40c12SJohn Marino */
wpa_dbus_dict_append_uint32(DBusMessageIter * iter_dict,const char * key,const dbus_uint32_t value)2923ff40c12SJohn Marino dbus_bool_t wpa_dbus_dict_append_uint32(DBusMessageIter *iter_dict,
2933ff40c12SJohn Marino const char *key,
2943ff40c12SJohn Marino const dbus_uint32_t value)
2953ff40c12SJohn Marino {
2963ff40c12SJohn Marino return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_UINT32,
2973ff40c12SJohn Marino &value);
2983ff40c12SJohn Marino }
2993ff40c12SJohn Marino
3003ff40c12SJohn Marino
3013ff40c12SJohn Marino /**
3023ff40c12SJohn Marino * Add a DBus object path entry to the dict.
3033ff40c12SJohn Marino *
3043ff40c12SJohn Marino * @param iter_dict A valid DBusMessageIter returned from
3053ff40c12SJohn Marino * wpa_dbus_dict_open_write()
3063ff40c12SJohn Marino * @param key The key of the dict item
3073ff40c12SJohn Marino * @param value The DBus object path value
3083ff40c12SJohn Marino * @return TRUE on success, FALSE on failure
3093ff40c12SJohn Marino *
3103ff40c12SJohn Marino */
wpa_dbus_dict_append_object_path(DBusMessageIter * iter_dict,const char * key,const char * value)3113ff40c12SJohn Marino dbus_bool_t wpa_dbus_dict_append_object_path(DBusMessageIter *iter_dict,
3123ff40c12SJohn Marino const char *key,
3133ff40c12SJohn Marino const char *value)
3143ff40c12SJohn Marino {
3153ff40c12SJohn Marino if (!value)
3163ff40c12SJohn Marino return FALSE;
3173ff40c12SJohn Marino return _wpa_dbus_add_dict_entry_basic(iter_dict, key,
3183ff40c12SJohn Marino DBUS_TYPE_OBJECT_PATH, &value);
3193ff40c12SJohn Marino }
3203ff40c12SJohn Marino
3213ff40c12SJohn Marino
3223ff40c12SJohn Marino /**
3233ff40c12SJohn Marino * Add a byte array entry to the dict.
3243ff40c12SJohn Marino *
3253ff40c12SJohn Marino * @param iter_dict A valid DBusMessageIter returned from
3263ff40c12SJohn Marino * wpa_dbus_dict_open_write()
3273ff40c12SJohn Marino * @param key The key of the dict item
3283ff40c12SJohn Marino * @param value The byte array
3293ff40c12SJohn Marino * @param value_len The length of the byte array, in bytes
3303ff40c12SJohn Marino * @return TRUE on success, FALSE on failure
3313ff40c12SJohn Marino *
3323ff40c12SJohn Marino */
wpa_dbus_dict_append_byte_array(DBusMessageIter * iter_dict,const char * key,const char * value,const dbus_uint32_t value_len)3333ff40c12SJohn Marino dbus_bool_t wpa_dbus_dict_append_byte_array(DBusMessageIter *iter_dict,
3343ff40c12SJohn Marino const char *key,
3353ff40c12SJohn Marino const char *value,
3363ff40c12SJohn Marino const dbus_uint32_t value_len)
3373ff40c12SJohn Marino {
338*a1157835SDaniel Fojt if (!key || (!value && value_len != 0))
3393ff40c12SJohn Marino return FALSE;
3403ff40c12SJohn Marino return _wpa_dbus_add_dict_entry_byte_array(iter_dict, key, value,
3413ff40c12SJohn Marino value_len);
3423ff40c12SJohn Marino }
3433ff40c12SJohn Marino
3443ff40c12SJohn Marino
3453ff40c12SJohn Marino /**
3463ff40c12SJohn Marino * Begin an array entry in the dict
3473ff40c12SJohn Marino *
3483ff40c12SJohn Marino * @param iter_dict A valid DBusMessageIter returned from
3493ff40c12SJohn Marino * wpa_dbus_dict_open_write()
3503ff40c12SJohn Marino * @param key The key of the dict item
3513ff40c12SJohn Marino * @param type The type of the contained data
3523ff40c12SJohn Marino * @param iter_dict_entry A private DBusMessageIter provided by the caller to
3533ff40c12SJohn Marino * be passed to wpa_dbus_dict_end_string_array()
3543ff40c12SJohn Marino * @param iter_dict_val A private DBusMessageIter provided by the caller to
3553ff40c12SJohn Marino * be passed to wpa_dbus_dict_end_string_array()
3563ff40c12SJohn Marino * @param iter_array On return, the DBusMessageIter to be passed to
3573ff40c12SJohn Marino * wpa_dbus_dict_string_array_add_element()
3583ff40c12SJohn Marino * @return TRUE on success, FALSE on failure
3593ff40c12SJohn Marino *
3603ff40c12SJohn Marino */
wpa_dbus_dict_begin_array(DBusMessageIter * iter_dict,const char * key,const char * type,DBusMessageIter * iter_dict_entry,DBusMessageIter * iter_dict_val,DBusMessageIter * iter_array)3613ff40c12SJohn Marino dbus_bool_t wpa_dbus_dict_begin_array(DBusMessageIter *iter_dict,
3623ff40c12SJohn Marino const char *key, const char *type,
3633ff40c12SJohn Marino DBusMessageIter *iter_dict_entry,
3643ff40c12SJohn Marino DBusMessageIter *iter_dict_val,
3653ff40c12SJohn Marino DBusMessageIter *iter_array)
3663ff40c12SJohn Marino {
3673ff40c12SJohn Marino char array_type[10];
3683ff40c12SJohn Marino int err;
3693ff40c12SJohn Marino
3703ff40c12SJohn Marino err = os_snprintf(array_type, sizeof(array_type),
3713ff40c12SJohn Marino DBUS_TYPE_ARRAY_AS_STRING "%s",
3723ff40c12SJohn Marino type);
373*a1157835SDaniel Fojt if (os_snprintf_error(sizeof(array_type), err))
3743ff40c12SJohn Marino return FALSE;
3753ff40c12SJohn Marino
376*a1157835SDaniel Fojt if (!iter_dict || !iter_dict_entry || !iter_dict_val || !iter_array ||
377*a1157835SDaniel Fojt !_wpa_dbus_add_dict_entry_start(iter_dict, iter_dict_entry,
378*a1157835SDaniel Fojt key, DBUS_TYPE_ARRAY) ||
379*a1157835SDaniel Fojt !dbus_message_iter_open_container(iter_dict_entry,
3803ff40c12SJohn Marino DBUS_TYPE_VARIANT,
3813ff40c12SJohn Marino array_type,
3823ff40c12SJohn Marino iter_dict_val))
3833ff40c12SJohn Marino return FALSE;
3843ff40c12SJohn Marino
385*a1157835SDaniel Fojt return dbus_message_iter_open_container(iter_dict_val, DBUS_TYPE_ARRAY,
386*a1157835SDaniel Fojt type, iter_array);
3873ff40c12SJohn Marino }
3883ff40c12SJohn Marino
3893ff40c12SJohn Marino
wpa_dbus_dict_begin_string_array(DBusMessageIter * iter_dict,const char * key,DBusMessageIter * iter_dict_entry,DBusMessageIter * iter_dict_val,DBusMessageIter * iter_array)3903ff40c12SJohn Marino dbus_bool_t wpa_dbus_dict_begin_string_array(DBusMessageIter *iter_dict,
3913ff40c12SJohn Marino const char *key,
3923ff40c12SJohn Marino DBusMessageIter *iter_dict_entry,
3933ff40c12SJohn Marino DBusMessageIter *iter_dict_val,
3943ff40c12SJohn Marino DBusMessageIter *iter_array)
3953ff40c12SJohn Marino {
3963ff40c12SJohn Marino return wpa_dbus_dict_begin_array(
3973ff40c12SJohn Marino iter_dict, key,
3983ff40c12SJohn Marino DBUS_TYPE_STRING_AS_STRING,
3993ff40c12SJohn Marino iter_dict_entry, iter_dict_val, iter_array);
4003ff40c12SJohn Marino }
4013ff40c12SJohn Marino
4023ff40c12SJohn Marino
4033ff40c12SJohn Marino /**
4043ff40c12SJohn Marino * Add a single string element to a string array dict entry
4053ff40c12SJohn Marino *
4063ff40c12SJohn Marino * @param iter_array A valid DBusMessageIter returned from
4073ff40c12SJohn Marino * wpa_dbus_dict_begin_string_array()'s
4083ff40c12SJohn Marino * iter_array parameter
4093ff40c12SJohn Marino * @param elem The string element to be added to the dict entry's string array
4103ff40c12SJohn Marino * @return TRUE on success, FALSE on failure
4113ff40c12SJohn Marino *
4123ff40c12SJohn Marino */
wpa_dbus_dict_string_array_add_element(DBusMessageIter * iter_array,const char * elem)4133ff40c12SJohn Marino dbus_bool_t wpa_dbus_dict_string_array_add_element(DBusMessageIter *iter_array,
4143ff40c12SJohn Marino const char *elem)
4153ff40c12SJohn Marino {
4163ff40c12SJohn Marino if (!iter_array || !elem)
4173ff40c12SJohn Marino return FALSE;
4183ff40c12SJohn Marino
4193ff40c12SJohn Marino return dbus_message_iter_append_basic(iter_array, DBUS_TYPE_STRING,
4203ff40c12SJohn Marino &elem);
4213ff40c12SJohn Marino }
4223ff40c12SJohn Marino
4233ff40c12SJohn Marino
4243ff40c12SJohn Marino /**
4253ff40c12SJohn Marino * Add a single byte array element to a string array dict entry
4263ff40c12SJohn Marino *
4273ff40c12SJohn Marino * @param iter_array A valid DBusMessageIter returned from
4283ff40c12SJohn Marino * wpa_dbus_dict_begin_array()'s iter_array
4293ff40c12SJohn Marino * parameter -- note that wpa_dbus_dict_begin_array()
4303ff40c12SJohn Marino * must have been called with "ay" as the type
4313ff40c12SJohn Marino * @param value The data to be added to the dict entry's array
4323ff40c12SJohn Marino * @param value_len The length of the data
4333ff40c12SJohn Marino * @return TRUE on success, FALSE on failure
4343ff40c12SJohn Marino *
4353ff40c12SJohn Marino */
wpa_dbus_dict_bin_array_add_element(DBusMessageIter * iter_array,const u8 * value,size_t value_len)4363ff40c12SJohn Marino dbus_bool_t wpa_dbus_dict_bin_array_add_element(DBusMessageIter *iter_array,
4373ff40c12SJohn Marino const u8 *value,
4383ff40c12SJohn Marino size_t value_len)
4393ff40c12SJohn Marino {
4403ff40c12SJohn Marino DBusMessageIter iter_bytes;
4413ff40c12SJohn Marino size_t i;
4423ff40c12SJohn Marino
443*a1157835SDaniel Fojt if (!iter_array || !value ||
444*a1157835SDaniel Fojt !dbus_message_iter_open_container(iter_array, DBUS_TYPE_ARRAY,
4453ff40c12SJohn Marino DBUS_TYPE_BYTE_AS_STRING,
4463ff40c12SJohn Marino &iter_bytes))
4473ff40c12SJohn Marino return FALSE;
4483ff40c12SJohn Marino
4493ff40c12SJohn Marino for (i = 0; i < value_len; i++) {
4503ff40c12SJohn Marino if (!dbus_message_iter_append_basic(&iter_bytes,
4513ff40c12SJohn Marino DBUS_TYPE_BYTE,
4523ff40c12SJohn Marino &(value[i])))
4533ff40c12SJohn Marino return FALSE;
4543ff40c12SJohn Marino }
4553ff40c12SJohn Marino
456*a1157835SDaniel Fojt return dbus_message_iter_close_container(iter_array, &iter_bytes);
4573ff40c12SJohn Marino }
4583ff40c12SJohn Marino
4593ff40c12SJohn Marino
4603ff40c12SJohn Marino /**
4613ff40c12SJohn Marino * End an array dict entry
4623ff40c12SJohn Marino *
4633ff40c12SJohn Marino * @param iter_dict A valid DBusMessageIter returned from
4643ff40c12SJohn Marino * wpa_dbus_dict_open_write()
4653ff40c12SJohn Marino * @param iter_dict_entry A private DBusMessageIter returned from
4663ff40c12SJohn Marino * wpa_dbus_dict_begin_string_array() or
4673ff40c12SJohn Marino * wpa_dbus_dict_begin_array()
4683ff40c12SJohn Marino * @param iter_dict_val A private DBusMessageIter returned from
4693ff40c12SJohn Marino * wpa_dbus_dict_begin_string_array() or
4703ff40c12SJohn Marino * wpa_dbus_dict_begin_array()
4713ff40c12SJohn Marino * @param iter_array A DBusMessageIter returned from
4723ff40c12SJohn Marino * wpa_dbus_dict_begin_string_array() or
4733ff40c12SJohn Marino * wpa_dbus_dict_begin_array()
4743ff40c12SJohn Marino * @return TRUE on success, FALSE on failure
4753ff40c12SJohn Marino *
4763ff40c12SJohn Marino */
wpa_dbus_dict_end_array(DBusMessageIter * iter_dict,DBusMessageIter * iter_dict_entry,DBusMessageIter * iter_dict_val,DBusMessageIter * iter_array)4773ff40c12SJohn Marino dbus_bool_t wpa_dbus_dict_end_array(DBusMessageIter *iter_dict,
4783ff40c12SJohn Marino DBusMessageIter *iter_dict_entry,
4793ff40c12SJohn Marino DBusMessageIter *iter_dict_val,
4803ff40c12SJohn Marino DBusMessageIter *iter_array)
4813ff40c12SJohn Marino {
482*a1157835SDaniel Fojt if (!iter_dict || !iter_dict_entry || !iter_dict_val || !iter_array ||
483*a1157835SDaniel Fojt !dbus_message_iter_close_container(iter_dict_val, iter_array))
4843ff40c12SJohn Marino return FALSE;
4853ff40c12SJohn Marino
486*a1157835SDaniel Fojt return _wpa_dbus_add_dict_entry_end(iter_dict, iter_dict_entry,
487*a1157835SDaniel Fojt iter_dict_val);
4883ff40c12SJohn Marino }
4893ff40c12SJohn Marino
4903ff40c12SJohn Marino
4913ff40c12SJohn Marino /**
4923ff40c12SJohn Marino * Convenience function to add an entire string array to the dict.
4933ff40c12SJohn Marino *
4943ff40c12SJohn Marino * @param iter_dict A valid DBusMessageIter returned from
4953ff40c12SJohn Marino * wpa_dbus_dict_open_write()
4963ff40c12SJohn Marino * @param key The key of the dict item
4973ff40c12SJohn Marino * @param items The array of strings
4983ff40c12SJohn Marino * @param num_items The number of strings in the array
4993ff40c12SJohn Marino * @return TRUE on success, FALSE on failure
5003ff40c12SJohn Marino *
5013ff40c12SJohn Marino */
wpa_dbus_dict_append_string_array(DBusMessageIter * iter_dict,const char * key,const char ** items,const dbus_uint32_t num_items)5023ff40c12SJohn Marino dbus_bool_t wpa_dbus_dict_append_string_array(DBusMessageIter *iter_dict,
5033ff40c12SJohn Marino const char *key,
5043ff40c12SJohn Marino const char **items,
5053ff40c12SJohn Marino const dbus_uint32_t num_items)
5063ff40c12SJohn Marino {
5073ff40c12SJohn Marino DBusMessageIter iter_dict_entry, iter_dict_val, iter_array;
5083ff40c12SJohn Marino dbus_uint32_t i;
5093ff40c12SJohn Marino
510*a1157835SDaniel Fojt if (!key || (!items && num_items != 0) ||
511*a1157835SDaniel Fojt !wpa_dbus_dict_begin_string_array(iter_dict, key,
5123ff40c12SJohn Marino &iter_dict_entry, &iter_dict_val,
5133ff40c12SJohn Marino &iter_array))
5143ff40c12SJohn Marino return FALSE;
5153ff40c12SJohn Marino
5163ff40c12SJohn Marino for (i = 0; i < num_items; i++) {
5173ff40c12SJohn Marino if (!wpa_dbus_dict_string_array_add_element(&iter_array,
5183ff40c12SJohn Marino items[i]))
5193ff40c12SJohn Marino return FALSE;
5203ff40c12SJohn Marino }
5213ff40c12SJohn Marino
522*a1157835SDaniel Fojt return wpa_dbus_dict_end_string_array(iter_dict, &iter_dict_entry,
523*a1157835SDaniel Fojt &iter_dict_val, &iter_array);
5243ff40c12SJohn Marino }
5253ff40c12SJohn Marino
5263ff40c12SJohn Marino
5273ff40c12SJohn Marino /**
5283ff40c12SJohn Marino * Convenience function to add an wpabuf binary array to the dict.
5293ff40c12SJohn Marino *
5303ff40c12SJohn Marino * @param iter_dict A valid DBusMessageIter returned from
5313ff40c12SJohn Marino * wpa_dbus_dict_open_write()
5323ff40c12SJohn Marino * @param key The key of the dict item
5333ff40c12SJohn Marino * @param items The array of wpabuf structures
5343ff40c12SJohn Marino * @param num_items The number of strings in the array
5353ff40c12SJohn Marino * @return TRUE on success, FALSE on failure
5363ff40c12SJohn Marino *
5373ff40c12SJohn Marino */
wpa_dbus_dict_append_wpabuf_array(DBusMessageIter * iter_dict,const char * key,const struct wpabuf ** items,const dbus_uint32_t num_items)5383ff40c12SJohn Marino dbus_bool_t wpa_dbus_dict_append_wpabuf_array(DBusMessageIter *iter_dict,
5393ff40c12SJohn Marino const char *key,
5403ff40c12SJohn Marino const struct wpabuf **items,
5413ff40c12SJohn Marino const dbus_uint32_t num_items)
5423ff40c12SJohn Marino {
5433ff40c12SJohn Marino DBusMessageIter iter_dict_entry, iter_dict_val, iter_array;
5443ff40c12SJohn Marino dbus_uint32_t i;
5453ff40c12SJohn Marino
546*a1157835SDaniel Fojt if (!key ||
547*a1157835SDaniel Fojt (!items && num_items != 0) ||
548*a1157835SDaniel Fojt !wpa_dbus_dict_begin_array(iter_dict, key,
5493ff40c12SJohn Marino DBUS_TYPE_ARRAY_AS_STRING
5503ff40c12SJohn Marino DBUS_TYPE_BYTE_AS_STRING,
5513ff40c12SJohn Marino &iter_dict_entry, &iter_dict_val,
5523ff40c12SJohn Marino &iter_array))
5533ff40c12SJohn Marino return FALSE;
5543ff40c12SJohn Marino
5553ff40c12SJohn Marino for (i = 0; i < num_items; i++) {
5563ff40c12SJohn Marino if (!wpa_dbus_dict_bin_array_add_element(&iter_array,
5573ff40c12SJohn Marino wpabuf_head(items[i]),
5583ff40c12SJohn Marino wpabuf_len(items[i])))
5593ff40c12SJohn Marino return FALSE;
5603ff40c12SJohn Marino }
5613ff40c12SJohn Marino
562*a1157835SDaniel Fojt return wpa_dbus_dict_end_array(iter_dict, &iter_dict_entry,
563*a1157835SDaniel Fojt &iter_dict_val, &iter_array);
5643ff40c12SJohn Marino }
5653ff40c12SJohn Marino
5663ff40c12SJohn Marino
5673ff40c12SJohn Marino /*****************************************************/
5683ff40c12SJohn Marino /* Stuff for reading dicts */
5693ff40c12SJohn Marino /*****************************************************/
5703ff40c12SJohn Marino
5713ff40c12SJohn Marino /**
5723ff40c12SJohn Marino * Start reading from a dbus dict.
5733ff40c12SJohn Marino *
5743ff40c12SJohn Marino * @param iter A valid DBusMessageIter pointing to the start of the dict
5753ff40c12SJohn Marino * @param iter_dict (out) A DBusMessageIter to be passed to
5763ff40c12SJohn Marino * wpa_dbus_dict_read_next_entry()
5773ff40c12SJohn Marino * @error on failure a descriptive error
5783ff40c12SJohn Marino * @return TRUE on success, FALSE on failure
5793ff40c12SJohn Marino *
5803ff40c12SJohn Marino */
wpa_dbus_dict_open_read(DBusMessageIter * iter,DBusMessageIter * iter_dict,DBusError * error)5813ff40c12SJohn Marino dbus_bool_t wpa_dbus_dict_open_read(DBusMessageIter *iter,
5823ff40c12SJohn Marino DBusMessageIter *iter_dict,
5833ff40c12SJohn Marino DBusError *error)
5843ff40c12SJohn Marino {
585*a1157835SDaniel Fojt int type;
586*a1157835SDaniel Fojt
587*a1157835SDaniel Fojt wpa_printf(MSG_MSGDUMP, "%s: start reading a dict entry", __func__);
5883ff40c12SJohn Marino if (!iter || !iter_dict) {
5893ff40c12SJohn Marino dbus_set_error_const(error, DBUS_ERROR_FAILED,
5903ff40c12SJohn Marino "[internal] missing message iterators");
5913ff40c12SJohn Marino return FALSE;
5923ff40c12SJohn Marino }
5933ff40c12SJohn Marino
594*a1157835SDaniel Fojt type = dbus_message_iter_get_arg_type(iter);
595*a1157835SDaniel Fojt if (type != DBUS_TYPE_ARRAY ||
5963ff40c12SJohn Marino dbus_message_iter_get_element_type(iter) != DBUS_TYPE_DICT_ENTRY) {
597*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG,
598*a1157835SDaniel Fojt "%s: unexpected message argument types (arg=%c element=%c)",
599*a1157835SDaniel Fojt __func__, type,
600*a1157835SDaniel Fojt type != DBUS_TYPE_ARRAY ? '?' :
601*a1157835SDaniel Fojt dbus_message_iter_get_element_type(iter));
6023ff40c12SJohn Marino dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
6033ff40c12SJohn Marino "unexpected message argument types");
6043ff40c12SJohn Marino return FALSE;
6053ff40c12SJohn Marino }
6063ff40c12SJohn Marino
6073ff40c12SJohn Marino dbus_message_iter_recurse(iter, iter_dict);
6083ff40c12SJohn Marino return TRUE;
6093ff40c12SJohn Marino }
6103ff40c12SJohn Marino
6113ff40c12SJohn Marino
6123ff40c12SJohn Marino #define BYTE_ARRAY_CHUNK_SIZE 34
6133ff40c12SJohn Marino #define BYTE_ARRAY_ITEM_SIZE (sizeof(char))
6143ff40c12SJohn Marino
_wpa_dbus_dict_entry_get_byte_array(DBusMessageIter * iter,struct wpa_dbus_dict_entry * entry)6153ff40c12SJohn Marino static dbus_bool_t _wpa_dbus_dict_entry_get_byte_array(
6163ff40c12SJohn Marino DBusMessageIter *iter, struct wpa_dbus_dict_entry *entry)
6173ff40c12SJohn Marino {
6183ff40c12SJohn Marino dbus_uint32_t count = 0;
6193ff40c12SJohn Marino dbus_bool_t success = FALSE;
6203ff40c12SJohn Marino char *buffer, *nbuffer;
6213ff40c12SJohn Marino
6223ff40c12SJohn Marino entry->bytearray_value = NULL;
6233ff40c12SJohn Marino entry->array_type = DBUS_TYPE_BYTE;
6243ff40c12SJohn Marino
6253ff40c12SJohn Marino buffer = os_calloc(BYTE_ARRAY_CHUNK_SIZE, BYTE_ARRAY_ITEM_SIZE);
6263ff40c12SJohn Marino if (!buffer)
6273ff40c12SJohn Marino return FALSE;
6283ff40c12SJohn Marino
6293ff40c12SJohn Marino entry->array_len = 0;
6303ff40c12SJohn Marino while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_BYTE) {
6313ff40c12SJohn Marino char byte;
6323ff40c12SJohn Marino
6333ff40c12SJohn Marino if ((count % BYTE_ARRAY_CHUNK_SIZE) == 0 && count != 0) {
6343ff40c12SJohn Marino nbuffer = os_realloc_array(
6353ff40c12SJohn Marino buffer, count + BYTE_ARRAY_CHUNK_SIZE,
6363ff40c12SJohn Marino BYTE_ARRAY_ITEM_SIZE);
6373ff40c12SJohn Marino if (nbuffer == NULL) {
6383ff40c12SJohn Marino os_free(buffer);
639*a1157835SDaniel Fojt wpa_printf(MSG_ERROR,
640*a1157835SDaniel Fojt "dbus: %s out of memory trying to retrieve the string array",
641*a1157835SDaniel Fojt __func__);
6423ff40c12SJohn Marino goto done;
6433ff40c12SJohn Marino }
6443ff40c12SJohn Marino buffer = nbuffer;
6453ff40c12SJohn Marino }
6463ff40c12SJohn Marino
6473ff40c12SJohn Marino dbus_message_iter_get_basic(iter, &byte);
648*a1157835SDaniel Fojt buffer[count] = byte;
6493ff40c12SJohn Marino entry->array_len = ++count;
6503ff40c12SJohn Marino dbus_message_iter_next(iter);
6513ff40c12SJohn Marino }
652*a1157835SDaniel Fojt entry->bytearray_value = buffer;
653*a1157835SDaniel Fojt wpa_hexdump_key(MSG_MSGDUMP, "dbus: byte array contents",
654*a1157835SDaniel Fojt entry->bytearray_value, entry->array_len);
6553ff40c12SJohn Marino
6563ff40c12SJohn Marino /* Zero-length arrays are valid. */
6573ff40c12SJohn Marino if (entry->array_len == 0) {
6583ff40c12SJohn Marino os_free(entry->bytearray_value);
6593ff40c12SJohn Marino entry->bytearray_value = NULL;
6603ff40c12SJohn Marino }
6613ff40c12SJohn Marino
6623ff40c12SJohn Marino success = TRUE;
6633ff40c12SJohn Marino
6643ff40c12SJohn Marino done:
6653ff40c12SJohn Marino return success;
6663ff40c12SJohn Marino }
6673ff40c12SJohn Marino
6683ff40c12SJohn Marino
6693ff40c12SJohn Marino #define STR_ARRAY_CHUNK_SIZE 8
6703ff40c12SJohn Marino #define STR_ARRAY_ITEM_SIZE (sizeof(char *))
6713ff40c12SJohn Marino
_wpa_dbus_dict_entry_get_string_array(DBusMessageIter * iter,int array_type,struct wpa_dbus_dict_entry * entry)6723ff40c12SJohn Marino static dbus_bool_t _wpa_dbus_dict_entry_get_string_array(
6733ff40c12SJohn Marino DBusMessageIter *iter, int array_type,
6743ff40c12SJohn Marino struct wpa_dbus_dict_entry *entry)
6753ff40c12SJohn Marino {
6763ff40c12SJohn Marino dbus_uint32_t count = 0;
6773ff40c12SJohn Marino char **buffer, **nbuffer;
6783ff40c12SJohn Marino
6793ff40c12SJohn Marino entry->strarray_value = NULL;
680*a1157835SDaniel Fojt entry->array_len = 0;
6813ff40c12SJohn Marino entry->array_type = DBUS_TYPE_STRING;
6823ff40c12SJohn Marino
6833ff40c12SJohn Marino buffer = os_calloc(STR_ARRAY_CHUNK_SIZE, STR_ARRAY_ITEM_SIZE);
6843ff40c12SJohn Marino if (buffer == NULL)
6853ff40c12SJohn Marino return FALSE;
6863ff40c12SJohn Marino
6873ff40c12SJohn Marino while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING) {
6883ff40c12SJohn Marino const char *value;
6893ff40c12SJohn Marino char *str;
6903ff40c12SJohn Marino
6913ff40c12SJohn Marino if ((count % STR_ARRAY_CHUNK_SIZE) == 0 && count != 0) {
6923ff40c12SJohn Marino nbuffer = os_realloc_array(
6933ff40c12SJohn Marino buffer, count + STR_ARRAY_CHUNK_SIZE,
6943ff40c12SJohn Marino STR_ARRAY_ITEM_SIZE);
6953ff40c12SJohn Marino if (nbuffer == NULL) {
696*a1157835SDaniel Fojt wpa_printf(MSG_ERROR,
697*a1157835SDaniel Fojt "dbus: %s out of memory trying to retrieve the string array",
698*a1157835SDaniel Fojt __func__);
699*a1157835SDaniel Fojt goto fail;
7003ff40c12SJohn Marino }
7013ff40c12SJohn Marino buffer = nbuffer;
7023ff40c12SJohn Marino }
7033ff40c12SJohn Marino
7043ff40c12SJohn Marino dbus_message_iter_get_basic(iter, &value);
705*a1157835SDaniel Fojt wpa_printf(MSG_MSGDUMP, "%s: string_array value: %s",
706*a1157835SDaniel Fojt __func__, wpa_debug_show_keys ? value : "[omitted]");
7073ff40c12SJohn Marino str = os_strdup(value);
7083ff40c12SJohn Marino if (str == NULL) {
709*a1157835SDaniel Fojt wpa_printf(MSG_ERROR,
710*a1157835SDaniel Fojt "dbus: %s out of memory trying to duplicate the string array",
711*a1157835SDaniel Fojt __func__);
712*a1157835SDaniel Fojt goto fail;
7133ff40c12SJohn Marino }
714*a1157835SDaniel Fojt buffer[count++] = str;
7153ff40c12SJohn Marino dbus_message_iter_next(iter);
7163ff40c12SJohn Marino }
717*a1157835SDaniel Fojt entry->strarray_value = buffer;
718*a1157835SDaniel Fojt entry->array_len = count;
719*a1157835SDaniel Fojt wpa_printf(MSG_MSGDUMP, "%s: string_array length %u",
720*a1157835SDaniel Fojt __func__, entry->array_len);
7213ff40c12SJohn Marino
7223ff40c12SJohn Marino /* Zero-length arrays are valid. */
7233ff40c12SJohn Marino if (entry->array_len == 0) {
7243ff40c12SJohn Marino os_free(entry->strarray_value);
7253ff40c12SJohn Marino entry->strarray_value = NULL;
7263ff40c12SJohn Marino }
7273ff40c12SJohn Marino
728*a1157835SDaniel Fojt return TRUE;
7293ff40c12SJohn Marino
730*a1157835SDaniel Fojt fail:
731*a1157835SDaniel Fojt while (count > 0) {
732*a1157835SDaniel Fojt count--;
733*a1157835SDaniel Fojt os_free(buffer[count]);
734*a1157835SDaniel Fojt }
735*a1157835SDaniel Fojt os_free(buffer);
736*a1157835SDaniel Fojt return FALSE;
7373ff40c12SJohn Marino }
7383ff40c12SJohn Marino
7393ff40c12SJohn Marino
7403ff40c12SJohn Marino #define BIN_ARRAY_CHUNK_SIZE 10
7413ff40c12SJohn Marino #define BIN_ARRAY_ITEM_SIZE (sizeof(struct wpabuf *))
7423ff40c12SJohn Marino
_wpa_dbus_dict_entry_get_binarray(DBusMessageIter * iter,struct wpa_dbus_dict_entry * entry)7433ff40c12SJohn Marino static dbus_bool_t _wpa_dbus_dict_entry_get_binarray(
7443ff40c12SJohn Marino DBusMessageIter *iter, struct wpa_dbus_dict_entry *entry)
7453ff40c12SJohn Marino {
7463ff40c12SJohn Marino struct wpa_dbus_dict_entry tmpentry;
7473ff40c12SJohn Marino size_t buflen = 0;
748*a1157835SDaniel Fojt int i, type;
7493ff40c12SJohn Marino
7503ff40c12SJohn Marino entry->array_type = WPAS_DBUS_TYPE_BINARRAY;
7513ff40c12SJohn Marino entry->array_len = 0;
7523ff40c12SJohn Marino entry->binarray_value = NULL;
7533ff40c12SJohn Marino
754*a1157835SDaniel Fojt type = dbus_message_iter_get_arg_type(iter);
755*a1157835SDaniel Fojt wpa_printf(MSG_MSGDUMP, "%s: parsing binarray type %c", __func__, type);
756*a1157835SDaniel Fojt if (type == DBUS_TYPE_INVALID) {
757*a1157835SDaniel Fojt /* Likely an empty array of arrays */
758*a1157835SDaniel Fojt return TRUE;
759*a1157835SDaniel Fojt }
760*a1157835SDaniel Fojt if (type != DBUS_TYPE_ARRAY) {
761*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "%s: not an array type: %c",
762*a1157835SDaniel Fojt __func__, type);
763*a1157835SDaniel Fojt return FALSE;
764*a1157835SDaniel Fojt }
765*a1157835SDaniel Fojt
766*a1157835SDaniel Fojt type = dbus_message_iter_get_element_type(iter);
767*a1157835SDaniel Fojt if (type != DBUS_TYPE_BYTE) {
768*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "%s: unexpected element type %c",
769*a1157835SDaniel Fojt __func__, type);
770*a1157835SDaniel Fojt return FALSE;
771*a1157835SDaniel Fojt }
772*a1157835SDaniel Fojt
7733ff40c12SJohn Marino while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_ARRAY) {
7743ff40c12SJohn Marino DBusMessageIter iter_array;
7753ff40c12SJohn Marino
7763ff40c12SJohn Marino if (entry->array_len == buflen) {
7773ff40c12SJohn Marino struct wpabuf **newbuf;
7783ff40c12SJohn Marino
7793ff40c12SJohn Marino buflen += BIN_ARRAY_CHUNK_SIZE;
7803ff40c12SJohn Marino
7813ff40c12SJohn Marino newbuf = os_realloc_array(entry->binarray_value,
7823ff40c12SJohn Marino buflen, BIN_ARRAY_ITEM_SIZE);
7833ff40c12SJohn Marino if (!newbuf)
7843ff40c12SJohn Marino goto cleanup;
7853ff40c12SJohn Marino entry->binarray_value = newbuf;
7863ff40c12SJohn Marino }
7873ff40c12SJohn Marino
7883ff40c12SJohn Marino dbus_message_iter_recurse(iter, &iter_array);
789*a1157835SDaniel Fojt os_memset(&tmpentry, 0, sizeof(tmpentry));
790*a1157835SDaniel Fojt tmpentry.type = DBUS_TYPE_ARRAY;
7913ff40c12SJohn Marino if (_wpa_dbus_dict_entry_get_byte_array(&iter_array, &tmpentry)
7923ff40c12SJohn Marino == FALSE)
7933ff40c12SJohn Marino goto cleanup;
7943ff40c12SJohn Marino
7953ff40c12SJohn Marino entry->binarray_value[entry->array_len] =
7963ff40c12SJohn Marino wpabuf_alloc_ext_data((u8 *) tmpentry.bytearray_value,
7973ff40c12SJohn Marino tmpentry.array_len);
7983ff40c12SJohn Marino if (entry->binarray_value[entry->array_len] == NULL) {
7993ff40c12SJohn Marino wpa_dbus_dict_entry_clear(&tmpentry);
8003ff40c12SJohn Marino goto cleanup;
8013ff40c12SJohn Marino }
8023ff40c12SJohn Marino entry->array_len++;
8033ff40c12SJohn Marino dbus_message_iter_next(iter);
8043ff40c12SJohn Marino }
805*a1157835SDaniel Fojt wpa_printf(MSG_MSGDUMP, "%s: binarray length %u",
806*a1157835SDaniel Fojt __func__, entry->array_len);
8073ff40c12SJohn Marino
8083ff40c12SJohn Marino return TRUE;
8093ff40c12SJohn Marino
8103ff40c12SJohn Marino cleanup:
8113ff40c12SJohn Marino for (i = 0; i < (int) entry->array_len; i++)
8123ff40c12SJohn Marino wpabuf_free(entry->binarray_value[i]);
8133ff40c12SJohn Marino os_free(entry->binarray_value);
8143ff40c12SJohn Marino entry->array_len = 0;
8153ff40c12SJohn Marino entry->binarray_value = NULL;
8163ff40c12SJohn Marino return FALSE;
8173ff40c12SJohn Marino }
8183ff40c12SJohn Marino
8193ff40c12SJohn Marino
_wpa_dbus_dict_entry_get_array(DBusMessageIter * iter_dict_val,struct wpa_dbus_dict_entry * entry)8203ff40c12SJohn Marino static dbus_bool_t _wpa_dbus_dict_entry_get_array(
8213ff40c12SJohn Marino DBusMessageIter *iter_dict_val, struct wpa_dbus_dict_entry *entry)
8223ff40c12SJohn Marino {
8233ff40c12SJohn Marino int array_type = dbus_message_iter_get_element_type(iter_dict_val);
8243ff40c12SJohn Marino dbus_bool_t success = FALSE;
8253ff40c12SJohn Marino DBusMessageIter iter_array;
8263ff40c12SJohn Marino
827*a1157835SDaniel Fojt wpa_printf(MSG_MSGDUMP, "%s: array_type %c", __func__, array_type);
8283ff40c12SJohn Marino
8293ff40c12SJohn Marino dbus_message_iter_recurse(iter_dict_val, &iter_array);
8303ff40c12SJohn Marino
8313ff40c12SJohn Marino switch (array_type) {
8323ff40c12SJohn Marino case DBUS_TYPE_BYTE:
8333ff40c12SJohn Marino success = _wpa_dbus_dict_entry_get_byte_array(&iter_array,
8343ff40c12SJohn Marino entry);
8353ff40c12SJohn Marino break;
8363ff40c12SJohn Marino case DBUS_TYPE_STRING:
8373ff40c12SJohn Marino success = _wpa_dbus_dict_entry_get_string_array(&iter_array,
8383ff40c12SJohn Marino array_type,
8393ff40c12SJohn Marino entry);
8403ff40c12SJohn Marino break;
8413ff40c12SJohn Marino case DBUS_TYPE_ARRAY:
8423ff40c12SJohn Marino success = _wpa_dbus_dict_entry_get_binarray(&iter_array, entry);
843*a1157835SDaniel Fojt break;
8443ff40c12SJohn Marino default:
845*a1157835SDaniel Fojt wpa_printf(MSG_MSGDUMP, "%s: unsupported array type %c",
846*a1157835SDaniel Fojt __func__, array_type);
8473ff40c12SJohn Marino break;
8483ff40c12SJohn Marino }
8493ff40c12SJohn Marino
8503ff40c12SJohn Marino return success;
8513ff40c12SJohn Marino }
8523ff40c12SJohn Marino
8533ff40c12SJohn Marino
_wpa_dbus_dict_fill_value_from_variant(struct wpa_dbus_dict_entry * entry,DBusMessageIter * iter)8543ff40c12SJohn Marino static dbus_bool_t _wpa_dbus_dict_fill_value_from_variant(
8553ff40c12SJohn Marino struct wpa_dbus_dict_entry *entry, DBusMessageIter *iter)
8563ff40c12SJohn Marino {
8573ff40c12SJohn Marino const char *v;
8583ff40c12SJohn Marino
8593ff40c12SJohn Marino switch (entry->type) {
8603ff40c12SJohn Marino case DBUS_TYPE_OBJECT_PATH:
861*a1157835SDaniel Fojt dbus_message_iter_get_basic(iter, &v);
862*a1157835SDaniel Fojt wpa_printf(MSG_MSGDUMP, "%s: object path value: %s",
863*a1157835SDaniel Fojt __func__, v);
864*a1157835SDaniel Fojt entry->str_value = os_strdup(v);
865*a1157835SDaniel Fojt if (entry->str_value == NULL)
866*a1157835SDaniel Fojt return FALSE;
867*a1157835SDaniel Fojt break;
8683ff40c12SJohn Marino case DBUS_TYPE_STRING:
8693ff40c12SJohn Marino dbus_message_iter_get_basic(iter, &v);
870*a1157835SDaniel Fojt wpa_printf(MSG_MSGDUMP, "%s: string value: %s",
871*a1157835SDaniel Fojt __func__, wpa_debug_show_keys ? v : "[omitted]");
8723ff40c12SJohn Marino entry->str_value = os_strdup(v);
8733ff40c12SJohn Marino if (entry->str_value == NULL)
8743ff40c12SJohn Marino return FALSE;
8753ff40c12SJohn Marino break;
8763ff40c12SJohn Marino case DBUS_TYPE_BOOLEAN:
8773ff40c12SJohn Marino dbus_message_iter_get_basic(iter, &entry->bool_value);
878*a1157835SDaniel Fojt wpa_printf(MSG_MSGDUMP, "%s: boolean value: %d",
879*a1157835SDaniel Fojt __func__, entry->bool_value);
8803ff40c12SJohn Marino break;
8813ff40c12SJohn Marino case DBUS_TYPE_BYTE:
8823ff40c12SJohn Marino dbus_message_iter_get_basic(iter, &entry->byte_value);
883*a1157835SDaniel Fojt wpa_printf(MSG_MSGDUMP, "%s: byte value: %d",
884*a1157835SDaniel Fojt __func__, entry->byte_value);
8853ff40c12SJohn Marino break;
8863ff40c12SJohn Marino case DBUS_TYPE_INT16:
8873ff40c12SJohn Marino dbus_message_iter_get_basic(iter, &entry->int16_value);
888*a1157835SDaniel Fojt wpa_printf(MSG_MSGDUMP, "%s: int16 value: %d",
889*a1157835SDaniel Fojt __func__, entry->int16_value);
8903ff40c12SJohn Marino break;
8913ff40c12SJohn Marino case DBUS_TYPE_UINT16:
8923ff40c12SJohn Marino dbus_message_iter_get_basic(iter, &entry->uint16_value);
893*a1157835SDaniel Fojt wpa_printf(MSG_MSGDUMP, "%s: uint16 value: %d",
894*a1157835SDaniel Fojt __func__, entry->uint16_value);
8953ff40c12SJohn Marino break;
8963ff40c12SJohn Marino case DBUS_TYPE_INT32:
8973ff40c12SJohn Marino dbus_message_iter_get_basic(iter, &entry->int32_value);
898*a1157835SDaniel Fojt wpa_printf(MSG_MSGDUMP, "%s: int32 value: %d",
899*a1157835SDaniel Fojt __func__, entry->int32_value);
9003ff40c12SJohn Marino break;
9013ff40c12SJohn Marino case DBUS_TYPE_UINT32:
9023ff40c12SJohn Marino dbus_message_iter_get_basic(iter, &entry->uint32_value);
903*a1157835SDaniel Fojt wpa_printf(MSG_MSGDUMP, "%s: uint32 value: %d",
904*a1157835SDaniel Fojt __func__, entry->uint32_value);
9053ff40c12SJohn Marino break;
9063ff40c12SJohn Marino case DBUS_TYPE_INT64:
9073ff40c12SJohn Marino dbus_message_iter_get_basic(iter, &entry->int64_value);
908*a1157835SDaniel Fojt wpa_printf(MSG_MSGDUMP, "%s: int64 value: %lld",
909*a1157835SDaniel Fojt __func__, (long long int) entry->int64_value);
9103ff40c12SJohn Marino break;
9113ff40c12SJohn Marino case DBUS_TYPE_UINT64:
9123ff40c12SJohn Marino dbus_message_iter_get_basic(iter, &entry->uint64_value);
913*a1157835SDaniel Fojt wpa_printf(MSG_MSGDUMP, "%s: uint64 value: %llu",
914*a1157835SDaniel Fojt __func__,
915*a1157835SDaniel Fojt (unsigned long long int) entry->uint64_value);
9163ff40c12SJohn Marino break;
9173ff40c12SJohn Marino case DBUS_TYPE_DOUBLE:
9183ff40c12SJohn Marino dbus_message_iter_get_basic(iter, &entry->double_value);
919*a1157835SDaniel Fojt wpa_printf(MSG_MSGDUMP, "%s: double value: %f",
920*a1157835SDaniel Fojt __func__, entry->double_value);
9213ff40c12SJohn Marino break;
9223ff40c12SJohn Marino case DBUS_TYPE_ARRAY:
9233ff40c12SJohn Marino return _wpa_dbus_dict_entry_get_array(iter, entry);
9243ff40c12SJohn Marino default:
925*a1157835SDaniel Fojt wpa_printf(MSG_MSGDUMP, "%s: unsupported type %c",
926*a1157835SDaniel Fojt __func__, entry->type);
9273ff40c12SJohn Marino return FALSE;
9283ff40c12SJohn Marino }
9293ff40c12SJohn Marino
9303ff40c12SJohn Marino return TRUE;
9313ff40c12SJohn Marino }
9323ff40c12SJohn Marino
9333ff40c12SJohn Marino
9343ff40c12SJohn Marino /**
9353ff40c12SJohn Marino * Read the current key/value entry from the dict. Entries are dynamically
9363ff40c12SJohn Marino * allocated when needed and must be freed after use with the
9373ff40c12SJohn Marino * wpa_dbus_dict_entry_clear() function.
9383ff40c12SJohn Marino *
9393ff40c12SJohn Marino * The returned entry object will be filled with the type and value of the next
9403ff40c12SJohn Marino * entry in the dict, or the type will be DBUS_TYPE_INVALID if an error
9413ff40c12SJohn Marino * occurred.
9423ff40c12SJohn Marino *
9433ff40c12SJohn Marino * @param iter_dict A valid DBusMessageIter returned from
9443ff40c12SJohn Marino * wpa_dbus_dict_open_read()
9453ff40c12SJohn Marino * @param entry A valid dict entry object into which the dict key and value
9463ff40c12SJohn Marino * will be placed
9473ff40c12SJohn Marino * @return TRUE on success, FALSE on failure
9483ff40c12SJohn Marino *
9493ff40c12SJohn Marino */
wpa_dbus_dict_get_entry(DBusMessageIter * iter_dict,struct wpa_dbus_dict_entry * entry)9503ff40c12SJohn Marino dbus_bool_t wpa_dbus_dict_get_entry(DBusMessageIter *iter_dict,
9513ff40c12SJohn Marino struct wpa_dbus_dict_entry * entry)
9523ff40c12SJohn Marino {
9533ff40c12SJohn Marino DBusMessageIter iter_dict_entry, iter_dict_val;
9543ff40c12SJohn Marino int type;
9553ff40c12SJohn Marino const char *key;
9563ff40c12SJohn Marino
957*a1157835SDaniel Fojt if (!iter_dict || !entry ||
958*a1157835SDaniel Fojt dbus_message_iter_get_arg_type(iter_dict) != DBUS_TYPE_DICT_ENTRY) {
959*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "%s: not a dict entry", __func__);
9603ff40c12SJohn Marino goto error;
961*a1157835SDaniel Fojt }
9623ff40c12SJohn Marino
9633ff40c12SJohn Marino dbus_message_iter_recurse(iter_dict, &iter_dict_entry);
9643ff40c12SJohn Marino dbus_message_iter_get_basic(&iter_dict_entry, &key);
965*a1157835SDaniel Fojt wpa_printf(MSG_MSGDUMP, "%s: dict entry key: %s", __func__, key);
9663ff40c12SJohn Marino entry->key = key;
9673ff40c12SJohn Marino
968*a1157835SDaniel Fojt if (!dbus_message_iter_next(&iter_dict_entry)) {
969*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG, "%s: no variant in dict entry", __func__);
9703ff40c12SJohn Marino goto error;
971*a1157835SDaniel Fojt }
9723ff40c12SJohn Marino type = dbus_message_iter_get_arg_type(&iter_dict_entry);
973*a1157835SDaniel Fojt if (type != DBUS_TYPE_VARIANT) {
974*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG,
975*a1157835SDaniel Fojt "%s: unexpected dict entry variant type: %c",
976*a1157835SDaniel Fojt __func__, type);
9773ff40c12SJohn Marino goto error;
978*a1157835SDaniel Fojt }
9793ff40c12SJohn Marino
9803ff40c12SJohn Marino dbus_message_iter_recurse(&iter_dict_entry, &iter_dict_val);
9813ff40c12SJohn Marino entry->type = dbus_message_iter_get_arg_type(&iter_dict_val);
982*a1157835SDaniel Fojt wpa_printf(MSG_MSGDUMP, "%s: dict entry variant content type: %c",
983*a1157835SDaniel Fojt __func__, entry->type);
984*a1157835SDaniel Fojt entry->array_type = DBUS_TYPE_INVALID;
985*a1157835SDaniel Fojt if (!_wpa_dbus_dict_fill_value_from_variant(entry, &iter_dict_val)) {
986*a1157835SDaniel Fojt wpa_printf(MSG_DEBUG,
987*a1157835SDaniel Fojt "%s: failed to fetch dict values from variant",
988*a1157835SDaniel Fojt __func__);
9893ff40c12SJohn Marino goto error;
990*a1157835SDaniel Fojt }
9913ff40c12SJohn Marino
9923ff40c12SJohn Marino dbus_message_iter_next(iter_dict);
9933ff40c12SJohn Marino return TRUE;
9943ff40c12SJohn Marino
9953ff40c12SJohn Marino error:
9963ff40c12SJohn Marino if (entry) {
9973ff40c12SJohn Marino wpa_dbus_dict_entry_clear(entry);
9983ff40c12SJohn Marino entry->type = DBUS_TYPE_INVALID;
9993ff40c12SJohn Marino entry->array_type = DBUS_TYPE_INVALID;
10003ff40c12SJohn Marino }
10013ff40c12SJohn Marino
10023ff40c12SJohn Marino return FALSE;
10033ff40c12SJohn Marino }
10043ff40c12SJohn Marino
10053ff40c12SJohn Marino
10063ff40c12SJohn Marino /**
10073ff40c12SJohn Marino * Return whether or not there are additional dictionary entries.
10083ff40c12SJohn Marino *
10093ff40c12SJohn Marino * @param iter_dict A valid DBusMessageIter returned from
10103ff40c12SJohn Marino * wpa_dbus_dict_open_read()
10113ff40c12SJohn Marino * @return TRUE if more dict entries exists, FALSE if no more dict entries
10123ff40c12SJohn Marino * exist
10133ff40c12SJohn Marino */
wpa_dbus_dict_has_dict_entry(DBusMessageIter * iter_dict)10143ff40c12SJohn Marino dbus_bool_t wpa_dbus_dict_has_dict_entry(DBusMessageIter *iter_dict)
10153ff40c12SJohn Marino {
10163ff40c12SJohn Marino if (!iter_dict)
10173ff40c12SJohn Marino return FALSE;
10183ff40c12SJohn Marino return dbus_message_iter_get_arg_type(iter_dict) ==
10193ff40c12SJohn Marino DBUS_TYPE_DICT_ENTRY;
10203ff40c12SJohn Marino }
10213ff40c12SJohn Marino
10223ff40c12SJohn Marino
10233ff40c12SJohn Marino /**
10243ff40c12SJohn Marino * Free any memory used by the entry object.
10253ff40c12SJohn Marino *
10263ff40c12SJohn Marino * @param entry The entry object
10273ff40c12SJohn Marino */
wpa_dbus_dict_entry_clear(struct wpa_dbus_dict_entry * entry)10283ff40c12SJohn Marino void wpa_dbus_dict_entry_clear(struct wpa_dbus_dict_entry *entry)
10293ff40c12SJohn Marino {
10303ff40c12SJohn Marino unsigned int i;
10313ff40c12SJohn Marino
10323ff40c12SJohn Marino if (!entry)
10333ff40c12SJohn Marino return;
10343ff40c12SJohn Marino switch (entry->type) {
10353ff40c12SJohn Marino case DBUS_TYPE_OBJECT_PATH:
10363ff40c12SJohn Marino case DBUS_TYPE_STRING:
10373ff40c12SJohn Marino os_free(entry->str_value);
10383ff40c12SJohn Marino break;
10393ff40c12SJohn Marino case DBUS_TYPE_ARRAY:
10403ff40c12SJohn Marino switch (entry->array_type) {
10413ff40c12SJohn Marino case DBUS_TYPE_BYTE:
10423ff40c12SJohn Marino os_free(entry->bytearray_value);
10433ff40c12SJohn Marino break;
10443ff40c12SJohn Marino case DBUS_TYPE_STRING:
1045*a1157835SDaniel Fojt if (!entry->strarray_value)
1046*a1157835SDaniel Fojt break;
10473ff40c12SJohn Marino for (i = 0; i < entry->array_len; i++)
10483ff40c12SJohn Marino os_free(entry->strarray_value[i]);
10493ff40c12SJohn Marino os_free(entry->strarray_value);
10503ff40c12SJohn Marino break;
10513ff40c12SJohn Marino case WPAS_DBUS_TYPE_BINARRAY:
10523ff40c12SJohn Marino for (i = 0; i < entry->array_len; i++)
10533ff40c12SJohn Marino wpabuf_free(entry->binarray_value[i]);
10543ff40c12SJohn Marino os_free(entry->binarray_value);
10553ff40c12SJohn Marino break;
10563ff40c12SJohn Marino }
10573ff40c12SJohn Marino break;
10583ff40c12SJohn Marino }
10593ff40c12SJohn Marino
10603ff40c12SJohn Marino os_memset(entry, 0, sizeof(struct wpa_dbus_dict_entry));
10613ff40c12SJohn Marino }
1062