$search
00001 /* 00002 * wpa_supplicant - D-Bus introspection 00003 * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc. 00004 * Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com> 00005 * Copyright (c) 2010, Jouni Malinen <j@w1.fi> 00006 * 00007 * This program is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License version 2 as 00009 * published by the Free Software Foundation. 00010 * 00011 * Alternatively, this software may be distributed under the terms of BSD 00012 * license. 00013 * 00014 * See README and COPYING for more details. 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; /* already in the list */ 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 /* add child nodes to introspection tree */ 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 }