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 */
wpa_dbus_dict_open_write(DBusMessageIter * iter,DBusMessageIter * iter_dict)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 */
wpa_dbus_dict_close_write(DBusMessageIter * iter,DBusMessageIter * iter_dict)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
_wpa_get_type_as_string_from_type(const int type)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
_wpa_dbus_add_dict_entry_start(DBusMessageIter * iter_dict,DBusMessageIter * iter_dict_entry,const char * key,const int value_type)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
_wpa_dbus_add_dict_entry_end(DBusMessageIter * iter_dict,DBusMessageIter * iter_dict_entry,DBusMessageIter * iter_dict_val)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
_wpa_dbus_add_dict_entry_basic(DBusMessageIter * iter_dict,const char * key,const int value_type,const void * value)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
_wpa_dbus_add_dict_entry_byte_array(DBusMessageIter * iter_dict,const char * key,const char * value,const dbus_uint32_t value_len)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 */
wpa_dbus_dict_append_string(DBusMessageIter * iter_dict,const char * key,const char * value)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 */
wpa_dbus_dict_append_byte(DBusMessageIter * iter_dict,const char * key,const char value)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 */
wpa_dbus_dict_append_bool(DBusMessageIter * iter_dict,const char * key,const dbus_bool_t value)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 */
wpa_dbus_dict_append_int16(DBusMessageIter * iter_dict,const char * key,const dbus_int16_t value)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 */
wpa_dbus_dict_append_uint16(DBusMessageIter * iter_dict,const char * key,const dbus_uint16_t value)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 */
wpa_dbus_dict_append_int32(DBusMessageIter * iter_dict,const char * key,const dbus_int32_t value)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 */
wpa_dbus_dict_append_uint32(DBusMessageIter * iter_dict,const char * key,const dbus_uint32_t value)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 */
wpa_dbus_dict_append_int64(DBusMessageIter * iter_dict,const char * key,const dbus_int64_t value)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 */
wpa_dbus_dict_append_uint64(DBusMessageIter * iter_dict,const char * key,const dbus_uint64_t value)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 */
wpa_dbus_dict_append_double(DBusMessageIter * iter_dict,const char * key,const double value)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 */
wpa_dbus_dict_append_object_path(DBusMessageIter * iter_dict,const char * key,const char * value)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 */
wpa_dbus_dict_append_byte_array(DBusMessageIter * iter_dict,const char * key,const char * value,const dbus_uint32_t value_len)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 */
wpa_dbus_dict_begin_string_array(DBusMessageIter * iter_dict,const char * key,DBusMessageIter * iter_dict_entry,DBusMessageIter * iter_dict_val,DBusMessageIter * iter_array)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 */
wpa_dbus_dict_string_array_add_element(DBusMessageIter * iter_array,const char * elem)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 */
wpa_dbus_dict_end_string_array(DBusMessageIter * iter_dict,DBusMessageIter * iter_dict_entry,DBusMessageIter * iter_dict_val,DBusMessageIter * iter_array)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 */
wpa_dbus_dict_append_string_array(DBusMessageIter * iter_dict,const char * key,const char ** items,const dbus_uint32_t num_items)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 */
wpa_dbus_dict_open_read(DBusMessageIter * iter,DBusMessageIter * iter_dict)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 #define BYTE_ARRAY_CHUNK_SIZE 34
633 #define BYTE_ARRAY_ITEM_SIZE (sizeof (char))
634
_wpa_dbus_dict_entry_get_byte_array(DBusMessageIter * iter,int array_type,struct wpa_dbus_dict_entry * entry)635 static dbus_bool_t _wpa_dbus_dict_entry_get_byte_array(
636 DBusMessageIter *iter, int array_type,
637 struct wpa_dbus_dict_entry *entry)
638 {
639 dbus_uint32_t count = 0;
640 dbus_bool_t success = FALSE;
641 char *buffer;
642
643 entry->bytearray_value = NULL;
644 entry->array_type = DBUS_TYPE_BYTE;
645
646 buffer = wpa_zalloc(BYTE_ARRAY_ITEM_SIZE * BYTE_ARRAY_CHUNK_SIZE);
647 if (!buffer) {
648 perror("_wpa_dbus_dict_entry_get_byte_array[dbus]: out of "
649 "memory");
650 goto done;
651 }
652
653 entry->bytearray_value = buffer;
654 entry->array_len = 0;
655 while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_BYTE) {
656 char byte;
657
658 if ((count % BYTE_ARRAY_CHUNK_SIZE) == 0 && count != 0) {
659 buffer = realloc(buffer, BYTE_ARRAY_ITEM_SIZE *
660 (count + BYTE_ARRAY_CHUNK_SIZE));
661 if (buffer == NULL) {
662 perror("_wpa_dbus_dict_entry_get_byte_array["
663 "dbus] out of memory trying to "
664 "retrieve the string array");
665 goto done;
666 }
667 }
668 entry->bytearray_value = buffer;
669
670 dbus_message_iter_get_basic(iter, &byte);
671 entry->bytearray_value[count] = byte;
672 entry->array_len = ++count;
673 dbus_message_iter_next(iter);
674 }
675
676 /* Zero-length arrays are valid. */
677 if (entry->array_len == 0) {
678 free(entry->bytearray_value);
679 entry->bytearray_value = NULL;
680 }
681
682 success = TRUE;
683
684 done:
685 return success;
686 }
687
688
689 #define STR_ARRAY_CHUNK_SIZE 8
690 #define STR_ARRAY_ITEM_SIZE (sizeof (char *))
691
_wpa_dbus_dict_entry_get_string_array(DBusMessageIter * iter,int array_type,struct wpa_dbus_dict_entry * entry)692 static dbus_bool_t _wpa_dbus_dict_entry_get_string_array(
693 DBusMessageIter *iter, int array_type,
694 struct wpa_dbus_dict_entry *entry)
695 {
696 dbus_uint32_t count = 0;
697 dbus_bool_t success = FALSE;
698 char **buffer;
699
700 entry->strarray_value = NULL;
701 entry->array_type = DBUS_TYPE_STRING;
702
703 buffer = wpa_zalloc(STR_ARRAY_ITEM_SIZE * STR_ARRAY_CHUNK_SIZE);
704 if (buffer == NULL) {
705 perror("_wpa_dbus_dict_entry_get_string_array[dbus] out of "
706 "memory trying to retrieve a string array");
707 goto done;
708 }
709
710 entry->strarray_value = buffer;
711 entry->array_len = 0;
712 while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING) {
713 const char *value;
714 char *str;
715
716 if ((count % STR_ARRAY_CHUNK_SIZE) == 0 && count != 0) {
717 buffer = realloc(buffer, STR_ARRAY_ITEM_SIZE *
718 (count + STR_ARRAY_CHUNK_SIZE));
719 if (buffer == NULL) {
720 perror("_wpa_dbus_dict_entry_get_string_array["
721 "dbus] out of memory trying to "
722 "retrieve the string array");
723 goto done;
724 }
725 }
726 entry->strarray_value = buffer;
727
728 dbus_message_iter_get_basic(iter, &value);
729 str = strdup(value);
730 if (str == NULL) {
731 perror("_wpa_dbus_dict_entry_get_string_array[dbus] "
732 "out of memory trying to duplicate the string "
733 "array");
734 goto done;
735 }
736 entry->strarray_value[count] = str;
737 entry->array_len = ++count;
738 dbus_message_iter_next(iter);
739 }
740
741 /* Zero-length arrays are valid. */
742 if (entry->array_len == 0) {
743 free(entry->strarray_value);
744 entry->strarray_value = NULL;
745 }
746
747 success = TRUE;
748
749 done:
750 return success;
751 }
752
753
_wpa_dbus_dict_entry_get_array(DBusMessageIter * iter_dict_val,struct wpa_dbus_dict_entry * entry)754 static dbus_bool_t _wpa_dbus_dict_entry_get_array(
755 DBusMessageIter *iter_dict_val, struct wpa_dbus_dict_entry *entry)
756 {
757 int array_type = dbus_message_iter_get_element_type(iter_dict_val);
758 dbus_bool_t success = FALSE;
759 DBusMessageIter iter_array;
760
761 if (!entry)
762 return FALSE;
763
764 dbus_message_iter_recurse(iter_dict_val, &iter_array);
765
766 switch (array_type) {
767 case DBUS_TYPE_BYTE:
768 success = _wpa_dbus_dict_entry_get_byte_array(&iter_array,
769 array_type,
770 entry);
771 break;
772 case DBUS_TYPE_STRING:
773 success = _wpa_dbus_dict_entry_get_string_array(&iter_array,
774 array_type,
775 entry);
776 break;
777 default:
778 break;
779 }
780
781 return success;
782 }
783
784
_wpa_dbus_dict_fill_value_from_variant(struct wpa_dbus_dict_entry * entry,DBusMessageIter * iter_dict_val)785 static dbus_bool_t _wpa_dbus_dict_fill_value_from_variant(
786 struct wpa_dbus_dict_entry *entry, DBusMessageIter *iter_dict_val)
787 {
788 dbus_bool_t success = TRUE;
789
790 switch (entry->type) {
791 case DBUS_TYPE_STRING: {
792 const char *v;
793 dbus_message_iter_get_basic(iter_dict_val, &v);
794 entry->str_value = strdup(v);
795 break;
796 }
797 case DBUS_TYPE_BOOLEAN: {
798 dbus_bool_t v;
799 dbus_message_iter_get_basic(iter_dict_val, &v);
800 entry->bool_value = v;
801 break;
802 }
803 case DBUS_TYPE_BYTE: {
804 char v;
805 dbus_message_iter_get_basic(iter_dict_val, &v);
806 entry->byte_value = v;
807 break;
808 }
809 case DBUS_TYPE_INT16: {
810 dbus_int16_t v;
811 dbus_message_iter_get_basic(iter_dict_val, &v);
812 entry->int16_value = v;
813 break;
814 }
815 case DBUS_TYPE_UINT16: {
816 dbus_uint16_t v;
817 dbus_message_iter_get_basic(iter_dict_val, &v);
818 entry->uint16_value = v;
819 break;
820 }
821 case DBUS_TYPE_INT32: {
822 dbus_int32_t v;
823 dbus_message_iter_get_basic(iter_dict_val, &v);
824 entry->int32_value = v;
825 break;
826 }
827 case DBUS_TYPE_UINT32: {
828 dbus_uint32_t v;
829 dbus_message_iter_get_basic(iter_dict_val, &v);
830 entry->uint32_value = v;
831 break;
832 }
833 case DBUS_TYPE_INT64: {
834 dbus_int64_t v;
835 dbus_message_iter_get_basic(iter_dict_val, &v);
836 entry->int64_value = v;
837 break;
838 }
839 case DBUS_TYPE_UINT64: {
840 dbus_uint64_t v;
841 dbus_message_iter_get_basic(iter_dict_val, &v);
842 entry->uint64_value = v;
843 break;
844 }
845 case DBUS_TYPE_DOUBLE: {
846 double v;
847 dbus_message_iter_get_basic(iter_dict_val, &v);
848 entry->double_value = v;
849 break;
850 }
851 case DBUS_TYPE_OBJECT_PATH: {
852 char *v;
853 dbus_message_iter_get_basic(iter_dict_val, &v);
854 entry->str_value = strdup(v);
855 break;
856 }
857 case DBUS_TYPE_ARRAY: {
858 success = _wpa_dbus_dict_entry_get_array(iter_dict_val, entry);
859 break;
860 }
861 default:
862 success = FALSE;
863 break;
864 }
865
866 return success;
867 }
868
869
870 /**
871 * Read the current key/value entry from the dict. Entries are dynamically
872 * allocated when needed and must be freed after use with the
873 * {@link wpa_dbus_dict_entry_clear} function.
874 *
875 * The returned entry object will be filled with the type and value of the next
876 * entry in the dict, or the type will be DBUS_TYPE_INVALID if an error
877 * occurred.
878 *
879 * @param iter_dict A valid DBusMessageIter returned from
880 * {@link wpa_dbus_dict_open_read}
881 * @param entry A valid dict entry object into which the dict key and value
882 * will be placed
883 * @return TRUE on success, FALSE on failure
884 *
885 */
wpa_dbus_dict_get_entry(DBusMessageIter * iter_dict,struct wpa_dbus_dict_entry * entry)886 dbus_bool_t wpa_dbus_dict_get_entry(DBusMessageIter *iter_dict,
887 struct wpa_dbus_dict_entry * entry)
888 {
889 DBusMessageIter iter_dict_entry, iter_dict_val;
890 int type;
891 const char *key;
892
893 if (!iter_dict || !entry)
894 goto error;
895
896 if (dbus_message_iter_get_arg_type(iter_dict) != DBUS_TYPE_DICT_ENTRY)
897 goto error;
898
899 dbus_message_iter_recurse(iter_dict, &iter_dict_entry);
900 dbus_message_iter_get_basic(&iter_dict_entry, &key);
901 entry->key = key;
902
903 if (!dbus_message_iter_next(&iter_dict_entry))
904 goto error;
905 type = dbus_message_iter_get_arg_type(&iter_dict_entry);
906 if (type != DBUS_TYPE_VARIANT)
907 goto error;
908
909 dbus_message_iter_recurse(&iter_dict_entry, &iter_dict_val);
910 entry->type = dbus_message_iter_get_arg_type(&iter_dict_val);
911 if (!_wpa_dbus_dict_fill_value_from_variant(entry, &iter_dict_val))
912 goto error;
913
914 dbus_message_iter_next(iter_dict);
915 return TRUE;
916
917 error:
918 if (entry) {
919 wpa_dbus_dict_entry_clear(entry);
920 entry->type = DBUS_TYPE_INVALID;
921 entry->array_type = DBUS_TYPE_INVALID;
922 }
923
924 return FALSE;
925 }
926
927
928 /**
929 * Return whether or not there are additional dictionary entries.
930 *
931 * @param iter_dict A valid DBusMessageIter returned from
932 * {@link wpa_dbus_dict_open_read}
933 * @return TRUE if more dict entries exists, FALSE if no more dict entries
934 * exist
935 */
wpa_dbus_dict_has_dict_entry(DBusMessageIter * iter_dict)936 dbus_bool_t wpa_dbus_dict_has_dict_entry(DBusMessageIter *iter_dict)
937 {
938 if (!iter_dict) {
939 perror("wpa_dbus_dict_has_dict_entry[dbus]: out of memory");
940 return FALSE;
941 }
942 return dbus_message_iter_get_arg_type(iter_dict) ==
943 DBUS_TYPE_DICT_ENTRY;
944 }
945
946
947 /**
948 * Free any memory used by the entry object.
949 *
950 * @param entry The entry object
951 */
wpa_dbus_dict_entry_clear(struct wpa_dbus_dict_entry * entry)952 void wpa_dbus_dict_entry_clear(struct wpa_dbus_dict_entry *entry)
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 }
967 case DBUS_TYPE_STRING: {
968 unsigned int i;
969 for (i = 0; i < entry->array_len; i++)
970 free(entry->strarray_value[i]);
971 free(entry->strarray_value);
972 break;
973 }
974 }
975 break;
976 }
977
978 memset(entry, 0, sizeof(struct wpa_dbus_dict_entry));
979 }
980