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