LCOV - code coverage report
Current view: top level - wpa_supplicant/dbus - dbus_new_introspect.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1443382998 Lines: 124 127 97.6 %
Date: 2015-09-27 Functions: 14 14 100.0 %

          Line data    Source code
       1             : /*
       2             :  * wpa_supplicant - D-Bus introspection
       3             :  * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
       4             :  * Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
       5             :  * Copyright (c) 2010, Jouni Malinen <j@w1.fi>
       6             :  *
       7             :  * This software may be distributed under the terms of the BSD license.
       8             :  * See README for more details.
       9             :  */
      10             : 
      11             : #include "utils/includes.h"
      12             : 
      13             : #include "utils/common.h"
      14             : #include "utils/list.h"
      15             : #include "utils/wpabuf.h"
      16             : #include "dbus_common_i.h"
      17             : #include "dbus_new_helpers.h"
      18             : 
      19             : 
      20             : struct interfaces {
      21             :         struct dl_list list;
      22             :         char *dbus_interface;
      23             :         struct wpabuf *xml;
      24             : };
      25             : 
      26             : 
      27       11743 : static struct interfaces * add_interface(struct dl_list *list,
      28             :                                          const char *dbus_interface)
      29             : {
      30             :         struct interfaces *iface;
      31             : 
      32       21748 :         dl_list_for_each(iface, list, struct interfaces, list) {
      33       21393 :                 if (os_strcmp(iface->dbus_interface, dbus_interface) == 0)
      34       11388 :                         return iface; /* already in the list */
      35             :         }
      36             : 
      37         355 :         iface = os_zalloc(sizeof(struct interfaces));
      38         355 :         if (!iface)
      39           1 :                 return NULL;
      40         354 :         iface->dbus_interface = os_strdup(dbus_interface);
      41         354 :         iface->xml = wpabuf_alloc(6000);
      42         354 :         if (iface->dbus_interface == NULL || iface->xml == NULL) {
      43           2 :                 os_free(iface->dbus_interface);
      44           2 :                 wpabuf_free(iface->xml);
      45           2 :                 os_free(iface);
      46           2 :                 return NULL;
      47             :         }
      48         352 :         wpabuf_printf(iface->xml, "<interface name=\"%s\">", dbus_interface);
      49         352 :         dl_list_add_tail(list, &iface->list);
      50         352 :         return iface;
      51             : }
      52             : 
      53             : 
      54       10747 : static void add_arg(struct wpabuf *xml, const char *name, const char *type,
      55             :                     const char *direction)
      56             : {
      57       10747 :         wpabuf_printf(xml, "<arg name=\"%s\"", name);
      58       10747 :         if (type)
      59       10747 :                 wpabuf_printf(xml, " type=\"%s\"", type);
      60       10747 :         if (direction)
      61        5840 :                 wpabuf_printf(xml, " direction=\"%s\"", direction);
      62       10747 :         wpabuf_put_str(xml, "/>");
      63       10747 : }
      64             : 
      65             : 
      66        8516 : static void add_entry(struct wpabuf *xml, const char *type, const char *name,
      67             :                       const struct wpa_dbus_argument *args, int include_dir)
      68             : {
      69             :         const struct wpa_dbus_argument *arg;
      70             : 
      71        8516 :         if (args == NULL || args->name == NULL) {
      72        1566 :                 wpabuf_printf(xml, "<%s name=\"%s\"/>", type, name);
      73       10082 :                 return;
      74             :         }
      75        6950 :         wpabuf_printf(xml, "<%s name=\"%s\">", type, name);
      76       16273 :         for (arg = args; arg && arg->name; arg++) {
      77       13739 :                 add_arg(xml, arg->name, arg->type,
      78        4416 :                         include_dir ? (arg->dir == ARG_IN ? "in" : "out") :
      79             :                         NULL);
      80             :         }
      81        6950 :         wpabuf_printf(xml, "</%s>", type);
      82             : }
      83             : 
      84             : 
      85        3224 : static void add_property(struct wpabuf *xml,
      86             :                          const struct wpa_dbus_property_desc *dsc)
      87             : {
      88        6448 :         wpabuf_printf(xml, "<property name=\"%s\" type=\"%s\" "
      89             :                       "access=\"%s%s\"/>",
      90             :                       dsc->dbus_property, dsc->type,
      91        3224 :                       dsc->getter ? "read" : "",
      92        3224 :                       dsc->setter ? "write" : "");
      93        3224 : }
      94             : 
      95             : 
      96         178 : static void extract_interfaces_methods(
      97             :         struct dl_list *list, const struct wpa_dbus_method_desc *methods)
      98             : {
      99             :         const struct wpa_dbus_method_desc *dsc;
     100             :         struct interfaces *iface;
     101             : 
     102        4900 :         for (dsc = methods; dsc && dsc->dbus_method; dsc++) {
     103        4722 :                 iface = add_interface(list, dsc->dbus_interface);
     104        4722 :                 if (iface)
     105        4719 :                         add_entry(iface->xml, "method", dsc->dbus_method,
     106        4719 :                                   dsc->args, 1);
     107             :         }
     108         178 : }
     109             : 
     110             : 
     111         178 : static void extract_interfaces_signals(
     112             :         struct dl_list *list, const struct wpa_dbus_signal_desc *signals)
     113             : {
     114             :         const struct wpa_dbus_signal_desc *dsc;
     115             :         struct interfaces *iface;
     116             : 
     117        3975 :         for (dsc = signals; dsc && dsc->dbus_signal; dsc++) {
     118        3797 :                 iface = add_interface(list, dsc->dbus_interface);
     119        3797 :                 if (iface)
     120        3797 :                         add_entry(iface->xml, "signal", dsc->dbus_signal,
     121        3797 :                                   dsc->args, 0);
     122             :         }
     123         178 : }
     124             : 
     125             : 
     126         178 : static void extract_interfaces_properties(
     127             :         struct dl_list *list, const struct wpa_dbus_property_desc *properties)
     128             : {
     129             :         const struct wpa_dbus_property_desc *dsc;
     130             :         struct interfaces *iface;
     131             : 
     132        3402 :         for (dsc = properties; dsc && dsc->dbus_property; dsc++) {
     133        3224 :                 iface = add_interface(list, dsc->dbus_interface);
     134        3224 :                 if (iface)
     135        3224 :                         add_property(iface->xml, dsc);
     136             :         }
     137         178 : }
     138             : 
     139             : 
     140             : /**
     141             :  * extract_interfaces - Extract interfaces from methods, signals and props
     142             :  * @list: Interface list to be filled
     143             :  * @obj_dsc: Description of object from which interfaces will be extracted
     144             :  *
     145             :  * Iterates over all methods, signals, and properties registered with an
     146             :  * object and collects all declared DBus interfaces and create interfaces'
     147             :  * node in XML root node for each. Returned list elements contain interface
     148             :  * name and XML node of corresponding interface.
     149             :  */
     150         178 : static void extract_interfaces(struct dl_list *list,
     151             :                                struct wpa_dbus_object_desc *obj_dsc)
     152             : {
     153         178 :         extract_interfaces_methods(list, obj_dsc->methods);
     154         178 :         extract_interfaces_signals(list, obj_dsc->signals);
     155         178 :         extract_interfaces_properties(list, obj_dsc->properties);
     156         178 : }
     157             : 
     158             : 
     159         178 : static void add_interfaces(struct dl_list *list, struct wpabuf *xml)
     160             : {
     161             :         struct interfaces *iface, *n;
     162             : 
     163         530 :         dl_list_for_each_safe(iface, n, list, struct interfaces, list) {
     164         352 :                 if (wpabuf_len(iface->xml) + 20 < wpabuf_tailroom(xml)) {
     165         352 :                         wpabuf_put_buf(xml, iface->xml);
     166         352 :                         wpabuf_put_str(xml, "</interface>");
     167             :                 } else {
     168           0 :                         wpa_printf(MSG_DEBUG,
     169             :                                    "dbus: Not enough room for add_interfaces inspect data: tailroom %u, add %u",
     170           0 :                                    (unsigned int) wpabuf_tailroom(xml),
     171           0 :                                    (unsigned int) wpabuf_len(iface->xml));
     172             :                 }
     173         352 :                 dl_list_del(&iface->list);
     174         352 :                 wpabuf_free(iface->xml);
     175         352 :                 os_free(iface->dbus_interface);
     176         352 :                 os_free(iface);
     177             :         }
     178         178 : }
     179             : 
     180             : 
     181         178 : static void add_child_nodes(struct wpabuf *xml, DBusConnection *con,
     182             :                             const char *path)
     183             : {
     184             :         char **children;
     185             :         int i;
     186             : 
     187             :         /* add child nodes to introspection tree */
     188         178 :         dbus_connection_list_registered(con, path, &children);
     189         669 :         for (i = 0; children[i]; i++)
     190         491 :                 wpabuf_printf(xml, "<node name=\"%s\"/>", children[i]);
     191         178 :         dbus_free_string_array(children);
     192         178 : }
     193             : 
     194             : 
     195         178 : static void add_introspectable_interface(struct wpabuf *xml)
     196             : {
     197         178 :         wpabuf_printf(xml, "<interface name=\"%s\">"
     198             :                       "<method name=\"%s\">"
     199             :                       "<arg name=\"data\" type=\"s\" direction=\"out\"/>"
     200             :                       "</method>"
     201             :                       "</interface>",
     202             :                       WPA_DBUS_INTROSPECTION_INTERFACE,
     203             :                       WPA_DBUS_INTROSPECTION_METHOD);
     204         178 : }
     205             : 
     206             : 
     207         178 : static void add_properties_interface(struct wpabuf *xml)
     208             : {
     209         178 :         wpabuf_printf(xml, "<interface name=\"%s\">",
     210             :                       WPA_DBUS_PROPERTIES_INTERFACE);
     211             : 
     212         178 :         wpabuf_printf(xml, "<method name=\"%s\">", WPA_DBUS_PROPERTIES_GET);
     213         178 :         add_arg(xml, "interface", "s", "in");
     214         178 :         add_arg(xml, "propname", "s", "in");
     215         178 :         add_arg(xml, "value", "v", "out");
     216         178 :         wpabuf_put_str(xml, "</method>");
     217             : 
     218         178 :         wpabuf_printf(xml, "<method name=\"%s\">", WPA_DBUS_PROPERTIES_GETALL);
     219         178 :         add_arg(xml, "interface", "s", "in");
     220         178 :         add_arg(xml, "props", "a{sv}", "out");
     221         178 :         wpabuf_put_str(xml, "</method>");
     222             : 
     223         178 :         wpabuf_printf(xml, "<method name=\"%s\">", WPA_DBUS_PROPERTIES_SET);
     224         178 :         add_arg(xml, "interface", "s", "in");
     225         178 :         add_arg(xml, "propname", "s", "in");
     226         178 :         add_arg(xml, "value", "v", "in");
     227         178 :         wpabuf_put_str(xml, "</method>");
     228             : 
     229         178 :         wpabuf_put_str(xml, "</interface>");
     230         178 : }
     231             : 
     232             : 
     233         178 : static void add_wpas_interfaces(struct wpabuf *xml,
     234             :                                 struct wpa_dbus_object_desc *obj_dsc)
     235             : {
     236             :         struct dl_list ifaces;
     237             : 
     238         178 :         dl_list_init(&ifaces);
     239         178 :         extract_interfaces(&ifaces, obj_dsc);
     240         178 :         add_interfaces(&ifaces, xml);
     241         178 : }
     242             : 
     243             : 
     244             : /**
     245             :  * wpa_dbus_introspect - Responds for Introspect calls on object
     246             :  * @message: Message with Introspect call
     247             :  * @obj_dsc: Object description on which Introspect was called
     248             :  * Returns: Message with introspection result XML string as only argument
     249             :  *
     250             :  * Iterates over all methods, signals and properties registered with
     251             :  * object and generates introspection data for the object as XML string.
     252             :  */
     253         179 : DBusMessage * wpa_dbus_introspect(DBusMessage *message,
     254             :                                   struct wpa_dbus_object_desc *obj_dsc)
     255             : {
     256             : 
     257             :         DBusMessage *reply;
     258             :         struct wpabuf *xml;
     259             : 
     260         179 :         xml = wpabuf_alloc(15000);
     261         179 :         if (xml == NULL)
     262           1 :                 return NULL;
     263             : 
     264         178 :         wpabuf_put_str(xml, "<?xml version=\"1.0\"?>\n");
     265         178 :         wpabuf_put_str(xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE);
     266         178 :         wpabuf_put_str(xml, "<node>");
     267             : 
     268         178 :         add_introspectable_interface(xml);
     269         178 :         add_properties_interface(xml);
     270         178 :         add_wpas_interfaces(xml, obj_dsc);
     271         178 :         add_child_nodes(xml, obj_dsc->connection,
     272             :                         dbus_message_get_path(message));
     273             : 
     274         178 :         wpabuf_put_str(xml, "</node>\n");
     275             : 
     276         178 :         reply = dbus_message_new_method_return(message);
     277         178 :         if (reply) {
     278         178 :                 const char *intro_str = wpabuf_head(xml);
     279             : 
     280         178 :                 dbus_message_append_args(reply, DBUS_TYPE_STRING, &intro_str,
     281             :                                          DBUS_TYPE_INVALID);
     282             :         }
     283         178 :         wpabuf_free(xml);
     284             : 
     285         178 :         return reply;
     286             : }

Generated by: LCOV version 1.10