dbus_dict_helpers.c 31 KB

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