dbus_dict_helpers.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134
  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->bytearray_value = buffer;
  611. entry->array_len = 0;
  612. while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_BYTE) {
  613. char byte;
  614. if ((count % BYTE_ARRAY_CHUNK_SIZE) == 0 && count != 0) {
  615. nbuffer = os_realloc_array(
  616. buffer, count + BYTE_ARRAY_CHUNK_SIZE,
  617. BYTE_ARRAY_ITEM_SIZE);
  618. if (nbuffer == NULL) {
  619. os_free(buffer);
  620. wpa_printf(MSG_ERROR, "dbus: _wpa_dbus_dict_"
  621. "entry_get_byte_array out of "
  622. "memory trying to retrieve the "
  623. "string array");
  624. goto done;
  625. }
  626. buffer = nbuffer;
  627. }
  628. entry->bytearray_value = buffer;
  629. dbus_message_iter_get_basic(iter, &byte);
  630. entry->bytearray_value[count] = byte;
  631. entry->array_len = ++count;
  632. dbus_message_iter_next(iter);
  633. }
  634. wpa_hexdump_key(MSG_MSGDUMP, "dbus: byte array contents",
  635. entry->bytearray_value, entry->array_len);
  636. /* Zero-length arrays are valid. */
  637. if (entry->array_len == 0) {
  638. os_free(entry->bytearray_value);
  639. entry->bytearray_value = NULL;
  640. }
  641. success = TRUE;
  642. done:
  643. return success;
  644. }
  645. #define STR_ARRAY_CHUNK_SIZE 8
  646. #define STR_ARRAY_ITEM_SIZE (sizeof(char *))
  647. static dbus_bool_t _wpa_dbus_dict_entry_get_string_array(
  648. DBusMessageIter *iter, int array_type,
  649. struct wpa_dbus_dict_entry *entry)
  650. {
  651. dbus_uint32_t count = 0;
  652. dbus_bool_t success = FALSE;
  653. char **buffer, **nbuffer;
  654. entry->strarray_value = NULL;
  655. entry->array_type = DBUS_TYPE_STRING;
  656. buffer = os_calloc(STR_ARRAY_CHUNK_SIZE, STR_ARRAY_ITEM_SIZE);
  657. if (buffer == NULL)
  658. return FALSE;
  659. entry->strarray_value = buffer;
  660. entry->array_len = 0;
  661. while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING) {
  662. const char *value;
  663. char *str;
  664. if ((count % STR_ARRAY_CHUNK_SIZE) == 0 && count != 0) {
  665. nbuffer = os_realloc_array(
  666. buffer, count + STR_ARRAY_CHUNK_SIZE,
  667. STR_ARRAY_ITEM_SIZE);
  668. if (nbuffer == NULL) {
  669. os_free(buffer);
  670. wpa_printf(MSG_ERROR, "dbus: _wpa_dbus_dict_"
  671. "entry_get_string_array out of "
  672. "memory trying to retrieve the "
  673. "string array");
  674. goto done;
  675. }
  676. buffer = nbuffer;
  677. }
  678. entry->strarray_value = buffer;
  679. dbus_message_iter_get_basic(iter, &value);
  680. wpa_printf(MSG_MSGDUMP, "%s: string_array value: %s",
  681. __func__, wpa_debug_show_keys ? value : "[omitted]");
  682. str = os_strdup(value);
  683. if (str == NULL) {
  684. wpa_printf(MSG_ERROR, "dbus: _wpa_dbus_dict_entry_get_"
  685. "string_array out of memory trying to "
  686. "duplicate the string array");
  687. goto done;
  688. }
  689. entry->strarray_value[count] = str;
  690. entry->array_len = ++count;
  691. dbus_message_iter_next(iter);
  692. }
  693. wpa_printf(MSG_MSGDUMP, "%s: string_array length %u",
  694. __func__, entry->array_len);
  695. /* Zero-length arrays are valid. */
  696. if (entry->array_len == 0) {
  697. os_free(entry->strarray_value);
  698. entry->strarray_value = NULL;
  699. }
  700. success = TRUE;
  701. done:
  702. return success;
  703. }
  704. #define BIN_ARRAY_CHUNK_SIZE 10
  705. #define BIN_ARRAY_ITEM_SIZE (sizeof(struct wpabuf *))
  706. static dbus_bool_t _wpa_dbus_dict_entry_get_binarray(
  707. DBusMessageIter *iter, struct wpa_dbus_dict_entry *entry)
  708. {
  709. struct wpa_dbus_dict_entry tmpentry;
  710. size_t buflen = 0;
  711. int i, type;
  712. entry->array_type = WPAS_DBUS_TYPE_BINARRAY;
  713. entry->array_len = 0;
  714. entry->binarray_value = NULL;
  715. type = dbus_message_iter_get_arg_type(iter);
  716. wpa_printf(MSG_MSGDUMP, "%s: parsing binarray type %c", __func__, type);
  717. if (type == DBUS_TYPE_INVALID) {
  718. /* Likely an empty array of arrays */
  719. return TRUE;
  720. }
  721. if (type != DBUS_TYPE_ARRAY) {
  722. wpa_printf(MSG_DEBUG, "%s: not an array type: %c",
  723. __func__, type);
  724. return FALSE;
  725. }
  726. type = dbus_message_iter_get_element_type(iter);
  727. if (type != DBUS_TYPE_BYTE) {
  728. wpa_printf(MSG_DEBUG, "%s: unexpected element type %c",
  729. __func__, type);
  730. return FALSE;
  731. }
  732. while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_ARRAY) {
  733. DBusMessageIter iter_array;
  734. if (entry->array_len == buflen) {
  735. struct wpabuf **newbuf;
  736. buflen += BIN_ARRAY_CHUNK_SIZE;
  737. newbuf = os_realloc_array(entry->binarray_value,
  738. buflen, BIN_ARRAY_ITEM_SIZE);
  739. if (!newbuf)
  740. goto cleanup;
  741. entry->binarray_value = newbuf;
  742. }
  743. dbus_message_iter_recurse(iter, &iter_array);
  744. os_memset(&tmpentry, 0, sizeof(tmpentry));
  745. tmpentry.type = DBUS_TYPE_ARRAY;
  746. if (_wpa_dbus_dict_entry_get_byte_array(&iter_array, &tmpentry)
  747. == FALSE)
  748. goto cleanup;
  749. entry->binarray_value[entry->array_len] =
  750. wpabuf_alloc_ext_data((u8 *) tmpentry.bytearray_value,
  751. tmpentry.array_len);
  752. if (entry->binarray_value[entry->array_len] == NULL) {
  753. wpa_dbus_dict_entry_clear(&tmpentry);
  754. goto cleanup;
  755. }
  756. entry->array_len++;
  757. dbus_message_iter_next(iter);
  758. }
  759. wpa_printf(MSG_MSGDUMP, "%s: binarray length %u",
  760. __func__, entry->array_len);
  761. return TRUE;
  762. cleanup:
  763. for (i = 0; i < (int) entry->array_len; i++)
  764. wpabuf_free(entry->binarray_value[i]);
  765. os_free(entry->binarray_value);
  766. entry->array_len = 0;
  767. entry->binarray_value = NULL;
  768. return FALSE;
  769. }
  770. static dbus_bool_t _wpa_dbus_dict_entry_get_array(
  771. DBusMessageIter *iter_dict_val, struct wpa_dbus_dict_entry *entry)
  772. {
  773. int array_type = dbus_message_iter_get_element_type(iter_dict_val);
  774. dbus_bool_t success = FALSE;
  775. DBusMessageIter iter_array;
  776. wpa_printf(MSG_MSGDUMP, "%s: array_type %c", __func__, array_type);
  777. dbus_message_iter_recurse(iter_dict_val, &iter_array);
  778. switch (array_type) {
  779. case DBUS_TYPE_BYTE:
  780. success = _wpa_dbus_dict_entry_get_byte_array(&iter_array,
  781. entry);
  782. break;
  783. case DBUS_TYPE_STRING:
  784. success = _wpa_dbus_dict_entry_get_string_array(&iter_array,
  785. array_type,
  786. entry);
  787. break;
  788. case DBUS_TYPE_ARRAY:
  789. success = _wpa_dbus_dict_entry_get_binarray(&iter_array, entry);
  790. break;
  791. default:
  792. wpa_printf(MSG_MSGDUMP, "%s: unsupported array type %c",
  793. __func__, array_type);
  794. break;
  795. }
  796. return success;
  797. }
  798. static dbus_bool_t _wpa_dbus_dict_fill_value_from_variant(
  799. struct wpa_dbus_dict_entry *entry, DBusMessageIter *iter)
  800. {
  801. const char *v;
  802. switch (entry->type) {
  803. case DBUS_TYPE_OBJECT_PATH:
  804. dbus_message_iter_get_basic(iter, &v);
  805. wpa_printf(MSG_MSGDUMP, "%s: object path value: %s",
  806. __func__, v);
  807. entry->str_value = os_strdup(v);
  808. if (entry->str_value == NULL)
  809. return FALSE;
  810. break;
  811. case DBUS_TYPE_STRING:
  812. dbus_message_iter_get_basic(iter, &v);
  813. wpa_printf(MSG_MSGDUMP, "%s: string value: %s",
  814. __func__, wpa_debug_show_keys ? v : "[omitted]");
  815. entry->str_value = os_strdup(v);
  816. if (entry->str_value == NULL)
  817. return FALSE;
  818. break;
  819. case DBUS_TYPE_BOOLEAN:
  820. dbus_message_iter_get_basic(iter, &entry->bool_value);
  821. wpa_printf(MSG_MSGDUMP, "%s: boolean value: %d",
  822. __func__, entry->bool_value);
  823. break;
  824. case DBUS_TYPE_BYTE:
  825. dbus_message_iter_get_basic(iter, &entry->byte_value);
  826. wpa_printf(MSG_MSGDUMP, "%s: byte value: %d",
  827. __func__, entry->byte_value);
  828. break;
  829. case DBUS_TYPE_INT16:
  830. dbus_message_iter_get_basic(iter, &entry->int16_value);
  831. wpa_printf(MSG_MSGDUMP, "%s: int16 value: %d",
  832. __func__, entry->int16_value);
  833. break;
  834. case DBUS_TYPE_UINT16:
  835. dbus_message_iter_get_basic(iter, &entry->uint16_value);
  836. wpa_printf(MSG_MSGDUMP, "%s: uint16 value: %d",
  837. __func__, entry->uint16_value);
  838. break;
  839. case DBUS_TYPE_INT32:
  840. dbus_message_iter_get_basic(iter, &entry->int32_value);
  841. wpa_printf(MSG_MSGDUMP, "%s: int32 value: %d",
  842. __func__, entry->int32_value);
  843. break;
  844. case DBUS_TYPE_UINT32:
  845. dbus_message_iter_get_basic(iter, &entry->uint32_value);
  846. wpa_printf(MSG_MSGDUMP, "%s: uint32 value: %d",
  847. __func__, entry->uint32_value);
  848. break;
  849. case DBUS_TYPE_INT64:
  850. dbus_message_iter_get_basic(iter, &entry->int64_value);
  851. wpa_printf(MSG_MSGDUMP, "%s: int64 value: %lld",
  852. __func__, (long long int) entry->int64_value);
  853. break;
  854. case DBUS_TYPE_UINT64:
  855. dbus_message_iter_get_basic(iter, &entry->uint64_value);
  856. wpa_printf(MSG_MSGDUMP, "%s: uint64 value: %llu",
  857. __func__,
  858. (unsigned long long int) entry->uint64_value);
  859. break;
  860. case DBUS_TYPE_DOUBLE:
  861. dbus_message_iter_get_basic(iter, &entry->double_value);
  862. wpa_printf(MSG_MSGDUMP, "%s: double value: %f",
  863. __func__, entry->double_value);
  864. break;
  865. case DBUS_TYPE_ARRAY:
  866. return _wpa_dbus_dict_entry_get_array(iter, entry);
  867. default:
  868. wpa_printf(MSG_MSGDUMP, "%s: unsupported type %c",
  869. __func__, entry->type);
  870. return FALSE;
  871. }
  872. return TRUE;
  873. }
  874. /**
  875. * Read the current key/value entry from the dict. Entries are dynamically
  876. * allocated when needed and must be freed after use with the
  877. * wpa_dbus_dict_entry_clear() function.
  878. *
  879. * The returned entry object will be filled with the type and value of the next
  880. * entry in the dict, or the type will be DBUS_TYPE_INVALID if an error
  881. * occurred.
  882. *
  883. * @param iter_dict A valid DBusMessageIter returned from
  884. * wpa_dbus_dict_open_read()
  885. * @param entry A valid dict entry object into which the dict key and value
  886. * will be placed
  887. * @return TRUE on success, FALSE on failure
  888. *
  889. */
  890. dbus_bool_t wpa_dbus_dict_get_entry(DBusMessageIter *iter_dict,
  891. struct wpa_dbus_dict_entry * entry)
  892. {
  893. DBusMessageIter iter_dict_entry, iter_dict_val;
  894. int type;
  895. const char *key;
  896. if (!iter_dict || !entry ||
  897. dbus_message_iter_get_arg_type(iter_dict) != DBUS_TYPE_DICT_ENTRY) {
  898. wpa_printf(MSG_DEBUG, "%s: not a dict entry", __func__);
  899. goto error;
  900. }
  901. dbus_message_iter_recurse(iter_dict, &iter_dict_entry);
  902. dbus_message_iter_get_basic(&iter_dict_entry, &key);
  903. wpa_printf(MSG_MSGDUMP, "%s: dict entry key: %s", __func__, key);
  904. entry->key = key;
  905. if (!dbus_message_iter_next(&iter_dict_entry)) {
  906. wpa_printf(MSG_DEBUG, "%s: no variant in dict entry", __func__);
  907. goto error;
  908. }
  909. type = dbus_message_iter_get_arg_type(&iter_dict_entry);
  910. if (type != DBUS_TYPE_VARIANT) {
  911. wpa_printf(MSG_DEBUG,
  912. "%s: unexpected dict entry variant type: %c",
  913. __func__, type);
  914. goto error;
  915. }
  916. dbus_message_iter_recurse(&iter_dict_entry, &iter_dict_val);
  917. entry->type = dbus_message_iter_get_arg_type(&iter_dict_val);
  918. wpa_printf(MSG_MSGDUMP, "%s: dict entry variant content type: %c",
  919. __func__, entry->type);
  920. entry->array_type = DBUS_TYPE_INVALID;
  921. if (!_wpa_dbus_dict_fill_value_from_variant(entry, &iter_dict_val)) {
  922. wpa_printf(MSG_DEBUG,
  923. "%s: failed to fetch dict values from variant",
  924. __func__);
  925. goto error;
  926. }
  927. dbus_message_iter_next(iter_dict);
  928. return TRUE;
  929. error:
  930. if (entry) {
  931. wpa_dbus_dict_entry_clear(entry);
  932. entry->type = DBUS_TYPE_INVALID;
  933. entry->array_type = DBUS_TYPE_INVALID;
  934. }
  935. return FALSE;
  936. }
  937. /**
  938. * Return whether or not there are additional dictionary entries.
  939. *
  940. * @param iter_dict A valid DBusMessageIter returned from
  941. * wpa_dbus_dict_open_read()
  942. * @return TRUE if more dict entries exists, FALSE if no more dict entries
  943. * exist
  944. */
  945. dbus_bool_t wpa_dbus_dict_has_dict_entry(DBusMessageIter *iter_dict)
  946. {
  947. if (!iter_dict)
  948. return FALSE;
  949. return dbus_message_iter_get_arg_type(iter_dict) ==
  950. DBUS_TYPE_DICT_ENTRY;
  951. }
  952. /**
  953. * Free any memory used by the entry object.
  954. *
  955. * @param entry The entry object
  956. */
  957. void wpa_dbus_dict_entry_clear(struct wpa_dbus_dict_entry *entry)
  958. {
  959. unsigned int i;
  960. if (!entry)
  961. return;
  962. switch (entry->type) {
  963. case DBUS_TYPE_OBJECT_PATH:
  964. case DBUS_TYPE_STRING:
  965. os_free(entry->str_value);
  966. break;
  967. case DBUS_TYPE_ARRAY:
  968. switch (entry->array_type) {
  969. case DBUS_TYPE_BYTE:
  970. os_free(entry->bytearray_value);
  971. break;
  972. case DBUS_TYPE_STRING:
  973. for (i = 0; i < entry->array_len; i++)
  974. os_free(entry->strarray_value[i]);
  975. os_free(entry->strarray_value);
  976. break;
  977. case WPAS_DBUS_TYPE_BINARRAY:
  978. for (i = 0; i < entry->array_len; i++)
  979. wpabuf_free(entry->binarray_value[i]);
  980. os_free(entry->binarray_value);
  981. break;
  982. }
  983. break;
  984. }
  985. os_memset(entry, 0, sizeof(struct wpa_dbus_dict_entry));
  986. }