wpa_supplicant: update vendor branch to 0.6.10
[dragonfly.git] / contrib / wpa_supplicant / 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 "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 }