1214501Srpaulo/*
2214501Srpaulo * WPA Supplicant / dbus-based control interface
3214501Srpaulo * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
4214501Srpaulo *
5252190Srpaulo * This software may be distributed under the terms of the BSD license.
6252190Srpaulo * See README for more details.
7214501Srpaulo */
8214501Srpaulo
9214501Srpaulo#include "includes.h"
10214501Srpaulo#include <dbus/dbus.h>
11214501Srpaulo
12214501Srpaulo#include "common.h"
13252190Srpaulo#include "wpabuf.h"
14214501Srpaulo#include "dbus_dict_helpers.h"
15214501Srpaulo
16214501Srpaulo
17214501Srpaulo/**
18214501Srpaulo * Start a dict in a dbus message.  Should be paired with a call to
19214501Srpaulo * wpa_dbus_dict_close_write().
20214501Srpaulo *
21214501Srpaulo * @param iter A valid dbus message iterator
22214501Srpaulo * @param iter_dict (out) A dict iterator to pass to further dict functions
23214501Srpaulo * @return TRUE on success, FALSE on failure
24214501Srpaulo *
25214501Srpaulo */
26214501Srpaulodbus_bool_t wpa_dbus_dict_open_write(DBusMessageIter *iter,
27214501Srpaulo				     DBusMessageIter *iter_dict)
28214501Srpaulo{
29214501Srpaulo	dbus_bool_t result;
30214501Srpaulo
31214501Srpaulo	if (!iter || !iter_dict)
32214501Srpaulo		return FALSE;
33214501Srpaulo
34214501Srpaulo	result = dbus_message_iter_open_container(
35214501Srpaulo		iter,
36214501Srpaulo		DBUS_TYPE_ARRAY,
37214501Srpaulo		DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
38214501Srpaulo		DBUS_TYPE_STRING_AS_STRING
39214501Srpaulo		DBUS_TYPE_VARIANT_AS_STRING
40214501Srpaulo		DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
41214501Srpaulo		iter_dict);
42214501Srpaulo	return result;
43214501Srpaulo}
44214501Srpaulo
45214501Srpaulo
46214501Srpaulo/**
47214501Srpaulo * End a dict element in a dbus message.  Should be paired with
48214501Srpaulo * a call to wpa_dbus_dict_open_write().
49214501Srpaulo *
50214501Srpaulo * @param iter valid dbus message iterator, same as passed to
51214501Srpaulo *    wpa_dbus_dict_open_write()
52214501Srpaulo * @param iter_dict a dbus dict iterator returned from
53214501Srpaulo *    wpa_dbus_dict_open_write()
54214501Srpaulo * @return TRUE on success, FALSE on failure
55214501Srpaulo *
56214501Srpaulo */
57214501Srpaulodbus_bool_t wpa_dbus_dict_close_write(DBusMessageIter *iter,
58214501Srpaulo				      DBusMessageIter *iter_dict)
59214501Srpaulo{
60214501Srpaulo	if (!iter || !iter_dict)
61214501Srpaulo		return FALSE;
62214501Srpaulo
63214501Srpaulo	return dbus_message_iter_close_container(iter, iter_dict);
64214501Srpaulo}
65214501Srpaulo
66214501Srpaulo
67214501Srpauloconst char * wpa_dbus_type_as_string(const int type)
68214501Srpaulo{
69281806Srpaulo	switch (type) {
70214501Srpaulo	case DBUS_TYPE_BYTE:
71214501Srpaulo		return DBUS_TYPE_BYTE_AS_STRING;
72214501Srpaulo	case DBUS_TYPE_BOOLEAN:
73214501Srpaulo		return DBUS_TYPE_BOOLEAN_AS_STRING;
74214501Srpaulo	case DBUS_TYPE_INT16:
75214501Srpaulo		return DBUS_TYPE_INT16_AS_STRING;
76214501Srpaulo	case DBUS_TYPE_UINT16:
77214501Srpaulo		return DBUS_TYPE_UINT16_AS_STRING;
78214501Srpaulo	case DBUS_TYPE_INT32:
79214501Srpaulo		return DBUS_TYPE_INT32_AS_STRING;
80214501Srpaulo	case DBUS_TYPE_UINT32:
81214501Srpaulo		return DBUS_TYPE_UINT32_AS_STRING;
82214501Srpaulo	case DBUS_TYPE_INT64:
83214501Srpaulo		return DBUS_TYPE_INT64_AS_STRING;
84214501Srpaulo	case DBUS_TYPE_UINT64:
85214501Srpaulo		return DBUS_TYPE_UINT64_AS_STRING;
86214501Srpaulo	case DBUS_TYPE_DOUBLE:
87214501Srpaulo		return DBUS_TYPE_DOUBLE_AS_STRING;
88214501Srpaulo	case DBUS_TYPE_STRING:
89214501Srpaulo		return DBUS_TYPE_STRING_AS_STRING;
90214501Srpaulo	case DBUS_TYPE_OBJECT_PATH:
91214501Srpaulo		return DBUS_TYPE_OBJECT_PATH_AS_STRING;
92214501Srpaulo	case DBUS_TYPE_ARRAY:
93214501Srpaulo		return DBUS_TYPE_ARRAY_AS_STRING;
94214501Srpaulo	default:
95214501Srpaulo		return NULL;
96214501Srpaulo	}
97214501Srpaulo}
98214501Srpaulo
99214501Srpaulo
100214501Srpaulostatic dbus_bool_t _wpa_dbus_add_dict_entry_start(
101214501Srpaulo	DBusMessageIter *iter_dict, DBusMessageIter *iter_dict_entry,
102214501Srpaulo	const char *key, const int value_type)
103214501Srpaulo{
104214501Srpaulo	if (!dbus_message_iter_open_container(iter_dict,
105214501Srpaulo					      DBUS_TYPE_DICT_ENTRY, NULL,
106214501Srpaulo					      iter_dict_entry))
107214501Srpaulo		return FALSE;
108214501Srpaulo
109281806Srpaulo	return dbus_message_iter_append_basic(iter_dict_entry, DBUS_TYPE_STRING,
110281806Srpaulo					      &key);
111214501Srpaulo}
112214501Srpaulo
113214501Srpaulo
114214501Srpaulostatic dbus_bool_t _wpa_dbus_add_dict_entry_end(
115214501Srpaulo	DBusMessageIter *iter_dict, DBusMessageIter *iter_dict_entry,
116214501Srpaulo	DBusMessageIter *iter_dict_val)
117214501Srpaulo{
118214501Srpaulo	if (!dbus_message_iter_close_container(iter_dict_entry, iter_dict_val))
119214501Srpaulo		return FALSE;
120214501Srpaulo
121281806Srpaulo	return dbus_message_iter_close_container(iter_dict, iter_dict_entry);
122214501Srpaulo}
123214501Srpaulo
124214501Srpaulo
125214501Srpaulostatic dbus_bool_t _wpa_dbus_add_dict_entry_basic(DBusMessageIter *iter_dict,
126214501Srpaulo						  const char *key,
127214501Srpaulo						  const int value_type,
128214501Srpaulo						  const void *value)
129214501Srpaulo{
130214501Srpaulo	DBusMessageIter iter_dict_entry, iter_dict_val;
131214501Srpaulo	const char *type_as_string = NULL;
132214501Srpaulo
133214501Srpaulo	if (key == NULL)
134214501Srpaulo		return FALSE;
135214501Srpaulo
136214501Srpaulo	type_as_string = wpa_dbus_type_as_string(value_type);
137214501Srpaulo	if (!type_as_string)
138214501Srpaulo		return FALSE;
139214501Srpaulo
140214501Srpaulo	if (!_wpa_dbus_add_dict_entry_start(iter_dict, &iter_dict_entry,
141281806Srpaulo					    key, value_type) ||
142281806Srpaulo	    !dbus_message_iter_open_container(&iter_dict_entry,
143214501Srpaulo					      DBUS_TYPE_VARIANT,
144281806Srpaulo					      type_as_string, &iter_dict_val) ||
145281806Srpaulo	    !dbus_message_iter_append_basic(&iter_dict_val, value_type, value))
146214501Srpaulo		return FALSE;
147214501Srpaulo
148281806Srpaulo	return _wpa_dbus_add_dict_entry_end(iter_dict, &iter_dict_entry,
149281806Srpaulo					    &iter_dict_val);
150214501Srpaulo}
151214501Srpaulo
152214501Srpaulo
153214501Srpaulostatic dbus_bool_t _wpa_dbus_add_dict_entry_byte_array(
154214501Srpaulo	DBusMessageIter *iter_dict, const char *key,
155214501Srpaulo	const char *value, const dbus_uint32_t value_len)
156214501Srpaulo{
157214501Srpaulo	DBusMessageIter iter_dict_entry, iter_dict_val, iter_array;
158214501Srpaulo	dbus_uint32_t i;
159214501Srpaulo
160214501Srpaulo	if (!_wpa_dbus_add_dict_entry_start(iter_dict, &iter_dict_entry,
161281806Srpaulo					    key, DBUS_TYPE_ARRAY) ||
162281806Srpaulo	    !dbus_message_iter_open_container(&iter_dict_entry,
163214501Srpaulo					      DBUS_TYPE_VARIANT,
164214501Srpaulo					      DBUS_TYPE_ARRAY_AS_STRING
165214501Srpaulo					      DBUS_TYPE_BYTE_AS_STRING,
166281806Srpaulo					      &iter_dict_val) ||
167281806Srpaulo	    !dbus_message_iter_open_container(&iter_dict_val, DBUS_TYPE_ARRAY,
168214501Srpaulo					      DBUS_TYPE_BYTE_AS_STRING,
169214501Srpaulo					      &iter_array))
170214501Srpaulo		return FALSE;
171214501Srpaulo
172214501Srpaulo	for (i = 0; i < value_len; i++) {
173214501Srpaulo		if (!dbus_message_iter_append_basic(&iter_array,
174214501Srpaulo						    DBUS_TYPE_BYTE,
175214501Srpaulo						    &(value[i])))
176214501Srpaulo			return FALSE;
177214501Srpaulo	}
178214501Srpaulo
179214501Srpaulo	if (!dbus_message_iter_close_container(&iter_dict_val, &iter_array))
180214501Srpaulo		return FALSE;
181214501Srpaulo
182281806Srpaulo	return _wpa_dbus_add_dict_entry_end(iter_dict, &iter_dict_entry,
183281806Srpaulo					    &iter_dict_val);
184214501Srpaulo}
185214501Srpaulo
186214501Srpaulo
187214501Srpaulo/**
188214501Srpaulo * Add a string entry to the dict.
189214501Srpaulo *
190214501Srpaulo * @param iter_dict A valid DBusMessageIter returned from
191214501Srpaulo *    wpa_dbus_dict_open_write()
192214501Srpaulo * @param key The key of the dict item
193214501Srpaulo * @param value The string value
194214501Srpaulo * @return TRUE on success, FALSE on failure
195214501Srpaulo *
196214501Srpaulo */
197214501Srpaulodbus_bool_t wpa_dbus_dict_append_string(DBusMessageIter *iter_dict,
198214501Srpaulo					const char *key, const char *value)
199214501Srpaulo{
200214501Srpaulo	if (!value)
201214501Srpaulo		return FALSE;
202214501Srpaulo	return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_STRING,
203214501Srpaulo					      &value);
204214501Srpaulo}
205214501Srpaulo
206214501Srpaulo
207214501Srpaulo/**
208214501Srpaulo * Add a byte entry to the dict.
209214501Srpaulo *
210214501Srpaulo * @param iter_dict A valid DBusMessageIter returned from
211214501Srpaulo *    wpa_dbus_dict_open_write()
212214501Srpaulo * @param key The key of the dict item
213214501Srpaulo * @param value The byte value
214214501Srpaulo * @return TRUE on success, FALSE on failure
215214501Srpaulo *
216214501Srpaulo */
217214501Srpaulodbus_bool_t wpa_dbus_dict_append_byte(DBusMessageIter *iter_dict,
218214501Srpaulo				      const char *key, const char value)
219214501Srpaulo{
220214501Srpaulo	return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_BYTE,
221214501Srpaulo					      &value);
222214501Srpaulo}
223214501Srpaulo
224214501Srpaulo
225214501Srpaulo/**
226214501Srpaulo * Add a boolean entry to the dict.
227214501Srpaulo *
228214501Srpaulo * @param iter_dict A valid DBusMessageIter returned from
229214501Srpaulo *    wpa_dbus_dict_open_write()
230214501Srpaulo * @param key The key of the dict item
231214501Srpaulo * @param value The boolean value
232214501Srpaulo * @return TRUE on success, FALSE on failure
233214501Srpaulo *
234214501Srpaulo */
235214501Srpaulodbus_bool_t wpa_dbus_dict_append_bool(DBusMessageIter *iter_dict,
236214501Srpaulo				      const char *key, const dbus_bool_t value)
237214501Srpaulo{
238214501Srpaulo	return _wpa_dbus_add_dict_entry_basic(iter_dict, key,
239214501Srpaulo					      DBUS_TYPE_BOOLEAN, &value);
240214501Srpaulo}
241214501Srpaulo
242214501Srpaulo
243214501Srpaulo/**
244214501Srpaulo * Add a 16-bit signed integer entry to the dict.
245214501Srpaulo *
246214501Srpaulo * @param iter_dict A valid DBusMessageIter returned from
247214501Srpaulo *    wpa_dbus_dict_open_write()
248214501Srpaulo * @param key The key of the dict item
249214501Srpaulo * @param value The 16-bit signed integer value
250214501Srpaulo * @return TRUE on success, FALSE on failure
251214501Srpaulo *
252214501Srpaulo */
253214501Srpaulodbus_bool_t wpa_dbus_dict_append_int16(DBusMessageIter *iter_dict,
254214501Srpaulo				       const char *key,
255214501Srpaulo				       const dbus_int16_t value)
256214501Srpaulo{
257214501Srpaulo	return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_INT16,
258214501Srpaulo					      &value);
259214501Srpaulo}
260214501Srpaulo
261214501Srpaulo
262214501Srpaulo/**
263214501Srpaulo * Add a 16-bit unsigned integer entry to the dict.
264214501Srpaulo *
265214501Srpaulo * @param iter_dict A valid DBusMessageIter returned from
266214501Srpaulo *    wpa_dbus_dict_open_write()
267214501Srpaulo * @param key The key of the dict item
268214501Srpaulo * @param value The 16-bit unsigned integer value
269214501Srpaulo * @return TRUE on success, FALSE on failure
270214501Srpaulo *
271214501Srpaulo */
272214501Srpaulodbus_bool_t wpa_dbus_dict_append_uint16(DBusMessageIter *iter_dict,
273214501Srpaulo					const char *key,
274214501Srpaulo					const dbus_uint16_t value)
275214501Srpaulo{
276214501Srpaulo	return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_UINT16,
277214501Srpaulo					      &value);
278214501Srpaulo}
279214501Srpaulo
280214501Srpaulo
281214501Srpaulo/**
282214501Srpaulo * Add a 32-bit signed integer to the dict.
283214501Srpaulo *
284214501Srpaulo * @param iter_dict A valid DBusMessageIter returned from
285214501Srpaulo *    wpa_dbus_dict_open_write()
286214501Srpaulo * @param key The key of the dict item
287214501Srpaulo * @param value The 32-bit signed integer value
288214501Srpaulo * @return TRUE on success, FALSE on failure
289214501Srpaulo *
290214501Srpaulo */
291214501Srpaulodbus_bool_t wpa_dbus_dict_append_int32(DBusMessageIter *iter_dict,
292214501Srpaulo				       const char *key,
293214501Srpaulo				       const dbus_int32_t value)
294214501Srpaulo{
295214501Srpaulo	return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_INT32,
296214501Srpaulo					      &value);
297214501Srpaulo}
298214501Srpaulo
299214501Srpaulo
300214501Srpaulo/**
301214501Srpaulo * Add a 32-bit unsigned integer entry to the dict.
302214501Srpaulo *
303214501Srpaulo * @param iter_dict A valid DBusMessageIter returned from
304214501Srpaulo *    wpa_dbus_dict_open_write()
305214501Srpaulo * @param key The key of the dict item
306214501Srpaulo * @param value The 32-bit unsigned integer value
307214501Srpaulo * @return TRUE on success, FALSE on failure
308214501Srpaulo *
309214501Srpaulo */
310214501Srpaulodbus_bool_t wpa_dbus_dict_append_uint32(DBusMessageIter *iter_dict,
311214501Srpaulo					const char *key,
312214501Srpaulo					const dbus_uint32_t value)
313214501Srpaulo{
314214501Srpaulo	return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_UINT32,
315214501Srpaulo					      &value);
316214501Srpaulo}
317214501Srpaulo
318214501Srpaulo
319214501Srpaulo/**
320214501Srpaulo * Add a 64-bit integer entry to the dict.
321214501Srpaulo *
322214501Srpaulo * @param iter_dict A valid DBusMessageIter returned from
323214501Srpaulo *    wpa_dbus_dict_open_write()
324214501Srpaulo * @param key The key of the dict item
325214501Srpaulo * @param value The 64-bit integer value
326214501Srpaulo * @return TRUE on success, FALSE on failure
327214501Srpaulo *
328214501Srpaulo */
329214501Srpaulodbus_bool_t wpa_dbus_dict_append_int64(DBusMessageIter *iter_dict,
330214501Srpaulo				       const char *key,
331214501Srpaulo				       const dbus_int64_t value)
332214501Srpaulo{
333214501Srpaulo	return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_INT64,
334214501Srpaulo					      &value);
335214501Srpaulo}
336214501Srpaulo
337214501Srpaulo
338214501Srpaulo/**
339214501Srpaulo * Add a 64-bit unsigned integer entry to the dict.
340214501Srpaulo *
341214501Srpaulo * @param iter_dict A valid DBusMessageIter returned from
342214501Srpaulo *    wpa_dbus_dict_open_write()
343214501Srpaulo * @param key The key of the dict item
344214501Srpaulo * @param value The 64-bit unsigned integer value
345214501Srpaulo * @return TRUE on success, FALSE on failure
346214501Srpaulo *
347214501Srpaulo */
348214501Srpaulodbus_bool_t wpa_dbus_dict_append_uint64(DBusMessageIter *iter_dict,
349214501Srpaulo					const char *key,
350214501Srpaulo					const dbus_uint64_t value)
351214501Srpaulo{
352214501Srpaulo	return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_UINT64,
353214501Srpaulo					      &value);
354214501Srpaulo}
355214501Srpaulo
356214501Srpaulo
357214501Srpaulo/**
358214501Srpaulo * Add a double-precision floating point entry to the dict.
359214501Srpaulo *
360214501Srpaulo * @param iter_dict A valid DBusMessageIter returned from
361214501Srpaulo *    wpa_dbus_dict_open_write()
362214501Srpaulo * @param key The key of the dict item
363214501Srpaulo * @param value The double-precision floating point value
364214501Srpaulo * @return TRUE on success, FALSE on failure
365214501Srpaulo *
366214501Srpaulo */
367214501Srpaulodbus_bool_t wpa_dbus_dict_append_double(DBusMessageIter *iter_dict,
368214501Srpaulo					const char *key, const double value)
369214501Srpaulo{
370214501Srpaulo	return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_DOUBLE,
371214501Srpaulo					      &value);
372214501Srpaulo}
373214501Srpaulo
374214501Srpaulo
375214501Srpaulo/**
376214501Srpaulo * Add a DBus object path entry to the dict.
377214501Srpaulo *
378214501Srpaulo * @param iter_dict A valid DBusMessageIter returned from
379214501Srpaulo *    wpa_dbus_dict_open_write()
380214501Srpaulo * @param key The key of the dict item
381214501Srpaulo * @param value The DBus object path value
382214501Srpaulo * @return TRUE on success, FALSE on failure
383214501Srpaulo *
384214501Srpaulo */
385214501Srpaulodbus_bool_t wpa_dbus_dict_append_object_path(DBusMessageIter *iter_dict,
386214501Srpaulo					     const char *key,
387214501Srpaulo					     const char *value)
388214501Srpaulo{
389214501Srpaulo	if (!value)
390214501Srpaulo		return FALSE;
391214501Srpaulo	return _wpa_dbus_add_dict_entry_basic(iter_dict, key,
392214501Srpaulo					      DBUS_TYPE_OBJECT_PATH, &value);
393214501Srpaulo}
394214501Srpaulo
395214501Srpaulo
396214501Srpaulo/**
397214501Srpaulo * Add a byte array entry to the dict.
398214501Srpaulo *
399214501Srpaulo * @param iter_dict A valid DBusMessageIter returned from
400214501Srpaulo *    wpa_dbus_dict_open_write()
401214501Srpaulo * @param key The key of the dict item
402214501Srpaulo * @param value The byte array
403214501Srpaulo * @param value_len The length of the byte array, in bytes
404214501Srpaulo * @return TRUE on success, FALSE on failure
405214501Srpaulo *
406214501Srpaulo */
407214501Srpaulodbus_bool_t wpa_dbus_dict_append_byte_array(DBusMessageIter *iter_dict,
408214501Srpaulo					    const char *key,
409214501Srpaulo					    const char *value,
410214501Srpaulo					    const dbus_uint32_t value_len)
411214501Srpaulo{
412281806Srpaulo	if (!key || (!value && value_len != 0))
413214501Srpaulo		return FALSE;
414214501Srpaulo	return _wpa_dbus_add_dict_entry_byte_array(iter_dict, key, value,
415214501Srpaulo						   value_len);
416214501Srpaulo}
417214501Srpaulo
418214501Srpaulo
419214501Srpaulo/**
420252190Srpaulo * Begin an array entry in the dict
421214501Srpaulo *
422214501Srpaulo * @param iter_dict A valid DBusMessageIter returned from
423214501Srpaulo *                  wpa_dbus_dict_open_write()
424214501Srpaulo * @param key The key of the dict item
425252190Srpaulo * @param type The type of the contained data
426214501Srpaulo * @param iter_dict_entry A private DBusMessageIter provided by the caller to
427214501Srpaulo *                        be passed to wpa_dbus_dict_end_string_array()
428214501Srpaulo * @param iter_dict_val A private DBusMessageIter provided by the caller to
429214501Srpaulo *                      be passed to wpa_dbus_dict_end_string_array()
430214501Srpaulo * @param iter_array On return, the DBusMessageIter to be passed to
431214501Srpaulo *                   wpa_dbus_dict_string_array_add_element()
432214501Srpaulo * @return TRUE on success, FALSE on failure
433214501Srpaulo *
434214501Srpaulo */
435252190Srpaulodbus_bool_t wpa_dbus_dict_begin_array(DBusMessageIter *iter_dict,
436252190Srpaulo				      const char *key, const char *type,
437252190Srpaulo				      DBusMessageIter *iter_dict_entry,
438252190Srpaulo				      DBusMessageIter *iter_dict_val,
439252190Srpaulo				      DBusMessageIter *iter_array)
440214501Srpaulo{
441252190Srpaulo	char array_type[10];
442252190Srpaulo	int err;
443252190Srpaulo
444252190Srpaulo	err = os_snprintf(array_type, sizeof(array_type),
445252190Srpaulo			  DBUS_TYPE_ARRAY_AS_STRING "%s",
446252190Srpaulo			  type);
447281806Srpaulo	if (os_snprintf_error(sizeof(array_type), err))
448252190Srpaulo		return FALSE;
449252190Srpaulo
450281806Srpaulo	if (!iter_dict || !iter_dict_entry || !iter_dict_val || !iter_array ||
451281806Srpaulo	    !_wpa_dbus_add_dict_entry_start(iter_dict, iter_dict_entry,
452281806Srpaulo					    key, DBUS_TYPE_ARRAY) ||
453281806Srpaulo	    !dbus_message_iter_open_container(iter_dict_entry,
454214501Srpaulo					      DBUS_TYPE_VARIANT,
455252190Srpaulo					      array_type,
456214501Srpaulo					      iter_dict_val))
457214501Srpaulo		return FALSE;
458214501Srpaulo
459281806Srpaulo	return dbus_message_iter_open_container(iter_dict_val, DBUS_TYPE_ARRAY,
460281806Srpaulo						type, iter_array);
461214501Srpaulo}
462214501Srpaulo
463214501Srpaulo
464252190Srpaulodbus_bool_t wpa_dbus_dict_begin_string_array(DBusMessageIter *iter_dict,
465252190Srpaulo					     const char *key,
466252190Srpaulo					     DBusMessageIter *iter_dict_entry,
467252190Srpaulo					     DBusMessageIter *iter_dict_val,
468252190Srpaulo					     DBusMessageIter *iter_array)
469252190Srpaulo{
470252190Srpaulo	return wpa_dbus_dict_begin_array(
471252190Srpaulo		iter_dict, key,
472252190Srpaulo		DBUS_TYPE_STRING_AS_STRING,
473252190Srpaulo		iter_dict_entry, iter_dict_val, iter_array);
474252190Srpaulo}
475252190Srpaulo
476252190Srpaulo
477214501Srpaulo/**
478214501Srpaulo * Add a single string element to a string array dict entry
479214501Srpaulo *
480214501Srpaulo * @param iter_array A valid DBusMessageIter returned from
481214501Srpaulo *                   wpa_dbus_dict_begin_string_array()'s
482214501Srpaulo *                   iter_array parameter
483214501Srpaulo * @param elem The string element to be added to the dict entry's string array
484214501Srpaulo * @return TRUE on success, FALSE on failure
485214501Srpaulo *
486214501Srpaulo */
487214501Srpaulodbus_bool_t wpa_dbus_dict_string_array_add_element(DBusMessageIter *iter_array,
488214501Srpaulo						   const char *elem)
489214501Srpaulo{
490214501Srpaulo	if (!iter_array || !elem)
491214501Srpaulo		return FALSE;
492214501Srpaulo
493214501Srpaulo	return dbus_message_iter_append_basic(iter_array, DBUS_TYPE_STRING,
494214501Srpaulo					      &elem);
495214501Srpaulo}
496214501Srpaulo
497214501Srpaulo
498214501Srpaulo/**
499252190Srpaulo * Add a single byte array element to a string array dict entry
500214501Srpaulo *
501252190Srpaulo * @param iter_array A valid DBusMessageIter returned from
502252190Srpaulo *                   wpa_dbus_dict_begin_array()'s iter_array
503252190Srpaulo *                   parameter -- note that wpa_dbus_dict_begin_array()
504252190Srpaulo *                   must have been called with "ay" as the type
505252190Srpaulo * @param value The data to be added to the dict entry's array
506252190Srpaulo * @param value_len The length of the data
507252190Srpaulo * @return TRUE on success, FALSE on failure
508252190Srpaulo *
509252190Srpaulo */
510252190Srpaulodbus_bool_t wpa_dbus_dict_bin_array_add_element(DBusMessageIter *iter_array,
511252190Srpaulo						const u8 *value,
512252190Srpaulo						size_t value_len)
513252190Srpaulo{
514252190Srpaulo	DBusMessageIter iter_bytes;
515252190Srpaulo	size_t i;
516252190Srpaulo
517281806Srpaulo	if (!iter_array || !value ||
518281806Srpaulo	    !dbus_message_iter_open_container(iter_array, DBUS_TYPE_ARRAY,
519252190Srpaulo					      DBUS_TYPE_BYTE_AS_STRING,
520252190Srpaulo					      &iter_bytes))
521252190Srpaulo		return FALSE;
522252190Srpaulo
523252190Srpaulo	for (i = 0; i < value_len; i++) {
524252190Srpaulo		if (!dbus_message_iter_append_basic(&iter_bytes,
525252190Srpaulo						    DBUS_TYPE_BYTE,
526252190Srpaulo						    &(value[i])))
527252190Srpaulo			return FALSE;
528252190Srpaulo	}
529252190Srpaulo
530281806Srpaulo	return dbus_message_iter_close_container(iter_array, &iter_bytes);
531252190Srpaulo}
532252190Srpaulo
533252190Srpaulo
534252190Srpaulo/**
535252190Srpaulo * End an array dict entry
536252190Srpaulo *
537214501Srpaulo * @param iter_dict A valid DBusMessageIter returned from
538214501Srpaulo *                  wpa_dbus_dict_open_write()
539214501Srpaulo * @param iter_dict_entry A private DBusMessageIter returned from
540252190Srpaulo *                        wpa_dbus_dict_begin_string_array() or
541252190Srpaulo *			  wpa_dbus_dict_begin_array()
542214501Srpaulo * @param iter_dict_val A private DBusMessageIter returned from
543252190Srpaulo *                      wpa_dbus_dict_begin_string_array() or
544252190Srpaulo *			wpa_dbus_dict_begin_array()
545214501Srpaulo * @param iter_array A DBusMessageIter returned from
546252190Srpaulo *                   wpa_dbus_dict_begin_string_array() or
547252190Srpaulo *		     wpa_dbus_dict_begin_array()
548214501Srpaulo * @return TRUE on success, FALSE on failure
549214501Srpaulo *
550214501Srpaulo */
551252190Srpaulodbus_bool_t wpa_dbus_dict_end_array(DBusMessageIter *iter_dict,
552252190Srpaulo				    DBusMessageIter *iter_dict_entry,
553252190Srpaulo				    DBusMessageIter *iter_dict_val,
554252190Srpaulo				    DBusMessageIter *iter_array)
555214501Srpaulo{
556281806Srpaulo	if (!iter_dict || !iter_dict_entry || !iter_dict_val || !iter_array ||
557281806Srpaulo	    !dbus_message_iter_close_container(iter_dict_val, iter_array))
558214501Srpaulo		return FALSE;
559214501Srpaulo
560281806Srpaulo	return _wpa_dbus_add_dict_entry_end(iter_dict, iter_dict_entry,
561281806Srpaulo					    iter_dict_val);
562214501Srpaulo}
563214501Srpaulo
564214501Srpaulo
565214501Srpaulo/**
566214501Srpaulo * Convenience function to add an entire string array to the dict.
567214501Srpaulo *
568214501Srpaulo * @param iter_dict A valid DBusMessageIter returned from
569214501Srpaulo *                  wpa_dbus_dict_open_write()
570214501Srpaulo * @param key The key of the dict item
571214501Srpaulo * @param items The array of strings
572214501Srpaulo * @param num_items The number of strings in the array
573214501Srpaulo * @return TRUE on success, FALSE on failure
574214501Srpaulo *
575214501Srpaulo */
576214501Srpaulodbus_bool_t wpa_dbus_dict_append_string_array(DBusMessageIter *iter_dict,
577214501Srpaulo					      const char *key,
578214501Srpaulo					      const char **items,
579214501Srpaulo					      const dbus_uint32_t num_items)
580214501Srpaulo{
581214501Srpaulo	DBusMessageIter iter_dict_entry, iter_dict_val, iter_array;
582214501Srpaulo	dbus_uint32_t i;
583214501Srpaulo
584281806Srpaulo	if (!key || (!items && num_items != 0) ||
585281806Srpaulo	    !wpa_dbus_dict_begin_string_array(iter_dict, key,
586214501Srpaulo					      &iter_dict_entry, &iter_dict_val,
587214501Srpaulo					      &iter_array))
588214501Srpaulo		return FALSE;
589214501Srpaulo
590214501Srpaulo	for (i = 0; i < num_items; i++) {
591214501Srpaulo		if (!wpa_dbus_dict_string_array_add_element(&iter_array,
592214501Srpaulo							    items[i]))
593214501Srpaulo			return FALSE;
594214501Srpaulo	}
595214501Srpaulo
596281806Srpaulo	return wpa_dbus_dict_end_string_array(iter_dict, &iter_dict_entry,
597281806Srpaulo					      &iter_dict_val, &iter_array);
598214501Srpaulo}
599214501Srpaulo
600214501Srpaulo
601252190Srpaulo/**
602252190Srpaulo * Convenience function to add an wpabuf binary array to the dict.
603252190Srpaulo *
604252190Srpaulo * @param iter_dict A valid DBusMessageIter returned from
605252190Srpaulo *                  wpa_dbus_dict_open_write()
606252190Srpaulo * @param key The key of the dict item
607252190Srpaulo * @param items The array of wpabuf structures
608252190Srpaulo * @param num_items The number of strings in the array
609252190Srpaulo * @return TRUE on success, FALSE on failure
610252190Srpaulo *
611252190Srpaulo */
612252190Srpaulodbus_bool_t wpa_dbus_dict_append_wpabuf_array(DBusMessageIter *iter_dict,
613252190Srpaulo					      const char *key,
614252190Srpaulo					      const struct wpabuf **items,
615252190Srpaulo					      const dbus_uint32_t num_items)
616252190Srpaulo{
617252190Srpaulo	DBusMessageIter iter_dict_entry, iter_dict_val, iter_array;
618252190Srpaulo	dbus_uint32_t i;
619252190Srpaulo
620281806Srpaulo	if (!key ||
621281806Srpaulo	    (!items && num_items != 0) ||
622281806Srpaulo	    !wpa_dbus_dict_begin_array(iter_dict, key,
623252190Srpaulo				       DBUS_TYPE_ARRAY_AS_STRING
624252190Srpaulo				       DBUS_TYPE_BYTE_AS_STRING,
625252190Srpaulo				       &iter_dict_entry, &iter_dict_val,
626252190Srpaulo				       &iter_array))
627252190Srpaulo		return FALSE;
628252190Srpaulo
629252190Srpaulo	for (i = 0; i < num_items; i++) {
630252190Srpaulo		if (!wpa_dbus_dict_bin_array_add_element(&iter_array,
631252190Srpaulo							 wpabuf_head(items[i]),
632252190Srpaulo							 wpabuf_len(items[i])))
633252190Srpaulo			return FALSE;
634252190Srpaulo	}
635252190Srpaulo
636281806Srpaulo	return wpa_dbus_dict_end_array(iter_dict, &iter_dict_entry,
637281806Srpaulo				       &iter_dict_val, &iter_array);
638252190Srpaulo}
639252190Srpaulo
640252190Srpaulo
641214501Srpaulo/*****************************************************/
642214501Srpaulo/* Stuff for reading dicts                           */
643214501Srpaulo/*****************************************************/
644214501Srpaulo
645214501Srpaulo/**
646214501Srpaulo * Start reading from a dbus dict.
647214501Srpaulo *
648214501Srpaulo * @param iter A valid DBusMessageIter pointing to the start of the dict
649214501Srpaulo * @param iter_dict (out) A DBusMessageIter to be passed to
650214501Srpaulo *    wpa_dbus_dict_read_next_entry()
651252190Srpaulo * @error on failure a descriptive error
652214501Srpaulo * @return TRUE on success, FALSE on failure
653214501Srpaulo *
654214501Srpaulo */
655214501Srpaulodbus_bool_t wpa_dbus_dict_open_read(DBusMessageIter *iter,
656252190Srpaulo				    DBusMessageIter *iter_dict,
657252190Srpaulo				    DBusError *error)
658214501Srpaulo{
659281806Srpaulo	int type;
660281806Srpaulo
661281806Srpaulo	wpa_printf(MSG_MSGDUMP, "%s: start reading a dict entry", __func__);
662252190Srpaulo	if (!iter || !iter_dict) {
663252190Srpaulo		dbus_set_error_const(error, DBUS_ERROR_FAILED,
664281806Srpaulo				     "[internal] missing message iterators");
665214501Srpaulo		return FALSE;
666252190Srpaulo	}
667214501Srpaulo
668281806Srpaulo	type = dbus_message_iter_get_arg_type(iter);
669281806Srpaulo	if (type != DBUS_TYPE_ARRAY ||
670252190Srpaulo	    dbus_message_iter_get_element_type(iter) != DBUS_TYPE_DICT_ENTRY) {
671281806Srpaulo		wpa_printf(MSG_DEBUG,
672281806Srpaulo			   "%s: unexpected message argument types (arg=%c element=%c)",
673281806Srpaulo			   __func__, type,
674281806Srpaulo			   type != DBUS_TYPE_ARRAY ? '?' :
675281806Srpaulo			   dbus_message_iter_get_element_type(iter));
676252190Srpaulo		dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
677281806Srpaulo				     "unexpected message argument types");
678214501Srpaulo		return FALSE;
679252190Srpaulo	}
680214501Srpaulo
681214501Srpaulo	dbus_message_iter_recurse(iter, iter_dict);
682214501Srpaulo	return TRUE;
683214501Srpaulo}
684214501Srpaulo
685214501Srpaulo
686214501Srpaulo#define BYTE_ARRAY_CHUNK_SIZE 34
687214501Srpaulo#define BYTE_ARRAY_ITEM_SIZE (sizeof(char))
688214501Srpaulo
689214501Srpaulostatic dbus_bool_t _wpa_dbus_dict_entry_get_byte_array(
690252190Srpaulo	DBusMessageIter *iter, struct wpa_dbus_dict_entry *entry)
691214501Srpaulo{
692214501Srpaulo	dbus_uint32_t count = 0;
693214501Srpaulo	dbus_bool_t success = FALSE;
694252190Srpaulo	char *buffer, *nbuffer;
695214501Srpaulo
696214501Srpaulo	entry->bytearray_value = NULL;
697214501Srpaulo	entry->array_type = DBUS_TYPE_BYTE;
698214501Srpaulo
699252190Srpaulo	buffer = os_calloc(BYTE_ARRAY_CHUNK_SIZE, BYTE_ARRAY_ITEM_SIZE);
700214501Srpaulo	if (!buffer)
701214501Srpaulo		return FALSE;
702214501Srpaulo
703214501Srpaulo	entry->array_len = 0;
704214501Srpaulo	while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_BYTE) {
705214501Srpaulo		char byte;
706214501Srpaulo
707214501Srpaulo		if ((count % BYTE_ARRAY_CHUNK_SIZE) == 0 && count != 0) {
708252190Srpaulo			nbuffer = os_realloc_array(
709252190Srpaulo				buffer, count + BYTE_ARRAY_CHUNK_SIZE,
710252190Srpaulo				BYTE_ARRAY_ITEM_SIZE);
711214501Srpaulo			if (nbuffer == NULL) {
712214501Srpaulo				os_free(buffer);
713281806Srpaulo				wpa_printf(MSG_ERROR,
714281806Srpaulo					   "dbus: %s out of memory trying to retrieve the string array",
715281806Srpaulo					   __func__);
716214501Srpaulo				goto done;
717214501Srpaulo			}
718214501Srpaulo			buffer = nbuffer;
719214501Srpaulo		}
720214501Srpaulo
721214501Srpaulo		dbus_message_iter_get_basic(iter, &byte);
722281806Srpaulo		buffer[count] = byte;
723214501Srpaulo		entry->array_len = ++count;
724214501Srpaulo		dbus_message_iter_next(iter);
725214501Srpaulo	}
726281806Srpaulo	entry->bytearray_value = buffer;
727281806Srpaulo	wpa_hexdump_key(MSG_MSGDUMP, "dbus: byte array contents",
728281806Srpaulo			entry->bytearray_value, entry->array_len);
729214501Srpaulo
730214501Srpaulo	/* Zero-length arrays are valid. */
731214501Srpaulo	if (entry->array_len == 0) {
732214501Srpaulo		os_free(entry->bytearray_value);
733214501Srpaulo		entry->bytearray_value = NULL;
734214501Srpaulo	}
735214501Srpaulo
736214501Srpaulo	success = TRUE;
737214501Srpaulo
738214501Srpaulodone:
739214501Srpaulo	return success;
740214501Srpaulo}
741214501Srpaulo
742214501Srpaulo
743214501Srpaulo#define STR_ARRAY_CHUNK_SIZE 8
744214501Srpaulo#define STR_ARRAY_ITEM_SIZE (sizeof(char *))
745214501Srpaulo
746214501Srpaulostatic dbus_bool_t _wpa_dbus_dict_entry_get_string_array(
747214501Srpaulo	DBusMessageIter *iter, int array_type,
748214501Srpaulo	struct wpa_dbus_dict_entry *entry)
749214501Srpaulo{
750214501Srpaulo	dbus_uint32_t count = 0;
751214501Srpaulo	char **buffer, **nbuffer;
752214501Srpaulo
753214501Srpaulo	entry->strarray_value = NULL;
754281806Srpaulo	entry->array_len = 0;
755214501Srpaulo	entry->array_type = DBUS_TYPE_STRING;
756214501Srpaulo
757252190Srpaulo	buffer = os_calloc(STR_ARRAY_CHUNK_SIZE, STR_ARRAY_ITEM_SIZE);
758214501Srpaulo	if (buffer == NULL)
759214501Srpaulo		return FALSE;
760214501Srpaulo
761214501Srpaulo	while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING) {
762214501Srpaulo		const char *value;
763214501Srpaulo		char *str;
764214501Srpaulo
765214501Srpaulo		if ((count % STR_ARRAY_CHUNK_SIZE) == 0 && count != 0) {
766252190Srpaulo			nbuffer = os_realloc_array(
767252190Srpaulo				buffer, count + STR_ARRAY_CHUNK_SIZE,
768252190Srpaulo				STR_ARRAY_ITEM_SIZE);
769214501Srpaulo			if (nbuffer == NULL) {
770281806Srpaulo				wpa_printf(MSG_ERROR,
771281806Srpaulo					   "dbus: %s out of memory trying to retrieve the string array",
772281806Srpaulo					   __func__);
773281806Srpaulo				goto fail;
774214501Srpaulo			}
775214501Srpaulo			buffer = nbuffer;
776214501Srpaulo		}
777214501Srpaulo
778214501Srpaulo		dbus_message_iter_get_basic(iter, &value);
779281806Srpaulo		wpa_printf(MSG_MSGDUMP, "%s: string_array value: %s",
780281806Srpaulo			   __func__, wpa_debug_show_keys ? value : "[omitted]");
781214501Srpaulo		str = os_strdup(value);
782214501Srpaulo		if (str == NULL) {
783281806Srpaulo			wpa_printf(MSG_ERROR,
784281806Srpaulo				   "dbus: %s out of memory trying to duplicate the string array",
785281806Srpaulo				   __func__);
786281806Srpaulo			goto fail;
787214501Srpaulo		}
788281806Srpaulo		buffer[count++] = str;
789214501Srpaulo		dbus_message_iter_next(iter);
790214501Srpaulo	}
791281806Srpaulo	entry->strarray_value = buffer;
792281806Srpaulo	entry->array_len = count;
793281806Srpaulo	wpa_printf(MSG_MSGDUMP, "%s: string_array length %u",
794281806Srpaulo		   __func__, entry->array_len);
795214501Srpaulo
796214501Srpaulo	/* Zero-length arrays are valid. */
797214501Srpaulo	if (entry->array_len == 0) {
798214501Srpaulo		os_free(entry->strarray_value);
799214501Srpaulo		entry->strarray_value = NULL;
800214501Srpaulo	}
801214501Srpaulo
802281806Srpaulo	return TRUE;
803214501Srpaulo
804281806Srpaulofail:
805281806Srpaulo	while (count > 0) {
806281806Srpaulo		count--;
807281806Srpaulo		os_free(buffer[count]);
808281806Srpaulo	}
809281806Srpaulo	os_free(buffer);
810281806Srpaulo	return FALSE;
811214501Srpaulo}
812214501Srpaulo
813214501Srpaulo
814252190Srpaulo#define BIN_ARRAY_CHUNK_SIZE 10
815252190Srpaulo#define BIN_ARRAY_ITEM_SIZE (sizeof(struct wpabuf *))
816252190Srpaulo
817252190Srpaulostatic dbus_bool_t _wpa_dbus_dict_entry_get_binarray(
818252190Srpaulo	DBusMessageIter *iter, struct wpa_dbus_dict_entry *entry)
819252190Srpaulo{
820252190Srpaulo	struct wpa_dbus_dict_entry tmpentry;
821252190Srpaulo	size_t buflen = 0;
822281806Srpaulo	int i, type;
823252190Srpaulo
824252190Srpaulo	entry->array_type = WPAS_DBUS_TYPE_BINARRAY;
825252190Srpaulo	entry->array_len = 0;
826252190Srpaulo	entry->binarray_value = NULL;
827252190Srpaulo
828281806Srpaulo	type = dbus_message_iter_get_arg_type(iter);
829281806Srpaulo	wpa_printf(MSG_MSGDUMP, "%s: parsing binarray type %c", __func__, type);
830281806Srpaulo	if (type == DBUS_TYPE_INVALID) {
831281806Srpaulo		/* Likely an empty array of arrays */
832281806Srpaulo		return TRUE;
833281806Srpaulo	}
834281806Srpaulo	if (type != DBUS_TYPE_ARRAY) {
835281806Srpaulo		wpa_printf(MSG_DEBUG, "%s: not an array type: %c",
836281806Srpaulo			   __func__, type);
837281806Srpaulo		return FALSE;
838281806Srpaulo	}
839281806Srpaulo
840281806Srpaulo	type = dbus_message_iter_get_element_type(iter);
841281806Srpaulo	if (type != DBUS_TYPE_BYTE) {
842281806Srpaulo		wpa_printf(MSG_DEBUG, "%s: unexpected element type %c",
843281806Srpaulo			   __func__, type);
844281806Srpaulo		return FALSE;
845281806Srpaulo	}
846281806Srpaulo
847252190Srpaulo	while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_ARRAY) {
848252190Srpaulo		DBusMessageIter iter_array;
849252190Srpaulo
850252190Srpaulo		if (entry->array_len == buflen) {
851252190Srpaulo			struct wpabuf **newbuf;
852252190Srpaulo
853252190Srpaulo			buflen += BIN_ARRAY_CHUNK_SIZE;
854252190Srpaulo
855252190Srpaulo			newbuf = os_realloc_array(entry->binarray_value,
856252190Srpaulo						  buflen, BIN_ARRAY_ITEM_SIZE);
857252190Srpaulo			if (!newbuf)
858252190Srpaulo				goto cleanup;
859252190Srpaulo			entry->binarray_value = newbuf;
860252190Srpaulo		}
861252190Srpaulo
862252190Srpaulo		dbus_message_iter_recurse(iter, &iter_array);
863281806Srpaulo		os_memset(&tmpentry, 0, sizeof(tmpentry));
864281806Srpaulo		tmpentry.type = DBUS_TYPE_ARRAY;
865252190Srpaulo		if (_wpa_dbus_dict_entry_get_byte_array(&iter_array, &tmpentry)
866281806Srpaulo		    == FALSE)
867252190Srpaulo			goto cleanup;
868252190Srpaulo
869252190Srpaulo		entry->binarray_value[entry->array_len] =
870252190Srpaulo			wpabuf_alloc_ext_data((u8 *) tmpentry.bytearray_value,
871252190Srpaulo					      tmpentry.array_len);
872252190Srpaulo		if (entry->binarray_value[entry->array_len] == NULL) {
873252190Srpaulo			wpa_dbus_dict_entry_clear(&tmpentry);
874252190Srpaulo			goto cleanup;
875252190Srpaulo		}
876252190Srpaulo		entry->array_len++;
877252190Srpaulo		dbus_message_iter_next(iter);
878252190Srpaulo	}
879281806Srpaulo	wpa_printf(MSG_MSGDUMP, "%s: binarray length %u",
880281806Srpaulo		   __func__, entry->array_len);
881252190Srpaulo
882252190Srpaulo	return TRUE;
883252190Srpaulo
884252190Srpaulo cleanup:
885252190Srpaulo	for (i = 0; i < (int) entry->array_len; i++)
886252190Srpaulo		wpabuf_free(entry->binarray_value[i]);
887252190Srpaulo	os_free(entry->binarray_value);
888252190Srpaulo	entry->array_len = 0;
889252190Srpaulo	entry->binarray_value = NULL;
890252190Srpaulo	return FALSE;
891252190Srpaulo}
892252190Srpaulo
893252190Srpaulo
894214501Srpaulostatic dbus_bool_t _wpa_dbus_dict_entry_get_array(
895214501Srpaulo	DBusMessageIter *iter_dict_val, struct wpa_dbus_dict_entry *entry)
896214501Srpaulo{
897214501Srpaulo	int array_type = dbus_message_iter_get_element_type(iter_dict_val);
898214501Srpaulo	dbus_bool_t success = FALSE;
899214501Srpaulo	DBusMessageIter iter_array;
900214501Srpaulo
901281806Srpaulo	wpa_printf(MSG_MSGDUMP, "%s: array_type %c", __func__, array_type);
902214501Srpaulo
903214501Srpaulo	dbus_message_iter_recurse(iter_dict_val, &iter_array);
904214501Srpaulo
905281806Srpaulo	switch (array_type) {
906214501Srpaulo	case DBUS_TYPE_BYTE:
907214501Srpaulo		success = _wpa_dbus_dict_entry_get_byte_array(&iter_array,
908214501Srpaulo							      entry);
909214501Srpaulo		break;
910214501Srpaulo	case DBUS_TYPE_STRING:
911214501Srpaulo		success = _wpa_dbus_dict_entry_get_string_array(&iter_array,
912214501Srpaulo								array_type,
913214501Srpaulo								entry);
914214501Srpaulo		break;
915252190Srpaulo	case DBUS_TYPE_ARRAY:
916252190Srpaulo		success = _wpa_dbus_dict_entry_get_binarray(&iter_array, entry);
917281806Srpaulo		break;
918214501Srpaulo	default:
919281806Srpaulo		wpa_printf(MSG_MSGDUMP, "%s: unsupported array type %c",
920281806Srpaulo			   __func__, array_type);
921214501Srpaulo		break;
922214501Srpaulo	}
923214501Srpaulo
924214501Srpaulo	return success;
925214501Srpaulo}
926214501Srpaulo
927214501Srpaulo
928214501Srpaulostatic dbus_bool_t _wpa_dbus_dict_fill_value_from_variant(
929214501Srpaulo	struct wpa_dbus_dict_entry *entry, DBusMessageIter *iter)
930214501Srpaulo{
931214501Srpaulo	const char *v;
932214501Srpaulo
933214501Srpaulo	switch (entry->type) {
934214501Srpaulo	case DBUS_TYPE_OBJECT_PATH:
935281806Srpaulo		dbus_message_iter_get_basic(iter, &v);
936281806Srpaulo		wpa_printf(MSG_MSGDUMP, "%s: object path value: %s",
937281806Srpaulo			   __func__, v);
938281806Srpaulo		entry->str_value = os_strdup(v);
939281806Srpaulo		if (entry->str_value == NULL)
940281806Srpaulo			return FALSE;
941281806Srpaulo		break;
942214501Srpaulo	case DBUS_TYPE_STRING:
943214501Srpaulo		dbus_message_iter_get_basic(iter, &v);
944281806Srpaulo		wpa_printf(MSG_MSGDUMP, "%s: string value: %s",
945281806Srpaulo			   __func__, wpa_debug_show_keys ? v : "[omitted]");
946214501Srpaulo		entry->str_value = os_strdup(v);
947214501Srpaulo		if (entry->str_value == NULL)
948214501Srpaulo			return FALSE;
949214501Srpaulo		break;
950214501Srpaulo	case DBUS_TYPE_BOOLEAN:
951214501Srpaulo		dbus_message_iter_get_basic(iter, &entry->bool_value);
952281806Srpaulo		wpa_printf(MSG_MSGDUMP, "%s: boolean value: %d",
953281806Srpaulo			   __func__, entry->bool_value);
954214501Srpaulo		break;
955214501Srpaulo	case DBUS_TYPE_BYTE:
956214501Srpaulo		dbus_message_iter_get_basic(iter, &entry->byte_value);
957281806Srpaulo		wpa_printf(MSG_MSGDUMP, "%s: byte value: %d",
958281806Srpaulo			   __func__, entry->byte_value);
959214501Srpaulo		break;
960214501Srpaulo	case DBUS_TYPE_INT16:
961214501Srpaulo		dbus_message_iter_get_basic(iter, &entry->int16_value);
962281806Srpaulo		wpa_printf(MSG_MSGDUMP, "%s: int16 value: %d",
963281806Srpaulo			   __func__, entry->int16_value);
964214501Srpaulo		break;
965214501Srpaulo	case DBUS_TYPE_UINT16:
966214501Srpaulo		dbus_message_iter_get_basic(iter, &entry->uint16_value);
967281806Srpaulo		wpa_printf(MSG_MSGDUMP, "%s: uint16 value: %d",
968281806Srpaulo			   __func__, entry->uint16_value);
969214501Srpaulo		break;
970214501Srpaulo	case DBUS_TYPE_INT32:
971214501Srpaulo		dbus_message_iter_get_basic(iter, &entry->int32_value);
972281806Srpaulo		wpa_printf(MSG_MSGDUMP, "%s: int32 value: %d",
973281806Srpaulo			   __func__, entry->int32_value);
974214501Srpaulo		break;
975214501Srpaulo	case DBUS_TYPE_UINT32:
976214501Srpaulo		dbus_message_iter_get_basic(iter, &entry->uint32_value);
977281806Srpaulo		wpa_printf(MSG_MSGDUMP, "%s: uint32 value: %d",
978281806Srpaulo			   __func__, entry->uint32_value);
979214501Srpaulo		break;
980214501Srpaulo	case DBUS_TYPE_INT64:
981214501Srpaulo		dbus_message_iter_get_basic(iter, &entry->int64_value);
982281806Srpaulo		wpa_printf(MSG_MSGDUMP, "%s: int64 value: %lld",
983281806Srpaulo			   __func__, (long long int) entry->int64_value);
984214501Srpaulo		break;
985214501Srpaulo	case DBUS_TYPE_UINT64:
986214501Srpaulo		dbus_message_iter_get_basic(iter, &entry->uint64_value);
987281806Srpaulo		wpa_printf(MSG_MSGDUMP, "%s: uint64 value: %llu",
988281806Srpaulo			   __func__,
989281806Srpaulo			   (unsigned long long int) entry->uint64_value);
990214501Srpaulo		break;
991214501Srpaulo	case DBUS_TYPE_DOUBLE:
992214501Srpaulo		dbus_message_iter_get_basic(iter, &entry->double_value);
993281806Srpaulo		wpa_printf(MSG_MSGDUMP, "%s: double value: %f",
994281806Srpaulo			   __func__, entry->double_value);
995214501Srpaulo		break;
996214501Srpaulo	case DBUS_TYPE_ARRAY:
997214501Srpaulo		return _wpa_dbus_dict_entry_get_array(iter, entry);
998214501Srpaulo	default:
999281806Srpaulo		wpa_printf(MSG_MSGDUMP, "%s: unsupported type %c",
1000281806Srpaulo			   __func__, entry->type);
1001214501Srpaulo		return FALSE;
1002214501Srpaulo	}
1003214501Srpaulo
1004214501Srpaulo	return TRUE;
1005214501Srpaulo}
1006214501Srpaulo
1007214501Srpaulo
1008214501Srpaulo/**
1009214501Srpaulo * Read the current key/value entry from the dict.  Entries are dynamically
1010214501Srpaulo * allocated when needed and must be freed after use with the
1011214501Srpaulo * wpa_dbus_dict_entry_clear() function.
1012214501Srpaulo *
1013214501Srpaulo * The returned entry object will be filled with the type and value of the next
1014214501Srpaulo * entry in the dict, or the type will be DBUS_TYPE_INVALID if an error
1015214501Srpaulo * occurred.
1016214501Srpaulo *
1017214501Srpaulo * @param iter_dict A valid DBusMessageIter returned from
1018214501Srpaulo *    wpa_dbus_dict_open_read()
1019214501Srpaulo * @param entry A valid dict entry object into which the dict key and value
1020214501Srpaulo *    will be placed
1021214501Srpaulo * @return TRUE on success, FALSE on failure
1022214501Srpaulo *
1023214501Srpaulo */
1024214501Srpaulodbus_bool_t wpa_dbus_dict_get_entry(DBusMessageIter *iter_dict,
1025214501Srpaulo				    struct wpa_dbus_dict_entry * entry)
1026214501Srpaulo{
1027214501Srpaulo	DBusMessageIter iter_dict_entry, iter_dict_val;
1028214501Srpaulo	int type;
1029214501Srpaulo	const char *key;
1030214501Srpaulo
1031281806Srpaulo	if (!iter_dict || !entry ||
1032281806Srpaulo	    dbus_message_iter_get_arg_type(iter_dict) != DBUS_TYPE_DICT_ENTRY) {
1033281806Srpaulo		wpa_printf(MSG_DEBUG, "%s: not a dict entry", __func__);
1034214501Srpaulo		goto error;
1035281806Srpaulo	}
1036214501Srpaulo
1037214501Srpaulo	dbus_message_iter_recurse(iter_dict, &iter_dict_entry);
1038214501Srpaulo	dbus_message_iter_get_basic(&iter_dict_entry, &key);
1039281806Srpaulo	wpa_printf(MSG_MSGDUMP, "%s: dict entry key: %s", __func__, key);
1040214501Srpaulo	entry->key = key;
1041214501Srpaulo
1042281806Srpaulo	if (!dbus_message_iter_next(&iter_dict_entry)) {
1043281806Srpaulo		wpa_printf(MSG_DEBUG, "%s: no variant in dict entry", __func__);
1044214501Srpaulo		goto error;
1045281806Srpaulo	}
1046214501Srpaulo	type = dbus_message_iter_get_arg_type(&iter_dict_entry);
1047281806Srpaulo	if (type != DBUS_TYPE_VARIANT) {
1048281806Srpaulo		wpa_printf(MSG_DEBUG,
1049281806Srpaulo			   "%s: unexpected dict entry variant type: %c",
1050281806Srpaulo			   __func__, type);
1051214501Srpaulo		goto error;
1052281806Srpaulo	}
1053214501Srpaulo
1054214501Srpaulo	dbus_message_iter_recurse(&iter_dict_entry, &iter_dict_val);
1055214501Srpaulo	entry->type = dbus_message_iter_get_arg_type(&iter_dict_val);
1056281806Srpaulo	wpa_printf(MSG_MSGDUMP, "%s: dict entry variant content type: %c",
1057281806Srpaulo		   __func__, entry->type);
1058281806Srpaulo	entry->array_type = DBUS_TYPE_INVALID;
1059281806Srpaulo	if (!_wpa_dbus_dict_fill_value_from_variant(entry, &iter_dict_val)) {
1060281806Srpaulo		wpa_printf(MSG_DEBUG,
1061281806Srpaulo			   "%s: failed to fetch dict values from variant",
1062281806Srpaulo			   __func__);
1063214501Srpaulo		goto error;
1064281806Srpaulo	}
1065214501Srpaulo
1066214501Srpaulo	dbus_message_iter_next(iter_dict);
1067214501Srpaulo	return TRUE;
1068214501Srpaulo
1069214501Srpauloerror:
1070214501Srpaulo	if (entry) {
1071214501Srpaulo		wpa_dbus_dict_entry_clear(entry);
1072214501Srpaulo		entry->type = DBUS_TYPE_INVALID;
1073214501Srpaulo		entry->array_type = DBUS_TYPE_INVALID;
1074214501Srpaulo	}
1075214501Srpaulo
1076214501Srpaulo	return FALSE;
1077214501Srpaulo}
1078214501Srpaulo
1079214501Srpaulo
1080214501Srpaulo/**
1081214501Srpaulo * Return whether or not there are additional dictionary entries.
1082214501Srpaulo *
1083214501Srpaulo * @param iter_dict A valid DBusMessageIter returned from
1084214501Srpaulo *    wpa_dbus_dict_open_read()
1085214501Srpaulo * @return TRUE if more dict entries exists, FALSE if no more dict entries
1086214501Srpaulo * exist
1087214501Srpaulo */
1088214501Srpaulodbus_bool_t wpa_dbus_dict_has_dict_entry(DBusMessageIter *iter_dict)
1089214501Srpaulo{
1090214501Srpaulo	if (!iter_dict)
1091214501Srpaulo		return FALSE;
1092214501Srpaulo	return dbus_message_iter_get_arg_type(iter_dict) ==
1093214501Srpaulo		DBUS_TYPE_DICT_ENTRY;
1094214501Srpaulo}
1095214501Srpaulo
1096214501Srpaulo
1097214501Srpaulo/**
1098214501Srpaulo * Free any memory used by the entry object.
1099214501Srpaulo *
1100214501Srpaulo * @param entry The entry object
1101214501Srpaulo */
1102214501Srpaulovoid wpa_dbus_dict_entry_clear(struct wpa_dbus_dict_entry *entry)
1103214501Srpaulo{
1104214501Srpaulo	unsigned int i;
1105214501Srpaulo
1106214501Srpaulo	if (!entry)
1107214501Srpaulo		return;
1108214501Srpaulo	switch (entry->type) {
1109214501Srpaulo	case DBUS_TYPE_OBJECT_PATH:
1110214501Srpaulo	case DBUS_TYPE_STRING:
1111214501Srpaulo		os_free(entry->str_value);
1112214501Srpaulo		break;
1113214501Srpaulo	case DBUS_TYPE_ARRAY:
1114214501Srpaulo		switch (entry->array_type) {
1115214501Srpaulo		case DBUS_TYPE_BYTE:
1116214501Srpaulo			os_free(entry->bytearray_value);
1117214501Srpaulo			break;
1118214501Srpaulo		case DBUS_TYPE_STRING:
1119281806Srpaulo			if (!entry->strarray_value)
1120281806Srpaulo				break;
1121214501Srpaulo			for (i = 0; i < entry->array_len; i++)
1122214501Srpaulo				os_free(entry->strarray_value[i]);
1123214501Srpaulo			os_free(entry->strarray_value);
1124214501Srpaulo			break;
1125252190Srpaulo		case WPAS_DBUS_TYPE_BINARRAY:
1126252190Srpaulo			for (i = 0; i < entry->array_len; i++)
1127252190Srpaulo				wpabuf_free(entry->binarray_value[i]);
1128252190Srpaulo			os_free(entry->binarray_value);
1129252190Srpaulo			break;
1130214501Srpaulo		}
1131214501Srpaulo		break;
1132214501Srpaulo	}
1133214501Srpaulo
1134252190Srpaulo	os_memset(entry, 0, sizeof(struct wpa_dbus_dict_entry));
1135214501Srpaulo}
1136