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