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