dbus_new_helpers.c 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945
  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 "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 *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;
  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. /* root node and dtd */
  490. doc = xmlNewDoc(BAD_CAST "1.0");
  491. root_node = xmlNewNode(NULL, BAD_CAST "node");
  492. xmlDocSetRootElement(doc, root_node);
  493. xmlCreateIntSubset(doc, BAD_CAST "node",
  494. BAD_CAST DBUS_INTROSPECT_1_0_XML_PUBLIC_IDENTIFIER,
  495. BAD_CAST DBUS_INTROSPECT_1_0_XML_SYSTEM_IDENTIFIER);
  496. /* Add Introspectable interface */
  497. iface_node = xmlNewChild(root_node, NULL, BAD_CAST "interface", NULL);
  498. xmlNewProp(iface_node, BAD_CAST "name",
  499. BAD_CAST WPA_DBUS_INTROSPECTION_INTERFACE);
  500. /* Add Introspect method */
  501. method_node = xmlNewChild(iface_node, NULL, BAD_CAST "method", NULL);
  502. xmlNewProp(method_node, BAD_CAST "name",
  503. BAD_CAST WPA_DBUS_INTROSPECTION_METHOD);
  504. arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
  505. xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "data");
  506. xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
  507. xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "out");
  508. /* Add Properties interface */
  509. iface_node = xmlNewChild(root_node, NULL,
  510. BAD_CAST "interface", NULL);
  511. xmlNewProp(iface_node, BAD_CAST "name",
  512. BAD_CAST WPA_DBUS_PROPERTIES_INTERFACE);
  513. /* Add Get method */
  514. method_node = xmlNewChild(iface_node, NULL, BAD_CAST "method", NULL);
  515. xmlNewProp(method_node, BAD_CAST "name",
  516. BAD_CAST WPA_DBUS_PROPERTIES_GET);
  517. arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
  518. xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "interface");
  519. xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
  520. xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
  521. arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
  522. xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "propname");
  523. xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
  524. xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
  525. arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
  526. xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "value");
  527. xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "v");
  528. xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "out");
  529. method_node = xmlNewChild(iface_node, NULL, BAD_CAST "method", NULL);
  530. /* Add GetAll method */
  531. xmlNewProp(method_node, BAD_CAST "name",
  532. BAD_CAST WPA_DBUS_PROPERTIES_GETALL);
  533. arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
  534. xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "interface");
  535. xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
  536. xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
  537. arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
  538. xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "props");
  539. xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "a{sv}");
  540. xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "out");
  541. method_node = xmlNewChild(iface_node, NULL, BAD_CAST "method", NULL);
  542. /* Add Set method */
  543. xmlNewProp(method_node, BAD_CAST "name",
  544. BAD_CAST WPA_DBUS_PROPERTIES_SET);
  545. arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
  546. xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "interface");
  547. xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
  548. xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
  549. arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
  550. xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "propname");
  551. xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
  552. xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
  553. arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
  554. xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "value");
  555. xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "v");
  556. xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
  557. /* get all interfaces registered with object */
  558. ifaces = extract_interfaces(obj_dsc, root_node);
  559. /* create methods' nodes */
  560. method_dsc = obj_dsc->methods;
  561. while (method_dsc) {
  562. struct interfaces *iface = ifaces;
  563. while (iface) {
  564. if (!os_strcmp(iface->dbus_interface,
  565. method_dsc->dbus_interface))
  566. break;
  567. iface = iface->next;
  568. }
  569. if (!iface)
  570. continue;
  571. iface_node = iface->interface_node;
  572. method_node = xmlNewChild(iface_node, NULL, BAD_CAST "method",
  573. NULL);
  574. xmlNewProp(method_node, BAD_CAST "name",
  575. BAD_CAST method_dsc->dbus_method);
  576. /* create args' nodes */
  577. for (i = 0; i < method_dsc->args_num; i++) {
  578. struct wpa_dbus_argument arg = method_dsc->args[i];
  579. arg_node = xmlNewChild(method_node, NULL,
  580. BAD_CAST "arg", NULL);
  581. if (arg.name && strlen(arg.name)) {
  582. xmlNewProp(arg_node, BAD_CAST "name",
  583. BAD_CAST arg.name);
  584. }
  585. xmlNewProp(arg_node, BAD_CAST "type",
  586. BAD_CAST arg.type);
  587. xmlNewProp(arg_node, BAD_CAST "direction",
  588. BAD_CAST (arg.dir == ARG_IN ?
  589. "in" : "out"));
  590. }
  591. method_dsc = method_dsc->next;
  592. }
  593. /* create signals' nodes */
  594. signal_dsc = obj_dsc->signals;
  595. while (signal_dsc) {
  596. struct interfaces *iface = ifaces;
  597. while (iface) {
  598. if (!os_strcmp(iface->dbus_interface,
  599. signal_dsc->dbus_interface))
  600. break;
  601. iface = iface->next;
  602. }
  603. if (!iface)
  604. continue;
  605. iface_node = iface->interface_node;
  606. signal_node = xmlNewChild(iface_node, NULL, BAD_CAST "signal",
  607. NULL);
  608. xmlNewProp(signal_node, BAD_CAST "name",
  609. BAD_CAST signal_dsc->dbus_signal);
  610. /* create args' nodes */
  611. for (i = 0; i < signal_dsc->args_num; i++) {
  612. struct wpa_dbus_argument arg = signal_dsc->args[i];
  613. arg_node = xmlNewChild(signal_node, NULL,
  614. BAD_CAST "arg", NULL);
  615. if (arg.name && strlen(arg.name)) {
  616. xmlNewProp(arg_node, BAD_CAST "name",
  617. BAD_CAST arg.name);
  618. }
  619. xmlNewProp(arg_node, BAD_CAST "type",
  620. BAD_CAST arg.type);
  621. }
  622. signal_dsc = signal_dsc->next;
  623. }
  624. /* create properties' nodes */
  625. property_dsc = obj_dsc->properties;
  626. while (property_dsc) {
  627. struct interfaces *iface = ifaces;
  628. while (iface) {
  629. if (!os_strcmp(iface->dbus_interface,
  630. property_dsc->dbus_interface))
  631. break;
  632. iface = iface->next;
  633. }
  634. if (!iface)
  635. continue;
  636. iface_node = iface->interface_node;
  637. property_node = xmlNewChild(iface_node, NULL,
  638. BAD_CAST "property", NULL);
  639. xmlNewProp(property_node, BAD_CAST "name",
  640. BAD_CAST property_dsc->dbus_property);
  641. xmlNewProp(property_node, BAD_CAST "type",
  642. BAD_CAST property_dsc->type);
  643. xmlNewProp(property_node, BAD_CAST "access", BAD_CAST
  644. (property_dsc->access == R ? "read" :
  645. (property_dsc->access == W ?
  646. "write" : "readwrite")));
  647. property_dsc = property_dsc->next;
  648. }
  649. /* add child nodes to introspection tree; */
  650. dbus_connection_list_registered(obj_dsc->connection,
  651. dbus_message_get_path(message),
  652. &children);
  653. for (i = 0; children[i]; i++) {
  654. node = xmlNewChild(root_node, NULL, BAD_CAST "node", NULL);
  655. xmlNewProp(node, BAD_CAST "name", BAD_CAST children[i]);
  656. }
  657. dbus_free_string_array(children);
  658. xmlDocDumpFormatMemory(doc, &intro_str, &s, 1);
  659. xmlFreeDoc(doc);
  660. while (ifaces) {
  661. tmp = ifaces;
  662. ifaces = ifaces->next;
  663. os_free(tmp->dbus_interface);
  664. os_free(tmp);
  665. }
  666. reply = dbus_message_new_method_return(message);
  667. if (reply == NULL) {
  668. xmlFree(intro_str);
  669. return NULL;
  670. }
  671. dbus_message_append_args(reply, DBUS_TYPE_STRING, &intro_str,
  672. DBUS_TYPE_INVALID);
  673. xmlFree(intro_str);
  674. return reply;
  675. }
  676. #else /* CONFIG_CTRL_IFACE_DBUS_INTRO */
  677. /**
  678. * introspect - Responds for Introspect calls on object
  679. * @message: Message with Introspect call
  680. * @obj_dsc: Object description on which Introspect was called
  681. * Returns: Message with introspection result XML string as only argument
  682. *
  683. * Returns error informing that introspection support was not compiled.
  684. */
  685. static DBusMessage * introspect(DBusMessage *message,
  686. struct wpa_dbus_object_desc *obj_dsc)
  687. {
  688. return dbus_message_new_error(message, DBUS_ERROR_UNKNOWN_METHOD,
  689. "wpa_supplicant was compiled without "
  690. "introspection support.");
  691. }
  692. #endif /* CONFIG_CTRL_IFACE_DBUS_INTRO */
  693. /**
  694. * recursive_iter_copy - Reads arguments from one iterator and
  695. * writes to another recursively
  696. * @from: iterator to read from
  697. * @to: iterator to write to
  698. *
  699. * Copies one iterator's elements to another. If any element in
  700. * iterator is of container type, its content is copied recursively
  701. */
  702. static void recursive_iter_copy(DBusMessageIter *from, DBusMessageIter *to)
  703. {
  704. char *subtype = NULL;
  705. int type;
  706. /* iterate over iterator to copy */
  707. while ((type = dbus_message_iter_get_arg_type (from)) !=
  708. DBUS_TYPE_INVALID) {
  709. /* simply copy basic type entries */
  710. if (dbus_type_is_basic(type)) {
  711. if (dbus_type_is_fixed(type)) {
  712. /*
  713. * According to DBus documentation all
  714. * fixed-length types are guaranteed to fit
  715. * 8 bytes
  716. */
  717. dbus_uint64_t v;
  718. dbus_message_iter_get_basic (from, &v);
  719. dbus_message_iter_append_basic (to, type, &v);
  720. } else {
  721. char *v;
  722. dbus_message_iter_get_basic (from, &v);
  723. dbus_message_iter_append_basic (to, type, &v);
  724. }
  725. } else {
  726. /* recursively copy container type entries */
  727. DBusMessageIter write_subiter, read_subiter;
  728. dbus_message_iter_recurse(from, &read_subiter);
  729. if (type == DBUS_TYPE_VARIANT ||
  730. type == DBUS_TYPE_ARRAY) {
  731. subtype = dbus_message_iter_get_signature(
  732. &read_subiter);
  733. }
  734. dbus_message_iter_open_container(to, type, subtype,
  735. &write_subiter);
  736. recursive_iter_copy(&read_subiter, &write_subiter);
  737. dbus_message_iter_close_container(to, &write_subiter);
  738. if (subtype)
  739. dbus_free(subtype);
  740. }
  741. dbus_message_iter_next(from);
  742. }
  743. }
  744. /**
  745. * get_all_properties - Responds for GetAll properties calls on object
  746. * @message: Message with GetAll call
  747. * @interface: interface name which properties will be returned
  748. * @property_dsc: list of object's properties
  749. * Returns: Message with dict of variants as argument with properties values
  750. *
  751. * Iterates over all properties registered with object and execute getters
  752. * of those, which are readable and which interface matches interface
  753. * specified as argument. Returned message contains one dict argument
  754. * with properties names as keys and theirs values as values.
  755. */
  756. static DBusMessage * get_all_properties(
  757. DBusMessage *message, char *interface,
  758. struct wpa_dbus_property_desc *property_dsc)
  759. {
  760. /* Create and initialize the return message */
  761. DBusMessage *reply = dbus_message_new_method_return(message);
  762. DBusMessage *getterReply = NULL;
  763. DBusMessageIter iter, dict_iter, entry_iter, ret_iter;
  764. int counter = 0;
  765. dbus_message_iter_init_append(reply, &iter);
  766. dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
  767. DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
  768. DBUS_TYPE_STRING_AS_STRING
  769. DBUS_TYPE_VARIANT_AS_STRING
  770. DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
  771. &dict_iter);
  772. while (property_dsc) {
  773. if (!os_strncmp(property_dsc->dbus_interface, interface,
  774. WPAS_DBUS_INTERFACE_MAX) &&
  775. property_dsc->access != W && property_dsc->getter) {
  776. getterReply = property_dsc->getter(
  777. message, property_dsc->user_data);
  778. dbus_message_iter_init(getterReply, &ret_iter);
  779. dbus_message_iter_open_container(&dict_iter,
  780. DBUS_TYPE_DICT_ENTRY,
  781. NULL, &entry_iter);
  782. dbus_message_iter_append_basic(
  783. &entry_iter, DBUS_TYPE_STRING,
  784. &(property_dsc->dbus_property));
  785. recursive_iter_copy(&ret_iter, &entry_iter);
  786. dbus_message_iter_close_container(&dict_iter,
  787. &entry_iter);
  788. dbus_message_unref(getterReply);
  789. counter++;
  790. }
  791. property_dsc = property_dsc->next;
  792. }
  793. dbus_message_iter_close_container(&iter, &dict_iter);
  794. if (counter == 0) {
  795. dbus_message_unref(reply);
  796. reply = dbus_message_new_error(message,
  797. DBUS_ERROR_INVALID_ARGS,
  798. "No readable properties in "
  799. "this interface");
  800. }
  801. return reply;
  802. }
  803. static int is_signature_correct(DBusMessage *message,
  804. struct wpa_dbus_method_desc *method_dsc)
  805. {
  806. /* According to DBus documentation max length of signature is 255 */
  807. #define MAX_SIG_LEN 256
  808. char registered_sig[MAX_SIG_LEN], *pos;
  809. const char *sig = dbus_message_get_signature(message);
  810. int i, ret;
  811. pos = registered_sig;
  812. *pos = '\0';
  813. for (i = 0; i < method_dsc->args_num; i++) {
  814. struct wpa_dbus_argument arg = method_dsc->args[i];
  815. if (arg.dir == ARG_IN) {
  816. size_t blen = registered_sig + MAX_SIG_LEN - pos;
  817. ret = os_snprintf(pos, blen, "%s", arg.type);
  818. if (ret < 0 || (size_t) ret >= blen)
  819. return 0;
  820. pos += ret;
  821. }
  822. }
  823. return !os_strncmp(registered_sig, sig, MAX_SIG_LEN);
  824. }
  825. static DBusMessage * properties_get_all(DBusMessage *message, char *interface,
  826. struct wpa_dbus_object_desc *obj_dsc)
  827. {
  828. if (os_strcmp(dbus_message_get_signature(message), "s") != 0)
  829. return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  830. NULL);
  831. return get_all_properties(message, interface,
  832. obj_dsc->properties);
  833. }
  834. static DBusMessage * properties_get(DBusMessage *message,
  835. struct wpa_dbus_property_desc *dsc)
  836. {
  837. if (os_strcmp(dbus_message_get_signature(message), "ss"))
  838. return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  839. NULL);
  840. if (dsc->access != W && dsc->getter)
  841. return dsc->getter(message, dsc->user_data);
  842. return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  843. "Property is write-only");
  844. }
  845. static DBusMessage * properties_set(DBusMessage *message,
  846. struct wpa_dbus_property_desc *dsc)
  847. {
  848. if (os_strcmp(dbus_message_get_signature(message), "ssv"))
  849. return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  850. NULL);
  851. if (dsc->access != R && dsc->setter)
  852. return dsc->setter(message, dsc->user_data);
  853. return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  854. "Property is read-only");
  855. }
  856. static DBusMessage *
  857. properties_get_or_set(DBusMessage *message, DBusMessageIter *iter,
  858. char *interface,
  859. struct wpa_dbus_object_desc *obj_dsc)
  860. {
  861. struct wpa_dbus_property_desc *property_dsc;
  862. char *property;
  863. const char *method;
  864. method = dbus_message_get_member(message);
  865. property_dsc = obj_dsc->properties;
  866. /* Second argument: property name (DBUS_TYPE_STRING) */
  867. if (!dbus_message_iter_next(iter) ||
  868. dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING) {
  869. return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  870. NULL);
  871. }
  872. dbus_message_iter_get_basic(iter, &property);
  873. while (property_dsc) {
  874. /* compare property names and
  875. * interfaces */
  876. if (!os_strncmp(property_dsc->dbus_property, property,
  877. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) &&
  878. !os_strncmp(property_dsc->dbus_interface, interface,
  879. WPAS_DBUS_INTERFACE_MAX))
  880. break;
  881. property_dsc = property_dsc->next;
  882. }
  883. if (property_dsc == NULL) {
  884. wpa_printf(MSG_DEBUG, "no property handler for %s.%s on %s",
  885. interface, property,
  886. dbus_message_get_path(message));
  887. return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  888. "No such property");
  889. }
  890. if (os_strncmp(WPA_DBUS_PROPERTIES_GET, method,
  891. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) == 0)
  892. return properties_get(message, property_dsc);
  893. return properties_set(message, property_dsc);
  894. }
  895. static DBusMessage * properties_handler(DBusMessage *message,
  896. struct wpa_dbus_object_desc *obj_dsc)
  897. {
  898. DBusMessageIter iter;
  899. char *interface;
  900. const char *method;
  901. method = dbus_message_get_member(message);
  902. dbus_message_iter_init(message, &iter);
  903. if (!os_strncmp(WPA_DBUS_PROPERTIES_GET, method,
  904. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) ||
  905. !os_strncmp(WPA_DBUS_PROPERTIES_SET, method,
  906. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) ||
  907. !os_strncmp(WPA_DBUS_PROPERTIES_GETALL, method,
  908. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX)) {
  909. /* First argument: interface name (DBUS_TYPE_STRING) */
  910. if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
  911. {
  912. return dbus_message_new_error(message,
  913. DBUS_ERROR_INVALID_ARGS,
  914. NULL);
  915. }
  916. dbus_message_iter_get_basic(&iter, &interface);
  917. if (!os_strncmp(WPA_DBUS_PROPERTIES_GETALL, method,
  918. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX)) {
  919. /* GetAll */
  920. return properties_get_all(message, interface, obj_dsc);
  921. }
  922. /* Get or Set */
  923. return properties_get_or_set(message, &iter, interface,
  924. obj_dsc);
  925. }
  926. return dbus_message_new_error(message, DBUS_ERROR_UNKNOWN_METHOD,
  927. NULL);
  928. }
  929. static DBusMessage * msg_method_handler(DBusMessage *message,
  930. struct wpa_dbus_object_desc *obj_dsc)
  931. {
  932. struct wpa_dbus_method_desc *method_dsc = obj_dsc->methods;
  933. const char *method;
  934. const char *msg_interface;
  935. method = dbus_message_get_member(message);
  936. msg_interface = dbus_message_get_interface(message);
  937. /* try match call to any registered method */
  938. while (method_dsc) {
  939. /* compare method names and interfaces */
  940. if (!os_strncmp(method_dsc->dbus_method, method,
  941. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) &&
  942. !os_strncmp(method_dsc->dbus_interface, msg_interface,
  943. WPAS_DBUS_INTERFACE_MAX))
  944. break;
  945. method_dsc = method_dsc->next;
  946. }
  947. if (method_dsc == NULL) {
  948. wpa_printf(MSG_DEBUG, "no method handler for %s.%s on %s",
  949. msg_interface, method,
  950. dbus_message_get_path(message));
  951. return dbus_message_new_error(message,
  952. DBUS_ERROR_UNKNOWN_METHOD, NULL);
  953. }
  954. if (!is_signature_correct(message, method_dsc)) {
  955. return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  956. NULL);
  957. }
  958. return method_dsc->method_handler(message,
  959. method_dsc->handler_argument);
  960. }
  961. /**
  962. * message_handler - Handles incoming DBus messages
  963. * @connection: DBus connection on which message was received
  964. * @message: Received message
  965. * @user_data: pointer to description of object to which message was sent
  966. * Returns: Returns information whether message was handled or not
  967. *
  968. * Reads message interface and method name, then checks if they matches one
  969. * of the special cases i.e. introspection call or properties get/getall/set
  970. * methods and handles it. Else it iterates over registered methods list
  971. * and tries to match method's name and interface to those read from message
  972. * If appropriate method was found its handler function is called and
  973. * response is sent. Otherwise, the DBUS_ERROR_UNKNOWN_METHOD error message
  974. * will be sent.
  975. */
  976. static DBusHandlerResult message_handler(DBusConnection *connection,
  977. DBusMessage *message, void *user_data)
  978. {
  979. struct wpa_dbus_object_desc *obj_dsc = user_data;
  980. const char *method;
  981. const char *path;
  982. const char *msg_interface;
  983. DBusMessage *reply;
  984. /* get method, interface and path the message is addressed to */
  985. method = dbus_message_get_member(message);
  986. path = dbus_message_get_path(message);
  987. msg_interface = dbus_message_get_interface(message);
  988. if (!method || !path || !msg_interface)
  989. return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
  990. wpa_printf(MSG_MSGDUMP, "dbus: %s.%s (%s)",
  991. msg_interface, method, path);
  992. /* if message is introspection method call */
  993. if (!os_strncmp(WPA_DBUS_INTROSPECTION_METHOD, method,
  994. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) &&
  995. !os_strncmp(WPA_DBUS_INTROSPECTION_INTERFACE, msg_interface,
  996. WPAS_DBUS_INTERFACE_MAX))
  997. reply = introspect(message, obj_dsc);
  998. else if (!os_strncmp(WPA_DBUS_PROPERTIES_INTERFACE, msg_interface,
  999. WPAS_DBUS_INTERFACE_MAX)) {
  1000. /* if message is properties method call */
  1001. reply = properties_handler(message, obj_dsc);
  1002. } else {
  1003. reply = msg_method_handler(message, obj_dsc);
  1004. }
  1005. /* If handler succeed returning NULL, reply empty message */
  1006. if (!reply)
  1007. reply = dbus_message_new_method_return(message);
  1008. if (reply) {
  1009. if (!dbus_message_get_no_reply(message))
  1010. dbus_connection_send(connection, reply, NULL);
  1011. dbus_message_unref(reply);
  1012. }
  1013. return DBUS_HANDLER_RESULT_HANDLED;
  1014. }
  1015. /**
  1016. * free_dbus_object_desc - Frees object description data structure
  1017. * @connection: DBus connection
  1018. * @obj_dsc: Object description to free
  1019. *
  1020. * Frees each of properties, methods and signals description lists and
  1021. * the object description structure itself.
  1022. */
  1023. void free_dbus_object_desc(struct wpa_dbus_object_desc *obj_dsc)
  1024. {
  1025. struct wpa_dbus_method_desc *method_dsc, *tmp_met_dsc;
  1026. struct wpa_dbus_signal_desc *signal_dsc, *tmp_sig_dsc;
  1027. struct wpa_dbus_property_desc *property_dsc, *tmp_prop_dsc;
  1028. int i;
  1029. if (!obj_dsc)
  1030. return;
  1031. /* free methods */
  1032. method_dsc = obj_dsc->methods;
  1033. while (method_dsc) {
  1034. tmp_met_dsc = method_dsc;
  1035. method_dsc = method_dsc->next;
  1036. os_free(tmp_met_dsc->dbus_interface);
  1037. os_free(tmp_met_dsc->dbus_method);
  1038. for (i = 0; i < tmp_met_dsc->args_num; i++) {
  1039. os_free(tmp_met_dsc->args[i].name);
  1040. os_free(tmp_met_dsc->args[i].type);
  1041. }
  1042. if (tmp_met_dsc->argument_free_func)
  1043. tmp_met_dsc->argument_free_func(
  1044. tmp_met_dsc->handler_argument);
  1045. os_free(tmp_met_dsc);
  1046. }
  1047. /* free signals */
  1048. signal_dsc = obj_dsc->signals;
  1049. while (signal_dsc) {
  1050. tmp_sig_dsc = signal_dsc;
  1051. signal_dsc = signal_dsc->next;
  1052. os_free(tmp_sig_dsc->dbus_interface);
  1053. os_free(tmp_sig_dsc->dbus_signal);
  1054. for (i = 0; i < tmp_sig_dsc->args_num; i++) {
  1055. os_free(tmp_sig_dsc->args[i].name);
  1056. os_free(tmp_sig_dsc->args[i].type);
  1057. }
  1058. os_free(tmp_sig_dsc);
  1059. }
  1060. /* free properties */
  1061. property_dsc = obj_dsc->properties;
  1062. while (property_dsc) {
  1063. tmp_prop_dsc = property_dsc;
  1064. property_dsc = property_dsc->next;
  1065. os_free(tmp_prop_dsc->dbus_interface);
  1066. os_free(tmp_prop_dsc->dbus_property);
  1067. os_free(tmp_prop_dsc->type);
  1068. if (tmp_prop_dsc->user_data_free_func)
  1069. tmp_prop_dsc->user_data_free_func(
  1070. tmp_prop_dsc->user_data);
  1071. os_free(tmp_prop_dsc);
  1072. }
  1073. os_free(obj_dsc);
  1074. }
  1075. static void free_dbus_object_desc_cb(DBusConnection *connection, void *obj_dsc)
  1076. {
  1077. free_dbus_object_desc(obj_dsc);
  1078. }
  1079. /**
  1080. * wpa_dbus_ctrl_iface_init - Initialize dbus control interface
  1081. * @application_data: Pointer to application specific data structure
  1082. * @dbus_path: DBus path to interface object
  1083. * @dbus_service: DBus service name to register with
  1084. * @messageHandler: a pointer to function which will handle dbus messages
  1085. * coming on interface
  1086. * Returns: Pointer to dbus_new_ctrl_iface date or %NULL on failure
  1087. *
  1088. * Initialize the dbus control interface and start receiving commands from
  1089. * external programs over the bus.
  1090. */
  1091. struct ctrl_iface_dbus_new_priv *
  1092. wpa_dbus_ctrl_iface_init(void *application_data,
  1093. char *dbus_path, char *dbus_service,
  1094. struct wpa_dbus_object_desc *obj_desc)
  1095. {
  1096. struct ctrl_iface_dbus_new_priv *iface;
  1097. DBusError error;
  1098. int ret = -1;
  1099. DBusObjectPathVTable wpa_vtable = {
  1100. &free_dbus_object_desc_cb, &message_handler,
  1101. NULL, NULL, NULL, NULL
  1102. };
  1103. iface = os_zalloc(sizeof(struct ctrl_iface_dbus_new_priv));
  1104. if (iface == NULL)
  1105. return NULL;
  1106. iface->application_data = application_data;
  1107. /* Get a reference to the system bus */
  1108. dbus_error_init(&error);
  1109. iface->con = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
  1110. dbus_error_free(&error);
  1111. if (!iface->con) {
  1112. perror("dbus_bus_get[ctrl_iface_dbus]");
  1113. wpa_printf(MSG_ERROR, "Could not acquire the system bus.");
  1114. goto fail;
  1115. }
  1116. obj_desc->connection = iface->con;
  1117. /* Tell dbus about our mainloop integration functions */
  1118. if (integrate_with_eloop(iface->con, iface))
  1119. goto fail;
  1120. /* Register the message handler for the global dbus interface */
  1121. if (!dbus_connection_register_object_path(iface->con,
  1122. dbus_path, &wpa_vtable,
  1123. obj_desc)) {
  1124. perror("dbus_connection_register_object_path[dbus]");
  1125. wpa_printf(MSG_ERROR, "Could not set up DBus message "
  1126. "handler.");
  1127. goto fail;
  1128. }
  1129. /* Register our service with the message bus */
  1130. dbus_error_init(&error);
  1131. switch (dbus_bus_request_name(iface->con, dbus_service,
  1132. 0, &error)) {
  1133. case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
  1134. ret = 0;
  1135. break;
  1136. case DBUS_REQUEST_NAME_REPLY_EXISTS:
  1137. case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
  1138. case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
  1139. perror("dbus_bus_request_name[dbus]");
  1140. wpa_printf(MSG_ERROR, "Could not request DBus service name: "
  1141. "already registered.");
  1142. break;
  1143. default:
  1144. perror("dbus_bus_request_name[dbus]");
  1145. wpa_printf(MSG_ERROR, "Could not request DBus service name: "
  1146. "%s %s.", error.name, error.message);
  1147. break;
  1148. }
  1149. dbus_error_free(&error);
  1150. if (ret != 0)
  1151. goto fail;
  1152. wpa_printf(MSG_DEBUG, "Providing DBus service '%s'.", dbus_service);
  1153. /*
  1154. * Dispatch initial DBus messages that may have come in since the bus
  1155. * name was claimed above. Happens when clients are quick to notice the
  1156. * service.
  1157. *
  1158. * FIXME: is there a better solution to this problem?
  1159. */
  1160. eloop_register_timeout(0, 50, dispatch_initial_dbus_messages,
  1161. iface->con, NULL);
  1162. return iface;
  1163. fail:
  1164. wpa_dbus_ctrl_iface_deinit(iface);
  1165. return NULL;
  1166. }
  1167. /**
  1168. * wpa_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface
  1169. * @iface: Pointer to dbus private data from wpa_dbus_ctrl_iface_init()
  1170. *
  1171. * Deinitialize the dbus control interface that was initialized with
  1172. * wpa_dbus_ctrl_iface_init().
  1173. */
  1174. void wpa_dbus_ctrl_iface_deinit(struct ctrl_iface_dbus_new_priv *iface)
  1175. {
  1176. if (iface == NULL)
  1177. return;
  1178. if (iface->con) {
  1179. eloop_cancel_timeout(dispatch_initial_dbus_messages,
  1180. iface->con, NULL);
  1181. dbus_connection_set_watch_functions(iface->con, NULL, NULL,
  1182. NULL, NULL, NULL);
  1183. dbus_connection_set_timeout_functions(iface->con, NULL, NULL,
  1184. NULL, NULL, NULL);
  1185. dbus_connection_unref(iface->con);
  1186. }
  1187. os_memset(iface, 0, sizeof(struct ctrl_iface_dbus_new_priv));
  1188. os_free(iface);
  1189. }
  1190. /**
  1191. * wpa_dbus_register_object_per_iface - Register a new object with dbus
  1192. * @ctrl_iface: pointer to dbus private data
  1193. * @path: DBus path to object
  1194. * @ifname: interface name
  1195. * @obj_desc: description of object's methods, signals and properties
  1196. * Returns: 0 on success, -1 on error
  1197. *
  1198. * Registers a new interface with dbus and assigns it a dbus object path.
  1199. */
  1200. int wpa_dbus_register_object_per_iface(
  1201. struct ctrl_iface_dbus_new_priv *ctrl_iface,
  1202. const char *path, const char *ifname,
  1203. struct wpa_dbus_object_desc *obj_desc)
  1204. {
  1205. DBusConnection *con;
  1206. DBusObjectPathVTable vtable = {
  1207. &free_dbus_object_desc_cb, &message_handler,
  1208. NULL, NULL, NULL, NULL
  1209. };
  1210. /* Do nothing if the control interface is not turned on */
  1211. if (ctrl_iface == NULL)
  1212. return 0;
  1213. con = ctrl_iface->con;
  1214. obj_desc->connection = con;
  1215. /* Register the message handler for the interface functions */
  1216. if (!dbus_connection_register_object_path(con, path, &vtable,
  1217. obj_desc)) {
  1218. perror("wpa_dbus_register_iface [dbus]");
  1219. wpa_printf(MSG_ERROR, "Could not set up DBus message "
  1220. "handler for interface %s\n"
  1221. "and object %s.", ifname, path);
  1222. return -1;
  1223. }
  1224. return 0;
  1225. }
  1226. /**
  1227. * wpa_dbus_unregister_object_per_iface - Unregisters DBus object
  1228. * @ctrl_iface: Pointer to dbus private data
  1229. * @path: DBus path to object which will be unregistered
  1230. * Returns: Zero on success and -1 on failure
  1231. *
  1232. * Unregisters DBus object given by its path
  1233. */
  1234. int wpa_dbus_unregister_object_per_iface(
  1235. struct ctrl_iface_dbus_new_priv *ctrl_iface, const char *path)
  1236. {
  1237. DBusConnection *con = ctrl_iface->con;
  1238. if (!dbus_connection_unregister_object_path(con, path))
  1239. return -1;
  1240. return 0;
  1241. }
  1242. /**
  1243. * wpa_dbus_method_register - Registers DBus method for given object
  1244. * @obj_dsc: Object description for which a method will be registered
  1245. * @dbus_interface: DBus interface under which method will be registered
  1246. * @dbus_method: a name the method will be registered with
  1247. * @method_handler: a function which will be called to handle this method call
  1248. * @handler_argument: an additional argument passed to handler function
  1249. * @argument_free_func: function used to free handler argument
  1250. * @args: method arguments list
  1251. * Returns: Zero on success and -1 on failure
  1252. *
  1253. * Registers DBus method under given name and interface for the object.
  1254. * Method calls will be handled with given handling function and optional
  1255. * argument passed to this function. Handler function is required to return
  1256. * a DBusMessage pointer which will be response to method call. Any method
  1257. * call before being handled must have registered appropriate handler by
  1258. * using this function.
  1259. */
  1260. int wpa_dbus_method_register(struct wpa_dbus_object_desc *obj_dsc,
  1261. const char *dbus_interface,
  1262. const char *dbus_method,
  1263. WPADBusMethodHandler method_handler,
  1264. void *handler_argument,
  1265. WPADBusArgumentFreeFunction argument_free_func,
  1266. const struct wpa_dbus_argument args[])
  1267. {
  1268. struct wpa_dbus_method_desc *method_dsc = obj_dsc->methods;
  1269. struct wpa_dbus_method_desc *prev_desc;
  1270. int args_num = 0;
  1271. int interface_len, method_len, i, len, error;
  1272. prev_desc = NULL;
  1273. while (method_dsc) {
  1274. prev_desc = method_dsc;
  1275. method_dsc = method_dsc->next;
  1276. }
  1277. /* count args */
  1278. if (args) {
  1279. while (args[args_num].name && args[args_num].type)
  1280. args_num++;
  1281. }
  1282. method_dsc = os_zalloc(sizeof(struct wpa_dbus_method_desc) +
  1283. args_num * sizeof(struct wpa_dbus_argument));
  1284. if (!method_dsc)
  1285. goto err;
  1286. if (prev_desc == NULL)
  1287. obj_dsc->methods = method_dsc;
  1288. else
  1289. prev_desc->next = method_dsc;
  1290. /* copy interface name */
  1291. interface_len = os_strlen(dbus_interface) + 1;
  1292. method_dsc->dbus_interface = os_malloc(interface_len);
  1293. if (!method_dsc->dbus_interface)
  1294. goto err;
  1295. os_strncpy(method_dsc->dbus_interface, dbus_interface, interface_len);
  1296. /* copy method name */
  1297. method_len = os_strlen(dbus_method) + 1;
  1298. method_dsc->dbus_method = os_malloc(method_len);
  1299. if (!method_dsc->dbus_method)
  1300. goto err;
  1301. os_strncpy(method_dsc->dbus_method, dbus_method, method_len);
  1302. /* copy arguments */
  1303. error = 0;
  1304. method_dsc->args_num = args_num;
  1305. for (i = 0; i < args_num; i++) {
  1306. len = os_strlen(args[i].name) + 1;
  1307. method_dsc->args[i].name = os_malloc(len);
  1308. if (!method_dsc->args[i].name) {
  1309. error = 1;
  1310. continue;
  1311. }
  1312. os_strncpy(method_dsc->args[i].name, args[i].name, len);
  1313. len = os_strlen(args[i].type) + 1;
  1314. method_dsc->args[i].type = os_malloc(len);
  1315. if (!method_dsc->args[i].type) {
  1316. error = 1;
  1317. continue;
  1318. }
  1319. os_strncpy(method_dsc->args[i].type, args[i].type, len);
  1320. method_dsc->args[i].dir = args[i].dir;
  1321. }
  1322. if (error)
  1323. goto err;
  1324. method_dsc->method_handler = method_handler;
  1325. method_dsc->handler_argument = handler_argument;
  1326. method_dsc->argument_free_func = argument_free_func;
  1327. method_dsc->next = NULL;
  1328. return 0;
  1329. err:
  1330. wpa_printf(MSG_WARNING, "Failed to register dbus method %s in "
  1331. "interface %s", dbus_method, dbus_interface);
  1332. if (method_dsc) {
  1333. os_free(method_dsc->dbus_interface);
  1334. os_free(method_dsc->dbus_method);
  1335. for (i = 0; i < method_dsc->args_num; i++) {
  1336. os_free(method_dsc->args[i].name);
  1337. os_free(method_dsc->args[i].type);
  1338. }
  1339. if (prev_desc == NULL)
  1340. obj_dsc->methods = NULL;
  1341. else
  1342. prev_desc->next = NULL;
  1343. os_free(method_dsc);
  1344. }
  1345. return -1;
  1346. }
  1347. /**
  1348. * wpa_dbus_signal_register - Registers DBus signal for given object
  1349. * @obj_dsc: Object description for which a signal will be registered
  1350. * @dbus_interface: DBus interface under which signal will be registered
  1351. * @dbus_signal: a name the signal will be registered with
  1352. * @args: signal arguments list
  1353. * Returns: Zero on success and -1 on failure
  1354. *
  1355. * Registers DBus signal under given name and interface for the object.
  1356. * Signal registration is NOT required in order to send signals, but not
  1357. * registered signals will not be respected in introspection data
  1358. * therefore it is highly recommended to register every signal before
  1359. * using it.
  1360. */
  1361. int wpa_dbus_signal_register(struct wpa_dbus_object_desc *obj_dsc,
  1362. const char *dbus_interface,
  1363. const char *dbus_signal,
  1364. const struct wpa_dbus_argument args[])
  1365. {
  1366. struct wpa_dbus_signal_desc *signal_dsc = obj_dsc->signals;
  1367. struct wpa_dbus_signal_desc *prev_desc;
  1368. int args_num = 0;
  1369. int interface_len, signal_len, i, len, error = 0;
  1370. prev_desc = NULL;
  1371. while (signal_dsc) {
  1372. prev_desc = signal_dsc;
  1373. signal_dsc = signal_dsc->next;
  1374. }
  1375. /* count args */
  1376. if (args) {
  1377. while (args[args_num].name && args[args_num].type)
  1378. args_num++;
  1379. }
  1380. signal_dsc = os_zalloc(sizeof(struct wpa_dbus_signal_desc) +
  1381. args_num * sizeof(struct wpa_dbus_argument));
  1382. if (!signal_dsc)
  1383. goto err;
  1384. if (prev_desc == NULL)
  1385. obj_dsc->signals = signal_dsc;
  1386. else
  1387. prev_desc->next = signal_dsc;
  1388. /* copy interface name */
  1389. interface_len = strlen(dbus_interface) + 1;
  1390. signal_dsc->dbus_interface = os_malloc(interface_len);
  1391. if (!signal_dsc->dbus_interface)
  1392. goto err;
  1393. os_strncpy(signal_dsc->dbus_interface, dbus_interface, interface_len);
  1394. /* copy signal name */
  1395. signal_len = strlen(dbus_signal) + 1;
  1396. signal_dsc->dbus_signal = os_malloc(signal_len);
  1397. if (!signal_dsc->dbus_signal)
  1398. goto err;
  1399. os_strncpy(signal_dsc->dbus_signal, dbus_signal, signal_len);
  1400. /* copy arguments */
  1401. signal_dsc->args_num = args_num;
  1402. for (i = 0; i < args_num; i++) {
  1403. len = os_strlen(args[i].name) + 1;
  1404. signal_dsc->args[i].name = os_malloc(len);
  1405. if (!signal_dsc->args[i].name) {
  1406. error = 1;
  1407. continue;
  1408. }
  1409. os_strncpy(signal_dsc->args[i].name, args[i].name, len);
  1410. len = strlen(args[i].type) + 1;
  1411. signal_dsc->args[i].type = os_malloc(len);
  1412. if (!signal_dsc->args[i].type) {
  1413. error = 1;
  1414. continue;
  1415. }
  1416. os_strncpy(signal_dsc->args[i].type, args[i].type, len);
  1417. }
  1418. if (error)
  1419. goto err;
  1420. signal_dsc->next = NULL;
  1421. return 0;
  1422. err:
  1423. wpa_printf(MSG_WARNING, "Failed to register dbus signal %s in "
  1424. "interface %s", dbus_signal, dbus_interface);
  1425. if (signal_dsc) {
  1426. os_free(signal_dsc->dbus_interface);
  1427. os_free(signal_dsc->dbus_signal);
  1428. for (i = 0; i < signal_dsc->args_num; i++) {
  1429. os_free(signal_dsc->args[i].name);
  1430. os_free(signal_dsc->args[i].type);
  1431. }
  1432. if (prev_desc == NULL)
  1433. obj_dsc->signals = NULL;
  1434. else
  1435. prev_desc->next = NULL;
  1436. os_free(signal_dsc);
  1437. }
  1438. return -1;
  1439. }
  1440. /**
  1441. * wpa_dbus_property_register - Registers DBus property for given object
  1442. * @obj_dsc: Object description for which a property will be registered
  1443. * @dbus_interface: DBus interface under which method will be registered
  1444. * @dbus_property: a name the property will be registered with
  1445. * @type: a property type signature in form of DBus type description
  1446. * @getter: a function called in order to get property value
  1447. * @setter: a function called in order to set property value
  1448. * @user_data: additional argument passed to setter or getter
  1449. * @user_data_free_func: function used to free additional argument
  1450. * @access: property access permissions specifier (R, W or RW)
  1451. * Returns: Zero on success and -1 on failure
  1452. *
  1453. * Registers DBus property under given name and interface for the object.
  1454. * Property are set with giver setter function and get with getter.
  1455. * Additional argument is passed to getter or setter. Getter or setter
  1456. * are required to return DBusMessage which is response to Set/Get method
  1457. * calls. Every property must be registered by this function before being
  1458. * used.
  1459. */
  1460. int wpa_dbus_property_register(struct wpa_dbus_object_desc *obj_dsc,
  1461. const char *dbus_interface,
  1462. const char *dbus_property,
  1463. const char *type,
  1464. WPADBusPropertyAccessor getter,
  1465. WPADBusPropertyAccessor setter,
  1466. void *user_data,
  1467. WPADBusArgumentFreeFunction user_data_free_func,
  1468. enum dbus_prop_access _access)
  1469. {
  1470. struct wpa_dbus_property_desc *property_dsc = obj_dsc->properties;
  1471. struct wpa_dbus_property_desc *prev_desc;
  1472. int interface_len, property_len, type_len;
  1473. prev_desc = NULL;
  1474. while (property_dsc) {
  1475. prev_desc = property_dsc;
  1476. property_dsc = property_dsc->next;
  1477. }
  1478. property_dsc = os_zalloc(sizeof(struct wpa_dbus_property_desc));
  1479. if (!property_dsc)
  1480. goto err;
  1481. if (prev_desc == NULL)
  1482. obj_dsc->properties = property_dsc;
  1483. else
  1484. prev_desc->next = property_dsc;
  1485. /* copy interface name */
  1486. interface_len = os_strlen(dbus_interface) + 1;
  1487. property_dsc->dbus_interface = os_malloc(interface_len);
  1488. if (!property_dsc->dbus_interface)
  1489. goto err;
  1490. os_strncpy(property_dsc->dbus_interface, dbus_interface,
  1491. interface_len);
  1492. /* copy property name */
  1493. property_len = os_strlen(dbus_property) + 1;
  1494. property_dsc->dbus_property = os_malloc(property_len);
  1495. if (!property_dsc->dbus_property)
  1496. goto err;
  1497. os_strncpy(property_dsc->dbus_property, dbus_property, property_len);
  1498. /* copy property type */
  1499. type_len = os_strlen(type) + 1;
  1500. property_dsc->type = os_malloc(type_len);
  1501. if (!property_dsc->type)
  1502. goto err;
  1503. os_strncpy(property_dsc->type, type, type_len);
  1504. property_dsc->getter = getter;
  1505. property_dsc->setter = setter;
  1506. property_dsc->user_data = user_data;
  1507. property_dsc->user_data_free_func = user_data_free_func;
  1508. property_dsc->access = _access;
  1509. property_dsc->next = NULL;
  1510. return 0;
  1511. err:
  1512. wpa_printf(MSG_WARNING, "Failed to register dbus property %s in "
  1513. "interface %s", dbus_property, dbus_interface);
  1514. if (property_dsc) {
  1515. os_free(property_dsc->dbus_interface);
  1516. os_free(property_dsc->dbus_property);
  1517. os_free(property_dsc->type);
  1518. if (prev_desc == NULL)
  1519. obj_dsc->properties = NULL;
  1520. else
  1521. prev_desc->next = NULL;
  1522. os_free(property_dsc);
  1523. }
  1524. return -1;
  1525. }
  1526. /**
  1527. * wpas_dbus_signal_network_added - Send a property changed signal
  1528. * @iface: dbus priv struct
  1529. * @property_getter: propperty getter used to fetch new property value
  1530. * @getter_arg: argument passed to property getter
  1531. * @path: path to object which property has changed
  1532. * @interface_name: signal and property interface
  1533. * @property_name: name of property which has changed
  1534. *
  1535. * Notify listeners about changing value of some property. Signal
  1536. * contains property name and its value fetched using given property
  1537. * getter.
  1538. */
  1539. void wpa_dbus_signal_property_changed(struct ctrl_iface_dbus_new_priv *iface,
  1540. WPADBusPropertyAccessor property_getter,
  1541. void *getter_arg,
  1542. const char *path,
  1543. const char *interface_name,
  1544. const char *property_name)
  1545. {
  1546. DBusConnection *connection;
  1547. DBusMessage *_signal, *getter_reply;
  1548. DBusMessageIter prop_iter, signal_iter, dict_iter, entry_iter;
  1549. if (!iface)
  1550. return;
  1551. connection = iface->con;
  1552. if (!property_getter) {
  1553. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  1554. "[dbus]: property getter not specified");
  1555. return;
  1556. }
  1557. if (!path || !interface_name || !property_name) {
  1558. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  1559. "[dbus]: path interface of property not specified");
  1560. return;
  1561. }
  1562. getter_reply = property_getter(NULL, getter_arg);
  1563. if (!getter_reply ||
  1564. dbus_message_get_type(getter_reply) == DBUS_MESSAGE_TYPE_ERROR) {
  1565. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  1566. "[dbus]: cannot get new value of property %s",
  1567. property_name);
  1568. return;
  1569. }
  1570. _signal = dbus_message_new_signal(path, interface_name,
  1571. "PropertiesChanged");
  1572. if (!_signal) {
  1573. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  1574. "[dbus]: cannot allocate signal");
  1575. dbus_message_unref(getter_reply);
  1576. return;
  1577. }
  1578. dbus_message_iter_init(getter_reply, &prop_iter);
  1579. dbus_message_iter_init_append(_signal, &signal_iter);
  1580. if (!dbus_message_iter_open_container(&signal_iter, DBUS_TYPE_ARRAY,
  1581. "{sv}", &dict_iter)) {
  1582. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  1583. "[dbus]: out of memory. cannot open dictionary");
  1584. goto err;
  1585. }
  1586. if (!dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_DICT_ENTRY,
  1587. NULL, &entry_iter)) {
  1588. wpa_printf(MSG_ERROR, "iwpa_dbus_signal_property_changed"
  1589. "[dbus]: out of memory. cannot open dictionary "
  1590. "element");
  1591. goto err;
  1592. }
  1593. if (!dbus_message_iter_append_basic(&entry_iter, DBUS_TYPE_STRING,
  1594. &property_name)) {
  1595. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  1596. "[dbus]: out of memory. cannot open add property "
  1597. "name");
  1598. goto err;
  1599. }
  1600. recursive_iter_copy(&prop_iter, &entry_iter);
  1601. if (!dbus_message_iter_close_container(&dict_iter, &entry_iter)) {
  1602. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  1603. "[dbus]: out of memory. cannot close dictionary "
  1604. "element");
  1605. goto err;
  1606. }
  1607. if (!dbus_message_iter_close_container(&signal_iter, &dict_iter)) {
  1608. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  1609. "[dbus]: out of memory. cannot close dictionary");
  1610. goto err;
  1611. }
  1612. dbus_connection_send(connection, _signal, NULL);
  1613. err:
  1614. dbus_message_unref(getter_reply);
  1615. dbus_message_unref(_signal);
  1616. }