dbus_dict_helpers.c 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061
  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 boolean 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 boolean value
  181. * @return TRUE on success, FALSE on failure
  182. *
  183. */
  184. dbus_bool_t wpa_dbus_dict_append_bool(DBusMessageIter *iter_dict,
  185. const char *key, const dbus_bool_t value)
  186. {
  187. return _wpa_dbus_add_dict_entry_basic(iter_dict, key,
  188. DBUS_TYPE_BOOLEAN, &value);
  189. }
  190. /**
  191. * Add a 16-bit signed integer 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 16-bit signed integer value
  197. * @return TRUE on success, FALSE on failure
  198. *
  199. */
  200. dbus_bool_t wpa_dbus_dict_append_int16(DBusMessageIter *iter_dict,
  201. const char *key,
  202. const dbus_int16_t value)
  203. {
  204. return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_INT16,
  205. &value);
  206. }
  207. /**
  208. * Add a 16-bit unsigned integer 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 16-bit unsigned integer value
  214. * @return TRUE on success, FALSE on failure
  215. *
  216. */
  217. dbus_bool_t wpa_dbus_dict_append_uint16(DBusMessageIter *iter_dict,
  218. const char *key,
  219. const dbus_uint16_t value)
  220. {
  221. return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_UINT16,
  222. &value);
  223. }
  224. /**
  225. * Add a 32-bit signed integer to the dict.
  226. *
  227. * @param iter_dict A valid DBusMessageIter returned from
  228. * wpa_dbus_dict_open_write()
  229. * @param key The key of the dict item
  230. * @param value The 32-bit signed integer value
  231. * @return TRUE on success, FALSE on failure
  232. *
  233. */
  234. dbus_bool_t wpa_dbus_dict_append_int32(DBusMessageIter *iter_dict,
  235. const char *key,
  236. const dbus_int32_t value)
  237. {
  238. return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_INT32,
  239. &value);
  240. }
  241. /**
  242. * Add a 32-bit unsigned integer entry to the dict.
  243. *
  244. * @param iter_dict A valid DBusMessageIter returned from
  245. * wpa_dbus_dict_open_write()
  246. * @param key The key of the dict item
  247. * @param value The 32-bit unsigned integer value
  248. * @return TRUE on success, FALSE on failure
  249. *
  250. */
  251. dbus_bool_t wpa_dbus_dict_append_uint32(DBusMessageIter *iter_dict,
  252. const char *key,
  253. const dbus_uint32_t value)
  254. {
  255. return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_UINT32,
  256. &value);
  257. }
  258. /**
  259. * Add a DBus object path entry to the dict.
  260. *
  261. * @param iter_dict A valid DBusMessageIter returned from
  262. * wpa_dbus_dict_open_write()
  263. * @param key The key of the dict item
  264. * @param value The DBus object path value
  265. * @return TRUE on success, FALSE on failure
  266. *
  267. */
  268. dbus_bool_t wpa_dbus_dict_append_object_path(DBusMessageIter *iter_dict,
  269. const char *key,
  270. const char *value)
  271. {
  272. if (!value)
  273. return FALSE;
  274. return _wpa_dbus_add_dict_entry_basic(iter_dict, key,
  275. DBUS_TYPE_OBJECT_PATH, &value);
  276. }
  277. /**
  278. * Add a byte array entry to the dict.
  279. *
  280. * @param iter_dict A valid DBusMessageIter returned from
  281. * wpa_dbus_dict_open_write()
  282. * @param key The key of the dict item
  283. * @param value The byte array
  284. * @param value_len The length of the byte array, in bytes
  285. * @return TRUE on success, FALSE on failure
  286. *
  287. */
  288. dbus_bool_t wpa_dbus_dict_append_byte_array(DBusMessageIter *iter_dict,
  289. const char *key,
  290. const char *value,
  291. const dbus_uint32_t value_len)
  292. {
  293. if (!key || (!value && value_len != 0))
  294. return FALSE;
  295. return _wpa_dbus_add_dict_entry_byte_array(iter_dict, key, value,
  296. value_len);
  297. }
  298. /**
  299. * Begin an array entry in the dict
  300. *
  301. * @param iter_dict A valid DBusMessageIter returned from
  302. * wpa_dbus_dict_open_write()
  303. * @param key The key of the dict item
  304. * @param type The type of the contained data
  305. * @param iter_dict_entry A private DBusMessageIter provided by the caller to
  306. * be passed to wpa_dbus_dict_end_string_array()
  307. * @param iter_dict_val A private DBusMessageIter provided by the caller to
  308. * be passed to wpa_dbus_dict_end_string_array()
  309. * @param iter_array On return, the DBusMessageIter to be passed to
  310. * wpa_dbus_dict_string_array_add_element()
  311. * @return TRUE on success, FALSE on failure
  312. *
  313. */
  314. dbus_bool_t wpa_dbus_dict_begin_array(DBusMessageIter *iter_dict,
  315. const char *key, const char *type,
  316. DBusMessageIter *iter_dict_entry,
  317. DBusMessageIter *iter_dict_val,
  318. DBusMessageIter *iter_array)
  319. {
  320. char array_type[10];
  321. int err;
  322. err = os_snprintf(array_type, sizeof(array_type),
  323. DBUS_TYPE_ARRAY_AS_STRING "%s",
  324. type);
  325. if (os_snprintf_error(sizeof(array_type), err))
  326. return FALSE;
  327. if (!iter_dict || !iter_dict_entry || !iter_dict_val || !iter_array ||
  328. !_wpa_dbus_add_dict_entry_start(iter_dict, iter_dict_entry,
  329. key, DBUS_TYPE_ARRAY) ||
  330. !dbus_message_iter_open_container(iter_dict_entry,
  331. DBUS_TYPE_VARIANT,
  332. array_type,
  333. iter_dict_val))
  334. return FALSE;
  335. return dbus_message_iter_open_container(iter_dict_val, DBUS_TYPE_ARRAY,
  336. type, iter_array);
  337. }
  338. dbus_bool_t wpa_dbus_dict_begin_string_array(DBusMessageIter *iter_dict,
  339. const char *key,
  340. DBusMessageIter *iter_dict_entry,
  341. DBusMessageIter *iter_dict_val,
  342. DBusMessageIter *iter_array)
  343. {
  344. return wpa_dbus_dict_begin_array(
  345. iter_dict, key,
  346. DBUS_TYPE_STRING_AS_STRING,
  347. iter_dict_entry, iter_dict_val, iter_array);
  348. }
  349. /**
  350. * Add a single string element to a string array dict entry
  351. *
  352. * @param iter_array A valid DBusMessageIter returned from
  353. * wpa_dbus_dict_begin_string_array()'s
  354. * iter_array parameter
  355. * @param elem The string element to be added to the dict entry's string array
  356. * @return TRUE on success, FALSE on failure
  357. *
  358. */
  359. dbus_bool_t wpa_dbus_dict_string_array_add_element(DBusMessageIter *iter_array,
  360. const char *elem)
  361. {
  362. if (!iter_array || !elem)
  363. return FALSE;
  364. return dbus_message_iter_append_basic(iter_array, DBUS_TYPE_STRING,
  365. &elem);
  366. }
  367. /**
  368. * Add a single byte array element to a string array dict entry
  369. *
  370. * @param iter_array A valid DBusMessageIter returned from
  371. * wpa_dbus_dict_begin_array()'s iter_array
  372. * parameter -- note that wpa_dbus_dict_begin_array()
  373. * must have been called with "ay" as the type
  374. * @param value The data to be added to the dict entry's array
  375. * @param value_len The length of the data
  376. * @return TRUE on success, FALSE on failure
  377. *
  378. */
  379. dbus_bool_t wpa_dbus_dict_bin_array_add_element(DBusMessageIter *iter_array,
  380. const u8 *value,
  381. size_t value_len)
  382. {
  383. DBusMessageIter iter_bytes;
  384. size_t i;
  385. if (!iter_array || !value ||
  386. !dbus_message_iter_open_container(iter_array, DBUS_TYPE_ARRAY,
  387. DBUS_TYPE_BYTE_AS_STRING,
  388. &iter_bytes))
  389. return FALSE;
  390. for (i = 0; i < value_len; i++) {
  391. if (!dbus_message_iter_append_basic(&iter_bytes,
  392. DBUS_TYPE_BYTE,
  393. &(value[i])))
  394. return FALSE;
  395. }
  396. return dbus_message_iter_close_container(iter_array, &iter_bytes);
  397. }
  398. /**
  399. * End an array dict entry
  400. *
  401. * @param iter_dict A valid DBusMessageIter returned from
  402. * wpa_dbus_dict_open_write()
  403. * @param iter_dict_entry A private DBusMessageIter returned from
  404. * wpa_dbus_dict_begin_string_array() or
  405. * wpa_dbus_dict_begin_array()
  406. * @param iter_dict_val A private DBusMessageIter returned from
  407. * wpa_dbus_dict_begin_string_array() or
  408. * wpa_dbus_dict_begin_array()
  409. * @param iter_array A DBusMessageIter returned from
  410. * wpa_dbus_dict_begin_string_array() or
  411. * wpa_dbus_dict_begin_array()
  412. * @return TRUE on success, FALSE on failure
  413. *
  414. */
  415. dbus_bool_t wpa_dbus_dict_end_array(DBusMessageIter *iter_dict,
  416. DBusMessageIter *iter_dict_entry,
  417. DBusMessageIter *iter_dict_val,
  418. DBusMessageIter *iter_array)
  419. {
  420. if (!iter_dict || !iter_dict_entry || !iter_dict_val || !iter_array ||
  421. !dbus_message_iter_close_container(iter_dict_val, iter_array))
  422. return FALSE;
  423. return _wpa_dbus_add_dict_entry_end(iter_dict, iter_dict_entry,
  424. iter_dict_val);
  425. }
  426. /**
  427. * Convenience function to add an entire string array to the dict.
  428. *
  429. * @param iter_dict A valid DBusMessageIter returned from
  430. * wpa_dbus_dict_open_write()
  431. * @param key The key of the dict item
  432. * @param items The array of strings
  433. * @param num_items The number of strings in the array
  434. * @return TRUE on success, FALSE on failure
  435. *
  436. */
  437. dbus_bool_t wpa_dbus_dict_append_string_array(DBusMessageIter *iter_dict,
  438. const char *key,
  439. const char **items,
  440. const dbus_uint32_t num_items)
  441. {
  442. DBusMessageIter iter_dict_entry, iter_dict_val, iter_array;
  443. dbus_uint32_t i;
  444. if (!key || (!items && num_items != 0) ||
  445. !wpa_dbus_dict_begin_string_array(iter_dict, key,
  446. &iter_dict_entry, &iter_dict_val,
  447. &iter_array))
  448. return FALSE;
  449. for (i = 0; i < num_items; i++) {
  450. if (!wpa_dbus_dict_string_array_add_element(&iter_array,
  451. items[i]))
  452. return FALSE;
  453. }
  454. return wpa_dbus_dict_end_string_array(iter_dict, &iter_dict_entry,
  455. &iter_dict_val, &iter_array);
  456. }
  457. /**
  458. * Convenience function to add an wpabuf binary array to the dict.
  459. *
  460. * @param iter_dict A valid DBusMessageIter returned from
  461. * wpa_dbus_dict_open_write()
  462. * @param key The key of the dict item
  463. * @param items The array of wpabuf structures
  464. * @param num_items The number of strings in the array
  465. * @return TRUE on success, FALSE on failure
  466. *
  467. */
  468. dbus_bool_t wpa_dbus_dict_append_wpabuf_array(DBusMessageIter *iter_dict,
  469. const char *key,
  470. const struct wpabuf **items,
  471. const dbus_uint32_t num_items)
  472. {
  473. DBusMessageIter iter_dict_entry, iter_dict_val, iter_array;
  474. dbus_uint32_t i;
  475. if (!key ||
  476. (!items && num_items != 0) ||
  477. !wpa_dbus_dict_begin_array(iter_dict, key,
  478. DBUS_TYPE_ARRAY_AS_STRING
  479. DBUS_TYPE_BYTE_AS_STRING,
  480. &iter_dict_entry, &iter_dict_val,
  481. &iter_array))
  482. return FALSE;
  483. for (i = 0; i < num_items; i++) {
  484. if (!wpa_dbus_dict_bin_array_add_element(&iter_array,
  485. wpabuf_head(items[i]),
  486. wpabuf_len(items[i])))
  487. return FALSE;
  488. }
  489. return wpa_dbus_dict_end_array(iter_dict, &iter_dict_entry,
  490. &iter_dict_val, &iter_array);
  491. }
  492. /*****************************************************/
  493. /* Stuff for reading dicts */
  494. /*****************************************************/
  495. /**
  496. * Start reading from a dbus dict.
  497. *
  498. * @param iter A valid DBusMessageIter pointing to the start of the dict
  499. * @param iter_dict (out) A DBusMessageIter to be passed to
  500. * wpa_dbus_dict_read_next_entry()
  501. * @error on failure a descriptive error
  502. * @return TRUE on success, FALSE on failure
  503. *
  504. */
  505. dbus_bool_t wpa_dbus_dict_open_read(DBusMessageIter *iter,
  506. DBusMessageIter *iter_dict,
  507. DBusError *error)
  508. {
  509. int type;
  510. wpa_printf(MSG_MSGDUMP, "%s: start reading a dict entry", __func__);
  511. if (!iter || !iter_dict) {
  512. dbus_set_error_const(error, DBUS_ERROR_FAILED,
  513. "[internal] missing message iterators");
  514. return FALSE;
  515. }
  516. type = dbus_message_iter_get_arg_type(iter);
  517. if (type != DBUS_TYPE_ARRAY ||
  518. dbus_message_iter_get_element_type(iter) != DBUS_TYPE_DICT_ENTRY) {
  519. wpa_printf(MSG_DEBUG,
  520. "%s: unexpected message argument types (arg=%c element=%c)",
  521. __func__, type,
  522. type != DBUS_TYPE_ARRAY ? '?' :
  523. dbus_message_iter_get_element_type(iter));
  524. dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS,
  525. "unexpected message argument types");
  526. return FALSE;
  527. }
  528. dbus_message_iter_recurse(iter, iter_dict);
  529. return TRUE;
  530. }
  531. #define BYTE_ARRAY_CHUNK_SIZE 34
  532. #define BYTE_ARRAY_ITEM_SIZE (sizeof(char))
  533. static dbus_bool_t _wpa_dbus_dict_entry_get_byte_array(
  534. DBusMessageIter *iter, struct wpa_dbus_dict_entry *entry)
  535. {
  536. dbus_uint32_t count = 0;
  537. dbus_bool_t success = FALSE;
  538. char *buffer, *nbuffer;
  539. entry->bytearray_value = NULL;
  540. entry->array_type = DBUS_TYPE_BYTE;
  541. buffer = os_calloc(BYTE_ARRAY_CHUNK_SIZE, BYTE_ARRAY_ITEM_SIZE);
  542. if (!buffer)
  543. return FALSE;
  544. entry->array_len = 0;
  545. while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_BYTE) {
  546. char byte;
  547. if ((count % BYTE_ARRAY_CHUNK_SIZE) == 0 && count != 0) {
  548. nbuffer = os_realloc_array(
  549. buffer, count + BYTE_ARRAY_CHUNK_SIZE,
  550. BYTE_ARRAY_ITEM_SIZE);
  551. if (nbuffer == NULL) {
  552. os_free(buffer);
  553. wpa_printf(MSG_ERROR,
  554. "dbus: %s out of memory trying to retrieve the string array",
  555. __func__);
  556. goto done;
  557. }
  558. buffer = nbuffer;
  559. }
  560. dbus_message_iter_get_basic(iter, &byte);
  561. buffer[count] = byte;
  562. entry->array_len = ++count;
  563. dbus_message_iter_next(iter);
  564. }
  565. entry->bytearray_value = buffer;
  566. wpa_hexdump_key(MSG_MSGDUMP, "dbus: byte array contents",
  567. entry->bytearray_value, entry->array_len);
  568. /* Zero-length arrays are valid. */
  569. if (entry->array_len == 0) {
  570. os_free(entry->bytearray_value);
  571. entry->bytearray_value = NULL;
  572. }
  573. success = TRUE;
  574. done:
  575. return success;
  576. }
  577. #define STR_ARRAY_CHUNK_SIZE 8
  578. #define STR_ARRAY_ITEM_SIZE (sizeof(char *))
  579. static dbus_bool_t _wpa_dbus_dict_entry_get_string_array(
  580. DBusMessageIter *iter, int array_type,
  581. struct wpa_dbus_dict_entry *entry)
  582. {
  583. dbus_uint32_t count = 0;
  584. char **buffer, **nbuffer;
  585. entry->strarray_value = NULL;
  586. entry->array_len = 0;
  587. entry->array_type = DBUS_TYPE_STRING;
  588. buffer = os_calloc(STR_ARRAY_CHUNK_SIZE, STR_ARRAY_ITEM_SIZE);
  589. if (buffer == NULL)
  590. return FALSE;
  591. while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING) {
  592. const char *value;
  593. char *str;
  594. if ((count % STR_ARRAY_CHUNK_SIZE) == 0 && count != 0) {
  595. nbuffer = os_realloc_array(
  596. buffer, count + STR_ARRAY_CHUNK_SIZE,
  597. STR_ARRAY_ITEM_SIZE);
  598. if (nbuffer == NULL) {
  599. wpa_printf(MSG_ERROR,
  600. "dbus: %s out of memory trying to retrieve the string array",
  601. __func__);
  602. goto fail;
  603. }
  604. buffer = nbuffer;
  605. }
  606. dbus_message_iter_get_basic(iter, &value);
  607. wpa_printf(MSG_MSGDUMP, "%s: string_array value: %s",
  608. __func__, wpa_debug_show_keys ? value : "[omitted]");
  609. str = os_strdup(value);
  610. if (str == NULL) {
  611. wpa_printf(MSG_ERROR,
  612. "dbus: %s out of memory trying to duplicate the string array",
  613. __func__);
  614. goto fail;
  615. }
  616. buffer[count++] = str;
  617. dbus_message_iter_next(iter);
  618. }
  619. entry->strarray_value = buffer;
  620. entry->array_len = count;
  621. wpa_printf(MSG_MSGDUMP, "%s: string_array length %u",
  622. __func__, entry->array_len);
  623. /* Zero-length arrays are valid. */
  624. if (entry->array_len == 0) {
  625. os_free(entry->strarray_value);
  626. entry->strarray_value = NULL;
  627. }
  628. return TRUE;
  629. fail:
  630. while (count > 0) {
  631. count--;
  632. os_free(buffer[count]);
  633. }
  634. os_free(buffer);
  635. return FALSE;
  636. }
  637. #define BIN_ARRAY_CHUNK_SIZE 10
  638. #define BIN_ARRAY_ITEM_SIZE (sizeof(struct wpabuf *))
  639. static dbus_bool_t _wpa_dbus_dict_entry_get_binarray(
  640. DBusMessageIter *iter, struct wpa_dbus_dict_entry *entry)
  641. {
  642. struct wpa_dbus_dict_entry tmpentry;
  643. size_t buflen = 0;
  644. int i, type;
  645. entry->array_type = WPAS_DBUS_TYPE_BINARRAY;
  646. entry->array_len = 0;
  647. entry->binarray_value = NULL;
  648. type = dbus_message_iter_get_arg_type(iter);
  649. wpa_printf(MSG_MSGDUMP, "%s: parsing binarray type %c", __func__, type);
  650. if (type == DBUS_TYPE_INVALID) {
  651. /* Likely an empty array of arrays */
  652. return TRUE;
  653. }
  654. if (type != DBUS_TYPE_ARRAY) {
  655. wpa_printf(MSG_DEBUG, "%s: not an array type: %c",
  656. __func__, type);
  657. return FALSE;
  658. }
  659. type = dbus_message_iter_get_element_type(iter);
  660. if (type != DBUS_TYPE_BYTE) {
  661. wpa_printf(MSG_DEBUG, "%s: unexpected element type %c",
  662. __func__, type);
  663. return FALSE;
  664. }
  665. while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_ARRAY) {
  666. DBusMessageIter iter_array;
  667. if (entry->array_len == buflen) {
  668. struct wpabuf **newbuf;
  669. buflen += BIN_ARRAY_CHUNK_SIZE;
  670. newbuf = os_realloc_array(entry->binarray_value,
  671. buflen, BIN_ARRAY_ITEM_SIZE);
  672. if (!newbuf)
  673. goto cleanup;
  674. entry->binarray_value = newbuf;
  675. }
  676. dbus_message_iter_recurse(iter, &iter_array);
  677. os_memset(&tmpentry, 0, sizeof(tmpentry));
  678. tmpentry.type = DBUS_TYPE_ARRAY;
  679. if (_wpa_dbus_dict_entry_get_byte_array(&iter_array, &tmpentry)
  680. == FALSE)
  681. goto cleanup;
  682. entry->binarray_value[entry->array_len] =
  683. wpabuf_alloc_ext_data((u8 *) tmpentry.bytearray_value,
  684. tmpentry.array_len);
  685. if (entry->binarray_value[entry->array_len] == NULL) {
  686. wpa_dbus_dict_entry_clear(&tmpentry);
  687. goto cleanup;
  688. }
  689. entry->array_len++;
  690. dbus_message_iter_next(iter);
  691. }
  692. wpa_printf(MSG_MSGDUMP, "%s: binarray length %u",
  693. __func__, entry->array_len);
  694. return TRUE;
  695. cleanup:
  696. for (i = 0; i < (int) entry->array_len; i++)
  697. wpabuf_free(entry->binarray_value[i]);
  698. os_free(entry->binarray_value);
  699. entry->array_len = 0;
  700. entry->binarray_value = NULL;
  701. return FALSE;
  702. }
  703. static dbus_bool_t _wpa_dbus_dict_entry_get_array(
  704. DBusMessageIter *iter_dict_val, struct wpa_dbus_dict_entry *entry)
  705. {
  706. int array_type = dbus_message_iter_get_element_type(iter_dict_val);
  707. dbus_bool_t success = FALSE;
  708. DBusMessageIter iter_array;
  709. wpa_printf(MSG_MSGDUMP, "%s: array_type %c", __func__, array_type);
  710. dbus_message_iter_recurse(iter_dict_val, &iter_array);
  711. switch (array_type) {
  712. case DBUS_TYPE_BYTE:
  713. success = _wpa_dbus_dict_entry_get_byte_array(&iter_array,
  714. entry);
  715. break;
  716. case DBUS_TYPE_STRING:
  717. success = _wpa_dbus_dict_entry_get_string_array(&iter_array,
  718. array_type,
  719. entry);
  720. break;
  721. case DBUS_TYPE_ARRAY:
  722. success = _wpa_dbus_dict_entry_get_binarray(&iter_array, entry);
  723. break;
  724. default:
  725. wpa_printf(MSG_MSGDUMP, "%s: unsupported array type %c",
  726. __func__, array_type);
  727. break;
  728. }
  729. return success;
  730. }
  731. static dbus_bool_t _wpa_dbus_dict_fill_value_from_variant(
  732. struct wpa_dbus_dict_entry *entry, DBusMessageIter *iter)
  733. {
  734. const char *v;
  735. switch (entry->type) {
  736. case DBUS_TYPE_OBJECT_PATH:
  737. dbus_message_iter_get_basic(iter, &v);
  738. wpa_printf(MSG_MSGDUMP, "%s: object path value: %s",
  739. __func__, v);
  740. entry->str_value = os_strdup(v);
  741. if (entry->str_value == NULL)
  742. return FALSE;
  743. break;
  744. case DBUS_TYPE_STRING:
  745. dbus_message_iter_get_basic(iter, &v);
  746. wpa_printf(MSG_MSGDUMP, "%s: string value: %s",
  747. __func__, wpa_debug_show_keys ? v : "[omitted]");
  748. entry->str_value = os_strdup(v);
  749. if (entry->str_value == NULL)
  750. return FALSE;
  751. break;
  752. case DBUS_TYPE_BOOLEAN:
  753. dbus_message_iter_get_basic(iter, &entry->bool_value);
  754. wpa_printf(MSG_MSGDUMP, "%s: boolean value: %d",
  755. __func__, entry->bool_value);
  756. break;
  757. case DBUS_TYPE_BYTE:
  758. dbus_message_iter_get_basic(iter, &entry->byte_value);
  759. wpa_printf(MSG_MSGDUMP, "%s: byte value: %d",
  760. __func__, entry->byte_value);
  761. break;
  762. case DBUS_TYPE_INT16:
  763. dbus_message_iter_get_basic(iter, &entry->int16_value);
  764. wpa_printf(MSG_MSGDUMP, "%s: int16 value: %d",
  765. __func__, entry->int16_value);
  766. break;
  767. case DBUS_TYPE_UINT16:
  768. dbus_message_iter_get_basic(iter, &entry->uint16_value);
  769. wpa_printf(MSG_MSGDUMP, "%s: uint16 value: %d",
  770. __func__, entry->uint16_value);
  771. break;
  772. case DBUS_TYPE_INT32:
  773. dbus_message_iter_get_basic(iter, &entry->int32_value);
  774. wpa_printf(MSG_MSGDUMP, "%s: int32 value: %d",
  775. __func__, entry->int32_value);
  776. break;
  777. case DBUS_TYPE_UINT32:
  778. dbus_message_iter_get_basic(iter, &entry->uint32_value);
  779. wpa_printf(MSG_MSGDUMP, "%s: uint32 value: %d",
  780. __func__, entry->uint32_value);
  781. break;
  782. case DBUS_TYPE_INT64:
  783. dbus_message_iter_get_basic(iter, &entry->int64_value);
  784. wpa_printf(MSG_MSGDUMP, "%s: int64 value: %lld",
  785. __func__, (long long int) entry->int64_value);
  786. break;
  787. case DBUS_TYPE_UINT64:
  788. dbus_message_iter_get_basic(iter, &entry->uint64_value);
  789. wpa_printf(MSG_MSGDUMP, "%s: uint64 value: %llu",
  790. __func__,
  791. (unsigned long long int) entry->uint64_value);
  792. break;
  793. case DBUS_TYPE_DOUBLE:
  794. dbus_message_iter_get_basic(iter, &entry->double_value);
  795. wpa_printf(MSG_MSGDUMP, "%s: double value: %f",
  796. __func__, entry->double_value);
  797. break;
  798. case DBUS_TYPE_ARRAY:
  799. return _wpa_dbus_dict_entry_get_array(iter, entry);
  800. default:
  801. wpa_printf(MSG_MSGDUMP, "%s: unsupported type %c",
  802. __func__, entry->type);
  803. return FALSE;
  804. }
  805. return TRUE;
  806. }
  807. /**
  808. * Read the current key/value entry from the dict. Entries are dynamically
  809. * allocated when needed and must be freed after use with the
  810. * wpa_dbus_dict_entry_clear() function.
  811. *
  812. * The returned entry object will be filled with the type and value of the next
  813. * entry in the dict, or the type will be DBUS_TYPE_INVALID if an error
  814. * occurred.
  815. *
  816. * @param iter_dict A valid DBusMessageIter returned from
  817. * wpa_dbus_dict_open_read()
  818. * @param entry A valid dict entry object into which the dict key and value
  819. * will be placed
  820. * @return TRUE on success, FALSE on failure
  821. *
  822. */
  823. dbus_bool_t wpa_dbus_dict_get_entry(DBusMessageIter *iter_dict,
  824. struct wpa_dbus_dict_entry * entry)
  825. {
  826. DBusMessageIter iter_dict_entry, iter_dict_val;
  827. int type;
  828. const char *key;
  829. if (!iter_dict || !entry ||
  830. dbus_message_iter_get_arg_type(iter_dict) != DBUS_TYPE_DICT_ENTRY) {
  831. wpa_printf(MSG_DEBUG, "%s: not a dict entry", __func__);
  832. goto error;
  833. }
  834. dbus_message_iter_recurse(iter_dict, &iter_dict_entry);
  835. dbus_message_iter_get_basic(&iter_dict_entry, &key);
  836. wpa_printf(MSG_MSGDUMP, "%s: dict entry key: %s", __func__, key);
  837. entry->key = key;
  838. if (!dbus_message_iter_next(&iter_dict_entry)) {
  839. wpa_printf(MSG_DEBUG, "%s: no variant in dict entry", __func__);
  840. goto error;
  841. }
  842. type = dbus_message_iter_get_arg_type(&iter_dict_entry);
  843. if (type != DBUS_TYPE_VARIANT) {
  844. wpa_printf(MSG_DEBUG,
  845. "%s: unexpected dict entry variant type: %c",
  846. __func__, type);
  847. goto error;
  848. }
  849. dbus_message_iter_recurse(&iter_dict_entry, &iter_dict_val);
  850. entry->type = dbus_message_iter_get_arg_type(&iter_dict_val);
  851. wpa_printf(MSG_MSGDUMP, "%s: dict entry variant content type: %c",
  852. __func__, entry->type);
  853. entry->array_type = DBUS_TYPE_INVALID;
  854. if (!_wpa_dbus_dict_fill_value_from_variant(entry, &iter_dict_val)) {
  855. wpa_printf(MSG_DEBUG,
  856. "%s: failed to fetch dict values from variant",
  857. __func__);
  858. goto error;
  859. }
  860. dbus_message_iter_next(iter_dict);
  861. return TRUE;
  862. error:
  863. if (entry) {
  864. wpa_dbus_dict_entry_clear(entry);
  865. entry->type = DBUS_TYPE_INVALID;
  866. entry->array_type = DBUS_TYPE_INVALID;
  867. }
  868. return FALSE;
  869. }
  870. /**
  871. * Return whether or not there are additional dictionary entries.
  872. *
  873. * @param iter_dict A valid DBusMessageIter returned from
  874. * wpa_dbus_dict_open_read()
  875. * @return TRUE if more dict entries exists, FALSE if no more dict entries
  876. * exist
  877. */
  878. dbus_bool_t wpa_dbus_dict_has_dict_entry(DBusMessageIter *iter_dict)
  879. {
  880. if (!iter_dict)
  881. return FALSE;
  882. return dbus_message_iter_get_arg_type(iter_dict) ==
  883. DBUS_TYPE_DICT_ENTRY;
  884. }
  885. /**
  886. * Free any memory used by the entry object.
  887. *
  888. * @param entry The entry object
  889. */
  890. void wpa_dbus_dict_entry_clear(struct wpa_dbus_dict_entry *entry)
  891. {
  892. unsigned int i;
  893. if (!entry)
  894. return;
  895. switch (entry->type) {
  896. case DBUS_TYPE_OBJECT_PATH:
  897. case DBUS_TYPE_STRING:
  898. os_free(entry->str_value);
  899. break;
  900. case DBUS_TYPE_ARRAY:
  901. switch (entry->array_type) {
  902. case DBUS_TYPE_BYTE:
  903. os_free(entry->bytearray_value);
  904. break;
  905. case DBUS_TYPE_STRING:
  906. if (!entry->strarray_value)
  907. break;
  908. for (i = 0; i < entry->array_len; i++)
  909. os_free(entry->strarray_value[i]);
  910. os_free(entry->strarray_value);
  911. break;
  912. case WPAS_DBUS_TYPE_BINARRAY:
  913. for (i = 0; i < entry->array_len; i++)
  914. wpabuf_free(entry->binarray_value[i]);
  915. os_free(entry->binarray_value);
  916. break;
  917. }
  918. break;
  919. }
  920. os_memset(entry, 0, sizeof(struct wpa_dbus_dict_entry));
  921. }