ctrl_iface_dbus_new_helpers.c 53 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913
  1. /*
  2. * WPA Supplicant / dbus-based control interface
  3. * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
  4. * Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. *
  10. * Alternatively, this software may be distributed under the terms of BSD
  11. * license.
  12. *
  13. * See README and COPYING for more details.
  14. */
  15. #include "includes.h"
  16. #include "common.h"
  17. #include "eloop.h"
  18. #include "ctrl_iface_dbus_new_helpers.h"
  19. /**
  20. * struct wpa_dbus_method_desc - DBus method description
  21. */
  22. struct wpa_dbus_method_desc {
  23. /* pointer to next description in list */
  24. struct wpa_dbus_method_desc *next;
  25. /* method interface */
  26. char *dbus_interface;
  27. /* method name */
  28. char *dbus_method;
  29. /* method handling function */
  30. WPADBusMethodHandler method_handler;
  31. /* handler function argument */
  32. void *handler_argument;
  33. /* function used to free handler argument */
  34. WPADBusArgumentFreeFunction argument_free_func;
  35. /* number of method arguments */
  36. int args_num;
  37. /* array of arguments */
  38. struct wpa_dbus_argument args[];
  39. };
  40. /**
  41. * struct wpa_dbus_signal_desc - DBus signal description
  42. */
  43. struct wpa_dbus_signal_desc {
  44. /* pointer to next description in list */
  45. struct wpa_dbus_signal_desc *next;
  46. /* signal interface */
  47. char *dbus_interface;
  48. /* signal name */
  49. char *dbus_signal;
  50. /* number of signal arguments */
  51. int args_num;
  52. /* array of arguments */
  53. struct wpa_dbus_argument args[0];
  54. };
  55. /**
  56. * struct wpa_dbus_property_desc - DBus property description
  57. */
  58. struct wpa_dbus_property_desc {
  59. /* pointer to next description in list */
  60. struct wpa_dbus_property_desc *next;
  61. /* property interface */
  62. char *dbus_interface;
  63. /* property name */
  64. char *dbus_property;
  65. /* property type signature in DBus type notation */
  66. char *type;
  67. /* property access permissions */
  68. enum dbus_prop_access access;
  69. /* property getter function */
  70. WPADBusPropertyAccessor getter;
  71. /* property setter function */
  72. WPADBusPropertyAccessor setter;
  73. /* argument for getter and setter functions */
  74. void *user_data;
  75. /* function used to free accessors argument */
  76. WPADBusArgumentFreeFunction user_data_free_func;
  77. };
  78. #ifdef CONFIG_CTRL_IFACE_DBUS_INTRO
  79. #include <libxml/tree.h>
  80. struct interfaces {
  81. struct interfaces *next;
  82. char *dbus_interface;
  83. xmlNodePtr interface_node;
  84. };
  85. #endif /* CONFIG_CTRL_IFACE_DBUS_INTRO */
  86. static void process_watch(struct ctrl_iface_dbus_new_priv *iface,
  87. DBusWatch *watch, eloop_event_type type)
  88. {
  89. dbus_connection_ref(iface->con);
  90. iface->should_dispatch = 0;
  91. if (type == EVENT_TYPE_READ)
  92. dbus_watch_handle(watch, DBUS_WATCH_READABLE);
  93. else if (type == EVENT_TYPE_WRITE)
  94. dbus_watch_handle(watch, DBUS_WATCH_WRITABLE);
  95. else if (type == EVENT_TYPE_EXCEPTION)
  96. dbus_watch_handle(watch, DBUS_WATCH_ERROR);
  97. if (iface->should_dispatch) {
  98. while (dbus_connection_get_dispatch_status(iface->con) ==
  99. DBUS_DISPATCH_DATA_REMAINS)
  100. dbus_connection_dispatch(iface->con);
  101. iface->should_dispatch = 0;
  102. }
  103. dbus_connection_unref(iface->con);
  104. }
  105. static void process_watch_exception(int sock, void *eloop_ctx, void *sock_ctx)
  106. {
  107. process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_EXCEPTION);
  108. }
  109. static void process_watch_read(int sock, void *eloop_ctx, void *sock_ctx)
  110. {
  111. process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_READ);
  112. }
  113. static void process_watch_write(int sock, void *eloop_ctx, void *sock_ctx)
  114. {
  115. process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_WRITE);
  116. }
  117. static void connection_setup_add_watch(struct ctrl_iface_dbus_new_priv *iface,
  118. DBusWatch *watch)
  119. {
  120. unsigned int flags;
  121. int fd;
  122. if (!dbus_watch_get_enabled(watch))
  123. return;
  124. flags = dbus_watch_get_flags(watch);
  125. fd = dbus_watch_get_unix_fd(watch);
  126. eloop_register_sock(fd, EVENT_TYPE_EXCEPTION, process_watch_exception,
  127. iface, watch);
  128. if (flags & DBUS_WATCH_READABLE) {
  129. eloop_register_sock(fd, EVENT_TYPE_READ, process_watch_read,
  130. iface, watch);
  131. }
  132. if (flags & DBUS_WATCH_WRITABLE) {
  133. eloop_register_sock(fd, EVENT_TYPE_WRITE, process_watch_write,
  134. iface, watch);
  135. }
  136. dbus_watch_set_data(watch, iface, NULL);
  137. }
  138. static void connection_setup_remove_watch(
  139. struct ctrl_iface_dbus_new_priv *iface, DBusWatch *watch)
  140. {
  141. unsigned int flags;
  142. int fd;
  143. flags = dbus_watch_get_flags(watch);
  144. fd = dbus_watch_get_unix_fd(watch);
  145. eloop_unregister_sock(fd, EVENT_TYPE_EXCEPTION);
  146. if (flags & DBUS_WATCH_READABLE)
  147. eloop_unregister_sock(fd, EVENT_TYPE_READ);
  148. if (flags & DBUS_WATCH_WRITABLE)
  149. eloop_unregister_sock(fd, EVENT_TYPE_WRITE);
  150. dbus_watch_set_data(watch, NULL, NULL);
  151. }
  152. static dbus_bool_t add_watch(DBusWatch *watch, void *data)
  153. {
  154. connection_setup_add_watch(data, watch);
  155. return TRUE;
  156. }
  157. static void remove_watch(DBusWatch *watch, void *data)
  158. {
  159. connection_setup_remove_watch(data, watch);
  160. }
  161. static void watch_toggled(DBusWatch *watch, void *data)
  162. {
  163. if (dbus_watch_get_enabled(watch))
  164. add_watch(watch, data);
  165. else
  166. remove_watch(watch, data);
  167. }
  168. static void process_timeout(void *eloop_ctx, void *sock_ctx)
  169. {
  170. DBusTimeout *timeout = sock_ctx;
  171. dbus_timeout_handle(timeout);
  172. }
  173. static void connection_setup_add_timeout(
  174. struct ctrl_iface_dbus_new_priv *iface, DBusTimeout *timeout)
  175. {
  176. if (!dbus_timeout_get_enabled(timeout))
  177. return;
  178. eloop_register_timeout(0, dbus_timeout_get_interval(timeout) * 1000,
  179. process_timeout, iface, timeout);
  180. dbus_timeout_set_data(timeout, iface, NULL);
  181. }
  182. static void connection_setup_remove_timeout(
  183. struct ctrl_iface_dbus_new_priv *iface, DBusTimeout *timeout)
  184. {
  185. eloop_cancel_timeout(process_timeout, iface, timeout);
  186. dbus_timeout_set_data(timeout, NULL, NULL);
  187. }
  188. static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data)
  189. {
  190. if (!dbus_timeout_get_enabled(timeout))
  191. return TRUE;
  192. connection_setup_add_timeout(data, timeout);
  193. return TRUE;
  194. }
  195. static void remove_timeout(DBusTimeout *timeout, void *data)
  196. {
  197. connection_setup_remove_timeout(data, timeout);
  198. }
  199. static void timeout_toggled(DBusTimeout *timeout, void *data)
  200. {
  201. if (dbus_timeout_get_enabled(timeout))
  202. add_timeout(timeout, data);
  203. else
  204. remove_timeout(timeout, data);
  205. }
  206. static void process_wakeup_main(int sig, void *eloop_ctx, void *signal_ctx)
  207. {
  208. struct ctrl_iface_dbus_new_priv *iface = signal_ctx;
  209. if (sig != SIGPOLL || !iface->con)
  210. return;
  211. if (dbus_connection_get_dispatch_status(iface->con) !=
  212. DBUS_DISPATCH_DATA_REMAINS)
  213. return;
  214. /* Only dispatch once - we do not want to starve other events */
  215. dbus_connection_ref(iface->con);
  216. dbus_connection_dispatch(iface->con);
  217. dbus_connection_unref(iface->con);
  218. }
  219. /**
  220. * wakeup_main - Attempt to wake our mainloop up
  221. * @data: dbus control interface private data
  222. *
  223. * Try to wake up the main eloop so it will process
  224. * dbus events that may have happened.
  225. */
  226. static void wakeup_main(void *data)
  227. {
  228. struct ctrl_iface_dbus_new_priv *iface = data;
  229. /* Use SIGPOLL to break out of the eloop select() */
  230. raise(SIGPOLL);
  231. iface->should_dispatch = 1;
  232. }
  233. /**
  234. * connection_setup_wakeup_main - Tell dbus about our wakeup_main function
  235. * @iface: dbus control interface private data
  236. * Returns: 0 on success, -1 on failure
  237. *
  238. * Register our wakeup_main handler with dbus
  239. */
  240. static int connection_setup_wakeup_main(struct ctrl_iface_dbus_new_priv *iface)
  241. {
  242. if (eloop_register_signal(SIGPOLL, process_wakeup_main, iface))
  243. return -1;
  244. dbus_connection_set_wakeup_main_function(iface->con, wakeup_main,
  245. iface, NULL);
  246. return 0;
  247. }
  248. /**
  249. * wpa_dbus_next_objid - Return next available object id
  250. * @iface: dbus control interface private data
  251. * Returns: Object id
  252. */
  253. u32 wpa_dbus_next_objid(struct ctrl_iface_dbus_new_priv *iface)
  254. {
  255. return iface->next_objid++;
  256. }
  257. /**
  258. * integrate_with_eloop - Register our mainloop integration with dbus
  259. * @connection: connection to the system message bus
  260. * @iface: a dbus control interface data structure
  261. * Returns: 0 on success, -1 on failure
  262. *
  263. * We register our mainloop integration functions with dbus here.
  264. */
  265. static int integrate_with_eloop(DBusConnection *connection,
  266. struct ctrl_iface_dbus_new_priv *iface)
  267. {
  268. if (!dbus_connection_set_watch_functions(connection, add_watch,
  269. remove_watch, watch_toggled,
  270. iface, NULL)) {
  271. perror("dbus_connection_set_watch_functions[dbus]");
  272. wpa_printf(MSG_ERROR, "Not enough memory to set up dbus.");
  273. return -1;
  274. }
  275. if (!dbus_connection_set_timeout_functions(connection, add_timeout,
  276. remove_timeout,
  277. timeout_toggled, iface,
  278. NULL)) {
  279. perror("dbus_connection_set_timeout_functions[dbus]");
  280. wpa_printf(MSG_ERROR, "Not enough memory to set up dbus.");
  281. return -1;
  282. }
  283. if (connection_setup_wakeup_main(iface) < 0) {
  284. perror("connection_setup_wakeup_main[dbus]");
  285. wpa_printf(MSG_ERROR, "Could not setup main wakeup function.");
  286. return -1;
  287. }
  288. return 0;
  289. }
  290. /**
  291. * dispatch_initial_dbus_messages - Dispatch initial dbus messages after
  292. * claiming bus name
  293. * @eloop_ctx: the DBusConnection to dispatch on
  294. * @timeout_ctx: unused
  295. *
  296. * If clients are quick to notice that service claimed its bus name,
  297. * there may have been messages that came in before initialization was
  298. * all finished. Dispatch those here.
  299. */
  300. static void dispatch_initial_dbus_messages(void *eloop_ctx, void *timeout_ctx)
  301. {
  302. DBusConnection *con = eloop_ctx;
  303. while (dbus_connection_get_dispatch_status(con) ==
  304. DBUS_DISPATCH_DATA_REMAINS)
  305. dbus_connection_dispatch(con);
  306. }
  307. #ifdef CONFIG_CTRL_IFACE_DBUS_INTRO
  308. /**
  309. * extract_interfaces - Extract interfaces from methods, signals and props
  310. * @obj_dsc: Description of object from which interfaces will be extracted
  311. * @root_node: root node of XML introspection document
  312. * Returns: List of interfaces found in object description
  313. *
  314. * Iterates over all methods, signals and properties registered with
  315. * object and collects all declared DBus interfaces and create interface's
  316. * node in XML root node for each. Returned list elements contains interface
  317. * name and XML node of corresponding interface.
  318. */
  319. static struct interfaces * extract_interfaces(
  320. struct wpa_dbus_object_desc *obj_dsc, xmlNodePtr root_node)
  321. {
  322. struct wpa_dbus_method_desc *method_dsc = obj_dsc->methods;
  323. struct wpa_dbus_signal_desc *signal_dsc = obj_dsc->signals;
  324. struct wpa_dbus_property_desc *property_dsc = obj_dsc->properties;
  325. struct interfaces *head = NULL;
  326. struct interfaces *iface, *last;
  327. int len;
  328. /* extract interfaces from methods */
  329. while (method_dsc) {
  330. iface = head;
  331. last = NULL;
  332. /* go to next method if its interface is already extracted */
  333. while (iface) {
  334. if (!os_strcmp(iface->dbus_interface,
  335. method_dsc->dbus_interface))
  336. break;
  337. last = iface;
  338. iface = iface->next;
  339. }
  340. if (iface) {
  341. method_dsc = method_dsc->next;
  342. continue;
  343. }
  344. iface = os_zalloc(sizeof(struct interfaces));
  345. if (!iface) {
  346. wpa_printf(MSG_ERROR, "Not enough memory to create "
  347. "interface introspection data");
  348. method_dsc = method_dsc->next;
  349. continue;
  350. }
  351. if (last)
  352. last->next = iface;
  353. else
  354. head = iface;
  355. len = os_strlen(method_dsc->dbus_interface) + 1;
  356. iface->dbus_interface = os_malloc(len);
  357. if (!iface->dbus_interface) {
  358. wpa_printf(MSG_ERROR, "Not enough memory to create "
  359. "interface introspection data (interface "
  360. "name)");
  361. method_dsc = method_dsc->next;
  362. continue;
  363. }
  364. os_strncpy(iface->dbus_interface, method_dsc->dbus_interface,
  365. len);
  366. iface->interface_node = xmlNewChild(root_node, NULL,
  367. BAD_CAST "interface",
  368. NULL);
  369. xmlNewProp(iface->interface_node, BAD_CAST "name",
  370. BAD_CAST method_dsc->dbus_interface);
  371. method_dsc = method_dsc->next;
  372. }
  373. /* extract interfaces from signals */
  374. while (signal_dsc) {
  375. iface = head;
  376. last = NULL;
  377. /* go to next signal if its interface is already extracted */
  378. while (iface) {
  379. if (!os_strcmp(iface->dbus_interface,
  380. signal_dsc->dbus_interface))
  381. break;
  382. last = iface;
  383. iface = iface->next;
  384. }
  385. if (iface) {
  386. signal_dsc = signal_dsc->next;
  387. continue;
  388. }
  389. iface = os_zalloc(sizeof(struct interfaces));
  390. if (!iface) {
  391. wpa_printf(MSG_ERROR, "Not enough memory to create "
  392. "interface introspection data");
  393. signal_dsc = signal_dsc->next;
  394. continue;
  395. }
  396. if (last)
  397. last->next = iface;
  398. else
  399. head = iface;
  400. len = os_strlen(signal_dsc->dbus_interface) + 1;
  401. iface->dbus_interface = os_malloc(len);
  402. if (!iface->dbus_interface) {
  403. wpa_printf(MSG_ERROR, "Not enough memory to create "
  404. "interface introspection data (interface "
  405. "name)");
  406. signal_dsc = signal_dsc->next;
  407. continue;
  408. }
  409. os_strncpy(iface->dbus_interface, signal_dsc->dbus_interface,
  410. len);
  411. iface->interface_node = xmlNewChild(root_node, NULL,
  412. BAD_CAST "interface",
  413. NULL);
  414. xmlNewProp(iface->interface_node, BAD_CAST "name",
  415. BAD_CAST signal_dsc->dbus_interface);
  416. signal_dsc = signal_dsc->next;
  417. }
  418. /* extract interfaces from properties */
  419. while (property_dsc) {
  420. iface = head;
  421. last = NULL;
  422. /* go to next property if its interface is already extracted */
  423. while (iface) {
  424. if (!os_strcmp(iface->dbus_interface,
  425. property_dsc->dbus_interface))
  426. break;
  427. last = iface;
  428. iface = iface->next;
  429. }
  430. if (iface) {
  431. property_dsc = property_dsc->next;
  432. continue;
  433. }
  434. iface = os_zalloc(sizeof(struct interfaces));
  435. if (!iface) {
  436. wpa_printf(MSG_ERROR, "Not enough memory to create "
  437. "interface introspection data");
  438. property_dsc = property_dsc->next;
  439. continue;
  440. }
  441. if (last)
  442. last->next = iface;
  443. else
  444. head = iface;
  445. len = os_strlen(property_dsc->dbus_interface) + 1;
  446. iface->dbus_interface = os_malloc(len);
  447. if (!iface->dbus_interface) {
  448. wpa_printf(MSG_ERROR, "Not enough memory to create "
  449. "interface introspection data (interface "
  450. "name)");
  451. property_dsc = property_dsc->next;
  452. continue;
  453. }
  454. os_strncpy(iface->dbus_interface, property_dsc->dbus_interface,
  455. len);
  456. iface->interface_node = xmlNewChild(root_node, NULL,
  457. BAD_CAST "interface",
  458. NULL);
  459. xmlNewProp(iface->interface_node, BAD_CAST "name",
  460. BAD_CAST property_dsc->dbus_interface);
  461. property_dsc = property_dsc->next;
  462. }
  463. return head;
  464. }
  465. /**
  466. * introspect - Responds for Introspect calls on object
  467. * @message: Message with Introspect call
  468. * @obj_dsc: Object description on which Introspect was called
  469. * Returns: Message with introspection result XML string as only argument
  470. *
  471. * Iterates over all methods, signals and properties registered with
  472. * object and generates introspection data for the object as XML string.
  473. */
  474. static DBusMessage * introspect(DBusMessage *message,
  475. struct wpa_dbus_object_desc *obj_dsc)
  476. {
  477. DBusMessage *reply = NULL;
  478. struct interfaces *ifaces, *tmp;
  479. struct wpa_dbus_signal_desc *signal_dsc;
  480. struct wpa_dbus_method_desc *method_dsc;
  481. struct wpa_dbus_property_desc *property_dsc;
  482. xmlChar *intro_str;
  483. char **children;
  484. int i, s;
  485. xmlDocPtr doc = NULL;
  486. xmlNodePtr root_node = NULL, node = NULL, iface_node = NULL;
  487. xmlNodePtr method_node = NULL, signal_node = NULL;
  488. xmlNodePtr property_node = NULL, arg_node = NULL;
  489. /* Create and initialize the return message */
  490. reply = dbus_message_new_method_return(message);
  491. /* root node and dtd */
  492. doc = xmlNewDoc(BAD_CAST "1.0");
  493. root_node = xmlNewNode(NULL, BAD_CAST "node");
  494. xmlDocSetRootElement(doc, root_node);
  495. xmlCreateIntSubset(doc, BAD_CAST "node",
  496. BAD_CAST DBUS_INTROSPECT_1_0_XML_PUBLIC_IDENTIFIER,
  497. BAD_CAST DBUS_INTROSPECT_1_0_XML_SYSTEM_IDENTIFIER);
  498. /* Add Introspectable interface */
  499. iface_node = xmlNewChild(root_node, NULL, BAD_CAST "interface", NULL);
  500. xmlNewProp(iface_node, BAD_CAST "name",
  501. BAD_CAST WPA_DBUS_INTROSPECTION_INTERFACE);
  502. /* Add Introspect method */
  503. method_node = xmlNewChild(iface_node, NULL, BAD_CAST "method", NULL);
  504. xmlNewProp(method_node, BAD_CAST "name",
  505. BAD_CAST WPA_DBUS_INTROSPECTION_METHOD);
  506. arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
  507. xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "data");
  508. xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
  509. xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "out");
  510. /* Add Properties interface */
  511. iface_node = xmlNewChild(root_node, NULL,
  512. BAD_CAST "interface", NULL);
  513. xmlNewProp(iface_node, BAD_CAST "name",
  514. BAD_CAST WPA_DBUS_PROPERTIES_INTERFACE);
  515. /* Add Get method */
  516. method_node = xmlNewChild(iface_node, NULL, BAD_CAST "method", NULL);
  517. xmlNewProp(method_node, BAD_CAST "name",
  518. BAD_CAST WPA_DBUS_PROPERTIES_GET);
  519. arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
  520. xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "interface");
  521. xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
  522. xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
  523. arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
  524. xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "propname");
  525. xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
  526. xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
  527. arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
  528. xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "value");
  529. xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "v");
  530. xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "out");
  531. method_node = xmlNewChild(iface_node, NULL, BAD_CAST "method", NULL);
  532. /* Add GetAll method */
  533. xmlNewProp(method_node, BAD_CAST "name",
  534. BAD_CAST WPA_DBUS_PROPERTIES_GETALL);
  535. arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
  536. xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "interface");
  537. xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
  538. xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
  539. arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
  540. xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "props");
  541. xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "a{sv}");
  542. xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "out");
  543. method_node = xmlNewChild(iface_node, NULL, BAD_CAST "method", NULL);
  544. /* Add Set method */
  545. xmlNewProp(method_node, BAD_CAST "name",
  546. BAD_CAST WPA_DBUS_PROPERTIES_SET);
  547. arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
  548. xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "interface");
  549. xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
  550. xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
  551. arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
  552. xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "propname");
  553. xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
  554. xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
  555. arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
  556. xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "value");
  557. xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "v");
  558. xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
  559. /* get all interfaces registered with object */
  560. ifaces = extract_interfaces(obj_dsc, root_node);
  561. /* create methods' nodes */
  562. method_dsc = obj_dsc->methods;
  563. while (method_dsc) {
  564. struct interfaces *iface = ifaces;
  565. while (iface) {
  566. if (!os_strcmp(iface->dbus_interface,
  567. method_dsc->dbus_interface))
  568. break;
  569. iface = iface->next;
  570. }
  571. if (!iface)
  572. continue;
  573. iface_node = iface->interface_node;
  574. method_node = xmlNewChild(iface_node, NULL, BAD_CAST "method",
  575. NULL);
  576. xmlNewProp(method_node, BAD_CAST "name",
  577. BAD_CAST method_dsc->dbus_method);
  578. /* create args' nodes */
  579. for (i = 0; i < method_dsc->args_num; i++) {
  580. struct wpa_dbus_argument arg = method_dsc->args[i];
  581. arg_node = xmlNewChild(method_node, NULL,
  582. BAD_CAST "arg", NULL);
  583. if (arg.name && strlen(arg.name)) {
  584. xmlNewProp(arg_node, BAD_CAST "name",
  585. BAD_CAST arg.name);
  586. }
  587. xmlNewProp(arg_node, BAD_CAST "type",
  588. BAD_CAST arg.type);
  589. xmlNewProp(arg_node, BAD_CAST "direction",
  590. BAD_CAST (arg.dir == ARG_IN ?
  591. "in" : "out"));
  592. }
  593. method_dsc = method_dsc->next;
  594. }
  595. /* create signals' nodes */
  596. signal_dsc = obj_dsc->signals;
  597. while (signal_dsc) {
  598. struct interfaces *iface = ifaces;
  599. while (iface) {
  600. if (!os_strcmp(iface->dbus_interface,
  601. signal_dsc->dbus_interface))
  602. break;
  603. iface = iface->next;
  604. }
  605. if (!iface)
  606. continue;
  607. iface_node = iface->interface_node;
  608. signal_node = xmlNewChild(iface_node, NULL, BAD_CAST "signal",
  609. NULL);
  610. xmlNewProp(signal_node, BAD_CAST "name",
  611. BAD_CAST signal_dsc->dbus_signal);
  612. /* create args' nodes */
  613. for (i = 0; i < signal_dsc->args_num; i++) {
  614. struct wpa_dbus_argument arg = signal_dsc->args[i];
  615. arg_node = xmlNewChild(signal_node, NULL,
  616. BAD_CAST "arg", NULL);
  617. if (arg.name && strlen(arg.name)) {
  618. xmlNewProp(arg_node, BAD_CAST "name",
  619. BAD_CAST arg.name);
  620. }
  621. xmlNewProp(arg_node, BAD_CAST "type",
  622. BAD_CAST arg.type);
  623. }
  624. signal_dsc = signal_dsc->next;
  625. }
  626. /* create properties' nodes */
  627. property_dsc = obj_dsc->properties;
  628. while (property_dsc) {
  629. struct interfaces *iface = ifaces;
  630. while (iface) {
  631. if (!os_strcmp(iface->dbus_interface,
  632. property_dsc->dbus_interface))
  633. break;
  634. iface = iface->next;
  635. }
  636. if (!iface)
  637. continue;
  638. iface_node = iface->interface_node;
  639. property_node = xmlNewChild(iface_node, NULL,
  640. BAD_CAST "property", NULL);
  641. xmlNewProp(property_node, BAD_CAST "name",
  642. BAD_CAST property_dsc->dbus_property);
  643. xmlNewProp(property_node, BAD_CAST "type",
  644. BAD_CAST property_dsc->type);
  645. xmlNewProp(property_node, BAD_CAST "access", BAD_CAST
  646. (property_dsc->access == R ? "read" :
  647. (property_dsc->access == W ?
  648. "write" : "readwrite")));
  649. property_dsc = property_dsc->next;
  650. }
  651. /* add child nodes to introspection tree; */
  652. dbus_connection_list_registered(obj_dsc->connection,
  653. dbus_message_get_path(message),
  654. &children);
  655. for (i = 0; children[i]; i++) {
  656. node = xmlNewChild(root_node, NULL, BAD_CAST "node", NULL);
  657. xmlNewProp(node, BAD_CAST "name", BAD_CAST children[i]);
  658. }
  659. dbus_free_string_array(children);
  660. xmlDocDumpFormatMemory(doc, &intro_str, &s, 1);
  661. xmlFreeDoc(doc);
  662. while (ifaces) {
  663. tmp = ifaces;
  664. ifaces = ifaces->next;
  665. os_free(tmp->dbus_interface);
  666. os_free(tmp);
  667. }
  668. dbus_message_append_args(reply, DBUS_TYPE_STRING, &intro_str,
  669. DBUS_TYPE_INVALID);
  670. xmlFree(intro_str);
  671. return reply;
  672. }
  673. #else /* CONFIG_CTRL_IFACE_DBUS_INTRO */
  674. /**
  675. * introspect - Responds for Introspect calls on object
  676. * @message: Message with Introspect call
  677. * @obj_dsc: Object description on which Introspect was called
  678. * Returns: Message with introspection result XML string as only argument
  679. *
  680. * Returns error informing that introspection support was not compiled.
  681. */
  682. static DBusMessage * introspect(DBusMessage *message,
  683. struct wpa_dbus_object_desc *obj_dsc)
  684. {
  685. return dbus_message_new_error(message, DBUS_ERROR_UNKNOWN_METHOD,
  686. "wpa_supplicant was compiled without "
  687. "introspection support.");
  688. }
  689. #endif /* CONFIG_CTRL_IFACE_DBUS_INTRO */
  690. /**
  691. * recursive_iter_copy - Reads arguments from one iterator and
  692. * writes to another recursively
  693. * @from: iterator to read from
  694. * @to: iterator to write to
  695. *
  696. * Copies one iterator's elements to another. If any element in
  697. * iterator is of container type, its content is copied recursively
  698. */
  699. static void recursive_iter_copy(DBusMessageIter *from, DBusMessageIter *to)
  700. {
  701. char *subtype = NULL;
  702. int type;
  703. /* iterate over iterator to copy */
  704. while ((type = dbus_message_iter_get_arg_type (from)) !=
  705. DBUS_TYPE_INVALID) {
  706. /* simply copy basic type entries */
  707. if (dbus_type_is_basic(type)) {
  708. if (dbus_type_is_fixed(type)) {
  709. /*
  710. * According to DBus documentation all
  711. * fixed-length types are guaranteed to fit
  712. * 8 bytes
  713. */
  714. dbus_uint64_t v;
  715. dbus_message_iter_get_basic (from, &v);
  716. dbus_message_iter_append_basic (to, type, &v);
  717. } else {
  718. char *v;
  719. dbus_message_iter_get_basic (from, &v);
  720. dbus_message_iter_append_basic (to, type, &v);
  721. }
  722. } else {
  723. /* recursively copy container type entries */
  724. DBusMessageIter write_subiter, read_subiter;
  725. dbus_message_iter_recurse(from, &read_subiter);
  726. if (type == DBUS_TYPE_VARIANT ||
  727. type == DBUS_TYPE_ARRAY) {
  728. subtype = dbus_message_iter_get_signature(
  729. &read_subiter);
  730. }
  731. dbus_message_iter_open_container(to, type, subtype,
  732. &write_subiter);
  733. recursive_iter_copy(&read_subiter, &write_subiter);
  734. dbus_message_iter_close_container(to, &write_subiter);
  735. if (subtype)
  736. dbus_free(subtype);
  737. }
  738. dbus_message_iter_next(from);
  739. }
  740. }
  741. /**
  742. * get_all_properties - Responds for GetAll properties calls on object
  743. * @message: Message with GetAll call
  744. * @interface: interface name which properties will be returned
  745. * @property_dsc: list of object's properties
  746. * Returns: Message with dict of variants as argument with properties values
  747. *
  748. * Iterates over all properties registered with object and execute getters
  749. * of those, which are readable and which interface matches interface
  750. * specified as argument. Returned message contains one dict argument
  751. * with properties names as keys and theirs values as values.
  752. */
  753. static DBusMessage * get_all_properties(
  754. DBusMessage *message, char *interface,
  755. struct wpa_dbus_property_desc *property_dsc)
  756. {
  757. /* Create and initialize the return message */
  758. DBusMessage *reply = dbus_message_new_method_return(message);
  759. DBusMessage *getterReply = NULL;
  760. DBusMessageIter iter, dict_iter, entry_iter, ret_iter;
  761. int counter = 0;
  762. dbus_message_iter_init_append(reply, &iter);
  763. dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
  764. DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
  765. DBUS_TYPE_STRING_AS_STRING
  766. DBUS_TYPE_VARIANT_AS_STRING
  767. DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
  768. &dict_iter);
  769. while (property_dsc) {
  770. if (!os_strncmp(property_dsc->dbus_interface, interface,
  771. WPAS_DBUS_INTERFACE_MAX) &&
  772. property_dsc->access != W && property_dsc->getter) {
  773. getterReply = property_dsc->getter(
  774. message, property_dsc->user_data);
  775. dbus_message_iter_init(getterReply, &ret_iter);
  776. dbus_message_iter_open_container(&dict_iter,
  777. DBUS_TYPE_DICT_ENTRY,
  778. NULL, &entry_iter);
  779. dbus_message_iter_append_basic(
  780. &entry_iter, DBUS_TYPE_STRING,
  781. &(property_dsc->dbus_property));
  782. recursive_iter_copy(&ret_iter, &entry_iter);
  783. dbus_message_iter_close_container(&dict_iter,
  784. &entry_iter);
  785. dbus_message_unref(getterReply);
  786. counter++;
  787. }
  788. property_dsc = property_dsc->next;
  789. }
  790. dbus_message_iter_close_container(&iter, &dict_iter);
  791. if (counter == 0) {
  792. dbus_message_unref(reply);
  793. reply = dbus_message_new_error(message,
  794. DBUS_ERROR_INVALID_ARGS,
  795. "No readable properties in "
  796. "this interface");
  797. }
  798. return reply;
  799. }
  800. static int is_signature_correct(DBusMessage *message,
  801. struct wpa_dbus_method_desc *method_dsc)
  802. {
  803. /* According to DBus documentation max length of signature is 255 */
  804. #define MAX_SIG_LEN 256
  805. char registered_sig[MAX_SIG_LEN], *pos;
  806. const char *sig = dbus_message_get_signature(message);
  807. int i, ret;
  808. pos = registered_sig;
  809. *pos = '\0';
  810. for (i = 0; i < method_dsc->args_num; i++) {
  811. struct wpa_dbus_argument arg = method_dsc->args[i];
  812. if (arg.dir == ARG_IN) {
  813. size_t blen = registered_sig + MAX_SIG_LEN - pos;
  814. ret = os_snprintf(pos, blen, "%s", arg.type);
  815. if (ret < 0 || (size_t) ret >= blen)
  816. return 0;
  817. pos += ret;
  818. }
  819. }
  820. return !os_strncmp(registered_sig, sig, MAX_SIG_LEN);
  821. }
  822. /**
  823. * message_handler - Handles incoming DBus messages
  824. * @connection: DBus connection on which message was received
  825. * @message: Received message
  826. * @user_data: pointer to description of object to which message was sent
  827. * Returns: Returns information whether message was handled or not
  828. *
  829. * Reads message interface and method name, then checks if they matches one
  830. * of the special cases i.e. introspection call or properties get/getall/set
  831. * methods and handles it. Else it iterates over registered methods list
  832. * and tries to match method's name and interface to those read from message
  833. * If appropriate method was found it's handler function is called and
  834. * response is sent. Otherwise the DBUS_ERROR_UNKNOWN_METHOD error message
  835. * will be sent.
  836. */
  837. static DBusHandlerResult message_handler(DBusConnection *connection,
  838. DBusMessage *message, void *user_data)
  839. {
  840. struct wpa_dbus_object_desc *obj_dsc = user_data;
  841. const char *method;
  842. const char *path;
  843. const char *msg_interface;
  844. #define MESSAGE_UNHANDLED (DBusMessage *) 1
  845. DBusMessage *reply = MESSAGE_UNHANDLED;
  846. /* get method, interface and path the message is addressed to */
  847. method = dbus_message_get_member(message);
  848. path = dbus_message_get_path(message);
  849. msg_interface = dbus_message_get_interface(message);
  850. if (!method || !path || !msg_interface)
  851. goto out;
  852. /* if message is introspection method call */
  853. if (!os_strncmp(WPA_DBUS_INTROSPECTION_METHOD, method,
  854. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) &&
  855. !os_strncmp(WPA_DBUS_INTROSPECTION_INTERFACE, msg_interface,
  856. WPAS_DBUS_INTERFACE_MAX))
  857. reply = introspect(message, obj_dsc);
  858. else if (!strncmp(WPA_DBUS_PROPERTIES_INTERFACE, msg_interface,
  859. WPAS_DBUS_INTERFACE_MAX)) {
  860. /* if message is properties method call */
  861. DBusMessageIter iter;
  862. char *interface;
  863. char *property;
  864. dbus_message_iter_init(message, &iter);
  865. if (!os_strncmp(WPA_DBUS_PROPERTIES_GET, method,
  866. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) ||
  867. !os_strncmp(WPA_DBUS_PROPERTIES_SET, method,
  868. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) ||
  869. !os_strncmp(WPA_DBUS_PROPERTIES_GETALL, method,
  870. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX)) {
  871. /* First argument: interface name (DBUS_TYPE_STRING) */
  872. if (dbus_message_iter_get_arg_type(&iter) !=
  873. DBUS_TYPE_STRING) {
  874. reply = dbus_message_new_error(
  875. message, DBUS_ERROR_INVALID_ARGS,
  876. NULL);
  877. goto out;
  878. }
  879. dbus_message_iter_get_basic(&iter, &interface);
  880. /* GetAll */
  881. if (!os_strncmp(WPA_DBUS_PROPERTIES_GETALL, method,
  882. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX)) {
  883. if (os_strcmp(dbus_message_get_signature(
  884. message), "s"))
  885. reply = dbus_message_new_error(
  886. message,
  887. DBUS_ERROR_INVALID_ARGS, NULL);
  888. else
  889. reply = get_all_properties(
  890. message, interface,
  891. obj_dsc->properties);
  892. } else {
  893. /* Get or Set */
  894. struct wpa_dbus_property_desc *property_dsc;
  895. property_dsc = obj_dsc->properties;
  896. /* Second argument: property name
  897. * (DBUS_TYPE_STRING) */
  898. if (!dbus_message_iter_next(&iter) ||
  899. dbus_message_iter_get_arg_type(&iter) !=
  900. DBUS_TYPE_STRING) {
  901. reply = dbus_message_new_error(
  902. message,
  903. DBUS_ERROR_INVALID_ARGS, NULL);
  904. goto out;
  905. }
  906. dbus_message_iter_get_basic(&iter, &property);
  907. while (property_dsc) {
  908. /* compare property names and
  909. * interfaces */
  910. if (!os_strncmp(property_dsc->dbus_property,
  911. property,
  912. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) &&
  913. !os_strncmp(property_dsc->dbus_interface, interface,
  914. WPAS_DBUS_INTERFACE_MAX))
  915. break;
  916. property_dsc = property_dsc->next;
  917. }
  918. if (property_dsc) {
  919. /* Get */
  920. if (!os_strncmp(WPA_DBUS_PROPERTIES_GET, method,
  921. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX)) {
  922. if (os_strcmp(dbus_message_get_signature(message), "ss"))
  923. reply = dbus_message_new_error(message,
  924. DBUS_ERROR_INVALID_ARGS, NULL);
  925. else if (property_dsc->access != W &&
  926. property_dsc->getter)
  927. reply = property_dsc->getter(message,
  928. property_dsc->user_data);
  929. else
  930. reply = dbus_message_new_error(message,
  931. DBUS_ERROR_INVALID_ARGS,
  932. "Property is write-only");
  933. } else {
  934. /* Set */
  935. if (os_strcmp(dbus_message_get_signature(message), "ssv"))
  936. reply = dbus_message_new_error(message,
  937. DBUS_ERROR_INVALID_ARGS, NULL);
  938. else if (property_dsc->access != R &&
  939. property_dsc->setter) {
  940. reply = property_dsc->setter
  941. (message, property_dsc->user_data);
  942. } else {
  943. reply = dbus_message_new_error(message,
  944. DBUS_ERROR_INVALID_ARGS,
  945. "Property is read-only");
  946. }
  947. }
  948. } else {
  949. wpa_printf(MSG_DEBUG, "no property handler for %s.%s\n"
  950. "on %s", interface, property, path);
  951. reply = dbus_message_new_error(message,
  952. DBUS_ERROR_INVALID_ARGS,
  953. "No such property");
  954. }
  955. }
  956. } else {
  957. reply = dbus_message_new_error(
  958. message, DBUS_ERROR_UNKNOWN_METHOD, NULL);
  959. goto out;
  960. }
  961. } else {
  962. struct wpa_dbus_method_desc *method_dsc = obj_dsc->methods;
  963. /* try match call to any registered method */
  964. while (method_dsc) {
  965. /* compare method names and interfaces */
  966. if (!os_strncmp(method_dsc->dbus_method, method,
  967. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) &&
  968. !os_strncmp(method_dsc->dbus_interface,
  969. msg_interface,
  970. WPAS_DBUS_INTERFACE_MAX))
  971. break;
  972. method_dsc = method_dsc->next;
  973. }
  974. if (method_dsc) {
  975. if (is_signature_correct(message, method_dsc)) {
  976. reply = method_dsc->method_handler(
  977. message, method_dsc->handler_argument);
  978. } else {
  979. reply = dbus_message_new_error(
  980. message, DBUS_ERROR_INVALID_ARGS,
  981. NULL);
  982. }
  983. } else {
  984. wpa_printf(MSG_DEBUG, "no method handler for %s.%s "
  985. "on %s", msg_interface, method, path);
  986. reply = dbus_message_new_error(
  987. message, DBUS_ERROR_UNKNOWN_METHOD, NULL);
  988. }
  989. }
  990. out:
  991. /* If the message was handled, send back the reply */
  992. if (reply != MESSAGE_UNHANDLED) {
  993. /* If handler succeed returning NULL, reply empty message */
  994. if (!reply)
  995. reply = dbus_message_new_method_return(message);
  996. if (reply) {
  997. if (!dbus_message_get_no_reply(message))
  998. dbus_connection_send(connection, reply, NULL);
  999. dbus_message_unref(reply);
  1000. }
  1001. return DBUS_HANDLER_RESULT_HANDLED;
  1002. } else
  1003. return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
  1004. }
  1005. /**
  1006. * free_dbus_object_desc - Frees object description data structure
  1007. * @connection: DBus connection
  1008. * @obj_dsc: Object description to free
  1009. *
  1010. * Frees each of properties, methods and signals description lists and
  1011. * the object description structure itself.
  1012. */
  1013. void free_dbus_object_desc(struct wpa_dbus_object_desc *obj_dsc)
  1014. {
  1015. struct wpa_dbus_method_desc *method_dsc, *tmp_met_dsc;
  1016. struct wpa_dbus_signal_desc *signal_dsc, *tmp_sig_dsc;
  1017. struct wpa_dbus_property_desc *property_dsc, *tmp_prop_dsc;
  1018. int i;
  1019. if (!obj_dsc)
  1020. return;
  1021. /* free methods */
  1022. method_dsc = obj_dsc->methods;
  1023. while (method_dsc) {
  1024. tmp_met_dsc = method_dsc;
  1025. method_dsc = method_dsc->next;
  1026. os_free(tmp_met_dsc->dbus_interface);
  1027. os_free(tmp_met_dsc->dbus_method);
  1028. for (i = 0; i < tmp_met_dsc->args_num; i++) {
  1029. os_free(tmp_met_dsc->args[i].name);
  1030. os_free(tmp_met_dsc->args[i].type);
  1031. }
  1032. if (tmp_met_dsc->argument_free_func)
  1033. tmp_met_dsc->argument_free_func(
  1034. tmp_met_dsc->handler_argument);
  1035. os_free(tmp_met_dsc);
  1036. }
  1037. /* free signals */
  1038. signal_dsc = obj_dsc->signals;
  1039. while (signal_dsc) {
  1040. tmp_sig_dsc = signal_dsc;
  1041. signal_dsc = signal_dsc->next;
  1042. os_free(tmp_sig_dsc->dbus_interface);
  1043. os_free(tmp_sig_dsc->dbus_signal);
  1044. for (i = 0; i < tmp_sig_dsc->args_num; i++) {
  1045. os_free(tmp_sig_dsc->args[i].name);
  1046. os_free(tmp_sig_dsc->args[i].type);
  1047. }
  1048. os_free(tmp_sig_dsc);
  1049. }
  1050. /* free properties */
  1051. property_dsc = obj_dsc->properties;
  1052. while (property_dsc) {
  1053. tmp_prop_dsc = property_dsc;
  1054. property_dsc = property_dsc->next;
  1055. os_free(tmp_prop_dsc->dbus_interface);
  1056. os_free(tmp_prop_dsc->dbus_property);
  1057. os_free(tmp_prop_dsc->type);
  1058. if (tmp_prop_dsc->user_data_free_func)
  1059. tmp_prop_dsc->user_data_free_func(
  1060. tmp_prop_dsc->user_data);
  1061. os_free(tmp_prop_dsc);
  1062. }
  1063. os_free(obj_dsc);
  1064. }
  1065. static void free_dbus_object_desc_cb(DBusConnection *connection, void *obj_dsc)
  1066. {
  1067. free_dbus_object_desc(obj_dsc);
  1068. }
  1069. /**
  1070. * wpa_dbus_ctrl_iface_init - Initialize dbus control interface
  1071. * @application_data: Pointer to application specific data structure
  1072. * @dbus_path: DBus path to interface object
  1073. * @dbus_service: DBus service name to register with
  1074. * @messageHandler: a pointer to function which will handle dbus messages
  1075. * coming on interface
  1076. * Returns: Pointer to dbus_new_ctrl_iface date or %NULL on failure
  1077. *
  1078. * Initialize the dbus control interface and start receiving commands from
  1079. * external programs over the bus.
  1080. */
  1081. struct ctrl_iface_dbus_new_priv *
  1082. wpa_dbus_ctrl_iface_init(void *application_data,
  1083. char *dbus_path, char *dbus_service,
  1084. struct wpa_dbus_object_desc *obj_desc)
  1085. {
  1086. struct ctrl_iface_dbus_new_priv *iface;
  1087. DBusError error;
  1088. int ret = -1;
  1089. DBusObjectPathVTable wpa_vtable = {
  1090. &free_dbus_object_desc_cb, &message_handler,
  1091. NULL, NULL, NULL, NULL
  1092. };
  1093. iface = os_zalloc(sizeof(struct ctrl_iface_dbus_new_priv));
  1094. if (iface == NULL)
  1095. return NULL;
  1096. iface->application_data = application_data;
  1097. /* Get a reference to the system bus */
  1098. dbus_error_init(&error);
  1099. iface->con = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
  1100. dbus_error_free(&error);
  1101. if (!iface->con) {
  1102. perror("dbus_bus_get[ctrl_iface_dbus]");
  1103. wpa_printf(MSG_ERROR, "Could not acquire the system bus.");
  1104. goto fail;
  1105. }
  1106. obj_desc->connection = iface->con;
  1107. /* Tell dbus about our mainloop integration functions */
  1108. if (integrate_with_eloop(iface->con, iface))
  1109. goto fail;
  1110. /* Register the message handler for the global dbus interface */
  1111. if (!dbus_connection_register_object_path(iface->con,
  1112. dbus_path, &wpa_vtable,
  1113. obj_desc)) {
  1114. perror("dbus_connection_register_object_path[dbus]");
  1115. wpa_printf(MSG_ERROR, "Could not set up DBus message "
  1116. "handler.");
  1117. goto fail;
  1118. }
  1119. /* Register our service with the message bus */
  1120. dbus_error_init(&error);
  1121. switch (dbus_bus_request_name(iface->con, dbus_service,
  1122. 0, &error)) {
  1123. case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
  1124. ret = 0;
  1125. break;
  1126. case DBUS_REQUEST_NAME_REPLY_EXISTS:
  1127. case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
  1128. case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
  1129. perror("dbus_bus_request_name[dbus]");
  1130. wpa_printf(MSG_ERROR, "Could not request DBus service name: "
  1131. "already registered.");
  1132. break;
  1133. default:
  1134. perror("dbus_bus_request_name[dbus]");
  1135. wpa_printf(MSG_ERROR, "Could not request DBus service name: "
  1136. "%s %s.", error.name, error.message);
  1137. break;
  1138. }
  1139. dbus_error_free(&error);
  1140. if (ret != 0)
  1141. goto fail;
  1142. wpa_printf(MSG_DEBUG, "Providing DBus service '%s'.", dbus_service);
  1143. /*
  1144. * Dispatch initial DBus messages that may have come in since the bus
  1145. * name was claimed above. Happens when clients are quick to notice the
  1146. * service.
  1147. *
  1148. * FIXME: is there a better solution to this problem?
  1149. */
  1150. eloop_register_timeout(0, 50, dispatch_initial_dbus_messages,
  1151. iface->con, NULL);
  1152. return iface;
  1153. fail:
  1154. wpa_dbus_ctrl_iface_deinit(iface);
  1155. return NULL;
  1156. }
  1157. /**
  1158. * wpa_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface
  1159. * @iface: Pointer to dbus private data from wpa_dbus_ctrl_iface_init()
  1160. *
  1161. * Deinitialize the dbus control interface that was initialized with
  1162. * wpa_dbus_ctrl_iface_init().
  1163. */
  1164. void wpa_dbus_ctrl_iface_deinit(struct ctrl_iface_dbus_new_priv *iface)
  1165. {
  1166. if (iface == NULL)
  1167. return;
  1168. if (iface->con) {
  1169. eloop_cancel_timeout(dispatch_initial_dbus_messages,
  1170. iface->con, NULL);
  1171. dbus_connection_set_watch_functions(iface->con, NULL, NULL,
  1172. NULL, NULL, NULL);
  1173. dbus_connection_set_timeout_functions(iface->con, NULL, NULL,
  1174. NULL, NULL, NULL);
  1175. dbus_connection_unref(iface->con);
  1176. }
  1177. os_memset(iface, 0, sizeof(struct ctrl_iface_dbus_new_priv));
  1178. os_free(iface);
  1179. }
  1180. /**
  1181. * wpa_dbus_register_object_per_iface - Register a new object with dbus
  1182. * @ctrl_iface: pointer to dbus private data
  1183. * @path: DBus path to object
  1184. * @ifname: interface name
  1185. * @obj_desc: description of object's methods, signals and properties
  1186. * Returns: 0 on success, -1 on error
  1187. *
  1188. * Registers a new interface with dbus and assigns it a dbus object path.
  1189. */
  1190. int wpa_dbus_register_object_per_iface(
  1191. struct ctrl_iface_dbus_new_priv *ctrl_iface,
  1192. const char *path, const char *ifname,
  1193. struct wpa_dbus_object_desc *obj_desc)
  1194. {
  1195. DBusConnection *con;
  1196. DBusObjectPathVTable vtable = {
  1197. &free_dbus_object_desc_cb, &message_handler,
  1198. NULL, NULL, NULL, NULL
  1199. };
  1200. /* Do nothing if the control interface is not turned on */
  1201. if (ctrl_iface == NULL)
  1202. return 0;
  1203. con = ctrl_iface->con;
  1204. obj_desc->connection = con;
  1205. /* Register the message handler for the interface functions */
  1206. if (!dbus_connection_register_object_path(con, path, &vtable,
  1207. obj_desc)) {
  1208. perror("wpa_dbus_register_iface [dbus]");
  1209. wpa_printf(MSG_ERROR, "Could not set up DBus message "
  1210. "handler for interface %s\n"
  1211. "and object %s.", ifname, path);
  1212. return -1;
  1213. }
  1214. return 0;
  1215. }
  1216. /**
  1217. * wpa_dbus_unregister_object_per_iface - Unregisters DBus object
  1218. * @ctrl_iface: Pointer to dbus private data
  1219. * @path: DBus path to object which will be unregistered
  1220. * Returns: Zero on success and -1 on failure
  1221. *
  1222. * Unregisters DBus object given by its path
  1223. */
  1224. int wpa_dbus_unregister_object_per_iface(
  1225. struct ctrl_iface_dbus_new_priv *ctrl_iface, const char *path)
  1226. {
  1227. DBusConnection *con = ctrl_iface->con;
  1228. if (!dbus_connection_unregister_object_path(con, path))
  1229. return -1;
  1230. return 0;
  1231. }
  1232. /**
  1233. * wpa_dbus_method_register - Registers DBus method for given object
  1234. * @obj_dsc: Object description for which a method will be registered
  1235. * @dbus_interface: DBus interface under which method will be registered
  1236. * @dbus_method: a name the method will be registered with
  1237. * @method_handler: a function which will be called to handle this method call
  1238. * @handler_argument: an additional argument passed to handler function
  1239. * @argument_free_func: function used to free handler argument
  1240. * @args: method arguments list
  1241. * Returns: Zero on success and -1 on failure
  1242. *
  1243. * Registers DBus method under given name and interface for the object.
  1244. * Method calls will be handled with given handling function and optional
  1245. * argument passed to this function. Handler function is required to return
  1246. * a DBusMessage pointer which will be response to method call. Any method
  1247. * call before being handled must have registered appropriate handler by
  1248. * using this function.
  1249. */
  1250. int wpa_dbus_method_register(struct wpa_dbus_object_desc *obj_dsc,
  1251. const char *dbus_interface,
  1252. const char *dbus_method,
  1253. WPADBusMethodHandler method_handler,
  1254. void *handler_argument,
  1255. WPADBusArgumentFreeFunction argument_free_func,
  1256. const struct wpa_dbus_argument args[])
  1257. {
  1258. struct wpa_dbus_method_desc *method_dsc = obj_dsc->methods;
  1259. struct wpa_dbus_method_desc *prev_desc;
  1260. int args_num = 0;
  1261. int interface_len, method_len, i, len, error;
  1262. prev_desc = NULL;
  1263. while (method_dsc) {
  1264. prev_desc = method_dsc;
  1265. method_dsc = method_dsc->next;
  1266. }
  1267. /* count args */
  1268. if (args) {
  1269. while (args[args_num].name && args[args_num].type)
  1270. args_num++;
  1271. }
  1272. method_dsc = os_zalloc(sizeof(struct wpa_dbus_method_desc) +
  1273. args_num * sizeof(struct wpa_dbus_argument));
  1274. if (!method_dsc)
  1275. goto err;
  1276. if (prev_desc == NULL)
  1277. obj_dsc->methods = method_dsc;
  1278. else
  1279. prev_desc->next = method_dsc;
  1280. /* copy interface name */
  1281. interface_len = os_strlen(dbus_interface) + 1;
  1282. method_dsc->dbus_interface = os_malloc(interface_len);
  1283. if (!method_dsc->dbus_interface)
  1284. goto err;
  1285. os_strncpy(method_dsc->dbus_interface, dbus_interface, interface_len);
  1286. /* copy method name */
  1287. method_len = os_strlen(dbus_method) + 1;
  1288. method_dsc->dbus_method = os_malloc(method_len);
  1289. if (!method_dsc->dbus_method)
  1290. goto err;
  1291. os_strncpy(method_dsc->dbus_method, dbus_method, method_len);
  1292. /* copy arguments */
  1293. error = 0;
  1294. method_dsc->args_num = args_num;
  1295. for (i = 0; i < args_num; i++) {
  1296. len = os_strlen(args[i].name) + 1;
  1297. method_dsc->args[i].name = os_malloc(len);
  1298. if (!method_dsc->args[i].name) {
  1299. error = 1;
  1300. continue;
  1301. }
  1302. os_strncpy(method_dsc->args[i].name, args[i].name, len);
  1303. len = os_strlen(args[i].type) + 1;
  1304. method_dsc->args[i].type = os_malloc(len);
  1305. if (!method_dsc->args[i].type) {
  1306. error = 1;
  1307. continue;
  1308. }
  1309. os_strncpy(method_dsc->args[i].type, args[i].type, len);
  1310. method_dsc->args[i].dir = args[i].dir;
  1311. }
  1312. if (error)
  1313. goto err;
  1314. method_dsc->method_handler = method_handler;
  1315. method_dsc->handler_argument = handler_argument;
  1316. method_dsc->argument_free_func = argument_free_func;
  1317. method_dsc->next = NULL;
  1318. return 0;
  1319. err:
  1320. wpa_printf(MSG_WARNING, "Failed to register dbus method %s in "
  1321. "interface %s", dbus_method, dbus_interface);
  1322. if (method_dsc) {
  1323. os_free(method_dsc->dbus_interface);
  1324. os_free(method_dsc->dbus_method);
  1325. for (i = 0; i < method_dsc->args_num; i++) {
  1326. os_free(method_dsc->args[i].name);
  1327. os_free(method_dsc->args[i].type);
  1328. }
  1329. if (prev_desc == NULL)
  1330. obj_dsc->methods = NULL;
  1331. else
  1332. prev_desc->next = NULL;
  1333. os_free(method_dsc);
  1334. }
  1335. return -1;
  1336. }
  1337. /**
  1338. * wpa_dbus_signal_register - Registers DBus signal for given object
  1339. * @obj_dsc: Object description for which a signal will be registered
  1340. * @dbus_interface: DBus interface under which signal will be registered
  1341. * @dbus_signal: a name the signal will be registered with
  1342. * @args: signal arguments list
  1343. * Returns: Zero on success and -1 on failure
  1344. *
  1345. * Registers DBus signal under given name and interface for the object.
  1346. * Signal registration is NOT required in order to send signals, but not
  1347. * registered signals will not be respected in introspection data
  1348. * therefore it is highly recommended to register every signal before
  1349. * using it.
  1350. */
  1351. int wpa_dbus_signal_register(struct wpa_dbus_object_desc *obj_dsc,
  1352. const char *dbus_interface,
  1353. const char *dbus_signal,
  1354. const struct wpa_dbus_argument args[])
  1355. {
  1356. struct wpa_dbus_signal_desc *signal_dsc = obj_dsc->signals;
  1357. struct wpa_dbus_signal_desc *prev_desc;
  1358. int args_num = 0;
  1359. int interface_len, signal_len, i, len, error = 0;
  1360. prev_desc = NULL;
  1361. while (signal_dsc) {
  1362. prev_desc = signal_dsc;
  1363. signal_dsc = signal_dsc->next;
  1364. }
  1365. /* count args */
  1366. if (args) {
  1367. while (args[args_num].name && args[args_num].type)
  1368. args_num++;
  1369. }
  1370. signal_dsc = os_zalloc(sizeof(struct wpa_dbus_signal_desc) +
  1371. args_num * sizeof(struct wpa_dbus_argument));
  1372. if (!signal_dsc)
  1373. goto err;
  1374. if (prev_desc == NULL)
  1375. obj_dsc->signals = signal_dsc;
  1376. else
  1377. prev_desc->next = signal_dsc;
  1378. /* copy interface name */
  1379. interface_len = strlen(dbus_interface) + 1;
  1380. signal_dsc->dbus_interface = os_malloc(interface_len);
  1381. if (!signal_dsc->dbus_interface)
  1382. goto err;
  1383. os_strncpy(signal_dsc->dbus_interface, dbus_interface, interface_len);
  1384. /* copy signal name */
  1385. signal_len = strlen(dbus_signal) + 1;
  1386. signal_dsc->dbus_signal = os_malloc(signal_len);
  1387. if (!signal_dsc->dbus_signal)
  1388. goto err;
  1389. os_strncpy(signal_dsc->dbus_signal, dbus_signal, signal_len);
  1390. /* copy arguments */
  1391. signal_dsc->args_num = args_num;
  1392. for (i = 0; i < args_num; i++) {
  1393. len = os_strlen(args[i].name) + 1;
  1394. signal_dsc->args[i].name = os_malloc(len);
  1395. if (!signal_dsc->args[i].name) {
  1396. error = 1;
  1397. continue;
  1398. }
  1399. os_strncpy(signal_dsc->args[i].name, args[i].name, len);
  1400. len = strlen(args[i].type) + 1;
  1401. signal_dsc->args[i].type = os_malloc(len);
  1402. if (!signal_dsc->args[i].type) {
  1403. error = 1;
  1404. continue;
  1405. }
  1406. os_strncpy(signal_dsc->args[i].type, args[i].type, len);
  1407. }
  1408. if (error)
  1409. goto err;
  1410. signal_dsc->next = NULL;
  1411. return 0;
  1412. err:
  1413. wpa_printf(MSG_WARNING, "Failed to register dbus signal %s in "
  1414. "interface %s", dbus_signal, dbus_interface);
  1415. if (signal_dsc) {
  1416. os_free(signal_dsc->dbus_interface);
  1417. os_free(signal_dsc->dbus_signal);
  1418. for (i = 0; i < signal_dsc->args_num; i++) {
  1419. os_free(signal_dsc->args[i].name);
  1420. os_free(signal_dsc->args[i].type);
  1421. }
  1422. if (prev_desc == NULL)
  1423. obj_dsc->signals = NULL;
  1424. else
  1425. prev_desc->next = NULL;
  1426. os_free(signal_dsc);
  1427. }
  1428. return -1;
  1429. }
  1430. /**
  1431. * wpa_dbus_property_register - Registers DBus property for given object
  1432. * @obj_dsc: Object description for which a property will be registered
  1433. * @dbus_interface: DBus interface under which method will be registered
  1434. * @dbus_property: a name the property will be registered with
  1435. * @type: a property type signature in form of DBus type description
  1436. * @getter: a function called in order to get property value
  1437. * @setter: a function called in order to set property value
  1438. * @user_data: additional argument passed to setter or getter
  1439. * @user_data_free_func: function used to free additional argument
  1440. * @access: property access permissions specifier (R, W or RW)
  1441. * Returns: Zero on success and -1 on failure
  1442. *
  1443. * Registers DBus property under given name and interface for the object.
  1444. * Property are set with giver setter function and get with getter.
  1445. * Additional argument is passed to getter or setter. Getter or setter
  1446. * are required to return DBusMessage which is response to Set/Get method
  1447. * calls. Every property must be registered by this function before being
  1448. * used.
  1449. */
  1450. int wpa_dbus_property_register(struct wpa_dbus_object_desc *obj_dsc,
  1451. const char *dbus_interface,
  1452. const char *dbus_property,
  1453. const char *type,
  1454. WPADBusPropertyAccessor getter,
  1455. WPADBusPropertyAccessor setter,
  1456. void *user_data,
  1457. WPADBusArgumentFreeFunction user_data_free_func,
  1458. enum dbus_prop_access _access)
  1459. {
  1460. struct wpa_dbus_property_desc *property_dsc = obj_dsc->properties;
  1461. struct wpa_dbus_property_desc *prev_desc;
  1462. int interface_len, property_len, type_len;
  1463. prev_desc = NULL;
  1464. while (property_dsc) {
  1465. prev_desc = property_dsc;
  1466. property_dsc = property_dsc->next;
  1467. }
  1468. property_dsc = os_zalloc(sizeof(struct wpa_dbus_property_desc));
  1469. if (!property_dsc)
  1470. goto err;
  1471. if (prev_desc == NULL)
  1472. obj_dsc->properties = property_dsc;
  1473. else
  1474. prev_desc->next = property_dsc;
  1475. /* copy interface name */
  1476. interface_len = os_strlen(dbus_interface) + 1;
  1477. property_dsc->dbus_interface = os_malloc(interface_len);
  1478. if (!property_dsc->dbus_interface)
  1479. goto err;
  1480. os_strncpy(property_dsc->dbus_interface, dbus_interface,
  1481. interface_len);
  1482. /* copy property name */
  1483. property_len = os_strlen(dbus_property) + 1;
  1484. property_dsc->dbus_property = os_malloc(property_len);
  1485. if (!property_dsc->dbus_property)
  1486. goto err;
  1487. os_strncpy(property_dsc->dbus_property, dbus_property, property_len);
  1488. /* copy property type */
  1489. type_len = os_strlen(type) + 1;
  1490. property_dsc->type = os_malloc(type_len);
  1491. if (!property_dsc->type)
  1492. goto err;
  1493. os_strncpy(property_dsc->type, type, type_len);
  1494. property_dsc->getter = getter;
  1495. property_dsc->setter = setter;
  1496. property_dsc->user_data = user_data;
  1497. property_dsc->user_data_free_func = user_data_free_func;
  1498. property_dsc->access = _access;
  1499. property_dsc->next = NULL;
  1500. return 0;
  1501. err:
  1502. wpa_printf(MSG_WARNING, "Failed to register dbus property %s in "
  1503. "interface %s", dbus_property, dbus_interface);
  1504. if (property_dsc) {
  1505. os_free(property_dsc->dbus_interface);
  1506. os_free(property_dsc->dbus_property);
  1507. os_free(property_dsc->type);
  1508. if (prev_desc == NULL)
  1509. obj_dsc->properties = NULL;
  1510. else
  1511. prev_desc->next = NULL;
  1512. os_free(property_dsc);
  1513. }
  1514. return -1;
  1515. }
  1516. /**
  1517. * wpas_dbus_signal_network_added - Send a property changed signal
  1518. * @iface: dbus priv struct
  1519. * @property_getter: propperty getter used to fetch new property value
  1520. * @getter_arg: argument passed to property getter
  1521. * @path: path to object which property has changed
  1522. * @interface_name: signal and property interface
  1523. * @property_name: name of property which has changed
  1524. *
  1525. * Notify listeners about changing value of some property. Signal
  1526. * contains property name and its value fetched using given property
  1527. * getter.
  1528. */
  1529. void wpa_dbus_signal_property_changed(struct ctrl_iface_dbus_new_priv *iface,
  1530. WPADBusPropertyAccessor property_getter,
  1531. void *getter_arg,
  1532. const char *path,
  1533. const char *interface_name,
  1534. const char *property_name)
  1535. {
  1536. DBusConnection *connection;
  1537. DBusMessage *_signal, *getter_reply;
  1538. DBusMessageIter prop_iter, signal_iter, dict_iter, entry_iter;
  1539. if (!iface)
  1540. return;
  1541. connection = iface->con;
  1542. if (!property_getter) {
  1543. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  1544. "[dbus]: property getter not specified");
  1545. return;
  1546. }
  1547. if (!path || !interface_name || !property_name) {
  1548. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  1549. "[dbus]: path interface of property not specified");
  1550. return;
  1551. }
  1552. getter_reply = property_getter(NULL, getter_arg);
  1553. if (!getter_reply ||
  1554. dbus_message_get_type(getter_reply) == DBUS_MESSAGE_TYPE_ERROR) {
  1555. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  1556. "[dbus]: cannot get new value of property %s",
  1557. property_name);
  1558. return;
  1559. }
  1560. _signal = dbus_message_new_signal(path, interface_name,
  1561. "PropertiesChanged");
  1562. if (!_signal) {
  1563. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  1564. "[dbus]: cannot allocate signal");
  1565. dbus_message_unref(getter_reply);
  1566. return;
  1567. }
  1568. dbus_message_iter_init(getter_reply, &prop_iter);
  1569. dbus_message_iter_init_append(_signal, &signal_iter);
  1570. if (!dbus_message_iter_open_container(&signal_iter, DBUS_TYPE_ARRAY,
  1571. "{sv}", &dict_iter)) {
  1572. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  1573. "[dbus]: out of memory. cannot open dictionary");
  1574. goto err;
  1575. }
  1576. if (!dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_DICT_ENTRY,
  1577. NULL, &entry_iter)) {
  1578. wpa_printf(MSG_ERROR, "iwpa_dbus_signal_property_changed"
  1579. "[dbus]: out of memory. cannot open dictionary "
  1580. "element");
  1581. goto err;
  1582. }
  1583. if (!dbus_message_iter_append_basic(&entry_iter, DBUS_TYPE_STRING,
  1584. &property_name)) {
  1585. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  1586. "[dbus]: out of memory. cannot open add property "
  1587. "name");
  1588. goto err;
  1589. }
  1590. recursive_iter_copy(&prop_iter, &entry_iter);
  1591. if (!dbus_message_iter_close_container(&dict_iter, &entry_iter)) {
  1592. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  1593. "[dbus]: out of memory. cannot close dictionary "
  1594. "element");
  1595. goto err;
  1596. }
  1597. if (!dbus_message_iter_close_container(&signal_iter, &dict_iter)) {
  1598. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  1599. "[dbus]: out of memory. cannot close dictionary");
  1600. goto err;
  1601. }
  1602. dbus_connection_send(connection, _signal, NULL);
  1603. err:
  1604. dbus_message_unref(getter_reply);
  1605. dbus_message_unref(_signal);
  1606. }