]> git.ipfire.org Git - thirdparty/hostap.git/blame - wpa_supplicant/ctrl_iface_dbus_new_helpers.c
WPS ER: Only send Enrollee notification on Probe Request and M1
[thirdparty/hostap.git] / wpa_supplicant / ctrl_iface_dbus_new_helpers.c
CommitLineData
8fc2fb56
WS
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
16#include "includes.h"
17
18#include "common.h"
19#include "eloop.h"
20#include "ctrl_iface_dbus_new_helpers.h"
21
22/**
23 * struct wpa_dbus_method_desc - DBus method description
24 */
25struct wpa_dbus_method_desc {
26 /* pointer to next description in list */
27 struct wpa_dbus_method_desc *next;
28
29 /* method interface */
30 char *dbus_interface;
31 /* method name */
32 char *dbus_method;
33
34 /* method handling function */
35 WPADBusMethodHandler method_handler;
36 /* handler function argument */
37 void *handler_argument;
38 /* function used to free handler argument */
39 WPADBusArgumentFreeFunction argument_free_func;
40
41 /* number of method arguments */
42 int args_num;
43 /* array of arguments */
44 struct wpa_dbus_argument args[];
45};
46
47
48/**
49 * struct wpa_dbus_signal_desc - DBus signal description
50 */
51struct wpa_dbus_signal_desc {
52 /* pointer to next description in list */
53 struct wpa_dbus_signal_desc *next;
54
55 /* signal interface */
56 char *dbus_interface;
57 /* signal name */
58 char *dbus_signal;
59
60 /* number of signal arguments */
61 int args_num;
62 /* array of arguments */
63 struct wpa_dbus_argument args[0];
64};
65
66
67/**
68 * struct wpa_dbus_property_desc - DBus property description
69 */
70struct wpa_dbus_property_desc {
71 /* pointer to next description in list */
72 struct wpa_dbus_property_desc *next;
73
74 /* property interface */
75 char *dbus_interface;
76 /* property name */
77 char *dbus_property;
78 /* property type signature in DBus type notation */
79 char *type;
80
81 /* property access permissions */
82 enum dbus_prop_access access;
83
84 /* property getter function */
85 WPADBusPropertyAccessor getter;
86 /* property setter function */
87 WPADBusPropertyAccessor setter;
88 /* argument for getter and setter functions */
89 void *user_data;
90 /* function used to free accessors argument */
91 WPADBusArgumentFreeFunction user_data_free_func;
92};
93
94
95#ifdef CONFIG_CTRL_IFACE_DBUS_INTRO
96#include <libxml/tree.h>
97
98struct interfaces {
99 struct interfaces *next;
100 char *dbus_interface;
101 xmlNodePtr interface_node;
102};
103#endif /* CONFIG_CTRL_IFACE_DBUS_INTRO */
104
105static void process_watch(struct ctrl_iface_dbus_new_priv *iface,
106 DBusWatch *watch, eloop_event_type type)
107{
108 dbus_connection_ref(iface->con);
109
110 iface->should_dispatch = 0;
111
112 if (type == EVENT_TYPE_READ)
113 dbus_watch_handle(watch, DBUS_WATCH_READABLE);
114 else if (type == EVENT_TYPE_WRITE)
115 dbus_watch_handle(watch, DBUS_WATCH_WRITABLE);
116 else if (type == EVENT_TYPE_EXCEPTION)
117 dbus_watch_handle(watch, DBUS_WATCH_ERROR);
118
119 if (iface->should_dispatch) {
120 while (dbus_connection_get_dispatch_status(iface->con) ==
121 DBUS_DISPATCH_DATA_REMAINS)
122 dbus_connection_dispatch(iface->con);
123 iface->should_dispatch = 0;
124 }
125
126 dbus_connection_unref(iface->con);
127}
128
129
130static void process_watch_exception(int sock, void *eloop_ctx, void *sock_ctx)
131{
132 process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_EXCEPTION);
133}
134
135
136static void process_watch_read(int sock, void *eloop_ctx, void *sock_ctx)
137{
138 process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_READ);
139}
140
141
142static void process_watch_write(int sock, void *eloop_ctx, void *sock_ctx)
143{
144 process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_WRITE);
145}
146
147
148static void connection_setup_add_watch(struct ctrl_iface_dbus_new_priv *iface,
149 DBusWatch *watch)
150{
151 unsigned int flags;
152 int fd;
153
154 if (!dbus_watch_get_enabled(watch))
155 return;
156
157 flags = dbus_watch_get_flags(watch);
158 fd = dbus_watch_get_unix_fd(watch);
159
160 eloop_register_sock(fd, EVENT_TYPE_EXCEPTION, process_watch_exception,
161 iface, watch);
162
163 if (flags & DBUS_WATCH_READABLE) {
164 eloop_register_sock(fd, EVENT_TYPE_READ, process_watch_read,
165 iface, watch);
166 }
167 if (flags & DBUS_WATCH_WRITABLE) {
168 eloop_register_sock(fd, EVENT_TYPE_WRITE, process_watch_write,
169 iface, watch);
170 }
171
172 dbus_watch_set_data(watch, iface, NULL);
173}
174
175
176static void connection_setup_remove_watch(
177 struct ctrl_iface_dbus_new_priv *iface, DBusWatch *watch)
178{
179 unsigned int flags;
180 int fd;
181
182 flags = dbus_watch_get_flags(watch);
183 fd = dbus_watch_get_unix_fd(watch);
184
185 eloop_unregister_sock(fd, EVENT_TYPE_EXCEPTION);
186
187 if (flags & DBUS_WATCH_READABLE)
188 eloop_unregister_sock(fd, EVENT_TYPE_READ);
189 if (flags & DBUS_WATCH_WRITABLE)
190 eloop_unregister_sock(fd, EVENT_TYPE_WRITE);
191
192 dbus_watch_set_data(watch, NULL, NULL);
193}
194
195
196static dbus_bool_t add_watch(DBusWatch *watch, void *data)
197{
198 connection_setup_add_watch(data, watch);
199 return TRUE;
200}
201
202
203static void remove_watch(DBusWatch *watch, void *data)
204{
205 connection_setup_remove_watch(data, watch);
206}
207
208
209static void watch_toggled(DBusWatch *watch, void *data)
210{
211 if (dbus_watch_get_enabled(watch))
212 add_watch(watch, data);
213 else
214 remove_watch(watch, data);
215}
216
217
218static void process_timeout(void *eloop_ctx, void *sock_ctx)
219{
220 DBusTimeout *timeout = sock_ctx;
221
222 dbus_timeout_handle(timeout);
223}
224
225
226static void connection_setup_add_timeout(
227 struct ctrl_iface_dbus_new_priv *iface, DBusTimeout *timeout)
228{
229 if (!dbus_timeout_get_enabled(timeout))
230 return;
231
232 eloop_register_timeout(0, dbus_timeout_get_interval(timeout) * 1000,
233 process_timeout, iface, timeout);
234
235 dbus_timeout_set_data(timeout, iface, NULL);
236}
237
238
239static void connection_setup_remove_timeout(
240 struct ctrl_iface_dbus_new_priv *iface, DBusTimeout *timeout)
241{
242 eloop_cancel_timeout(process_timeout, iface, timeout);
243 dbus_timeout_set_data(timeout, NULL, NULL);
244}
245
246
247static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data)
248{
249 if (!dbus_timeout_get_enabled(timeout))
250 return TRUE;
251
252 connection_setup_add_timeout(data, timeout);
253
254 return TRUE;
255}
256
257
258static void remove_timeout(DBusTimeout *timeout, void *data)
259{
260 connection_setup_remove_timeout(data, timeout);
261}
262
263
264static void timeout_toggled(DBusTimeout *timeout, void *data)
265{
266 if (dbus_timeout_get_enabled(timeout))
267 add_timeout(timeout, data);
268 else
269 remove_timeout(timeout, data);
270}
271
272
273static void process_wakeup_main(int sig, void *eloop_ctx, void *signal_ctx)
274{
275 struct ctrl_iface_dbus_new_priv *iface = signal_ctx;
276
277 if (sig != SIGPOLL || !iface->con)
278 return;
279
280 if (dbus_connection_get_dispatch_status(iface->con) !=
281 DBUS_DISPATCH_DATA_REMAINS)
282 return;
283
284 /* Only dispatch once - we do not want to starve other events */
285 dbus_connection_ref(iface->con);
286 dbus_connection_dispatch(iface->con);
287 dbus_connection_unref(iface->con);
288}
289
290
291/**
292 * wakeup_main - Attempt to wake our mainloop up
293 * @data: dbus control interface private data
294 *
295 * Try to wake up the main eloop so it will process
296 * dbus events that may have happened.
297 */
298static void wakeup_main(void *data)
299{
300 struct ctrl_iface_dbus_new_priv *iface = data;
301
302 /* Use SIGPOLL to break out of the eloop select() */
303 raise(SIGPOLL);
304 iface->should_dispatch = 1;
305}
306
307
308/**
309 * connection_setup_wakeup_main - Tell dbus about our wakeup_main function
310 * @iface: dbus control interface private data
311 * Returns: 0 on success, -1 on failure
312 *
313 * Register our wakeup_main handler with dbus
314 */
315static int connection_setup_wakeup_main(struct ctrl_iface_dbus_new_priv *iface)
316{
317 if (eloop_register_signal(SIGPOLL, process_wakeup_main, iface))
318 return -1;
319
320 dbus_connection_set_wakeup_main_function(iface->con, wakeup_main,
321 iface, NULL);
322
323 return 0;
324}
325
326
327/**
328 * wpa_dbus_next_objid - Return next available object id
329 * @iface: dbus control interface private data
330 * Returns: Object id
331 */
332u32 wpa_dbus_next_objid(struct ctrl_iface_dbus_new_priv *iface)
333{
334 return iface->next_objid++;
335}
336
337
338/**
339 * integrate_with_eloop - Register our mainloop integration with dbus
340 * @connection: connection to the system message bus
341 * @iface: a dbus control interface data structure
342 * Returns: 0 on success, -1 on failure
343 *
344 * We register our mainloop integration functions with dbus here.
345 */
346static int integrate_with_eloop(DBusConnection *connection,
347 struct ctrl_iface_dbus_new_priv *iface)
348{
349 if (!dbus_connection_set_watch_functions(connection, add_watch,
350 remove_watch, watch_toggled,
351 iface, NULL)) {
352 perror("dbus_connection_set_watch_functions[dbus]");
353 wpa_printf(MSG_ERROR, "Not enough memory to set up dbus.");
354 return -1;
355 }
356
357 if (!dbus_connection_set_timeout_functions(connection, add_timeout,
358 remove_timeout,
359 timeout_toggled, iface,
360 NULL)) {
361 perror("dbus_connection_set_timeout_functions[dbus]");
362 wpa_printf(MSG_ERROR, "Not enough memory to set up dbus.");
363 return -1;
364 }
365
366 if (connection_setup_wakeup_main(iface) < 0) {
367 perror("connection_setup_wakeup_main[dbus]");
368 wpa_printf(MSG_ERROR, "Could not setup main wakeup function.");
369 return -1;
370 }
371
372 return 0;
373}
374
375
376/**
377 * dispatch_initial_dbus_messages - Dispatch initial dbus messages after
378 * claiming bus name
379 * @eloop_ctx: the DBusConnection to dispatch on
380 * @timeout_ctx: unused
381 *
382 * If clients are quick to notice that service claimed its bus name,
383 * there may have been messages that came in before initialization was
384 * all finished. Dispatch those here.
385 */
386static void dispatch_initial_dbus_messages(void *eloop_ctx, void *timeout_ctx)
387{
388 DBusConnection *con = eloop_ctx;
389
390 while (dbus_connection_get_dispatch_status(con) ==
391 DBUS_DISPATCH_DATA_REMAINS)
392 dbus_connection_dispatch(con);
393}
394
395
396#ifdef CONFIG_CTRL_IFACE_DBUS_INTRO
397
398/**
399 * extract_interfaces - Extract interfaces from methods, signals and props
400 * @obj_dsc: Description of object from which interfaces will be extracted
401 * @root_node: root node of XML introspection document
402 * Returns: List of interfaces found in object description
403 *
404 * Iterates over all methods, signals and properties registered with
405 * object and collects all declared DBus interfaces and create interface's
406 * node in XML root node for each. Returned list elements contains interface
407 * name and XML node of corresponding interface.
408 */
409static struct interfaces * extract_interfaces(
410 struct wpa_dbus_object_desc *obj_dsc, xmlNodePtr root_node)
411{
412 struct wpa_dbus_method_desc *method_dsc = obj_dsc->methods;
413 struct wpa_dbus_signal_desc *signal_dsc = obj_dsc->signals;
414 struct wpa_dbus_property_desc *property_dsc = obj_dsc->properties;
415 struct interfaces *head = NULL;
416 struct interfaces *iface, *last;
417 int len;
418
419 /* extract interfaces from methods */
420 while (method_dsc) {
421 iface = head;
422 last = NULL;
423
424 /* go to next method if its interface is already extracted */
425 while (iface) {
426 if (!os_strcmp(iface->dbus_interface,
427 method_dsc->dbus_interface))
428 break;
429 last = iface;
430 iface = iface->next;
431 }
432 if (iface) {
433 method_dsc = method_dsc->next;
434 continue;
435 }
436
437 iface = os_zalloc(sizeof(struct interfaces));
438 if (!iface) {
439 wpa_printf(MSG_ERROR, "Not enough memory to create "
440 "interface introspection data");
441 method_dsc = method_dsc->next;
442 continue;
443 }
444
445 if (last)
446 last->next = iface;
447 else
448 head = iface;
449
450 len = os_strlen(method_dsc->dbus_interface) + 1;
451 iface->dbus_interface = os_malloc(len);
452 if (!iface->dbus_interface) {
453 wpa_printf(MSG_ERROR, "Not enough memory to create "
454 "interface introspection data (interface "
455 "name)");
456 method_dsc = method_dsc->next;
457 continue;
458 }
459 os_strncpy(iface->dbus_interface, method_dsc->dbus_interface,
460 len);
461
462 iface->interface_node = xmlNewChild(root_node, NULL,
463 BAD_CAST "interface",
464 NULL);
465 xmlNewProp(iface->interface_node, BAD_CAST "name",
466 BAD_CAST method_dsc->dbus_interface);
467
468 method_dsc = method_dsc->next;
469 }
470
471 /* extract interfaces from signals */
472 while (signal_dsc) {
473 iface = head;
474 last = NULL;
475
476 /* go to next signal if its interface is already extracted */
477 while (iface) {
478 if (!os_strcmp(iface->dbus_interface,
479 signal_dsc->dbus_interface))
480 break;
481 last = iface;
482 iface = iface->next;
483 }
484 if (iface) {
485 signal_dsc = signal_dsc->next;
486 continue;
487 }
488
489 iface = os_zalloc(sizeof(struct interfaces));
490 if (!iface) {
491 wpa_printf(MSG_ERROR, "Not enough memory to create "
492 "interface introspection data");
493 signal_dsc = signal_dsc->next;
494 continue;
495 }
496
497 if (last)
498 last->next = iface;
499 else
500 head = iface;
501
502 len = os_strlen(signal_dsc->dbus_interface) + 1;
503 iface->dbus_interface = os_malloc(len);
504 if (!iface->dbus_interface) {
505 wpa_printf(MSG_ERROR, "Not enough memory to create "
506 "interface introspection data (interface "
507 "name)");
508 signal_dsc = signal_dsc->next;
509 continue;
510 }
511 os_strncpy(iface->dbus_interface, signal_dsc->dbus_interface,
512 len);
513
514 iface->interface_node = xmlNewChild(root_node, NULL,
515 BAD_CAST "interface",
516 NULL);
517 xmlNewProp(iface->interface_node, BAD_CAST "name",
518 BAD_CAST signal_dsc->dbus_interface);
519
520 signal_dsc = signal_dsc->next;
521 }
522
523 /* extract interfaces from properties */
524 while (property_dsc) {
525 iface = head;
526 last = NULL;
527
528 /* go to next property if its interface is already extracted */
529 while (iface) {
530 if (!os_strcmp(iface->dbus_interface,
531 property_dsc->dbus_interface))
532 break;
533 last = iface;
534 iface = iface->next;
535 }
536 if (iface) {
537 property_dsc = property_dsc->next;
538 continue;
539 }
540
541 iface = os_zalloc(sizeof(struct interfaces));
542 if (!iface) {
543 wpa_printf(MSG_ERROR, "Not enough memory to create "
544 "interface introspection data");
545 property_dsc = property_dsc->next;
546 continue;
547 }
548
549 if (last)
550 last->next = iface;
551 else
552 head = iface;
553
554 len = os_strlen(property_dsc->dbus_interface) + 1;
555 iface->dbus_interface = os_malloc(len);
556 if (!iface->dbus_interface) {
557 wpa_printf(MSG_ERROR, "Not enough memory to create "
558 "interface introspection data (interface "
559 "name)");
560 property_dsc = property_dsc->next;
561 continue;
562 }
563 os_strncpy(iface->dbus_interface, property_dsc->dbus_interface,
564 len);
565
566 iface->interface_node = xmlNewChild(root_node, NULL,
567 BAD_CAST "interface",
568 NULL);
569 xmlNewProp(iface->interface_node, BAD_CAST "name",
570 BAD_CAST property_dsc->dbus_interface);
571
572 property_dsc = property_dsc->next;
573 }
574
575 return head;
576}
577
578
579/**
580 * introspect - Responds for Introspect calls on object
581 * @message: Message with Introspect call
582 * @obj_dsc: Object description on which Introspect was called
583 * Returns: Message with introspection result XML string as only argument
584 *
585 * Iterates over all methods, signals and properties registered with
586 * object and generates introspection data for the object as XML string.
587 */
588static DBusMessage * introspect(DBusMessage *message,
589 struct wpa_dbus_object_desc *obj_dsc)
590{
591
592 DBusMessage *reply = NULL;
593 struct interfaces *ifaces, *tmp;
594 struct wpa_dbus_signal_desc *signal_dsc;
595 struct wpa_dbus_method_desc *method_dsc;
596 struct wpa_dbus_property_desc *property_dsc;
ea20a1ad 597 xmlChar *intro_str;
8fc2fb56
WS
598 char **children;
599 int i, s;
600
601 xmlDocPtr doc = NULL;
602 xmlNodePtr root_node = NULL, node = NULL, iface_node = NULL;
603 xmlNodePtr method_node = NULL, signal_node = NULL;
604 xmlNodePtr property_node = NULL, arg_node = NULL;
605
606 /* Create and initialize the return message */
607 reply = dbus_message_new_method_return(message);
608
609 /* root node and dtd */
610 doc = xmlNewDoc(BAD_CAST "1.0");
611 root_node = xmlNewNode(NULL, BAD_CAST "node");
612 xmlDocSetRootElement(doc, root_node);
613 xmlCreateIntSubset(doc, BAD_CAST "node",
614 BAD_CAST DBUS_INTROSPECT_1_0_XML_PUBLIC_IDENTIFIER,
615 BAD_CAST DBUS_INTROSPECT_1_0_XML_SYSTEM_IDENTIFIER);
616
617 /* Add Introspectable interface */
618 iface_node = xmlNewChild(root_node, NULL, BAD_CAST "interface", NULL);
619 xmlNewProp(iface_node, BAD_CAST "name",
620 BAD_CAST WPA_DBUS_INTROSPECTION_INTERFACE);
621
622 /* Add Introspect method */
623 method_node = xmlNewChild(iface_node, NULL, BAD_CAST "method", NULL);
624 xmlNewProp(method_node, BAD_CAST "name",
625 BAD_CAST WPA_DBUS_INTROSPECTION_METHOD);
626 arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
627 xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "data");
628 xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
629 xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "out");
630
631
632 /* Add Properties interface */
633 iface_node = xmlNewChild(root_node, NULL,
634 BAD_CAST "interface", NULL);
635 xmlNewProp(iface_node, BAD_CAST "name",
636 BAD_CAST WPA_DBUS_PROPERTIES_INTERFACE);
637
638 /* Add Get method */
639 method_node = xmlNewChild(iface_node, NULL, BAD_CAST "method", NULL);
640 xmlNewProp(method_node, BAD_CAST "name",
641 BAD_CAST WPA_DBUS_PROPERTIES_GET);
642 arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
643 xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "interface");
644 xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
645 xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
646 arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
647 xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "propname");
648 xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
649 xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
650 arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
651 xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "value");
652 xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "v");
653 xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "out");
654 method_node = xmlNewChild(iface_node, NULL, BAD_CAST "method", NULL);
655
656 /* Add GetAll method */
657 xmlNewProp(method_node, BAD_CAST "name",
658 BAD_CAST WPA_DBUS_PROPERTIES_GETALL);
659 arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
660 xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "interface");
661 xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
662 xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
663 arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
664 xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "props");
665 xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "a{sv}");
666 xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "out");
667 method_node = xmlNewChild(iface_node, NULL, BAD_CAST "method", NULL);
668
669 /* Add Set method */
670 xmlNewProp(method_node, BAD_CAST "name",
671 BAD_CAST WPA_DBUS_PROPERTIES_SET);
672 arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
673 xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "interface");
674 xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
675 xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
676 arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
677 xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "propname");
678 xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
679 xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
680 arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
681 xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "value");
682 xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "v");
683 xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
684
685 /* get all interfaces registered with object */
686 ifaces = extract_interfaces(obj_dsc, root_node);
687
688 /* create methods' nodes */
689 method_dsc = obj_dsc->methods;
690 while (method_dsc) {
691
692 struct interfaces *iface = ifaces;
693 while (iface) {
694 if (!os_strcmp(iface->dbus_interface,
695 method_dsc->dbus_interface))
696 break;
697 iface = iface->next;
698 }
699 if (!iface)
700 continue;
701
702 iface_node = iface->interface_node;
703 method_node = xmlNewChild(iface_node, NULL, BAD_CAST "method",
704 NULL);
705 xmlNewProp(method_node, BAD_CAST "name",
706 BAD_CAST method_dsc->dbus_method);
707
708 /* create args' nodes */
709 for (i = 0; i < method_dsc->args_num; i++) {
710 struct wpa_dbus_argument arg = method_dsc->args[i];
711 arg_node = xmlNewChild(method_node, NULL,
712 BAD_CAST "arg", NULL);
713 if (arg.name && strlen(arg.name)) {
714 xmlNewProp(arg_node, BAD_CAST "name",
715 BAD_CAST arg.name);
716 }
717 xmlNewProp(arg_node, BAD_CAST "type",
718 BAD_CAST arg.type);
719 xmlNewProp(arg_node, BAD_CAST "direction",
720 BAD_CAST (arg.dir == ARG_IN ?
721 "in" : "out"));
722 }
723 method_dsc = method_dsc->next;
724 }
725
726 /* create signals' nodes */
727 signal_dsc = obj_dsc->signals;
728 while (signal_dsc) {
729
730 struct interfaces *iface = ifaces;
731 while (iface) {
732 if (!os_strcmp(iface->dbus_interface,
733 signal_dsc->dbus_interface))
734 break;
735 iface = iface->next;
736 }
737 if (!iface)
738 continue;
739
740 iface_node = iface->interface_node;
741 signal_node = xmlNewChild(iface_node, NULL, BAD_CAST "signal",
742 NULL);
743 xmlNewProp(signal_node, BAD_CAST "name",
744 BAD_CAST signal_dsc->dbus_signal);
745
746 /* create args' nodes */
747 for (i = 0; i < signal_dsc->args_num; i++) {
748 struct wpa_dbus_argument arg = signal_dsc->args[i];
749 arg_node = xmlNewChild(signal_node, NULL,
750 BAD_CAST "arg", NULL);
751 if (arg.name && strlen(arg.name)) {
752 xmlNewProp(arg_node, BAD_CAST "name",
753 BAD_CAST arg.name);
754 }
755 xmlNewProp(arg_node, BAD_CAST "type",
756 BAD_CAST arg.type);
757 }
758 signal_dsc = signal_dsc->next;
759 }
760
761 /* create properties' nodes */
762 property_dsc = obj_dsc->properties;
763 while (property_dsc) {
764
765 struct interfaces *iface = ifaces;
766 while (iface) {
767 if (!os_strcmp(iface->dbus_interface,
768 property_dsc->dbus_interface))
769 break;
770 iface = iface->next;
771 }
772 if (!iface)
773 continue;
774
775 iface_node = iface->interface_node;
776 property_node = xmlNewChild(iface_node, NULL,
777 BAD_CAST "property", NULL);
778 xmlNewProp(property_node, BAD_CAST "name",
779 BAD_CAST property_dsc->dbus_property);
780 xmlNewProp(property_node, BAD_CAST "type",
781 BAD_CAST property_dsc->type);
782 xmlNewProp(property_node, BAD_CAST "access", BAD_CAST
783 (property_dsc->access == R ? "read" :
784 (property_dsc->access == W ?
785 "write" : "readwrite")));
786
787 property_dsc = property_dsc->next;
788 }
789
790 /* add child nodes to introspection tree; */
791 dbus_connection_list_registered(obj_dsc->connection,
792 dbus_message_get_path(message),
793 &children);
794 for (i = 0; children[i]; i++) {
795 node = xmlNewChild(root_node, NULL, BAD_CAST "node", NULL);
796 xmlNewProp(node, BAD_CAST "name", BAD_CAST children[i]);
797 }
798 dbus_free_string_array(children);
799
800
ea20a1ad 801 xmlDocDumpFormatMemory(doc, &intro_str, &s, 1);
8fc2fb56
WS
802
803 xmlFreeDoc(doc);
804
805 while (ifaces) {
806 tmp = ifaces;
807 ifaces = ifaces->next;
808 os_free(tmp->dbus_interface);
809 os_free(tmp);
810 }
811
812 dbus_message_append_args(reply, DBUS_TYPE_STRING, &intro_str,
813 DBUS_TYPE_INVALID);
814
815 xmlFree(intro_str);
816
817 return reply;
818}
819
820#else /* CONFIG_CTRL_IFACE_DBUS_INTRO */
821
822/**
823 * introspect - Responds for Introspect calls on object
824 * @message: Message with Introspect call
825 * @obj_dsc: Object description on which Introspect was called
826 * Returns: Message with introspection result XML string as only argument
827 *
828 * Returns error informing that introspection support was not compiled.
829 */
830static DBusMessage * introspect(DBusMessage *message,
831 struct wpa_dbus_object_desc *obj_dsc)
832{
833 return dbus_message_new_error(message, DBUS_ERROR_UNKNOWN_METHOD,
834 "wpa_supplicant was compiled without "
835 "introspection support.");
836}
837
838#endif /* CONFIG_CTRL_IFACE_DBUS_INTRO */
839
840
841/**
842 * recursive_iter_copy - Reads arguments from one iterator and
843 * writes to another recursively
844 * @from: iterator to read from
845 * @to: iterator to write to
846 *
847 * Copies one iterator's elements to another. If any element in
848 * iterator is of container type, its content is copied recursively
849 */
850static void recursive_iter_copy(DBusMessageIter *from, DBusMessageIter *to)
851{
852
853 char *subtype = NULL;
854 int type;
855
856 /* iterate over iterator to copy */
857 while ((type = dbus_message_iter_get_arg_type (from)) !=
858 DBUS_TYPE_INVALID) {
859
860 /* simply copy basic type entries */
861 if (dbus_type_is_basic(type)) {
862 if (dbus_type_is_fixed(type)) {
863 /*
864 * According to DBus documentation all
865 * fixed-length types are guaranteed to fit
866 * 8 bytes
867 */
868 dbus_uint64_t v;
869 dbus_message_iter_get_basic (from, &v);
870 dbus_message_iter_append_basic (to, type, &v);
871 } else {
872 char *v;
873 dbus_message_iter_get_basic (from, &v);
874 dbus_message_iter_append_basic (to, type, &v);
875 }
876 } else {
877 /* recursively copy container type entries */
878 DBusMessageIter write_subiter, read_subiter;
879
880 dbus_message_iter_recurse(from, &read_subiter);
881
882 if (type == DBUS_TYPE_VARIANT ||
883 type == DBUS_TYPE_ARRAY) {
884 subtype = dbus_message_iter_get_signature(
885 &read_subiter);
886 }
887
888 dbus_message_iter_open_container(to, type, subtype,
889 &write_subiter);
890
891 recursive_iter_copy(&read_subiter, &write_subiter);
892
893 dbus_message_iter_close_container(to, &write_subiter);
894 if (subtype)
895 dbus_free(subtype);
896 }
897
898 dbus_message_iter_next(from);
899 }
900}
901
902
903/**
904 * get_all_properties - Responds for GetAll properties calls on object
905 * @message: Message with GetAll call
906 * @interface: interface name which properties will be returned
907 * @property_dsc: list of object's properties
908 * Returns: Message with dict of variants as argument with properties values
909 *
910 * Iterates over all properties registered with object and execute getters
911 * of those, which are readable and which interface matches interface
912 * specified as argument. Returned message contains one dict argument
913 * with properties names as keys and theirs values as values.
914 */
915static DBusMessage * get_all_properties(
916 DBusMessage *message, char *interface,
917 struct wpa_dbus_property_desc *property_dsc)
918{
919 /* Create and initialize the return message */
920 DBusMessage *reply = dbus_message_new_method_return(message);
921 DBusMessage *getterReply = NULL;
922 DBusMessageIter iter, dict_iter, entry_iter, ret_iter;
923 int counter = 0;
924
925 dbus_message_iter_init_append(reply, &iter);
926
927 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
928 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
929 DBUS_TYPE_STRING_AS_STRING
930 DBUS_TYPE_VARIANT_AS_STRING
931 DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
932 &dict_iter);
933
934 while (property_dsc) {
935 if (!os_strncmp(property_dsc->dbus_interface, interface,
936 WPAS_DBUS_INTERFACE_MAX) &&
937 property_dsc->access != W && property_dsc->getter) {
938
939 getterReply = property_dsc->getter(
940 message, property_dsc->user_data);
941 dbus_message_iter_init(getterReply, &ret_iter);
942
943 dbus_message_iter_open_container(&dict_iter,
944 DBUS_TYPE_DICT_ENTRY,
945 NULL, &entry_iter);
946 dbus_message_iter_append_basic(
947 &entry_iter, DBUS_TYPE_STRING,
948 &(property_dsc->dbus_property));
949
950 recursive_iter_copy(&ret_iter, &entry_iter);
951
952 dbus_message_iter_close_container(&dict_iter,
953 &entry_iter);
954 dbus_message_unref(getterReply);
955 counter++;
956 }
957 property_dsc = property_dsc->next;
958 }
959 dbus_message_iter_close_container(&iter, &dict_iter);
960
961 if (counter == 0) {
962 dbus_message_unref(reply);
963 reply = dbus_message_new_error(message,
964 DBUS_ERROR_INVALID_ARGS,
965 "No readable properties in "
966 "this interface");
967 }
968
969 return reply;
970}
971
972
68e7cb49 973static int is_signature_correct(DBusMessage *message,
8fc2fb56
WS
974 struct wpa_dbus_method_desc *method_dsc)
975{
976 /* According to DBus documentation max length of signature is 255 */
68e7cb49
JM
977#define MAX_SIG_LEN 256
978 char registered_sig[MAX_SIG_LEN], *pos;
8fc2fb56 979 const char *sig = dbus_message_get_signature(message);
68e7cb49 980 int i, ret;
8fc2fb56 981
68e7cb49
JM
982 pos = registered_sig;
983 *pos = '\0';
8fc2fb56
WS
984
985 for (i = 0; i < method_dsc->args_num; i++) {
986 struct wpa_dbus_argument arg = method_dsc->args[i];
68e7cb49
JM
987 if (arg.dir == ARG_IN) {
988 size_t blen = registered_sig + MAX_SIG_LEN - pos;
989 ret = os_snprintf(pos, blen, "%s", arg.type);
990 if (ret < 0 || (size_t) ret >= blen)
991 return 0;
992 pos += ret;
993 }
8fc2fb56
WS
994 }
995
996 return !os_strncmp(registered_sig, sig, MAX_SIG_LEN);
997}
998
999
1000/**
1001 * message_handler - Handles incoming DBus messages
1002 * @connection: DBus connection on which message was received
1003 * @message: Received message
1004 * @user_data: pointer to description of object to which message was sent
1005 * Returns: Returns information whether message was handled or not
1006 *
1007 * Reads message interface and method name, then checks if they matches one
1008 * of the special cases i.e. introspection call or properties get/getall/set
1009 * methods and handles it. Else it iterates over registered methods list
1010 * and tries to match method's name and interface to those read from message
1011 * If appropriate method was found it's handler function is called and
1012 * response is sent. Otherwise the DBUS_ERROR_UNKNOWN_METHOD error message
1013 * will be sent.
1014 */
1015static DBusHandlerResult message_handler(DBusConnection *connection,
1016 DBusMessage *message, void *user_data)
1017{
1018 struct wpa_dbus_object_desc *obj_dsc = user_data;
1019 const char *method;
1020 const char *path;
1021 const char *msg_interface;
1022
1023#define MESSAGE_UNHANDLED (DBusMessage *) 1
1024
1025 DBusMessage *reply = MESSAGE_UNHANDLED;
1026
1027 /* get method, interface and path the message is addressed to */
1028 method = dbus_message_get_member(message);
1029 path = dbus_message_get_path(message);
1030 msg_interface = dbus_message_get_interface(message);
1031 if (!method || !path || !msg_interface)
1032 goto out;
1033
1034 /* if message is introspection method call */
1035 if (!os_strncmp(WPA_DBUS_INTROSPECTION_METHOD, method,
1036 WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) &&
1037 !os_strncmp(WPA_DBUS_INTROSPECTION_INTERFACE, msg_interface,
1038 WPAS_DBUS_INTERFACE_MAX))
1039 reply = introspect(message, obj_dsc);
1040 else if (!strncmp(WPA_DBUS_PROPERTIES_INTERFACE, msg_interface,
1041 WPAS_DBUS_INTERFACE_MAX)) {
1042 /* if message is properties method call */
1043 DBusMessageIter iter;
1044 char *interface;
1045 char *property;
1046
1047 dbus_message_iter_init(message, &iter);
1048
1049 if (!os_strncmp(WPA_DBUS_PROPERTIES_GET, method,
1050 WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) ||
1051 !os_strncmp(WPA_DBUS_PROPERTIES_SET, method,
1052 WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) ||
1053 !os_strncmp(WPA_DBUS_PROPERTIES_GETALL, method,
1054 WPAS_DBUS_METHOD_SIGNAL_PROP_MAX)) {
1055 /* First argument: interface name (DBUS_TYPE_STRING) */
1056 if (dbus_message_iter_get_arg_type(&iter) !=
1057 DBUS_TYPE_STRING) {
1058 reply = dbus_message_new_error(
1059 message, DBUS_ERROR_INVALID_ARGS,
1060 NULL);
1061 goto out;
1062 }
1063
1064 dbus_message_iter_get_basic(&iter, &interface);
1065
1066 /* GetAll */
1067 if (!os_strncmp(WPA_DBUS_PROPERTIES_GETALL, method,
1068 WPAS_DBUS_METHOD_SIGNAL_PROP_MAX)) {
1069 if (os_strcmp(dbus_message_get_signature(
1070 message), "s"))
1071 reply = dbus_message_new_error(
1072 message,
1073 DBUS_ERROR_INVALID_ARGS, NULL);
1074 else
1075 reply = get_all_properties(
1076 message, interface,
1077 obj_dsc->properties);
1078 } else {
1079 /* Get or Set */
1080 struct wpa_dbus_property_desc *property_dsc;
1081 property_dsc = obj_dsc->properties;
1082
1083 /* Second argument: property name
1084 * (DBUS_TYPE_STRING) */
1085 if (!dbus_message_iter_next(&iter) ||
1086 dbus_message_iter_get_arg_type(&iter) !=
1087 DBUS_TYPE_STRING) {
1088 reply = dbus_message_new_error(
1089 message,
1090 DBUS_ERROR_INVALID_ARGS, NULL);
1091 goto out;
1092 }
1093 dbus_message_iter_get_basic(&iter, &property);
1094
1095 while (property_dsc) {
1096 /* compare property names and
1097 * interfaces */
1098 if (!os_strncmp(property_dsc->dbus_property,
1099 property,
1100 WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) &&
1101 !os_strncmp(property_dsc->dbus_interface, interface,
1102 WPAS_DBUS_INTERFACE_MAX))
1103 break;
1104
1105 property_dsc = property_dsc->next;
1106 }
1107 if (property_dsc) {
1108 /* Get */
1109 if (!os_strncmp(WPA_DBUS_PROPERTIES_GET, method,
1110 WPAS_DBUS_METHOD_SIGNAL_PROP_MAX)) {
1111 if (os_strcmp(dbus_message_get_signature(message), "ss"))
1112 reply = dbus_message_new_error(message,
1113 DBUS_ERROR_INVALID_ARGS, NULL);
1114 else if (property_dsc->access != W &&
1115 property_dsc->getter)
1116 reply = property_dsc->getter(message,
1117 property_dsc->user_data);
1118 else
1119 reply = dbus_message_new_error(message,
1120 DBUS_ERROR_INVALID_ARGS,
1121 "Property is write-only");
1122 } else {
1123 /* Set */
1124 if (os_strcmp(dbus_message_get_signature(message), "ssv"))
1125 reply = dbus_message_new_error(message,
1126 DBUS_ERROR_INVALID_ARGS, NULL);
1127 else if (property_dsc->access != R &&
1128 property_dsc->setter) {
1129 reply = property_dsc->setter
1130 (message, property_dsc->user_data);
1131 } else {
1132 reply = dbus_message_new_error(message,
1133 DBUS_ERROR_INVALID_ARGS,
1134 "Property is read-only");
1135 }
1136 }
1137 } else {
1138 wpa_printf(MSG_DEBUG, "no property handler for %s.%s\n"
1139 "on %s", interface, property, path);
1140 reply = dbus_message_new_error(message,
1141 DBUS_ERROR_INVALID_ARGS,
1142 "No such property");
1143 }
1144 }
1145 } else {
1146 reply = dbus_message_new_error(
1147 message, DBUS_ERROR_UNKNOWN_METHOD, NULL);
1148 goto out;
1149 }
1150 } else {
1151 struct wpa_dbus_method_desc *method_dsc = obj_dsc->methods;
1152
1153 /* try match call to any registered method */
1154 while (method_dsc) {
1155 /* compare method names and interfaces */
1156 if (!os_strncmp(method_dsc->dbus_method, method,
1157 WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) &&
1158 !os_strncmp(method_dsc->dbus_interface,
1159 msg_interface,
1160 WPAS_DBUS_INTERFACE_MAX))
1161 break;
1162
1163 method_dsc = method_dsc->next;
1164 }
1165 if (method_dsc) {
1166 if (is_signature_correct(message, method_dsc)) {
1167 reply = method_dsc->method_handler(
1168 message, method_dsc->handler_argument);
1169 } else {
1170 reply = dbus_message_new_error(
1171 message, DBUS_ERROR_INVALID_ARGS,
1172 NULL);
1173 }
1174 } else {
1175 wpa_printf(MSG_DEBUG, "no method handler for %s.%s "
1176 "on %s", msg_interface, method, path);
1177 reply = dbus_message_new_error(
1178 message, DBUS_ERROR_UNKNOWN_METHOD, NULL);
1179 }
1180 }
1181
1182out:
1183 /* If the message was handled, send back the reply */
1184 if (reply != MESSAGE_UNHANDLED) {
1185 /* If handler succeed returning NULL, reply empty message */
1186 if (!reply)
1187 reply = dbus_message_new_method_return(message);
1188 if (reply) {
1189 if (!dbus_message_get_no_reply(message))
1190 dbus_connection_send(connection, reply, NULL);
1191 dbus_message_unref(reply);
1192 }
1193 return DBUS_HANDLER_RESULT_HANDLED;
1194 } else
1195 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1196}
1197
1198
1199/**
1200 * free_dbus_object_desc - Frees object description data structure
1201 * @connection: DBus connection
1202 * @obj_dsc: Object description to free
1203 *
1204 * Frees each of properties, methods and signals description lists and
1205 * the object description structure itself.
1206 */
1207void free_dbus_object_desc(struct wpa_dbus_object_desc *obj_dsc)
1208{
1209 struct wpa_dbus_method_desc *method_dsc, *tmp_met_dsc;
1210 struct wpa_dbus_signal_desc *signal_dsc, *tmp_sig_dsc;
1211 struct wpa_dbus_property_desc *property_dsc, *tmp_prop_dsc;
1212 int i;
1213
1214 if (!obj_dsc)
1215 return;
1216
1217 /* free methods */
1218 method_dsc = obj_dsc->methods;
1219
1220 while (method_dsc) {
1221 tmp_met_dsc = method_dsc;
1222 method_dsc = method_dsc->next;
1223
1224 os_free(tmp_met_dsc->dbus_interface);
1225 os_free(tmp_met_dsc->dbus_method);
1226
1227 for (i = 0; i < tmp_met_dsc->args_num; i++) {
1228 os_free(tmp_met_dsc->args[i].name);
1229 os_free(tmp_met_dsc->args[i].type);
1230 }
1231
1232 if (tmp_met_dsc->argument_free_func)
1233 tmp_met_dsc->argument_free_func(
1234 tmp_met_dsc->handler_argument);
1235
1236 os_free(tmp_met_dsc);
1237 }
1238
1239 /* free signals */
1240 signal_dsc = obj_dsc->signals;
1241
1242 while (signal_dsc) {
1243 tmp_sig_dsc = signal_dsc;
1244 signal_dsc = signal_dsc->next;
1245
1246 os_free(tmp_sig_dsc->dbus_interface);
1247 os_free(tmp_sig_dsc->dbus_signal);
1248
1249 for (i = 0; i < tmp_sig_dsc->args_num; i++) {
1250 os_free(tmp_sig_dsc->args[i].name);
1251 os_free(tmp_sig_dsc->args[i].type);
1252 }
1253
1254 os_free(tmp_sig_dsc);
1255 }
1256
1257 /* free properties */
1258 property_dsc = obj_dsc->properties;
1259
1260 while (property_dsc) {
1261 tmp_prop_dsc = property_dsc;
1262 property_dsc = property_dsc->next;
1263
1264 os_free(tmp_prop_dsc->dbus_interface);
1265 os_free(tmp_prop_dsc->dbus_property);
1266 os_free(tmp_prop_dsc->type);
1267
1268 if (tmp_prop_dsc->user_data_free_func)
1269 tmp_prop_dsc->user_data_free_func(
1270 tmp_prop_dsc->user_data);
1271
1272 os_free(tmp_prop_dsc);
1273 }
1274
1275 os_free(obj_dsc);
1276}
1277
1278
1279static void free_dbus_object_desc_cb(DBusConnection *connection, void *obj_dsc)
1280{
1281 free_dbus_object_desc(obj_dsc);
1282}
1283
1284/**
1285 * wpa_dbus_ctrl_iface_init - Initialize dbus control interface
1286 * @application_data: Pointer to application specific data structure
1287 * @dbus_path: DBus path to interface object
1288 * @dbus_service: DBus service name to register with
1289 * @messageHandler: a pointer to function which will handle dbus messages
1290 * coming on interface
1291 * Returns: Pointer to dbus_new_ctrl_iface date or %NULL on failure
1292 *
1293 * Initialize the dbus control interface and start receiving commands from
1294 * external programs over the bus.
1295 */
1296struct ctrl_iface_dbus_new_priv *
1297wpa_dbus_ctrl_iface_init(void *application_data,
1298 char *dbus_path, char *dbus_service,
1299 struct wpa_dbus_object_desc *obj_desc)
1300{
1301 struct ctrl_iface_dbus_new_priv *iface;
1302 DBusError error;
1303 int ret = -1;
1304 DBusObjectPathVTable wpa_vtable = {
1305 &free_dbus_object_desc_cb, &message_handler,
1306 NULL, NULL, NULL, NULL
1307 };
1308
1309 iface = os_zalloc(sizeof(struct ctrl_iface_dbus_new_priv));
1310 if (iface == NULL)
1311 return NULL;
1312
1313 iface->application_data = application_data;
1314
1315 /* Get a reference to the system bus */
1316 dbus_error_init(&error);
1317 iface->con = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
1318 dbus_error_free(&error);
1319 if (!iface->con) {
1320 perror("dbus_bus_get[ctrl_iface_dbus]");
1321 wpa_printf(MSG_ERROR, "Could not acquire the system bus.");
1322 goto fail;
1323 }
1324
1325 obj_desc->connection = iface->con;
1326
1327 /* Tell dbus about our mainloop integration functions */
1328 if (integrate_with_eloop(iface->con, iface))
1329 goto fail;
1330
1331 /* Register the message handler for the global dbus interface */
1332 if (!dbus_connection_register_object_path(iface->con,
1333 dbus_path, &wpa_vtable,
1334 obj_desc)) {
1335 perror("dbus_connection_register_object_path[dbus]");
1336 wpa_printf(MSG_ERROR, "Could not set up DBus message "
1337 "handler.");
1338 goto fail;
1339 }
1340
1341 /* Register our service with the message bus */
1342 dbus_error_init(&error);
1343 switch (dbus_bus_request_name(iface->con, dbus_service,
1344 0, &error)) {
1345 case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
1346 ret = 0;
1347 break;
1348 case DBUS_REQUEST_NAME_REPLY_EXISTS:
1349 case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
1350 case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
1351 perror("dbus_bus_request_name[dbus]");
1352 wpa_printf(MSG_ERROR, "Could not request DBus service name: "
1353 "already registered.");
1354 break;
1355 default:
1356 perror("dbus_bus_request_name[dbus]");
1357 wpa_printf(MSG_ERROR, "Could not request DBus service name: "
1358 "%s %s.", error.name, error.message);
1359 break;
1360 }
1361 dbus_error_free(&error);
1362
1363 if (ret != 0)
1364 goto fail;
1365
1366 wpa_printf(MSG_DEBUG, "Providing DBus service '%s'.", dbus_service);
1367
1368 /*
1369 * Dispatch initial DBus messages that may have come in since the bus
1370 * name was claimed above. Happens when clients are quick to notice the
1371 * service.
1372 *
1373 * FIXME: is there a better solution to this problem?
1374 */
1375 eloop_register_timeout(0, 50, dispatch_initial_dbus_messages,
1376 iface->con, NULL);
1377
1378 return iface;
1379
1380fail:
1381 wpa_dbus_ctrl_iface_deinit(iface);
1382 return NULL;
1383}
1384
1385
1386/**
1387 * wpa_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface
1388 * @iface: Pointer to dbus private data from wpa_dbus_ctrl_iface_init()
1389 *
1390 * Deinitialize the dbus control interface that was initialized with
1391 * wpa_dbus_ctrl_iface_init().
1392 */
1393void wpa_dbus_ctrl_iface_deinit(struct ctrl_iface_dbus_new_priv *iface)
1394{
1395 if (iface == NULL)
1396 return;
1397
1398 if (iface->con) {
1399 eloop_cancel_timeout(dispatch_initial_dbus_messages,
1400 iface->con, NULL);
1401 dbus_connection_set_watch_functions(iface->con, NULL, NULL,
1402 NULL, NULL, NULL);
1403 dbus_connection_set_timeout_functions(iface->con, NULL, NULL,
1404 NULL, NULL, NULL);
1405 dbus_connection_unref(iface->con);
1406 }
1407
1408 os_memset(iface, 0, sizeof(struct ctrl_iface_dbus_new_priv));
1409 os_free(iface);
1410}
1411
1412
1413/**
1414 * wpa_dbus_register_object_per_iface - Register a new object with dbus
1415 * @ctrl_iface: pointer to dbus private data
1416 * @path: DBus path to object
1417 * @ifname: interface name
1418 * @obj_desc: description of object's methods, signals and properties
1419 * Returns: 0 on success, -1 on error
1420 *
1421 * Registers a new interface with dbus and assigns it a dbus object path.
1422 */
1423int wpa_dbus_register_object_per_iface(
1424 struct ctrl_iface_dbus_new_priv *ctrl_iface,
1425 const char *path, const char *ifname,
1426 struct wpa_dbus_object_desc *obj_desc)
1427{
1428 DBusConnection *con;
1429
1430 DBusObjectPathVTable vtable = {
1431 &free_dbus_object_desc_cb, &message_handler,
1432 NULL, NULL, NULL, NULL
1433 };
1434
1435 /* Do nothing if the control interface is not turned on */
1436 if (ctrl_iface == NULL)
1437 return 0;
1438
1439 con = ctrl_iface->con;
1440 obj_desc->connection = con;
1441
1442 /* Register the message handler for the interface functions */
1443 if (!dbus_connection_register_object_path(con, path, &vtable,
1444 obj_desc)) {
1445 perror("wpa_dbus_register_iface [dbus]");
1446 wpa_printf(MSG_ERROR, "Could not set up DBus message "
1447 "handler for interface %s\n"
1448 "and object %s.", ifname, path);
1449 return -1;
1450 }
1451
1452 return 0;
1453}
1454
1455
1456/**
1457 * wpa_dbus_unregister_object_per_iface - Unregisters DBus object
1458 * @ctrl_iface: Pointer to dbus private data
1459 * @path: DBus path to object which will be unregistered
1460 * Returns: Zero on success and -1 on failure
1461 *
1462 * Unregisters DBus object given by its path
1463 */
1464int wpa_dbus_unregister_object_per_iface(
1465 struct ctrl_iface_dbus_new_priv *ctrl_iface, const char *path)
1466{
1467 DBusConnection *con = ctrl_iface->con;
1468 if (!dbus_connection_unregister_object_path(con, path))
1469 return -1;
1470
1471 return 0;
1472}
1473
1474
1475/**
1476 * wpa_dbus_method_register - Registers DBus method for given object
1477 * @obj_dsc: Object description for which a method will be registered
1478 * @dbus_interface: DBus interface under which method will be registered
1479 * @dbus_method: a name the method will be registered with
1480 * @method_handler: a function which will be called to handle this method call
1481 * @handler_argument: an additional argument passed to handler function
1482 * @argument_free_func: function used to free handler argument
1483 * @args: method arguments list
1484 * Returns: Zero on success and -1 on failure
1485 *
1486 * Registers DBus method under given name and interface for the object.
1487 * Method calls will be handled with given handling function and optional
1488 * argument passed to this function. Handler function is required to return
1489 * a DBusMessage pointer which will be response to method call. Any method
1490 * call before being handled must have registered appropriate handler by
1491 * using this function.
1492 */
1493int wpa_dbus_method_register(struct wpa_dbus_object_desc *obj_dsc,
7ae7b192
JM
1494 const char *dbus_interface,
1495 const char *dbus_method,
8fc2fb56
WS
1496 WPADBusMethodHandler method_handler,
1497 void *handler_argument,
1498 WPADBusArgumentFreeFunction argument_free_func,
9b61515c 1499 const struct wpa_dbus_argument args[])
8fc2fb56
WS
1500{
1501 struct wpa_dbus_method_desc *method_dsc = obj_dsc->methods;
1502 struct wpa_dbus_method_desc *prev_desc;
1503 int args_num = 0;
1504 int interface_len, method_len, i, len, error;
1505
1506 prev_desc = NULL;
1507 while (method_dsc) {
1508 prev_desc = method_dsc;
1509 method_dsc = method_dsc->next;
1510 }
1511
1512 /* count args */
8fc2fb56
WS
1513 if (args) {
1514 while (args[args_num].name && args[args_num].type)
1515 args_num++;
1516 }
1517
1518 method_dsc = os_zalloc(sizeof(struct wpa_dbus_method_desc) +
1519 args_num * sizeof(struct wpa_dbus_argument));
1520 if (!method_dsc)
7ae7b192 1521 goto err;
8fc2fb56
WS
1522
1523 if (prev_desc == NULL)
1524 obj_dsc->methods = method_dsc;
1525 else
1526 prev_desc->next = method_dsc;
1527
1528 /* copy interface name */
1529 interface_len = os_strlen(dbus_interface) + 1;
1530 method_dsc->dbus_interface = os_malloc(interface_len);
1531 if (!method_dsc->dbus_interface)
1532 goto err;
1533 os_strncpy(method_dsc->dbus_interface, dbus_interface, interface_len);
1534
1535 /* copy method name */
1536 method_len = os_strlen(dbus_method) + 1;
1537 method_dsc->dbus_method = os_malloc(method_len);
1538 if (!method_dsc->dbus_method)
1539 goto err;
1540 os_strncpy(method_dsc->dbus_method, dbus_method, method_len);
1541
1542 /* copy arguments */
1543 error = 0;
1544 method_dsc->args_num = args_num;
1545 for (i = 0; i < args_num; i++) {
1546 len = os_strlen(args[i].name) + 1;
1547 method_dsc->args[i].name = os_malloc(len);
1548 if (!method_dsc->args[i].name) {
1549 error = 1;
1550 continue;
1551 }
1552 os_strncpy(method_dsc->args[i].name, args[i].name, len);
1553
1554 len = os_strlen(args[i].type) + 1;
1555 method_dsc->args[i].type = os_malloc(len);
1556 if (!method_dsc->args[i].type) {
1557 error = 1;
1558 continue;
1559 }
1560 os_strncpy(method_dsc->args[i].type, args[i].type, len);
1561
1562 method_dsc->args[i].dir = args[i].dir;
1563 }
1564 if (error)
1565 goto err;
1566
1567 method_dsc->method_handler = method_handler;
1568 method_dsc->handler_argument = handler_argument;
1569 method_dsc->argument_free_func = argument_free_func;
1570 method_dsc->next = NULL;
1571
1572 return 0;
1573
1574err:
7ae7b192
JM
1575 wpa_printf(MSG_WARNING, "Failed to register dbus method %s in "
1576 "interface %s", dbus_method, dbus_interface);
8fc2fb56
WS
1577 if (method_dsc) {
1578 os_free(method_dsc->dbus_interface);
1579 os_free(method_dsc->dbus_method);
1580 for (i = 0; i < method_dsc->args_num; i++) {
1581 os_free(method_dsc->args[i].name);
1582 os_free(method_dsc->args[i].type);
1583 }
1584
1585 if (prev_desc == NULL)
1586 obj_dsc->methods = NULL;
1587 else
1588 prev_desc->next = NULL;
1589
1590 os_free(method_dsc);
1591 }
1592
1593 return -1;
1594}
1595
1596
1597/**
1598 * wpa_dbus_signal_register - Registers DBus signal for given object
1599 * @obj_dsc: Object description for which a signal will be registered
1600 * @dbus_interface: DBus interface under which signal will be registered
1601 * @dbus_signal: a name the signal will be registered with
1602 * @args: signal arguments list
1603 * Returns: Zero on success and -1 on failure
1604 *
1605 * Registers DBus signal under given name and interface for the object.
1606 * Signal registration is NOT required in order to send signals, but not
1607 * registered signals will not be respected in introspection data
1608 * therefore it is highly recommended to register every signal before
1609 * using it.
1610 */
1611int wpa_dbus_signal_register(struct wpa_dbus_object_desc *obj_dsc,
7ae7b192
JM
1612 const char *dbus_interface,
1613 const char *dbus_signal,
9b61515c 1614 const struct wpa_dbus_argument args[])
8fc2fb56
WS
1615{
1616
1617 struct wpa_dbus_signal_desc *signal_dsc = obj_dsc->signals;
1618 struct wpa_dbus_signal_desc *prev_desc;
1619 int args_num = 0;
1620 int interface_len, signal_len, i, len, error = 0;
1621
1622 prev_desc = NULL;
1623 while (signal_dsc) {
1624 prev_desc = signal_dsc;
1625 signal_dsc = signal_dsc->next;
1626 }
1627
1628 /* count args */
1629 if (args) {
1630 while (args[args_num].name && args[args_num].type)
1631 args_num++;
1632 }
1633
1634 signal_dsc = os_zalloc(sizeof(struct wpa_dbus_signal_desc) +
7ae7b192 1635 args_num * sizeof(struct wpa_dbus_argument));
8fc2fb56 1636 if (!signal_dsc)
7ae7b192 1637 goto err;
8fc2fb56
WS
1638
1639 if (prev_desc == NULL)
1640 obj_dsc->signals = signal_dsc;
1641 else
1642 prev_desc->next = signal_dsc;
1643
1644 /* copy interface name */
1645 interface_len = strlen(dbus_interface) + 1;
1646 signal_dsc->dbus_interface = os_malloc(interface_len);
1647 if (!signal_dsc->dbus_interface)
1648 goto err;
1649 os_strncpy(signal_dsc->dbus_interface, dbus_interface, interface_len);
1650
1651 /* copy signal name */
1652 signal_len = strlen(dbus_signal) + 1;
1653 signal_dsc->dbus_signal = os_malloc(signal_len);
1654 if (!signal_dsc->dbus_signal)
1655 goto err;
1656 os_strncpy(signal_dsc->dbus_signal, dbus_signal, signal_len);
1657
1658 /* copy arguments */
1659 signal_dsc->args_num = args_num;
1660 for (i = 0; i < args_num; i++) {
1661 len = os_strlen(args[i].name) + 1;
1662 signal_dsc->args[i].name = os_malloc(len);
1663 if (!signal_dsc->args[i].name) {
1664 error = 1;
1665 continue;
1666 }
1667 os_strncpy(signal_dsc->args[i].name, args[i].name, len);
1668
1669 len = strlen(args[i].type) + 1;
1670 signal_dsc->args[i].type = os_malloc(len);
1671 if (!signal_dsc->args[i].type) {
1672 error = 1;
1673 continue;
1674 }
1675 os_strncpy(signal_dsc->args[i].type, args[i].type, len);
1676 }
1677 if (error)
1678 goto err;
1679
1680 signal_dsc->next = NULL;
1681
1682 return 0;
1683
1684err:
7ae7b192
JM
1685 wpa_printf(MSG_WARNING, "Failed to register dbus signal %s in "
1686 "interface %s", dbus_signal, dbus_interface);
8fc2fb56
WS
1687 if (signal_dsc) {
1688 os_free(signal_dsc->dbus_interface);
1689 os_free(signal_dsc->dbus_signal);
1690 for (i = 0; i < signal_dsc->args_num; i++) {
1691 os_free(signal_dsc->args[i].name);
1692 os_free(signal_dsc->args[i].type);
1693 }
1694
1695 if (prev_desc == NULL)
1696 obj_dsc->signals = NULL;
1697 else
1698 prev_desc->next = NULL;
1699
1700 os_free(signal_dsc);
1701 }
1702
1703 return -1;
1704}
1705
1706
1707/**
1708 * wpa_dbus_property_register - Registers DBus property for given object
1709 * @obj_dsc: Object description for which a property will be registered
1710 * @dbus_interface: DBus interface under which method will be registered
1711 * @dbus_property: a name the property will be registered with
1712 * @type: a property type signature in form of DBus type description
1713 * @getter: a function called in order to get property value
1714 * @setter: a function called in order to set property value
1715 * @user_data: additional argument passed to setter or getter
1716 * @user_data_free_func: function used to free additional argument
1717 * @access: property access permissions specifier (R, W or RW)
1718 * Returns: Zero on success and -1 on failure
1719 *
1720 * Registers DBus property under given name and interface for the object.
1721 * Property are set with giver setter function and get with getter.
1722 * Additional argument is passed to getter or setter. Getter or setter
1723 * are required to return DBusMessage which is response to Set/Get method
1724 * calls. Every property must be registered by this function before being
1725 * used.
1726 */
1727int wpa_dbus_property_register(struct wpa_dbus_object_desc *obj_dsc,
7ae7b192
JM
1728 const char *dbus_interface,
1729 const char *dbus_property,
1730 const char *type,
8fc2fb56
WS
1731 WPADBusPropertyAccessor getter,
1732 WPADBusPropertyAccessor setter,
1733 void *user_data,
1734 WPADBusArgumentFreeFunction user_data_free_func,
1735 enum dbus_prop_access _access)
1736{
1737 struct wpa_dbus_property_desc *property_dsc = obj_dsc->properties;
1738 struct wpa_dbus_property_desc *prev_desc;
1739 int interface_len, property_len, type_len;
1740
1741 prev_desc = NULL;
1742 while (property_dsc) {
1743 prev_desc = property_dsc;
1744 property_dsc = property_dsc->next;
1745 }
1746
1747 property_dsc = os_zalloc(sizeof(struct wpa_dbus_property_desc));
1748 if (!property_dsc)
7ae7b192 1749 goto err;
8fc2fb56
WS
1750
1751 if (prev_desc == NULL)
1752 obj_dsc->properties = property_dsc;
1753 else
1754 prev_desc->next = property_dsc;
1755
1756 /* copy interface name */
1757 interface_len = os_strlen(dbus_interface) + 1;
1758 property_dsc->dbus_interface = os_malloc(interface_len);
1759 if (!property_dsc->dbus_interface)
1760 goto err;
1761 os_strncpy(property_dsc->dbus_interface, dbus_interface,
1762 interface_len);
1763
1764 /* copy property name */
1765 property_len = os_strlen(dbus_property) + 1;
1766 property_dsc->dbus_property = os_malloc(property_len);
1767 if (!property_dsc->dbus_property)
1768 goto err;
1769 os_strncpy(property_dsc->dbus_property, dbus_property, property_len);
1770
1771 /* copy property type */
1772 type_len = os_strlen(type) + 1;
1773 property_dsc->type = os_malloc(type_len);
1774 if (!property_dsc->type)
1775 goto err;
1776 os_strncpy(property_dsc->type, type, type_len);
1777
1778 property_dsc->getter = getter;
1779 property_dsc->setter = setter;
1780 property_dsc->user_data = user_data;
1781 property_dsc->user_data_free_func = user_data_free_func;
1782 property_dsc->access = _access;
1783 property_dsc->next = NULL;
1784
1785 return 0;
1786
1787err:
7ae7b192
JM
1788 wpa_printf(MSG_WARNING, "Failed to register dbus property %s in "
1789 "interface %s", dbus_property, dbus_interface);
8fc2fb56
WS
1790 if (property_dsc) {
1791 os_free(property_dsc->dbus_interface);
1792 os_free(property_dsc->dbus_property);
1793 os_free(property_dsc->type);
1794
1795 if (prev_desc == NULL)
1796 obj_dsc->properties = NULL;
1797 else
1798 prev_desc->next = NULL;
1799
1800 os_free(property_dsc);
1801 }
1802
1803 return -1;
1804}
1805
1806
1807/**
1808 * wpas_dbus_signal_network_added - Send a property changed signal
1809 * @iface: dbus priv struct
1810 * @property_getter: propperty getter used to fetch new property value
1811 * @getter_arg: argument passed to property getter
1812 * @path: path to object which property has changed
1813 * @interface_name: signal and property interface
1814 * @property_name: name of property which has changed
1815 *
1816 * Notify listeners about changing value of some property. Signal
1817 * contains property name and its value fetched using given property
1818 * getter.
1819 */
1820void wpa_dbus_signal_property_changed(struct ctrl_iface_dbus_new_priv *iface,
1821 WPADBusPropertyAccessor property_getter,
1822 void *getter_arg,
1823 const char *path,
1824 const char *interface_name,
1825 const char *property_name)
1826{
1827
1828 DBusConnection *connection;
1829 DBusMessage *_signal, *getter_reply;
1830 DBusMessageIter prop_iter, signal_iter, dict_iter, entry_iter;
1831
1832 if (!iface)
1833 return;
1834 connection = iface->con;
1835
1836 if (!property_getter) {
1837 wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
1838 "[dbus]: property getter not specified");
1839 return;
1840 }
1841
1842 if (!path || !interface_name || !property_name) {
1843 wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
1844 "[dbus]: path interface of property not specified");
1845 return;
1846 }
1847
1848 getter_reply = property_getter(NULL, getter_arg);
1849 if (!getter_reply ||
1850 dbus_message_get_type(getter_reply) == DBUS_MESSAGE_TYPE_ERROR) {
1851 wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
1852 "[dbus]: cannot get new value of property %s",
1853 property_name);
1854 return;
1855 }
1856
1857 _signal = dbus_message_new_signal(path, interface_name,
1858 "PropertiesChanged");
1859 if (!_signal) {
1860 wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
1861 "[dbus]: cannot allocate signal");
1862 dbus_message_unref(getter_reply);
1863 return;
1864 }
1865
1866 dbus_message_iter_init(getter_reply, &prop_iter);
1867 dbus_message_iter_init_append(_signal, &signal_iter);
1868
1869 if (!dbus_message_iter_open_container(&signal_iter, DBUS_TYPE_ARRAY,
1870 "{sv}", &dict_iter)) {
1871 wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
1872 "[dbus]: out of memory. cannot open dictionary");
1873 goto err;
1874 }
1875
1876 if (!dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_DICT_ENTRY,
1877 NULL, &entry_iter)) {
1878 wpa_printf(MSG_ERROR, "iwpa_dbus_signal_property_changed"
1879 "[dbus]: out of memory. cannot open dictionary "
1880 "element");
1881 goto err;
1882 }
1883
1884 if (!dbus_message_iter_append_basic(&entry_iter, DBUS_TYPE_STRING,
1885 &property_name)) {
1886 wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
1887 "[dbus]: out of memory. cannot open add property "
1888 "name");
1889 goto err;
1890 }
1891
1892 recursive_iter_copy(&prop_iter, &entry_iter);
1893
1894 if (!dbus_message_iter_close_container(&dict_iter, &entry_iter)) {
1895 wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
1896 "[dbus]: out of memory. cannot close dictionary "
1897 "element");
1898 goto err;
1899 }
1900
1901 if (!dbus_message_iter_close_container(&signal_iter, &dict_iter)) {
1902 wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
1903 "[dbus]: out of memory. cannot close dictionary");
1904 goto err;
1905 }
1906
1907 dbus_connection_send(connection, _signal, NULL);
1908
1909err:
1910 dbus_message_unref(getter_reply);
1911 dbus_message_unref(_signal);
1912
1913}