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