00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "utils/includes.h"
00018
00019 #include "utils/common.h"
00020 #include "utils/list.h"
00021 #include "utils/wpabuf.h"
00022 #include "dbus_common_i.h"
00023 #include "dbus_new_helpers.h"
00024
00025
00026 struct interfaces {
00027 struct dl_list list;
00028 char *dbus_interface;
00029 struct wpabuf *xml;
00030 };
00031
00032
00033 static struct interfaces * add_interface(struct dl_list *list,
00034 const char *dbus_interface)
00035 {
00036 struct interfaces *iface;
00037
00038 dl_list_for_each(iface, list, struct interfaces, list) {
00039 if (os_strcmp(iface->dbus_interface, dbus_interface) == 0)
00040 return iface;
00041 }
00042
00043 iface = os_zalloc(sizeof(struct interfaces));
00044 if (!iface)
00045 return NULL;
00046 iface->xml = wpabuf_alloc(3000);
00047 if (iface->xml == NULL) {
00048 os_free(iface);
00049 return NULL;
00050 }
00051 wpabuf_printf(iface->xml, "<interface name=\"%s\">", dbus_interface);
00052 dl_list_add_tail(list, &iface->list);
00053 iface->dbus_interface = os_strdup(dbus_interface);
00054 return iface;
00055 }
00056
00057
00058 static void add_arg(struct wpabuf *xml, const char *name, const char *type,
00059 const char *direction)
00060 {
00061 wpabuf_printf(xml, "<arg name=\"%s\"", name);
00062 if (type)
00063 wpabuf_printf(xml, " type=\"%s\"", type);
00064 if (direction)
00065 wpabuf_printf(xml, " direction=\"%s\"", direction);
00066 wpabuf_put_str(xml, "/>");
00067 }
00068
00069
00070 static void add_entry(struct wpabuf *xml, const char *type, const char *name,
00071 const struct wpa_dbus_argument *args, int include_dir)
00072 {
00073 const struct wpa_dbus_argument *arg;
00074
00075 if (args == NULL || args->name == NULL) {
00076 wpabuf_printf(xml, "<%s name=\"%s\"/>", type, name);
00077 return;
00078 }
00079 wpabuf_printf(xml, "<%s name=\"%s\">", type, name);
00080 for (arg = args; arg && arg->name; arg++) {
00081 add_arg(xml, arg->name, arg->type,
00082 include_dir ? (arg->dir == ARG_IN ? "in" : "out") :
00083 NULL);
00084 }
00085 wpabuf_printf(xml, "</%s>", type);
00086 }
00087
00088
00089 static void add_property(struct wpabuf *xml,
00090 const struct wpa_dbus_property_desc *dsc)
00091 {
00092 wpabuf_printf(xml, "<property name=\"%s\" type=\"%s\" access=\"%s\"/>",
00093 dsc->dbus_property, dsc->type,
00094 (dsc->access == R ? "read" :
00095 (dsc->access == W ? "write" : "readwrite")));
00096 }
00097
00098
00099 static void extract_interfaces_methods(
00100 struct dl_list *list, const struct wpa_dbus_method_desc *methods)
00101 {
00102 const struct wpa_dbus_method_desc *dsc;
00103 struct interfaces *iface;
00104 for (dsc = methods; dsc && dsc->dbus_method; dsc++) {
00105 iface = add_interface(list, dsc->dbus_interface);
00106 if (iface)
00107 add_entry(iface->xml, "method", dsc->dbus_method,
00108 dsc->args, 1);
00109 }
00110 }
00111
00112
00113 static void extract_interfaces_signals(
00114 struct dl_list *list, const struct wpa_dbus_signal_desc *signals)
00115 {
00116 const struct wpa_dbus_signal_desc *dsc;
00117 struct interfaces *iface;
00118 for (dsc = signals; dsc && dsc->dbus_signal; dsc++) {
00119 iface = add_interface(list, dsc->dbus_interface);
00120 if (iface)
00121 add_entry(iface->xml, "signal", dsc->dbus_signal,
00122 dsc->args, 0);
00123 }
00124 }
00125
00126
00127 static void extract_interfaces_properties(
00128 struct dl_list *list, const struct wpa_dbus_property_desc *properties)
00129 {
00130 const struct wpa_dbus_property_desc *dsc;
00131 struct interfaces *iface;
00132 for (dsc = properties; dsc && dsc->dbus_property; dsc++) {
00133 iface = add_interface(list, dsc->dbus_interface);
00134 if (iface)
00135 add_property(iface->xml, dsc);
00136 }
00137 }
00138
00139
00150 static void extract_interfaces(struct dl_list *list,
00151 struct wpa_dbus_object_desc *obj_dsc)
00152 {
00153 extract_interfaces_methods(list, obj_dsc->methods);
00154 extract_interfaces_signals(list, obj_dsc->signals);
00155 extract_interfaces_properties(list, obj_dsc->properties);
00156 }
00157
00158
00159 static void add_interfaces(struct dl_list *list, struct wpabuf *xml)
00160 {
00161 struct interfaces *iface, *n;
00162 dl_list_for_each_safe(iface, n, list, struct interfaces, list) {
00163 if (wpabuf_len(iface->xml) + 20 < wpabuf_tailroom(xml)) {
00164 wpabuf_put_buf(xml, iface->xml);
00165 wpabuf_put_str(xml, "</interface>");
00166 }
00167 dl_list_del(&iface->list);
00168 wpabuf_free(iface->xml);
00169 os_free(iface->dbus_interface);
00170 os_free(iface);
00171 }
00172 }
00173
00174
00175 static void add_child_nodes(struct wpabuf *xml, DBusConnection *con,
00176 const char *path)
00177 {
00178 char **children;
00179 int i;
00180
00181
00182 dbus_connection_list_registered(con, path, &children);
00183 for (i = 0; children[i]; i++)
00184 wpabuf_printf(xml, "<node name=\"%s\"/>", children[i]);
00185 dbus_free_string_array(children);
00186 }
00187
00188
00189 static void add_introspectable_interface(struct wpabuf *xml)
00190 {
00191 wpabuf_printf(xml, "<interface name=\"%s\">"
00192 "<method name=\"%s\">"
00193 "<arg name=\"data\" type=\"s\" direction=\"out\"/>"
00194 "</method>"
00195 "</interface>",
00196 WPA_DBUS_INTROSPECTION_INTERFACE,
00197 WPA_DBUS_INTROSPECTION_METHOD);
00198 }
00199
00200
00201 static void add_properties_interface(struct wpabuf *xml)
00202 {
00203 wpabuf_printf(xml, "<interface name=\"%s\">",
00204 WPA_DBUS_PROPERTIES_INTERFACE);
00205
00206 wpabuf_printf(xml, "<method name=\"%s\">", WPA_DBUS_PROPERTIES_GET);
00207 add_arg(xml, "interface", "s", "in");
00208 add_arg(xml, "propname", "s", "in");
00209 add_arg(xml, "value", "v", "out");
00210 wpabuf_put_str(xml, "</method>");
00211
00212 wpabuf_printf(xml, "<method name=\"%s\">", WPA_DBUS_PROPERTIES_GETALL);
00213 add_arg(xml, "interface", "s", "in");
00214 add_arg(xml, "props", "a{sv}", "out");
00215 wpabuf_put_str(xml, "</method>");
00216
00217 wpabuf_printf(xml, "<method name=\"%s\">", WPA_DBUS_PROPERTIES_SET);
00218 add_arg(xml, "interface", "s", "in");
00219 add_arg(xml, "propname", "s", "in");
00220 add_arg(xml, "value", "v", "in");
00221 wpabuf_put_str(xml, "</method>");
00222
00223 wpabuf_put_str(xml, "</interface>");
00224 }
00225
00226
00227 static void add_wpas_interfaces(struct wpabuf *xml,
00228 struct wpa_dbus_object_desc *obj_dsc)
00229 {
00230 struct dl_list ifaces;
00231 dl_list_init(&ifaces);
00232 extract_interfaces(&ifaces, obj_dsc);
00233 add_interfaces(&ifaces, xml);
00234 }
00235
00236
00246 DBusMessage * wpa_dbus_introspect(DBusMessage *message,
00247 struct wpa_dbus_object_desc *obj_dsc)
00248 {
00249
00250 DBusMessage *reply;
00251 struct wpabuf *xml;
00252
00253 xml = wpabuf_alloc(4000);
00254 if (xml == NULL)
00255 return NULL;
00256
00257 wpabuf_put_str(xml, "<?xml version=\"1.0\"?>\n");
00258 wpabuf_put_str(xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE);
00259 wpabuf_put_str(xml, "<node>");
00260
00261 add_introspectable_interface(xml);
00262 add_properties_interface(xml);
00263 add_wpas_interfaces(xml, obj_dsc);
00264 add_child_nodes(xml, obj_dsc->connection,
00265 dbus_message_get_path(message));
00266
00267 wpabuf_put_str(xml, "</node>\n");
00268
00269 reply = dbus_message_new_method_return(message);
00270 if (reply) {
00271 const char *intro_str = wpabuf_head(xml);
00272 dbus_message_append_args(reply, DBUS_TYPE_STRING, &intro_str,
00273 DBUS_TYPE_INVALID);
00274 }
00275 wpabuf_free(xml);
00276
00277 return reply;
00278 }