dbus: show messages in debug log
[libeap.git] / wpa_supplicant / dbus / dbus_new_helpers.c
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 "dbus_new_helpers.h"
21
22 /**
23  * struct wpa_dbus_method_desc - DBus method description
24  */
25 struct 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  */
51 struct 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  */
70 struct 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
98 struct interfaces {
99         struct interfaces *next;
100         char *dbus_interface;
101         xmlNodePtr interface_node;
102 };
103 #endif /* CONFIG_CTRL_IFACE_DBUS_INTRO */
104
105 static 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
130 static 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
136 static 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
142 static 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
148 static 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
176 static 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
196 static dbus_bool_t add_watch(DBusWatch *watch, void *data)
197 {
198         connection_setup_add_watch(data, watch);
199         return TRUE;
200 }
201
202
203 static void remove_watch(DBusWatch *watch, void *data)
204 {
205         connection_setup_remove_watch(data, watch);
206 }
207
208
209 static 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
218 static void process_timeout(void *eloop_ctx, void *sock_ctx)
219 {
220         DBusTimeout *timeout = sock_ctx;
221
222         dbus_timeout_handle(timeout);
223 }
224
225
226 static 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
239 static 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
247 static 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
258 static void remove_timeout(DBusTimeout *timeout, void *data)
259 {
260         connection_setup_remove_timeout(data, timeout);
261 }
262
263
264 static 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
273 static void process_wakeup_main(int sig, 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  */
298 static 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  */
315 static 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  */
332 u32 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  */
346 static 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  */
386 static 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  */
409 static 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  */
588 static 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;
597         xmlChar *intro_str;
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
801         xmlDocDumpFormatMemory(doc, &intro_str, &s, 1);
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  */
830 static 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  */
850 static 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  */
915 static 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
973 static int is_signature_correct(DBusMessage *message,
974                                 struct wpa_dbus_method_desc *method_dsc)
975 {
976         /* According to DBus documentation max length of signature is 255 */
977 #define MAX_SIG_LEN 256
978         char registered_sig[MAX_SIG_LEN], *pos;
979         const char *sig = dbus_message_get_signature(message);
980         int i, ret;
981
982         pos = registered_sig;
983         *pos = '\0';
984
985         for (i = 0; i < method_dsc->args_num; i++) {
986                 struct wpa_dbus_argument arg = method_dsc->args[i];
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                 }
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  */
1015 static 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         wpa_printf(MSG_MSGDUMP, "dbus: %s.%s (%s)",
1034                    msg_interface, method, path);
1035
1036         /* if message is introspection method call */
1037         if (!os_strncmp(WPA_DBUS_INTROSPECTION_METHOD, method,
1038                         WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) &&
1039             !os_strncmp(WPA_DBUS_INTROSPECTION_INTERFACE, msg_interface,
1040                         WPAS_DBUS_INTERFACE_MAX))
1041                 reply = introspect(message, obj_dsc);
1042         else if (!strncmp(WPA_DBUS_PROPERTIES_INTERFACE, msg_interface,
1043                           WPAS_DBUS_INTERFACE_MAX)) {
1044                 /* if message is properties method call */
1045                 DBusMessageIter iter;
1046                 char *interface;
1047                 char *property;
1048
1049                 dbus_message_iter_init(message, &iter);
1050
1051                 if (!os_strncmp(WPA_DBUS_PROPERTIES_GET, method,
1052                                 WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) ||
1053                     !os_strncmp(WPA_DBUS_PROPERTIES_SET, method,
1054                                 WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) ||
1055                     !os_strncmp(WPA_DBUS_PROPERTIES_GETALL, method,
1056                                 WPAS_DBUS_METHOD_SIGNAL_PROP_MAX)) {
1057                         /* First argument: interface name (DBUS_TYPE_STRING) */
1058                         if (dbus_message_iter_get_arg_type(&iter) !=
1059                             DBUS_TYPE_STRING) {
1060                                 reply = dbus_message_new_error(
1061                                         message, DBUS_ERROR_INVALID_ARGS,
1062                                         NULL);
1063                                 goto out;
1064                         }
1065
1066                         dbus_message_iter_get_basic(&iter, &interface);
1067
1068                         /* GetAll */
1069                         if (!os_strncmp(WPA_DBUS_PROPERTIES_GETALL, method,
1070                                         WPAS_DBUS_METHOD_SIGNAL_PROP_MAX)) {
1071                                 if (os_strcmp(dbus_message_get_signature(
1072                                                       message), "s"))
1073                                         reply = dbus_message_new_error(
1074                                                 message,
1075                                                 DBUS_ERROR_INVALID_ARGS, NULL);
1076                                 else
1077                                         reply = get_all_properties(
1078                                                 message, interface,
1079                                                 obj_dsc->properties);
1080                         } else {
1081                                 /* Get or Set */
1082                                 struct wpa_dbus_property_desc *property_dsc;
1083                                 property_dsc = obj_dsc->properties;
1084
1085                                 /* Second argument: property name
1086                                  * (DBUS_TYPE_STRING) */
1087                                 if (!dbus_message_iter_next(&iter) ||
1088                                     dbus_message_iter_get_arg_type(&iter) !=
1089                                     DBUS_TYPE_STRING) {
1090                                         reply = dbus_message_new_error(
1091                                                 message,
1092                                                 DBUS_ERROR_INVALID_ARGS, NULL);
1093                                         goto out;
1094                                 }
1095                                 dbus_message_iter_get_basic(&iter, &property);
1096
1097                                 while (property_dsc) {
1098                                         /* compare property names and
1099                                          * interfaces */
1100                                         if (!os_strncmp(property_dsc->dbus_property,
1101                                                         property,
1102                                                         WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) &&
1103                                             !os_strncmp(property_dsc->dbus_interface, interface,
1104                                                         WPAS_DBUS_INTERFACE_MAX))
1105                                                 break;
1106
1107                                         property_dsc = property_dsc->next;
1108                                 }
1109                                 if (property_dsc) {
1110                                         /* Get */
1111                                         if (!os_strncmp(WPA_DBUS_PROPERTIES_GET, method,
1112                                                         WPAS_DBUS_METHOD_SIGNAL_PROP_MAX)) {
1113                                                 if (os_strcmp(dbus_message_get_signature(message), "ss"))
1114                                                         reply = dbus_message_new_error(message,
1115                                                                                        DBUS_ERROR_INVALID_ARGS, NULL);
1116                                                 else if (property_dsc->access != W &&
1117                                                          property_dsc->getter)
1118                                                         reply = property_dsc->getter(message,
1119                                                                                      property_dsc->user_data);
1120                                                 else
1121                                                         reply = dbus_message_new_error(message,
1122                                                                                        DBUS_ERROR_INVALID_ARGS,
1123                                                                                        "Property is write-only");
1124                                         } else {
1125                                                 /* Set */
1126                                                 if (os_strcmp(dbus_message_get_signature(message), "ssv"))
1127                                                         reply = dbus_message_new_error(message,
1128                                                                                        DBUS_ERROR_INVALID_ARGS, NULL);
1129                                                 else if (property_dsc->access != R &&
1130                                                          property_dsc->setter) {
1131                                                         reply = property_dsc->setter
1132                                                                 (message, property_dsc->user_data);
1133                                                 } else {
1134                                                         reply = dbus_message_new_error(message,
1135                                                                                        DBUS_ERROR_INVALID_ARGS,
1136                                                                                        "Property is read-only");
1137                                                 }
1138                                         }
1139                                 } else {
1140                                         wpa_printf(MSG_DEBUG, "no property handler for %s.%s\n"
1141                                                    "on %s", interface, property, path);
1142                                         reply = dbus_message_new_error(message,
1143                                                                        DBUS_ERROR_INVALID_ARGS,
1144                                                                        "No such property");
1145                                 }
1146                         }
1147                 } else {
1148                         reply = dbus_message_new_error(
1149                                 message, DBUS_ERROR_UNKNOWN_METHOD, NULL);
1150                         goto out;
1151                 }
1152         } else {
1153                 struct wpa_dbus_method_desc *method_dsc = obj_dsc->methods;
1154
1155                 /* try match call to any registered method */
1156                 while (method_dsc) {
1157                         /* compare method names and interfaces */
1158                         if (!os_strncmp(method_dsc->dbus_method, method,
1159                                         WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) &&
1160                             !os_strncmp(method_dsc->dbus_interface,
1161                                         msg_interface,
1162                                         WPAS_DBUS_INTERFACE_MAX))
1163                                 break;
1164
1165                         method_dsc = method_dsc->next;
1166                 }
1167                 if (method_dsc) {
1168                         if (is_signature_correct(message, method_dsc)) {
1169                                 reply = method_dsc->method_handler(
1170                                         message, method_dsc->handler_argument);
1171                         } else {
1172                                 reply = dbus_message_new_error(
1173                                         message, DBUS_ERROR_INVALID_ARGS,
1174                                         NULL);
1175                         }
1176                 } else {
1177                         wpa_printf(MSG_DEBUG, "no method handler for %s.%s "
1178                                    "on %s", msg_interface, method, path);
1179                         reply = dbus_message_new_error(
1180                                 message, DBUS_ERROR_UNKNOWN_METHOD, NULL);
1181                 }
1182         }
1183
1184 out:
1185         /* If the message was handled, send back the reply */
1186         if (reply != MESSAGE_UNHANDLED) {
1187                 /* If handler succeed returning NULL, reply empty message */
1188                 if (!reply)
1189                         reply = dbus_message_new_method_return(message);
1190                 if (reply) {
1191                         if (!dbus_message_get_no_reply(message))
1192                                 dbus_connection_send(connection, reply, NULL);
1193                         dbus_message_unref(reply);
1194                 }
1195                 return DBUS_HANDLER_RESULT_HANDLED;
1196         } else
1197                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1198 }
1199
1200
1201 /**
1202  * free_dbus_object_desc - Frees object description data structure
1203  * @connection: DBus connection
1204  * @obj_dsc: Object description to free
1205  *
1206  * Frees each of properties, methods and signals description lists and
1207  * the object description structure itself.
1208  */
1209 void free_dbus_object_desc(struct wpa_dbus_object_desc *obj_dsc)
1210 {
1211         struct wpa_dbus_method_desc *method_dsc, *tmp_met_dsc;
1212         struct wpa_dbus_signal_desc *signal_dsc, *tmp_sig_dsc;
1213         struct wpa_dbus_property_desc *property_dsc, *tmp_prop_dsc;
1214         int i;
1215
1216         if (!obj_dsc)
1217                 return;
1218
1219         /* free methods */
1220         method_dsc = obj_dsc->methods;
1221
1222         while (method_dsc) {
1223                 tmp_met_dsc = method_dsc;
1224                 method_dsc = method_dsc->next;
1225
1226                 os_free(tmp_met_dsc->dbus_interface);
1227                 os_free(tmp_met_dsc->dbus_method);
1228
1229                 for (i = 0; i < tmp_met_dsc->args_num; i++) {
1230                         os_free(tmp_met_dsc->args[i].name);
1231                         os_free(tmp_met_dsc->args[i].type);
1232                 }
1233
1234                 if (tmp_met_dsc->argument_free_func)
1235                         tmp_met_dsc->argument_free_func(
1236                                 tmp_met_dsc->handler_argument);
1237
1238                 os_free(tmp_met_dsc);
1239         }
1240
1241         /* free signals */
1242         signal_dsc = obj_dsc->signals;
1243
1244         while (signal_dsc) {
1245                 tmp_sig_dsc = signal_dsc;
1246                 signal_dsc = signal_dsc->next;
1247
1248                 os_free(tmp_sig_dsc->dbus_interface);
1249                 os_free(tmp_sig_dsc->dbus_signal);
1250
1251                 for (i = 0; i < tmp_sig_dsc->args_num; i++) {
1252                         os_free(tmp_sig_dsc->args[i].name);
1253                         os_free(tmp_sig_dsc->args[i].type);
1254                 }
1255
1256                 os_free(tmp_sig_dsc);
1257         }
1258
1259         /* free properties */
1260         property_dsc = obj_dsc->properties;
1261
1262         while (property_dsc) {
1263                 tmp_prop_dsc = property_dsc;
1264                 property_dsc = property_dsc->next;
1265
1266                 os_free(tmp_prop_dsc->dbus_interface);
1267                 os_free(tmp_prop_dsc->dbus_property);
1268                 os_free(tmp_prop_dsc->type);
1269
1270                 if (tmp_prop_dsc->user_data_free_func)
1271                         tmp_prop_dsc->user_data_free_func(
1272                                 tmp_prop_dsc->user_data);
1273
1274                 os_free(tmp_prop_dsc);
1275         }
1276
1277         os_free(obj_dsc);
1278 }
1279
1280
1281 static void free_dbus_object_desc_cb(DBusConnection *connection, void *obj_dsc)
1282 {
1283         free_dbus_object_desc(obj_dsc);
1284 }
1285
1286 /**
1287  * wpa_dbus_ctrl_iface_init - Initialize dbus control interface
1288  * @application_data: Pointer to application specific data structure
1289  * @dbus_path: DBus path to interface object
1290  * @dbus_service: DBus service name to register with
1291  * @messageHandler: a pointer to function which will handle dbus messages
1292  * coming on interface
1293  * Returns: Pointer to dbus_new_ctrl_iface date or %NULL on failure
1294  *
1295  * Initialize the dbus control interface and start receiving commands from
1296  * external programs over the bus.
1297  */
1298 struct ctrl_iface_dbus_new_priv *
1299 wpa_dbus_ctrl_iface_init(void *application_data,
1300                          char *dbus_path, char *dbus_service,
1301                          struct wpa_dbus_object_desc *obj_desc)
1302 {
1303         struct ctrl_iface_dbus_new_priv *iface;
1304         DBusError error;
1305         int ret = -1;
1306         DBusObjectPathVTable wpa_vtable = {
1307                 &free_dbus_object_desc_cb, &message_handler,
1308                 NULL, NULL, NULL, NULL
1309         };
1310
1311         iface = os_zalloc(sizeof(struct ctrl_iface_dbus_new_priv));
1312         if (iface == NULL)
1313                 return NULL;
1314
1315         iface->application_data = application_data;
1316
1317         /* Get a reference to the system bus */
1318         dbus_error_init(&error);
1319         iface->con = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
1320         dbus_error_free(&error);
1321         if (!iface->con) {
1322                 perror("dbus_bus_get[ctrl_iface_dbus]");
1323                 wpa_printf(MSG_ERROR, "Could not acquire the system bus.");
1324                 goto fail;
1325         }
1326
1327         obj_desc->connection = iface->con;
1328
1329         /* Tell dbus about our mainloop integration functions */
1330         if (integrate_with_eloop(iface->con, iface))
1331                 goto fail;
1332
1333         /* Register the message handler for the global dbus interface */
1334         if (!dbus_connection_register_object_path(iface->con,
1335                                                   dbus_path, &wpa_vtable,
1336                                                   obj_desc)) {
1337                 perror("dbus_connection_register_object_path[dbus]");
1338                 wpa_printf(MSG_ERROR, "Could not set up DBus message "
1339                            "handler.");
1340                 goto fail;
1341         }
1342
1343         /* Register our service with the message bus */
1344         dbus_error_init(&error);
1345         switch (dbus_bus_request_name(iface->con, dbus_service,
1346                                       0, &error)) {
1347         case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
1348                 ret = 0;
1349                 break;
1350         case DBUS_REQUEST_NAME_REPLY_EXISTS:
1351         case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
1352         case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
1353                 perror("dbus_bus_request_name[dbus]");
1354                 wpa_printf(MSG_ERROR, "Could not request DBus service name: "
1355                            "already registered.");
1356                 break;
1357         default:
1358                 perror("dbus_bus_request_name[dbus]");
1359                 wpa_printf(MSG_ERROR, "Could not request DBus service name: "
1360                            "%s %s.", error.name, error.message);
1361                 break;
1362         }
1363         dbus_error_free(&error);
1364
1365         if (ret != 0)
1366                 goto fail;
1367
1368         wpa_printf(MSG_DEBUG, "Providing DBus service '%s'.", dbus_service);
1369
1370         /*
1371          * Dispatch initial DBus messages that may have come in since the bus
1372          * name was claimed above. Happens when clients are quick to notice the
1373          * service.
1374          *
1375          * FIXME: is there a better solution to this problem?
1376          */
1377         eloop_register_timeout(0, 50, dispatch_initial_dbus_messages,
1378                                iface->con, NULL);
1379
1380         return iface;
1381
1382 fail:
1383         wpa_dbus_ctrl_iface_deinit(iface);
1384         return NULL;
1385 }
1386
1387
1388 /**
1389  * wpa_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface
1390  * @iface: Pointer to dbus private data from wpa_dbus_ctrl_iface_init()
1391  *
1392  * Deinitialize the dbus control interface that was initialized with
1393  * wpa_dbus_ctrl_iface_init().
1394  */
1395 void wpa_dbus_ctrl_iface_deinit(struct ctrl_iface_dbus_new_priv *iface)
1396 {
1397         if (iface == NULL)
1398                 return;
1399
1400         if (iface->con) {
1401                 eloop_cancel_timeout(dispatch_initial_dbus_messages,
1402                                      iface->con, NULL);
1403                 dbus_connection_set_watch_functions(iface->con, NULL, NULL,
1404                                                     NULL, NULL, NULL);
1405                 dbus_connection_set_timeout_functions(iface->con, NULL, NULL,
1406                                                       NULL, NULL, NULL);
1407                 dbus_connection_unref(iface->con);
1408         }
1409
1410         os_memset(iface, 0, sizeof(struct ctrl_iface_dbus_new_priv));
1411         os_free(iface);
1412 }
1413
1414
1415 /**
1416  * wpa_dbus_register_object_per_iface - Register a new object with dbus
1417  * @ctrl_iface: pointer to dbus private data
1418  * @path: DBus path to object
1419  * @ifname: interface name
1420  * @obj_desc: description of object's methods, signals and properties
1421  * Returns: 0 on success, -1 on error
1422  *
1423  * Registers a new interface with dbus and assigns it a dbus object path.
1424  */
1425 int wpa_dbus_register_object_per_iface(
1426         struct ctrl_iface_dbus_new_priv *ctrl_iface,
1427         const char *path, const char *ifname,
1428         struct wpa_dbus_object_desc *obj_desc)
1429 {
1430         DBusConnection *con;
1431
1432         DBusObjectPathVTable vtable = {
1433                 &free_dbus_object_desc_cb, &message_handler,
1434                 NULL, NULL, NULL, NULL
1435         };
1436
1437         /* Do nothing if the control interface is not turned on */
1438         if (ctrl_iface == NULL)
1439                 return 0;
1440
1441         con = ctrl_iface->con;
1442         obj_desc->connection = con;
1443
1444         /* Register the message handler for the interface functions */
1445         if (!dbus_connection_register_object_path(con, path, &vtable,
1446                                                   obj_desc)) {
1447                 perror("wpa_dbus_register_iface [dbus]");
1448                 wpa_printf(MSG_ERROR, "Could not set up DBus message "
1449                            "handler for interface %s\n"
1450                            "and object %s.", ifname, path);
1451                 return -1;
1452         }
1453
1454         return 0;
1455 }
1456
1457
1458 /**
1459  * wpa_dbus_unregister_object_per_iface - Unregisters DBus object
1460  * @ctrl_iface: Pointer to dbus private data
1461  * @path: DBus path to object which will be unregistered
1462  * Returns: Zero on success and -1 on failure
1463  *
1464  * Unregisters DBus object given by its path
1465  */
1466 int wpa_dbus_unregister_object_per_iface(
1467         struct ctrl_iface_dbus_new_priv *ctrl_iface, const char *path)
1468 {
1469         DBusConnection *con = ctrl_iface->con;
1470         if (!dbus_connection_unregister_object_path(con, path))
1471                 return -1;
1472
1473         return 0;
1474 }
1475
1476
1477 /**
1478  * wpa_dbus_method_register - Registers DBus method for given object
1479  * @obj_dsc: Object description for which a method will be registered
1480  * @dbus_interface: DBus interface under which method will be registered
1481  * @dbus_method: a name the method will be registered with
1482  * @method_handler: a function which will be called to handle this method call
1483  * @handler_argument: an additional argument passed to handler function
1484  * @argument_free_func: function used to free handler argument
1485  * @args: method arguments list
1486  * Returns: Zero on success and -1 on failure
1487  *
1488  * Registers DBus method under given name and interface for the object.
1489  * Method calls will be handled with given handling function and optional
1490  * argument passed to this function. Handler function is required to return
1491  * a DBusMessage pointer which will be response to method call. Any method
1492  * call before being handled must have registered appropriate handler by
1493  * using this function.
1494  */
1495 int wpa_dbus_method_register(struct wpa_dbus_object_desc *obj_dsc,
1496                              const char *dbus_interface,
1497                              const char *dbus_method,
1498                              WPADBusMethodHandler method_handler,
1499                              void *handler_argument,
1500                              WPADBusArgumentFreeFunction argument_free_func,
1501                              const struct wpa_dbus_argument args[])
1502 {
1503         struct wpa_dbus_method_desc *method_dsc = obj_dsc->methods;
1504         struct wpa_dbus_method_desc *prev_desc;
1505         int args_num = 0;
1506         int interface_len, method_len, i, len, error;
1507
1508         prev_desc = NULL;
1509         while (method_dsc) {
1510                 prev_desc = method_dsc;
1511                 method_dsc = method_dsc->next;
1512         }
1513
1514         /* count args */
1515         if (args) {
1516                 while (args[args_num].name && args[args_num].type)
1517                         args_num++;
1518         }
1519
1520         method_dsc = os_zalloc(sizeof(struct wpa_dbus_method_desc) +
1521                                args_num * sizeof(struct wpa_dbus_argument));
1522         if (!method_dsc)
1523                 goto err;
1524
1525         if (prev_desc == NULL)
1526                 obj_dsc->methods = method_dsc;
1527         else
1528                 prev_desc->next = method_dsc;
1529
1530         /* copy interface name */
1531         interface_len = os_strlen(dbus_interface) + 1;
1532         method_dsc->dbus_interface = os_malloc(interface_len);
1533         if (!method_dsc->dbus_interface)
1534                 goto err;
1535         os_strncpy(method_dsc->dbus_interface, dbus_interface, interface_len);
1536
1537         /* copy method name */
1538         method_len = os_strlen(dbus_method) + 1;
1539         method_dsc->dbus_method = os_malloc(method_len);
1540         if (!method_dsc->dbus_method)
1541                 goto err;
1542         os_strncpy(method_dsc->dbus_method, dbus_method, method_len);
1543
1544         /* copy arguments */
1545         error = 0;
1546         method_dsc->args_num = args_num;
1547         for (i = 0; i < args_num; i++) {
1548                 len = os_strlen(args[i].name) + 1;
1549                 method_dsc->args[i].name = os_malloc(len);
1550                 if (!method_dsc->args[i].name) {
1551                         error = 1;
1552                         continue;
1553                 }
1554                 os_strncpy(method_dsc->args[i].name, args[i].name, len);
1555
1556                 len = os_strlen(args[i].type) + 1;
1557                 method_dsc->args[i].type = os_malloc(len);
1558                 if (!method_dsc->args[i].type) {
1559                         error = 1;
1560                         continue;
1561                 }
1562                 os_strncpy(method_dsc->args[i].type, args[i].type, len);
1563
1564                 method_dsc->args[i].dir = args[i].dir;
1565         }
1566         if (error)
1567                 goto err;
1568
1569         method_dsc->method_handler = method_handler;
1570         method_dsc->handler_argument = handler_argument;
1571         method_dsc->argument_free_func = argument_free_func;
1572         method_dsc->next = NULL;
1573
1574         return 0;
1575
1576 err:
1577         wpa_printf(MSG_WARNING, "Failed to register dbus method %s in "
1578                    "interface %s", dbus_method, dbus_interface);
1579         if (method_dsc) {
1580                 os_free(method_dsc->dbus_interface);
1581                 os_free(method_dsc->dbus_method);
1582                 for (i = 0; i < method_dsc->args_num; i++) {
1583                         os_free(method_dsc->args[i].name);
1584                         os_free(method_dsc->args[i].type);
1585                 }
1586
1587                 if (prev_desc == NULL)
1588                         obj_dsc->methods = NULL;
1589                 else
1590                         prev_desc->next = NULL;
1591
1592                 os_free(method_dsc);
1593         }
1594
1595         return -1;
1596 }
1597
1598
1599 /**
1600  * wpa_dbus_signal_register - Registers DBus signal for given object
1601  * @obj_dsc: Object description for which a signal will be registered
1602  * @dbus_interface: DBus interface under which signal will be registered
1603  * @dbus_signal: a name the signal will be registered with
1604  * @args: signal arguments list
1605  * Returns: Zero on success and -1 on failure
1606  *
1607  * Registers DBus signal under given name and interface for the object.
1608  * Signal registration is NOT required in order to send signals, but not
1609  * registered signals will not be respected in introspection data
1610  * therefore it is highly recommended to register every signal before
1611  * using it.
1612  */
1613 int wpa_dbus_signal_register(struct wpa_dbus_object_desc *obj_dsc,
1614                              const char *dbus_interface,
1615                              const char *dbus_signal,
1616                              const struct wpa_dbus_argument args[])
1617 {
1618
1619         struct wpa_dbus_signal_desc *signal_dsc = obj_dsc->signals;
1620         struct wpa_dbus_signal_desc *prev_desc;
1621         int args_num = 0;
1622         int interface_len, signal_len, i, len, error = 0;
1623
1624         prev_desc = NULL;
1625         while (signal_dsc) {
1626                 prev_desc = signal_dsc;
1627                 signal_dsc = signal_dsc->next;
1628         }
1629
1630         /* count args */
1631         if (args) {
1632                 while (args[args_num].name && args[args_num].type)
1633                         args_num++;
1634         }
1635
1636         signal_dsc = os_zalloc(sizeof(struct wpa_dbus_signal_desc) +
1637                                args_num * sizeof(struct wpa_dbus_argument));
1638         if (!signal_dsc)
1639                 goto err;
1640
1641         if (prev_desc == NULL)
1642                 obj_dsc->signals = signal_dsc;
1643         else
1644                 prev_desc->next = signal_dsc;
1645
1646         /* copy interface name */
1647         interface_len = strlen(dbus_interface) + 1;
1648         signal_dsc->dbus_interface = os_malloc(interface_len);
1649         if (!signal_dsc->dbus_interface)
1650                 goto err;
1651         os_strncpy(signal_dsc->dbus_interface, dbus_interface, interface_len);
1652
1653         /* copy signal name */
1654         signal_len = strlen(dbus_signal) + 1;
1655         signal_dsc->dbus_signal = os_malloc(signal_len);
1656         if (!signal_dsc->dbus_signal)
1657                 goto err;
1658         os_strncpy(signal_dsc->dbus_signal, dbus_signal, signal_len);
1659
1660         /* copy arguments */
1661         signal_dsc->args_num = args_num;
1662         for (i = 0; i < args_num; i++) {
1663                 len = os_strlen(args[i].name) + 1;
1664                 signal_dsc->args[i].name = os_malloc(len);
1665                 if (!signal_dsc->args[i].name) {
1666                         error = 1;
1667                         continue;
1668                 }
1669                 os_strncpy(signal_dsc->args[i].name, args[i].name, len);
1670
1671                 len = strlen(args[i].type) + 1;
1672                 signal_dsc->args[i].type = os_malloc(len);
1673                 if (!signal_dsc->args[i].type) {
1674                         error = 1;
1675                         continue;
1676                 }
1677                 os_strncpy(signal_dsc->args[i].type, args[i].type, len);
1678         }
1679         if (error)
1680                 goto err;
1681
1682         signal_dsc->next = NULL;
1683
1684         return 0;
1685
1686 err:
1687         wpa_printf(MSG_WARNING, "Failed to register dbus signal %s in "
1688                    "interface %s", dbus_signal, dbus_interface);
1689         if (signal_dsc) {
1690                 os_free(signal_dsc->dbus_interface);
1691                 os_free(signal_dsc->dbus_signal);
1692                 for (i = 0; i < signal_dsc->args_num; i++) {
1693                         os_free(signal_dsc->args[i].name);
1694                         os_free(signal_dsc->args[i].type);
1695                 }
1696
1697                 if (prev_desc == NULL)
1698                         obj_dsc->signals = NULL;
1699                 else
1700                         prev_desc->next = NULL;
1701
1702                 os_free(signal_dsc);
1703         }
1704
1705         return -1;
1706 }
1707
1708
1709 /**
1710  * wpa_dbus_property_register - Registers DBus property for given object
1711  * @obj_dsc: Object description for which a property will be registered
1712  * @dbus_interface: DBus interface under which method will be registered
1713  * @dbus_property: a name the property will be registered with
1714  * @type: a property type signature in form of DBus type description
1715  * @getter: a function called in order to get property value
1716  * @setter: a function called in order to set property value
1717  * @user_data: additional argument passed to setter or getter
1718  * @user_data_free_func: function used to free additional argument
1719  * @access: property access permissions specifier (R, W or RW)
1720  * Returns: Zero on success and -1 on failure
1721  *
1722  * Registers DBus property under given name and interface for the object.
1723  * Property are set with giver setter function and get with getter.
1724  * Additional argument is passed to getter or setter. Getter or setter
1725  * are required to return DBusMessage which is response to Set/Get method
1726  * calls. Every property must be registered by this function before being
1727  * used.
1728  */
1729 int wpa_dbus_property_register(struct wpa_dbus_object_desc *obj_dsc,
1730                                const char *dbus_interface,
1731                                const char *dbus_property,
1732                                const char *type,
1733                                WPADBusPropertyAccessor getter,
1734                                WPADBusPropertyAccessor setter,
1735                                void *user_data,
1736                                WPADBusArgumentFreeFunction user_data_free_func,
1737                                enum dbus_prop_access _access)
1738 {
1739         struct wpa_dbus_property_desc *property_dsc = obj_dsc->properties;
1740         struct wpa_dbus_property_desc *prev_desc;
1741         int interface_len, property_len, type_len;
1742
1743         prev_desc = NULL;
1744         while (property_dsc) {
1745                 prev_desc = property_dsc;
1746                 property_dsc = property_dsc->next;
1747         }
1748
1749         property_dsc = os_zalloc(sizeof(struct wpa_dbus_property_desc));
1750         if (!property_dsc)
1751                 goto err;
1752
1753         if (prev_desc == NULL)
1754                 obj_dsc->properties = property_dsc;
1755         else
1756                 prev_desc->next = property_dsc;
1757
1758         /* copy interface name */
1759         interface_len = os_strlen(dbus_interface) + 1;
1760         property_dsc->dbus_interface = os_malloc(interface_len);
1761         if (!property_dsc->dbus_interface)
1762                 goto err;
1763         os_strncpy(property_dsc->dbus_interface, dbus_interface,
1764                    interface_len);
1765
1766         /* copy property name */
1767         property_len = os_strlen(dbus_property) + 1;
1768         property_dsc->dbus_property = os_malloc(property_len);
1769         if (!property_dsc->dbus_property)
1770                 goto err;
1771         os_strncpy(property_dsc->dbus_property, dbus_property, property_len);
1772
1773         /* copy property type */
1774         type_len = os_strlen(type) + 1;
1775         property_dsc->type = os_malloc(type_len);
1776         if (!property_dsc->type)
1777                 goto err;
1778         os_strncpy(property_dsc->type, type, type_len);
1779
1780         property_dsc->getter = getter;
1781         property_dsc->setter = setter;
1782         property_dsc->user_data = user_data;
1783         property_dsc->user_data_free_func = user_data_free_func;
1784         property_dsc->access = _access;
1785         property_dsc->next = NULL;
1786
1787         return 0;
1788
1789 err:
1790         wpa_printf(MSG_WARNING, "Failed to register dbus property %s in "
1791                    "interface %s", dbus_property, dbus_interface);
1792         if (property_dsc) {
1793                 os_free(property_dsc->dbus_interface);
1794                 os_free(property_dsc->dbus_property);
1795                 os_free(property_dsc->type);
1796
1797                 if (prev_desc == NULL)
1798                         obj_dsc->properties = NULL;
1799                 else
1800                         prev_desc->next = NULL;
1801
1802                 os_free(property_dsc);
1803         }
1804
1805         return -1;
1806 }
1807
1808
1809 /**
1810  * wpas_dbus_signal_network_added - Send a property changed signal
1811  * @iface: dbus priv struct
1812  * @property_getter: propperty getter used to fetch new property value
1813  * @getter_arg: argument passed to property getter
1814  * @path: path to object which property has changed
1815  * @interface_name: signal and property interface
1816  * @property_name: name of property which has changed
1817  *
1818  * Notify listeners about changing value of some property. Signal
1819  * contains property name and its value fetched using given property
1820  * getter.
1821  */
1822 void wpa_dbus_signal_property_changed(struct ctrl_iface_dbus_new_priv *iface,
1823                                       WPADBusPropertyAccessor property_getter,
1824                                       void *getter_arg,
1825                                       const char *path,
1826                                       const char *interface_name,
1827                                       const char *property_name)
1828 {
1829
1830         DBusConnection *connection;
1831         DBusMessage *_signal, *getter_reply;
1832         DBusMessageIter prop_iter, signal_iter, dict_iter, entry_iter;
1833
1834         if (!iface)
1835                 return;
1836         connection = iface->con;
1837
1838         if (!property_getter) {
1839                 wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
1840                            "[dbus]: property getter not specified");
1841                 return;
1842         }
1843
1844         if (!path || !interface_name || !property_name) {
1845                 wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
1846                            "[dbus]: path interface of property not specified");
1847                 return;
1848         }
1849
1850         getter_reply = property_getter(NULL, getter_arg);
1851         if (!getter_reply ||
1852             dbus_message_get_type(getter_reply) == DBUS_MESSAGE_TYPE_ERROR) {
1853                 wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
1854                            "[dbus]: cannot get new value of property %s",
1855                            property_name);
1856                 return;
1857         }
1858
1859         _signal = dbus_message_new_signal(path, interface_name,
1860                                           "PropertiesChanged");
1861         if (!_signal) {
1862                 wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
1863                            "[dbus]: cannot allocate signal");
1864                 dbus_message_unref(getter_reply);
1865                 return;
1866         }
1867
1868         dbus_message_iter_init(getter_reply, &prop_iter);
1869         dbus_message_iter_init_append(_signal, &signal_iter);
1870
1871         if (!dbus_message_iter_open_container(&signal_iter, DBUS_TYPE_ARRAY,
1872                                               "{sv}", &dict_iter)) {
1873                 wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
1874                            "[dbus]: out of memory. cannot open dictionary");
1875                 goto err;
1876         }
1877
1878         if (!dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_DICT_ENTRY,
1879                                               NULL, &entry_iter)) {
1880                 wpa_printf(MSG_ERROR, "iwpa_dbus_signal_property_changed"
1881                            "[dbus]: out of memory. cannot open dictionary "
1882                            "element");
1883                 goto err;
1884         }
1885
1886         if (!dbus_message_iter_append_basic(&entry_iter, DBUS_TYPE_STRING,
1887                                             &property_name)) {
1888                 wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
1889                            "[dbus]: out of memory. cannot open add property "
1890                            "name");
1891                 goto err;
1892         }
1893
1894         recursive_iter_copy(&prop_iter, &entry_iter);
1895
1896         if (!dbus_message_iter_close_container(&dict_iter, &entry_iter)) {
1897                 wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
1898                            "[dbus]: out of memory. cannot close dictionary "
1899                            "element");
1900                 goto err;
1901         }
1902
1903         if (!dbus_message_iter_close_container(&signal_iter, &dict_iter)) {
1904                 wpa_printf(MSG_ERROR, "wpa_dbus_signal_property_changed"
1905                            "[dbus]: out of memory. cannot close dictionary");
1906                 goto err;
1907         }
1908
1909         dbus_connection_send(connection, _signal, NULL);
1910
1911 err:
1912         dbus_message_unref(getter_reply);
1913         dbus_message_unref(_signal);
1914
1915 }