dbus_new_helpers.c 44 KB

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