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