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