dbus_dict_helpers.c 24 KB

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