dbus_new_helpers.c 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594
  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_common.h"
  19. #include "dbus_common_i.h"
  20. #include "dbus_new_helpers.h"
  21. /**
  22. * struct wpa_dbus_method_desc - DBus method description
  23. */
  24. struct wpa_dbus_method_desc {
  25. /* pointer to next description in list */
  26. struct wpa_dbus_method_desc *next;
  27. /* method interface */
  28. char *dbus_interface;
  29. /* method name */
  30. char *dbus_method;
  31. /* method handling function */
  32. WPADBusMethodHandler method_handler;
  33. /* handler function argument */
  34. void *handler_argument;
  35. /* function used to free handler argument */
  36. WPADBusArgumentFreeFunction argument_free_func;
  37. /* number of method arguments */
  38. int args_num;
  39. /* array of arguments */
  40. struct wpa_dbus_argument args[];
  41. };
  42. /**
  43. * struct wpa_dbus_signal_desc - DBus signal description
  44. */
  45. struct wpa_dbus_signal_desc {
  46. /* pointer to next description in list */
  47. struct wpa_dbus_signal_desc *next;
  48. /* signal interface */
  49. char *dbus_interface;
  50. /* signal name */
  51. char *dbus_signal;
  52. /* number of signal arguments */
  53. int args_num;
  54. /* array of arguments */
  55. struct wpa_dbus_argument args[0];
  56. };
  57. /**
  58. * struct wpa_dbus_property_desc - DBus property description
  59. */
  60. struct wpa_dbus_property_desc {
  61. /* pointer to next description in list */
  62. struct wpa_dbus_property_desc *next;
  63. /* property interface */
  64. char *dbus_interface;
  65. /* property name */
  66. char *dbus_property;
  67. /* property type signature in DBus type notation */
  68. char *type;
  69. /* property access permissions */
  70. enum dbus_prop_access access;
  71. /* property getter function */
  72. WPADBusPropertyAccessor getter;
  73. /* property setter function */
  74. WPADBusPropertyAccessor setter;
  75. /* argument for getter and setter functions */
  76. void *user_data;
  77. /* function used to free accessors argument */
  78. WPADBusArgumentFreeFunction user_data_free_func;
  79. };
  80. #ifdef CONFIG_CTRL_IFACE_DBUS_INTRO
  81. #include <libxml/tree.h>
  82. struct interfaces {
  83. struct interfaces *next;
  84. char *dbus_interface;
  85. xmlNodePtr interface_node;
  86. };
  87. #endif /* CONFIG_CTRL_IFACE_DBUS_INTRO */
  88. #ifdef CONFIG_CTRL_IFACE_DBUS_INTRO
  89. /**
  90. * extract_interfaces - Extract interfaces from methods, signals and props
  91. * @obj_dsc: Description of object from which interfaces will be extracted
  92. * @root_node: root node of XML introspection document
  93. * Returns: List of interfaces found in object description
  94. *
  95. * Iterates over all methods, signals and properties registered with
  96. * object and collects all declared DBus interfaces and create interface's
  97. * node in XML root node for each. Returned list elements contains interface
  98. * name and XML node of corresponding interface.
  99. */
  100. static struct interfaces * extract_interfaces(
  101. struct wpa_dbus_object_desc *obj_dsc, xmlNodePtr root_node)
  102. {
  103. struct wpa_dbus_method_desc *method_dsc = obj_dsc->methods;
  104. struct wpa_dbus_signal_desc *signal_dsc = obj_dsc->signals;
  105. struct wpa_dbus_property_desc *property_dsc = obj_dsc->properties;
  106. struct interfaces *head = NULL;
  107. struct interfaces *iface, *last;
  108. int len;
  109. /* extract interfaces from methods */
  110. while (method_dsc) {
  111. iface = head;
  112. last = NULL;
  113. /* go to next method if its interface is already extracted */
  114. while (iface) {
  115. if (!os_strcmp(iface->dbus_interface,
  116. method_dsc->dbus_interface))
  117. break;
  118. last = iface;
  119. iface = iface->next;
  120. }
  121. if (iface) {
  122. method_dsc = method_dsc->next;
  123. continue;
  124. }
  125. iface = os_zalloc(sizeof(struct interfaces));
  126. if (!iface) {
  127. wpa_printf(MSG_ERROR, "Not enough memory to create "
  128. "interface introspection data");
  129. method_dsc = method_dsc->next;
  130. continue;
  131. }
  132. if (last)
  133. last->next = iface;
  134. else
  135. head = iface;
  136. len = os_strlen(method_dsc->dbus_interface) + 1;
  137. iface->dbus_interface = os_malloc(len);
  138. if (!iface->dbus_interface) {
  139. wpa_printf(MSG_ERROR, "Not enough memory to create "
  140. "interface introspection data (interface "
  141. "name)");
  142. method_dsc = method_dsc->next;
  143. continue;
  144. }
  145. os_strncpy(iface->dbus_interface, method_dsc->dbus_interface,
  146. len);
  147. iface->interface_node = xmlNewChild(root_node, NULL,
  148. BAD_CAST "interface",
  149. NULL);
  150. xmlNewProp(iface->interface_node, BAD_CAST "name",
  151. BAD_CAST method_dsc->dbus_interface);
  152. method_dsc = method_dsc->next;
  153. }
  154. /* extract interfaces from signals */
  155. while (signal_dsc) {
  156. iface = head;
  157. last = NULL;
  158. /* go to next signal if its interface is already extracted */
  159. while (iface) {
  160. if (!os_strcmp(iface->dbus_interface,
  161. signal_dsc->dbus_interface))
  162. break;
  163. last = iface;
  164. iface = iface->next;
  165. }
  166. if (iface) {
  167. signal_dsc = signal_dsc->next;
  168. continue;
  169. }
  170. iface = os_zalloc(sizeof(struct interfaces));
  171. if (!iface) {
  172. wpa_printf(MSG_ERROR, "Not enough memory to create "
  173. "interface introspection data");
  174. signal_dsc = signal_dsc->next;
  175. continue;
  176. }
  177. if (last)
  178. last->next = iface;
  179. else
  180. head = iface;
  181. len = os_strlen(signal_dsc->dbus_interface) + 1;
  182. iface->dbus_interface = os_malloc(len);
  183. if (!iface->dbus_interface) {
  184. wpa_printf(MSG_ERROR, "Not enough memory to create "
  185. "interface introspection data (interface "
  186. "name)");
  187. signal_dsc = signal_dsc->next;
  188. continue;
  189. }
  190. os_strncpy(iface->dbus_interface, signal_dsc->dbus_interface,
  191. len);
  192. iface->interface_node = xmlNewChild(root_node, NULL,
  193. BAD_CAST "interface",
  194. NULL);
  195. xmlNewProp(iface->interface_node, BAD_CAST "name",
  196. BAD_CAST signal_dsc->dbus_interface);
  197. signal_dsc = signal_dsc->next;
  198. }
  199. /* extract interfaces from properties */
  200. while (property_dsc) {
  201. iface = head;
  202. last = NULL;
  203. /* go to next property if its interface is already extracted */
  204. while (iface) {
  205. if (!os_strcmp(iface->dbus_interface,
  206. property_dsc->dbus_interface))
  207. break;
  208. last = iface;
  209. iface = iface->next;
  210. }
  211. if (iface) {
  212. property_dsc = property_dsc->next;
  213. continue;
  214. }
  215. iface = os_zalloc(sizeof(struct interfaces));
  216. if (!iface) {
  217. wpa_printf(MSG_ERROR, "Not enough memory to create "
  218. "interface introspection data");
  219. property_dsc = property_dsc->next;
  220. continue;
  221. }
  222. if (last)
  223. last->next = iface;
  224. else
  225. head = iface;
  226. len = os_strlen(property_dsc->dbus_interface) + 1;
  227. iface->dbus_interface = os_malloc(len);
  228. if (!iface->dbus_interface) {
  229. wpa_printf(MSG_ERROR, "Not enough memory to create "
  230. "interface introspection data (interface "
  231. "name)");
  232. property_dsc = property_dsc->next;
  233. continue;
  234. }
  235. os_strncpy(iface->dbus_interface, property_dsc->dbus_interface,
  236. len);
  237. iface->interface_node = xmlNewChild(root_node, NULL,
  238. BAD_CAST "interface",
  239. NULL);
  240. xmlNewProp(iface->interface_node, BAD_CAST "name",
  241. BAD_CAST property_dsc->dbus_interface);
  242. property_dsc = property_dsc->next;
  243. }
  244. return head;
  245. }
  246. /**
  247. * introspect - Responds for Introspect calls on object
  248. * @message: Message with Introspect call
  249. * @obj_dsc: Object description on which Introspect was called
  250. * Returns: Message with introspection result XML string as only argument
  251. *
  252. * Iterates over all methods, signals and properties registered with
  253. * object and generates introspection data for the object as XML string.
  254. */
  255. static DBusMessage * introspect(DBusMessage *message,
  256. struct wpa_dbus_object_desc *obj_dsc)
  257. {
  258. DBusMessage *reply;
  259. struct interfaces *ifaces, *tmp;
  260. struct wpa_dbus_signal_desc *signal_dsc;
  261. struct wpa_dbus_method_desc *method_dsc;
  262. struct wpa_dbus_property_desc *property_dsc;
  263. xmlChar *intro_str;
  264. char **children;
  265. int i, s;
  266. xmlDocPtr doc = NULL;
  267. xmlNodePtr root_node = NULL, node = NULL, iface_node = NULL;
  268. xmlNodePtr method_node = NULL, signal_node = NULL;
  269. xmlNodePtr property_node = NULL, arg_node = NULL;
  270. /* root node and dtd */
  271. doc = xmlNewDoc(BAD_CAST "1.0");
  272. root_node = xmlNewNode(NULL, BAD_CAST "node");
  273. xmlDocSetRootElement(doc, root_node);
  274. xmlCreateIntSubset(doc, BAD_CAST "node",
  275. BAD_CAST DBUS_INTROSPECT_1_0_XML_PUBLIC_IDENTIFIER,
  276. BAD_CAST DBUS_INTROSPECT_1_0_XML_SYSTEM_IDENTIFIER);
  277. /* Add Introspectable interface */
  278. iface_node = xmlNewChild(root_node, NULL, BAD_CAST "interface", NULL);
  279. xmlNewProp(iface_node, BAD_CAST "name",
  280. BAD_CAST WPA_DBUS_INTROSPECTION_INTERFACE);
  281. /* Add Introspect method */
  282. method_node = xmlNewChild(iface_node, NULL, BAD_CAST "method", NULL);
  283. xmlNewProp(method_node, BAD_CAST "name",
  284. BAD_CAST WPA_DBUS_INTROSPECTION_METHOD);
  285. arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
  286. xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "data");
  287. xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
  288. xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "out");
  289. /* Add Properties interface */
  290. iface_node = xmlNewChild(root_node, NULL,
  291. BAD_CAST "interface", NULL);
  292. xmlNewProp(iface_node, BAD_CAST "name",
  293. BAD_CAST WPA_DBUS_PROPERTIES_INTERFACE);
  294. /* Add Get method */
  295. method_node = xmlNewChild(iface_node, NULL, BAD_CAST "method", NULL);
  296. xmlNewProp(method_node, BAD_CAST "name",
  297. BAD_CAST WPA_DBUS_PROPERTIES_GET);
  298. arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
  299. xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "interface");
  300. xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
  301. xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
  302. arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
  303. xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "propname");
  304. xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
  305. xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
  306. arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
  307. xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "value");
  308. xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "v");
  309. xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "out");
  310. method_node = xmlNewChild(iface_node, NULL, BAD_CAST "method", NULL);
  311. /* Add GetAll method */
  312. xmlNewProp(method_node, BAD_CAST "name",
  313. BAD_CAST WPA_DBUS_PROPERTIES_GETALL);
  314. arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
  315. xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "interface");
  316. xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
  317. xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
  318. arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
  319. xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "props");
  320. xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "a{sv}");
  321. xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "out");
  322. method_node = xmlNewChild(iface_node, NULL, BAD_CAST "method", NULL);
  323. /* Add Set method */
  324. xmlNewProp(method_node, BAD_CAST "name",
  325. BAD_CAST WPA_DBUS_PROPERTIES_SET);
  326. arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
  327. xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "interface");
  328. xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
  329. xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
  330. arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
  331. xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "propname");
  332. xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
  333. xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
  334. arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
  335. xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "value");
  336. xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "v");
  337. xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
  338. /* get all interfaces registered with object */
  339. ifaces = extract_interfaces(obj_dsc, root_node);
  340. /* create methods' nodes */
  341. method_dsc = obj_dsc->methods;
  342. while (method_dsc) {
  343. struct interfaces *iface = ifaces;
  344. while (iface) {
  345. if (!os_strcmp(iface->dbus_interface,
  346. method_dsc->dbus_interface))
  347. break;
  348. iface = iface->next;
  349. }
  350. if (!iface)
  351. continue;
  352. iface_node = iface->interface_node;
  353. method_node = xmlNewChild(iface_node, NULL, BAD_CAST "method",
  354. NULL);
  355. xmlNewProp(method_node, BAD_CAST "name",
  356. BAD_CAST method_dsc->dbus_method);
  357. /* create args' nodes */
  358. for (i = 0; i < method_dsc->args_num; i++) {
  359. struct wpa_dbus_argument arg = method_dsc->args[i];
  360. arg_node = xmlNewChild(method_node, NULL,
  361. BAD_CAST "arg", NULL);
  362. if (arg.name && strlen(arg.name)) {
  363. xmlNewProp(arg_node, BAD_CAST "name",
  364. BAD_CAST arg.name);
  365. }
  366. xmlNewProp(arg_node, BAD_CAST "type",
  367. BAD_CAST arg.type);
  368. xmlNewProp(arg_node, BAD_CAST "direction",
  369. BAD_CAST (arg.dir == ARG_IN ?
  370. "in" : "out"));
  371. }
  372. method_dsc = method_dsc->next;
  373. }
  374. /* create signals' nodes */
  375. signal_dsc = obj_dsc->signals;
  376. while (signal_dsc) {
  377. struct interfaces *iface = ifaces;
  378. while (iface) {
  379. if (!os_strcmp(iface->dbus_interface,
  380. signal_dsc->dbus_interface))
  381. break;
  382. iface = iface->next;
  383. }
  384. if (!iface)
  385. continue;
  386. iface_node = iface->interface_node;
  387. signal_node = xmlNewChild(iface_node, NULL, BAD_CAST "signal",
  388. NULL);
  389. xmlNewProp(signal_node, BAD_CAST "name",
  390. BAD_CAST signal_dsc->dbus_signal);
  391. /* create args' nodes */
  392. for (i = 0; i < signal_dsc->args_num; i++) {
  393. struct wpa_dbus_argument arg = signal_dsc->args[i];
  394. arg_node = xmlNewChild(signal_node, NULL,
  395. BAD_CAST "arg", NULL);
  396. if (arg.name && strlen(arg.name)) {
  397. xmlNewProp(arg_node, BAD_CAST "name",
  398. BAD_CAST arg.name);
  399. }
  400. xmlNewProp(arg_node, BAD_CAST "type",
  401. BAD_CAST arg.type);
  402. }
  403. signal_dsc = signal_dsc->next;
  404. }
  405. /* create properties' nodes */
  406. property_dsc = obj_dsc->properties;
  407. while (property_dsc) {
  408. struct interfaces *iface = ifaces;
  409. while (iface) {
  410. if (!os_strcmp(iface->dbus_interface,
  411. property_dsc->dbus_interface))
  412. break;
  413. iface = iface->next;
  414. }
  415. if (!iface)
  416. continue;
  417. iface_node = iface->interface_node;
  418. property_node = xmlNewChild(iface_node, NULL,
  419. BAD_CAST "property", NULL);
  420. xmlNewProp(property_node, BAD_CAST "name",
  421. BAD_CAST property_dsc->dbus_property);
  422. xmlNewProp(property_node, BAD_CAST "type",
  423. BAD_CAST property_dsc->type);
  424. xmlNewProp(property_node, BAD_CAST "access", BAD_CAST
  425. (property_dsc->access == R ? "read" :
  426. (property_dsc->access == W ?
  427. "write" : "readwrite")));
  428. property_dsc = property_dsc->next;
  429. }
  430. /* add child nodes to introspection tree; */
  431. dbus_connection_list_registered(obj_dsc->connection,
  432. dbus_message_get_path(message),
  433. &children);
  434. for (i = 0; children[i]; i++) {
  435. node = xmlNewChild(root_node, NULL, BAD_CAST "node", NULL);
  436. xmlNewProp(node, BAD_CAST "name", BAD_CAST children[i]);
  437. }
  438. dbus_free_string_array(children);
  439. xmlDocDumpFormatMemory(doc, &intro_str, &s, 1);
  440. xmlFreeDoc(doc);
  441. while (ifaces) {
  442. tmp = ifaces;
  443. ifaces = ifaces->next;
  444. os_free(tmp->dbus_interface);
  445. os_free(tmp);
  446. }
  447. reply = dbus_message_new_method_return(message);
  448. if (reply == NULL) {
  449. xmlFree(intro_str);
  450. return NULL;
  451. }
  452. dbus_message_append_args(reply, DBUS_TYPE_STRING, &intro_str,
  453. DBUS_TYPE_INVALID);
  454. xmlFree(intro_str);
  455. return reply;
  456. }
  457. #else /* CONFIG_CTRL_IFACE_DBUS_INTRO */
  458. /**
  459. * introspect - Responds for Introspect calls on object
  460. * @message: Message with Introspect call
  461. * @obj_dsc: Object description on which Introspect was called
  462. * Returns: Message with introspection result XML string as only argument
  463. *
  464. * Returns error informing that introspection support was not compiled.
  465. */
  466. static DBusMessage * introspect(DBusMessage *message,
  467. struct wpa_dbus_object_desc *obj_dsc)
  468. {
  469. return dbus_message_new_error(message, DBUS_ERROR_UNKNOWN_METHOD,
  470. "wpa_supplicant was compiled without "
  471. "introspection support.");
  472. }
  473. #endif /* CONFIG_CTRL_IFACE_DBUS_INTRO */
  474. /**
  475. * recursive_iter_copy - Reads arguments from one iterator and
  476. * writes to another recursively
  477. * @from: iterator to read from
  478. * @to: iterator to write to
  479. *
  480. * Copies one iterator's elements to another. If any element in
  481. * iterator is of container type, its content is copied recursively
  482. */
  483. static void recursive_iter_copy(DBusMessageIter *from, DBusMessageIter *to)
  484. {
  485. char *subtype = NULL;
  486. int type;
  487. /* iterate over iterator to copy */
  488. while ((type = dbus_message_iter_get_arg_type (from)) !=
  489. DBUS_TYPE_INVALID) {
  490. /* simply copy basic type entries */
  491. if (dbus_type_is_basic(type)) {
  492. if (dbus_type_is_fixed(type)) {
  493. /*
  494. * According to DBus documentation all
  495. * fixed-length types are guaranteed to fit
  496. * 8 bytes
  497. */
  498. dbus_uint64_t v;
  499. dbus_message_iter_get_basic (from, &v);
  500. dbus_message_iter_append_basic (to, type, &v);
  501. } else {
  502. char *v;
  503. dbus_message_iter_get_basic (from, &v);
  504. dbus_message_iter_append_basic (to, type, &v);
  505. }
  506. } else {
  507. /* recursively copy container type entries */
  508. DBusMessageIter write_subiter, read_subiter;
  509. dbus_message_iter_recurse(from, &read_subiter);
  510. if (type == DBUS_TYPE_VARIANT ||
  511. type == DBUS_TYPE_ARRAY) {
  512. subtype = dbus_message_iter_get_signature(
  513. &read_subiter);
  514. }
  515. dbus_message_iter_open_container(to, type, subtype,
  516. &write_subiter);
  517. recursive_iter_copy(&read_subiter, &write_subiter);
  518. dbus_message_iter_close_container(to, &write_subiter);
  519. if (subtype)
  520. dbus_free(subtype);
  521. }
  522. dbus_message_iter_next(from);
  523. }
  524. }
  525. /**
  526. * get_all_properties - Responds for GetAll properties calls on object
  527. * @message: Message with GetAll call
  528. * @interface: interface name which properties will be returned
  529. * @property_dsc: list of object's properties
  530. * Returns: Message with dict of variants as argument with properties values
  531. *
  532. * Iterates over all properties registered with object and execute getters
  533. * of those, which are readable and which interface matches interface
  534. * specified as argument. Returned message contains one dict argument
  535. * with properties names as keys and theirs values as values.
  536. */
  537. static DBusMessage * get_all_properties(
  538. DBusMessage *message, char *interface,
  539. struct wpa_dbus_property_desc *property_dsc)
  540. {
  541. /* Create and initialize the return message */
  542. DBusMessage *reply = dbus_message_new_method_return(message);
  543. DBusMessage *getterReply = NULL;
  544. DBusMessageIter iter, dict_iter, entry_iter, ret_iter;
  545. int counter = 0;
  546. dbus_message_iter_init_append(reply, &iter);
  547. dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
  548. DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
  549. DBUS_TYPE_STRING_AS_STRING
  550. DBUS_TYPE_VARIANT_AS_STRING
  551. DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
  552. &dict_iter);
  553. while (property_dsc) {
  554. if (!os_strncmp(property_dsc->dbus_interface, interface,
  555. WPAS_DBUS_INTERFACE_MAX) &&
  556. property_dsc->access != W && property_dsc->getter) {
  557. getterReply = property_dsc->getter(
  558. message, property_dsc->user_data);
  559. dbus_message_iter_init(getterReply, &ret_iter);
  560. dbus_message_iter_open_container(&dict_iter,
  561. DBUS_TYPE_DICT_ENTRY,
  562. NULL, &entry_iter);
  563. dbus_message_iter_append_basic(
  564. &entry_iter, DBUS_TYPE_STRING,
  565. &(property_dsc->dbus_property));
  566. recursive_iter_copy(&ret_iter, &entry_iter);
  567. dbus_message_iter_close_container(&dict_iter,
  568. &entry_iter);
  569. dbus_message_unref(getterReply);
  570. counter++;
  571. }
  572. property_dsc = property_dsc->next;
  573. }
  574. dbus_message_iter_close_container(&iter, &dict_iter);
  575. if (counter == 0) {
  576. dbus_message_unref(reply);
  577. reply = dbus_message_new_error(message,
  578. DBUS_ERROR_INVALID_ARGS,
  579. "No readable properties in "
  580. "this interface");
  581. }
  582. return reply;
  583. }
  584. static int is_signature_correct(DBusMessage *message,
  585. struct wpa_dbus_method_desc *method_dsc)
  586. {
  587. /* According to DBus documentation max length of signature is 255 */
  588. #define MAX_SIG_LEN 256
  589. char registered_sig[MAX_SIG_LEN], *pos;
  590. const char *sig = dbus_message_get_signature(message);
  591. int i, ret;
  592. pos = registered_sig;
  593. *pos = '\0';
  594. for (i = 0; i < method_dsc->args_num; i++) {
  595. struct wpa_dbus_argument arg = method_dsc->args[i];
  596. if (arg.dir == ARG_IN) {
  597. size_t blen = registered_sig + MAX_SIG_LEN - pos;
  598. ret = os_snprintf(pos, blen, "%s", arg.type);
  599. if (ret < 0 || (size_t) ret >= blen)
  600. return 0;
  601. pos += ret;
  602. }
  603. }
  604. return !os_strncmp(registered_sig, sig, MAX_SIG_LEN);
  605. }
  606. static DBusMessage * properties_get_all(DBusMessage *message, char *interface,
  607. struct wpa_dbus_object_desc *obj_dsc)
  608. {
  609. if (os_strcmp(dbus_message_get_signature(message), "s") != 0)
  610. return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  611. NULL);
  612. return get_all_properties(message, interface,
  613. obj_dsc->properties);
  614. }
  615. static DBusMessage * properties_get(DBusMessage *message,
  616. struct wpa_dbus_property_desc *dsc)
  617. {
  618. if (os_strcmp(dbus_message_get_signature(message), "ss"))
  619. return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  620. NULL);
  621. if (dsc->access != W && dsc->getter)
  622. return dsc->getter(message, dsc->user_data);
  623. return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  624. "Property is write-only");
  625. }
  626. static DBusMessage * properties_set(DBusMessage *message,
  627. struct wpa_dbus_property_desc *dsc)
  628. {
  629. if (os_strcmp(dbus_message_get_signature(message), "ssv"))
  630. return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  631. NULL);
  632. if (dsc->access != R && dsc->setter)
  633. return dsc->setter(message, dsc->user_data);
  634. return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  635. "Property is read-only");
  636. }
  637. static DBusMessage *
  638. properties_get_or_set(DBusMessage *message, DBusMessageIter *iter,
  639. char *interface,
  640. struct wpa_dbus_object_desc *obj_dsc)
  641. {
  642. struct wpa_dbus_property_desc *property_dsc;
  643. char *property;
  644. const char *method;
  645. method = dbus_message_get_member(message);
  646. property_dsc = obj_dsc->properties;
  647. /* Second argument: property name (DBUS_TYPE_STRING) */
  648. if (!dbus_message_iter_next(iter) ||
  649. dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING) {
  650. return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  651. NULL);
  652. }
  653. dbus_message_iter_get_basic(iter, &property);
  654. while (property_dsc) {
  655. /* compare property names and
  656. * interfaces */
  657. if (!os_strncmp(property_dsc->dbus_property, property,
  658. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) &&
  659. !os_strncmp(property_dsc->dbus_interface, interface,
  660. WPAS_DBUS_INTERFACE_MAX))
  661. break;
  662. property_dsc = property_dsc->next;
  663. }
  664. if (property_dsc == NULL) {
  665. wpa_printf(MSG_DEBUG, "no property handler for %s.%s on %s",
  666. interface, property,
  667. dbus_message_get_path(message));
  668. return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  669. "No such property");
  670. }
  671. if (os_strncmp(WPA_DBUS_PROPERTIES_GET, method,
  672. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) == 0)
  673. return properties_get(message, property_dsc);
  674. return properties_set(message, property_dsc);
  675. }
  676. static DBusMessage * properties_handler(DBusMessage *message,
  677. struct wpa_dbus_object_desc *obj_dsc)
  678. {
  679. DBusMessageIter iter;
  680. char *interface;
  681. const char *method;
  682. method = dbus_message_get_member(message);
  683. dbus_message_iter_init(message, &iter);
  684. if (!os_strncmp(WPA_DBUS_PROPERTIES_GET, method,
  685. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) ||
  686. !os_strncmp(WPA_DBUS_PROPERTIES_SET, method,
  687. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) ||
  688. !os_strncmp(WPA_DBUS_PROPERTIES_GETALL, method,
  689. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX)) {
  690. /* First argument: interface name (DBUS_TYPE_STRING) */
  691. if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
  692. {
  693. return dbus_message_new_error(message,
  694. DBUS_ERROR_INVALID_ARGS,
  695. NULL);
  696. }
  697. dbus_message_iter_get_basic(&iter, &interface);
  698. if (!os_strncmp(WPA_DBUS_PROPERTIES_GETALL, method,
  699. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX)) {
  700. /* GetAll */
  701. return properties_get_all(message, interface, obj_dsc);
  702. }
  703. /* Get or Set */
  704. return properties_get_or_set(message, &iter, interface,
  705. obj_dsc);
  706. }
  707. return dbus_message_new_error(message, DBUS_ERROR_UNKNOWN_METHOD,
  708. NULL);
  709. }
  710. static DBusMessage * msg_method_handler(DBusMessage *message,
  711. struct wpa_dbus_object_desc *obj_dsc)
  712. {
  713. struct wpa_dbus_method_desc *method_dsc = obj_dsc->methods;
  714. const char *method;
  715. const char *msg_interface;
  716. method = dbus_message_get_member(message);
  717. msg_interface = dbus_message_get_interface(message);
  718. /* try match call to any registered method */
  719. while (method_dsc) {
  720. /* compare method names and interfaces */
  721. if (!os_strncmp(method_dsc->dbus_method, method,
  722. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) &&
  723. !os_strncmp(method_dsc->dbus_interface, msg_interface,
  724. WPAS_DBUS_INTERFACE_MAX))
  725. break;
  726. method_dsc = method_dsc->next;
  727. }
  728. if (method_dsc == NULL) {
  729. wpa_printf(MSG_DEBUG, "no method handler for %s.%s on %s",
  730. msg_interface, method,
  731. dbus_message_get_path(message));
  732. return dbus_message_new_error(message,
  733. DBUS_ERROR_UNKNOWN_METHOD, NULL);
  734. }
  735. if (!is_signature_correct(message, method_dsc)) {
  736. return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  737. NULL);
  738. }
  739. return method_dsc->method_handler(message,
  740. method_dsc->handler_argument);
  741. }
  742. /**
  743. * message_handler - Handles incoming DBus messages
  744. * @connection: DBus connection on which message was received
  745. * @message: Received message
  746. * @user_data: pointer to description of object to which message was sent
  747. * Returns: Returns information whether message was handled or not
  748. *
  749. * Reads message interface and method name, then checks if they matches one
  750. * of the special cases i.e. introspection call or properties get/getall/set
  751. * methods and handles it. Else it iterates over registered methods list
  752. * and tries to match method's name and interface to those read from message
  753. * If appropriate method was found its handler function is called and
  754. * response is sent. Otherwise, the DBUS_ERROR_UNKNOWN_METHOD error message
  755. * will be sent.
  756. */
  757. static DBusHandlerResult message_handler(DBusConnection *connection,
  758. DBusMessage *message, void *user_data)
  759. {
  760. struct wpa_dbus_object_desc *obj_dsc = user_data;
  761. const char *method;
  762. const char *path;
  763. const char *msg_interface;
  764. DBusMessage *reply;
  765. /* get method, interface and path the message is addressed to */
  766. method = dbus_message_get_member(message);
  767. path = dbus_message_get_path(message);
  768. msg_interface = dbus_message_get_interface(message);
  769. if (!method || !path || !msg_interface)
  770. return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
  771. wpa_printf(MSG_MSGDUMP, "dbus: %s.%s (%s)",
  772. msg_interface, method, path);
  773. /* if message is introspection method call */
  774. if (!os_strncmp(WPA_DBUS_INTROSPECTION_METHOD, method,
  775. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) &&
  776. !os_strncmp(WPA_DBUS_INTROSPECTION_INTERFACE, msg_interface,
  777. WPAS_DBUS_INTERFACE_MAX))
  778. reply = introspect(message, obj_dsc);
  779. else if (!os_strncmp(WPA_DBUS_PROPERTIES_INTERFACE, msg_interface,
  780. WPAS_DBUS_INTERFACE_MAX)) {
  781. /* if message is properties method call */
  782. reply = properties_handler(message, obj_dsc);
  783. } else {
  784. reply = msg_method_handler(message, obj_dsc);
  785. }
  786. /* If handler succeed returning NULL, reply empty message */
  787. if (!reply)
  788. reply = dbus_message_new_method_return(message);
  789. if (reply) {
  790. if (!dbus_message_get_no_reply(message))
  791. dbus_connection_send(connection, reply, NULL);
  792. dbus_message_unref(reply);
  793. }
  794. return DBUS_HANDLER_RESULT_HANDLED;
  795. }
  796. /**
  797. * free_dbus_object_desc - Frees object description data structure
  798. * @connection: DBus connection
  799. * @obj_dsc: Object description to free
  800. *
  801. * Frees each of properties, methods and signals description lists and
  802. * the object description structure itself.
  803. */
  804. void free_dbus_object_desc(struct wpa_dbus_object_desc *obj_dsc)
  805. {
  806. struct wpa_dbus_method_desc *method_dsc, *tmp_met_dsc;
  807. struct wpa_dbus_signal_desc *signal_dsc, *tmp_sig_dsc;
  808. struct wpa_dbus_property_desc *property_dsc, *tmp_prop_dsc;
  809. int i;
  810. if (!obj_dsc)
  811. return;
  812. /* free methods */
  813. method_dsc = obj_dsc->methods;
  814. while (method_dsc) {
  815. tmp_met_dsc = method_dsc;
  816. method_dsc = method_dsc->next;
  817. os_free(tmp_met_dsc->dbus_interface);
  818. os_free(tmp_met_dsc->dbus_method);
  819. for (i = 0; i < tmp_met_dsc->args_num; i++) {
  820. os_free(tmp_met_dsc->args[i].name);
  821. os_free(tmp_met_dsc->args[i].type);
  822. }
  823. if (tmp_met_dsc->argument_free_func)
  824. tmp_met_dsc->argument_free_func(
  825. tmp_met_dsc->handler_argument);
  826. os_free(tmp_met_dsc);
  827. }
  828. /* free signals */
  829. signal_dsc = obj_dsc->signals;
  830. while (signal_dsc) {
  831. tmp_sig_dsc = signal_dsc;
  832. signal_dsc = signal_dsc->next;
  833. os_free(tmp_sig_dsc->dbus_interface);
  834. os_free(tmp_sig_dsc->dbus_signal);
  835. for (i = 0; i < tmp_sig_dsc->args_num; i++) {
  836. os_free(tmp_sig_dsc->args[i].name);
  837. os_free(tmp_sig_dsc->args[i].type);
  838. }
  839. os_free(tmp_sig_dsc);
  840. }
  841. /* free properties */
  842. property_dsc = obj_dsc->properties;
  843. while (property_dsc) {
  844. tmp_prop_dsc = property_dsc;
  845. property_dsc = property_dsc->next;
  846. os_free(tmp_prop_dsc->dbus_interface);
  847. os_free(tmp_prop_dsc->dbus_property);
  848. os_free(tmp_prop_dsc->type);
  849. if (tmp_prop_dsc->user_data_free_func)
  850. tmp_prop_dsc->user_data_free_func(
  851. tmp_prop_dsc->user_data);
  852. os_free(tmp_prop_dsc);
  853. }
  854. os_free(obj_dsc);
  855. }
  856. static void free_dbus_object_desc_cb(DBusConnection *connection, void *obj_dsc)
  857. {
  858. free_dbus_object_desc(obj_dsc);
  859. }
  860. /**
  861. * wpa_dbus_ctrl_iface_init - Initialize dbus control interface
  862. * @application_data: Pointer to application specific data structure
  863. * @dbus_path: DBus path to interface object
  864. * @dbus_service: DBus service name to register with
  865. * @messageHandler: a pointer to function which will handle dbus messages
  866. * coming on interface
  867. * Returns: 0 on success, -1 on failure
  868. *
  869. * Initialize the dbus control interface and start receiving commands from
  870. * external programs over the bus.
  871. */
  872. int wpa_dbus_ctrl_iface_init(struct wpas_dbus_priv *iface,
  873. char *dbus_path, char *dbus_service,
  874. struct wpa_dbus_object_desc *obj_desc)
  875. {
  876. DBusError error;
  877. int ret = -1;
  878. DBusObjectPathVTable wpa_vtable = {
  879. &free_dbus_object_desc_cb, &message_handler,
  880. NULL, NULL, NULL, NULL
  881. };
  882. obj_desc->connection = iface->con;
  883. /* Register the message handler for the global dbus interface */
  884. if (!dbus_connection_register_object_path(iface->con,
  885. dbus_path, &wpa_vtable,
  886. obj_desc)) {
  887. perror("dbus_connection_register_object_path[dbus]");
  888. wpa_printf(MSG_ERROR, "Could not set up DBus message "
  889. "handler.");
  890. return -1;
  891. }
  892. /* Register our service with the message bus */
  893. dbus_error_init(&error);
  894. switch (dbus_bus_request_name(iface->con, dbus_service,
  895. 0, &error)) {
  896. case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
  897. ret = 0;
  898. break;
  899. case DBUS_REQUEST_NAME_REPLY_EXISTS:
  900. case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
  901. case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
  902. perror("dbus_bus_request_name[dbus]");
  903. wpa_printf(MSG_ERROR, "Could not request DBus service name: "
  904. "already registered.");
  905. break;
  906. default:
  907. perror("dbus_bus_request_name[dbus]");
  908. wpa_printf(MSG_ERROR, "Could not request DBus service name: "
  909. "%s %s.", error.name, error.message);
  910. break;
  911. }
  912. dbus_error_free(&error);
  913. if (ret != 0)
  914. return -1;
  915. wpa_printf(MSG_DEBUG, "Providing DBus service '%s'.", dbus_service);
  916. return 0;
  917. }
  918. /**
  919. * wpa_dbus_register_object_per_iface - Register a new object with dbus
  920. * @ctrl_iface: pointer to dbus private data
  921. * @path: DBus path to object
  922. * @ifname: interface name
  923. * @obj_desc: description of object's methods, signals and properties
  924. * Returns: 0 on success, -1 on error
  925. *
  926. * Registers a new interface with dbus and assigns it a dbus object path.
  927. */
  928. int wpa_dbus_register_object_per_iface(
  929. struct wpas_dbus_priv *ctrl_iface,
  930. const char *path, const char *ifname,
  931. struct wpa_dbus_object_desc *obj_desc)
  932. {
  933. DBusConnection *con;
  934. DBusObjectPathVTable vtable = {
  935. &free_dbus_object_desc_cb, &message_handler,
  936. NULL, NULL, NULL, NULL
  937. };
  938. /* Do nothing if the control interface is not turned on */
  939. if (ctrl_iface == NULL)
  940. return 0;
  941. con = ctrl_iface->con;
  942. obj_desc->connection = con;
  943. /* Register the message handler for the interface functions */
  944. if (!dbus_connection_register_object_path(con, path, &vtable,
  945. obj_desc)) {
  946. perror("wpa_dbus_register_iface [dbus]");
  947. wpa_printf(MSG_ERROR, "Could not set up DBus message "
  948. "handler for interface %s\n"
  949. "and object %s.", ifname, path);
  950. return -1;
  951. }
  952. return 0;
  953. }
  954. /**
  955. * wpa_dbus_unregister_object_per_iface - Unregisters DBus object
  956. * @ctrl_iface: Pointer to dbus private data
  957. * @path: DBus path to object which will be unregistered
  958. * Returns: Zero on success and -1 on failure
  959. *
  960. * Unregisters DBus object given by its path
  961. */
  962. int wpa_dbus_unregister_object_per_iface(
  963. struct wpas_dbus_priv *ctrl_iface, const char *path)
  964. {
  965. DBusConnection *con = ctrl_iface->con;
  966. if (!dbus_connection_unregister_object_path(con, path))
  967. return -1;
  968. return 0;
  969. }
  970. /**
  971. * wpa_dbus_method_register - Registers DBus method for given object
  972. * @obj_dsc: Object description for which a method will be registered
  973. * @dbus_interface: DBus interface under which method will be registered
  974. * @dbus_method: a name the method will be registered with
  975. * @method_handler: a function which will be called to handle this method call
  976. * @handler_argument: an additional argument passed to handler function
  977. * @argument_free_func: function used to free handler argument
  978. * @args: method arguments list
  979. * Returns: Zero on success and -1 on failure
  980. *
  981. * Registers DBus method under given name and interface for the object.
  982. * Method calls will be handled with given handling function and optional
  983. * argument passed to this function. Handler function is required to return
  984. * a DBusMessage pointer which will be response to method call. Any method
  985. * call before being handled must have registered appropriate handler by
  986. * using this function.
  987. */
  988. int wpa_dbus_method_register(struct wpa_dbus_object_desc *obj_dsc,
  989. const char *dbus_interface,
  990. const char *dbus_method,
  991. WPADBusMethodHandler method_handler,
  992. void *handler_argument,
  993. WPADBusArgumentFreeFunction argument_free_func,
  994. const struct wpa_dbus_argument args[])
  995. {
  996. struct wpa_dbus_method_desc *method_dsc = obj_dsc->methods;
  997. struct wpa_dbus_method_desc *prev_desc;
  998. int args_num = 0;
  999. int interface_len, method_len, i, len, error;
  1000. prev_desc = NULL;
  1001. while (method_dsc) {
  1002. prev_desc = method_dsc;
  1003. method_dsc = method_dsc->next;
  1004. }
  1005. /* count args */
  1006. if (args) {
  1007. while (args[args_num].name && args[args_num].type)
  1008. args_num++;
  1009. }
  1010. method_dsc = os_zalloc(sizeof(struct wpa_dbus_method_desc) +
  1011. args_num * sizeof(struct wpa_dbus_argument));
  1012. if (!method_dsc)
  1013. goto err;
  1014. if (prev_desc == NULL)
  1015. obj_dsc->methods = method_dsc;
  1016. else
  1017. prev_desc->next = method_dsc;
  1018. /* copy interface name */
  1019. interface_len = os_strlen(dbus_interface) + 1;
  1020. method_dsc->dbus_interface = os_malloc(interface_len);
  1021. if (!method_dsc->dbus_interface)
  1022. goto err;
  1023. os_strncpy(method_dsc->dbus_interface, dbus_interface, interface_len);
  1024. /* copy method name */
  1025. method_len = os_strlen(dbus_method) + 1;
  1026. method_dsc->dbus_method = os_malloc(method_len);
  1027. if (!method_dsc->dbus_method)
  1028. goto err;
  1029. os_strncpy(method_dsc->dbus_method, dbus_method, method_len);
  1030. /* copy arguments */
  1031. error = 0;
  1032. method_dsc->args_num = args_num;
  1033. for (i = 0; i < args_num; i++) {
  1034. len = os_strlen(args[i].name) + 1;
  1035. method_dsc->args[i].name = os_malloc(len);
  1036. if (!method_dsc->args[i].name) {
  1037. error = 1;
  1038. continue;
  1039. }
  1040. os_strncpy(method_dsc->args[i].name, args[i].name, len);
  1041. len = os_strlen(args[i].type) + 1;
  1042. method_dsc->args[i].type = os_malloc(len);
  1043. if (!method_dsc->args[i].type) {
  1044. error = 1;
  1045. continue;
  1046. }
  1047. os_strncpy(method_dsc->args[i].type, args[i].type, len);
  1048. method_dsc->args[i].dir = args[i].dir;
  1049. }
  1050. if (error)
  1051. goto err;
  1052. method_dsc->method_handler = method_handler;
  1053. method_dsc->handler_argument = handler_argument;
  1054. method_dsc->argument_free_func = argument_free_func;
  1055. method_dsc->next = NULL;
  1056. return 0;
  1057. err:
  1058. wpa_printf(MSG_WARNING, "Failed to register dbus method %s in "
  1059. "interface %s", dbus_method, dbus_interface);
  1060. if (method_dsc) {
  1061. os_free(method_dsc->dbus_interface);
  1062. os_free(method_dsc->dbus_method);
  1063. for (i = 0; i < method_dsc->args_num; i++) {
  1064. os_free(method_dsc->args[i].name);
  1065. os_free(method_dsc->args[i].type);
  1066. }
  1067. if (prev_desc == NULL)
  1068. obj_dsc->methods = NULL;
  1069. else
  1070. prev_desc->next = NULL;
  1071. os_free(method_dsc);
  1072. }
  1073. return -1;
  1074. }
  1075. /**
  1076. * wpa_dbus_signal_register - Registers DBus signal for given object
  1077. * @obj_dsc: Object description for which a signal will be registered
  1078. * @dbus_interface: DBus interface under which signal will be registered
  1079. * @dbus_signal: a name the signal will be registered with
  1080. * @args: signal arguments list
  1081. * Returns: Zero on success and -1 on failure
  1082. *
  1083. * Registers DBus signal under given name and interface for the object.
  1084. * Signal registration is NOT required in order to send signals, but not
  1085. * registered signals will not be respected in introspection data
  1086. * therefore it is highly recommended to register every signal before
  1087. * using it.
  1088. */
  1089. int wpa_dbus_signal_register(struct wpa_dbus_object_desc *obj_dsc,
  1090. const char *dbus_interface,
  1091. const char *dbus_signal,
  1092. const struct wpa_dbus_argument args[])
  1093. {
  1094. struct wpa_dbus_signal_desc *signal_dsc = obj_dsc->signals;
  1095. struct wpa_dbus_signal_desc *prev_desc;
  1096. int args_num = 0;
  1097. int interface_len, signal_len, i, len, error = 0;
  1098. prev_desc = NULL;
  1099. while (signal_dsc) {
  1100. prev_desc = signal_dsc;
  1101. signal_dsc = signal_dsc->next;
  1102. }
  1103. /* count args */
  1104. if (args) {
  1105. while (args[args_num].name && args[args_num].type)
  1106. args_num++;
  1107. }
  1108. signal_dsc = os_zalloc(sizeof(struct wpa_dbus_signal_desc) +
  1109. args_num * sizeof(struct wpa_dbus_argument));
  1110. if (!signal_dsc)
  1111. goto err;
  1112. if (prev_desc == NULL)
  1113. obj_dsc->signals = signal_dsc;
  1114. else
  1115. prev_desc->next = signal_dsc;
  1116. /* copy interface name */
  1117. interface_len = strlen(dbus_interface) + 1;
  1118. signal_dsc->dbus_interface = os_malloc(interface_len);
  1119. if (!signal_dsc->dbus_interface)
  1120. goto err;
  1121. os_strncpy(signal_dsc->dbus_interface, dbus_interface, interface_len);
  1122. /* copy signal name */
  1123. signal_len = strlen(dbus_signal) + 1;
  1124. signal_dsc->dbus_signal = os_malloc(signal_len);
  1125. if (!signal_dsc->dbus_signal)
  1126. goto err;
  1127. os_strncpy(signal_dsc->dbus_signal, dbus_signal, signal_len);
  1128. /* copy arguments */
  1129. signal_dsc->args_num = args_num;
  1130. for (i = 0; i < args_num; i++) {
  1131. len = os_strlen(args[i].name) + 1;
  1132. signal_dsc->args[i].name = os_malloc(len);
  1133. if (!signal_dsc->args[i].name) {
  1134. error = 1;
  1135. continue;
  1136. }
  1137. os_strncpy(signal_dsc->args[i].name, args[i].name, len);
  1138. len = strlen(args[i].type) + 1;
  1139. signal_dsc->args[i].type = os_malloc(len);
  1140. if (!signal_dsc->args[i].type) {
  1141. error = 1;
  1142. continue;
  1143. }
  1144. os_strncpy(signal_dsc->args[i].type, args[i].type, len);
  1145. }
  1146. if (error)
  1147. goto err;
  1148. signal_dsc->next = NULL;
  1149. return 0;
  1150. err:
  1151. wpa_printf(MSG_WARNING, "Failed to register dbus signal %s in "
  1152. "interface %s", dbus_signal, dbus_interface);
  1153. if (signal_dsc) {
  1154. os_free(signal_dsc->dbus_interface);
  1155. os_free(signal_dsc->dbus_signal);
  1156. for (i = 0; i < signal_dsc->args_num; i++) {
  1157. os_free(signal_dsc->args[i].name);
  1158. os_free(signal_dsc->args[i].type);
  1159. }
  1160. if (prev_desc == NULL)
  1161. obj_dsc->signals = NULL;
  1162. else
  1163. prev_desc->next = NULL;
  1164. os_free(signal_dsc);
  1165. }
  1166. return -1;
  1167. }
  1168. /**
  1169. * wpa_dbus_property_register - Registers DBus property for given object
  1170. * @obj_dsc: Object description for which a property will be registered
  1171. * @dbus_interface: DBus interface under which method will be registered
  1172. * @dbus_property: a name the property will be registered with
  1173. * @type: a property type signature in form of DBus type description
  1174. * @getter: a function called in order to get property value
  1175. * @setter: a function called in order to set property value
  1176. * @user_data: additional argument passed to setter or getter
  1177. * @user_data_free_func: function used to free additional argument
  1178. * @access: property access permissions specifier (R, W or RW)
  1179. * Returns: Zero on success and -1 on failure
  1180. *
  1181. * Registers DBus property under given name and interface for the object.
  1182. * Property are set with giver setter function and get with getter.
  1183. * Additional argument is passed to getter or setter. Getter or setter
  1184. * are required to return DBusMessage which is response to Set/Get method
  1185. * calls. Every property must be registered by this function before being
  1186. * used.
  1187. */
  1188. int wpa_dbus_property_register(struct wpa_dbus_object_desc *obj_dsc,
  1189. const char *dbus_interface,
  1190. const char *dbus_property,
  1191. const char *type,
  1192. WPADBusPropertyAccessor getter,
  1193. WPADBusPropertyAccessor setter,
  1194. void *user_data,
  1195. WPADBusArgumentFreeFunction user_data_free_func,
  1196. enum dbus_prop_access _access)
  1197. {
  1198. struct wpa_dbus_property_desc *property_dsc = obj_dsc->properties;
  1199. struct wpa_dbus_property_desc *prev_desc;
  1200. int interface_len, property_len, type_len;
  1201. prev_desc = NULL;
  1202. while (property_dsc) {
  1203. prev_desc = property_dsc;
  1204. property_dsc = property_dsc->next;
  1205. }
  1206. property_dsc = os_zalloc(sizeof(struct wpa_dbus_property_desc));
  1207. if (!property_dsc)
  1208. goto err;
  1209. if (prev_desc == NULL)
  1210. obj_dsc->properties = property_dsc;
  1211. else
  1212. prev_desc->next = property_dsc;
  1213. /* copy interface name */
  1214. interface_len = os_strlen(dbus_interface) + 1;
  1215. property_dsc->dbus_interface = os_malloc(interface_len);
  1216. if (!property_dsc->dbus_interface)
  1217. goto err;
  1218. os_strncpy(property_dsc->dbus_interface, dbus_interface,
  1219. interface_len);
  1220. /* copy property name */
  1221. property_len = os_strlen(dbus_property) + 1;
  1222. property_dsc->dbus_property = os_malloc(property_len);
  1223. if (!property_dsc->dbus_property)
  1224. goto err;
  1225. os_strncpy(property_dsc->dbus_property, dbus_property, property_len);
  1226. /* copy property type */
  1227. type_len = os_strlen(type) + 1;
  1228. property_dsc->type = os_malloc(type_len);
  1229. if (!property_dsc->type)
  1230. goto err;
  1231. os_strncpy(property_dsc->type, type, type_len);
  1232. property_dsc->getter = getter;
  1233. property_dsc->setter = setter;
  1234. property_dsc->user_data = user_data;
  1235. property_dsc->user_data_free_func = user_data_free_func;
  1236. property_dsc->access = _access;
  1237. property_dsc->next = NULL;
  1238. return 0;
  1239. err:
  1240. wpa_printf(MSG_WARNING, "Failed to register dbus property %s in "
  1241. "interface %s", dbus_property, dbus_interface);
  1242. if (property_dsc) {
  1243. os_free(property_dsc->dbus_interface);
  1244. os_free(property_dsc->dbus_property);
  1245. os_free(property_dsc->type);
  1246. if (prev_desc == NULL)
  1247. obj_dsc->properties = NULL;
  1248. else
  1249. prev_desc->next = NULL;
  1250. os_free(property_dsc);
  1251. }
  1252. return -1;
  1253. }
  1254. /**
  1255. * wpas_dbus_signal_network_added - Send a property changed signal
  1256. * @iface: dbus priv struct
  1257. * @property_getter: propperty getter used to fetch new property value
  1258. * @getter_arg: argument passed to property getter
  1259. * @path: path to object which property has changed
  1260. * @interface_name: signal and property interface
  1261. * @property_name: name of property which has changed
  1262. *
  1263. * Notify listeners about changing value of some property. Signal
  1264. * contains property name and its value fetched using given property
  1265. * getter.
  1266. */
  1267. void wpa_dbus_signal_property_changed(struct wpas_dbus_priv *iface,
  1268. WPADBusPropertyAccessor property_getter,
  1269. void *getter_arg,
  1270. const char *path,
  1271. const char *interface_name,
  1272. const char *property_name)
  1273. {
  1274. DBusConnection *connection;
  1275. DBusMessage *_signal, *getter_reply;
  1276. DBusMessageIter prop_iter, signal_iter, dict_iter, entry_iter;
  1277. if (!iface)
  1278. return;
  1279. connection = iface->con;
  1280. if (!property_getter) {
  1281. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  1282. "[dbus]: property getter not specified");
  1283. return;
  1284. }
  1285. if (!path || !interface_name || !property_name) {
  1286. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  1287. "[dbus]: path interface of property not specified");
  1288. return;
  1289. }
  1290. getter_reply = property_getter(NULL, getter_arg);
  1291. if (!getter_reply ||
  1292. dbus_message_get_type(getter_reply) == DBUS_MESSAGE_TYPE_ERROR) {
  1293. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  1294. "[dbus]: cannot get new value of property %s",
  1295. property_name);
  1296. return;
  1297. }
  1298. _signal = dbus_message_new_signal(path, interface_name,
  1299. "PropertiesChanged");
  1300. if (!_signal) {
  1301. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  1302. "[dbus]: cannot allocate signal");
  1303. dbus_message_unref(getter_reply);
  1304. return;
  1305. }
  1306. dbus_message_iter_init(getter_reply, &prop_iter);
  1307. dbus_message_iter_init_append(_signal, &signal_iter);
  1308. if (!dbus_message_iter_open_container(&signal_iter, DBUS_TYPE_ARRAY,
  1309. "{sv}", &dict_iter)) {
  1310. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  1311. "[dbus]: out of memory. cannot open dictionary");
  1312. goto err;
  1313. }
  1314. if (!dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_DICT_ENTRY,
  1315. NULL, &entry_iter)) {
  1316. wpa_printf(MSG_ERROR, "iwpa_dbus_signal_property_changed"
  1317. "[dbus]: out of memory. cannot open dictionary "
  1318. "element");
  1319. goto err;
  1320. }
  1321. if (!dbus_message_iter_append_basic(&entry_iter, DBUS_TYPE_STRING,
  1322. &property_name)) {
  1323. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  1324. "[dbus]: out of memory. cannot open add property "
  1325. "name");
  1326. goto err;
  1327. }
  1328. recursive_iter_copy(&prop_iter, &entry_iter);
  1329. if (!dbus_message_iter_close_container(&dict_iter, &entry_iter)) {
  1330. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  1331. "[dbus]: out of memory. cannot close dictionary "
  1332. "element");
  1333. goto err;
  1334. }
  1335. if (!dbus_message_iter_close_container(&signal_iter, &dict_iter)) {
  1336. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  1337. "[dbus]: out of memory. cannot close dictionary");
  1338. goto err;
  1339. }
  1340. dbus_connection_send(connection, _signal, NULL);
  1341. err:
  1342. dbus_message_unref(getter_reply);
  1343. dbus_message_unref(_signal);
  1344. }