dbus: Move introspection support into a separate file
This commit is contained in:
parent
64bde6d730
commit
04551ee6d6
5 changed files with 532 additions and 527 deletions
|
@ -1083,6 +1083,7 @@ ifndef DBUS_INCLUDE
|
||||||
DBUS_INCLUDE := $(shell pkg-config --cflags dbus-1)
|
DBUS_INCLUDE := $(shell pkg-config --cflags dbus-1)
|
||||||
endif
|
endif
|
||||||
ifdef CONFIG_CTRL_IFACE_DBUS_INTRO
|
ifdef CONFIG_CTRL_IFACE_DBUS_INTRO
|
||||||
|
DBUS_OBJS += dbus/dbus_new_introspect.o
|
||||||
DBUS_CFLAGS += -DCONFIG_CTRL_IFACE_DBUS_INTRO
|
DBUS_CFLAGS += -DCONFIG_CTRL_IFACE_DBUS_INTRO
|
||||||
DBUS_INCLUDE += $(shell xml2-config --cflags)
|
DBUS_INCLUDE += $(shell xml2-config --cflags)
|
||||||
DBUS_LIBS += $(shell xml2-config --libs)
|
DBUS_LIBS += $(shell xml2-config --libs)
|
||||||
|
|
|
@ -70,6 +70,7 @@ LIB_OBJS= \
|
||||||
dbus_new.o \
|
dbus_new.o \
|
||||||
dbus_new_handlers.o \
|
dbus_new_handlers.o \
|
||||||
dbus_new_helpers.o \
|
dbus_new_helpers.o \
|
||||||
|
dbus_new_introspect.o \
|
||||||
dbus_dict_helpers.o
|
dbus_dict_helpers.o
|
||||||
|
|
||||||
ifdef CONFIG_WPS
|
ifdef CONFIG_WPS
|
||||||
|
|
|
@ -16,534 +16,10 @@
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "eloop.h"
|
|
||||||
#include "dbus_common.h"
|
#include "dbus_common.h"
|
||||||
#include "dbus_common_i.h"
|
#include "dbus_common_i.h"
|
||||||
#include "dbus_new_helpers.h"
|
#include "dbus_new_helpers.h"
|
||||||
|
|
||||||
/**
|
|
||||||
* struct wpa_dbus_method_desc - DBus method description
|
|
||||||
*/
|
|
||||||
struct wpa_dbus_method_desc {
|
|
||||||
/* pointer to next description in list */
|
|
||||||
struct wpa_dbus_method_desc *next;
|
|
||||||
|
|
||||||
/* method interface */
|
|
||||||
char *dbus_interface;
|
|
||||||
/* method name */
|
|
||||||
char *dbus_method;
|
|
||||||
|
|
||||||
/* method handling function */
|
|
||||||
WPADBusMethodHandler method_handler;
|
|
||||||
|
|
||||||
/* number of method arguments */
|
|
||||||
int args_num;
|
|
||||||
/* array of arguments */
|
|
||||||
struct wpa_dbus_argument args[];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* struct wpa_dbus_signal_desc - DBus signal description
|
|
||||||
*/
|
|
||||||
struct wpa_dbus_signal_desc {
|
|
||||||
/* pointer to next description in list */
|
|
||||||
struct wpa_dbus_signal_desc *next;
|
|
||||||
|
|
||||||
/* signal interface */
|
|
||||||
char *dbus_interface;
|
|
||||||
/* signal name */
|
|
||||||
char *dbus_signal;
|
|
||||||
|
|
||||||
/* number of signal arguments */
|
|
||||||
int args_num;
|
|
||||||
/* array of arguments */
|
|
||||||
struct wpa_dbus_argument args[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* struct wpa_dbus_property_desc - DBus property description
|
|
||||||
*/
|
|
||||||
struct wpa_dbus_property_desc {
|
|
||||||
/* pointer to next description in list */
|
|
||||||
struct wpa_dbus_property_desc *next;
|
|
||||||
|
|
||||||
/* property interface */
|
|
||||||
char *dbus_interface;
|
|
||||||
/* property name */
|
|
||||||
char *dbus_property;
|
|
||||||
/* property type signature in DBus type notation */
|
|
||||||
char *type;
|
|
||||||
|
|
||||||
/* property access permissions */
|
|
||||||
enum dbus_prop_access access;
|
|
||||||
|
|
||||||
/* property getter function */
|
|
||||||
WPADBusPropertyAccessor getter;
|
|
||||||
/* property setter function */
|
|
||||||
WPADBusPropertyAccessor setter;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_CTRL_IFACE_DBUS_INTRO
|
|
||||||
#include <libxml/tree.h>
|
|
||||||
|
|
||||||
struct interfaces {
|
|
||||||
struct interfaces *next;
|
|
||||||
char *dbus_interface;
|
|
||||||
xmlNodePtr interface_node;
|
|
||||||
};
|
|
||||||
#endif /* CONFIG_CTRL_IFACE_DBUS_INTRO */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_CTRL_IFACE_DBUS_INTRO
|
|
||||||
|
|
||||||
/**
|
|
||||||
* extract_interfaces - Extract interfaces from methods, signals and props
|
|
||||||
* @obj_dsc: Description of object from which interfaces will be extracted
|
|
||||||
* @root_node: root node of XML introspection document
|
|
||||||
* Returns: List of interfaces found in object description
|
|
||||||
*
|
|
||||||
* Iterates over all methods, signals and properties registered with
|
|
||||||
* object and collects all declared DBus interfaces and create interface's
|
|
||||||
* node in XML root node for each. Returned list elements contains interface
|
|
||||||
* name and XML node of corresponding interface.
|
|
||||||
*/
|
|
||||||
static struct interfaces * extract_interfaces(
|
|
||||||
struct wpa_dbus_object_desc *obj_dsc, xmlNodePtr root_node)
|
|
||||||
{
|
|
||||||
struct wpa_dbus_method_desc *method_dsc = obj_dsc->methods;
|
|
||||||
struct wpa_dbus_signal_desc *signal_dsc = obj_dsc->signals;
|
|
||||||
struct wpa_dbus_property_desc *property_dsc = obj_dsc->properties;
|
|
||||||
struct interfaces *head = NULL;
|
|
||||||
struct interfaces *iface, *last;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
/* extract interfaces from methods */
|
|
||||||
while (method_dsc) {
|
|
||||||
iface = head;
|
|
||||||
last = NULL;
|
|
||||||
|
|
||||||
/* go to next method if its interface is already extracted */
|
|
||||||
while (iface) {
|
|
||||||
if (!os_strcmp(iface->dbus_interface,
|
|
||||||
method_dsc->dbus_interface))
|
|
||||||
break;
|
|
||||||
last = iface;
|
|
||||||
iface = iface->next;
|
|
||||||
}
|
|
||||||
if (iface) {
|
|
||||||
method_dsc = method_dsc->next;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
iface = os_zalloc(sizeof(struct interfaces));
|
|
||||||
if (!iface) {
|
|
||||||
wpa_printf(MSG_ERROR, "Not enough memory to create "
|
|
||||||
"interface introspection data");
|
|
||||||
method_dsc = method_dsc->next;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (last)
|
|
||||||
last->next = iface;
|
|
||||||
else
|
|
||||||
head = iface;
|
|
||||||
|
|
||||||
len = os_strlen(method_dsc->dbus_interface) + 1;
|
|
||||||
iface->dbus_interface = os_malloc(len);
|
|
||||||
if (!iface->dbus_interface) {
|
|
||||||
wpa_printf(MSG_ERROR, "Not enough memory to create "
|
|
||||||
"interface introspection data (interface "
|
|
||||||
"name)");
|
|
||||||
method_dsc = method_dsc->next;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
os_strncpy(iface->dbus_interface, method_dsc->dbus_interface,
|
|
||||||
len);
|
|
||||||
|
|
||||||
iface->interface_node = xmlNewChild(root_node, NULL,
|
|
||||||
BAD_CAST "interface",
|
|
||||||
NULL);
|
|
||||||
xmlNewProp(iface->interface_node, BAD_CAST "name",
|
|
||||||
BAD_CAST method_dsc->dbus_interface);
|
|
||||||
|
|
||||||
method_dsc = method_dsc->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* extract interfaces from signals */
|
|
||||||
while (signal_dsc) {
|
|
||||||
iface = head;
|
|
||||||
last = NULL;
|
|
||||||
|
|
||||||
/* go to next signal if its interface is already extracted */
|
|
||||||
while (iface) {
|
|
||||||
if (!os_strcmp(iface->dbus_interface,
|
|
||||||
signal_dsc->dbus_interface))
|
|
||||||
break;
|
|
||||||
last = iface;
|
|
||||||
iface = iface->next;
|
|
||||||
}
|
|
||||||
if (iface) {
|
|
||||||
signal_dsc = signal_dsc->next;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
iface = os_zalloc(sizeof(struct interfaces));
|
|
||||||
if (!iface) {
|
|
||||||
wpa_printf(MSG_ERROR, "Not enough memory to create "
|
|
||||||
"interface introspection data");
|
|
||||||
signal_dsc = signal_dsc->next;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (last)
|
|
||||||
last->next = iface;
|
|
||||||
else
|
|
||||||
head = iface;
|
|
||||||
|
|
||||||
len = os_strlen(signal_dsc->dbus_interface) + 1;
|
|
||||||
iface->dbus_interface = os_malloc(len);
|
|
||||||
if (!iface->dbus_interface) {
|
|
||||||
wpa_printf(MSG_ERROR, "Not enough memory to create "
|
|
||||||
"interface introspection data (interface "
|
|
||||||
"name)");
|
|
||||||
signal_dsc = signal_dsc->next;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
os_strncpy(iface->dbus_interface, signal_dsc->dbus_interface,
|
|
||||||
len);
|
|
||||||
|
|
||||||
iface->interface_node = xmlNewChild(root_node, NULL,
|
|
||||||
BAD_CAST "interface",
|
|
||||||
NULL);
|
|
||||||
xmlNewProp(iface->interface_node, BAD_CAST "name",
|
|
||||||
BAD_CAST signal_dsc->dbus_interface);
|
|
||||||
|
|
||||||
signal_dsc = signal_dsc->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* extract interfaces from properties */
|
|
||||||
while (property_dsc) {
|
|
||||||
iface = head;
|
|
||||||
last = NULL;
|
|
||||||
|
|
||||||
/* go to next property if its interface is already extracted */
|
|
||||||
while (iface) {
|
|
||||||
if (!os_strcmp(iface->dbus_interface,
|
|
||||||
property_dsc->dbus_interface))
|
|
||||||
break;
|
|
||||||
last = iface;
|
|
||||||
iface = iface->next;
|
|
||||||
}
|
|
||||||
if (iface) {
|
|
||||||
property_dsc = property_dsc->next;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
iface = os_zalloc(sizeof(struct interfaces));
|
|
||||||
if (!iface) {
|
|
||||||
wpa_printf(MSG_ERROR, "Not enough memory to create "
|
|
||||||
"interface introspection data");
|
|
||||||
property_dsc = property_dsc->next;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (last)
|
|
||||||
last->next = iface;
|
|
||||||
else
|
|
||||||
head = iface;
|
|
||||||
|
|
||||||
len = os_strlen(property_dsc->dbus_interface) + 1;
|
|
||||||
iface->dbus_interface = os_malloc(len);
|
|
||||||
if (!iface->dbus_interface) {
|
|
||||||
wpa_printf(MSG_ERROR, "Not enough memory to create "
|
|
||||||
"interface introspection data (interface "
|
|
||||||
"name)");
|
|
||||||
property_dsc = property_dsc->next;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
os_strncpy(iface->dbus_interface, property_dsc->dbus_interface,
|
|
||||||
len);
|
|
||||||
|
|
||||||
iface->interface_node = xmlNewChild(root_node, NULL,
|
|
||||||
BAD_CAST "interface",
|
|
||||||
NULL);
|
|
||||||
xmlNewProp(iface->interface_node, BAD_CAST "name",
|
|
||||||
BAD_CAST property_dsc->dbus_interface);
|
|
||||||
|
|
||||||
property_dsc = property_dsc->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return head;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* introspect - Responds for Introspect calls on object
|
|
||||||
* @message: Message with Introspect call
|
|
||||||
* @obj_dsc: Object description on which Introspect was called
|
|
||||||
* Returns: Message with introspection result XML string as only argument
|
|
||||||
*
|
|
||||||
* Iterates over all methods, signals and properties registered with
|
|
||||||
* object and generates introspection data for the object as XML string.
|
|
||||||
*/
|
|
||||||
static DBusMessage * introspect(DBusMessage *message,
|
|
||||||
struct wpa_dbus_object_desc *obj_dsc)
|
|
||||||
{
|
|
||||||
|
|
||||||
DBusMessage *reply;
|
|
||||||
struct interfaces *ifaces, *tmp;
|
|
||||||
struct wpa_dbus_signal_desc *signal_dsc;
|
|
||||||
struct wpa_dbus_method_desc *method_dsc;
|
|
||||||
struct wpa_dbus_property_desc *property_dsc;
|
|
||||||
xmlChar *intro_str;
|
|
||||||
char **children;
|
|
||||||
int i, s;
|
|
||||||
|
|
||||||
xmlDocPtr doc = NULL;
|
|
||||||
xmlNodePtr root_node = NULL, node = NULL, iface_node = NULL;
|
|
||||||
xmlNodePtr method_node = NULL, signal_node = NULL;
|
|
||||||
xmlNodePtr property_node = NULL, arg_node = NULL;
|
|
||||||
|
|
||||||
/* root node and dtd */
|
|
||||||
doc = xmlNewDoc(BAD_CAST "1.0");
|
|
||||||
root_node = xmlNewNode(NULL, BAD_CAST "node");
|
|
||||||
xmlDocSetRootElement(doc, root_node);
|
|
||||||
xmlCreateIntSubset(doc, BAD_CAST "node",
|
|
||||||
BAD_CAST DBUS_INTROSPECT_1_0_XML_PUBLIC_IDENTIFIER,
|
|
||||||
BAD_CAST DBUS_INTROSPECT_1_0_XML_SYSTEM_IDENTIFIER);
|
|
||||||
|
|
||||||
/* Add Introspectable interface */
|
|
||||||
iface_node = xmlNewChild(root_node, NULL, BAD_CAST "interface", NULL);
|
|
||||||
xmlNewProp(iface_node, BAD_CAST "name",
|
|
||||||
BAD_CAST WPA_DBUS_INTROSPECTION_INTERFACE);
|
|
||||||
|
|
||||||
/* Add Introspect method */
|
|
||||||
method_node = xmlNewChild(iface_node, NULL, BAD_CAST "method", NULL);
|
|
||||||
xmlNewProp(method_node, BAD_CAST "name",
|
|
||||||
BAD_CAST WPA_DBUS_INTROSPECTION_METHOD);
|
|
||||||
arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
|
|
||||||
xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "data");
|
|
||||||
xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
|
|
||||||
xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "out");
|
|
||||||
|
|
||||||
|
|
||||||
/* Add Properties interface */
|
|
||||||
iface_node = xmlNewChild(root_node, NULL,
|
|
||||||
BAD_CAST "interface", NULL);
|
|
||||||
xmlNewProp(iface_node, BAD_CAST "name",
|
|
||||||
BAD_CAST WPA_DBUS_PROPERTIES_INTERFACE);
|
|
||||||
|
|
||||||
/* Add Get method */
|
|
||||||
method_node = xmlNewChild(iface_node, NULL, BAD_CAST "method", NULL);
|
|
||||||
xmlNewProp(method_node, BAD_CAST "name",
|
|
||||||
BAD_CAST WPA_DBUS_PROPERTIES_GET);
|
|
||||||
arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
|
|
||||||
xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "interface");
|
|
||||||
xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
|
|
||||||
xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
|
|
||||||
arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
|
|
||||||
xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "propname");
|
|
||||||
xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
|
|
||||||
xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
|
|
||||||
arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
|
|
||||||
xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "value");
|
|
||||||
xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "v");
|
|
||||||
xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "out");
|
|
||||||
method_node = xmlNewChild(iface_node, NULL, BAD_CAST "method", NULL);
|
|
||||||
|
|
||||||
/* Add GetAll method */
|
|
||||||
xmlNewProp(method_node, BAD_CAST "name",
|
|
||||||
BAD_CAST WPA_DBUS_PROPERTIES_GETALL);
|
|
||||||
arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
|
|
||||||
xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "interface");
|
|
||||||
xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
|
|
||||||
xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
|
|
||||||
arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
|
|
||||||
xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "props");
|
|
||||||
xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "a{sv}");
|
|
||||||
xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "out");
|
|
||||||
method_node = xmlNewChild(iface_node, NULL, BAD_CAST "method", NULL);
|
|
||||||
|
|
||||||
/* Add Set method */
|
|
||||||
xmlNewProp(method_node, BAD_CAST "name",
|
|
||||||
BAD_CAST WPA_DBUS_PROPERTIES_SET);
|
|
||||||
arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
|
|
||||||
xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "interface");
|
|
||||||
xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
|
|
||||||
xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
|
|
||||||
arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
|
|
||||||
xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "propname");
|
|
||||||
xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
|
|
||||||
xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
|
|
||||||
arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
|
|
||||||
xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "value");
|
|
||||||
xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "v");
|
|
||||||
xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
|
|
||||||
|
|
||||||
/* get all interfaces registered with object */
|
|
||||||
ifaces = extract_interfaces(obj_dsc, root_node);
|
|
||||||
|
|
||||||
/* create methods' nodes */
|
|
||||||
method_dsc = obj_dsc->methods;
|
|
||||||
while (method_dsc) {
|
|
||||||
|
|
||||||
struct interfaces *iface = ifaces;
|
|
||||||
while (iface) {
|
|
||||||
if (!os_strcmp(iface->dbus_interface,
|
|
||||||
method_dsc->dbus_interface))
|
|
||||||
break;
|
|
||||||
iface = iface->next;
|
|
||||||
}
|
|
||||||
if (!iface)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
iface_node = iface->interface_node;
|
|
||||||
method_node = xmlNewChild(iface_node, NULL, BAD_CAST "method",
|
|
||||||
NULL);
|
|
||||||
xmlNewProp(method_node, BAD_CAST "name",
|
|
||||||
BAD_CAST method_dsc->dbus_method);
|
|
||||||
|
|
||||||
/* create args' nodes */
|
|
||||||
for (i = 0; i < method_dsc->args_num; i++) {
|
|
||||||
struct wpa_dbus_argument arg = method_dsc->args[i];
|
|
||||||
arg_node = xmlNewChild(method_node, NULL,
|
|
||||||
BAD_CAST "arg", NULL);
|
|
||||||
if (arg.name && strlen(arg.name)) {
|
|
||||||
xmlNewProp(arg_node, BAD_CAST "name",
|
|
||||||
BAD_CAST arg.name);
|
|
||||||
}
|
|
||||||
xmlNewProp(arg_node, BAD_CAST "type",
|
|
||||||
BAD_CAST arg.type);
|
|
||||||
xmlNewProp(arg_node, BAD_CAST "direction",
|
|
||||||
BAD_CAST (arg.dir == ARG_IN ?
|
|
||||||
"in" : "out"));
|
|
||||||
}
|
|
||||||
method_dsc = method_dsc->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create signals' nodes */
|
|
||||||
signal_dsc = obj_dsc->signals;
|
|
||||||
while (signal_dsc) {
|
|
||||||
|
|
||||||
struct interfaces *iface = ifaces;
|
|
||||||
while (iface) {
|
|
||||||
if (!os_strcmp(iface->dbus_interface,
|
|
||||||
signal_dsc->dbus_interface))
|
|
||||||
break;
|
|
||||||
iface = iface->next;
|
|
||||||
}
|
|
||||||
if (!iface)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
iface_node = iface->interface_node;
|
|
||||||
signal_node = xmlNewChild(iface_node, NULL, BAD_CAST "signal",
|
|
||||||
NULL);
|
|
||||||
xmlNewProp(signal_node, BAD_CAST "name",
|
|
||||||
BAD_CAST signal_dsc->dbus_signal);
|
|
||||||
|
|
||||||
/* create args' nodes */
|
|
||||||
for (i = 0; i < signal_dsc->args_num; i++) {
|
|
||||||
struct wpa_dbus_argument arg = signal_dsc->args[i];
|
|
||||||
arg_node = xmlNewChild(signal_node, NULL,
|
|
||||||
BAD_CAST "arg", NULL);
|
|
||||||
if (arg.name && strlen(arg.name)) {
|
|
||||||
xmlNewProp(arg_node, BAD_CAST "name",
|
|
||||||
BAD_CAST arg.name);
|
|
||||||
}
|
|
||||||
xmlNewProp(arg_node, BAD_CAST "type",
|
|
||||||
BAD_CAST arg.type);
|
|
||||||
}
|
|
||||||
signal_dsc = signal_dsc->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create properties' nodes */
|
|
||||||
property_dsc = obj_dsc->properties;
|
|
||||||
while (property_dsc) {
|
|
||||||
|
|
||||||
struct interfaces *iface = ifaces;
|
|
||||||
while (iface) {
|
|
||||||
if (!os_strcmp(iface->dbus_interface,
|
|
||||||
property_dsc->dbus_interface))
|
|
||||||
break;
|
|
||||||
iface = iface->next;
|
|
||||||
}
|
|
||||||
if (!iface)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
iface_node = iface->interface_node;
|
|
||||||
property_node = xmlNewChild(iface_node, NULL,
|
|
||||||
BAD_CAST "property", NULL);
|
|
||||||
xmlNewProp(property_node, BAD_CAST "name",
|
|
||||||
BAD_CAST property_dsc->dbus_property);
|
|
||||||
xmlNewProp(property_node, BAD_CAST "type",
|
|
||||||
BAD_CAST property_dsc->type);
|
|
||||||
xmlNewProp(property_node, BAD_CAST "access", BAD_CAST
|
|
||||||
(property_dsc->access == R ? "read" :
|
|
||||||
(property_dsc->access == W ?
|
|
||||||
"write" : "readwrite")));
|
|
||||||
|
|
||||||
property_dsc = property_dsc->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* add child nodes to introspection tree; */
|
|
||||||
dbus_connection_list_registered(obj_dsc->connection,
|
|
||||||
dbus_message_get_path(message),
|
|
||||||
&children);
|
|
||||||
for (i = 0; children[i]; i++) {
|
|
||||||
node = xmlNewChild(root_node, NULL, BAD_CAST "node", NULL);
|
|
||||||
xmlNewProp(node, BAD_CAST "name", BAD_CAST children[i]);
|
|
||||||
}
|
|
||||||
dbus_free_string_array(children);
|
|
||||||
|
|
||||||
|
|
||||||
xmlDocDumpFormatMemory(doc, &intro_str, &s, 1);
|
|
||||||
|
|
||||||
xmlFreeDoc(doc);
|
|
||||||
|
|
||||||
while (ifaces) {
|
|
||||||
tmp = ifaces;
|
|
||||||
ifaces = ifaces->next;
|
|
||||||
os_free(tmp->dbus_interface);
|
|
||||||
os_free(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
reply = dbus_message_new_method_return(message);
|
|
||||||
if (reply == NULL) {
|
|
||||||
xmlFree(intro_str);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
dbus_message_append_args(reply, DBUS_TYPE_STRING, &intro_str,
|
|
||||||
DBUS_TYPE_INVALID);
|
|
||||||
|
|
||||||
xmlFree(intro_str);
|
|
||||||
|
|
||||||
return reply;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* CONFIG_CTRL_IFACE_DBUS_INTRO */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* introspect - Responds for Introspect calls on object
|
|
||||||
* @message: Message with Introspect call
|
|
||||||
* @obj_dsc: Object description on which Introspect was called
|
|
||||||
* Returns: Message with introspection result XML string as only argument
|
|
||||||
*
|
|
||||||
* Returns error informing that introspection support was not compiled.
|
|
||||||
*/
|
|
||||||
static DBusMessage * introspect(DBusMessage *message,
|
|
||||||
struct wpa_dbus_object_desc *obj_dsc)
|
|
||||||
{
|
|
||||||
return dbus_message_new_error(message, DBUS_ERROR_UNKNOWN_METHOD,
|
|
||||||
"wpa_supplicant was compiled without "
|
|
||||||
"introspection support.");
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* CONFIG_CTRL_IFACE_DBUS_INTRO */
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* recursive_iter_copy - Reads arguments from one iterator and
|
* recursive_iter_copy - Reads arguments from one iterator and
|
||||||
|
@ -935,9 +411,16 @@ static DBusHandlerResult message_handler(DBusConnection *connection,
|
||||||
if (!os_strncmp(WPA_DBUS_INTROSPECTION_METHOD, method,
|
if (!os_strncmp(WPA_DBUS_INTROSPECTION_METHOD, method,
|
||||||
WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) &&
|
WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) &&
|
||||||
!os_strncmp(WPA_DBUS_INTROSPECTION_INTERFACE, msg_interface,
|
!os_strncmp(WPA_DBUS_INTROSPECTION_INTERFACE, msg_interface,
|
||||||
WPAS_DBUS_INTERFACE_MAX))
|
WPAS_DBUS_INTERFACE_MAX)) {
|
||||||
reply = introspect(message, obj_dsc);
|
#ifdef CONFIG_CTRL_IFACE_DBUS_INTRO
|
||||||
else if (!os_strncmp(WPA_DBUS_PROPERTIES_INTERFACE, msg_interface,
|
reply = wpa_dbus_introspect(message, obj_dsc);
|
||||||
|
#else /* CONFIG_CTRL_IFACE_DBUS_INTRO */
|
||||||
|
reply = dbus_message_new_error(
|
||||||
|
message, DBUS_ERROR_UNKNOWN_METHOD,
|
||||||
|
"wpa_supplicant was compiled without "
|
||||||
|
"introspection support.");
|
||||||
|
#endif /* CONFIG_CTRL_IFACE_DBUS_INTRO */
|
||||||
|
} else if (!os_strncmp(WPA_DBUS_PROPERTIES_INTERFACE, msg_interface,
|
||||||
WPAS_DBUS_INTERFACE_MAX)) {
|
WPAS_DBUS_INTERFACE_MAX)) {
|
||||||
/* if message is properties method call */
|
/* if message is properties method call */
|
||||||
reply = properties_handler(message, obj_dsc);
|
reply = properties_handler(message, obj_dsc);
|
||||||
|
|
|
@ -52,6 +52,69 @@ struct wpa_dbus_argument {
|
||||||
|
|
||||||
#define END_ARGS { NULL, NULL, ARG_IN }
|
#define END_ARGS { NULL, NULL, ARG_IN }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct wpa_dbus_method_desc - DBus method description
|
||||||
|
*/
|
||||||
|
struct wpa_dbus_method_desc {
|
||||||
|
/* pointer to next description in list */
|
||||||
|
struct wpa_dbus_method_desc *next;
|
||||||
|
|
||||||
|
/* method interface */
|
||||||
|
char *dbus_interface;
|
||||||
|
/* method name */
|
||||||
|
char *dbus_method;
|
||||||
|
|
||||||
|
/* method handling function */
|
||||||
|
WPADBusMethodHandler method_handler;
|
||||||
|
|
||||||
|
/* number of method arguments */
|
||||||
|
int args_num;
|
||||||
|
/* array of arguments */
|
||||||
|
struct wpa_dbus_argument args[];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct wpa_dbus_signal_desc - DBus signal description
|
||||||
|
*/
|
||||||
|
struct wpa_dbus_signal_desc {
|
||||||
|
/* pointer to next description in list */
|
||||||
|
struct wpa_dbus_signal_desc *next;
|
||||||
|
|
||||||
|
/* signal interface */
|
||||||
|
char *dbus_interface;
|
||||||
|
/* signal name */
|
||||||
|
char *dbus_signal;
|
||||||
|
|
||||||
|
/* number of signal arguments */
|
||||||
|
int args_num;
|
||||||
|
/* array of arguments */
|
||||||
|
struct wpa_dbus_argument args[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct wpa_dbus_property_desc - DBus property description
|
||||||
|
*/
|
||||||
|
struct wpa_dbus_property_desc {
|
||||||
|
/* pointer to next description in list */
|
||||||
|
struct wpa_dbus_property_desc *next;
|
||||||
|
|
||||||
|
/* property interface */
|
||||||
|
char *dbus_interface;
|
||||||
|
/* property name */
|
||||||
|
char *dbus_property;
|
||||||
|
/* property type signature in DBus type notation */
|
||||||
|
char *type;
|
||||||
|
|
||||||
|
/* property access permissions */
|
||||||
|
enum dbus_prop_access access;
|
||||||
|
|
||||||
|
/* property getter function */
|
||||||
|
WPADBusPropertyAccessor getter;
|
||||||
|
/* property setter function */
|
||||||
|
WPADBusPropertyAccessor setter;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#ifndef SIGPOLL
|
#ifndef SIGPOLL
|
||||||
#ifdef SIGIO
|
#ifdef SIGIO
|
||||||
/*
|
/*
|
||||||
|
@ -118,4 +181,7 @@ void wpa_dbus_get_object_properties(struct wpas_dbus_priv *iface,
|
||||||
const char *path, const char *interface,
|
const char *path, const char *interface,
|
||||||
DBusMessageIter *dict_iter);
|
DBusMessageIter *dict_iter);
|
||||||
|
|
||||||
|
DBusMessage * wpa_dbus_introspect(DBusMessage *message,
|
||||||
|
struct wpa_dbus_object_desc *obj_dsc);
|
||||||
|
|
||||||
#endif /* WPA_DBUS_CTRL_H */
|
#endif /* WPA_DBUS_CTRL_H */
|
||||||
|
|
454
wpa_supplicant/dbus/dbus_new_introspect.c
Normal file
454
wpa_supplicant/dbus/dbus_new_introspect.c
Normal file
|
@ -0,0 +1,454 @@
|
||||||
|
/*
|
||||||
|
* WPA Supplicant / dbus-based control interface
|
||||||
|
* Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
|
||||||
|
* Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "utils/includes.h"
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
|
||||||
|
#include "utils/common.h"
|
||||||
|
#include "dbus_common_i.h"
|
||||||
|
#include "dbus_new_helpers.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct interfaces {
|
||||||
|
struct interfaces *next;
|
||||||
|
char *dbus_interface;
|
||||||
|
xmlNodePtr interface_node;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* extract_interfaces - Extract interfaces from methods, signals and props
|
||||||
|
* @obj_dsc: Description of object from which interfaces will be extracted
|
||||||
|
* @root_node: root node of XML introspection document
|
||||||
|
* Returns: List of interfaces found in object description
|
||||||
|
*
|
||||||
|
* Iterates over all methods, signals and properties registered with
|
||||||
|
* object and collects all declared DBus interfaces and create interface's
|
||||||
|
* node in XML root node for each. Returned list elements contains interface
|
||||||
|
* name and XML node of corresponding interface.
|
||||||
|
*/
|
||||||
|
static struct interfaces * extract_interfaces(
|
||||||
|
struct wpa_dbus_object_desc *obj_dsc, xmlNodePtr root_node)
|
||||||
|
{
|
||||||
|
struct wpa_dbus_method_desc *method_dsc = obj_dsc->methods;
|
||||||
|
struct wpa_dbus_signal_desc *signal_dsc = obj_dsc->signals;
|
||||||
|
struct wpa_dbus_property_desc *property_dsc = obj_dsc->properties;
|
||||||
|
struct interfaces *head = NULL;
|
||||||
|
struct interfaces *iface, *last;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
/* extract interfaces from methods */
|
||||||
|
while (method_dsc) {
|
||||||
|
iface = head;
|
||||||
|
last = NULL;
|
||||||
|
|
||||||
|
/* go to next method if its interface is already extracted */
|
||||||
|
while (iface) {
|
||||||
|
if (!os_strcmp(iface->dbus_interface,
|
||||||
|
method_dsc->dbus_interface))
|
||||||
|
break;
|
||||||
|
last = iface;
|
||||||
|
iface = iface->next;
|
||||||
|
}
|
||||||
|
if (iface) {
|
||||||
|
method_dsc = method_dsc->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
iface = os_zalloc(sizeof(struct interfaces));
|
||||||
|
if (!iface) {
|
||||||
|
wpa_printf(MSG_ERROR, "Not enough memory to create "
|
||||||
|
"interface introspection data");
|
||||||
|
method_dsc = method_dsc->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (last)
|
||||||
|
last->next = iface;
|
||||||
|
else
|
||||||
|
head = iface;
|
||||||
|
|
||||||
|
len = os_strlen(method_dsc->dbus_interface) + 1;
|
||||||
|
iface->dbus_interface = os_malloc(len);
|
||||||
|
if (!iface->dbus_interface) {
|
||||||
|
wpa_printf(MSG_ERROR, "Not enough memory to create "
|
||||||
|
"interface introspection data (interface "
|
||||||
|
"name)");
|
||||||
|
method_dsc = method_dsc->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
os_strncpy(iface->dbus_interface, method_dsc->dbus_interface,
|
||||||
|
len);
|
||||||
|
|
||||||
|
iface->interface_node = xmlNewChild(root_node, NULL,
|
||||||
|
BAD_CAST "interface",
|
||||||
|
NULL);
|
||||||
|
xmlNewProp(iface->interface_node, BAD_CAST "name",
|
||||||
|
BAD_CAST method_dsc->dbus_interface);
|
||||||
|
|
||||||
|
method_dsc = method_dsc->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* extract interfaces from signals */
|
||||||
|
while (signal_dsc) {
|
||||||
|
iface = head;
|
||||||
|
last = NULL;
|
||||||
|
|
||||||
|
/* go to next signal if its interface is already extracted */
|
||||||
|
while (iface) {
|
||||||
|
if (!os_strcmp(iface->dbus_interface,
|
||||||
|
signal_dsc->dbus_interface))
|
||||||
|
break;
|
||||||
|
last = iface;
|
||||||
|
iface = iface->next;
|
||||||
|
}
|
||||||
|
if (iface) {
|
||||||
|
signal_dsc = signal_dsc->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
iface = os_zalloc(sizeof(struct interfaces));
|
||||||
|
if (!iface) {
|
||||||
|
wpa_printf(MSG_ERROR, "Not enough memory to create "
|
||||||
|
"interface introspection data");
|
||||||
|
signal_dsc = signal_dsc->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (last)
|
||||||
|
last->next = iface;
|
||||||
|
else
|
||||||
|
head = iface;
|
||||||
|
|
||||||
|
len = os_strlen(signal_dsc->dbus_interface) + 1;
|
||||||
|
iface->dbus_interface = os_malloc(len);
|
||||||
|
if (!iface->dbus_interface) {
|
||||||
|
wpa_printf(MSG_ERROR, "Not enough memory to create "
|
||||||
|
"interface introspection data (interface "
|
||||||
|
"name)");
|
||||||
|
signal_dsc = signal_dsc->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
os_strncpy(iface->dbus_interface, signal_dsc->dbus_interface,
|
||||||
|
len);
|
||||||
|
|
||||||
|
iface->interface_node = xmlNewChild(root_node, NULL,
|
||||||
|
BAD_CAST "interface",
|
||||||
|
NULL);
|
||||||
|
xmlNewProp(iface->interface_node, BAD_CAST "name",
|
||||||
|
BAD_CAST signal_dsc->dbus_interface);
|
||||||
|
|
||||||
|
signal_dsc = signal_dsc->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* extract interfaces from properties */
|
||||||
|
while (property_dsc) {
|
||||||
|
iface = head;
|
||||||
|
last = NULL;
|
||||||
|
|
||||||
|
/* go to next property if its interface is already extracted */
|
||||||
|
while (iface) {
|
||||||
|
if (!os_strcmp(iface->dbus_interface,
|
||||||
|
property_dsc->dbus_interface))
|
||||||
|
break;
|
||||||
|
last = iface;
|
||||||
|
iface = iface->next;
|
||||||
|
}
|
||||||
|
if (iface) {
|
||||||
|
property_dsc = property_dsc->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
iface = os_zalloc(sizeof(struct interfaces));
|
||||||
|
if (!iface) {
|
||||||
|
wpa_printf(MSG_ERROR, "Not enough memory to create "
|
||||||
|
"interface introspection data");
|
||||||
|
property_dsc = property_dsc->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (last)
|
||||||
|
last->next = iface;
|
||||||
|
else
|
||||||
|
head = iface;
|
||||||
|
|
||||||
|
len = os_strlen(property_dsc->dbus_interface) + 1;
|
||||||
|
iface->dbus_interface = os_malloc(len);
|
||||||
|
if (!iface->dbus_interface) {
|
||||||
|
wpa_printf(MSG_ERROR, "Not enough memory to create "
|
||||||
|
"interface introspection data (interface "
|
||||||
|
"name)");
|
||||||
|
property_dsc = property_dsc->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
os_strncpy(iface->dbus_interface, property_dsc->dbus_interface,
|
||||||
|
len);
|
||||||
|
|
||||||
|
iface->interface_node = xmlNewChild(root_node, NULL,
|
||||||
|
BAD_CAST "interface",
|
||||||
|
NULL);
|
||||||
|
xmlNewProp(iface->interface_node, BAD_CAST "name",
|
||||||
|
BAD_CAST property_dsc->dbus_interface);
|
||||||
|
|
||||||
|
property_dsc = property_dsc->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wpa_dbus_introspect - Responds for Introspect calls on object
|
||||||
|
* @message: Message with Introspect call
|
||||||
|
* @obj_dsc: Object description on which Introspect was called
|
||||||
|
* Returns: Message with introspection result XML string as only argument
|
||||||
|
*
|
||||||
|
* Iterates over all methods, signals and properties registered with
|
||||||
|
* object and generates introspection data for the object as XML string.
|
||||||
|
*/
|
||||||
|
DBusMessage * wpa_dbus_introspect(DBusMessage *message,
|
||||||
|
struct wpa_dbus_object_desc *obj_dsc)
|
||||||
|
{
|
||||||
|
|
||||||
|
DBusMessage *reply;
|
||||||
|
struct interfaces *ifaces, *tmp;
|
||||||
|
struct wpa_dbus_signal_desc *signal_dsc;
|
||||||
|
struct wpa_dbus_method_desc *method_dsc;
|
||||||
|
struct wpa_dbus_property_desc *property_dsc;
|
||||||
|
xmlChar *intro_str;
|
||||||
|
char **children;
|
||||||
|
int i, s;
|
||||||
|
|
||||||
|
xmlDocPtr doc = NULL;
|
||||||
|
xmlNodePtr root_node = NULL, node = NULL, iface_node = NULL;
|
||||||
|
xmlNodePtr method_node = NULL, signal_node = NULL;
|
||||||
|
xmlNodePtr property_node = NULL, arg_node = NULL;
|
||||||
|
|
||||||
|
/* root node and dtd */
|
||||||
|
doc = xmlNewDoc(BAD_CAST "1.0");
|
||||||
|
root_node = xmlNewNode(NULL, BAD_CAST "node");
|
||||||
|
xmlDocSetRootElement(doc, root_node);
|
||||||
|
xmlCreateIntSubset(doc, BAD_CAST "node",
|
||||||
|
BAD_CAST DBUS_INTROSPECT_1_0_XML_PUBLIC_IDENTIFIER,
|
||||||
|
BAD_CAST DBUS_INTROSPECT_1_0_XML_SYSTEM_IDENTIFIER);
|
||||||
|
|
||||||
|
/* Add Introspectable interface */
|
||||||
|
iface_node = xmlNewChild(root_node, NULL, BAD_CAST "interface", NULL);
|
||||||
|
xmlNewProp(iface_node, BAD_CAST "name",
|
||||||
|
BAD_CAST WPA_DBUS_INTROSPECTION_INTERFACE);
|
||||||
|
|
||||||
|
/* Add Introspect method */
|
||||||
|
method_node = xmlNewChild(iface_node, NULL, BAD_CAST "method", NULL);
|
||||||
|
xmlNewProp(method_node, BAD_CAST "name",
|
||||||
|
BAD_CAST WPA_DBUS_INTROSPECTION_METHOD);
|
||||||
|
arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
|
||||||
|
xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "data");
|
||||||
|
xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
|
||||||
|
xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "out");
|
||||||
|
|
||||||
|
|
||||||
|
/* Add Properties interface */
|
||||||
|
iface_node = xmlNewChild(root_node, NULL,
|
||||||
|
BAD_CAST "interface", NULL);
|
||||||
|
xmlNewProp(iface_node, BAD_CAST "name",
|
||||||
|
BAD_CAST WPA_DBUS_PROPERTIES_INTERFACE);
|
||||||
|
|
||||||
|
/* Add Get method */
|
||||||
|
method_node = xmlNewChild(iface_node, NULL, BAD_CAST "method", NULL);
|
||||||
|
xmlNewProp(method_node, BAD_CAST "name",
|
||||||
|
BAD_CAST WPA_DBUS_PROPERTIES_GET);
|
||||||
|
arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
|
||||||
|
xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "interface");
|
||||||
|
xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
|
||||||
|
xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
|
||||||
|
arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
|
||||||
|
xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "propname");
|
||||||
|
xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
|
||||||
|
xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
|
||||||
|
arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
|
||||||
|
xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "value");
|
||||||
|
xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "v");
|
||||||
|
xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "out");
|
||||||
|
method_node = xmlNewChild(iface_node, NULL, BAD_CAST "method", NULL);
|
||||||
|
|
||||||
|
/* Add GetAll method */
|
||||||
|
xmlNewProp(method_node, BAD_CAST "name",
|
||||||
|
BAD_CAST WPA_DBUS_PROPERTIES_GETALL);
|
||||||
|
arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
|
||||||
|
xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "interface");
|
||||||
|
xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
|
||||||
|
xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
|
||||||
|
arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
|
||||||
|
xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "props");
|
||||||
|
xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "a{sv}");
|
||||||
|
xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "out");
|
||||||
|
method_node = xmlNewChild(iface_node, NULL, BAD_CAST "method", NULL);
|
||||||
|
|
||||||
|
/* Add Set method */
|
||||||
|
xmlNewProp(method_node, BAD_CAST "name",
|
||||||
|
BAD_CAST WPA_DBUS_PROPERTIES_SET);
|
||||||
|
arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
|
||||||
|
xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "interface");
|
||||||
|
xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
|
||||||
|
xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
|
||||||
|
arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
|
||||||
|
xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "propname");
|
||||||
|
xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "s");
|
||||||
|
xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
|
||||||
|
arg_node = xmlNewChild(method_node, NULL, BAD_CAST "arg", NULL);
|
||||||
|
xmlNewProp(arg_node, BAD_CAST "name", BAD_CAST "value");
|
||||||
|
xmlNewProp(arg_node, BAD_CAST "type", BAD_CAST "v");
|
||||||
|
xmlNewProp(arg_node, BAD_CAST "direction", BAD_CAST "in");
|
||||||
|
|
||||||
|
/* get all interfaces registered with object */
|
||||||
|
ifaces = extract_interfaces(obj_dsc, root_node);
|
||||||
|
|
||||||
|
/* create methods' nodes */
|
||||||
|
method_dsc = obj_dsc->methods;
|
||||||
|
while (method_dsc) {
|
||||||
|
|
||||||
|
struct interfaces *iface = ifaces;
|
||||||
|
while (iface) {
|
||||||
|
if (!os_strcmp(iface->dbus_interface,
|
||||||
|
method_dsc->dbus_interface))
|
||||||
|
break;
|
||||||
|
iface = iface->next;
|
||||||
|
}
|
||||||
|
if (!iface)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
iface_node = iface->interface_node;
|
||||||
|
method_node = xmlNewChild(iface_node, NULL, BAD_CAST "method",
|
||||||
|
NULL);
|
||||||
|
xmlNewProp(method_node, BAD_CAST "name",
|
||||||
|
BAD_CAST method_dsc->dbus_method);
|
||||||
|
|
||||||
|
/* create args' nodes */
|
||||||
|
for (i = 0; i < method_dsc->args_num; i++) {
|
||||||
|
struct wpa_dbus_argument arg = method_dsc->args[i];
|
||||||
|
arg_node = xmlNewChild(method_node, NULL,
|
||||||
|
BAD_CAST "arg", NULL);
|
||||||
|
if (arg.name && strlen(arg.name)) {
|
||||||
|
xmlNewProp(arg_node, BAD_CAST "name",
|
||||||
|
BAD_CAST arg.name);
|
||||||
|
}
|
||||||
|
xmlNewProp(arg_node, BAD_CAST "type",
|
||||||
|
BAD_CAST arg.type);
|
||||||
|
xmlNewProp(arg_node, BAD_CAST "direction",
|
||||||
|
BAD_CAST (arg.dir == ARG_IN ?
|
||||||
|
"in" : "out"));
|
||||||
|
}
|
||||||
|
method_dsc = method_dsc->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create signals' nodes */
|
||||||
|
signal_dsc = obj_dsc->signals;
|
||||||
|
while (signal_dsc) {
|
||||||
|
|
||||||
|
struct interfaces *iface = ifaces;
|
||||||
|
while (iface) {
|
||||||
|
if (!os_strcmp(iface->dbus_interface,
|
||||||
|
signal_dsc->dbus_interface))
|
||||||
|
break;
|
||||||
|
iface = iface->next;
|
||||||
|
}
|
||||||
|
if (!iface)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
iface_node = iface->interface_node;
|
||||||
|
signal_node = xmlNewChild(iface_node, NULL, BAD_CAST "signal",
|
||||||
|
NULL);
|
||||||
|
xmlNewProp(signal_node, BAD_CAST "name",
|
||||||
|
BAD_CAST signal_dsc->dbus_signal);
|
||||||
|
|
||||||
|
/* create args' nodes */
|
||||||
|
for (i = 0; i < signal_dsc->args_num; i++) {
|
||||||
|
struct wpa_dbus_argument arg = signal_dsc->args[i];
|
||||||
|
arg_node = xmlNewChild(signal_node, NULL,
|
||||||
|
BAD_CAST "arg", NULL);
|
||||||
|
if (arg.name && strlen(arg.name)) {
|
||||||
|
xmlNewProp(arg_node, BAD_CAST "name",
|
||||||
|
BAD_CAST arg.name);
|
||||||
|
}
|
||||||
|
xmlNewProp(arg_node, BAD_CAST "type",
|
||||||
|
BAD_CAST arg.type);
|
||||||
|
}
|
||||||
|
signal_dsc = signal_dsc->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create properties' nodes */
|
||||||
|
property_dsc = obj_dsc->properties;
|
||||||
|
while (property_dsc) {
|
||||||
|
|
||||||
|
struct interfaces *iface = ifaces;
|
||||||
|
while (iface) {
|
||||||
|
if (!os_strcmp(iface->dbus_interface,
|
||||||
|
property_dsc->dbus_interface))
|
||||||
|
break;
|
||||||
|
iface = iface->next;
|
||||||
|
}
|
||||||
|
if (!iface)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
iface_node = iface->interface_node;
|
||||||
|
property_node = xmlNewChild(iface_node, NULL,
|
||||||
|
BAD_CAST "property", NULL);
|
||||||
|
xmlNewProp(property_node, BAD_CAST "name",
|
||||||
|
BAD_CAST property_dsc->dbus_property);
|
||||||
|
xmlNewProp(property_node, BAD_CAST "type",
|
||||||
|
BAD_CAST property_dsc->type);
|
||||||
|
xmlNewProp(property_node, BAD_CAST "access", BAD_CAST
|
||||||
|
(property_dsc->access == R ? "read" :
|
||||||
|
(property_dsc->access == W ?
|
||||||
|
"write" : "readwrite")));
|
||||||
|
|
||||||
|
property_dsc = property_dsc->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add child nodes to introspection tree; */
|
||||||
|
dbus_connection_list_registered(obj_dsc->connection,
|
||||||
|
dbus_message_get_path(message),
|
||||||
|
&children);
|
||||||
|
for (i = 0; children[i]; i++) {
|
||||||
|
node = xmlNewChild(root_node, NULL, BAD_CAST "node", NULL);
|
||||||
|
xmlNewProp(node, BAD_CAST "name", BAD_CAST children[i]);
|
||||||
|
}
|
||||||
|
dbus_free_string_array(children);
|
||||||
|
|
||||||
|
|
||||||
|
xmlDocDumpFormatMemory(doc, &intro_str, &s, 1);
|
||||||
|
|
||||||
|
xmlFreeDoc(doc);
|
||||||
|
|
||||||
|
while (ifaces) {
|
||||||
|
tmp = ifaces;
|
||||||
|
ifaces = ifaces->next;
|
||||||
|
os_free(tmp->dbus_interface);
|
||||||
|
os_free(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
reply = dbus_message_new_method_return(message);
|
||||||
|
if (reply == NULL) {
|
||||||
|
xmlFree(intro_str);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbus_message_append_args(reply, DBUS_TYPE_STRING, &intro_str,
|
||||||
|
DBUS_TYPE_INVALID);
|
||||||
|
|
||||||
|
xmlFree(intro_str);
|
||||||
|
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue