dbus_new_helpers.c 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573
  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. dbus_message_iter_init(getterReply, &ret_iter);
  554. dbus_message_iter_open_container(&dict_iter,
  555. DBUS_TYPE_DICT_ENTRY,
  556. NULL, &entry_iter);
  557. dbus_message_iter_append_basic(
  558. &entry_iter, DBUS_TYPE_STRING,
  559. &(property_dsc->dbus_property));
  560. recursive_iter_copy(&ret_iter, &entry_iter);
  561. dbus_message_iter_close_container(&dict_iter,
  562. &entry_iter);
  563. dbus_message_unref(getterReply);
  564. counter++;
  565. }
  566. property_dsc = property_dsc->next;
  567. }
  568. dbus_message_iter_close_container(&iter, &dict_iter);
  569. if (counter == 0) {
  570. dbus_message_unref(reply);
  571. reply = dbus_message_new_error(message,
  572. DBUS_ERROR_INVALID_ARGS,
  573. "No readable properties in "
  574. "this interface");
  575. }
  576. return reply;
  577. }
  578. static int is_signature_correct(DBusMessage *message,
  579. struct wpa_dbus_method_desc *method_dsc)
  580. {
  581. /* According to DBus documentation max length of signature is 255 */
  582. #define MAX_SIG_LEN 256
  583. char registered_sig[MAX_SIG_LEN], *pos;
  584. const char *sig = dbus_message_get_signature(message);
  585. int i, ret;
  586. pos = registered_sig;
  587. *pos = '\0';
  588. for (i = 0; i < method_dsc->args_num; i++) {
  589. struct wpa_dbus_argument arg = method_dsc->args[i];
  590. if (arg.dir == ARG_IN) {
  591. size_t blen = registered_sig + MAX_SIG_LEN - pos;
  592. ret = os_snprintf(pos, blen, "%s", arg.type);
  593. if (ret < 0 || (size_t) ret >= blen)
  594. return 0;
  595. pos += ret;
  596. }
  597. }
  598. return !os_strncmp(registered_sig, sig, MAX_SIG_LEN);
  599. }
  600. static DBusMessage * properties_get_all(DBusMessage *message, char *interface,
  601. struct wpa_dbus_object_desc *obj_dsc)
  602. {
  603. if (os_strcmp(dbus_message_get_signature(message), "s") != 0)
  604. return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  605. NULL);
  606. return get_all_properties(message, interface, obj_dsc);
  607. }
  608. static DBusMessage * properties_get(DBusMessage *message,
  609. struct wpa_dbus_property_desc *dsc,
  610. void *user_data)
  611. {
  612. if (os_strcmp(dbus_message_get_signature(message), "ss"))
  613. return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  614. NULL);
  615. if (dsc->access != W && dsc->getter)
  616. return dsc->getter(message, user_data);
  617. return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  618. "Property is write-only");
  619. }
  620. static DBusMessage * properties_set(DBusMessage *message,
  621. struct wpa_dbus_property_desc *dsc,
  622. void *user_data)
  623. {
  624. if (os_strcmp(dbus_message_get_signature(message), "ssv"))
  625. return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  626. NULL);
  627. if (dsc->access != R && dsc->setter)
  628. return dsc->setter(message, user_data);
  629. return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  630. "Property is read-only");
  631. }
  632. static DBusMessage *
  633. properties_get_or_set(DBusMessage *message, DBusMessageIter *iter,
  634. char *interface,
  635. struct wpa_dbus_object_desc *obj_dsc)
  636. {
  637. struct wpa_dbus_property_desc *property_dsc;
  638. char *property;
  639. const char *method;
  640. method = dbus_message_get_member(message);
  641. property_dsc = obj_dsc->properties;
  642. /* Second argument: property name (DBUS_TYPE_STRING) */
  643. if (!dbus_message_iter_next(iter) ||
  644. dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING) {
  645. return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  646. NULL);
  647. }
  648. dbus_message_iter_get_basic(iter, &property);
  649. while (property_dsc) {
  650. /* compare property names and
  651. * interfaces */
  652. if (!os_strncmp(property_dsc->dbus_property, property,
  653. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) &&
  654. !os_strncmp(property_dsc->dbus_interface, interface,
  655. WPAS_DBUS_INTERFACE_MAX))
  656. break;
  657. property_dsc = property_dsc->next;
  658. }
  659. if (property_dsc == NULL) {
  660. wpa_printf(MSG_DEBUG, "no property handler for %s.%s on %s",
  661. interface, property,
  662. dbus_message_get_path(message));
  663. return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  664. "No such property");
  665. }
  666. if (os_strncmp(WPA_DBUS_PROPERTIES_GET, method,
  667. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) == 0)
  668. return properties_get(message, property_dsc,
  669. obj_dsc->user_data);
  670. return properties_set(message, property_dsc, obj_dsc->user_data);
  671. }
  672. static DBusMessage * properties_handler(DBusMessage *message,
  673. struct wpa_dbus_object_desc *obj_dsc)
  674. {
  675. DBusMessageIter iter;
  676. char *interface;
  677. const char *method;
  678. method = dbus_message_get_member(message);
  679. dbus_message_iter_init(message, &iter);
  680. if (!os_strncmp(WPA_DBUS_PROPERTIES_GET, method,
  681. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) ||
  682. !os_strncmp(WPA_DBUS_PROPERTIES_SET, method,
  683. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) ||
  684. !os_strncmp(WPA_DBUS_PROPERTIES_GETALL, method,
  685. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX)) {
  686. /* First argument: interface name (DBUS_TYPE_STRING) */
  687. if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
  688. {
  689. return dbus_message_new_error(message,
  690. DBUS_ERROR_INVALID_ARGS,
  691. NULL);
  692. }
  693. dbus_message_iter_get_basic(&iter, &interface);
  694. if (!os_strncmp(WPA_DBUS_PROPERTIES_GETALL, method,
  695. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX)) {
  696. /* GetAll */
  697. return properties_get_all(message, interface, obj_dsc);
  698. }
  699. /* Get or Set */
  700. return properties_get_or_set(message, &iter, interface,
  701. obj_dsc);
  702. }
  703. return dbus_message_new_error(message, DBUS_ERROR_UNKNOWN_METHOD,
  704. NULL);
  705. }
  706. static DBusMessage * msg_method_handler(DBusMessage *message,
  707. struct wpa_dbus_object_desc *obj_dsc)
  708. {
  709. struct wpa_dbus_method_desc *method_dsc = obj_dsc->methods;
  710. const char *method;
  711. const char *msg_interface;
  712. method = dbus_message_get_member(message);
  713. msg_interface = dbus_message_get_interface(message);
  714. /* try match call to any registered method */
  715. while (method_dsc) {
  716. /* compare method names and interfaces */
  717. if (!os_strncmp(method_dsc->dbus_method, method,
  718. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) &&
  719. !os_strncmp(method_dsc->dbus_interface, msg_interface,
  720. WPAS_DBUS_INTERFACE_MAX))
  721. break;
  722. method_dsc = method_dsc->next;
  723. }
  724. if (method_dsc == NULL) {
  725. wpa_printf(MSG_DEBUG, "no method handler for %s.%s on %s",
  726. msg_interface, method,
  727. dbus_message_get_path(message));
  728. return dbus_message_new_error(message,
  729. DBUS_ERROR_UNKNOWN_METHOD, NULL);
  730. }
  731. if (!is_signature_correct(message, method_dsc)) {
  732. return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  733. NULL);
  734. }
  735. return method_dsc->method_handler(message,
  736. obj_dsc->user_data);
  737. }
  738. /**
  739. * message_handler - Handles incoming DBus messages
  740. * @connection: DBus connection on which message was received
  741. * @message: Received message
  742. * @user_data: pointer to description of object to which message was sent
  743. * Returns: Returns information whether message was handled or not
  744. *
  745. * Reads message interface and method name, then checks if they matches one
  746. * of the special cases i.e. introspection call or properties get/getall/set
  747. * methods and handles it. Else it iterates over registered methods list
  748. * and tries to match method's name and interface to those read from message
  749. * If appropriate method was found its handler function is called and
  750. * response is sent. Otherwise, the DBUS_ERROR_UNKNOWN_METHOD error message
  751. * will be sent.
  752. */
  753. static DBusHandlerResult message_handler(DBusConnection *connection,
  754. DBusMessage *message, void *user_data)
  755. {
  756. struct wpa_dbus_object_desc *obj_dsc = user_data;
  757. const char *method;
  758. const char *path;
  759. const char *msg_interface;
  760. DBusMessage *reply;
  761. /* get method, interface and path the message is addressed to */
  762. method = dbus_message_get_member(message);
  763. path = dbus_message_get_path(message);
  764. msg_interface = dbus_message_get_interface(message);
  765. if (!method || !path || !msg_interface)
  766. return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
  767. wpa_printf(MSG_MSGDUMP, "dbus: %s.%s (%s)",
  768. msg_interface, method, path);
  769. /* if message is introspection method call */
  770. if (!os_strncmp(WPA_DBUS_INTROSPECTION_METHOD, method,
  771. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) &&
  772. !os_strncmp(WPA_DBUS_INTROSPECTION_INTERFACE, msg_interface,
  773. WPAS_DBUS_INTERFACE_MAX))
  774. reply = introspect(message, obj_dsc);
  775. else if (!os_strncmp(WPA_DBUS_PROPERTIES_INTERFACE, msg_interface,
  776. WPAS_DBUS_INTERFACE_MAX)) {
  777. /* if message is properties method call */
  778. reply = properties_handler(message, obj_dsc);
  779. } else {
  780. reply = msg_method_handler(message, obj_dsc);
  781. }
  782. /* If handler succeed returning NULL, reply empty message */
  783. if (!reply)
  784. reply = dbus_message_new_method_return(message);
  785. if (reply) {
  786. if (!dbus_message_get_no_reply(message))
  787. dbus_connection_send(connection, reply, NULL);
  788. dbus_message_unref(reply);
  789. }
  790. return DBUS_HANDLER_RESULT_HANDLED;
  791. }
  792. /**
  793. * free_dbus_object_desc - Frees object description data structure
  794. * @connection: DBus connection
  795. * @obj_dsc: Object description to free
  796. *
  797. * Frees each of properties, methods and signals description lists and
  798. * the object description structure itself.
  799. */
  800. void free_dbus_object_desc(struct wpa_dbus_object_desc *obj_dsc)
  801. {
  802. struct wpa_dbus_method_desc *method_dsc, *tmp_met_dsc;
  803. struct wpa_dbus_signal_desc *signal_dsc, *tmp_sig_dsc;
  804. struct wpa_dbus_property_desc *property_dsc, *tmp_prop_dsc;
  805. int i;
  806. if (!obj_dsc)
  807. return;
  808. /* free methods */
  809. method_dsc = obj_dsc->methods;
  810. while (method_dsc) {
  811. tmp_met_dsc = method_dsc;
  812. method_dsc = method_dsc->next;
  813. os_free(tmp_met_dsc->dbus_interface);
  814. os_free(tmp_met_dsc->dbus_method);
  815. for (i = 0; i < tmp_met_dsc->args_num; i++) {
  816. os_free(tmp_met_dsc->args[i].name);
  817. os_free(tmp_met_dsc->args[i].type);
  818. }
  819. os_free(tmp_met_dsc);
  820. }
  821. /* free signals */
  822. signal_dsc = obj_dsc->signals;
  823. while (signal_dsc) {
  824. tmp_sig_dsc = signal_dsc;
  825. signal_dsc = signal_dsc->next;
  826. os_free(tmp_sig_dsc->dbus_interface);
  827. os_free(tmp_sig_dsc->dbus_signal);
  828. for (i = 0; i < tmp_sig_dsc->args_num; i++) {
  829. os_free(tmp_sig_dsc->args[i].name);
  830. os_free(tmp_sig_dsc->args[i].type);
  831. }
  832. os_free(tmp_sig_dsc);
  833. }
  834. /* free properties */
  835. property_dsc = obj_dsc->properties;
  836. while (property_dsc) {
  837. tmp_prop_dsc = property_dsc;
  838. property_dsc = property_dsc->next;
  839. os_free(tmp_prop_dsc->dbus_interface);
  840. os_free(tmp_prop_dsc->dbus_property);
  841. os_free(tmp_prop_dsc->type);
  842. os_free(tmp_prop_dsc);
  843. }
  844. /* free handler's argument */
  845. if (obj_dsc->user_data_free_func)
  846. obj_dsc->user_data_free_func(obj_dsc->user_data);
  847. os_free(obj_dsc);
  848. }
  849. static void free_dbus_object_desc_cb(DBusConnection *connection, void *obj_dsc)
  850. {
  851. free_dbus_object_desc(obj_dsc);
  852. }
  853. /**
  854. * wpa_dbus_ctrl_iface_init - Initialize dbus control interface
  855. * @application_data: Pointer to application specific data structure
  856. * @dbus_path: DBus path to interface object
  857. * @dbus_service: DBus service name to register with
  858. * @messageHandler: a pointer to function which will handle dbus messages
  859. * coming on interface
  860. * Returns: 0 on success, -1 on failure
  861. *
  862. * Initialize the dbus control interface and start receiving commands from
  863. * external programs over the bus.
  864. */
  865. int wpa_dbus_ctrl_iface_init(struct wpas_dbus_priv *iface,
  866. char *dbus_path, char *dbus_service,
  867. struct wpa_dbus_object_desc *obj_desc)
  868. {
  869. DBusError error;
  870. int ret = -1;
  871. DBusObjectPathVTable wpa_vtable = {
  872. &free_dbus_object_desc_cb, &message_handler,
  873. NULL, NULL, NULL, NULL
  874. };
  875. obj_desc->connection = iface->con;
  876. /* Register the message handler for the global dbus interface */
  877. if (!dbus_connection_register_object_path(iface->con,
  878. dbus_path, &wpa_vtable,
  879. obj_desc)) {
  880. perror("dbus_connection_register_object_path[dbus]");
  881. wpa_printf(MSG_ERROR, "Could not set up DBus message "
  882. "handler.");
  883. return -1;
  884. }
  885. /* Register our service with the message bus */
  886. dbus_error_init(&error);
  887. switch (dbus_bus_request_name(iface->con, dbus_service,
  888. 0, &error)) {
  889. case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
  890. ret = 0;
  891. break;
  892. case DBUS_REQUEST_NAME_REPLY_EXISTS:
  893. case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
  894. case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
  895. perror("dbus_bus_request_name[dbus]");
  896. wpa_printf(MSG_ERROR, "Could not request DBus service name: "
  897. "already registered.");
  898. break;
  899. default:
  900. perror("dbus_bus_request_name[dbus]");
  901. wpa_printf(MSG_ERROR, "Could not request DBus service name: "
  902. "%s %s.", error.name, error.message);
  903. break;
  904. }
  905. dbus_error_free(&error);
  906. if (ret != 0)
  907. return -1;
  908. wpa_printf(MSG_DEBUG, "Providing DBus service '%s'.", dbus_service);
  909. return 0;
  910. }
  911. /**
  912. * wpa_dbus_register_object_per_iface - Register a new object with dbus
  913. * @ctrl_iface: pointer to dbus private data
  914. * @path: DBus path to object
  915. * @ifname: interface name
  916. * @obj_desc: description of object's methods, signals and properties
  917. * Returns: 0 on success, -1 on error
  918. *
  919. * Registers a new interface with dbus and assigns it a dbus object path.
  920. */
  921. int wpa_dbus_register_object_per_iface(
  922. struct wpas_dbus_priv *ctrl_iface,
  923. const char *path, const char *ifname,
  924. struct wpa_dbus_object_desc *obj_desc)
  925. {
  926. DBusConnection *con;
  927. DBusObjectPathVTable vtable = {
  928. &free_dbus_object_desc_cb, &message_handler,
  929. NULL, NULL, NULL, NULL
  930. };
  931. /* Do nothing if the control interface is not turned on */
  932. if (ctrl_iface == NULL)
  933. return 0;
  934. con = ctrl_iface->con;
  935. obj_desc->connection = con;
  936. /* Register the message handler for the interface functions */
  937. if (!dbus_connection_register_object_path(con, path, &vtable,
  938. obj_desc)) {
  939. perror("wpa_dbus_register_iface [dbus]");
  940. wpa_printf(MSG_ERROR, "Could not set up DBus message "
  941. "handler for interface %s\n"
  942. "and object %s.", ifname, path);
  943. return -1;
  944. }
  945. return 0;
  946. }
  947. /**
  948. * wpa_dbus_unregister_object_per_iface - Unregisters DBus object
  949. * @ctrl_iface: Pointer to dbus private data
  950. * @path: DBus path to object which will be unregistered
  951. * Returns: Zero on success and -1 on failure
  952. *
  953. * Unregisters DBus object given by its path
  954. */
  955. int wpa_dbus_unregister_object_per_iface(
  956. struct wpas_dbus_priv *ctrl_iface, const char *path)
  957. {
  958. DBusConnection *con = ctrl_iface->con;
  959. if (!dbus_connection_unregister_object_path(con, path))
  960. return -1;
  961. return 0;
  962. }
  963. /**
  964. * wpa_dbus_method_register - Registers DBus method for given object
  965. * @obj_dsc: Object description for which a method will be registered
  966. * @dbus_interface: DBus interface under which method will be registered
  967. * @dbus_method: a name the method will be registered with
  968. * @method_handler: a function which will be called to handle this method call
  969. * @args: method arguments list
  970. * Returns: Zero on success and -1 on failure
  971. *
  972. * Registers DBus method under given name and interface for the object.
  973. * Method calls will be handled with given handling function.
  974. * Handler function is required to return a DBusMessage pointer which
  975. * will be response to method call. Any method call before being handled
  976. * must have registered appropriate handler by using this function.
  977. */
  978. int wpa_dbus_method_register(struct wpa_dbus_object_desc *obj_dsc,
  979. const char *dbus_interface,
  980. const char *dbus_method,
  981. WPADBusMethodHandler method_handler,
  982. const struct wpa_dbus_argument args[])
  983. {
  984. struct wpa_dbus_method_desc *method_dsc = obj_dsc->methods;
  985. struct wpa_dbus_method_desc *prev_desc;
  986. int args_num = 0;
  987. int interface_len, method_len, i, len, error;
  988. prev_desc = NULL;
  989. while (method_dsc) {
  990. prev_desc = method_dsc;
  991. method_dsc = method_dsc->next;
  992. }
  993. /* count args */
  994. if (args) {
  995. while (args[args_num].name && args[args_num].type)
  996. args_num++;
  997. }
  998. method_dsc = os_zalloc(sizeof(struct wpa_dbus_method_desc) +
  999. args_num * sizeof(struct wpa_dbus_argument));
  1000. if (!method_dsc)
  1001. goto err;
  1002. if (prev_desc == NULL)
  1003. obj_dsc->methods = method_dsc;
  1004. else
  1005. prev_desc->next = method_dsc;
  1006. /* copy interface name */
  1007. interface_len = os_strlen(dbus_interface) + 1;
  1008. method_dsc->dbus_interface = os_malloc(interface_len);
  1009. if (!method_dsc->dbus_interface)
  1010. goto err;
  1011. os_strncpy(method_dsc->dbus_interface, dbus_interface, interface_len);
  1012. /* copy method name */
  1013. method_len = os_strlen(dbus_method) + 1;
  1014. method_dsc->dbus_method = os_malloc(method_len);
  1015. if (!method_dsc->dbus_method)
  1016. goto err;
  1017. os_strncpy(method_dsc->dbus_method, dbus_method, method_len);
  1018. /* copy arguments */
  1019. error = 0;
  1020. method_dsc->args_num = args_num;
  1021. for (i = 0; i < args_num; i++) {
  1022. len = os_strlen(args[i].name) + 1;
  1023. method_dsc->args[i].name = os_malloc(len);
  1024. if (!method_dsc->args[i].name) {
  1025. error = 1;
  1026. continue;
  1027. }
  1028. os_strncpy(method_dsc->args[i].name, args[i].name, len);
  1029. len = os_strlen(args[i].type) + 1;
  1030. method_dsc->args[i].type = os_malloc(len);
  1031. if (!method_dsc->args[i].type) {
  1032. error = 1;
  1033. continue;
  1034. }
  1035. os_strncpy(method_dsc->args[i].type, args[i].type, len);
  1036. method_dsc->args[i].dir = args[i].dir;
  1037. }
  1038. if (error)
  1039. goto err;
  1040. method_dsc->method_handler = method_handler;
  1041. method_dsc->next = NULL;
  1042. return 0;
  1043. err:
  1044. wpa_printf(MSG_WARNING, "Failed to register dbus method %s in "
  1045. "interface %s", dbus_method, dbus_interface);
  1046. if (method_dsc) {
  1047. os_free(method_dsc->dbus_interface);
  1048. os_free(method_dsc->dbus_method);
  1049. for (i = 0; i < method_dsc->args_num; i++) {
  1050. os_free(method_dsc->args[i].name);
  1051. os_free(method_dsc->args[i].type);
  1052. }
  1053. if (prev_desc == NULL)
  1054. obj_dsc->methods = NULL;
  1055. else
  1056. prev_desc->next = NULL;
  1057. os_free(method_dsc);
  1058. }
  1059. return -1;
  1060. }
  1061. /**
  1062. * wpa_dbus_signal_register - Registers DBus signal for given object
  1063. * @obj_dsc: Object description for which a signal will be registered
  1064. * @dbus_interface: DBus interface under which signal will be registered
  1065. * @dbus_signal: a name the signal will be registered with
  1066. * @args: signal arguments list
  1067. * Returns: Zero on success and -1 on failure
  1068. *
  1069. * Registers DBus signal under given name and interface for the object.
  1070. * Signal registration is NOT required in order to send signals, but not
  1071. * registered signals will not be respected in introspection data
  1072. * therefore it is highly recommended to register every signal before
  1073. * using it.
  1074. */
  1075. int wpa_dbus_signal_register(struct wpa_dbus_object_desc *obj_dsc,
  1076. const char *dbus_interface,
  1077. const char *dbus_signal,
  1078. const struct wpa_dbus_argument args[])
  1079. {
  1080. struct wpa_dbus_signal_desc *signal_dsc = obj_dsc->signals;
  1081. struct wpa_dbus_signal_desc *prev_desc;
  1082. int args_num = 0;
  1083. int interface_len, signal_len, i, len, error = 0;
  1084. prev_desc = NULL;
  1085. while (signal_dsc) {
  1086. prev_desc = signal_dsc;
  1087. signal_dsc = signal_dsc->next;
  1088. }
  1089. /* count args */
  1090. if (args) {
  1091. while (args[args_num].name && args[args_num].type)
  1092. args_num++;
  1093. }
  1094. signal_dsc = os_zalloc(sizeof(struct wpa_dbus_signal_desc) +
  1095. args_num * sizeof(struct wpa_dbus_argument));
  1096. if (!signal_dsc)
  1097. goto err;
  1098. if (prev_desc == NULL)
  1099. obj_dsc->signals = signal_dsc;
  1100. else
  1101. prev_desc->next = signal_dsc;
  1102. /* copy interface name */
  1103. interface_len = strlen(dbus_interface) + 1;
  1104. signal_dsc->dbus_interface = os_malloc(interface_len);
  1105. if (!signal_dsc->dbus_interface)
  1106. goto err;
  1107. os_strncpy(signal_dsc->dbus_interface, dbus_interface, interface_len);
  1108. /* copy signal name */
  1109. signal_len = strlen(dbus_signal) + 1;
  1110. signal_dsc->dbus_signal = os_malloc(signal_len);
  1111. if (!signal_dsc->dbus_signal)
  1112. goto err;
  1113. os_strncpy(signal_dsc->dbus_signal, dbus_signal, signal_len);
  1114. /* copy arguments */
  1115. signal_dsc->args_num = args_num;
  1116. for (i = 0; i < args_num; i++) {
  1117. len = os_strlen(args[i].name) + 1;
  1118. signal_dsc->args[i].name = os_malloc(len);
  1119. if (!signal_dsc->args[i].name) {
  1120. error = 1;
  1121. continue;
  1122. }
  1123. os_strncpy(signal_dsc->args[i].name, args[i].name, len);
  1124. len = strlen(args[i].type) + 1;
  1125. signal_dsc->args[i].type = os_malloc(len);
  1126. if (!signal_dsc->args[i].type) {
  1127. error = 1;
  1128. continue;
  1129. }
  1130. os_strncpy(signal_dsc->args[i].type, args[i].type, len);
  1131. }
  1132. if (error)
  1133. goto err;
  1134. signal_dsc->next = NULL;
  1135. return 0;
  1136. err:
  1137. wpa_printf(MSG_WARNING, "Failed to register dbus signal %s in "
  1138. "interface %s", dbus_signal, dbus_interface);
  1139. if (signal_dsc) {
  1140. os_free(signal_dsc->dbus_interface);
  1141. os_free(signal_dsc->dbus_signal);
  1142. for (i = 0; i < signal_dsc->args_num; i++) {
  1143. os_free(signal_dsc->args[i].name);
  1144. os_free(signal_dsc->args[i].type);
  1145. }
  1146. if (prev_desc == NULL)
  1147. obj_dsc->signals = NULL;
  1148. else
  1149. prev_desc->next = NULL;
  1150. os_free(signal_dsc);
  1151. }
  1152. return -1;
  1153. }
  1154. /**
  1155. * wpa_dbus_property_register - Registers DBus property for given object
  1156. * @obj_dsc: Object description for which a property will be registered
  1157. * @dbus_interface: DBus interface under which method will be registered
  1158. * @dbus_property: a name the property will be registered with
  1159. * @type: a property type signature in form of DBus type description
  1160. * @getter: a function called in order to get property value
  1161. * @setter: a function called in order to set property value
  1162. * @access: property access permissions specifier (R, W or RW)
  1163. * Returns: Zero on success and -1 on failure
  1164. *
  1165. * Registers DBus property under given name and interface for the object.
  1166. * Properties are set with giver setter function and get with getter.Getter
  1167. * or setter are required to return DBusMessage which is response to Set/Get
  1168. * method calls. Every property must be registered by this function before
  1169. * being used.
  1170. */
  1171. int wpa_dbus_property_register(struct wpa_dbus_object_desc *obj_dsc,
  1172. const char *dbus_interface,
  1173. const char *dbus_property,
  1174. const char *type,
  1175. WPADBusPropertyAccessor getter,
  1176. WPADBusPropertyAccessor setter,
  1177. enum dbus_prop_access _access)
  1178. {
  1179. struct wpa_dbus_property_desc *property_dsc = obj_dsc->properties;
  1180. struct wpa_dbus_property_desc *prev_desc;
  1181. int interface_len, property_len, type_len;
  1182. prev_desc = NULL;
  1183. while (property_dsc) {
  1184. prev_desc = property_dsc;
  1185. property_dsc = property_dsc->next;
  1186. }
  1187. property_dsc = os_zalloc(sizeof(struct wpa_dbus_property_desc));
  1188. if (!property_dsc)
  1189. goto err;
  1190. if (prev_desc == NULL)
  1191. obj_dsc->properties = property_dsc;
  1192. else
  1193. prev_desc->next = property_dsc;
  1194. /* copy interface name */
  1195. interface_len = os_strlen(dbus_interface) + 1;
  1196. property_dsc->dbus_interface = os_malloc(interface_len);
  1197. if (!property_dsc->dbus_interface)
  1198. goto err;
  1199. os_strncpy(property_dsc->dbus_interface, dbus_interface,
  1200. interface_len);
  1201. /* copy property name */
  1202. property_len = os_strlen(dbus_property) + 1;
  1203. property_dsc->dbus_property = os_malloc(property_len);
  1204. if (!property_dsc->dbus_property)
  1205. goto err;
  1206. os_strncpy(property_dsc->dbus_property, dbus_property, property_len);
  1207. /* copy property type */
  1208. type_len = os_strlen(type) + 1;
  1209. property_dsc->type = os_malloc(type_len);
  1210. if (!property_dsc->type)
  1211. goto err;
  1212. os_strncpy(property_dsc->type, type, type_len);
  1213. property_dsc->getter = getter;
  1214. property_dsc->setter = setter;
  1215. property_dsc->access = _access;
  1216. property_dsc->next = NULL;
  1217. return 0;
  1218. err:
  1219. wpa_printf(MSG_WARNING, "Failed to register dbus property %s in "
  1220. "interface %s", dbus_property, dbus_interface);
  1221. if (property_dsc) {
  1222. os_free(property_dsc->dbus_interface);
  1223. os_free(property_dsc->dbus_property);
  1224. os_free(property_dsc->type);
  1225. if (prev_desc == NULL)
  1226. obj_dsc->properties = NULL;
  1227. else
  1228. prev_desc->next = NULL;
  1229. os_free(property_dsc);
  1230. }
  1231. return -1;
  1232. }
  1233. /**
  1234. * wpas_dbus_signal_network_added - Send a property changed signal
  1235. * @iface: dbus priv struct
  1236. * @property_getter: propperty getter used to fetch new property value
  1237. * @getter_arg: argument passed to property getter
  1238. * @path: path to object which property has changed
  1239. * @interface_name: signal and property interface
  1240. * @property_name: name of property which has changed
  1241. *
  1242. * Notify listeners about changing value of some property. Signal
  1243. * contains property name and its value fetched using given property
  1244. * getter.
  1245. */
  1246. void wpa_dbus_signal_property_changed(struct wpas_dbus_priv *iface,
  1247. WPADBusPropertyAccessor property_getter,
  1248. void *getter_arg,
  1249. const char *path,
  1250. const char *interface_name,
  1251. const char *property_name)
  1252. {
  1253. DBusConnection *connection;
  1254. DBusMessage *_signal, *getter_reply;
  1255. DBusMessageIter prop_iter, signal_iter, dict_iter, entry_iter;
  1256. if (!iface)
  1257. return;
  1258. connection = iface->con;
  1259. if (!property_getter) {
  1260. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  1261. "[dbus]: property getter not specified");
  1262. return;
  1263. }
  1264. if (!path || !interface_name || !property_name) {
  1265. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  1266. "[dbus]: path interface of property not specified");
  1267. return;
  1268. }
  1269. getter_reply = property_getter(NULL, getter_arg);
  1270. if (!getter_reply ||
  1271. dbus_message_get_type(getter_reply) == DBUS_MESSAGE_TYPE_ERROR) {
  1272. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  1273. "[dbus]: cannot get new value of property %s",
  1274. property_name);
  1275. return;
  1276. }
  1277. _signal = dbus_message_new_signal(path, interface_name,
  1278. "PropertiesChanged");
  1279. if (!_signal) {
  1280. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  1281. "[dbus]: cannot allocate signal");
  1282. dbus_message_unref(getter_reply);
  1283. return;
  1284. }
  1285. dbus_message_iter_init(getter_reply, &prop_iter);
  1286. dbus_message_iter_init_append(_signal, &signal_iter);
  1287. if (!dbus_message_iter_open_container(&signal_iter, DBUS_TYPE_ARRAY,
  1288. "{sv}", &dict_iter)) {
  1289. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  1290. "[dbus]: out of memory. cannot open dictionary");
  1291. goto err;
  1292. }
  1293. if (!dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_DICT_ENTRY,
  1294. NULL, &entry_iter)) {
  1295. wpa_printf(MSG_ERROR, "iwpa_dbus_signal_property_changed"
  1296. "[dbus]: out of memory. cannot open dictionary "
  1297. "element");
  1298. goto err;
  1299. }
  1300. if (!dbus_message_iter_append_basic(&entry_iter, DBUS_TYPE_STRING,
  1301. &property_name)) {
  1302. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  1303. "[dbus]: out of memory. cannot open add property "
  1304. "name");
  1305. goto err;
  1306. }
  1307. recursive_iter_copy(&prop_iter, &entry_iter);
  1308. if (!dbus_message_iter_close_container(&dict_iter, &entry_iter)) {
  1309. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  1310. "[dbus]: out of memory. cannot close dictionary "
  1311. "element");
  1312. goto err;
  1313. }
  1314. if (!dbus_message_iter_close_container(&signal_iter, &dict_iter)) {
  1315. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  1316. "[dbus]: out of memory. cannot close dictionary");
  1317. goto err;
  1318. }
  1319. dbus_connection_send(connection, _signal, NULL);
  1320. err:
  1321. dbus_message_unref(getter_reply);
  1322. dbus_message_unref(_signal);
  1323. }