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