dbus_new_helpers.c 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078
  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 "dbus_common.h"
  18. #include "dbus_common_i.h"
  19. #include "dbus_new_helpers.h"
  20. /**
  21. * recursive_iter_copy - Reads arguments from one iterator and
  22. * writes to another recursively
  23. * @from: iterator to read from
  24. * @to: iterator to write to
  25. *
  26. * Copies one iterator's elements to another. If any element in
  27. * iterator is of container type, its content is copied recursively
  28. */
  29. static void recursive_iter_copy(DBusMessageIter *from, DBusMessageIter *to)
  30. {
  31. char *subtype = NULL;
  32. int type;
  33. /* iterate over iterator to copy */
  34. while ((type = dbus_message_iter_get_arg_type (from)) !=
  35. DBUS_TYPE_INVALID) {
  36. /* simply copy basic type entries */
  37. if (dbus_type_is_basic(type)) {
  38. if (dbus_type_is_fixed(type)) {
  39. /*
  40. * According to DBus documentation all
  41. * fixed-length types are guaranteed to fit
  42. * 8 bytes
  43. */
  44. dbus_uint64_t v;
  45. dbus_message_iter_get_basic (from, &v);
  46. dbus_message_iter_append_basic (to, type, &v);
  47. } else {
  48. char *v;
  49. dbus_message_iter_get_basic (from, &v);
  50. dbus_message_iter_append_basic (to, type, &v);
  51. }
  52. } else {
  53. /* recursively copy container type entries */
  54. DBusMessageIter write_subiter, read_subiter;
  55. dbus_message_iter_recurse(from, &read_subiter);
  56. if (type == DBUS_TYPE_VARIANT ||
  57. type == DBUS_TYPE_ARRAY) {
  58. subtype = dbus_message_iter_get_signature(
  59. &read_subiter);
  60. }
  61. dbus_message_iter_open_container(to, type, subtype,
  62. &write_subiter);
  63. recursive_iter_copy(&read_subiter, &write_subiter);
  64. dbus_message_iter_close_container(to, &write_subiter);
  65. if (subtype)
  66. dbus_free(subtype);
  67. }
  68. dbus_message_iter_next(from);
  69. }
  70. }
  71. static unsigned int fill_dict_with_properties(
  72. DBusMessageIter *dict_iter, struct wpa_dbus_property_desc *props,
  73. const char *interface, const void *user_data)
  74. {
  75. DBusMessage *reply;
  76. DBusMessageIter entry_iter, ret_iter;
  77. unsigned int counter = 0;
  78. struct wpa_dbus_property_desc *property_dsc;
  79. for (property_dsc = props; property_dsc;
  80. property_dsc = property_dsc->next) {
  81. if (!os_strncmp(property_dsc->dbus_interface, interface,
  82. WPAS_DBUS_INTERFACE_MAX) &&
  83. property_dsc->access != W && property_dsc->getter) {
  84. reply = property_dsc->getter(NULL, user_data);
  85. if (!reply)
  86. continue;
  87. if (dbus_message_get_type(reply) ==
  88. DBUS_MESSAGE_TYPE_ERROR) {
  89. dbus_message_unref(reply);
  90. continue;
  91. }
  92. dbus_message_iter_init(reply, &ret_iter);
  93. dbus_message_iter_open_container(dict_iter,
  94. DBUS_TYPE_DICT_ENTRY,
  95. NULL, &entry_iter);
  96. dbus_message_iter_append_basic(
  97. &entry_iter, DBUS_TYPE_STRING,
  98. &(property_dsc->dbus_property));
  99. recursive_iter_copy(&ret_iter, &entry_iter);
  100. dbus_message_iter_close_container(dict_iter,
  101. &entry_iter);
  102. dbus_message_unref(reply);
  103. counter++;
  104. }
  105. }
  106. return counter;
  107. }
  108. /**
  109. * get_all_properties - Responds for GetAll properties calls on object
  110. * @message: Message with GetAll call
  111. * @interface: interface name which properties will be returned
  112. * @property_dsc: list of object's properties
  113. * Returns: Message with dict of variants as argument with properties values
  114. *
  115. * Iterates over all properties registered with object and execute getters
  116. * of those, which are readable and which interface matches interface
  117. * specified as argument. Returned message contains one dict argument
  118. * with properties names as keys and theirs values as values.
  119. */
  120. static DBusMessage * get_all_properties(
  121. DBusMessage *message, char *interface,
  122. struct wpa_dbus_object_desc *obj_dsc)
  123. {
  124. /* Create and initialize the return message */
  125. DBusMessage *reply = dbus_message_new_method_return(message);
  126. DBusMessageIter iter, dict_iter;
  127. int props_num;
  128. dbus_message_iter_init_append(reply, &iter);
  129. dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
  130. DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
  131. DBUS_TYPE_STRING_AS_STRING
  132. DBUS_TYPE_VARIANT_AS_STRING
  133. DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
  134. &dict_iter);
  135. props_num = fill_dict_with_properties(&dict_iter,obj_dsc->properties,
  136. interface, obj_dsc->user_data);
  137. dbus_message_iter_close_container(&iter, &dict_iter);
  138. if (props_num == 0) {
  139. dbus_message_unref(reply);
  140. reply = dbus_message_new_error(message,
  141. DBUS_ERROR_INVALID_ARGS,
  142. "No readable properties in "
  143. "this interface");
  144. }
  145. return reply;
  146. }
  147. static int is_signature_correct(DBusMessage *message,
  148. struct wpa_dbus_method_desc *method_dsc)
  149. {
  150. /* According to DBus documentation max length of signature is 255 */
  151. #define MAX_SIG_LEN 256
  152. char registered_sig[MAX_SIG_LEN], *pos;
  153. const char *sig = dbus_message_get_signature(message);
  154. int i, ret;
  155. pos = registered_sig;
  156. *pos = '\0';
  157. for (i = 0; i < method_dsc->args_num; i++) {
  158. struct wpa_dbus_argument arg = method_dsc->args[i];
  159. if (arg.dir == ARG_IN) {
  160. size_t blen = registered_sig + MAX_SIG_LEN - pos;
  161. ret = os_snprintf(pos, blen, "%s", arg.type);
  162. if (ret < 0 || (size_t) ret >= blen)
  163. return 0;
  164. pos += ret;
  165. }
  166. }
  167. return !os_strncmp(registered_sig, sig, MAX_SIG_LEN);
  168. }
  169. static DBusMessage * properties_get_all(DBusMessage *message, char *interface,
  170. struct wpa_dbus_object_desc *obj_dsc)
  171. {
  172. if (os_strcmp(dbus_message_get_signature(message), "s") != 0)
  173. return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  174. NULL);
  175. return get_all_properties(message, interface, obj_dsc);
  176. }
  177. static DBusMessage * properties_get(DBusMessage *message,
  178. struct wpa_dbus_property_desc *dsc,
  179. void *user_data)
  180. {
  181. if (os_strcmp(dbus_message_get_signature(message), "ss"))
  182. return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  183. NULL);
  184. if (dsc->access != W && dsc->getter)
  185. return dsc->getter(message, user_data);
  186. return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  187. "Property is write-only");
  188. }
  189. static DBusMessage * properties_set(DBusMessage *message,
  190. struct wpa_dbus_property_desc *dsc,
  191. void *user_data)
  192. {
  193. if (os_strcmp(dbus_message_get_signature(message), "ssv"))
  194. return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  195. NULL);
  196. if (dsc->access != R && dsc->setter)
  197. return dsc->setter(message, user_data);
  198. return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  199. "Property is read-only");
  200. }
  201. static DBusMessage *
  202. properties_get_or_set(DBusMessage *message, DBusMessageIter *iter,
  203. char *interface,
  204. struct wpa_dbus_object_desc *obj_dsc)
  205. {
  206. struct wpa_dbus_property_desc *property_dsc;
  207. char *property;
  208. const char *method;
  209. method = dbus_message_get_member(message);
  210. property_dsc = obj_dsc->properties;
  211. /* Second argument: property name (DBUS_TYPE_STRING) */
  212. if (!dbus_message_iter_next(iter) ||
  213. dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING) {
  214. return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  215. NULL);
  216. }
  217. dbus_message_iter_get_basic(iter, &property);
  218. while (property_dsc) {
  219. /* compare property names and
  220. * interfaces */
  221. if (!os_strncmp(property_dsc->dbus_property, property,
  222. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) &&
  223. !os_strncmp(property_dsc->dbus_interface, interface,
  224. WPAS_DBUS_INTERFACE_MAX))
  225. break;
  226. property_dsc = property_dsc->next;
  227. }
  228. if (property_dsc == NULL) {
  229. wpa_printf(MSG_DEBUG, "no property handler for %s.%s on %s",
  230. interface, property,
  231. dbus_message_get_path(message));
  232. return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  233. "No such property");
  234. }
  235. if (os_strncmp(WPA_DBUS_PROPERTIES_GET, method,
  236. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) == 0)
  237. return properties_get(message, property_dsc,
  238. obj_dsc->user_data);
  239. return properties_set(message, property_dsc, obj_dsc->user_data);
  240. }
  241. static DBusMessage * properties_handler(DBusMessage *message,
  242. struct wpa_dbus_object_desc *obj_dsc)
  243. {
  244. DBusMessageIter iter;
  245. char *interface;
  246. const char *method;
  247. method = dbus_message_get_member(message);
  248. dbus_message_iter_init(message, &iter);
  249. if (!os_strncmp(WPA_DBUS_PROPERTIES_GET, method,
  250. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) ||
  251. !os_strncmp(WPA_DBUS_PROPERTIES_SET, method,
  252. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) ||
  253. !os_strncmp(WPA_DBUS_PROPERTIES_GETALL, method,
  254. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX)) {
  255. /* First argument: interface name (DBUS_TYPE_STRING) */
  256. if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
  257. {
  258. return dbus_message_new_error(message,
  259. DBUS_ERROR_INVALID_ARGS,
  260. NULL);
  261. }
  262. dbus_message_iter_get_basic(&iter, &interface);
  263. if (!os_strncmp(WPA_DBUS_PROPERTIES_GETALL, method,
  264. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX)) {
  265. /* GetAll */
  266. return properties_get_all(message, interface, obj_dsc);
  267. }
  268. /* Get or Set */
  269. return properties_get_or_set(message, &iter, interface,
  270. obj_dsc);
  271. }
  272. return dbus_message_new_error(message, DBUS_ERROR_UNKNOWN_METHOD,
  273. NULL);
  274. }
  275. static DBusMessage * msg_method_handler(DBusMessage *message,
  276. struct wpa_dbus_object_desc *obj_dsc)
  277. {
  278. struct wpa_dbus_method_desc *method_dsc = obj_dsc->methods;
  279. const char *method;
  280. const char *msg_interface;
  281. method = dbus_message_get_member(message);
  282. msg_interface = dbus_message_get_interface(message);
  283. /* try match call to any registered method */
  284. while (method_dsc) {
  285. /* compare method names and interfaces */
  286. if (!os_strncmp(method_dsc->dbus_method, method,
  287. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) &&
  288. !os_strncmp(method_dsc->dbus_interface, msg_interface,
  289. WPAS_DBUS_INTERFACE_MAX))
  290. break;
  291. method_dsc = method_dsc->next;
  292. }
  293. if (method_dsc == NULL) {
  294. wpa_printf(MSG_DEBUG, "no method handler for %s.%s on %s",
  295. msg_interface, method,
  296. dbus_message_get_path(message));
  297. return dbus_message_new_error(message,
  298. DBUS_ERROR_UNKNOWN_METHOD, NULL);
  299. }
  300. if (!is_signature_correct(message, method_dsc)) {
  301. return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
  302. NULL);
  303. }
  304. return method_dsc->method_handler(message,
  305. obj_dsc->user_data);
  306. }
  307. /**
  308. * message_handler - Handles incoming DBus messages
  309. * @connection: DBus connection on which message was received
  310. * @message: Received message
  311. * @user_data: pointer to description of object to which message was sent
  312. * Returns: Returns information whether message was handled or not
  313. *
  314. * Reads message interface and method name, then checks if they matches one
  315. * of the special cases i.e. introspection call or properties get/getall/set
  316. * methods and handles it. Else it iterates over registered methods list
  317. * and tries to match method's name and interface to those read from message
  318. * If appropriate method was found its handler function is called and
  319. * response is sent. Otherwise, the DBUS_ERROR_UNKNOWN_METHOD error message
  320. * will be sent.
  321. */
  322. static DBusHandlerResult message_handler(DBusConnection *connection,
  323. DBusMessage *message, void *user_data)
  324. {
  325. struct wpa_dbus_object_desc *obj_dsc = user_data;
  326. const char *method;
  327. const char *path;
  328. const char *msg_interface;
  329. DBusMessage *reply;
  330. /* get method, interface and path the message is addressed to */
  331. method = dbus_message_get_member(message);
  332. path = dbus_message_get_path(message);
  333. msg_interface = dbus_message_get_interface(message);
  334. if (!method || !path || !msg_interface)
  335. return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
  336. wpa_printf(MSG_MSGDUMP, "dbus: %s.%s (%s)",
  337. msg_interface, method, path);
  338. /* if message is introspection method call */
  339. if (!os_strncmp(WPA_DBUS_INTROSPECTION_METHOD, method,
  340. WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) &&
  341. !os_strncmp(WPA_DBUS_INTROSPECTION_INTERFACE, msg_interface,
  342. WPAS_DBUS_INTERFACE_MAX)) {
  343. #ifdef CONFIG_CTRL_IFACE_DBUS_INTRO
  344. reply = wpa_dbus_introspect(message, obj_dsc);
  345. #else /* CONFIG_CTRL_IFACE_DBUS_INTRO */
  346. reply = dbus_message_new_error(
  347. message, DBUS_ERROR_UNKNOWN_METHOD,
  348. "wpa_supplicant was compiled without "
  349. "introspection support.");
  350. #endif /* CONFIG_CTRL_IFACE_DBUS_INTRO */
  351. } else if (!os_strncmp(WPA_DBUS_PROPERTIES_INTERFACE, msg_interface,
  352. WPAS_DBUS_INTERFACE_MAX)) {
  353. /* if message is properties method call */
  354. reply = properties_handler(message, obj_dsc);
  355. } else {
  356. reply = msg_method_handler(message, obj_dsc);
  357. }
  358. /* If handler succeed returning NULL, reply empty message */
  359. if (!reply)
  360. reply = dbus_message_new_method_return(message);
  361. if (reply) {
  362. if (!dbus_message_get_no_reply(message))
  363. dbus_connection_send(connection, reply, NULL);
  364. dbus_message_unref(reply);
  365. }
  366. return DBUS_HANDLER_RESULT_HANDLED;
  367. }
  368. /**
  369. * free_dbus_object_desc - Frees object description data structure
  370. * @connection: DBus connection
  371. * @obj_dsc: Object description to free
  372. *
  373. * Frees each of properties, methods and signals description lists and
  374. * the object description structure itself.
  375. */
  376. void free_dbus_object_desc(struct wpa_dbus_object_desc *obj_dsc)
  377. {
  378. struct wpa_dbus_method_desc *method_dsc, *tmp_met_dsc;
  379. struct wpa_dbus_signal_desc *signal_dsc, *tmp_sig_dsc;
  380. struct wpa_dbus_property_desc *property_dsc, *tmp_prop_dsc;
  381. int i;
  382. if (!obj_dsc)
  383. return;
  384. /* free methods */
  385. method_dsc = obj_dsc->methods;
  386. while (method_dsc) {
  387. tmp_met_dsc = method_dsc;
  388. method_dsc = method_dsc->next;
  389. os_free(tmp_met_dsc->dbus_interface);
  390. os_free(tmp_met_dsc->dbus_method);
  391. for (i = 0; i < tmp_met_dsc->args_num; i++) {
  392. os_free(tmp_met_dsc->args[i].name);
  393. os_free(tmp_met_dsc->args[i].type);
  394. }
  395. os_free(tmp_met_dsc);
  396. }
  397. /* free signals */
  398. signal_dsc = obj_dsc->signals;
  399. while (signal_dsc) {
  400. tmp_sig_dsc = signal_dsc;
  401. signal_dsc = signal_dsc->next;
  402. os_free(tmp_sig_dsc->dbus_interface);
  403. os_free(tmp_sig_dsc->dbus_signal);
  404. for (i = 0; i < tmp_sig_dsc->args_num; i++) {
  405. os_free(tmp_sig_dsc->args[i].name);
  406. os_free(tmp_sig_dsc->args[i].type);
  407. }
  408. os_free(tmp_sig_dsc);
  409. }
  410. /* free properties */
  411. property_dsc = obj_dsc->properties;
  412. while (property_dsc) {
  413. tmp_prop_dsc = property_dsc;
  414. property_dsc = property_dsc->next;
  415. os_free(tmp_prop_dsc->dbus_interface);
  416. os_free(tmp_prop_dsc->dbus_property);
  417. os_free(tmp_prop_dsc->type);
  418. os_free(tmp_prop_dsc);
  419. }
  420. /* free handler's argument */
  421. if (obj_dsc->user_data_free_func)
  422. obj_dsc->user_data_free_func(obj_dsc->user_data);
  423. os_free(obj_dsc);
  424. }
  425. static void free_dbus_object_desc_cb(DBusConnection *connection, void *obj_dsc)
  426. {
  427. free_dbus_object_desc(obj_dsc);
  428. }
  429. /**
  430. * wpa_dbus_ctrl_iface_init - Initialize dbus control interface
  431. * @application_data: Pointer to application specific data structure
  432. * @dbus_path: DBus path to interface object
  433. * @dbus_service: DBus service name to register with
  434. * @messageHandler: a pointer to function which will handle dbus messages
  435. * coming on interface
  436. * Returns: 0 on success, -1 on failure
  437. *
  438. * Initialize the dbus control interface and start receiving commands from
  439. * external programs over the bus.
  440. */
  441. int wpa_dbus_ctrl_iface_init(struct wpas_dbus_priv *iface,
  442. char *dbus_path, char *dbus_service,
  443. struct wpa_dbus_object_desc *obj_desc)
  444. {
  445. DBusError error;
  446. int ret = -1;
  447. DBusObjectPathVTable wpa_vtable = {
  448. &free_dbus_object_desc_cb, &message_handler,
  449. NULL, NULL, NULL, NULL
  450. };
  451. obj_desc->connection = iface->con;
  452. /* Register the message handler for the global dbus interface */
  453. if (!dbus_connection_register_object_path(iface->con,
  454. dbus_path, &wpa_vtable,
  455. obj_desc)) {
  456. wpa_printf(MSG_ERROR, "dbus: Could not set up message "
  457. "handler");
  458. return -1;
  459. }
  460. /* Register our service with the message bus */
  461. dbus_error_init(&error);
  462. switch (dbus_bus_request_name(iface->con, dbus_service,
  463. 0, &error)) {
  464. case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
  465. ret = 0;
  466. break;
  467. case DBUS_REQUEST_NAME_REPLY_EXISTS:
  468. case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
  469. case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
  470. wpa_printf(MSG_ERROR, "dbus: Could not request service name: "
  471. "already registered");
  472. break;
  473. default:
  474. wpa_printf(MSG_ERROR, "dbus: Could not request service name: "
  475. "%s %s", error.name, error.message);
  476. break;
  477. }
  478. dbus_error_free(&error);
  479. if (ret != 0)
  480. return -1;
  481. wpa_printf(MSG_DEBUG, "Providing DBus service '%s'.", dbus_service);
  482. return 0;
  483. }
  484. /**
  485. * wpa_dbus_register_object_per_iface - Register a new object with dbus
  486. * @ctrl_iface: pointer to dbus private data
  487. * @path: DBus path to object
  488. * @ifname: interface name
  489. * @obj_desc: description of object's methods, signals and properties
  490. * Returns: 0 on success, -1 on error
  491. *
  492. * Registers a new interface with dbus and assigns it a dbus object path.
  493. */
  494. int wpa_dbus_register_object_per_iface(
  495. struct wpas_dbus_priv *ctrl_iface,
  496. const char *path, const char *ifname,
  497. struct wpa_dbus_object_desc *obj_desc)
  498. {
  499. DBusConnection *con;
  500. DBusObjectPathVTable vtable = {
  501. &free_dbus_object_desc_cb, &message_handler,
  502. NULL, NULL, NULL, NULL
  503. };
  504. /* Do nothing if the control interface is not turned on */
  505. if (ctrl_iface == NULL)
  506. return 0;
  507. con = ctrl_iface->con;
  508. obj_desc->connection = con;
  509. /* Register the message handler for the interface functions */
  510. if (!dbus_connection_register_object_path(con, path, &vtable,
  511. obj_desc)) {
  512. wpa_printf(MSG_ERROR, "dbus: Could not set up message "
  513. "handler for interface %s object %s", ifname, path);
  514. return -1;
  515. }
  516. return 0;
  517. }
  518. /**
  519. * wpa_dbus_unregister_object_per_iface - Unregisters DBus object
  520. * @ctrl_iface: Pointer to dbus private data
  521. * @path: DBus path to object which will be unregistered
  522. * Returns: Zero on success and -1 on failure
  523. *
  524. * Unregisters DBus object given by its path
  525. */
  526. int wpa_dbus_unregister_object_per_iface(
  527. struct wpas_dbus_priv *ctrl_iface, const char *path)
  528. {
  529. DBusConnection *con = ctrl_iface->con;
  530. if (!dbus_connection_unregister_object_path(con, path))
  531. return -1;
  532. return 0;
  533. }
  534. /**
  535. * wpa_dbus_method_register - Registers DBus method for given object
  536. * @obj_dsc: Object description for which a method will be registered
  537. * @dbus_interface: DBus interface under which method will be registered
  538. * @dbus_method: a name the method will be registered with
  539. * @method_handler: a function which will be called to handle this method call
  540. * @args: method arguments list
  541. * Returns: Zero on success and -1 on failure
  542. *
  543. * Registers DBus method under given name and interface for the object.
  544. * Method calls will be handled with given handling function.
  545. * Handler function is required to return a DBusMessage pointer which
  546. * will be response to method call. Any method call before being handled
  547. * must have registered appropriate handler by using this function.
  548. */
  549. int wpa_dbus_method_register(struct wpa_dbus_object_desc *obj_dsc,
  550. const char *dbus_interface,
  551. const char *dbus_method,
  552. WPADBusMethodHandler method_handler,
  553. const struct wpa_dbus_argument args[])
  554. {
  555. struct wpa_dbus_method_desc *method_dsc = obj_dsc->methods;
  556. struct wpa_dbus_method_desc *prev_desc;
  557. int args_num = 0;
  558. int i, error;
  559. prev_desc = NULL;
  560. while (method_dsc) {
  561. prev_desc = method_dsc;
  562. method_dsc = method_dsc->next;
  563. }
  564. /* count args */
  565. if (args) {
  566. while (args[args_num].name && args[args_num].type)
  567. args_num++;
  568. }
  569. method_dsc = os_zalloc(sizeof(struct wpa_dbus_method_desc) +
  570. args_num * sizeof(struct wpa_dbus_argument));
  571. if (!method_dsc)
  572. goto err;
  573. if (prev_desc == NULL)
  574. obj_dsc->methods = method_dsc;
  575. else
  576. prev_desc->next = method_dsc;
  577. /* copy interface name */
  578. method_dsc->dbus_interface = os_strdup(dbus_interface);
  579. if (!method_dsc->dbus_interface)
  580. goto err;
  581. /* copy method name */
  582. method_dsc->dbus_method = os_strdup(dbus_method);
  583. if (!method_dsc->dbus_method)
  584. goto err;
  585. /* copy arguments */
  586. error = 0;
  587. method_dsc->args_num = args_num;
  588. for (i = 0; i < args_num; i++) {
  589. method_dsc->args[i].name = os_strdup(args[i].name);
  590. if (!method_dsc->args[i].name) {
  591. error = 1;
  592. continue;
  593. }
  594. method_dsc->args[i].type = os_strdup(args[i].type);
  595. if (!method_dsc->args[i].type) {
  596. error = 1;
  597. continue;
  598. }
  599. method_dsc->args[i].dir = args[i].dir;
  600. }
  601. if (error)
  602. goto err;
  603. method_dsc->method_handler = method_handler;
  604. method_dsc->next = NULL;
  605. return 0;
  606. err:
  607. wpa_printf(MSG_WARNING, "Failed to register dbus method %s in "
  608. "interface %s", dbus_method, dbus_interface);
  609. if (method_dsc) {
  610. os_free(method_dsc->dbus_interface);
  611. os_free(method_dsc->dbus_method);
  612. for (i = 0; i < method_dsc->args_num; i++) {
  613. os_free(method_dsc->args[i].name);
  614. os_free(method_dsc->args[i].type);
  615. }
  616. if (prev_desc == NULL)
  617. obj_dsc->methods = NULL;
  618. else
  619. prev_desc->next = NULL;
  620. os_free(method_dsc);
  621. }
  622. return -1;
  623. }
  624. /**
  625. * wpa_dbus_signal_register - Registers DBus signal for given object
  626. * @obj_dsc: Object description for which a signal will be registered
  627. * @dbus_interface: DBus interface under which signal will be registered
  628. * @dbus_signal: a name the signal will be registered with
  629. * @args: signal arguments list
  630. * Returns: Zero on success and -1 on failure
  631. *
  632. * Registers DBus signal under given name and interface for the object.
  633. * Signal registration is NOT required in order to send signals, but not
  634. * registered signals will not be respected in introspection data
  635. * therefore it is highly recommended to register every signal before
  636. * using it.
  637. */
  638. int wpa_dbus_signal_register(struct wpa_dbus_object_desc *obj_dsc,
  639. const char *dbus_interface,
  640. const char *dbus_signal,
  641. const struct wpa_dbus_argument args[])
  642. {
  643. struct wpa_dbus_signal_desc *signal_dsc = obj_dsc->signals;
  644. struct wpa_dbus_signal_desc *prev_desc;
  645. int args_num = 0;
  646. int i, error = 0;
  647. prev_desc = NULL;
  648. while (signal_dsc) {
  649. prev_desc = signal_dsc;
  650. signal_dsc = signal_dsc->next;
  651. }
  652. /* count args */
  653. if (args) {
  654. while (args[args_num].name && args[args_num].type)
  655. args_num++;
  656. }
  657. signal_dsc = os_zalloc(sizeof(struct wpa_dbus_signal_desc) +
  658. args_num * sizeof(struct wpa_dbus_argument));
  659. if (!signal_dsc)
  660. goto err;
  661. if (prev_desc == NULL)
  662. obj_dsc->signals = signal_dsc;
  663. else
  664. prev_desc->next = signal_dsc;
  665. /* copy interface name */
  666. signal_dsc->dbus_interface = os_strdup(dbus_interface);
  667. if (!signal_dsc->dbus_interface)
  668. goto err;
  669. /* copy signal name */
  670. signal_dsc->dbus_signal = os_strdup(dbus_signal);
  671. if (!signal_dsc->dbus_signal)
  672. goto err;
  673. /* copy arguments */
  674. signal_dsc->args_num = args_num;
  675. for (i = 0; i < args_num; i++) {
  676. signal_dsc->args[i].name = os_strdup(args[i].name);
  677. if (!signal_dsc->args[i].name) {
  678. error = 1;
  679. continue;
  680. }
  681. signal_dsc->args[i].type = os_strdup(args[i].type);
  682. if (!signal_dsc->args[i].type) {
  683. error = 1;
  684. continue;
  685. }
  686. }
  687. if (error)
  688. goto err;
  689. signal_dsc->next = NULL;
  690. return 0;
  691. err:
  692. wpa_printf(MSG_WARNING, "Failed to register dbus signal %s in "
  693. "interface %s", dbus_signal, dbus_interface);
  694. if (signal_dsc) {
  695. os_free(signal_dsc->dbus_interface);
  696. os_free(signal_dsc->dbus_signal);
  697. for (i = 0; i < signal_dsc->args_num; i++) {
  698. os_free(signal_dsc->args[i].name);
  699. os_free(signal_dsc->args[i].type);
  700. }
  701. if (prev_desc == NULL)
  702. obj_dsc->signals = NULL;
  703. else
  704. prev_desc->next = NULL;
  705. os_free(signal_dsc);
  706. }
  707. return -1;
  708. }
  709. /**
  710. * wpa_dbus_property_register - Registers DBus property for given object
  711. * @obj_dsc: Object description for which a property will be registered
  712. * @dbus_interface: DBus interface under which method will be registered
  713. * @dbus_property: a name the property will be registered with
  714. * @type: a property type signature in form of DBus type description
  715. * @getter: a function called in order to get property value
  716. * @setter: a function called in order to set property value
  717. * @access: property access permissions specifier (R, W or RW)
  718. * Returns: Zero on success and -1 on failure
  719. *
  720. * Registers DBus property under given name and interface for the object.
  721. * Properties are set with giver setter function and get with getter.Getter
  722. * or setter are required to return DBusMessage which is response to Set/Get
  723. * method calls. Every property must be registered by this function before
  724. * being used.
  725. */
  726. int wpa_dbus_property_register(struct wpa_dbus_object_desc *obj_dsc,
  727. const char *dbus_interface,
  728. const char *dbus_property,
  729. const char *type,
  730. WPADBusPropertyAccessor getter,
  731. WPADBusPropertyAccessor setter,
  732. enum dbus_prop_access _access)
  733. {
  734. struct wpa_dbus_property_desc *property_dsc = obj_dsc->properties;
  735. struct wpa_dbus_property_desc *prev_desc;
  736. prev_desc = NULL;
  737. while (property_dsc) {
  738. prev_desc = property_dsc;
  739. property_dsc = property_dsc->next;
  740. }
  741. property_dsc = os_zalloc(sizeof(struct wpa_dbus_property_desc));
  742. if (!property_dsc)
  743. goto err;
  744. if (prev_desc == NULL)
  745. obj_dsc->properties = property_dsc;
  746. else
  747. prev_desc->next = property_dsc;
  748. /* copy interface name */
  749. property_dsc->dbus_interface = os_strdup(dbus_interface);
  750. if (!property_dsc->dbus_interface)
  751. goto err;
  752. /* copy property name */
  753. property_dsc->dbus_property = os_strdup(dbus_property);
  754. if (!property_dsc->dbus_property)
  755. goto err;
  756. /* copy property type */
  757. property_dsc->type = os_strdup(type);
  758. if (!property_dsc->type)
  759. goto err;
  760. property_dsc->getter = getter;
  761. property_dsc->setter = setter;
  762. property_dsc->access = _access;
  763. property_dsc->next = NULL;
  764. return 0;
  765. err:
  766. wpa_printf(MSG_WARNING, "Failed to register dbus property %s in "
  767. "interface %s", dbus_property, dbus_interface);
  768. if (property_dsc) {
  769. os_free(property_dsc->dbus_interface);
  770. os_free(property_dsc->dbus_property);
  771. os_free(property_dsc->type);
  772. if (prev_desc == NULL)
  773. obj_dsc->properties = NULL;
  774. else
  775. prev_desc->next = NULL;
  776. os_free(property_dsc);
  777. }
  778. return -1;
  779. }
  780. /**
  781. * wpas_dbus_signal_network_added - Send a property changed signal
  782. * @iface: dbus priv struct
  783. * @property_getter: propperty getter used to fetch new property value
  784. * @getter_arg: argument passed to property getter
  785. * @path: path to object which property has changed
  786. * @interface_name: signal and property interface
  787. * @property_name: name of property which has changed
  788. *
  789. * Notify listeners about changing value of some property. Signal
  790. * contains property name and its value fetched using given property
  791. * getter.
  792. */
  793. void wpa_dbus_signal_property_changed(struct wpas_dbus_priv *iface,
  794. WPADBusPropertyAccessor property_getter,
  795. void *getter_arg,
  796. const char *path,
  797. const char *interface_name,
  798. const char *property_name)
  799. {
  800. DBusConnection *connection;
  801. DBusMessage *_signal, *getter_reply;
  802. DBusMessageIter prop_iter, signal_iter, dict_iter, entry_iter;
  803. if (!iface)
  804. return;
  805. connection = iface->con;
  806. if (!property_getter) {
  807. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  808. "[dbus]: property getter not specified");
  809. return;
  810. }
  811. if (!path || !interface_name || !property_name) {
  812. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  813. "[dbus]: path interface of property not specified");
  814. return;
  815. }
  816. getter_reply = property_getter(NULL, getter_arg);
  817. if (!getter_reply ||
  818. dbus_message_get_type(getter_reply) == DBUS_MESSAGE_TYPE_ERROR) {
  819. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  820. "[dbus]: cannot get new value of property %s",
  821. property_name);
  822. return;
  823. }
  824. _signal = dbus_message_new_signal(path, interface_name,
  825. "PropertiesChanged");
  826. if (!_signal) {
  827. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  828. "[dbus]: cannot allocate signal");
  829. dbus_message_unref(getter_reply);
  830. return;
  831. }
  832. dbus_message_iter_init(getter_reply, &prop_iter);
  833. dbus_message_iter_init_append(_signal, &signal_iter);
  834. if (!dbus_message_iter_open_container(&signal_iter, DBUS_TYPE_ARRAY,
  835. "{sv}", &dict_iter)) {
  836. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  837. "[dbus]: out of memory. cannot open dictionary");
  838. goto err;
  839. }
  840. if (!dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_DICT_ENTRY,
  841. NULL, &entry_iter)) {
  842. wpa_printf(MSG_ERROR, "iwpa_dbus_signal_property_changed"
  843. "[dbus]: out of memory. cannot open dictionary "
  844. "element");
  845. goto err;
  846. }
  847. if (!dbus_message_iter_append_basic(&entry_iter, DBUS_TYPE_STRING,
  848. &property_name)) {
  849. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  850. "[dbus]: out of memory. cannot open add property "
  851. "name");
  852. goto err;
  853. }
  854. recursive_iter_copy(&prop_iter, &entry_iter);
  855. if (!dbus_message_iter_close_container(&dict_iter, &entry_iter)) {
  856. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  857. "[dbus]: out of memory. cannot close dictionary "
  858. "element");
  859. goto err;
  860. }
  861. if (!dbus_message_iter_close_container(&signal_iter, &dict_iter)) {
  862. wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
  863. "[dbus]: out of memory. cannot close dictionary");
  864. goto err;
  865. }
  866. dbus_connection_send(connection, _signal, NULL);
  867. err:
  868. dbus_message_unref(getter_reply);
  869. dbus_message_unref(_signal);
  870. }
  871. /**
  872. * wpa_dbus_get_object_properties - Put object's properties into dictionary
  873. * @iface: dbus priv struct
  874. * @path: path to DBus object which properties will be obtained
  875. * @interface: interface name which properties will be obtained
  876. * @dict_iter: correct, open DBus dictionary iterator.
  877. *
  878. * Iterates over all properties registered with object and execute getters
  879. * of those, which are readable and which interface matches interface
  880. * specified as argument. Obtained properties values are stored in
  881. * dict_iter dictionary.
  882. */
  883. void wpa_dbus_get_object_properties(struct wpas_dbus_priv *iface,
  884. const char *path, const char *interface,
  885. DBusMessageIter *dict_iter)
  886. {
  887. struct wpa_dbus_object_desc *obj_desc = NULL;
  888. dbus_connection_get_object_path_data(iface->con, path,
  889. (void **) &obj_desc);
  890. if (!obj_desc) {
  891. wpa_printf(MSG_ERROR, "dbus: wpa_dbus_get_object_properties: "
  892. "could not obtain object's private data: %s", path);
  893. return;
  894. }
  895. fill_dict_with_properties(dict_iter, obj_desc->properties,
  896. interface, obj_desc->user_data);
  897. }