Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923
  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. const char * wpa_dbus_type_as_string(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. if (key == NULL)
  123. return FALSE;
  124. type_as_string = wpa_dbus_type_as_string(value_type);
  125. if (!type_as_string)
  126. return FALSE;
  127. if (!_wpa_dbus_add_dict_entry_start(iter_dict, &iter_dict_entry,
  128. key, value_type))
  129. return FALSE;
  130. if (!dbus_message_iter_open_container(&iter_dict_entry,
  131. DBUS_TYPE_VARIANT,
  132. type_as_string, &iter_dict_val))
  133. return FALSE;
  134. if (!dbus_message_iter_append_basic(&iter_dict_val, value_type, value))
  135. return FALSE;
  136. if (!_wpa_dbus_add_dict_entry_end(iter_dict, &iter_dict_entry,
  137. &iter_dict_val))
  138. return FALSE;
  139. return TRUE;
  140. }
  141. static dbus_bool_t _wpa_dbus_add_dict_entry_byte_array(
  142. DBusMessageIter *iter_dict, const char *key,
  143. const char *value, const dbus_uint32_t value_len)
  144. {
  145. DBusMessageIter iter_dict_entry, iter_dict_val, iter_array;
  146. dbus_uint32_t i;
  147. if (!_wpa_dbus_add_dict_entry_start(iter_dict, &iter_dict_entry,
  148. key, DBUS_TYPE_ARRAY))
  149. return FALSE;
  150. if (!dbus_message_iter_open_container(&iter_dict_entry,
  151. DBUS_TYPE_VARIANT,
  152. DBUS_TYPE_ARRAY_AS_STRING
  153. DBUS_TYPE_BYTE_AS_STRING,
  154. &iter_dict_val))
  155. return FALSE;
  156. if (!dbus_message_iter_open_container(&iter_dict_val, DBUS_TYPE_ARRAY,
  157. DBUS_TYPE_BYTE_AS_STRING,
  158. &iter_array))
  159. return FALSE;
  160. for (i = 0; i < value_len; i++) {
  161. if (!dbus_message_iter_append_basic(&iter_array,
  162. DBUS_TYPE_BYTE,
  163. &(value[i])))
  164. return FALSE;
  165. }
  166. if (!dbus_message_iter_close_container(&iter_dict_val, &iter_array))
  167. return FALSE;
  168. if (!_wpa_dbus_add_dict_entry_end(iter_dict, &iter_dict_entry,
  169. &iter_dict_val))
  170. return FALSE;
  171. return TRUE;
  172. }
  173. /**
  174. * Add a string entry to the dict.
  175. *
  176. * @param iter_dict A valid DBusMessageIter returned from
  177. * wpa_dbus_dict_open_write()
  178. * @param key The key of the dict item
  179. * @param value The string value
  180. * @return TRUE on success, FALSE on failure
  181. *
  182. */
  183. dbus_bool_t wpa_dbus_dict_append_string(DBusMessageIter *iter_dict,
  184. const char *key, const char *value)
  185. {
  186. if (!value)
  187. return FALSE;
  188. return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_STRING,
  189. &value);
  190. }
  191. /**
  192. * Add a byte entry to the dict.
  193. *
  194. * @param iter_dict A valid DBusMessageIter returned from
  195. * wpa_dbus_dict_open_write()
  196. * @param key The key of the dict item
  197. * @param value The byte value
  198. * @return TRUE on success, FALSE on failure
  199. *
  200. */
  201. dbus_bool_t wpa_dbus_dict_append_byte(DBusMessageIter *iter_dict,
  202. const char *key, const char value)
  203. {
  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. return _wpa_dbus_add_dict_entry_basic(iter_dict, key,
  221. DBUS_TYPE_BOOLEAN, &value);
  222. }
  223. /**
  224. * Add a 16-bit signed 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 signed integer value
  230. * @return TRUE on success, FALSE on failure
  231. *
  232. */
  233. dbus_bool_t wpa_dbus_dict_append_int16(DBusMessageIter *iter_dict,
  234. const char *key,
  235. const dbus_int16_t value)
  236. {
  237. return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_INT16,
  238. &value);
  239. }
  240. /**
  241. * Add a 16-bit unsigned integer entry 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 16-bit unsigned integer value
  247. * @return TRUE on success, FALSE on failure
  248. *
  249. */
  250. dbus_bool_t wpa_dbus_dict_append_uint16(DBusMessageIter *iter_dict,
  251. const char *key,
  252. const dbus_uint16_t value)
  253. {
  254. return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_UINT16,
  255. &value);
  256. }
  257. /**
  258. * Add a 32-bit signed integer 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 signed integer value
  264. * @return TRUE on success, FALSE on failure
  265. *
  266. */
  267. dbus_bool_t wpa_dbus_dict_append_int32(DBusMessageIter *iter_dict,
  268. const char *key,
  269. const dbus_int32_t value)
  270. {
  271. return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_INT32,
  272. &value);
  273. }
  274. /**
  275. * Add a 32-bit unsigned 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 32-bit unsigned integer value
  281. * @return TRUE on success, FALSE on failure
  282. *
  283. */
  284. dbus_bool_t wpa_dbus_dict_append_uint32(DBusMessageIter *iter_dict,
  285. const char *key,
  286. const dbus_uint32_t value)
  287. {
  288. return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_UINT32,
  289. &value);
  290. }
  291. /**
  292. * Add a 64-bit 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 integer value
  298. * @return TRUE on success, FALSE on failure
  299. *
  300. */
  301. dbus_bool_t wpa_dbus_dict_append_int64(DBusMessageIter *iter_dict,
  302. const char *key,
  303. const dbus_int64_t value)
  304. {
  305. return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_INT64,
  306. &value);
  307. }
  308. /**
  309. * Add a 64-bit unsigned integer 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 64-bit unsigned integer value
  315. * @return TRUE on success, FALSE on failure
  316. *
  317. */
  318. dbus_bool_t wpa_dbus_dict_append_uint64(DBusMessageIter *iter_dict,
  319. const char *key,
  320. const dbus_uint64_t value)
  321. {
  322. return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_UINT64,
  323. &value);
  324. }
  325. /**
  326. * Add a double-precision floating point entry to the dict.
  327. *
  328. * @param iter_dict A valid DBusMessageIter returned from
  329. * wpa_dbus_dict_open_write()
  330. * @param key The key of the dict item
  331. * @param value The double-precision floating point value
  332. * @return TRUE on success, FALSE on failure
  333. *
  334. */
  335. dbus_bool_t wpa_dbus_dict_append_double(DBusMessageIter *iter_dict,
  336. const char *key, const double value)
  337. {
  338. return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_DOUBLE,
  339. &value);
  340. }
  341. /**
  342. * Add a DBus object path entry to the dict.
  343. *
  344. * @param iter_dict A valid DBusMessageIter returned from
  345. * wpa_dbus_dict_open_write()
  346. * @param key The key of the dict item
  347. * @param value The DBus object path value
  348. * @return TRUE on success, FALSE on failure
  349. *
  350. */
  351. dbus_bool_t wpa_dbus_dict_append_object_path(DBusMessageIter *iter_dict,
  352. const char *key,
  353. const char *value)
  354. {
  355. if (!value)
  356. return FALSE;
  357. return _wpa_dbus_add_dict_entry_basic(iter_dict, key,
  358. DBUS_TYPE_OBJECT_PATH, &value);
  359. }
  360. /**
  361. * Add a byte array entry to the dict.
  362. *
  363. * @param iter_dict A valid DBusMessageIter returned from
  364. * wpa_dbus_dict_open_write()
  365. * @param key The key of the dict item
  366. * @param value The byte array
  367. * @param value_len The length of the byte array, in bytes
  368. * @return TRUE on success, FALSE on failure
  369. *
  370. */
  371. dbus_bool_t wpa_dbus_dict_append_byte_array(DBusMessageIter *iter_dict,
  372. const char *key,
  373. const char *value,
  374. const dbus_uint32_t value_len)
  375. {
  376. if (!key)
  377. return FALSE;
  378. if (!value && (value_len != 0))
  379. return FALSE;
  380. return _wpa_dbus_add_dict_entry_byte_array(iter_dict, key, value,
  381. value_len);
  382. }
  383. /**
  384. * Begin a string array entry in the dict
  385. *
  386. * @param iter_dict A valid DBusMessageIter returned from
  387. * wpa_dbus_dict_open_write()
  388. * @param key The key of the dict item
  389. * @param iter_dict_entry A private DBusMessageIter provided by the caller to
  390. * be passed to wpa_dbus_dict_end_string_array()
  391. * @param iter_dict_val A private DBusMessageIter provided by the caller to
  392. * be passed to wpa_dbus_dict_end_string_array()
  393. * @param iter_array On return, the DBusMessageIter to be passed to
  394. * wpa_dbus_dict_string_array_add_element()
  395. * @return TRUE on success, FALSE on failure
  396. *
  397. */
  398. dbus_bool_t wpa_dbus_dict_begin_string_array(DBusMessageIter *iter_dict,
  399. const char *key,
  400. DBusMessageIter *iter_dict_entry,
  401. DBusMessageIter *iter_dict_val,
  402. DBusMessageIter *iter_array)
  403. {
  404. if (!iter_dict || !iter_dict_entry || !iter_dict_val || !iter_array)
  405. return FALSE;
  406. if (!_wpa_dbus_add_dict_entry_start(iter_dict, iter_dict_entry,
  407. key, DBUS_TYPE_ARRAY))
  408. return FALSE;
  409. if (!dbus_message_iter_open_container(iter_dict_entry,
  410. DBUS_TYPE_VARIANT,
  411. DBUS_TYPE_ARRAY_AS_STRING
  412. DBUS_TYPE_STRING_AS_STRING,
  413. iter_dict_val))
  414. return FALSE;
  415. if (!dbus_message_iter_open_container(iter_dict_val, DBUS_TYPE_ARRAY,
  416. DBUS_TYPE_STRING_AS_STRING,
  417. iter_array))
  418. return FALSE;
  419. return TRUE;
  420. }
  421. /**
  422. * Add a single string element to a string array dict entry
  423. *
  424. * @param iter_array A valid DBusMessageIter returned from
  425. * wpa_dbus_dict_begin_string_array()'s
  426. * iter_array parameter
  427. * @param elem The string element to be added to the dict entry's string array
  428. * @return TRUE on success, FALSE on failure
  429. *
  430. */
  431. dbus_bool_t wpa_dbus_dict_string_array_add_element(DBusMessageIter *iter_array,
  432. const char *elem)
  433. {
  434. if (!iter_array || !elem)
  435. return FALSE;
  436. return dbus_message_iter_append_basic(iter_array, DBUS_TYPE_STRING,
  437. &elem);
  438. }
  439. /**
  440. * End a string array dict entry
  441. *
  442. * @param iter_dict A valid DBusMessageIter returned from
  443. * wpa_dbus_dict_open_write()
  444. * @param iter_dict_entry A private DBusMessageIter returned from
  445. * wpa_dbus_dict_end_string_array()
  446. * @param iter_dict_val A private DBusMessageIter returned from
  447. * wpa_dbus_dict_end_string_array()
  448. * @param iter_array A DBusMessageIter returned from
  449. * wpa_dbus_dict_end_string_array()
  450. * @return TRUE on success, FALSE on failure
  451. *
  452. */
  453. dbus_bool_t wpa_dbus_dict_end_string_array(DBusMessageIter *iter_dict,
  454. DBusMessageIter *iter_dict_entry,
  455. DBusMessageIter *iter_dict_val,
  456. DBusMessageIter *iter_array)
  457. {
  458. if (!iter_dict || !iter_dict_entry || !iter_dict_val || !iter_array)
  459. return FALSE;
  460. if (!dbus_message_iter_close_container(iter_dict_val, iter_array))
  461. return FALSE;
  462. if (!_wpa_dbus_add_dict_entry_end(iter_dict, iter_dict_entry,
  463. iter_dict_val))
  464. return FALSE;
  465. return TRUE;
  466. }
  467. /**
  468. * Convenience function to add an entire string array to the dict.
  469. *
  470. * @param iter_dict A valid DBusMessageIter returned from
  471. * wpa_dbus_dict_open_write()
  472. * @param key The key of the dict item
  473. * @param items The array of strings
  474. * @param num_items The number of strings in the array
  475. * @return TRUE on success, FALSE on failure
  476. *
  477. */
  478. dbus_bool_t wpa_dbus_dict_append_string_array(DBusMessageIter *iter_dict,
  479. const char *key,
  480. const char **items,
  481. const dbus_uint32_t num_items)
  482. {
  483. DBusMessageIter iter_dict_entry, iter_dict_val, iter_array;
  484. dbus_uint32_t i;
  485. if (!key)
  486. return FALSE;
  487. if (!items && (num_items != 0))
  488. return FALSE;
  489. if (!wpa_dbus_dict_begin_string_array(iter_dict, key,
  490. &iter_dict_entry, &iter_dict_val,
  491. &iter_array))
  492. return FALSE;
  493. for (i = 0; i < num_items; i++) {
  494. if (!wpa_dbus_dict_string_array_add_element(&iter_array,
  495. items[i]))
  496. return FALSE;
  497. }
  498. if (!wpa_dbus_dict_end_string_array(iter_dict, &iter_dict_entry,
  499. &iter_dict_val, &iter_array))
  500. return FALSE;
  501. return TRUE;
  502. }
  503. /*****************************************************/
  504. /* Stuff for reading dicts */
  505. /*****************************************************/
  506. /**
  507. * Start reading from a dbus dict.
  508. *
  509. * @param iter A valid DBusMessageIter pointing to the start of the dict
  510. * @param iter_dict (out) A DBusMessageIter to be passed to
  511. * wpa_dbus_dict_read_next_entry()
  512. * @return TRUE on success, FALSE on failure
  513. *
  514. */
  515. dbus_bool_t wpa_dbus_dict_open_read(DBusMessageIter *iter,
  516. DBusMessageIter *iter_dict)
  517. {
  518. if (!iter || !iter_dict)
  519. return FALSE;
  520. if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY ||
  521. dbus_message_iter_get_element_type(iter) != DBUS_TYPE_DICT_ENTRY)
  522. return FALSE;
  523. dbus_message_iter_recurse(iter, iter_dict);
  524. return TRUE;
  525. }
  526. #define BYTE_ARRAY_CHUNK_SIZE 34
  527. #define BYTE_ARRAY_ITEM_SIZE (sizeof(char))
  528. static dbus_bool_t _wpa_dbus_dict_entry_get_byte_array(
  529. DBusMessageIter *iter, int array_type,
  530. struct wpa_dbus_dict_entry *entry)
  531. {
  532. dbus_uint32_t count = 0;
  533. dbus_bool_t success = FALSE;
  534. char *buffer, *nbuffer;;
  535. entry->bytearray_value = NULL;
  536. entry->array_type = DBUS_TYPE_BYTE;
  537. buffer = os_zalloc(BYTE_ARRAY_ITEM_SIZE * BYTE_ARRAY_CHUNK_SIZE);
  538. if (!buffer)
  539. return FALSE;
  540. entry->bytearray_value = buffer;
  541. entry->array_len = 0;
  542. while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_BYTE) {
  543. char byte;
  544. if ((count % BYTE_ARRAY_CHUNK_SIZE) == 0 && count != 0) {
  545. nbuffer = os_realloc(buffer, BYTE_ARRAY_ITEM_SIZE *
  546. (count + BYTE_ARRAY_CHUNK_SIZE));
  547. if (nbuffer == NULL) {
  548. os_free(buffer);
  549. wpa_printf(MSG_ERROR, "dbus: _wpa_dbus_dict_"
  550. "entry_get_byte_array out of "
  551. "memory trying to retrieve the "
  552. "string array");
  553. goto done;
  554. }
  555. buffer = nbuffer;
  556. }
  557. entry->bytearray_value = buffer;
  558. dbus_message_iter_get_basic(iter, &byte);
  559. entry->bytearray_value[count] = byte;
  560. entry->array_len = ++count;
  561. dbus_message_iter_next(iter);
  562. }
  563. /* Zero-length arrays are valid. */
  564. if (entry->array_len == 0) {
  565. os_free(entry->bytearray_value);
  566. entry->bytearray_value = NULL;
  567. }
  568. success = TRUE;
  569. done:
  570. return success;
  571. }
  572. #define STR_ARRAY_CHUNK_SIZE 8
  573. #define STR_ARRAY_ITEM_SIZE (sizeof(char *))
  574. static dbus_bool_t _wpa_dbus_dict_entry_get_string_array(
  575. DBusMessageIter *iter, int array_type,
  576. struct wpa_dbus_dict_entry *entry)
  577. {
  578. dbus_uint32_t count = 0;
  579. dbus_bool_t success = FALSE;
  580. char **buffer, **nbuffer;
  581. entry->strarray_value = NULL;
  582. entry->array_type = DBUS_TYPE_STRING;
  583. buffer = os_zalloc(STR_ARRAY_ITEM_SIZE * STR_ARRAY_CHUNK_SIZE);
  584. if (buffer == NULL)
  585. return FALSE;
  586. entry->strarray_value = buffer;
  587. entry->array_len = 0;
  588. while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING) {
  589. const char *value;
  590. char *str;
  591. if ((count % STR_ARRAY_CHUNK_SIZE) == 0 && count != 0) {
  592. nbuffer = os_realloc(buffer, STR_ARRAY_ITEM_SIZE *
  593. (count + STR_ARRAY_CHUNK_SIZE));
  594. if (nbuffer == NULL) {
  595. os_free(buffer);
  596. wpa_printf(MSG_ERROR, "dbus: _wpa_dbus_dict_"
  597. "entry_get_string_array out of "
  598. "memory trying to retrieve the "
  599. "string array");
  600. goto done;
  601. }
  602. buffer = nbuffer;
  603. }
  604. entry->strarray_value = buffer;
  605. dbus_message_iter_get_basic(iter, &value);
  606. str = os_strdup(value);
  607. if (str == NULL) {
  608. wpa_printf(MSG_ERROR, "dbus: _wpa_dbus_dict_entry_get_"
  609. "string_array out of memory trying to "
  610. "duplicate the string array");
  611. goto done;
  612. }
  613. entry->strarray_value[count] = str;
  614. entry->array_len = ++count;
  615. dbus_message_iter_next(iter);
  616. }
  617. /* Zero-length arrays are valid. */
  618. if (entry->array_len == 0) {
  619. os_free(entry->strarray_value);
  620. entry->strarray_value = NULL;
  621. }
  622. success = TRUE;
  623. done:
  624. return success;
  625. }
  626. static dbus_bool_t _wpa_dbus_dict_entry_get_array(
  627. DBusMessageIter *iter_dict_val, struct wpa_dbus_dict_entry *entry)
  628. {
  629. int array_type = dbus_message_iter_get_element_type(iter_dict_val);
  630. dbus_bool_t success = FALSE;
  631. DBusMessageIter iter_array;
  632. if (!entry)
  633. return FALSE;
  634. dbus_message_iter_recurse(iter_dict_val, &iter_array);
  635. switch (array_type) {
  636. case DBUS_TYPE_BYTE:
  637. success = _wpa_dbus_dict_entry_get_byte_array(&iter_array,
  638. array_type,
  639. entry);
  640. break;
  641. case DBUS_TYPE_STRING:
  642. success = _wpa_dbus_dict_entry_get_string_array(&iter_array,
  643. array_type,
  644. entry);
  645. break;
  646. default:
  647. break;
  648. }
  649. return success;
  650. }
  651. static dbus_bool_t _wpa_dbus_dict_fill_value_from_variant(
  652. struct wpa_dbus_dict_entry *entry, DBusMessageIter *iter)
  653. {
  654. const char *v;
  655. switch (entry->type) {
  656. case DBUS_TYPE_OBJECT_PATH:
  657. case DBUS_TYPE_STRING:
  658. dbus_message_iter_get_basic(iter, &v);
  659. entry->str_value = os_strdup(v);
  660. if (entry->str_value == NULL)
  661. return FALSE;
  662. break;
  663. case DBUS_TYPE_BOOLEAN:
  664. dbus_message_iter_get_basic(iter, &entry->bool_value);
  665. break;
  666. case DBUS_TYPE_BYTE:
  667. dbus_message_iter_get_basic(iter, &entry->byte_value);
  668. break;
  669. case DBUS_TYPE_INT16:
  670. dbus_message_iter_get_basic(iter, &entry->int16_value);
  671. break;
  672. case DBUS_TYPE_UINT16:
  673. dbus_message_iter_get_basic(iter, &entry->uint16_value);
  674. break;
  675. case DBUS_TYPE_INT32:
  676. dbus_message_iter_get_basic(iter, &entry->int32_value);
  677. break;
  678. case DBUS_TYPE_UINT32:
  679. dbus_message_iter_get_basic(iter, &entry->uint32_value);
  680. break;
  681. case DBUS_TYPE_INT64:
  682. dbus_message_iter_get_basic(iter, &entry->int64_value);
  683. break;
  684. case DBUS_TYPE_UINT64:
  685. dbus_message_iter_get_basic(iter, &entry->uint64_value);
  686. break;
  687. case DBUS_TYPE_DOUBLE:
  688. dbus_message_iter_get_basic(iter, &entry->double_value);
  689. break;
  690. case DBUS_TYPE_ARRAY:
  691. return _wpa_dbus_dict_entry_get_array(iter, entry);
  692. default:
  693. return FALSE;
  694. }
  695. return TRUE;
  696. }
  697. /**
  698. * Read the current key/value entry from the dict. Entries are dynamically
  699. * allocated when needed and must be freed after use with the
  700. * wpa_dbus_dict_entry_clear() function.
  701. *
  702. * The returned entry object will be filled with the type and value of the next
  703. * entry in the dict, or the type will be DBUS_TYPE_INVALID if an error
  704. * occurred.
  705. *
  706. * @param iter_dict A valid DBusMessageIter returned from
  707. * wpa_dbus_dict_open_read()
  708. * @param entry A valid dict entry object into which the dict key and value
  709. * will be placed
  710. * @return TRUE on success, FALSE on failure
  711. *
  712. */
  713. dbus_bool_t wpa_dbus_dict_get_entry(DBusMessageIter *iter_dict,
  714. struct wpa_dbus_dict_entry * entry)
  715. {
  716. DBusMessageIter iter_dict_entry, iter_dict_val;
  717. int type;
  718. const char *key;
  719. if (!iter_dict || !entry)
  720. goto error;
  721. if (dbus_message_iter_get_arg_type(iter_dict) != DBUS_TYPE_DICT_ENTRY)
  722. goto error;
  723. dbus_message_iter_recurse(iter_dict, &iter_dict_entry);
  724. dbus_message_iter_get_basic(&iter_dict_entry, &key);
  725. entry->key = key;
  726. if (!dbus_message_iter_next(&iter_dict_entry))
  727. goto error;
  728. type = dbus_message_iter_get_arg_type(&iter_dict_entry);
  729. if (type != DBUS_TYPE_VARIANT)
  730. goto error;
  731. dbus_message_iter_recurse(&iter_dict_entry, &iter_dict_val);
  732. entry->type = dbus_message_iter_get_arg_type(&iter_dict_val);
  733. if (!_wpa_dbus_dict_fill_value_from_variant(entry, &iter_dict_val))
  734. goto error;
  735. dbus_message_iter_next(iter_dict);
  736. return TRUE;
  737. error:
  738. if (entry) {
  739. wpa_dbus_dict_entry_clear(entry);
  740. entry->type = DBUS_TYPE_INVALID;
  741. entry->array_type = DBUS_TYPE_INVALID;
  742. }
  743. return FALSE;
  744. }
  745. /**
  746. * Return whether or not there are additional dictionary entries.
  747. *
  748. * @param iter_dict A valid DBusMessageIter returned from
  749. * wpa_dbus_dict_open_read()
  750. * @return TRUE if more dict entries exists, FALSE if no more dict entries
  751. * exist
  752. */
  753. dbus_bool_t wpa_dbus_dict_has_dict_entry(DBusMessageIter *iter_dict)
  754. {
  755. if (!iter_dict)
  756. return FALSE;
  757. return dbus_message_iter_get_arg_type(iter_dict) ==
  758. DBUS_TYPE_DICT_ENTRY;
  759. }
  760. /**
  761. * Free any memory used by the entry object.
  762. *
  763. * @param entry The entry object
  764. */
  765. void wpa_dbus_dict_entry_clear(struct wpa_dbus_dict_entry *entry)
  766. {
  767. unsigned int i;
  768. if (!entry)
  769. return;
  770. switch (entry->type) {
  771. case DBUS_TYPE_OBJECT_PATH:
  772. case DBUS_TYPE_STRING:
  773. os_free(entry->str_value);
  774. break;
  775. case DBUS_TYPE_ARRAY:
  776. switch (entry->array_type) {
  777. case DBUS_TYPE_BYTE:
  778. os_free(entry->bytearray_value);
  779. break;
  780. case DBUS_TYPE_STRING:
  781. for (i = 0; i < entry->array_len; i++)
  782. os_free(entry->strarray_value[i]);
  783. os_free(entry->strarray_value);
  784. break;
  785. }
  786. break;
  787. }
  788. memset(entry, 0, sizeof(struct wpa_dbus_dict_entry));
  789. }