Branch data 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 : 0 : static struct interfaces * add_interface(struct dl_list *list,
28 : : const char *dbus_interface)
29 : : {
30 : : struct interfaces *iface;
31 : :
32 [ # # ]: 0 : dl_list_for_each(iface, list, struct interfaces, list) {
33 [ # # ]: 0 : if (os_strcmp(iface->dbus_interface, dbus_interface) == 0)
34 : 0 : return iface; /* already in the list */
35 : : }
36 : :
37 : 0 : iface = os_zalloc(sizeof(struct interfaces));
38 [ # # ]: 0 : if (!iface)
39 : 0 : return NULL;
40 : 0 : iface->xml = wpabuf_alloc(6000);
41 [ # # ]: 0 : if (iface->xml == NULL) {
42 : 0 : os_free(iface);
43 : 0 : return NULL;
44 : : }
45 : 0 : wpabuf_printf(iface->xml, "<interface name=\"%s\">", dbus_interface);
46 : 0 : dl_list_add_tail(list, &iface->list);
47 : 0 : iface->dbus_interface = os_strdup(dbus_interface);
48 : 0 : return iface;
49 : : }
50 : :
51 : :
52 : 0 : static void add_arg(struct wpabuf *xml, const char *name, const char *type,
53 : : const char *direction)
54 : : {
55 : 0 : wpabuf_printf(xml, "<arg name=\"%s\"", name);
56 [ # # ]: 0 : if (type)
57 : 0 : wpabuf_printf(xml, " type=\"%s\"", type);
58 [ # # ]: 0 : if (direction)
59 : 0 : wpabuf_printf(xml, " direction=\"%s\"", direction);
60 : 0 : wpabuf_put_str(xml, "/>");
61 : 0 : }
62 : :
63 : :
64 : 0 : static 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 [ # # ][ # # ]: 0 : if (args == NULL || args->name == NULL) {
70 : 0 : wpabuf_printf(xml, "<%s name=\"%s\"/>", type, name);
71 : 0 : return;
72 : : }
73 : 0 : wpabuf_printf(xml, "<%s name=\"%s\">", type, name);
74 [ # # ][ # # ]: 0 : for (arg = args; arg && arg->name; arg++) {
75 [ # # ]: 0 : add_arg(xml, arg->name, arg->type,
76 [ # # ]: 0 : include_dir ? (arg->dir == ARG_IN ? "in" : "out") :
77 : : NULL);
78 : : }
79 : 0 : wpabuf_printf(xml, "</%s>", type);
80 : : }
81 : :
82 : :
83 : 0 : static void add_property(struct wpabuf *xml,
84 : : const struct wpa_dbus_property_desc *dsc)
85 : : {
86 [ # # ][ # # ]: 0 : wpabuf_printf(xml, "<property name=\"%s\" type=\"%s\" "
87 : : "access=\"%s%s\"/>",
88 : : dsc->dbus_property, dsc->type,
89 : 0 : dsc->getter ? "read" : "",
90 : 0 : dsc->setter ? "write" : "");
91 : 0 : }
92 : :
93 : :
94 : 0 : static 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 [ # # ][ # # ]: 0 : for (dsc = methods; dsc && dsc->dbus_method; dsc++) {
100 : 0 : iface = add_interface(list, dsc->dbus_interface);
101 [ # # ]: 0 : if (iface)
102 : 0 : add_entry(iface->xml, "method", dsc->dbus_method,
103 : 0 : dsc->args, 1);
104 : : }
105 : 0 : }
106 : :
107 : :
108 : 0 : static 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 [ # # ][ # # ]: 0 : for (dsc = signals; dsc && dsc->dbus_signal; dsc++) {
114 : 0 : iface = add_interface(list, dsc->dbus_interface);
115 [ # # ]: 0 : if (iface)
116 : 0 : add_entry(iface->xml, "signal", dsc->dbus_signal,
117 : 0 : dsc->args, 0);
118 : : }
119 : 0 : }
120 : :
121 : :
122 : 0 : static 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 [ # # ][ # # ]: 0 : for (dsc = properties; dsc && dsc->dbus_property; dsc++) {
128 : 0 : iface = add_interface(list, dsc->dbus_interface);
129 [ # # ]: 0 : if (iface)
130 : 0 : add_property(iface->xml, dsc);
131 : : }
132 : 0 : }
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 : : */
145 : 0 : static void extract_interfaces(struct dl_list *list,
146 : : struct wpa_dbus_object_desc *obj_dsc)
147 : : {
148 : 0 : extract_interfaces_methods(list, obj_dsc->methods);
149 : 0 : extract_interfaces_signals(list, obj_dsc->signals);
150 : 0 : extract_interfaces_properties(list, obj_dsc->properties);
151 : 0 : }
152 : :
153 : :
154 : 0 : static void add_interfaces(struct dl_list *list, struct wpabuf *xml)
155 : : {
156 : : struct interfaces *iface, *n;
157 [ # # ]: 0 : dl_list_for_each_safe(iface, n, list, struct interfaces, list) {
158 [ # # ]: 0 : if (wpabuf_len(iface->xml) + 20 < wpabuf_tailroom(xml)) {
159 : 0 : wpabuf_put_buf(xml, iface->xml);
160 : 0 : wpabuf_put_str(xml, "</interface>");
161 : : } else {
162 : 0 : wpa_printf(MSG_DEBUG, "dbus: Not enough room for "
163 : : "add_interfaces inspect data: tailroom %u, "
164 : : "add %u",
165 : 0 : (unsigned int) wpabuf_tailroom(xml),
166 : 0 : (unsigned int) wpabuf_len(iface->xml));
167 : : }
168 : 0 : dl_list_del(&iface->list);
169 : 0 : wpabuf_free(iface->xml);
170 : 0 : os_free(iface->dbus_interface);
171 : 0 : os_free(iface);
172 : : }
173 : 0 : }
174 : :
175 : :
176 : 0 : static 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 : 0 : dbus_connection_list_registered(con, path, &children);
184 [ # # ]: 0 : for (i = 0; children[i]; i++)
185 : 0 : wpabuf_printf(xml, "<node name=\"%s\"/>", children[i]);
186 : 0 : dbus_free_string_array(children);
187 : 0 : }
188 : :
189 : :
190 : 0 : static void add_introspectable_interface(struct wpabuf *xml)
191 : : {
192 : 0 : 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 : 0 : }
200 : :
201 : :
202 : 0 : static void add_properties_interface(struct wpabuf *xml)
203 : : {
204 : 0 : wpabuf_printf(xml, "<interface name=\"%s\">",
205 : : WPA_DBUS_PROPERTIES_INTERFACE);
206 : :
207 : 0 : wpabuf_printf(xml, "<method name=\"%s\">", WPA_DBUS_PROPERTIES_GET);
208 : 0 : add_arg(xml, "interface", "s", "in");
209 : 0 : add_arg(xml, "propname", "s", "in");
210 : 0 : add_arg(xml, "value", "v", "out");
211 : 0 : wpabuf_put_str(xml, "</method>");
212 : :
213 : 0 : wpabuf_printf(xml, "<method name=\"%s\">", WPA_DBUS_PROPERTIES_GETALL);
214 : 0 : add_arg(xml, "interface", "s", "in");
215 : 0 : add_arg(xml, "props", "a{sv}", "out");
216 : 0 : wpabuf_put_str(xml, "</method>");
217 : :
218 : 0 : wpabuf_printf(xml, "<method name=\"%s\">", WPA_DBUS_PROPERTIES_SET);
219 : 0 : add_arg(xml, "interface", "s", "in");
220 : 0 : add_arg(xml, "propname", "s", "in");
221 : 0 : add_arg(xml, "value", "v", "in");
222 : 0 : wpabuf_put_str(xml, "</method>");
223 : :
224 : 0 : wpabuf_put_str(xml, "</interface>");
225 : 0 : }
226 : :
227 : :
228 : 0 : static void add_wpas_interfaces(struct wpabuf *xml,
229 : : struct wpa_dbus_object_desc *obj_dsc)
230 : : {
231 : : struct dl_list ifaces;
232 : 0 : dl_list_init(&ifaces);
233 : 0 : extract_interfaces(&ifaces, obj_dsc);
234 : 0 : add_interfaces(&ifaces, xml);
235 : 0 : }
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 : : */
247 : 0 : DBusMessage * wpa_dbus_introspect(DBusMessage *message,
248 : : struct wpa_dbus_object_desc *obj_dsc)
249 : : {
250 : :
251 : : DBusMessage *reply;
252 : : struct wpabuf *xml;
253 : :
254 : 0 : xml = wpabuf_alloc(10000);
255 [ # # ]: 0 : if (xml == NULL)
256 : 0 : return NULL;
257 : :
258 : 0 : wpabuf_put_str(xml, "<?xml version=\"1.0\"?>\n");
259 : 0 : wpabuf_put_str(xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE);
260 : 0 : wpabuf_put_str(xml, "<node>");
261 : :
262 : 0 : add_introspectable_interface(xml);
263 : 0 : add_properties_interface(xml);
264 : 0 : add_wpas_interfaces(xml, obj_dsc);
265 : 0 : add_child_nodes(xml, obj_dsc->connection,
266 : : dbus_message_get_path(message));
267 : :
268 : 0 : wpabuf_put_str(xml, "</node>\n");
269 : :
270 : 0 : reply = dbus_message_new_method_return(message);
271 [ # # ]: 0 : if (reply) {
272 : 0 : const char *intro_str = wpabuf_head(xml);
273 : 0 : dbus_message_append_args(reply, DBUS_TYPE_STRING, &intro_str,
274 : : DBUS_TYPE_INVALID);
275 : : }
276 : 0 : wpabuf_free(xml);
277 : :
278 : 0 : return reply;
279 : : }
|