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