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