D-Bus: Don't do <deny send_interface="..." /> in dbus service file
[mech_eap.git] / wpa_supplicant / dbus / dbus_new_introspect.c
index cf34505..aee105b 100644 (file)
@@ -4,14 +4,8 @@
  * Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
  * Copyright (c) 2010, Jouni Malinen <j@w1.fi>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
  */
 
 #include "utils/includes.h"
@@ -30,53 +24,116 @@ struct interfaces {
 };
 
 
-static void add_interface(struct dl_list *list, const char *dbus_interface)
+static struct interfaces * add_interface(struct dl_list *list,
+                                        const char *dbus_interface)
 {
        struct interfaces *iface;
 
        dl_list_for_each(iface, list, struct interfaces, list) {
                if (os_strcmp(iface->dbus_interface, dbus_interface) == 0)
-                       return; /* already in the list */
+                       return iface; /* already in the list */
        }
 
        iface = os_zalloc(sizeof(struct interfaces));
        if (!iface)
-               return;
-       iface->xml = wpabuf_alloc(3000);
-       if (iface->xml == NULL) {
+               return NULL;
+       iface->dbus_interface = os_strdup(dbus_interface);
+       iface->xml = wpabuf_alloc(15000);
+       if (iface->dbus_interface == NULL || iface->xml == NULL) {
+               os_free(iface->dbus_interface);
+               wpabuf_free(iface->xml);
                os_free(iface);
-               return;
+               return NULL;
        }
        wpabuf_printf(iface->xml, "<interface name=\"%s\">", dbus_interface);
        dl_list_add_tail(list, &iface->list);
-       iface->dbus_interface = os_strdup(dbus_interface);
+       return iface;
 }
 
 
-static void extract_interfaces_methods(struct dl_list *list,
-                                      struct wpa_dbus_method_desc *methods)
+static void add_arg(struct wpabuf *xml, const char *name, const char *type,
+                   const char *direction)
 {
-       struct wpa_dbus_method_desc *dsc;
-       for (dsc = methods; dsc; dsc = dsc->next)
-               add_interface(list, dsc->dbus_interface);
+       wpabuf_printf(xml, "<arg name=\"%s\"", name);
+       if (type)
+               wpabuf_printf(xml, " type=\"%s\"", type);
+       if (direction)
+               wpabuf_printf(xml, " direction=\"%s\"", direction);
+       wpabuf_put_str(xml, "/>");
 }
 
 
-static void extract_interfaces_signals(struct dl_list *list,
-                                      struct wpa_dbus_signal_desc *signals)
+static void add_entry(struct wpabuf *xml, const char *type, const char *name,
+                     const struct wpa_dbus_argument *args, int include_dir)
 {
-       struct wpa_dbus_signal_desc *dsc;
-       for (dsc = signals; dsc; dsc = dsc->next)
-               add_interface(list, dsc->dbus_interface);
+       const struct wpa_dbus_argument *arg;
+
+       if (args == NULL || args->name == NULL) {
+               wpabuf_printf(xml, "<%s name=\"%s\"/>", type, name);
+               return;
+       }
+       wpabuf_printf(xml, "<%s name=\"%s\">", type, name);
+       for (arg = args; arg && arg->name; arg++) {
+               add_arg(xml, arg->name, arg->type,
+                       include_dir ? (arg->dir == ARG_IN ? "in" : "out") :
+                       NULL);
+       }
+       wpabuf_printf(xml, "</%s>", type);
+}
+
+
+static void add_property(struct wpabuf *xml,
+                        const struct wpa_dbus_property_desc *dsc)
+{
+       wpabuf_printf(xml, "<property name=\"%s\" type=\"%s\" "
+                     "access=\"%s%s\"/>",
+                     dsc->dbus_property, dsc->type,
+                     dsc->getter ? "read" : "",
+                     dsc->setter ? "write" : "");
+}
+
+
+static void extract_interfaces_methods(
+       struct dl_list *list, const struct wpa_dbus_method_desc *methods)
+{
+       const struct wpa_dbus_method_desc *dsc;
+       struct interfaces *iface;
+
+       for (dsc = methods; dsc && dsc->dbus_method; dsc++) {
+               iface = add_interface(list, dsc->dbus_interface);
+               if (iface)
+                       add_entry(iface->xml, "method", dsc->dbus_method,
+                                 dsc->args, 1);
+       }
+}
+
+
+static void extract_interfaces_signals(
+       struct dl_list *list, const struct wpa_dbus_signal_desc *signals)
+{
+       const struct wpa_dbus_signal_desc *dsc;
+       struct interfaces *iface;
+
+       for (dsc = signals; dsc && dsc->dbus_signal; dsc++) {
+               iface = add_interface(list, dsc->dbus_interface);
+               if (iface)
+                       add_entry(iface->xml, "signal", dsc->dbus_signal,
+                                 dsc->args, 0);
+       }
 }
 
 
 static void extract_interfaces_properties(
-       struct dl_list *list, struct wpa_dbus_property_desc *properties)
+       struct dl_list *list, const struct wpa_dbus_property_desc *properties)
 {
-       struct wpa_dbus_property_desc *dsc;
-       for (dsc = properties; dsc; dsc = dsc->next)
-               add_interface(list, dsc->dbus_interface);
+       const struct wpa_dbus_property_desc *dsc;
+       struct interfaces *iface;
+
+       for (dsc = properties; dsc && dsc->dbus_property; dsc++) {
+               iface = add_interface(list, dsc->dbus_interface);
+               if (iface)
+                       add_property(iface->xml, dsc);
+       }
 }
 
 
@@ -102,9 +159,17 @@ static void extract_interfaces(struct dl_list *list,
 static void add_interfaces(struct dl_list *list, struct wpabuf *xml)
 {
        struct interfaces *iface, *n;
+
        dl_list_for_each_safe(iface, n, list, struct interfaces, list) {
-               wpabuf_put_buf(xml, iface->xml);
-               wpabuf_put_str(xml, "</interface>");
+               if (wpabuf_len(iface->xml) + 20 < wpabuf_tailroom(xml)) {
+                       wpabuf_put_buf(xml, iface->xml);
+                       wpabuf_put_str(xml, "</interface>");
+               } else {
+                       wpa_printf(MSG_DEBUG,
+                                  "dbus: Not enough room for add_interfaces inspect data: tailroom %u, add %u",
+                                  (unsigned int) wpabuf_tailroom(xml),
+                                  (unsigned int) wpabuf_len(iface->xml));
+               }
                dl_list_del(&iface->list);
                wpabuf_free(iface->xml);
                os_free(iface->dbus_interface);
@@ -113,18 +178,6 @@ static void add_interfaces(struct dl_list *list, struct wpabuf *xml)
 }
 
 
-static struct interfaces * get_interface(struct dl_list *list,
-                                        const char *dbus_interface)
-{
-       struct interfaces *iface;
-       dl_list_for_each(iface, list, struct interfaces, list) {
-               if (os_strcmp(iface->dbus_interface, dbus_interface) == 0)
-                       return iface;
-       }
-       return NULL;
-}
-
-
 static void add_child_nodes(struct wpabuf *xml, DBusConnection *con,
                            const char *path)
 {
@@ -139,18 +192,6 @@ static void add_child_nodes(struct wpabuf *xml, DBusConnection *con,
 }
 
 
-static void add_arg(struct wpabuf *xml, const char *name, const char *type,
-                   const char *direction)
-{
-       wpabuf_printf(xml, "<arg name=\"%s\"", name);
-       if (type)
-               wpabuf_printf(xml, " type=\"%s\"", type);
-       if (direction)
-               wpabuf_printf(xml, " direction=\"%s\"", direction);
-       wpabuf_put_str(xml, "/>");
-}
-
-
 static void add_introspectable_interface(struct wpabuf *xml)
 {
        wpabuf_printf(xml, "<interface name=\"%s\">"
@@ -189,91 +230,13 @@ static void add_properties_interface(struct wpabuf *xml)
 }
 
 
-static void add_entry(struct wpabuf *xml, char *type, char *name, int args_num,
-                     struct wpa_dbus_argument *args, int include_dir)
-{
-       int i;
-       if (args_num == 0) {
-               wpabuf_printf(xml, "<%s name=\"%s\"/>", type, name);
-               return;
-       }
-       wpabuf_printf(xml, "<%s name=\"%s\">", type, name);
-       for (i = 0; i < args_num; i++) {
-               struct wpa_dbus_argument *arg = &args[i];
-               add_arg(xml, arg->name, arg->type,
-                       include_dir ? (arg->dir == ARG_IN ? "in" : "out") :
-                       NULL);
-       }
-       wpabuf_printf(xml, "</%s>", type);
-}
-
-
-static void add_property(struct wpabuf *xml,
-                        struct wpa_dbus_property_desc *dsc)
-{
-       wpabuf_printf(xml, "<property name=\"%s\" type=\"%s\" access=\"%s\"/>",
-                     dsc->dbus_property, dsc->type,
-                     (dsc->access == R ? "read" :
-                      (dsc->access == W ? "write" : "readwrite")));
-}
-
-
-static void create_method_nodes(struct dl_list *list,
-                               struct wpa_dbus_method_desc *methods)
-{
-       struct wpa_dbus_method_desc *dsc;
-       struct interfaces *iface;
-
-       for (dsc = methods; dsc; dsc = dsc->next) {
-               iface = get_interface(list, dsc->dbus_interface);
-               if (!iface)
-                       continue;
-               add_entry(iface->xml, "method", dsc->dbus_method,
-                         dsc->args_num, dsc->args, 1);
-       }
-}
-
-
-static void create_signal_nodes(struct dl_list *list,
-                               struct wpa_dbus_signal_desc *signals)
-{
-       struct wpa_dbus_signal_desc *dsc;
-       struct interfaces *iface;
-
-       for (dsc = signals; dsc; dsc = dsc->next) {
-               iface = get_interface(list, dsc->dbus_interface);
-               if (!iface)
-                       continue;
-               add_entry(iface->xml, "signal", dsc->dbus_signal,
-                         dsc->args_num, dsc->args, 0);
-       }
-}
-
-
-static void create_property_nodes(struct dl_list *list,
-                                 struct wpa_dbus_property_desc *properties)
-{
-       struct wpa_dbus_property_desc *dsc;
-       struct interfaces *iface;
-
-       for (dsc = properties; dsc; dsc = dsc->next) {
-               iface = get_interface(list, dsc->dbus_interface);
-               if (!iface)
-                       continue;
-               add_property(iface->xml, dsc);
-       }
-}
-
-
 static void add_wpas_interfaces(struct wpabuf *xml,
                                struct wpa_dbus_object_desc *obj_dsc)
 {
        struct dl_list ifaces;
+
        dl_list_init(&ifaces);
        extract_interfaces(&ifaces, obj_dsc);
-       create_method_nodes(&ifaces, obj_dsc->methods);
-       create_signal_nodes(&ifaces, obj_dsc->signals);
-       create_property_nodes(&ifaces, obj_dsc->properties);
        add_interfaces(&ifaces, xml);
 }
 
@@ -293,9 +256,8 @@ DBusMessage * wpa_dbus_introspect(DBusMessage *message,
 
        DBusMessage *reply;
        struct wpabuf *xml;
-       const char *intro_str;
 
-       xml = wpabuf_alloc(4000);
+       xml = wpabuf_alloc(20000);
        if (xml == NULL)
                return NULL;
 
@@ -306,20 +268,18 @@ DBusMessage * wpa_dbus_introspect(DBusMessage *message,
        add_introspectable_interface(xml);
        add_properties_interface(xml);
        add_wpas_interfaces(xml, obj_dsc);
-
        add_child_nodes(xml, obj_dsc->connection,
                        dbus_message_get_path(message));
+
        wpabuf_put_str(xml, "</node>\n");
 
        reply = dbus_message_new_method_return(message);
-       if (reply == NULL) {
-               wpabuf_free(xml);
-               return NULL;
-       }
+       if (reply) {
+               const char *intro_str = wpabuf_head(xml);
 
-       intro_str = wpabuf_head(xml);
-       dbus_message_append_args(reply, DBUS_TYPE_STRING, &intro_str,
-                                DBUS_TYPE_INVALID);
+               dbus_message_append_args(reply, DBUS_TYPE_STRING, &intro_str,
+                                        DBUS_TYPE_INVALID);
+       }
        wpabuf_free(xml);
 
        return reply;