Home | History | Annotate | Download | only in wpa_supplicant
      1 /*
      2  * WPA Supplicant / dbus-based control interface
      3  * Copyright (c) 2006, Dan Williams <dcbw (at) redhat.com> and Red Hat, Inc.
      4  *
      5  * This program is free software; you can redistribute it and/or modify
      6  * it under the terms of the GNU General Public License version 2 as
      7  * published by the Free Software Foundation.
      8  *
      9  * Alternatively, this software may be distributed under the terms of BSD
     10  * license.
     11  *
     12  * See README and COPYING for more details.
     13  */
     14 
     15 #include "includes.h"
     16 #include <dbus/dbus.h>
     17 
     18 #include "common.h"
     19 #include "dbus_dict_helpers.h"
     20 
     21 
     22 /**
     23  * Start a dict in a dbus message.  Should be paired with a call to
     24  * wpa_dbus_dict_close_write().
     25  *
     26  * @param iter A valid dbus message iterator
     27  * @param iter_dict (out) A dict iterator to pass to further dict functions
     28  * @return TRUE on success, FALSE on failure
     29  *
     30  */
     31 dbus_bool_t wpa_dbus_dict_open_write(DBusMessageIter *iter,
     32 				     DBusMessageIter *iter_dict)
     33 {
     34 	dbus_bool_t result;
     35 
     36 	if (!iter || !iter_dict)
     37 		return FALSE;
     38 
     39 	result = dbus_message_iter_open_container(
     40 		iter,
     41 		DBUS_TYPE_ARRAY,
     42 		DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
     43 		DBUS_TYPE_STRING_AS_STRING
     44 		DBUS_TYPE_VARIANT_AS_STRING
     45 		DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
     46 		iter_dict);
     47 	return result;
     48 }
     49 
     50 
     51 /**
     52  * End a dict element in a dbus message.  Should be paired with
     53  * a call to wpa_dbus_dict_open_write().
     54  *
     55  * @param iter valid dbus message iterator, same as passed to
     56  *    wpa_dbus_dict_open_write()
     57  * @param iter_dict a dbus dict iterator returned from
     58  *    wpa_dbus_dict_open_write()
     59  * @return TRUE on success, FALSE on failure
     60  *
     61  */
     62 dbus_bool_t wpa_dbus_dict_close_write(DBusMessageIter *iter,
     63 				      DBusMessageIter *iter_dict)
     64 {
     65 	if (!iter || !iter_dict)
     66 		return FALSE;
     67 
     68 	return dbus_message_iter_close_container(iter, iter_dict);
     69 }
     70 
     71 
     72 static const char * _wpa_get_type_as_string_from_type(const int type)
     73 {
     74 	switch(type) {
     75 	case DBUS_TYPE_BYTE:
     76 		return DBUS_TYPE_BYTE_AS_STRING;
     77 	case DBUS_TYPE_BOOLEAN:
     78 		return DBUS_TYPE_BOOLEAN_AS_STRING;
     79 	case DBUS_TYPE_INT16:
     80 		return DBUS_TYPE_INT16_AS_STRING;
     81 	case DBUS_TYPE_UINT16:
     82 		return DBUS_TYPE_UINT16_AS_STRING;
     83 	case DBUS_TYPE_INT32:
     84 		return DBUS_TYPE_INT32_AS_STRING;
     85 	case DBUS_TYPE_UINT32:
     86 		return DBUS_TYPE_UINT32_AS_STRING;
     87 	case DBUS_TYPE_INT64:
     88 		return DBUS_TYPE_INT64_AS_STRING;
     89 	case DBUS_TYPE_UINT64:
     90 		return DBUS_TYPE_UINT64_AS_STRING;
     91 	case DBUS_TYPE_DOUBLE:
     92 		return DBUS_TYPE_DOUBLE_AS_STRING;
     93 	case DBUS_TYPE_STRING:
     94 		return DBUS_TYPE_STRING_AS_STRING;
     95 	case DBUS_TYPE_OBJECT_PATH:
     96 		return DBUS_TYPE_OBJECT_PATH_AS_STRING;
     97 	case DBUS_TYPE_ARRAY:
     98 		return DBUS_TYPE_ARRAY_AS_STRING;
     99 	default:
    100 		return NULL;
    101 	}
    102 }
    103 
    104 
    105 static dbus_bool_t _wpa_dbus_add_dict_entry_start(
    106 	DBusMessageIter *iter_dict, DBusMessageIter *iter_dict_entry,
    107 	const char *key, const int value_type)
    108 {
    109 	if (!dbus_message_iter_open_container(iter_dict,
    110 					      DBUS_TYPE_DICT_ENTRY, NULL,
    111 					      iter_dict_entry))
    112 		return FALSE;
    113 
    114 	if (!dbus_message_iter_append_basic(iter_dict_entry, DBUS_TYPE_STRING,
    115 					    &key))
    116 		return FALSE;
    117 
    118 	return TRUE;
    119 }
    120 
    121 
    122 static dbus_bool_t _wpa_dbus_add_dict_entry_end(
    123 	DBusMessageIter *iter_dict, DBusMessageIter *iter_dict_entry,
    124 	DBusMessageIter *iter_dict_val)
    125 {
    126 	if (!dbus_message_iter_close_container(iter_dict_entry, iter_dict_val))
    127 		return FALSE;
    128 	if (!dbus_message_iter_close_container(iter_dict, iter_dict_entry))
    129 		return FALSE;
    130 
    131 	return TRUE;
    132 }
    133 
    134 
    135 static dbus_bool_t _wpa_dbus_add_dict_entry_basic(DBusMessageIter *iter_dict,
    136 						  const char *key,
    137 						  const int value_type,
    138 						  const void *value)
    139 {
    140 	DBusMessageIter iter_dict_entry, iter_dict_val;
    141 	const char *type_as_string = NULL;
    142 
    143 	type_as_string = _wpa_get_type_as_string_from_type(value_type);
    144 	if (!type_as_string)
    145 		return FALSE;
    146 
    147 	if (!_wpa_dbus_add_dict_entry_start(iter_dict, &iter_dict_entry,
    148 					    key, value_type))
    149 		return FALSE;
    150 
    151 	if (!dbus_message_iter_open_container(&iter_dict_entry,
    152 					      DBUS_TYPE_VARIANT,
    153 					      type_as_string, &iter_dict_val))
    154 		return FALSE;
    155 
    156 	if (!dbus_message_iter_append_basic(&iter_dict_val, value_type, value))
    157 		return FALSE;
    158 
    159 	if (!_wpa_dbus_add_dict_entry_end(iter_dict, &iter_dict_entry,
    160 					  &iter_dict_val))
    161 		return FALSE;
    162 
    163 	return TRUE;
    164 }
    165 
    166 
    167 static dbus_bool_t _wpa_dbus_add_dict_entry_byte_array(
    168 	DBusMessageIter *iter_dict, const char *key,
    169 	const char *value, const dbus_uint32_t value_len)
    170 {
    171 	DBusMessageIter iter_dict_entry, iter_dict_val, iter_array;
    172 	dbus_uint32_t i;
    173 
    174 	if (!_wpa_dbus_add_dict_entry_start(iter_dict, &iter_dict_entry,
    175 					    key, DBUS_TYPE_ARRAY))
    176 		return FALSE;
    177 
    178 	if (!dbus_message_iter_open_container(&iter_dict_entry,
    179 					      DBUS_TYPE_VARIANT,
    180 					      DBUS_TYPE_ARRAY_AS_STRING
    181 					      DBUS_TYPE_BYTE_AS_STRING,
    182 					      &iter_dict_val))
    183 		return FALSE;
    184 
    185 	if (!dbus_message_iter_open_container(&iter_dict_val, DBUS_TYPE_ARRAY,
    186 					      DBUS_TYPE_BYTE_AS_STRING,
    187 					      &iter_array))
    188 		return FALSE;
    189 
    190 	for (i = 0; i < value_len; i++) {
    191 		if (!dbus_message_iter_append_basic(&iter_array,
    192 						    DBUS_TYPE_BYTE,
    193 						    &(value[i])))
    194 			return FALSE;
    195 	}
    196 
    197 	if (!dbus_message_iter_close_container(&iter_dict_val, &iter_array))
    198 		return FALSE;
    199 
    200 	if (!_wpa_dbus_add_dict_entry_end(iter_dict, &iter_dict_entry,
    201 					  &iter_dict_val))
    202 		return FALSE;
    203 
    204 	return TRUE;
    205 }
    206 
    207 
    208 /**
    209  * Add a string entry to the dict.
    210  *
    211  * @param iter_dict A valid DBusMessageIter returned from
    212  *    wpa_dbus_dict_open_write()
    213  * @param key The key of the dict item
    214  * @param value The string value
    215  * @return TRUE on success, FALSE on failure
    216  *
    217  */
    218 dbus_bool_t wpa_dbus_dict_append_string(DBusMessageIter *iter_dict,
    219 					const char *key, const char *value)
    220 {
    221 	if (!key || !value)
    222 		return FALSE;
    223 	return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_STRING,
    224 					      &value);
    225 }
    226 
    227 
    228 /**
    229  * Add a byte entry to the dict.
    230  *
    231  * @param iter_dict A valid DBusMessageIter returned from
    232  *    wpa_dbus_dict_open_write()
    233  * @param key The key of the dict item
    234  * @param value The byte value
    235  * @return TRUE on success, FALSE on failure
    236  *
    237  */
    238 dbus_bool_t wpa_dbus_dict_append_byte(DBusMessageIter *iter_dict,
    239 				      const char *key, const char value)
    240 {
    241 	if (!key)
    242 		return FALSE;
    243 	return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_BYTE,
    244 					      &value);
    245 }
    246 
    247 
    248 /**
    249  * Add a boolean entry to the dict.
    250  *
    251  * @param iter_dict A valid DBusMessageIter returned from
    252  *    wpa_dbus_dict_open_write()
    253  * @param key The key of the dict item
    254  * @param value The boolean value
    255  * @return TRUE on success, FALSE on failure
    256  *
    257  */
    258 dbus_bool_t wpa_dbus_dict_append_bool(DBusMessageIter *iter_dict,
    259 				      const char *key, const dbus_bool_t value)
    260 {
    261 	if (!key)
    262 		return FALSE;
    263 	return _wpa_dbus_add_dict_entry_basic(iter_dict, key,
    264 					      DBUS_TYPE_BOOLEAN, &value);
    265 }
    266 
    267 
    268 /**
    269  * Add a 16-bit signed integer entry to the dict.
    270  *
    271  * @param iter_dict A valid DBusMessageIter returned from
    272  *    wpa_dbus_dict_open_write()
    273  * @param key The key of the dict item
    274  * @param value The 16-bit signed integer value
    275  * @return TRUE on success, FALSE on failure
    276  *
    277  */
    278 dbus_bool_t wpa_dbus_dict_append_int16(DBusMessageIter *iter_dict,
    279 				       const char *key,
    280 				       const dbus_int16_t value)
    281 {
    282 	if (!key)
    283 		return FALSE;
    284 	return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_INT16,
    285 					      &value);
    286 }
    287 
    288 
    289 /**
    290  * Add a 16-bit unsigned integer entry to the dict.
    291  *
    292  * @param iter_dict A valid DBusMessageIter returned from
    293  *    wpa_dbus_dict_open_write()
    294  * @param key The key of the dict item
    295  * @param value The 16-bit unsigned integer value
    296  * @return TRUE on success, FALSE on failure
    297  *
    298  */
    299 dbus_bool_t wpa_dbus_dict_append_uint16(DBusMessageIter *iter_dict,
    300 					const char *key,
    301 					const dbus_uint16_t value)
    302 {
    303 	if (!key)
    304 		return FALSE;
    305 	return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_UINT16,
    306 					      &value);
    307 }
    308 
    309 
    310 /**
    311  * Add a 32-bit signed integer to the dict.
    312  *
    313  * @param iter_dict A valid DBusMessageIter returned from
    314  *    wpa_dbus_dict_open_write()
    315  * @param key The key of the dict item
    316  * @param value The 32-bit signed integer value
    317  * @return TRUE on success, FALSE on failure
    318  *
    319  */
    320 dbus_bool_t wpa_dbus_dict_append_int32(DBusMessageIter *iter_dict,
    321 				       const char *key,
    322 				       const dbus_int32_t value)
    323 {
    324 	if (!key)
    325 		return FALSE;
    326 	return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_INT32,
    327 					      &value);
    328 }
    329 
    330 
    331 /**
    332  * Add a 32-bit unsigned integer entry to the dict.
    333  *
    334  * @param iter_dict A valid DBusMessageIter returned from
    335  *    wpa_dbus_dict_open_write()
    336  * @param key The key of the dict item
    337  * @param value The 32-bit unsigned integer value
    338  * @return TRUE on success, FALSE on failure
    339  *
    340  */
    341 dbus_bool_t wpa_dbus_dict_append_uint32(DBusMessageIter *iter_dict,
    342 					const char *key,
    343 					const dbus_uint32_t value)
    344 {
    345 	if (!key)
    346 		return FALSE;
    347 	return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_UINT32,
    348 					      &value);
    349 }
    350 
    351 
    352 /**
    353  * Add a 64-bit integer entry to the dict.
    354  *
    355  * @param iter_dict A valid DBusMessageIter returned from
    356  *    wpa_dbus_dict_open_write()
    357  * @param key The key of the dict item
    358  * @param value The 64-bit integer value
    359  * @return TRUE on success, FALSE on failure
    360  *
    361  */
    362 dbus_bool_t wpa_dbus_dict_append_int64(DBusMessageIter *iter_dict,
    363 				       const char *key,
    364 				       const dbus_int64_t value)
    365 {
    366 	if (!key)
    367 		return FALSE;
    368 	return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_INT64,
    369 					      &value);
    370 }
    371 
    372 
    373 /**
    374  * Add a 64-bit unsigned integer entry to the dict.
    375  *
    376  * @param iter_dict A valid DBusMessageIter returned from
    377  *    wpa_dbus_dict_open_write()
    378  * @param key The key of the dict item
    379  * @param value The 64-bit unsigned integer value
    380  * @return TRUE on success, FALSE on failure
    381  *
    382  */
    383 dbus_bool_t wpa_dbus_dict_append_uint64(DBusMessageIter *iter_dict,
    384 					const char *key,
    385 					const dbus_uint64_t value)
    386 {
    387 	if (!key)
    388 		return FALSE;
    389 	return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_UINT64,
    390 					      &value);
    391 }
    392 
    393 
    394 /**
    395  * Add a double-precision floating point entry to the dict.
    396  *
    397  * @param iter_dict A valid DBusMessageIter returned from
    398  *    wpa_dbus_dict_open_write()
    399  * @param key The key of the dict item
    400  * @param value The double-precision floating point value
    401  * @return TRUE on success, FALSE on failure
    402  *
    403  */
    404 dbus_bool_t wpa_dbus_dict_append_double(DBusMessageIter *iter_dict,
    405 					const char * key,
    406 					const double value)
    407 {
    408 	if (!key)
    409 		return FALSE;
    410 	return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_DOUBLE,
    411 					      &value);
    412 }
    413 
    414 
    415 /**
    416  * Add a DBus object path entry to the dict.
    417  *
    418  * @param iter_dict A valid DBusMessageIter returned from
    419  *    wpa_dbus_dict_open_write()
    420  * @param key The key of the dict item
    421  * @param value The DBus object path value
    422  * @return TRUE on success, FALSE on failure
    423  *
    424  */
    425 dbus_bool_t wpa_dbus_dict_append_object_path(DBusMessageIter *iter_dict,
    426 					     const char *key,
    427 					     const char *value)
    428 {
    429 	if (!key || !value)
    430 		return FALSE;
    431 	return _wpa_dbus_add_dict_entry_basic(iter_dict, key,
    432 					      DBUS_TYPE_OBJECT_PATH, &value);
    433 }
    434 
    435 
    436 /**
    437  * Add a byte array entry to the dict.
    438  *
    439  * @param iter_dict A valid DBusMessageIter returned from
    440  *    wpa_dbus_dict_open_write()
    441  * @param key The key of the dict item
    442  * @param value The byte array
    443  * @param value_len The length of the byte array, in bytes
    444  * @return TRUE on success, FALSE on failure
    445  *
    446  */
    447 dbus_bool_t wpa_dbus_dict_append_byte_array(DBusMessageIter *iter_dict,
    448 					    const char *key,
    449 					    const char *value,
    450 					    const dbus_uint32_t value_len)
    451 {
    452 	if (!key)
    453 		return FALSE;
    454 	if (!value && (value_len != 0))
    455 		return FALSE;
    456 	return _wpa_dbus_add_dict_entry_byte_array(iter_dict, key, value,
    457 						   value_len);
    458 }
    459 
    460 
    461 /**
    462  * Begin a string array entry in the dict
    463  *
    464  * @param iter_dict A valid DBusMessageIter returned from
    465  *                  wpa_dbus_dict_open_write()
    466  * @param key The key of the dict item
    467  * @param iter_dict_entry A private DBusMessageIter provided by the caller to
    468  *                        be passed to wpa_dbus_dict_end_string_array()
    469  * @param iter_dict_val A private DBusMessageIter provided by the caller to
    470  *                      be passed to wpa_dbus_dict_end_string_array()
    471  * @param iter_array On return, the DBusMessageIter to be passed to
    472  *                   wpa_dbus_dict_string_array_add_element()
    473  * @return TRUE on success, FALSE on failure
    474  *
    475  */
    476 dbus_bool_t wpa_dbus_dict_begin_string_array(DBusMessageIter *iter_dict,
    477 					     const char *key,
    478 					     DBusMessageIter *iter_dict_entry,
    479 					     DBusMessageIter *iter_dict_val,
    480 					     DBusMessageIter *iter_array)
    481 {
    482 	if (!iter_dict || !iter_dict_entry || !iter_dict_val || !iter_array)
    483 		return FALSE;
    484 
    485 	if (!_wpa_dbus_add_dict_entry_start(iter_dict, iter_dict_entry,
    486 					    key, DBUS_TYPE_ARRAY))
    487 		return FALSE;
    488 
    489 	if (!dbus_message_iter_open_container(iter_dict_entry,
    490 					      DBUS_TYPE_VARIANT,
    491 					      DBUS_TYPE_ARRAY_AS_STRING
    492 					      DBUS_TYPE_STRING_AS_STRING,
    493 					      iter_dict_val))
    494 		return FALSE;
    495 
    496 	if (!dbus_message_iter_open_container(iter_dict_val, DBUS_TYPE_ARRAY,
    497 					      DBUS_TYPE_BYTE_AS_STRING,
    498 					      iter_array))
    499 		return FALSE;
    500 
    501 	return TRUE;
    502 }
    503 
    504 
    505 /**
    506  * Add a single string element to a string array dict entry
    507  *
    508  * @param iter_array A valid DBusMessageIter returned from
    509  *                   wpa_dbus_dict_begin_string_array()'s
    510  *                   iter_array parameter
    511  * @param elem The string element to be added to the dict entry's string array
    512  * @return TRUE on success, FALSE on failure
    513  *
    514  */
    515 dbus_bool_t wpa_dbus_dict_string_array_add_element(DBusMessageIter *iter_array,
    516 						   const char *elem)
    517 {
    518 	if (!iter_array || !elem)
    519 		return FALSE;
    520 
    521 	return dbus_message_iter_append_basic(iter_array, DBUS_TYPE_STRING,
    522 					      &elem);
    523 }
    524 
    525 
    526 /**
    527  * End a string array dict entry
    528  *
    529  * @param iter_dict A valid DBusMessageIter returned from
    530  *                  wpa_dbus_dict_open_write()
    531  * @param iter_dict_entry A private DBusMessageIter returned from
    532  *                        wpa_dbus_dict_end_string_array()
    533  * @param iter_dict_val A private DBusMessageIter returned from
    534  *                      wpa_dbus_dict_end_string_array()
    535  * @param iter_array A DBusMessageIter returned from
    536  *                   wpa_dbus_dict_end_string_array()
    537  * @return TRUE on success, FALSE on failure
    538  *
    539  */
    540 dbus_bool_t wpa_dbus_dict_end_string_array(DBusMessageIter *iter_dict,
    541 					   DBusMessageIter *iter_dict_entry,
    542 					   DBusMessageIter *iter_dict_val,
    543 					   DBusMessageIter *iter_array)
    544 {
    545 	if (!iter_dict || !iter_dict_entry || !iter_dict_val || !iter_array)
    546 		return FALSE;
    547 
    548 	if (!dbus_message_iter_close_container(iter_dict_val, iter_array))
    549 		return FALSE;
    550 
    551 	if (!_wpa_dbus_add_dict_entry_end(iter_dict, iter_dict_entry,
    552 					  iter_dict_val))
    553 		return FALSE;
    554 
    555 	return TRUE;
    556 }
    557 
    558 
    559 /**
    560  * Convenience function to add an entire string array to the dict.
    561  *
    562  * @param iter_dict A valid DBusMessageIter returned from
    563  *                  wpa_dbus_dict_open_write()
    564  * @param key The key of the dict item
    565  * @param items The array of strings
    566  * @param num_items The number of strings in the array
    567  * @return TRUE on success, FALSE on failure
    568  *
    569  */
    570 dbus_bool_t wpa_dbus_dict_append_string_array(DBusMessageIter *iter_dict,
    571 					      const char *key,
    572 					      const char **items,
    573 					      const dbus_uint32_t num_items)
    574 {
    575 	DBusMessageIter iter_dict_entry, iter_dict_val, iter_array;
    576 	dbus_uint32_t i;
    577 
    578 	if (!key)
    579 		return FALSE;
    580 	if (!items && (num_items != 0))
    581 		return FALSE;
    582 
    583 	if (!wpa_dbus_dict_begin_string_array(iter_dict, key,
    584 					      &iter_dict_entry, &iter_dict_val,
    585 					      &iter_array))
    586 		return FALSE;
    587 
    588 	for (i = 0; i < num_items; i++) {
    589 		if (!wpa_dbus_dict_string_array_add_element(&iter_array,
    590 							    items[i]))
    591 			return FALSE;
    592 	}
    593 
    594 	if (!wpa_dbus_dict_end_string_array(iter_dict, &iter_dict_entry,
    595 					    &iter_dict_val, &iter_array))
    596 		return FALSE;
    597 
    598 	return TRUE;
    599 }
    600 
    601 
    602 /*****************************************************/
    603 /* Stuff for reading dicts                           */
    604 /*****************************************************/
    605 
    606 /**
    607  * Start reading from a dbus dict.
    608  *
    609  * @param iter A valid DBusMessageIter pointing to the start of the dict
    610  * @param iter_dict (out) A DBusMessageIter to be passed to
    611  *    wpa_dbus_dict_read_next_entry()
    612  * @return TRUE on success, FALSE on failure
    613  *
    614  */
    615 dbus_bool_t wpa_dbus_dict_open_read(DBusMessageIter *iter,
    616 				    DBusMessageIter *iter_dict)
    617 {
    618 	if (!iter || !iter_dict)
    619 		return FALSE;
    620 
    621 	if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY ||
    622 	    dbus_message_iter_get_element_type(iter) != DBUS_TYPE_DICT_ENTRY)
    623 		return FALSE;
    624 
    625 	dbus_message_iter_recurse(iter, iter_dict);
    626 	return TRUE;
    627 }
    628 
    629 
    630 #define BYTE_ARRAY_CHUNK_SIZE 34
    631 #define BYTE_ARRAY_ITEM_SIZE (sizeof(char))
    632 
    633 static dbus_bool_t _wpa_dbus_dict_entry_get_byte_array(
    634 	DBusMessageIter *iter, int array_type,
    635 	struct wpa_dbus_dict_entry *entry)
    636 {
    637 	dbus_uint32_t count = 0;
    638 	dbus_bool_t success = FALSE;
    639 	char *buffer;
    640 
    641 	entry->bytearray_value = NULL;
    642 	entry->array_type = DBUS_TYPE_BYTE;
    643 
    644 	buffer = os_zalloc(BYTE_ARRAY_ITEM_SIZE * BYTE_ARRAY_CHUNK_SIZE);
    645 	if (!buffer) {
    646 		perror("_wpa_dbus_dict_entry_get_byte_array[dbus]: out of "
    647 		       "memory");
    648 		goto done;
    649 	}
    650 
    651 	entry->bytearray_value = buffer;
    652 	entry->array_len = 0;
    653 	while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_BYTE) {
    654 		char byte;
    655 
    656 		if ((count % BYTE_ARRAY_CHUNK_SIZE) == 0 && count != 0) {
    657 			buffer = realloc(buffer, BYTE_ARRAY_ITEM_SIZE *
    658 					 (count + BYTE_ARRAY_CHUNK_SIZE));
    659 			if (buffer == NULL) {
    660 				perror("_wpa_dbus_dict_entry_get_byte_array["
    661 				       "dbus] out of memory trying to "
    662 				       "retrieve the string array");
    663 				goto done;
    664 			}
    665 		}
    666 		entry->bytearray_value = buffer;
    667 
    668 		dbus_message_iter_get_basic(iter, &byte);
    669 		entry->bytearray_value[count] = byte;
    670 		entry->array_len = ++count;
    671 		dbus_message_iter_next(iter);
    672 	}
    673 
    674 	/* Zero-length arrays are valid. */
    675 	if (entry->array_len == 0) {
    676 		free(entry->bytearray_value);
    677 		entry->bytearray_value = NULL;
    678 	}
    679 
    680 	success = TRUE;
    681 
    682 done:
    683 	return success;
    684 }
    685 
    686 
    687 #define STR_ARRAY_CHUNK_SIZE 8
    688 #define STR_ARRAY_ITEM_SIZE (sizeof(char *))
    689 
    690 static dbus_bool_t _wpa_dbus_dict_entry_get_string_array(
    691 	DBusMessageIter *iter, int array_type,
    692 	struct wpa_dbus_dict_entry *entry)
    693 {
    694 	dbus_uint32_t count = 0;
    695 	dbus_bool_t success = FALSE;
    696 	char **buffer;
    697 
    698 	entry->strarray_value = NULL;
    699 	entry->array_type = DBUS_TYPE_STRING;
    700 
    701 	buffer = os_zalloc(STR_ARRAY_ITEM_SIZE * STR_ARRAY_CHUNK_SIZE);
    702 	if (buffer == NULL) {
    703 		perror("_wpa_dbus_dict_entry_get_string_array[dbus] out of "
    704 		       "memory trying to retrieve a string array");
    705 		goto done;
    706 	}
    707 
    708 	entry->strarray_value = buffer;
    709 	entry->array_len = 0;
    710 	while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING) {
    711 		const char *value;
    712 		char *str;
    713 
    714 		if ((count % STR_ARRAY_CHUNK_SIZE) == 0 && count != 0) {
    715 			buffer = realloc(buffer, STR_ARRAY_ITEM_SIZE *
    716 					 (count + STR_ARRAY_CHUNK_SIZE));
    717 			if (buffer == NULL) {
    718 				perror("_wpa_dbus_dict_entry_get_string_array["
    719 				       "dbus] out of memory trying to "
    720 				       "retrieve the string array");
    721 				goto done;
    722 			}
    723 		}
    724 		entry->strarray_value = buffer;
    725 
    726 		dbus_message_iter_get_basic(iter, &value);
    727 		str = strdup(value);
    728 		if (str == NULL) {
    729 			perror("_wpa_dbus_dict_entry_get_string_array[dbus] "
    730 			       "out of memory trying to duplicate the string "
    731 			       "array");
    732 			goto done;
    733 		}
    734 		entry->strarray_value[count] = str;
    735 		entry->array_len = ++count;
    736 		dbus_message_iter_next(iter);
    737 	}
    738 
    739 	/* Zero-length arrays are valid. */
    740 	if (entry->array_len == 0) {
    741 		free(entry->strarray_value);
    742 		entry->strarray_value = NULL;
    743 	}
    744 
    745 	success = TRUE;
    746 
    747 done:
    748 	return success;
    749 }
    750 
    751 
    752 static dbus_bool_t _wpa_dbus_dict_entry_get_array(
    753 	DBusMessageIter *iter_dict_val, struct wpa_dbus_dict_entry *entry)
    754 {
    755 	int array_type = dbus_message_iter_get_element_type(iter_dict_val);
    756 	dbus_bool_t success = FALSE;
    757 	DBusMessageIter iter_array;
    758 
    759 	if (!entry)
    760 		return FALSE;
    761 
    762 	dbus_message_iter_recurse(iter_dict_val, &iter_array);
    763 
    764  	switch (array_type) {
    765 	case DBUS_TYPE_BYTE:
    766 		success = _wpa_dbus_dict_entry_get_byte_array(&iter_array,
    767 							      array_type,
    768 							      entry);
    769 		break;
    770 	case DBUS_TYPE_STRING:
    771 		success = _wpa_dbus_dict_entry_get_string_array(&iter_array,
    772 								array_type,
    773 								entry);
    774 		break;
    775 	default:
    776 		break;
    777 	}
    778 
    779 	return success;
    780 }
    781 
    782 
    783 static dbus_bool_t _wpa_dbus_dict_fill_value_from_variant(
    784 	struct wpa_dbus_dict_entry *entry, DBusMessageIter *iter_dict_val)
    785 {
    786 	dbus_bool_t success = TRUE;
    787 
    788 	switch (entry->type) {
    789 	case DBUS_TYPE_STRING: {
    790 		const char *v;
    791 		dbus_message_iter_get_basic(iter_dict_val, &v);
    792 		entry->str_value = strdup(v);
    793 		break;
    794 	}
    795 	case DBUS_TYPE_BOOLEAN: {
    796 		dbus_bool_t v;
    797 		dbus_message_iter_get_basic(iter_dict_val, &v);
    798 		entry->bool_value = v;
    799 		break;
    800 	}
    801 	case DBUS_TYPE_BYTE: {
    802 		char v;
    803 		dbus_message_iter_get_basic(iter_dict_val, &v);
    804 		entry->byte_value = v;
    805 		break;
    806 	}
    807 	case DBUS_TYPE_INT16: {
    808 		dbus_int16_t v;
    809 		dbus_message_iter_get_basic(iter_dict_val, &v);
    810 		entry->int16_value = v;
    811 		break;
    812 	}
    813 	case DBUS_TYPE_UINT16: {
    814 		dbus_uint16_t v;
    815 		dbus_message_iter_get_basic(iter_dict_val, &v);
    816 		entry->uint16_value = v;
    817 		break;
    818 	}
    819 	case DBUS_TYPE_INT32: {
    820 		dbus_int32_t v;
    821 		dbus_message_iter_get_basic(iter_dict_val, &v);
    822 		entry->int32_value = v;
    823 		break;
    824 	}
    825 	case DBUS_TYPE_UINT32: {
    826 		dbus_uint32_t v;
    827 		dbus_message_iter_get_basic(iter_dict_val, &v);
    828 		entry->uint32_value = v;
    829 		break;
    830 	}
    831 	case DBUS_TYPE_INT64: {
    832 		dbus_int64_t v;
    833 		dbus_message_iter_get_basic(iter_dict_val, &v);
    834 		entry->int64_value = v;
    835 		break;
    836 	}
    837 	case DBUS_TYPE_UINT64: {
    838 		dbus_uint64_t v;
    839 		dbus_message_iter_get_basic(iter_dict_val, &v);
    840 		entry->uint64_value = v;
    841 		break;
    842 	}
    843 	case DBUS_TYPE_DOUBLE: {
    844 		double v;
    845 		dbus_message_iter_get_basic(iter_dict_val, &v);
    846 		entry->double_value = v;
    847 		break;
    848 	}
    849 	case DBUS_TYPE_OBJECT_PATH: {
    850 		char *v;
    851 		dbus_message_iter_get_basic(iter_dict_val, &v);
    852 		entry->str_value = strdup(v);
    853 		break;
    854 	}
    855 	case DBUS_TYPE_ARRAY: {
    856 		success = _wpa_dbus_dict_entry_get_array(iter_dict_val, entry);
    857 		break;
    858 	}
    859 	default:
    860 		success = FALSE;
    861 		break;
    862 	}
    863 
    864 	return success;
    865 }
    866 
    867 
    868 /**
    869  * Read the current key/value entry from the dict.  Entries are dynamically
    870  * allocated when needed and must be freed after use with the
    871  * wpa_dbus_dict_entry_clear() function.
    872  *
    873  * The returned entry object will be filled with the type and value of the next
    874  * entry in the dict, or the type will be DBUS_TYPE_INVALID if an error
    875  * occurred.
    876  *
    877  * @param iter_dict A valid DBusMessageIter returned from
    878  *    wpa_dbus_dict_open_read()
    879  * @param entry A valid dict entry object into which the dict key and value
    880  *    will be placed
    881  * @return TRUE on success, FALSE on failure
    882  *
    883  */
    884 dbus_bool_t wpa_dbus_dict_get_entry(DBusMessageIter *iter_dict,
    885 				    struct wpa_dbus_dict_entry * entry)
    886 {
    887 	DBusMessageIter iter_dict_entry, iter_dict_val;
    888 	int type;
    889 	const char *key;
    890 
    891 	if (!iter_dict || !entry)
    892 		goto error;
    893 
    894 	if (dbus_message_iter_get_arg_type(iter_dict) != DBUS_TYPE_DICT_ENTRY)
    895 		goto error;
    896 
    897 	dbus_message_iter_recurse(iter_dict, &iter_dict_entry);
    898 	dbus_message_iter_get_basic(&iter_dict_entry, &key);
    899 	entry->key = key;
    900 
    901 	if (!dbus_message_iter_next(&iter_dict_entry))
    902 		goto error;
    903 	type = dbus_message_iter_get_arg_type(&iter_dict_entry);
    904 	if (type != DBUS_TYPE_VARIANT)
    905 		goto error;
    906 
    907 	dbus_message_iter_recurse(&iter_dict_entry, &iter_dict_val);
    908 	entry->type = dbus_message_iter_get_arg_type(&iter_dict_val);
    909 	if (!_wpa_dbus_dict_fill_value_from_variant(entry, &iter_dict_val))
    910 		goto error;
    911 
    912 	dbus_message_iter_next(iter_dict);
    913 	return TRUE;
    914 
    915 error:
    916 	if (entry) {
    917 		wpa_dbus_dict_entry_clear(entry);
    918 		entry->type = DBUS_TYPE_INVALID;
    919 		entry->array_type = DBUS_TYPE_INVALID;
    920 	}
    921 
    922 	return FALSE;
    923 }
    924 
    925 
    926 /**
    927  * Return whether or not there are additional dictionary entries.
    928  *
    929  * @param iter_dict A valid DBusMessageIter returned from
    930  *    wpa_dbus_dict_open_read()
    931  * @return TRUE if more dict entries exists, FALSE if no more dict entries
    932  * exist
    933  */
    934 dbus_bool_t wpa_dbus_dict_has_dict_entry(DBusMessageIter *iter_dict)
    935 {
    936 	if (!iter_dict) {
    937 		perror("wpa_dbus_dict_has_dict_entry[dbus]: out of memory");
    938 		return FALSE;
    939 	}
    940 	return dbus_message_iter_get_arg_type(iter_dict) ==
    941 		DBUS_TYPE_DICT_ENTRY;
    942 }
    943 
    944 
    945 /**
    946  * Free any memory used by the entry object.
    947  *
    948  * @param entry The entry object
    949  */
    950 void wpa_dbus_dict_entry_clear(struct wpa_dbus_dict_entry *entry)
    951 {
    952 	unsigned int i;
    953 
    954 	if (!entry)
    955 		return;
    956 	switch (entry->type) {
    957 	case DBUS_TYPE_OBJECT_PATH:
    958 	case DBUS_TYPE_STRING:
    959 		free(entry->str_value);
    960 		break;
    961 	case DBUS_TYPE_ARRAY:
    962 		switch (entry->array_type) {
    963 		case DBUS_TYPE_BYTE:
    964 			free(entry->bytearray_value);
    965 			break;
    966 		case DBUS_TYPE_STRING:
    967 			for (i = 0; i < entry->array_len; i++)
    968 				free(entry->strarray_value[i]);
    969 			free(entry->strarray_value);
    970 			break;
    971 		}
    972 		break;
    973 	}
    974 
    975 	memset(entry, 0, sizeof(struct wpa_dbus_dict_entry));
    976 }
    977