wpa_supplicant: Initial Revision 0.8.X

Based on:
commit 0725cc7b7efc434910e89865c42eda7ce61bbf08
Author: Jouni Malinen <j@w1.fi>
Date:   Thu Apr 21 20:41:01 2011 +0300

    Enable CONFIG_DRIVER_NL80211=y in the default configuration

    nl80211 should be preferred over WEXT with any recent Linux
    kernel version.

Change-Id: I26aec5afbbd4f4a1f5fd900912545b6f5050de64
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/wpa_supplicant/dbus/.gitignore b/wpa_supplicant/dbus/.gitignore
new file mode 100644
index 0000000..6db2468
--- /dev/null
+++ b/wpa_supplicant/dbus/.gitignore
@@ -0,0 +1 @@
+libwpadbus.a
diff --git a/wpa_supplicant/dbus/Makefile b/wpa_supplicant/dbus/Makefile
new file mode 100644
index 0000000..cfaf58d
--- /dev/null
+++ b/wpa_supplicant/dbus/Makefile
@@ -0,0 +1,84 @@
+all: libwpadbus.a
+
+clean:
+	rm -f *~ *.o *.d
+	rm -f libwpadbus.a
+
+install:
+	@echo Nothing to be made.
+
+ifndef CC
+CC=gcc
+endif
+
+ifndef CFLAGS
+CFLAGS = -MMD -O2 -Wall -g
+endif
+
+CFLAGS += -I../../src -I../../src/utils
+
+
+Q=@
+E=echo
+ifeq ($(V), 1)
+Q=
+E=true
+endif
+
+%.o: %.c
+	$(Q)$(CC) -c -o $@ $(CFLAGS) $<
+	@$(E) "  CC " $<
+
+
+ifdef CONFIG_WPS
+CFLAGS += -DCONFIG_WPS
+endif
+
+CFLAGS += -DCONFIG_CTRL_IFACE_DBUS_NEW
+CFLAGS += -DCONFIG_CTRL_IFACE_DBUS
+
+ifndef DBUS_LIBS
+DBUS_LIBS := $(shell pkg-config --libs dbus-1)
+endif
+ifndef DBUS_INCLUDE
+DBUS_INCLUDE := $(shell pkg-config --cflags dbus-1)
+endif
+ifdef CONFIG_CTRL_IFACE_DBUS_INTRO
+CFLAGS += -DCONFIG_CTRL_IFACE_DBUS_INTRO
+DBUS_INCLUDE += $(shell xml2-config --cflags)
+DBUS_LIBS += $(shell xml2-config --libs)
+endif
+
+dbus_version=$(subst ., ,$(shell pkg-config --modversion dbus-1))
+DBUS_VERSION_MAJOR=$(word 1,$(dbus_version))
+DBUS_VERSION_MINOR=$(word 2,$(dbus_version))
+ifeq ($(DBUS_VERSION_MAJOR),)
+DBUS_VERSION_MAJOR=0
+endif
+ifeq ($(DBUS_VERSION_MINOR),)
+DBUS_VERSION_MINOR=0
+endif
+DBUS_INCLUDE += -DDBUS_VERSION_MAJOR=$(DBUS_VERSION_MAJOR)
+DBUS_INCLUDE += -DDBUS_VERSION_MINOR=$(DBUS_VERSION_MINOR)
+
+CFLAGS += $(DBUS_INCLUDE)
+
+LIB_OBJS= \
+	dbus_common.o \
+	dbus_old.o \
+	dbus_old_handlers.o \
+	dbus_new.o \
+	dbus_new_handlers.o \
+	dbus_new_helpers.o \
+	dbus_new_introspect.o \
+	dbus_dict_helpers.o
+
+ifdef CONFIG_WPS
+LIB_OBJS += dbus_old_handlers_wps.o
+LIB_OBJS += dbus_new_handlers_wps.o
+endif
+
+libwpadbus.a: $(LIB_OBJS)
+	$(AR) crT $@ $?
+
+-include $(OBJS:%.o=%.d)
diff --git a/wpa_supplicant/dbus/dbus-wpa_supplicant.conf b/wpa_supplicant/dbus/dbus-wpa_supplicant.conf
new file mode 100644
index 0000000..c091234
--- /dev/null
+++ b/wpa_supplicant/dbus/dbus-wpa_supplicant.conf
@@ -0,0 +1,27 @@
+<!DOCTYPE busconfig PUBLIC
+ "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+        <policy user="root">
+                <allow own="fi.epitest.hostap.WPASupplicant"/>
+
+                <allow send_destination="fi.epitest.hostap.WPASupplicant"/>
+                <allow send_interface="fi.epitest.hostap.WPASupplicant"/>
+
+                <allow own="fi.w1.wpa_supplicant1"/>
+
+                <allow send_destination="fi.w1.wpa_supplicant1"/>
+                <allow send_interface="fi.w1.wpa_supplicant1"/>
+                <allow receive_sender="fi.w1.wpa_supplicant1" receive_type="signal"/>
+        </policy>
+        <policy context="default">
+                <deny own="fi.epitest.hostap.WPASupplicant"/>
+                <deny send_destination="fi.epitest.hostap.WPASupplicant"/>
+                <deny send_interface="fi.epitest.hostap.WPASupplicant"/>
+
+                <deny own="fi.w1.wpa_supplicant1"/>
+                <deny send_destination="fi.w1.wpa_supplicant1"/>
+                <deny send_interface="fi.w1.wpa_supplicant1"/>
+                <deny receive_sender="fi.w1.wpa_supplicant1" receive_type="signal"/>
+        </policy>
+</busconfig>
diff --git a/wpa_supplicant/dbus/dbus_common.c b/wpa_supplicant/dbus/dbus_common.c
new file mode 100644
index 0000000..5850636
--- /dev/null
+++ b/wpa_supplicant/dbus/dbus_common.c
@@ -0,0 +1,371 @@
+/*
+ * wpa_supplicant D-Bus control interface - common functionality
+ * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
+ * Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
+ * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
+ *
+ * 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 <dbus/dbus.h>
+
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "dbus_common.h"
+#include "dbus_common_i.h"
+#include "dbus_new.h"
+#include "dbus_old.h"
+
+
+#ifndef SIGPOLL
+#ifdef SIGIO
+/*
+ * If we do not have SIGPOLL, try to use SIGIO instead. This is needed for
+ * FreeBSD.
+ */
+#define SIGPOLL SIGIO
+#endif
+#endif
+
+
+static void dispatch_data(DBusConnection *con)
+{
+	while (dbus_connection_get_dispatch_status(con) ==
+	       DBUS_DISPATCH_DATA_REMAINS)
+		dbus_connection_dispatch(con);
+}
+
+
+/**
+ * dispatch_initial_dbus_messages - Dispatch initial dbus messages after
+ *     claiming bus name
+ * @eloop_ctx: the DBusConnection to dispatch on
+ * @timeout_ctx: unused
+ *
+ * If clients are quick to notice that service claimed its bus name,
+ * there may have been messages that came in before initialization was
+ * all finished.  Dispatch those here.
+ */
+static void dispatch_initial_dbus_messages(void *eloop_ctx, void *timeout_ctx)
+{
+	DBusConnection *con = eloop_ctx;
+	dispatch_data(con);
+}
+
+
+static void process_watch(struct wpas_dbus_priv *priv,
+			  DBusWatch *watch, eloop_event_type type)
+{
+	dbus_connection_ref(priv->con);
+
+	priv->should_dispatch = 0;
+
+	if (type == EVENT_TYPE_READ)
+		dbus_watch_handle(watch, DBUS_WATCH_READABLE);
+	else if (type == EVENT_TYPE_WRITE)
+		dbus_watch_handle(watch, DBUS_WATCH_WRITABLE);
+	else if (type == EVENT_TYPE_EXCEPTION)
+		dbus_watch_handle(watch, DBUS_WATCH_ERROR);
+
+	if (priv->should_dispatch) {
+		dispatch_data(priv->con);
+		priv->should_dispatch = 0;
+	}
+
+	dbus_connection_unref(priv->con);
+}
+
+
+static void process_watch_exception(int sock, void *eloop_ctx, void *sock_ctx)
+{
+	process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_EXCEPTION);
+}
+
+
+static void process_watch_read(int sock, void *eloop_ctx, void *sock_ctx)
+{
+	process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_READ);
+}
+
+
+static void process_watch_write(int sock, void *eloop_ctx, void *sock_ctx)
+{
+	process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_WRITE);
+}
+
+
+static dbus_bool_t add_watch(DBusWatch *watch, void *data)
+{
+	struct wpas_dbus_priv *priv = data;
+	unsigned int flags;
+	int fd;
+
+	if (!dbus_watch_get_enabled(watch))
+		return TRUE;
+
+	flags = dbus_watch_get_flags(watch);
+	fd = dbus_watch_get_unix_fd(watch);
+
+	eloop_register_sock(fd, EVENT_TYPE_EXCEPTION, process_watch_exception,
+			    priv, watch);
+
+	if (flags & DBUS_WATCH_READABLE) {
+		eloop_register_sock(fd, EVENT_TYPE_READ, process_watch_read,
+				    priv, watch);
+	}
+	if (flags & DBUS_WATCH_WRITABLE) {
+		eloop_register_sock(fd, EVENT_TYPE_WRITE, process_watch_write,
+				    priv, watch);
+	}
+
+	dbus_watch_set_data(watch, priv, NULL);
+
+	return TRUE;
+}
+
+
+static void remove_watch(DBusWatch *watch, void *data)
+{
+	unsigned int flags;
+	int fd;
+
+	flags = dbus_watch_get_flags(watch);
+	fd = dbus_watch_get_unix_fd(watch);
+
+	eloop_unregister_sock(fd, EVENT_TYPE_EXCEPTION);
+
+	if (flags & DBUS_WATCH_READABLE)
+		eloop_unregister_sock(fd, EVENT_TYPE_READ);
+	if (flags & DBUS_WATCH_WRITABLE)
+		eloop_unregister_sock(fd, EVENT_TYPE_WRITE);
+
+	dbus_watch_set_data(watch, NULL, NULL);
+}
+
+
+static void watch_toggled(DBusWatch *watch, void *data)
+{
+	if (dbus_watch_get_enabled(watch))
+		add_watch(watch, data);
+	else
+		remove_watch(watch, data);
+}
+
+
+static void process_timeout(void *eloop_ctx, void *sock_ctx)
+{
+	DBusTimeout *timeout = sock_ctx;
+	dbus_timeout_handle(timeout);
+}
+
+
+static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data)
+{
+	struct wpas_dbus_priv *priv = data;
+	if (!dbus_timeout_get_enabled(timeout))
+		return TRUE;
+
+	eloop_register_timeout(0, dbus_timeout_get_interval(timeout) * 1000,
+			       process_timeout, priv, timeout);
+
+	dbus_timeout_set_data(timeout, priv, NULL);
+
+	return TRUE;
+}
+
+
+static void remove_timeout(DBusTimeout *timeout, void *data)
+{
+	struct wpas_dbus_priv *priv = data;
+	eloop_cancel_timeout(process_timeout, priv, timeout);
+	dbus_timeout_set_data(timeout, NULL, NULL);
+}
+
+
+static void timeout_toggled(DBusTimeout *timeout, void *data)
+{
+	if (dbus_timeout_get_enabled(timeout))
+		add_timeout(timeout, data);
+	else
+		remove_timeout(timeout, data);
+}
+
+
+static void process_wakeup_main(int sig, void *signal_ctx)
+{
+	struct wpas_dbus_priv *priv = signal_ctx;
+
+	if (sig != SIGPOLL || !priv->con)
+		return;
+
+	if (dbus_connection_get_dispatch_status(priv->con) !=
+	    DBUS_DISPATCH_DATA_REMAINS)
+		return;
+
+	/* Only dispatch once - we do not want to starve other events */
+	dbus_connection_ref(priv->con);
+	dbus_connection_dispatch(priv->con);
+	dbus_connection_unref(priv->con);
+}
+
+
+/**
+ * wakeup_main - Attempt to wake our mainloop up
+ * @data: dbus control interface private data
+ *
+ * Try to wake up the main eloop so it will process
+ * dbus events that may have happened.
+ */
+static void wakeup_main(void *data)
+{
+	struct wpas_dbus_priv *priv = data;
+
+	/* Use SIGPOLL to break out of the eloop select() */
+	raise(SIGPOLL);
+	priv->should_dispatch = 1;
+}
+
+
+/**
+ * integrate_with_eloop - Register our mainloop integration with dbus
+ * @connection: connection to the system message bus
+ * @priv: a dbus control interface data structure
+ * Returns: 0 on success, -1 on failure
+ */
+static int integrate_with_eloop(struct wpas_dbus_priv *priv)
+{
+	if (!dbus_connection_set_watch_functions(priv->con, add_watch,
+						 remove_watch, watch_toggled,
+						 priv, NULL) ||
+	    !dbus_connection_set_timeout_functions(priv->con, add_timeout,
+						   remove_timeout,
+						   timeout_toggled, priv,
+						   NULL)) {
+		wpa_printf(MSG_ERROR, "dbus: Failed to set callback "
+			   "functions");
+		return -1;
+	}
+
+	if (eloop_register_signal(SIGPOLL, process_wakeup_main, priv))
+		return -1;
+	dbus_connection_set_wakeup_main_function(priv->con, wakeup_main,
+						 priv, NULL);
+
+	return 0;
+}
+
+
+static int wpas_dbus_init_common(struct wpas_dbus_priv *priv)
+{
+	DBusError error;
+	int ret = 0;
+
+	/* Get a reference to the system bus */
+	dbus_error_init(&error);
+	priv->con = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+	if (!priv->con) {
+		wpa_printf(MSG_ERROR, "dbus: Could not acquire the system "
+			   "bus: %s - %s", error.name, error.message);
+		ret = -1;
+	}
+	dbus_error_free(&error);
+
+	return ret;
+}
+
+
+static int wpas_dbus_init_common_finish(struct wpas_dbus_priv *priv)
+{
+	/* Tell dbus about our mainloop integration functions */
+	integrate_with_eloop(priv);
+
+	/*
+	 * Dispatch initial DBus messages that may have come in since the bus
+	 * name was claimed above. Happens when clients are quick to notice the
+	 * service.
+	 *
+	 * FIXME: is there a better solution to this problem?
+	 */
+	eloop_register_timeout(0, 50, dispatch_initial_dbus_messages,
+	                       priv->con, NULL);
+
+	return 0;
+}
+
+
+static void wpas_dbus_deinit_common(struct wpas_dbus_priv *priv)
+{
+	if (priv->con) {
+		eloop_cancel_timeout(dispatch_initial_dbus_messages,
+				     priv->con, NULL);
+		dbus_connection_set_watch_functions(priv->con, NULL, NULL,
+						    NULL, NULL, NULL);
+		dbus_connection_set_timeout_functions(priv->con, NULL, NULL,
+						      NULL, NULL, NULL);
+		dbus_connection_unref(priv->con);
+	}
+
+	os_free(priv);
+}
+
+
+struct wpas_dbus_priv * wpas_dbus_init(struct wpa_global *global)
+{
+	struct wpas_dbus_priv *priv;
+
+	priv = os_zalloc(sizeof(*priv));
+	if (priv == NULL)
+		return NULL;
+	priv->global = global;
+
+	if (wpas_dbus_init_common(priv) < 0) {
+		wpas_dbus_deinit(priv);
+		return NULL;
+	}
+
+#ifdef CONFIG_CTRL_IFACE_DBUS_NEW
+	if (wpas_dbus_ctrl_iface_init(priv) < 0) {
+		wpas_dbus_deinit(priv);
+		return NULL;
+	}
+#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
+
+#ifdef CONFIG_CTRL_IFACE_DBUS
+	if (wpa_supplicant_dbus_ctrl_iface_init(priv) < 0) {
+		wpas_dbus_deinit(priv);
+		return NULL;
+	}
+#endif /* CONFIG_CTRL_IFACE_DBUS */
+
+	if (wpas_dbus_init_common_finish(priv) < 0) {
+		wpas_dbus_deinit(priv);
+		return NULL;
+	}
+
+	return priv;
+}
+
+
+void wpas_dbus_deinit(struct wpas_dbus_priv *priv)
+{
+	if (priv == NULL)
+		return;
+
+#ifdef CONFIG_CTRL_IFACE_DBUS_NEW
+	wpas_dbus_ctrl_iface_deinit(priv);
+#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
+
+#ifdef CONFIG_CTRL_IFACE_DBUS
+	/* TODO: is any deinit needed? */
+#endif /* CONFIG_CTRL_IFACE_DBUS */
+
+	wpas_dbus_deinit_common(priv);
+}
diff --git a/wpa_supplicant/dbus/dbus_common.h b/wpa_supplicant/dbus/dbus_common.h
new file mode 100644
index 0000000..50da09b
--- /dev/null
+++ b/wpa_supplicant/dbus/dbus_common.h
@@ -0,0 +1,26 @@
+/*
+ * wpa_supplicant D-Bus control interface - common definitions
+ * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
+ * Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
+ * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
+ *
+ * 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.
+ */
+
+#ifndef DBUS_COMMON_H
+#define DBUS_COMMON_H
+
+struct wpas_dbus_priv;
+struct wpa_global;
+
+struct wpas_dbus_priv * wpas_dbus_init(struct wpa_global *global);
+void wpas_dbus_deinit(struct wpas_dbus_priv *priv);
+
+#endif /* DBUS_COMMON_H */
diff --git a/wpa_supplicant/dbus/dbus_common_i.h b/wpa_supplicant/dbus/dbus_common_i.h
new file mode 100644
index 0000000..9dab1ee
--- /dev/null
+++ b/wpa_supplicant/dbus/dbus_common_i.h
@@ -0,0 +1,30 @@
+/*
+ * wpa_supplicant D-Bus control interface - internal definitions
+ * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
+ * Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
+ * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
+ *
+ * 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.
+ */
+
+#ifndef DBUS_COMMON_I_H
+#define DBUS_COMMON_I_H
+
+#include <dbus/dbus.h>
+
+struct wpas_dbus_priv {
+	DBusConnection *con;
+	int should_dispatch;
+	struct wpa_global *global;
+	u32 next_objid;
+	int dbus_new_initialized;
+};
+
+#endif /* DBUS_COMMON_I_H */
diff --git a/wpa_supplicant/dbus/dbus_dict_helpers.c b/wpa_supplicant/dbus/dbus_dict_helpers.c
new file mode 100644
index 0000000..d900487
--- /dev/null
+++ b/wpa_supplicant/dbus/dbus_dict_helpers.c
@@ -0,0 +1,923 @@
+/*
+ * WPA Supplicant / dbus-based control interface
+ * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
+ *
+ * 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 "includes.h"
+#include <dbus/dbus.h>
+
+#include "common.h"
+#include "dbus_dict_helpers.h"
+
+
+/**
+ * Start a dict in a dbus message.  Should be paired with a call to
+ * wpa_dbus_dict_close_write().
+ *
+ * @param iter A valid dbus message iterator
+ * @param iter_dict (out) A dict iterator to pass to further dict functions
+ * @return TRUE on success, FALSE on failure
+ *
+ */
+dbus_bool_t wpa_dbus_dict_open_write(DBusMessageIter *iter,
+				     DBusMessageIter *iter_dict)
+{
+	dbus_bool_t result;
+
+	if (!iter || !iter_dict)
+		return FALSE;
+
+	result = dbus_message_iter_open_container(
+		iter,
+		DBUS_TYPE_ARRAY,
+		DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+		DBUS_TYPE_STRING_AS_STRING
+		DBUS_TYPE_VARIANT_AS_STRING
+		DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+		iter_dict);
+	return result;
+}
+
+
+/**
+ * End a dict element in a dbus message.  Should be paired with
+ * a call to wpa_dbus_dict_open_write().
+ *
+ * @param iter valid dbus message iterator, same as passed to
+ *    wpa_dbus_dict_open_write()
+ * @param iter_dict a dbus dict iterator returned from
+ *    wpa_dbus_dict_open_write()
+ * @return TRUE on success, FALSE on failure
+ *
+ */
+dbus_bool_t wpa_dbus_dict_close_write(DBusMessageIter *iter,
+				      DBusMessageIter *iter_dict)
+{
+	if (!iter || !iter_dict)
+		return FALSE;
+
+	return dbus_message_iter_close_container(iter, iter_dict);
+}
+
+
+const char * wpa_dbus_type_as_string(const int type)
+{
+	switch(type) {
+	case DBUS_TYPE_BYTE:
+		return DBUS_TYPE_BYTE_AS_STRING;
+	case DBUS_TYPE_BOOLEAN:
+		return DBUS_TYPE_BOOLEAN_AS_STRING;
+	case DBUS_TYPE_INT16:
+		return DBUS_TYPE_INT16_AS_STRING;
+	case DBUS_TYPE_UINT16:
+		return DBUS_TYPE_UINT16_AS_STRING;
+	case DBUS_TYPE_INT32:
+		return DBUS_TYPE_INT32_AS_STRING;
+	case DBUS_TYPE_UINT32:
+		return DBUS_TYPE_UINT32_AS_STRING;
+	case DBUS_TYPE_INT64:
+		return DBUS_TYPE_INT64_AS_STRING;
+	case DBUS_TYPE_UINT64:
+		return DBUS_TYPE_UINT64_AS_STRING;
+	case DBUS_TYPE_DOUBLE:
+		return DBUS_TYPE_DOUBLE_AS_STRING;
+	case DBUS_TYPE_STRING:
+		return DBUS_TYPE_STRING_AS_STRING;
+	case DBUS_TYPE_OBJECT_PATH:
+		return DBUS_TYPE_OBJECT_PATH_AS_STRING;
+	case DBUS_TYPE_ARRAY:
+		return DBUS_TYPE_ARRAY_AS_STRING;
+	default:
+		return NULL;
+	}
+}
+
+
+static dbus_bool_t _wpa_dbus_add_dict_entry_start(
+	DBusMessageIter *iter_dict, DBusMessageIter *iter_dict_entry,
+	const char *key, const int value_type)
+{
+	if (!dbus_message_iter_open_container(iter_dict,
+					      DBUS_TYPE_DICT_ENTRY, NULL,
+					      iter_dict_entry))
+		return FALSE;
+
+	if (!dbus_message_iter_append_basic(iter_dict_entry, DBUS_TYPE_STRING,
+					    &key))
+		return FALSE;
+
+	return TRUE;
+}
+
+
+static dbus_bool_t _wpa_dbus_add_dict_entry_end(
+	DBusMessageIter *iter_dict, DBusMessageIter *iter_dict_entry,
+	DBusMessageIter *iter_dict_val)
+{
+	if (!dbus_message_iter_close_container(iter_dict_entry, iter_dict_val))
+		return FALSE;
+	if (!dbus_message_iter_close_container(iter_dict, iter_dict_entry))
+		return FALSE;
+
+	return TRUE;
+}
+
+
+static dbus_bool_t _wpa_dbus_add_dict_entry_basic(DBusMessageIter *iter_dict,
+						  const char *key,
+						  const int value_type,
+						  const void *value)
+{
+	DBusMessageIter iter_dict_entry, iter_dict_val;
+	const char *type_as_string = NULL;
+
+	if (key == NULL)
+		return FALSE;
+
+	type_as_string = wpa_dbus_type_as_string(value_type);
+	if (!type_as_string)
+		return FALSE;
+
+	if (!_wpa_dbus_add_dict_entry_start(iter_dict, &iter_dict_entry,
+					    key, value_type))
+		return FALSE;
+
+	if (!dbus_message_iter_open_container(&iter_dict_entry,
+					      DBUS_TYPE_VARIANT,
+					      type_as_string, &iter_dict_val))
+		return FALSE;
+
+	if (!dbus_message_iter_append_basic(&iter_dict_val, value_type, value))
+		return FALSE;
+
+	if (!_wpa_dbus_add_dict_entry_end(iter_dict, &iter_dict_entry,
+					  &iter_dict_val))
+		return FALSE;
+
+	return TRUE;
+}
+
+
+static dbus_bool_t _wpa_dbus_add_dict_entry_byte_array(
+	DBusMessageIter *iter_dict, const char *key,
+	const char *value, const dbus_uint32_t value_len)
+{
+	DBusMessageIter iter_dict_entry, iter_dict_val, iter_array;
+	dbus_uint32_t i;
+
+	if (!_wpa_dbus_add_dict_entry_start(iter_dict, &iter_dict_entry,
+					    key, DBUS_TYPE_ARRAY))
+		return FALSE;
+
+	if (!dbus_message_iter_open_container(&iter_dict_entry,
+					      DBUS_TYPE_VARIANT,
+					      DBUS_TYPE_ARRAY_AS_STRING
+					      DBUS_TYPE_BYTE_AS_STRING,
+					      &iter_dict_val))
+		return FALSE;
+
+	if (!dbus_message_iter_open_container(&iter_dict_val, DBUS_TYPE_ARRAY,
+					      DBUS_TYPE_BYTE_AS_STRING,
+					      &iter_array))
+		return FALSE;
+
+	for (i = 0; i < value_len; i++) {
+		if (!dbus_message_iter_append_basic(&iter_array,
+						    DBUS_TYPE_BYTE,
+						    &(value[i])))
+			return FALSE;
+	}
+
+	if (!dbus_message_iter_close_container(&iter_dict_val, &iter_array))
+		return FALSE;
+
+	if (!_wpa_dbus_add_dict_entry_end(iter_dict, &iter_dict_entry,
+					  &iter_dict_val))
+		return FALSE;
+
+	return TRUE;
+}
+
+
+/**
+ * Add a string entry to the dict.
+ *
+ * @param iter_dict A valid DBusMessageIter returned from
+ *    wpa_dbus_dict_open_write()
+ * @param key The key of the dict item
+ * @param value The string value
+ * @return TRUE on success, FALSE on failure
+ *
+ */
+dbus_bool_t wpa_dbus_dict_append_string(DBusMessageIter *iter_dict,
+					const char *key, const char *value)
+{
+	if (!value)
+		return FALSE;
+	return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_STRING,
+					      &value);
+}
+
+
+/**
+ * Add a byte entry to the dict.
+ *
+ * @param iter_dict A valid DBusMessageIter returned from
+ *    wpa_dbus_dict_open_write()
+ * @param key The key of the dict item
+ * @param value The byte value
+ * @return TRUE on success, FALSE on failure
+ *
+ */
+dbus_bool_t wpa_dbus_dict_append_byte(DBusMessageIter *iter_dict,
+				      const char *key, const char value)
+{
+	return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_BYTE,
+					      &value);
+}
+
+
+/**
+ * Add a boolean entry to the dict.
+ *
+ * @param iter_dict A valid DBusMessageIter returned from
+ *    wpa_dbus_dict_open_write()
+ * @param key The key of the dict item
+ * @param value The boolean value
+ * @return TRUE on success, FALSE on failure
+ *
+ */
+dbus_bool_t wpa_dbus_dict_append_bool(DBusMessageIter *iter_dict,
+				      const char *key, const dbus_bool_t value)
+{
+	return _wpa_dbus_add_dict_entry_basic(iter_dict, key,
+					      DBUS_TYPE_BOOLEAN, &value);
+}
+
+
+/**
+ * Add a 16-bit signed integer entry to the dict.
+ *
+ * @param iter_dict A valid DBusMessageIter returned from
+ *    wpa_dbus_dict_open_write()
+ * @param key The key of the dict item
+ * @param value The 16-bit signed integer value
+ * @return TRUE on success, FALSE on failure
+ *
+ */
+dbus_bool_t wpa_dbus_dict_append_int16(DBusMessageIter *iter_dict,
+				       const char *key,
+				       const dbus_int16_t value)
+{
+	return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_INT16,
+					      &value);
+}
+
+
+/**
+ * Add a 16-bit unsigned integer entry to the dict.
+ *
+ * @param iter_dict A valid DBusMessageIter returned from
+ *    wpa_dbus_dict_open_write()
+ * @param key The key of the dict item
+ * @param value The 16-bit unsigned integer value
+ * @return TRUE on success, FALSE on failure
+ *
+ */
+dbus_bool_t wpa_dbus_dict_append_uint16(DBusMessageIter *iter_dict,
+					const char *key,
+					const dbus_uint16_t value)
+{
+	return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_UINT16,
+					      &value);
+}
+
+
+/**
+ * Add a 32-bit signed integer to the dict.
+ *
+ * @param iter_dict A valid DBusMessageIter returned from
+ *    wpa_dbus_dict_open_write()
+ * @param key The key of the dict item
+ * @param value The 32-bit signed integer value
+ * @return TRUE on success, FALSE on failure
+ *
+ */
+dbus_bool_t wpa_dbus_dict_append_int32(DBusMessageIter *iter_dict,
+				       const char *key,
+				       const dbus_int32_t value)
+{
+	return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_INT32,
+					      &value);
+}
+
+
+/**
+ * Add a 32-bit unsigned integer entry to the dict.
+ *
+ * @param iter_dict A valid DBusMessageIter returned from
+ *    wpa_dbus_dict_open_write()
+ * @param key The key of the dict item
+ * @param value The 32-bit unsigned integer value
+ * @return TRUE on success, FALSE on failure
+ *
+ */
+dbus_bool_t wpa_dbus_dict_append_uint32(DBusMessageIter *iter_dict,
+					const char *key,
+					const dbus_uint32_t value)
+{
+	return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_UINT32,
+					      &value);
+}
+
+
+/**
+ * Add a 64-bit integer entry to the dict.
+ *
+ * @param iter_dict A valid DBusMessageIter returned from
+ *    wpa_dbus_dict_open_write()
+ * @param key The key of the dict item
+ * @param value The 64-bit integer value
+ * @return TRUE on success, FALSE on failure
+ *
+ */
+dbus_bool_t wpa_dbus_dict_append_int64(DBusMessageIter *iter_dict,
+				       const char *key,
+				       const dbus_int64_t value)
+{
+	return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_INT64,
+					      &value);
+}
+
+
+/**
+ * Add a 64-bit unsigned integer entry to the dict.
+ *
+ * @param iter_dict A valid DBusMessageIter returned from
+ *    wpa_dbus_dict_open_write()
+ * @param key The key of the dict item
+ * @param value The 64-bit unsigned integer value
+ * @return TRUE on success, FALSE on failure
+ *
+ */
+dbus_bool_t wpa_dbus_dict_append_uint64(DBusMessageIter *iter_dict,
+					const char *key,
+					const dbus_uint64_t value)
+{
+	return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_UINT64,
+					      &value);
+}
+
+
+/**
+ * Add a double-precision floating point entry to the dict.
+ *
+ * @param iter_dict A valid DBusMessageIter returned from
+ *    wpa_dbus_dict_open_write()
+ * @param key The key of the dict item
+ * @param value The double-precision floating point value
+ * @return TRUE on success, FALSE on failure
+ *
+ */
+dbus_bool_t wpa_dbus_dict_append_double(DBusMessageIter *iter_dict,
+					const char *key, const double value)
+{
+	return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_DOUBLE,
+					      &value);
+}
+
+
+/**
+ * Add a DBus object path entry to the dict.
+ *
+ * @param iter_dict A valid DBusMessageIter returned from
+ *    wpa_dbus_dict_open_write()
+ * @param key The key of the dict item
+ * @param value The DBus object path value
+ * @return TRUE on success, FALSE on failure
+ *
+ */
+dbus_bool_t wpa_dbus_dict_append_object_path(DBusMessageIter *iter_dict,
+					     const char *key,
+					     const char *value)
+{
+	if (!value)
+		return FALSE;
+	return _wpa_dbus_add_dict_entry_basic(iter_dict, key,
+					      DBUS_TYPE_OBJECT_PATH, &value);
+}
+
+
+/**
+ * Add a byte array entry to the dict.
+ *
+ * @param iter_dict A valid DBusMessageIter returned from
+ *    wpa_dbus_dict_open_write()
+ * @param key The key of the dict item
+ * @param value The byte array
+ * @param value_len The length of the byte array, in bytes
+ * @return TRUE on success, FALSE on failure
+ *
+ */
+dbus_bool_t wpa_dbus_dict_append_byte_array(DBusMessageIter *iter_dict,
+					    const char *key,
+					    const char *value,
+					    const dbus_uint32_t value_len)
+{
+	if (!key)
+		return FALSE;
+	if (!value && (value_len != 0))
+		return FALSE;
+	return _wpa_dbus_add_dict_entry_byte_array(iter_dict, key, value,
+						   value_len);
+}
+
+
+/**
+ * Begin a string array entry in the dict
+ *
+ * @param iter_dict A valid DBusMessageIter returned from
+ *                  wpa_dbus_dict_open_write()
+ * @param key The key of the dict item
+ * @param iter_dict_entry A private DBusMessageIter provided by the caller to
+ *                        be passed to wpa_dbus_dict_end_string_array()
+ * @param iter_dict_val A private DBusMessageIter provided by the caller to
+ *                      be passed to wpa_dbus_dict_end_string_array()
+ * @param iter_array On return, the DBusMessageIter to be passed to
+ *                   wpa_dbus_dict_string_array_add_element()
+ * @return TRUE on success, FALSE on failure
+ *
+ */
+dbus_bool_t wpa_dbus_dict_begin_string_array(DBusMessageIter *iter_dict,
+					     const char *key,
+					     DBusMessageIter *iter_dict_entry,
+					     DBusMessageIter *iter_dict_val,
+					     DBusMessageIter *iter_array)
+{
+	if (!iter_dict || !iter_dict_entry || !iter_dict_val || !iter_array)
+		return FALSE;
+
+	if (!_wpa_dbus_add_dict_entry_start(iter_dict, iter_dict_entry,
+					    key, DBUS_TYPE_ARRAY))
+		return FALSE;
+
+	if (!dbus_message_iter_open_container(iter_dict_entry,
+					      DBUS_TYPE_VARIANT,
+					      DBUS_TYPE_ARRAY_AS_STRING
+					      DBUS_TYPE_STRING_AS_STRING,
+					      iter_dict_val))
+		return FALSE;
+
+	if (!dbus_message_iter_open_container(iter_dict_val, DBUS_TYPE_ARRAY,
+					      DBUS_TYPE_STRING_AS_STRING,
+					      iter_array))
+		return FALSE;
+
+	return TRUE;
+}
+
+
+/**
+ * Add a single string element to a string array dict entry
+ *
+ * @param iter_array A valid DBusMessageIter returned from
+ *                   wpa_dbus_dict_begin_string_array()'s
+ *                   iter_array parameter
+ * @param elem The string element to be added to the dict entry's string array
+ * @return TRUE on success, FALSE on failure
+ *
+ */
+dbus_bool_t wpa_dbus_dict_string_array_add_element(DBusMessageIter *iter_array,
+						   const char *elem)
+{
+	if (!iter_array || !elem)
+		return FALSE;
+
+	return dbus_message_iter_append_basic(iter_array, DBUS_TYPE_STRING,
+					      &elem);
+}
+
+
+/**
+ * End a string array dict entry
+ *
+ * @param iter_dict A valid DBusMessageIter returned from
+ *                  wpa_dbus_dict_open_write()
+ * @param iter_dict_entry A private DBusMessageIter returned from
+ *                        wpa_dbus_dict_end_string_array()
+ * @param iter_dict_val A private DBusMessageIter returned from
+ *                      wpa_dbus_dict_end_string_array()
+ * @param iter_array A DBusMessageIter returned from
+ *                   wpa_dbus_dict_end_string_array()
+ * @return TRUE on success, FALSE on failure
+ *
+ */
+dbus_bool_t wpa_dbus_dict_end_string_array(DBusMessageIter *iter_dict,
+					   DBusMessageIter *iter_dict_entry,
+					   DBusMessageIter *iter_dict_val,
+					   DBusMessageIter *iter_array)
+{
+	if (!iter_dict || !iter_dict_entry || !iter_dict_val || !iter_array)
+		return FALSE;
+
+	if (!dbus_message_iter_close_container(iter_dict_val, iter_array))
+		return FALSE;
+
+	if (!_wpa_dbus_add_dict_entry_end(iter_dict, iter_dict_entry,
+					  iter_dict_val))
+		return FALSE;
+
+	return TRUE;
+}
+
+
+/**
+ * Convenience function to add an entire string array to the dict.
+ *
+ * @param iter_dict A valid DBusMessageIter returned from
+ *                  wpa_dbus_dict_open_write()
+ * @param key The key of the dict item
+ * @param items The array of strings
+ * @param num_items The number of strings in the array
+ * @return TRUE on success, FALSE on failure
+ *
+ */
+dbus_bool_t wpa_dbus_dict_append_string_array(DBusMessageIter *iter_dict,
+					      const char *key,
+					      const char **items,
+					      const dbus_uint32_t num_items)
+{
+	DBusMessageIter iter_dict_entry, iter_dict_val, iter_array;
+	dbus_uint32_t i;
+
+	if (!key)
+		return FALSE;
+	if (!items && (num_items != 0))
+		return FALSE;
+
+	if (!wpa_dbus_dict_begin_string_array(iter_dict, key,
+					      &iter_dict_entry, &iter_dict_val,
+					      &iter_array))
+		return FALSE;
+
+	for (i = 0; i < num_items; i++) {
+		if (!wpa_dbus_dict_string_array_add_element(&iter_array,
+							    items[i]))
+			return FALSE;
+	}
+
+	if (!wpa_dbus_dict_end_string_array(iter_dict, &iter_dict_entry,
+					    &iter_dict_val, &iter_array))
+		return FALSE;
+
+	return TRUE;
+}
+
+
+/*****************************************************/
+/* Stuff for reading dicts                           */
+/*****************************************************/
+
+/**
+ * Start reading from a dbus dict.
+ *
+ * @param iter A valid DBusMessageIter pointing to the start of the dict
+ * @param iter_dict (out) A DBusMessageIter to be passed to
+ *    wpa_dbus_dict_read_next_entry()
+ * @return TRUE on success, FALSE on failure
+ *
+ */
+dbus_bool_t wpa_dbus_dict_open_read(DBusMessageIter *iter,
+				    DBusMessageIter *iter_dict)
+{
+	if (!iter || !iter_dict)
+		return FALSE;
+
+	if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY ||
+	    dbus_message_iter_get_element_type(iter) != DBUS_TYPE_DICT_ENTRY)
+		return FALSE;
+
+	dbus_message_iter_recurse(iter, iter_dict);
+	return TRUE;
+}
+
+
+#define BYTE_ARRAY_CHUNK_SIZE 34
+#define BYTE_ARRAY_ITEM_SIZE (sizeof(char))
+
+static dbus_bool_t _wpa_dbus_dict_entry_get_byte_array(
+	DBusMessageIter *iter, int array_type,
+	struct wpa_dbus_dict_entry *entry)
+{
+	dbus_uint32_t count = 0;
+	dbus_bool_t success = FALSE;
+	char *buffer, *nbuffer;;
+
+	entry->bytearray_value = NULL;
+	entry->array_type = DBUS_TYPE_BYTE;
+
+	buffer = os_zalloc(BYTE_ARRAY_ITEM_SIZE * BYTE_ARRAY_CHUNK_SIZE);
+	if (!buffer)
+		return FALSE;
+
+	entry->bytearray_value = buffer;
+	entry->array_len = 0;
+	while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_BYTE) {
+		char byte;
+
+		if ((count % BYTE_ARRAY_CHUNK_SIZE) == 0 && count != 0) {
+			nbuffer = os_realloc(buffer, BYTE_ARRAY_ITEM_SIZE *
+					     (count + BYTE_ARRAY_CHUNK_SIZE));
+			if (nbuffer == NULL) {
+				os_free(buffer);
+				wpa_printf(MSG_ERROR, "dbus: _wpa_dbus_dict_"
+					   "entry_get_byte_array out of "
+					   "memory trying to retrieve the "
+					   "string array");
+				goto done;
+			}
+			buffer = nbuffer;
+		}
+		entry->bytearray_value = buffer;
+
+		dbus_message_iter_get_basic(iter, &byte);
+		entry->bytearray_value[count] = byte;
+		entry->array_len = ++count;
+		dbus_message_iter_next(iter);
+	}
+
+	/* Zero-length arrays are valid. */
+	if (entry->array_len == 0) {
+		os_free(entry->bytearray_value);
+		entry->bytearray_value = NULL;
+	}
+
+	success = TRUE;
+
+done:
+	return success;
+}
+
+
+#define STR_ARRAY_CHUNK_SIZE 8
+#define STR_ARRAY_ITEM_SIZE (sizeof(char *))
+
+static dbus_bool_t _wpa_dbus_dict_entry_get_string_array(
+	DBusMessageIter *iter, int array_type,
+	struct wpa_dbus_dict_entry *entry)
+{
+	dbus_uint32_t count = 0;
+	dbus_bool_t success = FALSE;
+	char **buffer, **nbuffer;
+
+	entry->strarray_value = NULL;
+	entry->array_type = DBUS_TYPE_STRING;
+
+	buffer = os_zalloc(STR_ARRAY_ITEM_SIZE * STR_ARRAY_CHUNK_SIZE);
+	if (buffer == NULL)
+		return FALSE;
+
+	entry->strarray_value = buffer;
+	entry->array_len = 0;
+	while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING) {
+		const char *value;
+		char *str;
+
+		if ((count % STR_ARRAY_CHUNK_SIZE) == 0 && count != 0) {
+			nbuffer = os_realloc(buffer, STR_ARRAY_ITEM_SIZE *
+					     (count + STR_ARRAY_CHUNK_SIZE));
+			if (nbuffer == NULL) {
+				os_free(buffer);
+				wpa_printf(MSG_ERROR, "dbus: _wpa_dbus_dict_"
+					   "entry_get_string_array out of "
+					   "memory trying to retrieve the "
+					   "string array");
+				goto done;
+			}
+			buffer = nbuffer;
+		}
+		entry->strarray_value = buffer;
+
+		dbus_message_iter_get_basic(iter, &value);
+		str = os_strdup(value);
+		if (str == NULL) {
+			wpa_printf(MSG_ERROR, "dbus: _wpa_dbus_dict_entry_get_"
+				   "string_array out of memory trying to "
+				   "duplicate the string array");
+			goto done;
+		}
+		entry->strarray_value[count] = str;
+		entry->array_len = ++count;
+		dbus_message_iter_next(iter);
+	}
+
+	/* Zero-length arrays are valid. */
+	if (entry->array_len == 0) {
+		os_free(entry->strarray_value);
+		entry->strarray_value = NULL;
+	}
+
+	success = TRUE;
+
+done:
+	return success;
+}
+
+
+static dbus_bool_t _wpa_dbus_dict_entry_get_array(
+	DBusMessageIter *iter_dict_val, struct wpa_dbus_dict_entry *entry)
+{
+	int array_type = dbus_message_iter_get_element_type(iter_dict_val);
+	dbus_bool_t success = FALSE;
+	DBusMessageIter iter_array;
+
+	if (!entry)
+		return FALSE;
+
+	dbus_message_iter_recurse(iter_dict_val, &iter_array);
+
+ 	switch (array_type) {
+	case DBUS_TYPE_BYTE:
+		success = _wpa_dbus_dict_entry_get_byte_array(&iter_array,
+							      array_type,
+							      entry);
+		break;
+	case DBUS_TYPE_STRING:
+		success = _wpa_dbus_dict_entry_get_string_array(&iter_array,
+								array_type,
+								entry);
+		break;
+	default:
+		break;
+	}
+
+	return success;
+}
+
+
+static dbus_bool_t _wpa_dbus_dict_fill_value_from_variant(
+	struct wpa_dbus_dict_entry *entry, DBusMessageIter *iter)
+{
+	const char *v;
+
+	switch (entry->type) {
+	case DBUS_TYPE_OBJECT_PATH:
+	case DBUS_TYPE_STRING:
+		dbus_message_iter_get_basic(iter, &v);
+		entry->str_value = os_strdup(v);
+		if (entry->str_value == NULL)
+			return FALSE;
+		break;
+	case DBUS_TYPE_BOOLEAN:
+		dbus_message_iter_get_basic(iter, &entry->bool_value);
+		break;
+	case DBUS_TYPE_BYTE:
+		dbus_message_iter_get_basic(iter, &entry->byte_value);
+		break;
+	case DBUS_TYPE_INT16:
+		dbus_message_iter_get_basic(iter, &entry->int16_value);
+		break;
+	case DBUS_TYPE_UINT16:
+		dbus_message_iter_get_basic(iter, &entry->uint16_value);
+		break;
+	case DBUS_TYPE_INT32:
+		dbus_message_iter_get_basic(iter, &entry->int32_value);
+		break;
+	case DBUS_TYPE_UINT32:
+		dbus_message_iter_get_basic(iter, &entry->uint32_value);
+		break;
+	case DBUS_TYPE_INT64:
+		dbus_message_iter_get_basic(iter, &entry->int64_value);
+		break;
+	case DBUS_TYPE_UINT64:
+		dbus_message_iter_get_basic(iter, &entry->uint64_value);
+		break;
+	case DBUS_TYPE_DOUBLE:
+		dbus_message_iter_get_basic(iter, &entry->double_value);
+		break;
+	case DBUS_TYPE_ARRAY:
+		return _wpa_dbus_dict_entry_get_array(iter, entry);
+	default:
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+
+/**
+ * Read the current key/value entry from the dict.  Entries are dynamically
+ * allocated when needed and must be freed after use with the
+ * wpa_dbus_dict_entry_clear() function.
+ *
+ * The returned entry object will be filled with the type and value of the next
+ * entry in the dict, or the type will be DBUS_TYPE_INVALID if an error
+ * occurred.
+ *
+ * @param iter_dict A valid DBusMessageIter returned from
+ *    wpa_dbus_dict_open_read()
+ * @param entry A valid dict entry object into which the dict key and value
+ *    will be placed
+ * @return TRUE on success, FALSE on failure
+ *
+ */
+dbus_bool_t wpa_dbus_dict_get_entry(DBusMessageIter *iter_dict,
+				    struct wpa_dbus_dict_entry * entry)
+{
+	DBusMessageIter iter_dict_entry, iter_dict_val;
+	int type;
+	const char *key;
+
+	if (!iter_dict || !entry)
+		goto error;
+
+	if (dbus_message_iter_get_arg_type(iter_dict) != DBUS_TYPE_DICT_ENTRY)
+		goto error;
+
+	dbus_message_iter_recurse(iter_dict, &iter_dict_entry);
+	dbus_message_iter_get_basic(&iter_dict_entry, &key);
+	entry->key = key;
+
+	if (!dbus_message_iter_next(&iter_dict_entry))
+		goto error;
+	type = dbus_message_iter_get_arg_type(&iter_dict_entry);
+	if (type != DBUS_TYPE_VARIANT)
+		goto error;
+
+	dbus_message_iter_recurse(&iter_dict_entry, &iter_dict_val);
+	entry->type = dbus_message_iter_get_arg_type(&iter_dict_val);
+	if (!_wpa_dbus_dict_fill_value_from_variant(entry, &iter_dict_val))
+		goto error;
+
+	dbus_message_iter_next(iter_dict);
+	return TRUE;
+
+error:
+	if (entry) {
+		wpa_dbus_dict_entry_clear(entry);
+		entry->type = DBUS_TYPE_INVALID;
+		entry->array_type = DBUS_TYPE_INVALID;
+	}
+
+	return FALSE;
+}
+
+
+/**
+ * Return whether or not there are additional dictionary entries.
+ *
+ * @param iter_dict A valid DBusMessageIter returned from
+ *    wpa_dbus_dict_open_read()
+ * @return TRUE if more dict entries exists, FALSE if no more dict entries
+ * exist
+ */
+dbus_bool_t wpa_dbus_dict_has_dict_entry(DBusMessageIter *iter_dict)
+{
+	if (!iter_dict)
+		return FALSE;
+	return dbus_message_iter_get_arg_type(iter_dict) ==
+		DBUS_TYPE_DICT_ENTRY;
+}
+
+
+/**
+ * Free any memory used by the entry object.
+ *
+ * @param entry The entry object
+ */
+void wpa_dbus_dict_entry_clear(struct wpa_dbus_dict_entry *entry)
+{
+	unsigned int i;
+
+	if (!entry)
+		return;
+	switch (entry->type) {
+	case DBUS_TYPE_OBJECT_PATH:
+	case DBUS_TYPE_STRING:
+		os_free(entry->str_value);
+		break;
+	case DBUS_TYPE_ARRAY:
+		switch (entry->array_type) {
+		case DBUS_TYPE_BYTE:
+			os_free(entry->bytearray_value);
+			break;
+		case DBUS_TYPE_STRING:
+			for (i = 0; i < entry->array_len; i++)
+				os_free(entry->strarray_value[i]);
+			os_free(entry->strarray_value);
+			break;
+		}
+		break;
+	}
+
+	memset(entry, 0, sizeof(struct wpa_dbus_dict_entry));
+}
diff --git a/wpa_supplicant/dbus/dbus_dict_helpers.h b/wpa_supplicant/dbus/dbus_dict_helpers.h
new file mode 100644
index 0000000..eb31575
--- /dev/null
+++ b/wpa_supplicant/dbus/dbus_dict_helpers.h
@@ -0,0 +1,137 @@
+/*
+ * WPA Supplicant / dbus-based control interface
+ * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
+ *
+ * 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.
+ */
+
+#ifndef DBUS_DICT_HELPERS_H
+#define DBUS_DICT_HELPERS_H
+
+/*
+ * Adding a dict to a DBusMessage
+ */
+
+dbus_bool_t wpa_dbus_dict_open_write(DBusMessageIter *iter,
+				     DBusMessageIter *iter_dict);
+
+dbus_bool_t wpa_dbus_dict_close_write(DBusMessageIter *iter,
+				      DBusMessageIter *iter_dict);
+
+const char * wpa_dbus_type_as_string(const int type);
+
+dbus_bool_t wpa_dbus_dict_append_string(DBusMessageIter *iter_dict,
+					const char *key, const char *value);
+
+dbus_bool_t wpa_dbus_dict_append_byte(DBusMessageIter *iter_dict,
+				      const char *key, const char value);
+
+dbus_bool_t wpa_dbus_dict_append_bool(DBusMessageIter *iter_dict,
+				      const char *key,
+				      const dbus_bool_t value);
+
+dbus_bool_t wpa_dbus_dict_append_int16(DBusMessageIter *iter_dict,
+				       const char *key,
+				       const dbus_int16_t value);
+
+dbus_bool_t wpa_dbus_dict_append_uint16(DBusMessageIter *iter_dict,
+					const char *key,
+					const dbus_uint16_t value);
+
+dbus_bool_t wpa_dbus_dict_append_int32(DBusMessageIter *iter_dict,
+				       const char *key,
+				       const dbus_int32_t value);
+
+dbus_bool_t wpa_dbus_dict_append_uint32(DBusMessageIter *iter_dict,
+					const char *key,
+					const dbus_uint32_t value);
+
+dbus_bool_t wpa_dbus_dict_append_int64(DBusMessageIter *iter_dict,
+				       const char *key,
+				       const dbus_int64_t value);
+
+dbus_bool_t wpa_dbus_dict_append_uint64(DBusMessageIter *iter_dict,
+					const char *key,
+					const dbus_uint64_t value);
+
+dbus_bool_t wpa_dbus_dict_append_double(DBusMessageIter *iter_dict,
+					const char *key,
+					const double value);
+
+dbus_bool_t wpa_dbus_dict_append_object_path(DBusMessageIter *iter_dict,
+					     const char *key,
+					     const char *value);
+
+dbus_bool_t wpa_dbus_dict_append_byte_array(DBusMessageIter *iter_dict,
+					    const char *key,
+					    const char *value,
+					    const dbus_uint32_t value_len);
+
+/* Manual construction and addition of string array elements */
+dbus_bool_t wpa_dbus_dict_begin_string_array(DBusMessageIter *iter_dict,
+                                             const char *key,
+                                             DBusMessageIter *iter_dict_entry,
+                                             DBusMessageIter *iter_dict_val,
+                                             DBusMessageIter *iter_array);
+
+dbus_bool_t wpa_dbus_dict_string_array_add_element(DBusMessageIter *iter_array,
+                                             const char *elem);
+
+dbus_bool_t wpa_dbus_dict_end_string_array(DBusMessageIter *iter_dict,
+                                           DBusMessageIter *iter_dict_entry,
+                                           DBusMessageIter *iter_dict_val,
+                                           DBusMessageIter *iter_array);
+
+/* Convenience function to add a whole string list */
+dbus_bool_t wpa_dbus_dict_append_string_array(DBusMessageIter *iter_dict,
+					      const char *key,
+					      const char **items,
+					      const dbus_uint32_t num_items);
+
+/*
+ * Reading a dict from a DBusMessage
+ */
+
+struct wpa_dbus_dict_entry {
+	int type;         /** the dbus type of the dict entry's value */
+	int array_type;   /** the dbus type of the array elements if the dict
+			      entry value contains an array */
+	const char *key;  /** key of the dict entry */
+
+	/** Possible values of the property */
+	union {
+		char *str_value;
+		char byte_value;
+		dbus_bool_t bool_value;
+		dbus_int16_t int16_value;
+		dbus_uint16_t uint16_value;
+		dbus_int32_t int32_value;
+		dbus_uint32_t uint32_value;
+		dbus_int64_t int64_value;
+		dbus_uint64_t uint64_value;
+		double double_value;
+		char *bytearray_value;
+		char **strarray_value;
+	};
+	dbus_uint32_t array_len; /** length of the array if the dict entry's
+				     value contains an array */
+};
+
+dbus_bool_t wpa_dbus_dict_open_read(DBusMessageIter *iter,
+				    DBusMessageIter *iter_dict);
+
+dbus_bool_t wpa_dbus_dict_get_entry(DBusMessageIter *iter_dict,
+				    struct wpa_dbus_dict_entry *entry);
+
+dbus_bool_t wpa_dbus_dict_has_dict_entry(DBusMessageIter *iter_dict);
+
+void wpa_dbus_dict_entry_clear(struct wpa_dbus_dict_entry *entry);
+
+#endif  /* DBUS_DICT_HELPERS_H */
diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c
new file mode 100644
index 0000000..49a0895
--- /dev/null
+++ b/wpa_supplicant/dbus/dbus_new.c
@@ -0,0 +1,1605 @@
+/*
+ * WPA Supplicant / dbus-based control interface
+ * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
+ * Copyright (c) 2009-2010, Witold Sowa <witold.sowa@gmail.com>
+ * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
+ *
+ * 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 "includes.h"
+
+#include "common.h"
+#include "wps/wps.h"
+#include "../config.h"
+#include "../wpa_supplicant_i.h"
+#include "../bss.h"
+#include "dbus_new_helpers.h"
+#include "dbus_dict_helpers.h"
+#include "dbus_new.h"
+#include "dbus_new_handlers.h"
+#include "dbus_common.h"
+#include "dbus_common_i.h"
+
+
+/**
+ * wpas_dbus_signal_interface - Send a interface related event signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @sig_name: signal name - InterfaceAdded or InterfaceRemoved
+ * @properties: Whether to add second argument with object properties
+ *
+ * Notify listeners about event related with interface
+ */
+static void wpas_dbus_signal_interface(struct wpa_supplicant *wpa_s,
+				       const char *sig_name, int properties)
+{
+	struct wpas_dbus_priv *iface;
+	DBusMessage *msg;
+	DBusMessageIter iter, iter_dict;
+
+	iface = wpa_s->global->dbus;
+
+	/* Do nothing if the control interface is not turned on */
+	if (iface == NULL)
+		return;
+
+	msg = dbus_message_new_signal(WPAS_DBUS_NEW_PATH,
+				      WPAS_DBUS_NEW_INTERFACE, sig_name);
+	if (msg == NULL)
+		return;
+
+	dbus_message_iter_init_append(msg, &iter);
+	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
+					    &wpa_s->dbus_new_path))
+		goto err;
+
+	if (properties) {
+		if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
+			goto err;
+
+		wpa_dbus_get_object_properties(iface, wpa_s->dbus_new_path,
+					       WPAS_DBUS_NEW_IFACE_INTERFACE,
+					       &iter_dict);
+
+		if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
+			goto err;
+	}
+
+	dbus_connection_send(iface->con, msg, NULL);
+	dbus_message_unref(msg);
+	return;
+
+err:
+	wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
+	dbus_message_unref(msg);
+}
+
+
+/**
+ * wpas_dbus_signal_interface_added - Send a interface created signal
+ * @wpa_s: %wpa_supplicant network interface data
+ *
+ * Notify listeners about creating new interface
+ */
+static void wpas_dbus_signal_interface_added(struct wpa_supplicant *wpa_s)
+{
+	wpas_dbus_signal_interface(wpa_s, "InterfaceAdded", TRUE);
+}
+
+
+/**
+ * wpas_dbus_signal_interface_removed - Send a interface removed signal
+ * @wpa_s: %wpa_supplicant network interface data
+ *
+ * Notify listeners about removing interface
+ */
+static void wpas_dbus_signal_interface_removed(struct wpa_supplicant *wpa_s)
+{
+	wpas_dbus_signal_interface(wpa_s, "InterfaceRemoved", FALSE);
+
+}
+
+
+/**
+ * wpas_dbus_signal_scan_done - send scan done signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @success: indicates if scanning succeed or failed
+ *
+ * Notify listeners about finishing a scan
+ */
+void wpas_dbus_signal_scan_done(struct wpa_supplicant *wpa_s, int success)
+{
+	struct wpas_dbus_priv *iface;
+	DBusMessage *msg;
+	dbus_bool_t succ;
+
+	iface = wpa_s->global->dbus;
+
+	/* Do nothing if the control interface is not turned on */
+	if (iface == NULL)
+		return;
+
+	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
+				      WPAS_DBUS_NEW_IFACE_INTERFACE,
+				      "ScanDone");
+	if (msg == NULL)
+		return;
+
+	succ = success ? TRUE : FALSE;
+	if (dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &succ,
+				     DBUS_TYPE_INVALID))
+		dbus_connection_send(iface->con, msg, NULL);
+	else
+		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
+	dbus_message_unref(msg);
+}
+
+
+/**
+ * wpas_dbus_signal_blob - Send a BSS related event signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @bss_obj_path: BSS object path
+ * @sig_name: signal name - BSSAdded or BSSRemoved
+ * @properties: Whether to add second argument with object properties
+ *
+ * Notify listeners about event related with BSS
+ */
+static void wpas_dbus_signal_bss(struct wpa_supplicant *wpa_s,
+				 const char *bss_obj_path,
+				 const char *sig_name, int properties)
+{
+	struct wpas_dbus_priv *iface;
+	DBusMessage *msg;
+	DBusMessageIter iter, iter_dict;
+
+	iface = wpa_s->global->dbus;
+
+	/* Do nothing if the control interface is not turned on */
+	if (iface == NULL)
+		return;
+
+	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
+				      WPAS_DBUS_NEW_IFACE_INTERFACE,
+				      sig_name);
+	if (msg == NULL)
+		return;
+
+	dbus_message_iter_init_append(msg, &iter);
+	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
+					    &bss_obj_path))
+		goto err;
+
+	if (properties) {
+		if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
+			goto err;
+
+		wpa_dbus_get_object_properties(iface, bss_obj_path,
+					       WPAS_DBUS_NEW_IFACE_BSS,
+					       &iter_dict);
+
+		if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
+			goto err;
+	}
+
+	dbus_connection_send(iface->con, msg, NULL);
+	dbus_message_unref(msg);
+	return;
+
+err:
+	wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
+	dbus_message_unref(msg);
+}
+
+
+/**
+ * wpas_dbus_signal_bss_added - Send a BSS added signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @bss_obj_path: new BSS object path
+ *
+ * Notify listeners about adding new BSS
+ */
+static void wpas_dbus_signal_bss_added(struct wpa_supplicant *wpa_s,
+				       const char *bss_obj_path)
+{
+	wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSAdded", TRUE);
+}
+
+
+/**
+ * wpas_dbus_signal_bss_removed - Send a BSS removed signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @bss_obj_path: BSS object path
+ *
+ * Notify listeners about removing BSS
+ */
+static void wpas_dbus_signal_bss_removed(struct wpa_supplicant *wpa_s,
+					 const char *bss_obj_path)
+{
+	wpas_dbus_signal_bss(wpa_s, bss_obj_path, "BSSRemoved", FALSE);
+}
+
+
+/**
+ * wpas_dbus_signal_blob - Send a blob related event signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @name: blob name
+ * @sig_name: signal name - BlobAdded or BlobRemoved
+ *
+ * Notify listeners about event related with blob
+ */
+static void wpas_dbus_signal_blob(struct wpa_supplicant *wpa_s,
+				  const char *name, const char *sig_name)
+{
+	struct wpas_dbus_priv *iface;
+	DBusMessage *msg;
+
+	iface = wpa_s->global->dbus;
+
+	/* Do nothing if the control interface is not turned on */
+	if (iface == NULL)
+		return;
+
+	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
+				      WPAS_DBUS_NEW_IFACE_INTERFACE,
+				      sig_name);
+	if (msg == NULL)
+		return;
+
+	if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &name,
+				     DBUS_TYPE_INVALID))
+		dbus_connection_send(iface->con, msg, NULL);
+	else
+		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
+	dbus_message_unref(msg);
+}
+
+
+/**
+ * wpas_dbus_signal_blob_added - Send a blob added signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @name: blob name
+ *
+ * Notify listeners about adding a new blob
+ */
+void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s,
+				 const char *name)
+{
+	wpas_dbus_signal_blob(wpa_s, name, "BlobAdded");
+}
+
+
+/**
+ * wpas_dbus_signal_blob_removed - Send a blob removed signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @name: blob name
+ *
+ * Notify listeners about removing blob
+ */
+void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s,
+				   const char *name)
+{
+	wpas_dbus_signal_blob(wpa_s, name, "BlobRemoved");
+}
+
+
+/**
+ * wpas_dbus_signal_network - Send a network related event signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @id: new network id
+ * @sig_name: signal name - NetworkAdded, NetworkRemoved or NetworkSelected
+ * @properties: determines if add second argument with object properties
+ *
+ * Notify listeners about event related with configured network
+ */
+static void wpas_dbus_signal_network(struct wpa_supplicant *wpa_s,
+				     int id, const char *sig_name,
+				     int properties)
+{
+	struct wpas_dbus_priv *iface;
+	DBusMessage *msg;
+	DBusMessageIter iter, iter_dict;
+	char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
+
+	iface = wpa_s->global->dbus;
+
+	/* Do nothing if the control interface is not turned on */
+	if (iface == NULL)
+		return;
+
+	os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
+		    wpa_s->dbus_new_path, id);
+
+	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
+				      WPAS_DBUS_NEW_IFACE_INTERFACE,
+				      sig_name);
+	if (msg == NULL)
+		return;
+
+	dbus_message_iter_init_append(msg, &iter);
+	path = net_obj_path;
+	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
+					    &path))
+		goto err;
+
+	if (properties) {
+		if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
+			goto err;
+
+		wpa_dbus_get_object_properties(iface, net_obj_path,
+					       WPAS_DBUS_NEW_IFACE_NETWORK,
+					       &iter_dict);
+
+		if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
+			goto err;
+	}
+
+	dbus_connection_send(iface->con, msg, NULL);
+
+	dbus_message_unref(msg);
+	return;
+
+err:
+	wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
+	dbus_message_unref(msg);
+}
+
+
+/**
+ * wpas_dbus_signal_network_added - Send a network added signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @id: new network id
+ *
+ * Notify listeners about adding new network
+ */
+static void wpas_dbus_signal_network_added(struct wpa_supplicant *wpa_s,
+					   int id)
+{
+	wpas_dbus_signal_network(wpa_s, id, "NetworkAdded", TRUE);
+}
+
+
+/**
+ * wpas_dbus_signal_network_removed - Send a network removed signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @id: network id
+ *
+ * Notify listeners about removing a network
+ */
+static void wpas_dbus_signal_network_removed(struct wpa_supplicant *wpa_s,
+					     int id)
+{
+	wpas_dbus_signal_network(wpa_s, id, "NetworkRemoved", FALSE);
+}
+
+
+/**
+ * wpas_dbus_signal_network_selected - Send a network selected signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @id: network id
+ *
+ * Notify listeners about selecting a network
+ */
+void wpas_dbus_signal_network_selected(struct wpa_supplicant *wpa_s, int id)
+{
+	wpas_dbus_signal_network(wpa_s, id, "NetworkSelected", FALSE);
+}
+
+
+/**
+ * wpas_dbus_signal_network_enabled_changed - Signals Enabled property changes
+ * @wpa_s: %wpa_supplicant network interface data
+ * @ssid: configured network which Enabled property has changed
+ *
+ * Sends PropertyChanged signals containing new value of Enabled property
+ * for specified network
+ */
+void wpas_dbus_signal_network_enabled_changed(struct wpa_supplicant *wpa_s,
+					      struct wpa_ssid *ssid)
+{
+
+	char path[WPAS_DBUS_OBJECT_PATH_MAX];
+	os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
+		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
+		    wpa_s->dbus_new_path, ssid->id);
+
+	wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
+				       WPAS_DBUS_NEW_IFACE_NETWORK, "Enabled");
+}
+
+
+#ifdef CONFIG_WPS
+
+/**
+ * wpas_dbus_signal_wps_event_success - Signals Success WPS event
+ * @wpa_s: %wpa_supplicant network interface data
+ *
+ * Sends Event dbus signal with name "success" and empty dict as arguments
+ */
+void wpas_dbus_signal_wps_event_success(struct wpa_supplicant *wpa_s)
+{
+
+	DBusMessage *msg;
+	DBusMessageIter iter, dict_iter;
+	struct wpas_dbus_priv *iface;
+	char *key = "success";
+
+	iface = wpa_s->global->dbus;
+
+	/* Do nothing if the control interface is not turned on */
+	if (iface == NULL)
+		return;
+
+	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
+				      WPAS_DBUS_NEW_IFACE_WPS, "Event");
+	if (msg == NULL)
+		return;
+
+	dbus_message_iter_init_append(msg, &iter);
+
+	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
+	    !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
+	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
+		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
+	else
+		dbus_connection_send(iface->con, msg, NULL);
+
+	dbus_message_unref(msg);
+}
+
+
+/**
+ * wpas_dbus_signal_wps_event_fail - Signals Fail WPS event
+ * @wpa_s: %wpa_supplicant network interface data
+ *
+ * Sends Event dbus signal with name "fail" and dictionary containing
+ * "msg field with fail message number (int32) as arguments
+ */
+void wpas_dbus_signal_wps_event_fail(struct wpa_supplicant *wpa_s,
+				     struct wps_event_fail *fail)
+{
+
+	DBusMessage *msg;
+	DBusMessageIter iter, dict_iter;
+	struct wpas_dbus_priv *iface;
+	char *key = "fail";
+
+	iface = wpa_s->global->dbus;
+
+	/* Do nothing if the control interface is not turned on */
+	if (iface == NULL)
+		return;
+
+	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
+				      WPAS_DBUS_NEW_IFACE_WPS, "Event");
+	if (msg == NULL)
+		return;
+
+	dbus_message_iter_init_append(msg, &iter);
+
+	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
+	    !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
+	    !wpa_dbus_dict_append_int32(&dict_iter, "msg", fail->msg) ||
+	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
+		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
+	else
+		dbus_connection_send(iface->con, msg, NULL);
+
+	dbus_message_unref(msg);
+}
+
+
+/**
+ * wpas_dbus_signal_wps_event_m2d - Signals M2D WPS event
+ * @wpa_s: %wpa_supplicant network interface data
+ *
+ * Sends Event dbus signal with name "m2d" and dictionary containing
+ * fields of wps_event_m2d structure.
+ */
+void wpas_dbus_signal_wps_event_m2d(struct wpa_supplicant *wpa_s,
+				    struct wps_event_m2d *m2d)
+{
+
+	DBusMessage *msg;
+	DBusMessageIter iter, dict_iter;
+	struct wpas_dbus_priv *iface;
+	char *key = "m2d";
+
+	iface = wpa_s->global->dbus;
+
+	/* Do nothing if the control interface is not turned on */
+	if (iface == NULL)
+		return;
+
+	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
+				      WPAS_DBUS_NEW_IFACE_WPS, "Event");
+	if (msg == NULL)
+		return;
+
+	dbus_message_iter_init_append(msg, &iter);
+
+	if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key) ||
+	    !wpa_dbus_dict_open_write(&iter, &dict_iter) ||
+	    !wpa_dbus_dict_append_uint16(&dict_iter, "config_methods",
+					 m2d->config_methods) ||
+	    !wpa_dbus_dict_append_byte_array(&dict_iter, "manufacturer",
+					     (const char *) m2d->manufacturer,
+					     m2d->manufacturer_len) ||
+	    !wpa_dbus_dict_append_byte_array(&dict_iter, "model_name",
+					     (const char *) m2d->model_name,
+					     m2d->model_name_len) ||
+	    !wpa_dbus_dict_append_byte_array(&dict_iter, "model_number",
+					     (const char *) m2d->model_number,
+					     m2d->model_number_len) ||
+	    !wpa_dbus_dict_append_byte_array(&dict_iter, "serial_number",
+					     (const char *)
+					     m2d->serial_number,
+					     m2d->serial_number_len) ||
+	    !wpa_dbus_dict_append_byte_array(&dict_iter, "dev_name",
+					     (const char *) m2d->dev_name,
+					     m2d->dev_name_len) ||
+	    !wpa_dbus_dict_append_byte_array(&dict_iter, "primary_dev_type",
+					     (const char *)
+					     m2d->primary_dev_type, 8) ||
+	    !wpa_dbus_dict_append_uint16(&dict_iter, "config_error",
+					 m2d->config_error) ||
+	    !wpa_dbus_dict_append_uint16(&dict_iter, "dev_password_id",
+					 m2d->dev_password_id) ||
+	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
+		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
+	else
+		dbus_connection_send(iface->con, msg, NULL);
+
+	dbus_message_unref(msg);
+}
+
+
+/**
+ * wpas_dbus_signal_wps_cred - Signals new credentials
+ * @wpa_s: %wpa_supplicant network interface data
+ *
+ * Sends signal with credentials in directory argument
+ */
+void wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s,
+			       const struct wps_credential *cred)
+{
+	DBusMessage *msg;
+	DBusMessageIter iter, dict_iter;
+	struct wpas_dbus_priv *iface;
+	char *auth_type[6]; /* we have six possible authorization types */
+	int at_num = 0;
+	char *encr_type[4]; /* we have four possible encryption types */
+	int et_num = 0;
+
+	iface = wpa_s->global->dbus;
+
+	/* Do nothing if the control interface is not turned on */
+	if (iface == NULL)
+		return;
+
+	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
+				      WPAS_DBUS_NEW_IFACE_WPS,
+				      "Credentials");
+	if (msg == NULL)
+		return;
+
+	dbus_message_iter_init_append(msg, &iter);
+	if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
+		goto nomem;
+
+	if (cred->auth_type & WPS_AUTH_OPEN)
+		auth_type[at_num++] = "open";
+	if (cred->auth_type & WPS_AUTH_WPAPSK)
+		auth_type[at_num++] = "wpa-psk";
+	if (cred->auth_type & WPS_AUTH_SHARED)
+		auth_type[at_num++] = "shared";
+	if (cred->auth_type & WPS_AUTH_WPA)
+		auth_type[at_num++] = "wpa-eap";
+	if (cred->auth_type & WPS_AUTH_WPA2)
+		auth_type[at_num++] = "wpa2-eap";
+	if (cred->auth_type & WPS_AUTH_WPA2PSK)
+		auth_type[at_num++] =
+		"wpa2-psk";
+
+	if (cred->encr_type & WPS_ENCR_NONE)
+		encr_type[et_num++] = "none";
+	if (cred->encr_type & WPS_ENCR_WEP)
+		encr_type[et_num++] = "wep";
+	if (cred->encr_type & WPS_ENCR_TKIP)
+		encr_type[et_num++] = "tkip";
+	if (cred->encr_type & WPS_ENCR_AES)
+		encr_type[et_num++] = "aes";
+
+	if (wpa_s->current_ssid) {
+		if (!wpa_dbus_dict_append_byte_array(
+			    &dict_iter, "BSSID",
+			    (const char *) wpa_s->current_ssid->bssid,
+			    ETH_ALEN))
+			goto nomem;
+	}
+
+	if (!wpa_dbus_dict_append_byte_array(&dict_iter, "SSID",
+					     (const char *) cred->ssid,
+					     cred->ssid_len) ||
+	    !wpa_dbus_dict_append_string_array(&dict_iter, "AuthType",
+					       (const char **) auth_type,
+					       at_num) ||
+	    !wpa_dbus_dict_append_string_array(&dict_iter, "EncrType",
+					       (const char **) encr_type,
+					       et_num) ||
+	    !wpa_dbus_dict_append_byte_array(&dict_iter, "Key",
+					     (const char *) cred->key,
+					     cred->key_len) ||
+	    !wpa_dbus_dict_append_uint32(&dict_iter, "KeyIndex",
+					 cred->key_idx) ||
+	    !wpa_dbus_dict_close_write(&iter, &dict_iter))
+		goto nomem;
+
+	dbus_connection_send(iface->con, msg, NULL);
+
+nomem:
+	dbus_message_unref(msg);
+}
+
+#endif /* CONFIG_WPS */
+
+
+/**
+ * wpas_dbus_signal_prop_changed - Signals change of property
+ * @wpa_s: %wpa_supplicant network interface data
+ * @property: indicates which property has changed
+ *
+ * Sends ProertyChanged signals with path, interface and arguments
+ * depending on which property has changed.
+ */
+void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
+				   enum wpas_dbus_prop property)
+{
+	WPADBusPropertyAccessor getter;
+	char *prop;
+
+	if (wpa_s->dbus_new_path == NULL)
+		return; /* Skip signal since D-Bus setup is not yet ready */
+
+	switch (property) {
+	case WPAS_DBUS_PROP_AP_SCAN:
+		getter = (WPADBusPropertyAccessor) wpas_dbus_getter_ap_scan;
+		prop = "ApScan";
+		break;
+	case WPAS_DBUS_PROP_SCANNING:
+		getter = (WPADBusPropertyAccessor) wpas_dbus_getter_scanning;
+		prop = "Scanning";
+		break;
+	case WPAS_DBUS_PROP_STATE:
+		getter = (WPADBusPropertyAccessor) wpas_dbus_getter_state;
+		prop = "State";
+		break;
+	case WPAS_DBUS_PROP_CURRENT_BSS:
+		getter = (WPADBusPropertyAccessor)
+			wpas_dbus_getter_current_bss;
+		prop = "CurrentBSS";
+		break;
+	case WPAS_DBUS_PROP_CURRENT_NETWORK:
+		getter = (WPADBusPropertyAccessor)
+			wpas_dbus_getter_current_network;
+		prop = "CurrentNetwork";
+		break;
+	case WPAS_DBUS_PROP_BSSS:
+		getter = (WPADBusPropertyAccessor) wpas_dbus_getter_bsss;
+		prop = "BSSs";
+		break;
+	case WPAS_DBUS_PROP_CURRENT_AUTH_MODE:
+		getter = (WPADBusPropertyAccessor)
+			wpas_dbus_getter_current_auth_mode;
+		prop = "CurrentAuthMode";
+		break;
+	default:
+		wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
+			   __func__, property);
+		return;
+	}
+
+	wpa_dbus_mark_property_changed(wpa_s->global->dbus,
+				       wpa_s->dbus_new_path,
+				       WPAS_DBUS_NEW_IFACE_INTERFACE, prop);
+}
+
+
+/**
+ * wpas_dbus_bss_signal_prop_changed - Signals change of BSS property
+ * @wpa_s: %wpa_supplicant network interface data
+ * @property: indicates which property has changed
+ * @id: unique BSS identifier
+ *
+ * Sends PropertyChanged signals with path, interface, and arguments depending
+ * on which property has changed.
+ */
+void wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant *wpa_s,
+				       enum wpas_dbus_bss_prop property,
+				       unsigned int id)
+{
+	char path[WPAS_DBUS_OBJECT_PATH_MAX];
+	char *prop;
+
+	switch (property) {
+	case WPAS_DBUS_BSS_PROP_SIGNAL:
+		prop = "Signal";
+		break;
+	case WPAS_DBUS_BSS_PROP_FREQ:
+		prop = "Frequency";
+		break;
+	case WPAS_DBUS_BSS_PROP_MODE:
+		prop = "Mode";
+		break;
+	case WPAS_DBUS_BSS_PROP_PRIVACY:
+		prop = "Privacy";
+		break;
+	case WPAS_DBUS_BSS_PROP_RATES:
+		prop = "Rates";
+		break;
+	case WPAS_DBUS_BSS_PROP_WPA:
+		prop = "WPA";
+		break;
+	case WPAS_DBUS_BSS_PROP_RSN:
+		prop = "RSN";
+		break;
+	case WPAS_DBUS_BSS_PROP_IES:
+		prop = "IEs";
+		break;
+	default:
+		wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
+			   __func__, property);
+		return;
+	}
+
+	os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
+		    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
+		    wpa_s->dbus_new_path, id);
+
+	wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
+				       WPAS_DBUS_NEW_IFACE_BSS, prop);
+}
+
+
+/**
+ * wpas_dbus_signal_debug_level_changed - Signals change of debug param
+ * @global: wpa_global structure
+ *
+ * Sends ProertyChanged signals informing that debug level has changed.
+ */
+void wpas_dbus_signal_debug_level_changed(struct wpa_global *global)
+{
+	wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
+				       WPAS_DBUS_NEW_INTERFACE,
+				       "DebugLevel");
+}
+
+
+/**
+ * wpas_dbus_signal_debug_timestamp_changed - Signals change of debug param
+ * @global: wpa_global structure
+ *
+ * Sends ProertyChanged signals informing that debug timestamp has changed.
+ */
+void wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global)
+{
+	wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
+				       WPAS_DBUS_NEW_INTERFACE,
+				       "DebugTimestamp");
+}
+
+
+/**
+ * wpas_dbus_signal_debug_show_keys_changed - Signals change of debug param
+ * @global: wpa_global structure
+ *
+ * Sends ProertyChanged signals informing that debug show_keys has changed.
+ */
+void wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global)
+{
+	wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
+				       WPAS_DBUS_NEW_INTERFACE,
+				       "DebugShowKeys");
+}
+
+
+static void wpas_dbus_register(struct wpa_dbus_object_desc *obj_desc,
+			       void *priv,
+			       WPADBusArgumentFreeFunction priv_free,
+			       const struct wpa_dbus_method_desc *methods,
+			       const struct wpa_dbus_property_desc *properties,
+			       const struct wpa_dbus_signal_desc *signals)
+{
+	int n;
+
+	obj_desc->user_data = priv;
+	obj_desc->user_data_free_func = priv_free;
+	obj_desc->methods = methods;
+	obj_desc->properties = properties;
+	obj_desc->signals = signals;
+
+	for (n = 0; properties && properties->dbus_property; properties++)
+		n++;
+
+	obj_desc->prop_changed_flags = os_zalloc(n);
+	if (!obj_desc->prop_changed_flags)
+		wpa_printf(MSG_DEBUG, "dbus: %s: can't register handlers",
+			   __func__);
+}
+
+
+static const struct wpa_dbus_method_desc wpas_dbus_global_methods[] = {
+	{ "CreateInterface", WPAS_DBUS_NEW_INTERFACE,
+	  (WPADBusMethodHandler) &wpas_dbus_handler_create_interface,
+	  {
+		  { "args", "a{sv}", ARG_IN },
+		  { "path", "o", ARG_OUT },
+		  END_ARGS
+	  }
+	},
+	{ "RemoveInterface", WPAS_DBUS_NEW_INTERFACE,
+	  (WPADBusMethodHandler) &wpas_dbus_handler_remove_interface,
+	  {
+		  { "path", "o", ARG_IN },
+		  END_ARGS
+	  }
+	},
+	{ "GetInterface", WPAS_DBUS_NEW_INTERFACE,
+	  (WPADBusMethodHandler) &wpas_dbus_handler_get_interface,
+	  {
+		  { "ifname", "s", ARG_IN },
+		  { "path", "o", ARG_OUT },
+		  END_ARGS
+	  }
+	},
+	{ NULL, NULL, NULL, { END_ARGS } }
+};
+
+static const struct wpa_dbus_property_desc wpas_dbus_global_properties[] = {
+	{ "DebugLevel", WPAS_DBUS_NEW_INTERFACE, "s",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_debug_level,
+	  (WPADBusPropertyAccessor) wpas_dbus_setter_debug_level,
+	  RW
+	},
+	{ "DebugTimestamp", WPAS_DBUS_NEW_INTERFACE, "b",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_debug_timestamp,
+	  (WPADBusPropertyAccessor) wpas_dbus_setter_debug_timestamp,
+	  RW
+	},
+	{ "DebugShowKeys", WPAS_DBUS_NEW_INTERFACE, "b",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_debug_show_keys,
+	  (WPADBusPropertyAccessor) wpas_dbus_setter_debug_show_keys,
+	  RW
+	},
+	{ "Interfaces", WPAS_DBUS_NEW_INTERFACE, "ao",
+	  (WPADBusPropertyAccessor) &wpas_dbus_getter_interfaces,
+	  NULL,
+	  R
+	},
+	{ "EapMethods", WPAS_DBUS_NEW_INTERFACE, "as",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_eap_methods,
+	  NULL,
+	  R
+	},
+	{ NULL, NULL, NULL, NULL, NULL, 0 }
+};
+
+static const struct wpa_dbus_signal_desc wpas_dbus_global_signals[] = {
+	{ "InterfaceAdded", WPAS_DBUS_NEW_INTERFACE,
+	  {
+		  { "path", "o", ARG_OUT },
+		  { "properties", "a{sv}", ARG_OUT },
+		  END_ARGS
+	  }
+	},
+	{ "InterfaceRemoved", WPAS_DBUS_NEW_INTERFACE,
+	  {
+		  { "path", "o", ARG_OUT },
+		  END_ARGS
+	  }
+	},
+	{ "PropertiesChanged", WPAS_DBUS_NEW_INTERFACE,
+	  {
+		  { "properties", "a{sv}", ARG_OUT },
+		  END_ARGS
+	  }
+	},
+	{ NULL, NULL, { END_ARGS } }
+};
+
+
+/**
+ * wpas_dbus_ctrl_iface_init - Initialize dbus control interface
+ * @global: Pointer to global data from wpa_supplicant_init()
+ * Returns: 0 on success or -1 on failure
+ *
+ * Initialize the dbus control interface for wpa_supplicantand and start
+ * receiving commands from external programs over the bus.
+ */
+int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv)
+{
+	struct wpa_dbus_object_desc *obj_desc;
+	int ret;
+
+	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
+	if (!obj_desc) {
+		wpa_printf(MSG_ERROR, "Not enough memory "
+			   "to create object description");
+		return -1;
+	}
+
+	wpas_dbus_register(obj_desc, priv->global, NULL,
+			   wpas_dbus_global_methods,
+			   wpas_dbus_global_properties,
+			   wpas_dbus_global_signals);
+
+	wpa_printf(MSG_DEBUG, "dbus: Register D-Bus object '%s'",
+		   WPAS_DBUS_NEW_PATH);
+	ret = wpa_dbus_ctrl_iface_init(priv, WPAS_DBUS_NEW_PATH,
+				       WPAS_DBUS_NEW_SERVICE,
+				       obj_desc);
+	if (ret < 0)
+		free_dbus_object_desc(obj_desc);
+	else
+		priv->dbus_new_initialized = 1;
+
+	return ret;
+}
+
+
+/**
+ * wpas_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface for
+ * wpa_supplicant
+ * @iface: Pointer to dbus private data from wpas_dbus_init()
+ *
+ * Deinitialize the dbus control interface that was initialized with
+ * wpas_dbus_ctrl_iface_init().
+ */
+void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *iface)
+{
+	if (!iface->dbus_new_initialized)
+		return;
+	wpa_printf(MSG_DEBUG, "dbus: Unregister D-Bus object '%s'",
+		   WPAS_DBUS_NEW_PATH);
+	dbus_connection_unregister_object_path(iface->con,
+					       WPAS_DBUS_NEW_PATH);
+}
+
+
+static void wpa_dbus_free(void *ptr)
+{
+	os_free(ptr);
+}
+
+
+static const struct wpa_dbus_property_desc wpas_dbus_network_properties[] = {
+	{ "Properties", WPAS_DBUS_NEW_IFACE_NETWORK, "a{sv}",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_network_properties,
+	  (WPADBusPropertyAccessor) wpas_dbus_setter_network_properties,
+	  RW
+	},
+	{ "Enabled", WPAS_DBUS_NEW_IFACE_NETWORK, "b",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_enabled,
+	  (WPADBusPropertyAccessor) wpas_dbus_setter_enabled,
+	  RW
+	},
+	{ NULL, NULL, NULL, NULL, NULL, 0 }
+};
+
+
+static const struct wpa_dbus_signal_desc wpas_dbus_network_signals[] = {
+	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_NETWORK,
+	  {
+		  { "properties", "a{sv}", ARG_OUT },
+		  END_ARGS
+	  }
+	},
+	{ NULL, NULL, { END_ARGS } }
+};
+
+
+/**
+ * wpas_dbus_register_network - Register a configured network with dbus
+ * @wpa_s: wpa_supplicant interface structure
+ * @ssid: network configuration data
+ * Returns: 0 on success, -1 on failure
+ *
+ * Registers network representing object with dbus
+ */
+int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
+			       struct wpa_ssid *ssid)
+{
+	struct wpas_dbus_priv *ctrl_iface;
+	struct wpa_dbus_object_desc *obj_desc;
+	struct network_handler_args *arg;
+	char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
+
+	/* Do nothing if the control interface is not turned on */
+	if (wpa_s == NULL || wpa_s->global == NULL)
+		return 0;
+	ctrl_iface = wpa_s->global->dbus;
+	if (ctrl_iface == NULL)
+		return 0;
+
+	os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
+		    wpa_s->dbus_new_path, ssid->id);
+
+	wpa_printf(MSG_DEBUG, "dbus: Register network object '%s'",
+		   net_obj_path);
+	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
+	if (!obj_desc) {
+		wpa_printf(MSG_ERROR, "Not enough memory "
+			   "to create object description");
+		goto err;
+	}
+
+	/* allocate memory for handlers arguments */
+	arg = os_zalloc(sizeof(struct network_handler_args));
+	if (!arg) {
+		wpa_printf(MSG_ERROR, "Not enough memory "
+			   "to create arguments for method");
+		goto err;
+	}
+
+	arg->wpa_s = wpa_s;
+	arg->ssid = ssid;
+
+	wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
+			   wpas_dbus_network_properties,
+			   wpas_dbus_network_signals);
+
+	if (wpa_dbus_register_object_per_iface(ctrl_iface, net_obj_path,
+					       wpa_s->ifname, obj_desc))
+		goto err;
+
+	wpas_dbus_signal_network_added(wpa_s, ssid->id);
+
+	return 0;
+
+err:
+	free_dbus_object_desc(obj_desc);
+	return -1;
+}
+
+
+/**
+ * wpas_dbus_unregister_network - Unregister a configured network from dbus
+ * @wpa_s: wpa_supplicant interface structure
+ * @nid: network id
+ * Returns: 0 on success, -1 on failure
+ *
+ * Unregisters network representing object from dbus
+ */
+int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid)
+{
+	struct wpas_dbus_priv *ctrl_iface;
+	char net_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
+	int ret;
+
+	/* Do nothing if the control interface is not turned on */
+	if (wpa_s == NULL || wpa_s->global == NULL ||
+	    wpa_s->dbus_new_path == NULL)
+		return 0;
+	ctrl_iface = wpa_s->global->dbus;
+	if (ctrl_iface == NULL)
+		return 0;
+
+	os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
+		    wpa_s->dbus_new_path, nid);
+
+	wpa_printf(MSG_DEBUG, "dbus: Unregister network object '%s'",
+		   net_obj_path);
+	ret = wpa_dbus_unregister_object_per_iface(ctrl_iface, net_obj_path);
+
+	if (!ret)
+		wpas_dbus_signal_network_removed(wpa_s, nid);
+
+	return ret;
+}
+
+
+static const struct wpa_dbus_property_desc wpas_dbus_bss_properties[] = {
+	{ "SSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_bss_ssid,
+	  NULL,
+	  R
+	},
+	{ "BSSID", WPAS_DBUS_NEW_IFACE_BSS, "ay",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_bss_bssid,
+	  NULL,
+	  R
+	},
+	{ "Privacy", WPAS_DBUS_NEW_IFACE_BSS, "b",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_bss_privacy,
+	  NULL,
+	  R
+	},
+	{ "Mode", WPAS_DBUS_NEW_IFACE_BSS, "s",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_bss_mode,
+	  NULL,
+	  R
+	},
+	{ "Signal", WPAS_DBUS_NEW_IFACE_BSS, "n",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_bss_signal,
+	  NULL,
+	  R
+	},
+	{ "Frequency", WPAS_DBUS_NEW_IFACE_BSS, "q",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_bss_frequency,
+	  NULL,
+	  R
+	},
+	{ "Rates", WPAS_DBUS_NEW_IFACE_BSS, "au",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_bss_rates,
+	  NULL,
+	  R
+	},
+	{ "WPA", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_bss_wpa,
+	  NULL,
+	  R
+	},
+	{ "RSN", WPAS_DBUS_NEW_IFACE_BSS, "a{sv}",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_bss_rsn,
+	  NULL,
+	  R
+	},
+	{ "IEs", WPAS_DBUS_NEW_IFACE_BSS, "ay",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_bss_ies,
+	  NULL,
+	  R
+	},
+	{ NULL, NULL, NULL, NULL, NULL, 0 }
+};
+
+
+static const struct wpa_dbus_signal_desc wpas_dbus_bss_signals[] = {
+	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_BSS,
+	  {
+		  { "properties", "a{sv}", ARG_OUT },
+		  END_ARGS
+	  }
+	},
+	{ NULL, NULL, { END_ARGS } }
+};
+
+
+/**
+ * wpas_dbus_unregister_bss - Unregister a scanned BSS from dbus
+ * @wpa_s: wpa_supplicant interface structure
+ * @bssid: scanned network bssid
+ * @id: unique BSS identifier
+ * Returns: 0 on success, -1 on failure
+ *
+ * Unregisters BSS representing object from dbus
+ */
+int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
+			     u8 bssid[ETH_ALEN], unsigned int id)
+{
+	struct wpas_dbus_priv *ctrl_iface;
+	char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
+
+	/* Do nothing if the control interface is not turned on */
+	if (wpa_s == NULL || wpa_s->global == NULL)
+		return 0;
+	ctrl_iface = wpa_s->global->dbus;
+	if (ctrl_iface == NULL)
+		return 0;
+
+	os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+		    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
+		    wpa_s->dbus_new_path, id);
+
+	wpa_printf(MSG_DEBUG, "dbus: Unregister BSS object '%s'",
+		   bss_obj_path);
+	if (wpa_dbus_unregister_object_per_iface(ctrl_iface, bss_obj_path)) {
+		wpa_printf(MSG_ERROR, "dbus: Cannot unregister BSS object %s",
+			   bss_obj_path);
+		return -1;
+	}
+
+	wpas_dbus_signal_bss_removed(wpa_s, bss_obj_path);
+	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
+
+	return 0;
+}
+
+
+/**
+ * wpas_dbus_register_bss - Register a scanned BSS with dbus
+ * @wpa_s: wpa_supplicant interface structure
+ * @bssid: scanned network bssid
+ * @id: unique BSS identifier
+ * Returns: 0 on success, -1 on failure
+ *
+ * Registers BSS representing object with dbus
+ */
+int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
+			   u8 bssid[ETH_ALEN], unsigned int id)
+{
+	struct wpas_dbus_priv *ctrl_iface;
+	struct wpa_dbus_object_desc *obj_desc;
+	char bss_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
+	struct bss_handler_args *arg;
+
+	/* Do nothing if the control interface is not turned on */
+	if (wpa_s == NULL || wpa_s->global == NULL)
+		return 0;
+	ctrl_iface = wpa_s->global->dbus;
+	if (ctrl_iface == NULL)
+		return 0;
+
+	os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+		    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
+		    wpa_s->dbus_new_path, id);
+
+	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
+	if (!obj_desc) {
+		wpa_printf(MSG_ERROR, "Not enough memory "
+			   "to create object description");
+		goto err;
+	}
+
+	arg = os_zalloc(sizeof(struct bss_handler_args));
+	if (!arg) {
+		wpa_printf(MSG_ERROR, "Not enough memory "
+			   "to create arguments for handler");
+		goto err;
+	}
+	arg->wpa_s = wpa_s;
+	arg->id = id;
+
+	wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
+			   wpas_dbus_bss_properties,
+			   wpas_dbus_bss_signals);
+
+	wpa_printf(MSG_DEBUG, "dbus: Register BSS object '%s'",
+		   bss_obj_path);
+	if (wpa_dbus_register_object_per_iface(ctrl_iface, bss_obj_path,
+					       wpa_s->ifname, obj_desc)) {
+		wpa_printf(MSG_ERROR,
+			   "Cannot register BSSID dbus object %s.",
+			   bss_obj_path);
+		goto err;
+	}
+
+	wpas_dbus_signal_bss_added(wpa_s, bss_obj_path);
+	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_BSSS);
+
+	return 0;
+
+err:
+	free_dbus_object_desc(obj_desc);
+	return -1;
+}
+
+
+static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
+	{ "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE,
+	  (WPADBusMethodHandler) &wpas_dbus_handler_scan,
+	  {
+		  { "args", "a{sv}", ARG_IN },
+		  END_ARGS
+	  }
+	},
+	{ "Disconnect", WPAS_DBUS_NEW_IFACE_INTERFACE,
+	  (WPADBusMethodHandler) &wpas_dbus_handler_disconnect,
+	  {
+		  END_ARGS
+	  }
+	},
+	{ "AddNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
+	  (WPADBusMethodHandler) &wpas_dbus_handler_add_network,
+	  {
+		  { "args", "a{sv}", ARG_IN },
+		  { "path", "o", ARG_OUT },
+		  END_ARGS
+	  }
+	},
+	{ "RemoveNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
+	  (WPADBusMethodHandler) &wpas_dbus_handler_remove_network,
+	  {
+		  { "path", "o", ARG_IN },
+		  END_ARGS
+	  }
+	},
+	{ "RemoveAllNetworks", WPAS_DBUS_NEW_IFACE_INTERFACE,
+	  (WPADBusMethodHandler) &wpas_dbus_handler_remove_all_networks,
+	  {
+		  END_ARGS
+	  }
+	},
+	{ "SelectNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE,
+	  (WPADBusMethodHandler) &wpas_dbus_handler_select_network,
+	  {
+		  { "path", "o", ARG_IN },
+		  END_ARGS
+	  }
+	},
+	{ "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
+	  (WPADBusMethodHandler) &wpas_dbus_handler_add_blob,
+	  {
+		  { "name", "s", ARG_IN },
+		  { "data", "ay", ARG_IN },
+		  END_ARGS
+	  }
+	},
+	{ "GetBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
+	  (WPADBusMethodHandler) &wpas_dbus_handler_get_blob,
+	  {
+		  { "name", "s", ARG_IN },
+		  { "data", "ay", ARG_OUT },
+		  END_ARGS
+	  }
+	},
+	{ "RemoveBlob", WPAS_DBUS_NEW_IFACE_INTERFACE,
+	  (WPADBusMethodHandler) &wpas_dbus_handler_remove_blob,
+	  {
+		  { "name", "s", ARG_IN },
+		  END_ARGS
+	  }
+	},
+#ifdef CONFIG_WPS
+	{ "Start", WPAS_DBUS_NEW_IFACE_WPS,
+	  (WPADBusMethodHandler) &wpas_dbus_handler_wps_start,
+	  {
+		  { "args", "a{sv}", ARG_IN },
+		  { "output", "a{sv}", ARG_OUT },
+		  END_ARGS
+	  }
+	},
+#endif /* CONFIG_WPS */
+	{ "FlushBSS", WPAS_DBUS_NEW_IFACE_INTERFACE,
+	  (WPADBusMethodHandler) &wpas_dbus_handler_flush_bss,
+	  {
+		  { "age", "u", ARG_IN },
+		  END_ARGS
+	  }
+	},
+	{ NULL, NULL, NULL, { END_ARGS } }
+};
+
+static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = {
+	{ "Capabilities", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{sv}",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_capabilities,
+	  NULL, R
+	},
+	{ "State", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_state,
+	  NULL, R
+	},
+	{ "Scanning", WPAS_DBUS_NEW_IFACE_INTERFACE, "b",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_scanning,
+	  NULL, R
+	},
+	{ "ApScan", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_ap_scan,
+	  (WPADBusPropertyAccessor) wpas_dbus_setter_ap_scan,
+	  RW
+	},
+	{ "BSSExpireAge", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_bss_expire_age,
+	  (WPADBusPropertyAccessor) wpas_dbus_setter_bss_expire_age,
+	  RW
+	},
+	{ "BSSExpireCount", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_bss_expire_count,
+	  (WPADBusPropertyAccessor) wpas_dbus_setter_bss_expire_count,
+	  RW
+	},
+	{ "Country", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_country,
+	  (WPADBusPropertyAccessor) wpas_dbus_setter_country,
+	  RW
+	},
+	{ "Ifname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_ifname,
+	  NULL, R
+	},
+	{ "Driver", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_driver,
+	  NULL, R
+	},
+	{ "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_bridge_ifname,
+	  NULL, R
+	},
+	{ "CurrentBSS", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_current_bss,
+	  NULL, R
+	},
+	{ "CurrentNetwork", WPAS_DBUS_NEW_IFACE_INTERFACE, "o",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_current_network,
+	  NULL, R
+	},
+	{ "CurrentAuthMode", WPAS_DBUS_NEW_IFACE_INTERFACE, "s",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_current_auth_mode,
+	  NULL, R
+	},
+	{ "Blobs", WPAS_DBUS_NEW_IFACE_INTERFACE, "a{say}",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_blobs,
+	  NULL, R
+	},
+	{ "BSSs", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_bsss,
+	  NULL, R
+	},
+	{ "Networks", WPAS_DBUS_NEW_IFACE_INTERFACE, "ao",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_networks,
+	  NULL, R
+	},
+#ifdef CONFIG_WPS
+	{ "ProcessCredentials", WPAS_DBUS_NEW_IFACE_WPS, "b",
+	  (WPADBusPropertyAccessor) wpas_dbus_getter_process_credentials,
+	  (WPADBusPropertyAccessor) wpas_dbus_setter_process_credentials,
+	  RW
+	},
+#endif /* CONFIG_WPS */
+	{ NULL, NULL, NULL, NULL, NULL, 0 }
+};
+
+static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
+	{ "ScanDone", WPAS_DBUS_NEW_IFACE_INTERFACE,
+	  {
+		  { "success", "b", ARG_OUT },
+		  END_ARGS
+	  }
+	},
+	{ "BSSAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
+	  {
+		  { "path", "o", ARG_OUT },
+		  { "properties", "a{sv}", ARG_OUT },
+		  END_ARGS
+	  }
+	},
+	{ "BSSRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
+	  {
+		  { "path", "o", ARG_OUT },
+		  END_ARGS
+	  }
+	},
+	{ "BlobAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
+	  {
+		  { "name", "s", ARG_OUT },
+		  END_ARGS
+	  }
+	},
+	{ "BlobRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
+	  {
+		  { "name", "s", ARG_OUT },
+		  END_ARGS
+	  }
+	},
+	{ "NetworkAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
+	  {
+		  { "path", "o", ARG_OUT },
+		  { "properties", "a{sv}", ARG_OUT },
+		  END_ARGS
+	  }
+	},
+	{ "NetworkRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
+	  {
+		  { "path", "o", ARG_OUT },
+		  END_ARGS
+	  }
+	},
+	{ "NetworkSelected", WPAS_DBUS_NEW_IFACE_INTERFACE,
+	  {
+		  { "path", "o", ARG_OUT },
+		  END_ARGS
+	  }
+	},
+	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_INTERFACE,
+	  {
+		  { "properties", "a{sv}", ARG_OUT },
+		  END_ARGS
+	  }
+	},
+#ifdef CONFIG_WPS
+	{ "Event", WPAS_DBUS_NEW_IFACE_WPS,
+	  {
+		  { "name", "s", ARG_OUT },
+		  { "args", "a{sv}", ARG_OUT },
+		  END_ARGS
+	  }
+	},
+	{ "Credentials", WPAS_DBUS_NEW_IFACE_WPS,
+	  {
+		  { "credentials", "a{sv}", ARG_OUT },
+		  END_ARGS
+	  }
+	},
+	{ "PropertiesChanged", WPAS_DBUS_NEW_IFACE_WPS,
+	  {
+		  { "properties", "a{sv}", ARG_OUT },
+		  END_ARGS
+	  }
+	},
+#endif /* CONFIG_WPS */
+	{ NULL, NULL, { END_ARGS } }
+};
+
+
+int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
+{
+
+	struct wpa_dbus_object_desc *obj_desc = NULL;
+	struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
+	int next;
+
+	/* Do nothing if the control interface is not turned on */
+	if (ctrl_iface == NULL)
+		return 0;
+
+	/* Create and set the interface's object path */
+	wpa_s->dbus_new_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
+	if (wpa_s->dbus_new_path == NULL)
+		return -1;
+	next = ctrl_iface->next_objid++;
+	os_snprintf(wpa_s->dbus_new_path, WPAS_DBUS_OBJECT_PATH_MAX,
+		    WPAS_DBUS_NEW_PATH_INTERFACES "/%u",
+		    next);
+
+	obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
+	if (!obj_desc) {
+		wpa_printf(MSG_ERROR, "Not enough memory "
+			   "to create object description");
+		goto err;
+	}
+
+	wpas_dbus_register(obj_desc, wpa_s, NULL, wpas_dbus_interface_methods,
+			   wpas_dbus_interface_properties,
+			   wpas_dbus_interface_signals);
+
+	wpa_printf(MSG_DEBUG, "dbus: Register interface object '%s'",
+		   wpa_s->dbus_new_path);
+	if (wpa_dbus_register_object_per_iface(ctrl_iface,
+					       wpa_s->dbus_new_path,
+					       wpa_s->ifname, obj_desc))
+		goto err;
+
+	wpas_dbus_signal_interface_added(wpa_s);
+
+	return 0;
+
+err:
+	os_free(wpa_s->dbus_new_path);
+	wpa_s->dbus_new_path = NULL;
+	free_dbus_object_desc(obj_desc);
+	return -1;
+}
+
+
+int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
+{
+	struct wpas_dbus_priv *ctrl_iface;
+
+	/* Do nothing if the control interface is not turned on */
+	if (wpa_s == NULL || wpa_s->global == NULL)
+		return 0;
+	ctrl_iface = wpa_s->global->dbus;
+	if (ctrl_iface == NULL)
+		return 0;
+
+	wpa_printf(MSG_DEBUG, "dbus: Unregister interface object '%s'",
+		   wpa_s->dbus_new_path);
+	if (wpa_dbus_unregister_object_per_iface(ctrl_iface,
+						 wpa_s->dbus_new_path))
+		return -1;
+
+	wpas_dbus_signal_interface_removed(wpa_s);
+
+	os_free(wpa_s->dbus_new_path);
+	wpa_s->dbus_new_path = NULL;
+
+	return 0;
+}
diff --git a/wpa_supplicant/dbus/dbus_new.h b/wpa_supplicant/dbus/dbus_new.h
new file mode 100644
index 0000000..377e381
--- /dev/null
+++ b/wpa_supplicant/dbus/dbus_new.h
@@ -0,0 +1,236 @@
+/*
+ * WPA Supplicant / dbus-based control interface
+ * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
+ * Copyright (c) 2009-2010, 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.
+ */
+
+#ifndef CTRL_IFACE_DBUS_NEW_H
+#define CTRL_IFACE_DBUS_NEW_H
+
+struct wpa_global;
+struct wpa_supplicant;
+struct wpa_ssid;
+struct wps_event_m2d;
+struct wps_event_fail;
+struct wps_credential;
+enum wpa_states;
+
+enum wpas_dbus_prop {
+	WPAS_DBUS_PROP_AP_SCAN,
+	WPAS_DBUS_PROP_SCANNING,
+	WPAS_DBUS_PROP_STATE,
+	WPAS_DBUS_PROP_CURRENT_BSS,
+	WPAS_DBUS_PROP_CURRENT_NETWORK,
+	WPAS_DBUS_PROP_CURRENT_AUTH_MODE,
+	WPAS_DBUS_PROP_BSSS,
+};
+
+enum wpas_dbus_bss_prop {
+	WPAS_DBUS_BSS_PROP_SIGNAL,
+	WPAS_DBUS_BSS_PROP_FREQ,
+	WPAS_DBUS_BSS_PROP_MODE,
+	WPAS_DBUS_BSS_PROP_PRIVACY,
+	WPAS_DBUS_BSS_PROP_RATES,
+	WPAS_DBUS_BSS_PROP_WPA,
+	WPAS_DBUS_BSS_PROP_RSN,
+	WPAS_DBUS_BSS_PROP_IES,
+};
+
+#define WPAS_DBUS_OBJECT_PATH_MAX 150
+
+#define WPAS_DBUS_NEW_SERVICE		"fi.w1.wpa_supplicant1"
+#define WPAS_DBUS_NEW_PATH		"/fi/w1/wpa_supplicant1"
+#define WPAS_DBUS_NEW_INTERFACE		"fi.w1.wpa_supplicant1"
+
+#define WPAS_DBUS_NEW_PATH_INTERFACES	WPAS_DBUS_NEW_PATH "/Interfaces"
+#define WPAS_DBUS_NEW_IFACE_INTERFACE	WPAS_DBUS_NEW_INTERFACE ".Interface"
+#define WPAS_DBUS_NEW_IFACE_WPS WPAS_DBUS_NEW_IFACE_INTERFACE ".WPS"
+
+#define WPAS_DBUS_NEW_NETWORKS_PART "Networks"
+#define WPAS_DBUS_NEW_IFACE_NETWORK WPAS_DBUS_NEW_INTERFACE ".Network"
+
+#define WPAS_DBUS_NEW_BSSIDS_PART "BSSs"
+#define WPAS_DBUS_NEW_IFACE_BSS	WPAS_DBUS_NEW_INTERFACE ".BSS"
+
+
+/* Errors */
+#define WPAS_DBUS_ERROR_UNKNOWN_ERROR \
+	WPAS_DBUS_NEW_INTERFACE ".UnknownError"
+#define WPAS_DBUS_ERROR_INVALID_ARGS \
+	WPAS_DBUS_NEW_INTERFACE ".InvalidArgs"
+
+#define WPAS_DBUS_ERROR_IFACE_EXISTS \
+	WPAS_DBUS_NEW_INTERFACE ".InterfaceExists"
+#define WPAS_DBUS_ERROR_IFACE_UNKNOWN \
+	WPAS_DBUS_NEW_INTERFACE ".InterfaceUnknown"
+
+#define WPAS_DBUS_ERROR_NOT_CONNECTED \
+	WPAS_DBUS_NEW_INTERFACE ".NotConnected"
+#define WPAS_DBUS_ERROR_NETWORK_UNKNOWN \
+	WPAS_DBUS_NEW_INTERFACE ".NetworkUnknown"
+
+#define WPAS_DBUS_ERROR_BLOB_EXISTS \
+	WPAS_DBUS_NEW_INTERFACE ".BlobExists"
+#define WPAS_DBUS_ERROR_BLOB_UNKNOWN \
+	WPAS_DBUS_NEW_INTERFACE ".BlobUnknown"
+
+
+#ifdef CONFIG_CTRL_IFACE_DBUS_NEW
+
+int wpas_dbus_ctrl_iface_init(struct wpas_dbus_priv *priv);
+void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *iface);
+
+int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s);
+int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s);
+void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
+				   enum wpas_dbus_prop property);
+void wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant *wpa_s,
+				       enum wpas_dbus_bss_prop property,
+				       unsigned int id);
+void wpas_dbus_signal_network_enabled_changed(struct wpa_supplicant *wpa_s,
+					      struct wpa_ssid *ssid);
+void wpas_dbus_signal_network_selected(struct wpa_supplicant *wpa_s, int id);
+void wpas_dbus_signal_scan_done(struct wpa_supplicant *wpa_s, int success);
+void wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s,
+			       const struct wps_credential *cred);
+void wpas_dbus_signal_wps_event_m2d(struct wpa_supplicant *wpa_s,
+				    struct wps_event_m2d *m2d);
+void wpas_dbus_signal_wps_event_fail(struct wpa_supplicant *wpa_s,
+				     struct wps_event_fail *fail);
+void wpas_dbus_signal_wps_event_success(struct wpa_supplicant *wpa_s);
+int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
+			       struct wpa_ssid *ssid);
+int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s, int nid);
+int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
+			     u8 bssid[ETH_ALEN], unsigned int id);
+int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
+			   u8 bssid[ETH_ALEN], unsigned int id);
+void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s,
+				 const char *name);
+void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s,
+				   const char *name);
+void wpas_dbus_signal_debug_level_changed(struct wpa_global *global);
+void wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global);
+void wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global);
+
+#else /* CONFIG_CTRL_IFACE_DBUS_NEW */
+
+static inline int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s)
+{
+	return 0;
+}
+
+static inline int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
+{
+	return 0;
+}
+
+#define wpas_dbus_signal_state_changed(w, n, o) do { } while (0)
+
+static inline void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
+						 enum wpas_dbus_prop property)
+{
+}
+
+static inline void wpas_dbus_bss_signal_prop_changed(
+	struct wpa_supplicant *wpa_s, enum wpas_dbus_bss_prop property,
+	unsigned int id)
+{
+}
+
+static inline void wpas_dbus_signal_network_enabled_changed(
+	struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
+{
+}
+
+static inline void wpas_dbus_signal_network_selected(
+	struct wpa_supplicant *wpa_s, int id)
+{
+}
+
+static inline void wpas_dbus_signal_scan_done(struct wpa_supplicant *wpa_s,
+					      int success)
+{
+}
+
+static inline void wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s,
+					     const struct wps_credential *cred)
+{
+}
+
+static inline void wpas_dbus_signal_wps_event_m2d(struct wpa_supplicant *wpa_s,
+						  struct wps_event_m2d *m2d)
+{
+}
+
+static inline void wpas_dbus_signal_wps_event_fail(
+	struct wpa_supplicant *wpa_s, struct wps_event_fail *fail)
+{
+}
+
+static inline void wpas_dbus_signal_wps_event_success(
+	struct wpa_supplicant *wpa_s)
+{
+}
+
+static inline int wpas_dbus_register_network(struct wpa_supplicant *wpa_s,
+					     struct wpa_ssid *ssid)
+{
+	return 0;
+}
+
+static inline int wpas_dbus_unregister_network(struct wpa_supplicant *wpa_s,
+					       int nid)
+{
+	return 0;
+}
+
+static inline int wpas_dbus_unregister_bss(struct wpa_supplicant *wpa_s,
+					   u8 bssid[ETH_ALEN], unsigned int id)
+{
+	return 0;
+}
+
+static inline int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
+					 u8 bssid[ETH_ALEN], unsigned int id)
+{
+	return 0;
+}
+
+static inline void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s,
+					       const char *name)
+{
+}
+
+static inline void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s,
+						 const char *name)
+{
+}
+
+static inline void wpas_dbus_signal_debug_level_changed(
+	struct wpa_global *global)
+{
+}
+
+static inline void wpas_dbus_signal_debug_timestamp_changed(
+	struct wpa_global *global)
+{
+}
+
+static inline void wpas_dbus_signal_debug_show_keys_changed(
+	struct wpa_global *global)
+{
+}
+
+#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
+
+#endif /* CTRL_IFACE_DBUS_H_NEW */
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c
new file mode 100644
index 0000000..68e5465
--- /dev/null
+++ b/wpa_supplicant/dbus/dbus_new_handlers.c
@@ -0,0 +1,3228 @@
+/*
+ * WPA Supplicant / dbus-based control interface
+ * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
+ * Copyright (c) 2009-2010, Witold Sowa <witold.sowa@gmail.com>
+ * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
+ *
+ * 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 "includes.h"
+
+#include "common.h"
+#include "common/ieee802_11_defs.h"
+#include "eap_peer/eap_methods.h"
+#include "eapol_supp/eapol_supp_sm.h"
+#include "rsn_supp/wpa.h"
+#include "../config.h"
+#include "../wpa_supplicant_i.h"
+#include "../driver_i.h"
+#include "../notify.h"
+#include "../wpas_glue.h"
+#include "../bss.h"
+#include "../scan.h"
+#include "dbus_new_helpers.h"
+#include "dbus_new.h"
+#include "dbus_new_handlers.h"
+#include "dbus_dict_helpers.h"
+
+extern int wpa_debug_level;
+extern int wpa_debug_show_keys;
+extern int wpa_debug_timestamp;
+
+static const char *debug_strings[] = {
+	"excessive", "msgdump", "debug", "info", "warning", "error", NULL
+};
+
+
+/**
+ * wpas_dbus_new_decompose_object_path - Decompose an interface object path into parts
+ * @path: The dbus object path
+ * @network: (out) the configured network this object path refers to, if any
+ * @bssid: (out) the scanned bssid this object path refers to, if any
+ * Returns: The object path of the network interface this path refers to
+ *
+ * For a given object path, decomposes the object path into object id, network,
+ * and BSSID parts, if those parts exist.
+ */
+static char * wpas_dbus_new_decompose_object_path(const char *path,
+						  char **network,
+						  char **bssid)
+{
+	const unsigned int dev_path_prefix_len =
+		strlen(WPAS_DBUS_NEW_PATH_INTERFACES "/");
+	char *obj_path_only;
+	char *next_sep;
+
+	/* Be a bit paranoid about path */
+	if (!path || os_strncmp(path, WPAS_DBUS_NEW_PATH_INTERFACES "/",
+				dev_path_prefix_len))
+		return NULL;
+
+	/* Ensure there's something at the end of the path */
+	if ((path + dev_path_prefix_len)[0] == '\0')
+		return NULL;
+
+	obj_path_only = os_strdup(path);
+	if (obj_path_only == NULL)
+		return NULL;
+
+	next_sep = os_strchr(obj_path_only + dev_path_prefix_len, '/');
+	if (next_sep != NULL) {
+		const char *net_part = os_strstr(
+			next_sep, WPAS_DBUS_NEW_NETWORKS_PART "/");
+		const char *bssid_part = os_strstr(
+			next_sep, WPAS_DBUS_NEW_BSSIDS_PART "/");
+
+		if (network && net_part) {
+			/* Deal with a request for a configured network */
+			const char *net_name = net_part +
+				os_strlen(WPAS_DBUS_NEW_NETWORKS_PART "/");
+			*network = NULL;
+			if (os_strlen(net_name))
+				*network = os_strdup(net_name);
+		} else if (bssid && bssid_part) {
+			/* Deal with a request for a scanned BSSID */
+			const char *bssid_name = bssid_part +
+				os_strlen(WPAS_DBUS_NEW_BSSIDS_PART "/");
+			if (strlen(bssid_name))
+				*bssid = os_strdup(bssid_name);
+			else
+				*bssid = NULL;
+		}
+
+		/* Cut off interface object path before "/" */
+		*next_sep = '\0';
+	}
+
+	return obj_path_only;
+}
+
+
+/**
+ * wpas_dbus_error_unknown_error - Return a new InvalidArgs error message
+ * @message: Pointer to incoming dbus message this error refers to
+ * @arg: Optional string appended to error message
+ * Returns: a dbus error message
+ *
+ * Convenience function to create and return an UnknownError
+ */
+DBusMessage * wpas_dbus_error_unknown_error(DBusMessage *message,
+					    const char *arg)
+{
+	/*
+	 * This function can be called as a result of a failure
+	 * within internal getter calls, which will call this function
+	 * with a NULL message parameter.  However, dbus_message_new_error
+	 * looks very unkindly (i.e, abort()) on a NULL message, so
+	 * in this case, we should not call it.
+	 */
+	if (message == NULL) {
+		wpa_printf(MSG_INFO, "dbus: wpas_dbus_error_unknown_error "
+			   "called with NULL message (arg=%s)",
+			   arg ? arg : "N/A");
+		return NULL;
+	}
+
+	return dbus_message_new_error(message, WPAS_DBUS_ERROR_UNKNOWN_ERROR,
+				      arg);
+}
+
+
+/**
+ * wpas_dbus_error_iface_unknown - Return a new invalid interface error message
+ * @message: Pointer to incoming dbus message this error refers to
+ * Returns: A dbus error message
+ *
+ * Convenience function to create and return an invalid interface error
+ */
+static DBusMessage * wpas_dbus_error_iface_unknown(DBusMessage *message)
+{
+	return dbus_message_new_error(message, WPAS_DBUS_ERROR_IFACE_UNKNOWN,
+				      "wpa_supplicant knows nothing about "
+				      "this interface.");
+}
+
+
+/**
+ * wpas_dbus_error_network_unknown - Return a new NetworkUnknown error message
+ * @message: Pointer to incoming dbus message this error refers to
+ * Returns: a dbus error message
+ *
+ * Convenience function to create and return an invalid network error
+ */
+static DBusMessage * wpas_dbus_error_network_unknown(DBusMessage *message)
+{
+	return dbus_message_new_error(message, WPAS_DBUS_ERROR_NETWORK_UNKNOWN,
+				      "There is no such a network in this "
+				      "interface.");
+}
+
+
+/**
+ * wpas_dbus_error_invalid_args - Return a new InvalidArgs error message
+ * @message: Pointer to incoming dbus message this error refers to
+ * Returns: a dbus error message
+ *
+ * Convenience function to create and return an invalid options error
+ */
+DBusMessage * wpas_dbus_error_invalid_args(DBusMessage *message,
+					  const char *arg)
+{
+	DBusMessage *reply;
+
+	reply = dbus_message_new_error(message, WPAS_DBUS_ERROR_INVALID_ARGS,
+				       "Did not receive correct message "
+				       "arguments.");
+	if (arg != NULL)
+		dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg,
+					 DBUS_TYPE_INVALID);
+
+	return reply;
+}
+
+
+static const char *dont_quote[] = {
+	"key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
+	"opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path",
+	"bssid", NULL
+};
+
+static dbus_bool_t should_quote_opt(const char *key)
+{
+	int i = 0;
+	while (dont_quote[i] != NULL) {
+		if (os_strcmp(key, dont_quote[i]) == 0)
+			return FALSE;
+		i++;
+	}
+	return TRUE;
+}
+
+/**
+ * get_iface_by_dbus_path - Get a new network interface
+ * @global: Pointer to global data from wpa_supplicant_init()
+ * @path: Pointer to a dbus object path representing an interface
+ * Returns: Pointer to the interface or %NULL if not found
+ */
+static struct wpa_supplicant * get_iface_by_dbus_path(
+	struct wpa_global *global, const char *path)
+{
+	struct wpa_supplicant *wpa_s;
+
+	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
+		if (os_strcmp(wpa_s->dbus_new_path, path) == 0)
+			return wpa_s;
+	}
+	return NULL;
+}
+
+
+/**
+ * set_network_properties - Set properties of a configured network
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * @ssid: wpa_ssid structure for a configured network
+ * @iter: DBus message iterator containing dictionary of network
+ * properties to set.
+ * Returns: NULL when succeed or DBus error on failure
+ *
+ * Sets network configuration with parameters given id DBus dictionary
+ */
+static DBusMessage * set_network_properties(DBusMessage *message,
+					    struct wpa_supplicant *wpa_s,
+					    struct wpa_ssid *ssid,
+					    DBusMessageIter *iter)
+{
+
+	struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
+	DBusMessage *reply = NULL;
+	DBusMessageIter	iter_dict;
+
+	if (!wpa_dbus_dict_open_read(iter, &iter_dict))
+		return wpas_dbus_error_invalid_args(message, NULL);
+
+	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
+		char *value = NULL;
+		size_t size = 50;
+		int ret;
+		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
+			reply = wpas_dbus_error_invalid_args(message, NULL);
+			break;
+		}
+		if (entry.type == DBUS_TYPE_ARRAY &&
+		    entry.array_type == DBUS_TYPE_BYTE) {
+			if (entry.array_len <= 0)
+				goto error;
+
+			size = entry.array_len * 2 + 1;
+			value = os_zalloc(size);
+			if (value == NULL)
+				goto error;
+
+			ret = wpa_snprintf_hex(value, size,
+					       (u8 *) entry.bytearray_value,
+					       entry.array_len);
+			if (ret <= 0)
+				goto error;
+		} else if (entry.type == DBUS_TYPE_STRING) {
+			if (should_quote_opt(entry.key)) {
+				size = os_strlen(entry.str_value);
+				if (size <= 0)
+					goto error;
+
+				size += 3;
+				value = os_zalloc(size);
+				if (value == NULL)
+					goto error;
+
+				ret = os_snprintf(value, size, "\"%s\"",
+						  entry.str_value);
+				if (ret < 0 || (size_t) ret != (size - 1))
+					goto error;
+			} else {
+				value = os_strdup(entry.str_value);
+				if (value == NULL)
+					goto error;
+			}
+		} else if (entry.type == DBUS_TYPE_UINT32) {
+			value = os_zalloc(size);
+			if (value == NULL)
+				goto error;
+
+			ret = os_snprintf(value, size, "%u",
+					  entry.uint32_value);
+			if (ret <= 0)
+				goto error;
+		} else if (entry.type == DBUS_TYPE_INT32) {
+			value = os_zalloc(size);
+			if (value == NULL)
+				goto error;
+
+			ret = os_snprintf(value, size, "%d",
+					  entry.int32_value);
+			if (ret <= 0)
+				goto error;
+		} else
+			goto error;
+
+		if (wpa_config_set(ssid, entry.key, value, 0) < 0)
+			goto error;
+
+		if ((os_strcmp(entry.key, "psk") == 0 &&
+		     value[0] == '"' && ssid->ssid_len) ||
+		    (strcmp(entry.key, "ssid") == 0 && ssid->passphrase))
+			wpa_config_update_psk(ssid);
+		else if (os_strcmp(entry.key, "priority") == 0)
+			wpa_config_update_prio_list(wpa_s->conf);
+
+		os_free(value);
+		wpa_dbus_dict_entry_clear(&entry);
+		continue;
+
+	error:
+		os_free(value);
+		reply = wpas_dbus_error_invalid_args(message, entry.key);
+		wpa_dbus_dict_entry_clear(&entry);
+		break;
+	}
+
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_simple_property_getter - Get basic type property
+ * @message: Pointer to incoming dbus message
+ * @type: DBus type of property (must be basic type)
+ * @val: pointer to place holding property value
+ * Returns: The DBus message containing response for Properties.Get call
+ * or DBus error message if error occurred.
+ *
+ * Generic getter for basic type properties. Type is required to be basic.
+ */
+DBusMessage * wpas_dbus_simple_property_getter(DBusMessage *message,
+					       const int type, const void *val)
+{
+	DBusMessage *reply = NULL;
+	DBusMessageIter iter, variant_iter;
+
+	if (!dbus_type_is_basic(type)) {
+		wpa_printf(MSG_ERROR, "dbus: wpas_dbus_simple_property_getter:"
+			   " given type is not basic");
+		return wpas_dbus_error_unknown_error(message, NULL);
+	}
+
+	if (message == NULL)
+		reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
+	else
+		reply = dbus_message_new_method_return(message);
+
+	if (reply != NULL) {
+		dbus_message_iter_init_append(reply, &iter);
+		if (!dbus_message_iter_open_container(
+			    &iter, DBUS_TYPE_VARIANT,
+			    wpa_dbus_type_as_string(type), &variant_iter) ||
+		    !dbus_message_iter_append_basic(&variant_iter, type,
+						    val) ||
+		    !dbus_message_iter_close_container(&iter, &variant_iter)) {
+			wpa_printf(MSG_ERROR, "dbus: "
+				   "wpas_dbus_simple_property_getter: out of "
+				   "memory to put property value into "
+				   "message");
+			dbus_message_unref(reply);
+			reply = dbus_message_new_error(message,
+						       DBUS_ERROR_NO_MEMORY,
+						       NULL);
+		}
+	} else {
+		wpa_printf(MSG_ERROR, "dbus: wpas_dbus_simple_property_getter:"
+			   " out of memory to return property value");
+		reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					       NULL);
+	}
+
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_simple_property_setter - Set basic type property
+ * @message: Pointer to incoming dbus message
+ * @type: DBus type of property (must be basic type)
+ * @val: pointer to place where value being set will be stored
+ * Returns: NULL or DBus error message if error occurred.
+ *
+ * Generic setter for basic type properties. Type is required to be basic.
+ */
+DBusMessage * wpas_dbus_simple_property_setter(DBusMessage *message,
+					       const int type, void *val)
+{
+	DBusMessageIter iter, variant_iter;
+
+	if (!dbus_type_is_basic(type)) {
+		wpa_printf(MSG_ERROR, "dbus: wpas_dbus_simple_property_setter:"
+			   " given type is not basic");
+		return wpas_dbus_error_unknown_error(message, NULL);
+	}
+
+	if (!dbus_message_iter_init(message, &iter)) {
+		wpa_printf(MSG_ERROR, "dbus: wpas_dbus_simple_property_setter:"
+			   " out of memory to return scanning state");
+		return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					      NULL);
+	}
+
+	/* omit first and second argument and get value from third */
+	dbus_message_iter_next(&iter);
+	dbus_message_iter_next(&iter);
+	dbus_message_iter_recurse(&iter, &variant_iter);
+
+	if (dbus_message_iter_get_arg_type(&variant_iter) != type) {
+		wpa_printf(MSG_DEBUG, "dbus: wpas_dbus_simple_property_setter:"
+			   " wrong property type");
+		return wpas_dbus_error_invalid_args(message,
+						    "wrong property type");
+	}
+	dbus_message_iter_get_basic(&variant_iter, val);
+
+	return NULL;
+}
+
+
+/**
+ * wpas_dbus_simple_array_property_getter - Get array type property
+ * @message: Pointer to incoming dbus message
+ * @type: DBus type of property array elements (must be basic type)
+ * @array: pointer to array of elements to put into response message
+ * @array_len: length of above array
+ * Returns: The DBus message containing response for Properties.Get call
+ * or DBus error message if error occurred.
+ *
+ * Generic getter for array type properties. Array elements type is
+ * required to be basic.
+ */
+DBusMessage * wpas_dbus_simple_array_property_getter(DBusMessage *message,
+						     const int type,
+						     const void *array,
+						     size_t array_len)
+{
+	DBusMessage *reply = NULL;
+	DBusMessageIter iter, variant_iter, array_iter;
+	char type_str[] = "a?"; /* ? will be replaced with subtype letter; */
+	const char *sub_type_str;
+	size_t element_size, i;
+
+	if (!dbus_type_is_basic(type)) {
+		wpa_printf(MSG_ERROR, "dbus: "
+			   "wpas_dbus_simple_array_property_getter: given "
+			   "type is not basic");
+		return wpas_dbus_error_unknown_error(message, NULL);
+	}
+
+	sub_type_str = wpa_dbus_type_as_string(type);
+	type_str[1] = sub_type_str[0];
+
+	if (message == NULL)
+		reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
+	else
+		reply = dbus_message_new_method_return(message);
+	if (reply == NULL) {
+		wpa_printf(MSG_ERROR, "dbus: "
+			   "wpas_dbus_simple_array_property_getter: out of "
+			   "memory to create return message");
+		return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					      NULL);
+	}
+
+	dbus_message_iter_init_append(reply, &iter);
+
+	if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
+					      type_str, &variant_iter) ||
+	    !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
+					      sub_type_str, &array_iter)) {
+		wpa_printf(MSG_ERROR, "dbus: "
+			   "wpas_dbus_simple_array_property_getter: out of "
+			   "memory to open container");
+		dbus_message_unref(reply);
+		return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					      NULL);
+	}
+
+	switch(type) {
+	case DBUS_TYPE_BYTE:
+	case DBUS_TYPE_BOOLEAN:
+		element_size = 1;
+		break;
+	case DBUS_TYPE_INT16:
+	case DBUS_TYPE_UINT16:
+		element_size = sizeof(uint16_t);
+		break;
+	case DBUS_TYPE_INT32:
+	case DBUS_TYPE_UINT32:
+		element_size = sizeof(uint32_t);
+		break;
+	case DBUS_TYPE_INT64:
+	case DBUS_TYPE_UINT64:
+		element_size = sizeof(uint64_t);
+		break;
+	case DBUS_TYPE_DOUBLE:
+		element_size = sizeof(double);
+		break;
+	case DBUS_TYPE_STRING:
+	case DBUS_TYPE_OBJECT_PATH:
+		element_size = sizeof(char *);
+		break;
+	default:
+		wpa_printf(MSG_ERROR, "dbus: "
+			   "wpas_dbus_simple_array_property_getter: "
+			   "fatal: unknown element type");
+		element_size = 1;
+		break;
+	}
+
+	for (i = 0; i < array_len; i++) {
+		dbus_message_iter_append_basic(&array_iter, type,
+					       array + i * element_size);
+	}
+
+	if (!dbus_message_iter_close_container(&variant_iter, &array_iter) ||
+	    !dbus_message_iter_close_container(&iter, &variant_iter)) {
+		wpa_printf(MSG_ERROR, "dbus: "
+			   "wpas_dbus_simple_array_property_getter: out of "
+			   "memory to close container");
+		dbus_message_unref(reply);
+		return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					      NULL);
+	}
+
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_handler_create_interface - Request registration of a network iface
+ * @message: Pointer to incoming dbus message
+ * @global: %wpa_supplicant global data structure
+ * Returns: The object path of the new interface object,
+ *          or a dbus error message with more information
+ *
+ * Handler function for "CreateInterface" method call. Handles requests
+ * by dbus clients to register a network interface that wpa_supplicant
+ * will manage.
+ */
+DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message,
+						 struct wpa_global *global)
+{
+	DBusMessageIter iter_dict;
+	DBusMessage *reply = NULL;
+	DBusMessageIter iter;
+	struct wpa_dbus_dict_entry entry;
+	char *driver = NULL;
+	char *ifname = NULL;
+	char *confname = NULL;
+	char *bridge_ifname = NULL;
+
+	dbus_message_iter_init(message, &iter);
+
+	if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
+		goto error;
+	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
+		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
+			goto error;
+		if (!strcmp(entry.key, "Driver") &&
+		    (entry.type == DBUS_TYPE_STRING)) {
+			driver = os_strdup(entry.str_value);
+			wpa_dbus_dict_entry_clear(&entry);
+			if (driver == NULL)
+				goto error;
+		} else if (!strcmp(entry.key, "Ifname") &&
+			   (entry.type == DBUS_TYPE_STRING)) {
+			ifname = os_strdup(entry.str_value);
+			wpa_dbus_dict_entry_clear(&entry);
+			if (ifname == NULL)
+				goto error;
+		} else if (!strcmp(entry.key, "ConfigFile") &&
+			   (entry.type == DBUS_TYPE_STRING)) {
+			confname = os_strdup(entry.str_value);
+			wpa_dbus_dict_entry_clear(&entry);
+			if (confname == NULL)
+				goto error;
+		} else if (!strcmp(entry.key, "BridgeIfname") &&
+			   (entry.type == DBUS_TYPE_STRING)) {
+			bridge_ifname = os_strdup(entry.str_value);
+			wpa_dbus_dict_entry_clear(&entry);
+			if (bridge_ifname == NULL)
+				goto error;
+		} else {
+			wpa_dbus_dict_entry_clear(&entry);
+			goto error;
+		}
+	}
+
+	if (ifname == NULL)
+		goto error; /* Required Ifname argument missing */
+
+	/*
+	 * Try to get the wpa_supplicant record for this iface, return
+	 * an error if we already control it.
+	 */
+	if (wpa_supplicant_get_iface(global, ifname) != NULL) {
+		reply = dbus_message_new_error(message,
+					       WPAS_DBUS_ERROR_IFACE_EXISTS,
+					       "wpa_supplicant already "
+					       "controls this interface.");
+	} else {
+		struct wpa_supplicant *wpa_s;
+		struct wpa_interface iface;
+		os_memset(&iface, 0, sizeof(iface));
+		iface.driver = driver;
+		iface.ifname = ifname;
+		iface.confname = confname;
+		iface.bridge_ifname = bridge_ifname;
+		/* Otherwise, have wpa_supplicant attach to it. */
+		if ((wpa_s = wpa_supplicant_add_iface(global, &iface))) {
+			const char *path = wpa_s->dbus_new_path;
+			reply = dbus_message_new_method_return(message);
+			dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
+			                         &path, DBUS_TYPE_INVALID);
+		} else {
+			reply = wpas_dbus_error_unknown_error(
+				message, "wpa_supplicant couldn't grab this "
+				"interface.");
+		}
+	}
+
+out:
+	os_free(driver);
+	os_free(ifname);
+	os_free(bridge_ifname);
+	return reply;
+
+error:
+	reply = wpas_dbus_error_invalid_args(message, NULL);
+	goto out;
+}
+
+
+/**
+ * wpas_dbus_handler_remove_interface - Request deregistration of an interface
+ * @message: Pointer to incoming dbus message
+ * @global: wpa_supplicant global data structure
+ * Returns: a dbus message containing a UINT32 indicating success (1) or
+ *          failure (0), or returns a dbus error message with more information
+ *
+ * Handler function for "removeInterface" method call.  Handles requests
+ * by dbus clients to deregister a network interface that wpa_supplicant
+ * currently manages.
+ */
+DBusMessage * wpas_dbus_handler_remove_interface(DBusMessage *message,
+						 struct wpa_global *global)
+{
+	struct wpa_supplicant *wpa_s;
+	char *path;
+	DBusMessage *reply = NULL;
+
+	dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+			      DBUS_TYPE_INVALID);
+
+	wpa_s = get_iface_by_dbus_path(global, path);
+	if (wpa_s == NULL)
+		reply = wpas_dbus_error_iface_unknown(message);
+	else if (wpa_supplicant_remove_iface(global, wpa_s)) {
+		reply = wpas_dbus_error_unknown_error(
+			message, "wpa_supplicant couldn't remove this "
+			"interface.");
+	}
+
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_handler_get_interface - Get the object path for an interface name
+ * @message: Pointer to incoming dbus message
+ * @global: %wpa_supplicant global data structure
+ * Returns: The object path of the interface object,
+ *          or a dbus error message with more information
+ *
+ * Handler function for "getInterface" method call.
+ */
+DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message,
+					      struct wpa_global *global)
+{
+	DBusMessage *reply = NULL;
+	const char *ifname;
+	const char *path;
+	struct wpa_supplicant *wpa_s;
+
+	dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &ifname,
+			      DBUS_TYPE_INVALID);
+
+	wpa_s = wpa_supplicant_get_iface(global, ifname);
+	if (wpa_s == NULL)
+		return wpas_dbus_error_iface_unknown(message);
+
+	path = wpa_s->dbus_new_path;
+	reply = dbus_message_new_method_return(message);
+	if (reply == NULL)
+		return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					      NULL);
+	if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
+				      DBUS_TYPE_INVALID)) {
+		dbus_message_unref(reply);
+		return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					      NULL);
+	}
+
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_getter_debug_level - Get debug level
+ * @message: Pointer to incoming dbus message
+ * @global: %wpa_supplicant global data structure
+ * Returns: DBus message with value of debug level
+ *
+ * Getter for "DebugLevel" property.
+ */
+DBusMessage * wpas_dbus_getter_debug_level(DBusMessage *message,
+					   struct wpa_global *global)
+{
+	const char *str;
+	int idx = wpa_debug_level;
+	if (idx < 0)
+		idx = 0;
+	if (idx > 5)
+		idx = 5;
+	str = debug_strings[idx];
+	return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
+						&str);
+}
+
+
+/**
+ * wpas_dbus_getter_debug_timestamp - Get debug timestamp
+ * @message: Pointer to incoming dbus message
+ * @global: %wpa_supplicant global data structure
+ * Returns: DBus message with value of debug timestamp
+ *
+ * Getter for "DebugTimestamp" property.
+ */
+DBusMessage * wpas_dbus_getter_debug_timestamp(DBusMessage *message,
+					       struct wpa_global *global)
+{
+	return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN,
+						&wpa_debug_timestamp);
+
+}
+
+
+/**
+ * wpas_dbus_getter_debug_show_keys - Get debug show keys
+ * @message: Pointer to incoming dbus message
+ * @global: %wpa_supplicant global data structure
+ * Returns: DBus message with value of debug show_keys
+ *
+ * Getter for "DebugShowKeys" property.
+ */
+DBusMessage * wpas_dbus_getter_debug_show_keys(DBusMessage *message,
+					       struct wpa_global *global)
+{
+	return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN,
+						&wpa_debug_show_keys);
+
+}
+
+/**
+ * wpas_dbus_setter_debug_level - Set debug level
+ * @message: Pointer to incoming dbus message
+ * @global: %wpa_supplicant global data structure
+ * Returns: %NULL or DBus error message
+ *
+ * Setter for "DebugLevel" property.
+ */
+DBusMessage * wpas_dbus_setter_debug_level(DBusMessage *message,
+					   struct wpa_global *global)
+{
+	DBusMessage *reply;
+	const char *str = NULL;
+	int i, val = -1;
+
+	reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_STRING,
+						 &str);
+	if (reply)
+		return reply;
+
+	for (i = 0; debug_strings[i]; i++)
+		if (os_strcmp(debug_strings[i], str) == 0) {
+			val = i;
+			break;
+		}
+
+	if (val < 0 ||
+	    wpa_supplicant_set_debug_params(global, val, wpa_debug_timestamp,
+					    wpa_debug_show_keys)) {
+		return wpas_dbus_error_invalid_args(
+			message, "Wrong debug level value");
+	}
+
+	return NULL;
+}
+
+
+/**
+ * wpas_dbus_setter_debug_timestamp - Set debug timestamp
+ * @message: Pointer to incoming dbus message
+ * @global: %wpa_supplicant global data structure
+ * Returns: %NULL or DBus error message
+ *
+ * Setter for "DebugTimestamp" property.
+ */
+DBusMessage * wpas_dbus_setter_debug_timestamp(DBusMessage *message,
+					       struct wpa_global *global)
+{
+	DBusMessage *reply;
+	dbus_bool_t val;
+
+	reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_BOOLEAN,
+						 &val);
+	if (reply)
+		return reply;
+
+	wpa_supplicant_set_debug_params(global, wpa_debug_level, val ? 1 : 0,
+					wpa_debug_show_keys);
+
+	return NULL;
+}
+
+
+/**
+ * wpas_dbus_setter_debug_show_keys - Set debug show keys
+ * @message: Pointer to incoming dbus message
+ * @global: %wpa_supplicant global data structure
+ * Returns: %NULL or DBus error message
+ *
+ * Setter for "DebugShowKeys" property.
+ */
+DBusMessage * wpas_dbus_setter_debug_show_keys(DBusMessage *message,
+					       struct wpa_global *global)
+{
+	DBusMessage *reply;
+	dbus_bool_t val;
+
+	reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_BOOLEAN,
+						 &val);
+	if (reply)
+		return reply;
+
+	wpa_supplicant_set_debug_params(global, wpa_debug_level,
+					wpa_debug_timestamp,
+					val ? 1 : 0);
+
+	return NULL;
+}
+
+
+/**
+ * wpas_dbus_getter_interfaces - Request registered interfaces list
+ * @message: Pointer to incoming dbus message
+ * @global: %wpa_supplicant global data structure
+ * Returns: The object paths array containing registered interfaces
+ * objects paths or DBus error on failure
+ *
+ * Getter for "Interfaces" property. Handles requests
+ * by dbus clients to return list of registered interfaces objects
+ * paths
+ */
+DBusMessage * wpas_dbus_getter_interfaces(DBusMessage *message,
+					  struct wpa_global *global)
+{
+	DBusMessage *reply = NULL;
+	struct wpa_supplicant *wpa_s;
+	const char **paths;
+	unsigned int i = 0, num = 0;
+
+	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
+		num++;
+
+	paths = os_zalloc(num * sizeof(char*));
+	if (!paths) {
+		return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					      NULL);
+	}
+
+	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
+		paths[i++] = wpa_s->dbus_new_path;
+
+	reply = wpas_dbus_simple_array_property_getter(message,
+						       DBUS_TYPE_OBJECT_PATH,
+						       paths, num);
+
+	os_free(paths);
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_getter_eap_methods - Request supported EAP methods list
+ * @message: Pointer to incoming dbus message
+ * @nothing: not used argument. may be NULL or anything else
+ * Returns: The object paths array containing supported EAP methods
+ * represented by strings or DBus error on failure
+ *
+ * Getter for "EapMethods" property. Handles requests
+ * by dbus clients to return list of strings with supported EAP methods
+ */
+DBusMessage * wpas_dbus_getter_eap_methods(DBusMessage *message, void *nothing)
+{
+	DBusMessage *reply = NULL;
+	char **eap_methods;
+	size_t num_items = 0;
+
+	eap_methods = eap_get_names_as_string_array(&num_items);
+	if (!eap_methods) {
+		return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					      NULL);
+	}
+
+	reply = wpas_dbus_simple_array_property_getter(message,
+						       DBUS_TYPE_STRING,
+						       eap_methods, num_items);
+
+	while (num_items)
+		os_free(eap_methods[--num_items]);
+	os_free(eap_methods);
+	return reply;
+}
+
+
+static int wpas_dbus_get_scan_type(DBusMessage *message, DBusMessageIter *var,
+				   char **type, DBusMessage **reply)
+{
+	if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_STRING) {
+		wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
+			   "Type must be a string");
+		*reply = wpas_dbus_error_invalid_args(
+			message, "Wrong Type value type. String required");
+		return -1;
+	}
+	dbus_message_iter_get_basic(var, type);
+	return 0;
+}
+
+
+static int wpas_dbus_get_scan_ssids(DBusMessage *message, DBusMessageIter *var,
+				    struct wpa_driver_scan_params *params,
+				    DBusMessage **reply)
+{
+	struct wpa_driver_scan_ssid *ssids = params->ssids;
+	size_t ssids_num = 0;
+	u8 *ssid;
+	DBusMessageIter array_iter, sub_array_iter;
+	char *val;
+	int len;
+
+	if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
+		wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ssids "
+			   "must be an array of arrays of bytes");
+		*reply = wpas_dbus_error_invalid_args(
+			message, "Wrong SSIDs value type. Array of arrays of "
+			"bytes required");
+		return -1;
+	}
+
+	dbus_message_iter_recurse(var, &array_iter);
+
+	if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
+	    dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE)
+	{
+		wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ssids "
+			   "must be an array of arrays of bytes");
+		*reply = wpas_dbus_error_invalid_args(
+			message, "Wrong SSIDs value type. Array of arrays of "
+			"bytes required");
+		return -1;
+	}
+
+	while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY)
+	{
+		if (ssids_num >= WPAS_MAX_SCAN_SSIDS) {
+			wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
+				   "Too many ssids specified on scan dbus "
+				   "call");
+			*reply = wpas_dbus_error_invalid_args(
+				message, "Too many ssids specified. Specify "
+				"at most four");
+			return -1;
+		}
+
+		dbus_message_iter_recurse(&array_iter, &sub_array_iter);
+
+		dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
+
+		if (len != 0) {
+			ssid = os_malloc(len);
+			if (ssid == NULL) {
+				wpa_printf(MSG_DEBUG,
+					   "wpas_dbus_handler_scan[dbus]: "
+					   "out of memory. Cannot allocate "
+					   "memory for SSID");
+				*reply = dbus_message_new_error(
+					message, DBUS_ERROR_NO_MEMORY, NULL);
+				return -1;
+			}
+			os_memcpy(ssid, val, len);
+		} else {
+			/* Allow zero-length SSIDs */
+			ssid = NULL;
+		}
+
+		ssids[ssids_num].ssid = ssid;
+		ssids[ssids_num].ssid_len = len;
+
+		dbus_message_iter_next(&array_iter);
+		ssids_num++;
+	}
+
+	params->num_ssids = ssids_num;
+	return 0;
+}
+
+
+static int wpas_dbus_get_scan_ies(DBusMessage *message, DBusMessageIter *var,
+				  struct wpa_driver_scan_params *params,
+				  DBusMessage **reply)
+{
+	u8 *ies = NULL, *nies;
+	int ies_len = 0;
+	DBusMessageIter array_iter, sub_array_iter;
+	char *val;
+	int len;
+
+	if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
+		wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ies must "
+			   "be an array of arrays of bytes");
+		*reply = wpas_dbus_error_invalid_args(
+			message, "Wrong IEs value type. Array of arrays of "
+			"bytes required");
+		return -1;
+	}
+
+	dbus_message_iter_recurse(var, &array_iter);
+
+	if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_ARRAY ||
+	    dbus_message_iter_get_element_type(&array_iter) != DBUS_TYPE_BYTE)
+	{
+		wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: ies must "
+			   "be an array of arrays of bytes");
+		*reply = wpas_dbus_error_invalid_args(
+			message, "Wrong IEs value type. Array required");
+		return -1;
+	}
+
+	while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_ARRAY)
+	{
+		dbus_message_iter_recurse(&array_iter, &sub_array_iter);
+
+		dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len);
+		if (len == 0) {
+			dbus_message_iter_next(&array_iter);
+			continue;
+		}
+
+		nies = os_realloc(ies, ies_len + len);
+		if (nies == NULL) {
+			wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
+				   "out of memory. Cannot allocate memory for "
+				   "IE");
+			os_free(ies);
+			*reply = dbus_message_new_error(
+				message, DBUS_ERROR_NO_MEMORY, NULL);
+			return -1;
+		}
+		ies = nies;
+		os_memcpy(ies + ies_len, val, len);
+		ies_len += len;
+
+		dbus_message_iter_next(&array_iter);
+	}
+
+	params->extra_ies = ies;
+	params->extra_ies_len = ies_len;
+	return 0;
+}
+
+
+static int wpas_dbus_get_scan_channels(DBusMessage *message,
+				       DBusMessageIter *var,
+				       struct wpa_driver_scan_params *params,
+				       DBusMessage **reply)
+{
+	DBusMessageIter array_iter, sub_array_iter;
+	int *freqs = NULL, *nfreqs;
+	int freqs_num = 0;
+
+	if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) {
+		wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
+			   "Channels must be an array of structs");
+		*reply = wpas_dbus_error_invalid_args(
+			message, "Wrong Channels value type. Array of structs "
+			"required");
+		return -1;
+	}
+
+	dbus_message_iter_recurse(var, &array_iter);
+
+	if (dbus_message_iter_get_arg_type(&array_iter) != DBUS_TYPE_STRUCT) {
+		wpa_printf(MSG_DEBUG,
+			   "wpas_dbus_handler_scan[dbus]: Channels must be an "
+			   "array of structs");
+		*reply = wpas_dbus_error_invalid_args(
+			message, "Wrong Channels value type. Array of structs "
+			"required");
+		return -1;
+	}
+
+	while (dbus_message_iter_get_arg_type(&array_iter) == DBUS_TYPE_STRUCT)
+	{
+		int freq, width;
+
+		dbus_message_iter_recurse(&array_iter, &sub_array_iter);
+
+		if (dbus_message_iter_get_arg_type(&sub_array_iter) !=
+		    DBUS_TYPE_UINT32) {
+			wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
+				   "Channel must by specified by struct of "
+				   "two UINT32s %c",
+				   dbus_message_iter_get_arg_type(
+					   &sub_array_iter));
+			*reply = wpas_dbus_error_invalid_args(
+				message, "Wrong Channel struct. Two UINT32s "
+				"required");
+			os_free(freqs);
+			return -1;
+		}
+		dbus_message_iter_get_basic(&sub_array_iter, &freq);
+
+		if (!dbus_message_iter_next(&sub_array_iter) ||
+		    dbus_message_iter_get_arg_type(&sub_array_iter) !=
+		    DBUS_TYPE_UINT32) {
+			wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
+				   "Channel must by specified by struct of "
+				   "two UINT32s");
+			*reply = wpas_dbus_error_invalid_args(
+				message,
+				"Wrong Channel struct. Two UINT32s required");
+			os_free(freqs);
+			return -1;
+		}
+
+		dbus_message_iter_get_basic(&sub_array_iter, &width);
+
+#define FREQS_ALLOC_CHUNK 32
+		if (freqs_num % FREQS_ALLOC_CHUNK == 0) {
+			nfreqs = os_realloc(freqs, sizeof(int) *
+					    (freqs_num + FREQS_ALLOC_CHUNK));
+			if (nfreqs == NULL)
+				os_free(freqs);
+			freqs = nfreqs;
+		}
+		if (freqs == NULL) {
+			wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
+				   "out of memory. can't allocate memory for "
+				   "freqs");
+			*reply = dbus_message_new_error(
+				message, DBUS_ERROR_NO_MEMORY, NULL);
+			return -1;
+		}
+
+		freqs[freqs_num] = freq;
+
+		freqs_num++;
+		dbus_message_iter_next(&array_iter);
+	}
+
+	nfreqs = os_realloc(freqs,
+			    sizeof(int) * (freqs_num + 1));
+	if (nfreqs == NULL)
+		os_free(freqs);
+	freqs = nfreqs;
+	if (freqs == NULL) {
+		wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
+			   "out of memory. Can't allocate memory for freqs");
+		*reply = dbus_message_new_error(
+			message, DBUS_ERROR_NO_MEMORY, NULL);
+		return -1;
+	}
+	freqs[freqs_num] = 0;
+
+	params->freqs = freqs;
+	return 0;
+}
+
+
+/**
+ * wpas_dbus_handler_scan - Request a wireless scan on an interface
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: NULL indicating success or DBus error message on failure
+ *
+ * Handler function for "Scan" method call of a network device. Requests
+ * that wpa_supplicant perform a wireless scan as soon as possible
+ * on a particular wireless interface.
+ */
+DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
+				     struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply = NULL;
+	DBusMessageIter iter, dict_iter, entry_iter, variant_iter;
+	char *key = NULL, *type = NULL;
+	struct wpa_driver_scan_params params;
+	size_t i;
+
+	os_memset(&params, 0, sizeof(params));
+
+	dbus_message_iter_init(message, &iter);
+
+	dbus_message_iter_recurse(&iter, &dict_iter);
+
+	while (dbus_message_iter_get_arg_type(&dict_iter) ==
+			DBUS_TYPE_DICT_ENTRY) {
+		dbus_message_iter_recurse(&dict_iter, &entry_iter);
+		dbus_message_iter_get_basic(&entry_iter, &key);
+		dbus_message_iter_next(&entry_iter);
+		dbus_message_iter_recurse(&entry_iter, &variant_iter);
+
+		if (os_strcmp(key, "Type") == 0) {
+			if (wpas_dbus_get_scan_type(message, &variant_iter,
+						    &type, &reply) < 0)
+				goto out;
+		} else if (os_strcmp(key, "SSIDs") == 0) {
+			if (wpas_dbus_get_scan_ssids(message, &variant_iter,
+						     &params, &reply) < 0)
+				goto out;
+		} else if (os_strcmp(key, "IEs") == 0) {
+			if (wpas_dbus_get_scan_ies(message, &variant_iter,
+						   &params, &reply) < 0)
+				goto out;
+		} else if (os_strcmp(key, "Channels") == 0) {
+			if (wpas_dbus_get_scan_channels(message, &variant_iter,
+							&params, &reply) < 0)
+				goto out;
+		} else {
+			wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
+				   "Unknown argument %s", key);
+			reply = wpas_dbus_error_invalid_args(message, key);
+			goto out;
+		}
+
+		dbus_message_iter_next(&dict_iter);
+	}
+
+	if (!type) {
+		wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
+			   "Scan type not specified");
+		reply = wpas_dbus_error_invalid_args(message, key);
+		goto out;
+	}
+
+	if (!os_strcmp(type, "passive")) {
+		if (params.num_ssids || params.extra_ies_len) {
+			wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
+				   "SSIDs or IEs specified for passive scan.");
+			reply = wpas_dbus_error_invalid_args(
+				message, "You can specify only Channels in "
+				"passive scan");
+			goto out;
+		} else if (params.freqs && params.freqs[0]) {
+			wpa_supplicant_trigger_scan(wpa_s, &params);
+		} else {
+			wpa_s->scan_req = 2;
+			wpa_supplicant_req_scan(wpa_s, 0, 0);
+		}
+	} else if (!os_strcmp(type, "active")) {
+		if (!params.num_ssids) {
+			/* Add wildcard ssid */
+			params.num_ssids++;
+		}
+		wpa_supplicant_trigger_scan(wpa_s, &params);
+	} else {
+		wpa_printf(MSG_DEBUG, "wpas_dbus_handler_scan[dbus]: "
+			   "Unknown scan type: %s", type);
+		reply = wpas_dbus_error_invalid_args(message,
+						     "Wrong scan type");
+		goto out;
+	}
+
+out:
+	for (i = 0; i < WPAS_MAX_SCAN_SSIDS; i++)
+		os_free((u8 *) params.ssids[i].ssid);
+	os_free((u8 *) params.extra_ies);
+	os_free(params.freqs);
+	return reply;
+}
+
+
+/*
+ * wpas_dbus_handler_disconnect - Terminate the current connection
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: NotConnected DBus error message if already not connected
+ * or NULL otherwise.
+ *
+ * Handler function for "Disconnect" method call of network interface.
+ */
+DBusMessage * wpas_dbus_handler_disconnect(DBusMessage *message,
+					   struct wpa_supplicant *wpa_s)
+{
+	if (wpa_s->current_ssid != NULL) {
+		wpa_s->disconnected = 1;
+		wpa_supplicant_deauthenticate(wpa_s,
+					      WLAN_REASON_DEAUTH_LEAVING);
+
+		return NULL;
+	}
+
+	return dbus_message_new_error(message, WPAS_DBUS_ERROR_NOT_CONNECTED,
+				      "This interface is not connected");
+}
+
+
+/**
+ * wpas_dbus_new_iface_add_network - Add a new configured network
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: A dbus message containing the object path of the new network
+ *
+ * Handler function for "AddNetwork" method call of a network interface.
+ */
+DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message,
+					    struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply = NULL;
+	DBusMessageIter	iter;
+	struct wpa_ssid *ssid = NULL;
+	char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
+
+	dbus_message_iter_init(message, &iter);
+
+	ssid = wpa_config_add_network(wpa_s->conf);
+	if (ssid == NULL) {
+		wpa_printf(MSG_ERROR, "wpas_dbus_handler_add_network[dbus]: "
+			   "can't add new interface.");
+		reply = wpas_dbus_error_unknown_error(
+			message,
+			"wpa_supplicant could not add "
+			"a network on this interface.");
+		goto err;
+	}
+	wpas_notify_network_added(wpa_s, ssid);
+	ssid->disabled = 1;
+	wpa_config_set_network_defaults(ssid);
+
+	reply = set_network_properties(message, wpa_s, ssid, &iter);
+	if (reply) {
+		wpa_printf(MSG_DEBUG, "wpas_dbus_handler_add_network[dbus]:"
+			   "control interface couldn't set network "
+			   "properties");
+		goto err;
+	}
+
+	/* Construct the object path for this network. */
+	os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
+		    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
+		    wpa_s->dbus_new_path, ssid->id);
+
+	reply = dbus_message_new_method_return(message);
+	if (reply == NULL) {
+		reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					       NULL);
+		goto err;
+	}
+	if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path,
+				      DBUS_TYPE_INVALID)) {
+		dbus_message_unref(reply);
+		reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					       NULL);
+		goto err;
+	}
+
+	return reply;
+
+err:
+	if (ssid) {
+		wpas_notify_network_removed(wpa_s, ssid);
+		wpa_config_remove_network(wpa_s->conf, ssid->id);
+	}
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_handler_remove_network - Remove a configured network
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: NULL on success or dbus error on failure
+ *
+ * Handler function for "RemoveNetwork" method call of a network interface.
+ */
+DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
+					       struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply = NULL;
+	const char *op;
+	char *iface = NULL, *net_id = NULL;
+	int id;
+	struct wpa_ssid *ssid;
+
+	dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
+			      DBUS_TYPE_INVALID);
+
+	/* Extract the network ID and ensure the network */
+	/* is actually a child of this interface */
+	iface = wpas_dbus_new_decompose_object_path(op, &net_id, NULL);
+	if (iface == NULL || os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
+		reply = wpas_dbus_error_invalid_args(message, op);
+		goto out;
+	}
+
+	id = strtoul(net_id, NULL, 10);
+	if (errno == EINVAL) {
+		reply = wpas_dbus_error_invalid_args(message, op);
+		goto out;
+	}
+
+	ssid = wpa_config_get_network(wpa_s->conf, id);
+	if (ssid == NULL) {
+		reply = wpas_dbus_error_network_unknown(message);
+		goto out;
+	}
+
+	wpas_notify_network_removed(wpa_s, ssid);
+
+	if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
+		wpa_printf(MSG_ERROR,
+			   "wpas_dbus_handler_remove_network[dbus]: "
+			   "error occurred when removing network %d", id);
+		reply = wpas_dbus_error_unknown_error(
+			message, "error removing the specified network on "
+			"this interface.");
+		goto out;
+	}
+
+	if (ssid == wpa_s->current_ssid)
+		wpa_supplicant_deauthenticate(wpa_s,
+					      WLAN_REASON_DEAUTH_LEAVING);
+
+out:
+	os_free(iface);
+	os_free(net_id);
+	return reply;
+}
+
+
+static void remove_network(void *arg, struct wpa_ssid *ssid)
+{
+	struct wpa_supplicant *wpa_s = arg;
+
+	wpas_notify_network_removed(wpa_s, ssid);
+
+	if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) {
+		wpa_printf(MSG_ERROR,
+			   "wpas_dbus_handler_remove_all_networks[dbus]: "
+			   "error occurred when removing network %d",
+			   ssid->id);
+		return;
+	}
+
+	if (ssid == wpa_s->current_ssid)
+		wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
+}
+
+
+/**
+ * wpas_dbus_handler_remove_all_networks - Remove all configured networks
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: NULL on success or dbus error on failure
+ *
+ * Handler function for "RemoveAllNetworks" method call of a network interface.
+ */
+DBusMessage * wpas_dbus_handler_remove_all_networks(
+	DBusMessage *message, struct wpa_supplicant *wpa_s)
+{
+	/* NB: could check for failure and return an error */
+	wpa_config_foreach_network(wpa_s->conf, remove_network, wpa_s);
+	return NULL;
+}
+
+
+/**
+ * wpas_dbus_handler_select_network - Attempt association with a network
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: NULL on success or dbus error on failure
+ *
+ * Handler function for "SelectNetwork" method call of network interface.
+ */
+DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message,
+					       struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply = NULL;
+	const char *op;
+	char *iface = NULL, *net_id = NULL;
+	int id;
+	struct wpa_ssid *ssid;
+
+	dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op,
+			      DBUS_TYPE_INVALID);
+
+	/* Extract the network ID and ensure the network */
+	/* is actually a child of this interface */
+	iface = wpas_dbus_new_decompose_object_path(op, &net_id, NULL);
+	if (iface == NULL || os_strcmp(iface, wpa_s->dbus_new_path) != 0) {
+		reply = wpas_dbus_error_invalid_args(message, op);
+		goto out;
+	}
+
+	id = strtoul(net_id, NULL, 10);
+	if (errno == EINVAL) {
+		reply = wpas_dbus_error_invalid_args(message, op);
+		goto out;
+	}
+
+	ssid = wpa_config_get_network(wpa_s->conf, id);
+	if (ssid == NULL) {
+		reply = wpas_dbus_error_network_unknown(message);
+		goto out;
+	}
+
+	/* Finally, associate with the network */
+	wpa_supplicant_select_network(wpa_s, ssid);
+
+out:
+	os_free(iface);
+	os_free(net_id);
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_handler_add_blob - Store named binary blob (ie, for certificates)
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: %wpa_supplicant data structure
+ * Returns: A dbus message containing an error on failure or NULL on success
+ *
+ * Asks wpa_supplicant to internally store a binary blobs.
+ */
+DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message,
+					 struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply = NULL;
+	DBusMessageIter	iter, array_iter;
+
+	char *blob_name;
+	u8 *blob_data;
+	int blob_len;
+	struct wpa_config_blob *blob = NULL;
+
+	dbus_message_iter_init(message, &iter);
+	dbus_message_iter_get_basic(&iter, &blob_name);
+
+	if (wpa_config_get_blob(wpa_s->conf, blob_name)) {
+		return dbus_message_new_error(message,
+					      WPAS_DBUS_ERROR_BLOB_EXISTS,
+					      NULL);
+	}
+
+	dbus_message_iter_next(&iter);
+	dbus_message_iter_recurse(&iter, &array_iter);
+
+	dbus_message_iter_get_fixed_array(&array_iter, &blob_data, &blob_len);
+
+	blob = os_zalloc(sizeof(*blob));
+	if (!blob) {
+		reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					       NULL);
+		goto err;
+	}
+
+	blob->data = os_malloc(blob_len);
+	if (!blob->data) {
+		reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					       NULL);
+		goto err;
+	}
+	os_memcpy(blob->data, blob_data, blob_len);
+
+	blob->len = blob_len;
+	blob->name = os_strdup(blob_name);
+	if (!blob->name) {
+		reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					       NULL);
+		goto err;
+	}
+
+	wpa_config_set_blob(wpa_s->conf, blob);
+	wpas_notify_blob_added(wpa_s, blob->name);
+
+	return reply;
+
+err:
+	if (blob) {
+		os_free(blob->name);
+		os_free(blob->data);
+		os_free(blob);
+	}
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_handler_get_blob - Get named binary blob (ie, for certificates)
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: %wpa_supplicant data structure
+ * Returns: A dbus message containing array of bytes (blob)
+ *
+ * Gets one wpa_supplicant's binary blobs.
+ */
+DBusMessage * wpas_dbus_handler_get_blob(DBusMessage *message,
+					 struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply = NULL;
+	DBusMessageIter	iter, array_iter;
+
+	char *blob_name;
+	const struct wpa_config_blob *blob;
+
+	dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
+			      DBUS_TYPE_INVALID);
+
+	blob = wpa_config_get_blob(wpa_s->conf, blob_name);
+	if (!blob) {
+		return dbus_message_new_error(message,
+					      WPAS_DBUS_ERROR_BLOB_UNKNOWN,
+					      "Blob id not set");
+	}
+
+	reply = dbus_message_new_method_return(message);
+	if (!reply) {
+		reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					       NULL);
+		goto out;
+	}
+
+	dbus_message_iter_init_append(reply, &iter);
+
+	if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+					      DBUS_TYPE_BYTE_AS_STRING,
+					      &array_iter)) {
+		dbus_message_unref(reply);
+		reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					       NULL);
+		goto out;
+	}
+
+	if (!dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
+						  &(blob->data), blob->len)) {
+		dbus_message_unref(reply);
+		reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					       NULL);
+		goto out;
+	}
+
+	if (!dbus_message_iter_close_container(&iter, &array_iter)) {
+		dbus_message_unref(reply);
+		reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					       NULL);
+		goto out;
+	}
+
+out:
+	return reply;
+}
+
+
+/**
+ * wpas_remove_handler_remove_blob - Remove named binary blob
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: %wpa_supplicant data structure
+ * Returns: NULL on success or dbus error
+ *
+ * Asks wpa_supplicant to internally remove a binary blobs.
+ */
+DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message,
+					    struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply = NULL;
+	char *blob_name;
+
+	dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &blob_name,
+			      DBUS_TYPE_INVALID);
+
+	if (wpa_config_remove_blob(wpa_s->conf, blob_name)) {
+		return dbus_message_new_error(message,
+					      WPAS_DBUS_ERROR_BLOB_UNKNOWN,
+					      "Blob id not set");
+	}
+	wpas_notify_blob_removed(wpa_s, blob_name);
+
+	return reply;
+
+}
+
+/*
+ * wpas_dbus_handler_flush_bss - Flush the BSS cache
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: NULL
+ *
+ * Handler function for "FlushBSS" method call of network interface.
+ */
+DBusMessage * wpas_dbus_handler_flush_bss(DBusMessage *message,
+					  struct wpa_supplicant *wpa_s)
+{
+	dbus_uint32_t age;
+
+	dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &age,
+			      DBUS_TYPE_INVALID);
+
+	if (age == 0)
+		wpa_bss_flush(wpa_s);
+	else
+		wpa_bss_flush_by_age(wpa_s, age);
+
+	return NULL;
+}
+
+
+/**
+ * wpas_dbus_getter_capabilities - Return interface capabilities
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: A dbus message containing a dict of strings
+ *
+ * Getter for "Capabilities" property of an interface.
+ */
+DBusMessage * wpas_dbus_getter_capabilities(DBusMessage *message,
+					    struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply = NULL;
+	struct wpa_driver_capa capa;
+	int res;
+	DBusMessageIter iter, iter_dict;
+	DBusMessageIter iter_dict_entry, iter_dict_val, iter_array,
+		variant_iter;
+	const char *scans[] = { "active", "passive", "ssid" };
+	const char *modes[] = { "infrastructure", "ad-hoc", "ap" };
+	int n = sizeof(modes) / sizeof(char *);
+
+	if (message == NULL)
+		reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
+	else
+		reply = dbus_message_new_method_return(message);
+	if (!reply)
+		goto nomem;
+
+	dbus_message_iter_init_append(reply, &iter);
+	if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
+					      "a{sv}", &variant_iter))
+		goto nomem;
+
+	if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
+		goto nomem;
+
+	res = wpa_drv_get_capa(wpa_s, &capa);
+
+	/***** pairwise cipher */
+	if (res < 0) {
+		const char *args[] = {"ccmp", "tkip", "none"};
+		if (!wpa_dbus_dict_append_string_array(
+			    &iter_dict, "Pairwise", args,
+			    sizeof(args) / sizeof(char*)))
+			goto nomem;
+	} else {
+		if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Pairwise",
+						      &iter_dict_entry,
+						      &iter_dict_val,
+						      &iter_array))
+			goto nomem;
+
+		if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
+			if (!wpa_dbus_dict_string_array_add_element(
+				    &iter_array, "ccmp"))
+				goto nomem;
+		}
+
+		if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
+			if (!wpa_dbus_dict_string_array_add_element(
+				    &iter_array, "tkip"))
+				goto nomem;
+		}
+
+		if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
+			if (!wpa_dbus_dict_string_array_add_element(
+				    &iter_array, "none"))
+				goto nomem;
+		}
+
+		if (!wpa_dbus_dict_end_string_array(&iter_dict,
+						    &iter_dict_entry,
+						    &iter_dict_val,
+						    &iter_array))
+			goto nomem;
+	}
+
+	/***** group cipher */
+	if (res < 0) {
+		const char *args[] = {
+			"ccmp", "tkip", "wep104", "wep40"
+		};
+		if (!wpa_dbus_dict_append_string_array(
+			    &iter_dict, "Group", args,
+			    sizeof(args) / sizeof(char*)))
+			goto nomem;
+	} else {
+		if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Group",
+						      &iter_dict_entry,
+						      &iter_dict_val,
+						      &iter_array))
+			goto nomem;
+
+		if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
+			if (!wpa_dbus_dict_string_array_add_element(
+				    &iter_array, "ccmp"))
+				goto nomem;
+		}
+
+		if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
+			if (!wpa_dbus_dict_string_array_add_element(
+				    &iter_array, "tkip"))
+				goto nomem;
+		}
+
+		if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) {
+			if (!wpa_dbus_dict_string_array_add_element(
+				    &iter_array, "wep104"))
+				goto nomem;
+		}
+
+		if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) {
+			if (!wpa_dbus_dict_string_array_add_element(
+				    &iter_array, "wep40"))
+				goto nomem;
+		}
+
+		if (!wpa_dbus_dict_end_string_array(&iter_dict,
+						    &iter_dict_entry,
+						    &iter_dict_val,
+						    &iter_array))
+			goto nomem;
+	}
+
+	/***** key management */
+	if (res < 0) {
+		const char *args[] = {
+			"wpa-psk", "wpa-eap", "ieee8021x", "wpa-none",
+#ifdef CONFIG_WPS
+			"wps",
+#endif /* CONFIG_WPS */
+			"none"
+		};
+		if (!wpa_dbus_dict_append_string_array(
+			    &iter_dict, "KeyMgmt", args,
+			    sizeof(args) / sizeof(char*)))
+			goto nomem;
+	} else {
+		if (!wpa_dbus_dict_begin_string_array(&iter_dict, "KeyMgmt",
+						      &iter_dict_entry,
+						      &iter_dict_val,
+						      &iter_array))
+			goto nomem;
+
+		if (!wpa_dbus_dict_string_array_add_element(&iter_array,
+							    "none"))
+			goto nomem;
+
+		if (!wpa_dbus_dict_string_array_add_element(&iter_array,
+							    "ieee8021x"))
+			goto nomem;
+
+		if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
+				     WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
+			if (!wpa_dbus_dict_string_array_add_element(
+				    &iter_array, "wpa-eap"))
+				goto nomem;
+
+			if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT)
+				if (!wpa_dbus_dict_string_array_add_element(
+					    &iter_array, "wpa-ft-eap"))
+					goto nomem;
+
+/* TODO: Ensure that driver actually supports sha256 encryption. */
+#ifdef CONFIG_IEEE80211W
+			if (!wpa_dbus_dict_string_array_add_element(
+				    &iter_array, "wpa-eap-sha256"))
+				goto nomem;
+#endif /* CONFIG_IEEE80211W */
+		}
+
+		if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
+				     WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
+			if (!wpa_dbus_dict_string_array_add_element(
+				    &iter_array, "wpa-psk"))
+				goto nomem;
+
+			if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK)
+				if (!wpa_dbus_dict_string_array_add_element(
+					    &iter_array, "wpa-ft-psk"))
+					goto nomem;
+
+/* TODO: Ensure that driver actually supports sha256 encryption. */
+#ifdef CONFIG_IEEE80211W
+			if (!wpa_dbus_dict_string_array_add_element(
+				    &iter_array, "wpa-psk-sha256"))
+				goto nomem;
+#endif /* CONFIG_IEEE80211W */
+		}
+
+		if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
+			if (!wpa_dbus_dict_string_array_add_element(
+				    &iter_array, "wpa-none"))
+				goto nomem;
+		}
+
+
+#ifdef CONFIG_WPS
+		if (!wpa_dbus_dict_string_array_add_element(&iter_array,
+							    "wps"))
+			goto nomem;
+#endif /* CONFIG_WPS */
+
+		if (!wpa_dbus_dict_end_string_array(&iter_dict,
+						    &iter_dict_entry,
+						    &iter_dict_val,
+						    &iter_array))
+			goto nomem;
+	}
+
+	/***** WPA protocol */
+	if (res < 0) {
+		const char *args[] = { "rsn", "wpa" };
+		if (!wpa_dbus_dict_append_string_array(
+			    &iter_dict, "Protocol", args,
+			    sizeof(args) / sizeof(char*)))
+			goto nomem;
+	} else {
+		if (!wpa_dbus_dict_begin_string_array(&iter_dict, "Protocol",
+						      &iter_dict_entry,
+						      &iter_dict_val,
+						      &iter_array))
+			goto nomem;
+
+		if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
+				     WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
+			if (!wpa_dbus_dict_string_array_add_element(
+				    &iter_array, "rsn"))
+				goto nomem;
+		}
+
+		if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
+				     WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
+			if (!wpa_dbus_dict_string_array_add_element(
+				    &iter_array, "wpa"))
+				goto nomem;
+		}
+
+		if (!wpa_dbus_dict_end_string_array(&iter_dict,
+						    &iter_dict_entry,
+						    &iter_dict_val,
+						    &iter_array))
+			goto nomem;
+	}
+
+	/***** auth alg */
+	if (res < 0) {
+		const char *args[] = { "open", "shared", "leap" };
+		if (!wpa_dbus_dict_append_string_array(
+			    &iter_dict, "AuthAlg", args,
+			    sizeof(args) / sizeof(char*)))
+			goto nomem;
+	} else {
+		if (!wpa_dbus_dict_begin_string_array(&iter_dict, "AuthAlg",
+						      &iter_dict_entry,
+						      &iter_dict_val,
+						      &iter_array))
+			goto nomem;
+
+		if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) {
+			if (!wpa_dbus_dict_string_array_add_element(
+				    &iter_array, "open"))
+				goto nomem;
+		}
+
+		if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) {
+			if (!wpa_dbus_dict_string_array_add_element(
+				    &iter_array, "shared"))
+				goto nomem;
+		}
+
+		if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) {
+			if (!wpa_dbus_dict_string_array_add_element(
+				    &iter_array, "leap"))
+				goto nomem;
+		}
+
+		if (!wpa_dbus_dict_end_string_array(&iter_dict,
+						    &iter_dict_entry,
+						    &iter_dict_val,
+						    &iter_array))
+			goto nomem;
+	}
+
+	/***** Scan */
+	if (!wpa_dbus_dict_append_string_array(&iter_dict, "Scan", scans,
+					       sizeof(scans) / sizeof(char *)))
+		goto nomem;
+
+	/***** Modes */
+	if (res < 0 || !(capa.flags & WPA_DRIVER_FLAGS_AP))
+		n--; /* exclude ap mode if it is not supported by the driver */
+	if (!wpa_dbus_dict_append_string_array(&iter_dict, "Modes", modes, n))
+		goto nomem;
+
+	if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict))
+		goto nomem;
+	if (!dbus_message_iter_close_container(&iter, &variant_iter))
+		goto nomem;
+
+	return reply;
+
+nomem:
+	if (reply)
+		dbus_message_unref(reply);
+
+	return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
+}
+
+
+/**
+ * wpas_dbus_getter_state - Get interface state
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: A dbus message containing a STRING representing the current
+ *          interface state
+ *
+ * Getter for "State" property.
+ */
+DBusMessage * wpas_dbus_getter_state(DBusMessage *message,
+				     struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply = NULL;
+	const char *str_state;
+	char *state_ls, *tmp;
+
+	str_state = wpa_supplicant_state_txt(wpa_s->wpa_state);
+
+	/* make state string lowercase to fit new DBus API convention
+	 */
+	state_ls = tmp = os_strdup(str_state);
+	if (!tmp) {
+		return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					      NULL);
+	}
+	while (*tmp) {
+		*tmp = tolower(*tmp);
+		tmp++;
+	}
+
+	reply = wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
+						 &state_ls);
+
+	os_free(state_ls);
+
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_new_iface_get_scanning - Get interface scanning state
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: A dbus message containing whether the interface is scanning
+ *
+ * Getter for "scanning" property.
+ */
+DBusMessage * wpas_dbus_getter_scanning(DBusMessage *message,
+					struct wpa_supplicant *wpa_s)
+{
+	dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
+	return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN,
+						&scanning);
+}
+
+
+/**
+ * wpas_dbus_getter_ap_scan - Control roaming mode
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: A message containong value of ap_scan variable
+ *
+ * Getter function for "ApScan" property.
+ */
+DBusMessage * wpas_dbus_getter_ap_scan(DBusMessage *message,
+				       struct wpa_supplicant *wpa_s)
+{
+	dbus_uint32_t ap_scan = wpa_s->conf->ap_scan;
+	return wpas_dbus_simple_property_getter(message, DBUS_TYPE_UINT32,
+						&ap_scan);
+}
+
+
+/**
+ * wpas_dbus_setter_ap_scan - Control roaming mode
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: NULL
+ *
+ * Setter function for "ApScan" property.
+ */
+DBusMessage * wpas_dbus_setter_ap_scan(DBusMessage *message,
+				       struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply = NULL;
+	dbus_uint32_t ap_scan;
+
+	reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_UINT32,
+						 &ap_scan);
+	if (reply)
+		return reply;
+
+	if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) {
+		return wpas_dbus_error_invalid_args(
+			message, "ap_scan must equal 0, 1 or 2");
+	}
+	return NULL;
+}
+
+
+/**
+ * wpas_dbus_getter_bss_expire_age - Get BSS entry expiration age
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: A message containing value of bss_expiration_age variable
+ *
+ * Getter function for "BSSExpireAge" property.
+ */
+DBusMessage * wpas_dbus_getter_bss_expire_age(DBusMessage *message,
+					      struct wpa_supplicant *wpa_s)
+{
+	dbus_uint32_t expire_age = wpa_s->conf->bss_expiration_age;
+	return wpas_dbus_simple_property_getter(message, DBUS_TYPE_UINT32,
+						&expire_age);
+}
+
+
+/**
+ * wpas_dbus_setter_bss_expire_age - Control BSS entry expiration age
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: NULL
+ *
+ * Setter function for "BSSExpireAge" property.
+ */
+DBusMessage * wpas_dbus_setter_bss_expire_age(DBusMessage *message,
+					      struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply = NULL;
+	dbus_uint32_t expire_age;
+
+	reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_UINT32,
+						 &expire_age);
+	if (reply)
+		return reply;
+
+	if (wpa_supplicant_set_bss_expiration_age(wpa_s, expire_age)) {
+		return wpas_dbus_error_invalid_args(
+			message, "BSSExpireAge must be >=10");
+	}
+	return NULL;
+}
+
+
+/**
+ * wpas_dbus_getter_bss_expire_count - Get BSS entry expiration scan count
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: A message containing value of bss_expire_count variable
+ *
+ * Getter function for "BSSExpireCount" property.
+ */
+DBusMessage * wpas_dbus_getter_bss_expire_count(DBusMessage *message,
+						struct wpa_supplicant *wpa_s)
+{
+	dbus_uint32_t expire_count = wpa_s->conf->bss_expiration_age;
+	return wpas_dbus_simple_property_getter(message, DBUS_TYPE_UINT32,
+						&expire_count);
+}
+
+
+/**
+ * wpas_dbus_setter_bss_expire_count - Control BSS entry expiration scan count
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: NULL
+ *
+ * Setter function for "BSSExpireCount" property.
+ */
+DBusMessage * wpas_dbus_setter_bss_expire_count(DBusMessage *message,
+						struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply = NULL;
+	dbus_uint32_t expire_count;
+
+	reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_UINT32,
+						 &expire_count);
+	if (reply)
+		return reply;
+
+	if (wpa_supplicant_set_bss_expiration_count(wpa_s, expire_count)) {
+		return wpas_dbus_error_invalid_args(
+			message, "BSSExpireCount must be >0");
+	}
+	return NULL;
+}
+
+
+/**
+ * wpas_dbus_getter_country - Control country code
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: A message containong value of country variable
+ *
+ * Getter function for "Country" property.
+ */
+DBusMessage * wpas_dbus_getter_country(DBusMessage *message,
+				       struct wpa_supplicant *wpa_s)
+{
+	char country[3];
+	char *str = country;
+
+	country[0] = wpa_s->conf->country[0];
+	country[1] = wpa_s->conf->country[1];
+	country[2] = '\0';
+
+	return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
+						&str);
+}
+
+
+/**
+ * wpas_dbus_setter_country - Control country code
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: NULL
+ *
+ * Setter function for "Country" property.
+ */
+DBusMessage * wpas_dbus_setter_country(DBusMessage *message,
+				       struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply = NULL;
+	const char *country;
+
+	reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_STRING,
+						 &country);
+	if (reply)
+		return reply;
+
+	if (!country[0] || !country[1])
+		return wpas_dbus_error_invalid_args(message,
+						    "invalid country code");
+
+	if (wpa_s->drv_priv != NULL && wpa_drv_set_country(wpa_s, country)) {
+		wpa_printf(MSG_DEBUG, "Failed to set country");
+		return wpas_dbus_error_invalid_args(
+			message, "failed to set country code");
+	}
+
+	wpa_s->conf->country[0] = country[0];
+	wpa_s->conf->country[1] = country[1];
+	return NULL;
+}
+
+
+/**
+ * wpas_dbus_getter_ifname - Get interface name
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: A dbus message containing a name of network interface
+ * associated with with wpa_s
+ *
+ * Getter for "Ifname" property.
+ */
+DBusMessage * wpas_dbus_getter_ifname(DBusMessage *message,
+				      struct wpa_supplicant *wpa_s)
+{
+	const char *ifname = wpa_s->ifname;
+	return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
+						&ifname);
+}
+
+
+/**
+ * wpas_dbus_getter_driver - Get interface name
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: A dbus message containing a name of network interface
+ * driver associated with with wpa_s
+ *
+ * Getter for "Driver" property.
+ */
+DBusMessage * wpas_dbus_getter_driver(DBusMessage *message,
+				      struct wpa_supplicant *wpa_s)
+{
+	const char *driver;
+
+	if (wpa_s->driver == NULL || wpa_s->driver->name == NULL) {
+		wpa_printf(MSG_DEBUG, "wpas_dbus_getter_driver[dbus]: "
+			   "wpa_s has no driver set");
+		return wpas_dbus_error_unknown_error(message, NULL);
+	}
+
+	driver = wpa_s->driver->name;
+	return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
+						&driver);
+}
+
+
+/**
+ * wpas_dbus_getter_current_bss - Get current bss object path
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: A dbus message containing a DBus object path to
+ * current BSS
+ *
+ * Getter for "CurrentBSS" property.
+ */
+DBusMessage * wpas_dbus_getter_current_bss(DBusMessage *message,
+					   struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply;
+	char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path = path_buf;
+
+	if (wpa_s->current_bss)
+		os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+			    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
+			    wpa_s->dbus_new_path, wpa_s->current_bss->id);
+	else
+		os_snprintf(bss_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
+
+	reply = wpas_dbus_simple_property_getter(message,
+						 DBUS_TYPE_OBJECT_PATH,
+						 &bss_obj_path);
+
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_getter_current_network - Get current network object path
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: A dbus message containing a DBus object path to
+ * current network
+ *
+ * Getter for "CurrentNetwork" property.
+ */
+DBusMessage * wpas_dbus_getter_current_network(DBusMessage *message,
+					       struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply;
+	char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *net_obj_path = path_buf;
+
+	if (wpa_s->current_ssid)
+		os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+			    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%u",
+			    wpa_s->dbus_new_path, wpa_s->current_ssid->id);
+	else
+		os_snprintf(net_obj_path, WPAS_DBUS_OBJECT_PATH_MAX, "/");
+
+	reply = wpas_dbus_simple_property_getter(message,
+						 DBUS_TYPE_OBJECT_PATH,
+						 &net_obj_path);
+
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_getter_current_auth_mode - Get current authentication type
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: A dbus message containing a string indicating the current
+ * authentication type.
+ *
+ * Getter for "CurrentAuthMode" property.
+ */
+DBusMessage * wpas_dbus_getter_current_auth_mode(DBusMessage *message,
+						 struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply;
+	const char *eap_mode;
+	const char *auth_mode;
+	char eap_mode_buf[WPAS_DBUS_AUTH_MODE_MAX];
+
+	if (wpa_s->wpa_state != WPA_COMPLETED) {
+		auth_mode = "INACTIVE";
+	} else if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X ||
+	    wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
+		eap_mode = wpa_supplicant_get_eap_mode(wpa_s);
+		os_snprintf(eap_mode_buf, WPAS_DBUS_AUTH_MODE_MAX,
+			    "EAP-%s", eap_mode);
+		auth_mode = eap_mode_buf;
+
+	} else {
+		auth_mode = wpa_key_mgmt_txt(wpa_s->key_mgmt,
+					     wpa_s->current_ssid->proto);
+	}
+
+	reply = wpas_dbus_simple_property_getter(message,
+						 DBUS_TYPE_STRING,
+						 &auth_mode);
+
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_getter_bridge_ifname - Get interface name
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: A dbus message containing a name of bridge network
+ * interface associated with with wpa_s
+ *
+ * Getter for "BridgeIfname" property.
+ */
+DBusMessage * wpas_dbus_getter_bridge_ifname(DBusMessage *message,
+					     struct wpa_supplicant *wpa_s)
+{
+	const char *bridge_ifname = NULL;
+
+	bridge_ifname = wpa_s->bridge_ifname;
+	if (bridge_ifname == NULL) {
+		wpa_printf(MSG_ERROR, "wpas_dbus_getter_bridge_ifname[dbus]: "
+			   "wpa_s has no bridge interface name set");
+		return wpas_dbus_error_unknown_error(message, NULL);
+	}
+
+	return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
+						&bridge_ifname);
+}
+
+
+/**
+ * wpas_dbus_getter_bsss - Get array of BSSs objects
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: a dbus message containing an array of all known BSS objects
+ * dbus paths
+ *
+ * Getter for "BSSs" property.
+ */
+DBusMessage * wpas_dbus_getter_bsss(DBusMessage *message,
+				    struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply = NULL;
+	struct wpa_bss *bss;
+	char **paths;
+	unsigned int i = 0;
+
+	paths = os_zalloc(wpa_s->num_bss * sizeof(char *));
+	if (!paths) {
+		return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					      NULL);
+	}
+
+	/* Loop through scan results and append each result's object path */
+	dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
+		paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
+		if (paths[i] == NULL) {
+			reply = dbus_message_new_error(message,
+						       DBUS_ERROR_NO_MEMORY,
+						       NULL);
+			goto out;
+		}
+		/* Construct the object path for this BSS. */
+		os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
+			    "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
+			    wpa_s->dbus_new_path, bss->id);
+	}
+
+	reply = wpas_dbus_simple_array_property_getter(message,
+						       DBUS_TYPE_OBJECT_PATH,
+						       paths, wpa_s->num_bss);
+
+out:
+	while (i)
+		os_free(paths[--i]);
+	os_free(paths);
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_getter_networks - Get array of networks objects
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: a dbus message containing an array of all configured
+ * networks dbus object paths.
+ *
+ * Getter for "Networks" property.
+ */
+DBusMessage * wpas_dbus_getter_networks(DBusMessage *message,
+					struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply = NULL;
+	struct wpa_ssid *ssid;
+	char **paths;
+	unsigned int i = 0, num = 0;
+
+	if (wpa_s->conf == NULL) {
+		wpa_printf(MSG_ERROR, "wpas_dbus_getter_networks[dbus]: "
+			   "An error occurred getting networks list.");
+		return wpas_dbus_error_unknown_error(message, NULL);
+	}
+
+	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
+		num++;
+
+	paths = os_zalloc(num * sizeof(char *));
+	if (!paths) {
+		return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					      NULL);
+	}
+
+	/* Loop through configured networks and append object path of each */
+	for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
+		paths[i] = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
+		if (paths[i] == NULL) {
+			reply = dbus_message_new_error(message,
+						       DBUS_ERROR_NO_MEMORY,
+						       NULL);
+			goto out;
+		}
+
+		/* Construct the object path for this network. */
+		os_snprintf(paths[i++], WPAS_DBUS_OBJECT_PATH_MAX,
+			    "%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
+			    wpa_s->dbus_new_path, ssid->id);
+	}
+
+	reply = wpas_dbus_simple_array_property_getter(message,
+						       DBUS_TYPE_OBJECT_PATH,
+						       paths, num);
+
+out:
+	while (i)
+		os_free(paths[--i]);
+	os_free(paths);
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_getter_blobs - Get all blobs defined for this interface
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: a dbus message containing a dictionary of pairs (blob_name, blob)
+ *
+ * Getter for "Blobs" property.
+ */
+DBusMessage * wpas_dbus_getter_blobs(DBusMessage *message,
+				     struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply = NULL;
+	DBusMessageIter iter, variant_iter, dict_iter, entry_iter, array_iter;
+	struct wpa_config_blob *blob;
+
+	if (message == NULL)
+		reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
+	else
+		reply = dbus_message_new_method_return(message);
+	if (!reply)
+		return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					      NULL);
+
+	dbus_message_iter_init_append(reply, &iter);
+
+	if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
+					      "a{say}", &variant_iter) ||
+	    !dbus_message_iter_open_container(&variant_iter, DBUS_TYPE_ARRAY,
+					      "{say}", &dict_iter)) {
+		dbus_message_unref(reply);
+		return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					      NULL);
+	}
+
+	blob = wpa_s->conf->blobs;
+	while (blob) {
+		if (!dbus_message_iter_open_container(&dict_iter,
+						      DBUS_TYPE_DICT_ENTRY,
+						      NULL, &entry_iter) ||
+		    !dbus_message_iter_append_basic(&entry_iter,
+						    DBUS_TYPE_STRING,
+						    &(blob->name)) ||
+		    !dbus_message_iter_open_container(&entry_iter,
+						      DBUS_TYPE_ARRAY,
+						      DBUS_TYPE_BYTE_AS_STRING,
+						      &array_iter) ||
+		    !dbus_message_iter_append_fixed_array(&array_iter,
+							  DBUS_TYPE_BYTE,
+							  &(blob->data),
+							  blob->len) ||
+		    !dbus_message_iter_close_container(&entry_iter,
+						       &array_iter) ||
+		    !dbus_message_iter_close_container(&dict_iter,
+						       &entry_iter)) {
+			dbus_message_unref(reply);
+			return dbus_message_new_error(message,
+						      DBUS_ERROR_NO_MEMORY,
+						      NULL);
+		}
+
+		blob = blob->next;
+	}
+
+	if (!dbus_message_iter_close_container(&variant_iter, &dict_iter) ||
+	    !dbus_message_iter_close_container(&iter, &variant_iter)) {
+		dbus_message_unref(reply);
+		return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					      NULL);
+	}
+
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_getter_bss_bssid - Return the BSSID of a BSS
+ * @message: Pointer to incoming dbus message
+ * @bss: a pair of interface describing structure and bss's id
+ * Returns: a dbus message containing the bssid for the requested bss
+ *
+ * Getter for "BSSID" property.
+ */
+DBusMessage * wpas_dbus_getter_bss_bssid(DBusMessage *message,
+					 struct bss_handler_args *bss)
+{
+	struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
+
+	if (!res) {
+		wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_bssid[dbus]: no "
+			   "bss with id %d found", bss->id);
+		return NULL;
+	}
+
+	return wpas_dbus_simple_array_property_getter(message, DBUS_TYPE_BYTE,
+						      res->bssid, ETH_ALEN);
+}
+
+
+/**
+ * wpas_dbus_getter_bss_ssid - Return the SSID of a BSS
+ * @message: Pointer to incoming dbus message
+ * @bss: a pair of interface describing structure and bss's id
+ * Returns: a dbus message containing the ssid for the requested bss
+ *
+ * Getter for "SSID" property.
+ */
+DBusMessage * wpas_dbus_getter_bss_ssid(DBusMessage *message,
+					      struct bss_handler_args *bss)
+{
+	struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
+
+	if (!res) {
+		wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_ssid[dbus]: no "
+			   "bss with id %d found", bss->id);
+		return NULL;
+	}
+
+	return wpas_dbus_simple_array_property_getter(message, DBUS_TYPE_BYTE,
+						      res->ssid,
+						      res->ssid_len);
+}
+
+
+/**
+ * wpas_dbus_getter_bss_privacy - Return the privacy flag of a BSS
+ * @message: Pointer to incoming dbus message
+ * @bss: a pair of interface describing structure and bss's id
+ * Returns: a dbus message containing the privacy flag value of requested bss
+ *
+ * Getter for "Privacy" property.
+ */
+DBusMessage * wpas_dbus_getter_bss_privacy(DBusMessage *message,
+					   struct bss_handler_args *bss)
+{
+	struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
+	dbus_bool_t privacy;
+
+	if (!res) {
+		wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_privacy[dbus]: no "
+			   "bss with id %d found", bss->id);
+		return NULL;
+	}
+
+	privacy = (res->caps & IEEE80211_CAP_PRIVACY) ? TRUE : FALSE;
+	return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN,
+						&privacy);
+}
+
+
+/**
+ * wpas_dbus_getter_bss_mode - Return the mode of a BSS
+ * @message: Pointer to incoming dbus message
+ * @bss: a pair of interface describing structure and bss's id
+ * Returns: a dbus message containing the mode of requested bss
+ *
+ * Getter for "Mode" property.
+ */
+DBusMessage * wpas_dbus_getter_bss_mode(DBusMessage *message,
+					struct bss_handler_args *bss)
+{
+	struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
+	const char *mode;
+
+	if (!res) {
+		wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_mode[dbus]: no "
+			   "bss with id %d found", bss->id);
+		return NULL;
+	}
+
+	if (res->caps & IEEE80211_CAP_IBSS)
+		mode = "ad-hoc";
+	else
+		mode = "infrastructure";
+
+	return wpas_dbus_simple_property_getter(message, DBUS_TYPE_STRING,
+						&mode);
+}
+
+
+/**
+ * wpas_dbus_getter_bss_level - Return the signal strength of a BSS
+ * @message: Pointer to incoming dbus message
+ * @bss: a pair of interface describing structure and bss's id
+ * Returns: a dbus message containing the signal strength of requested bss
+ *
+ * Getter for "Level" property.
+ */
+DBusMessage * wpas_dbus_getter_bss_signal(DBusMessage *message,
+					  struct bss_handler_args *bss)
+{
+	struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
+
+	if (!res) {
+		wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_signal[dbus]: no "
+			   "bss with id %d found", bss->id);
+		return NULL;
+	}
+
+	return wpas_dbus_simple_property_getter(message, DBUS_TYPE_INT16,
+						&res->level);
+}
+
+
+/**
+ * wpas_dbus_getter_bss_frequency - Return the frequency of a BSS
+ * @message: Pointer to incoming dbus message
+ * @bss: a pair of interface describing structure and bss's id
+ * Returns: a dbus message containing the frequency of requested bss
+ *
+ * Getter for "Frequency" property.
+ */
+DBusMessage * wpas_dbus_getter_bss_frequency(DBusMessage *message,
+					     struct bss_handler_args *bss)
+{
+	struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
+
+	if (!res) {
+		wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_frequency[dbus]: "
+			   "no bss with id %d found", bss->id);
+		return NULL;
+	}
+
+	return wpas_dbus_simple_property_getter(message, DBUS_TYPE_UINT16,
+						&res->freq);
+}
+
+
+static int cmp_u8s_desc(const void *a, const void *b)
+{
+	return (*(u8 *) b - *(u8 *) a);
+}
+
+
+/**
+ * wpas_dbus_getter_bss_rates - Return available bit rates of a BSS
+ * @message: Pointer to incoming dbus message
+ * @bss: a pair of interface describing structure and bss's id
+ * Returns: a dbus message containing sorted array of bit rates
+ *
+ * Getter for "Rates" property.
+ */
+DBusMessage * wpas_dbus_getter_bss_rates(DBusMessage *message,
+					    struct bss_handler_args *bss)
+{
+	DBusMessage *reply;
+	struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
+	u8 *ie_rates = NULL;
+	u32 *real_rates;
+	int rates_num, i;
+
+	if (!res) {
+		wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_rates[dbus]: "
+			   "no bss with id %d found", bss->id);
+		return NULL;
+	}
+
+	rates_num = wpa_bss_get_bit_rates(res, &ie_rates);
+	if (rates_num < 0)
+		return NULL;
+
+	qsort(ie_rates, rates_num, 1, cmp_u8s_desc);
+
+	real_rates = os_malloc(sizeof(u32) * rates_num);
+	if (!real_rates) {
+		os_free(ie_rates);
+		return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					      NULL);
+	}
+
+	for (i = 0; i < rates_num; i++)
+		real_rates[i] = ie_rates[i] * 500000;
+
+	reply = wpas_dbus_simple_array_property_getter(message,
+						       DBUS_TYPE_UINT32,
+						       real_rates, rates_num);
+
+	os_free(ie_rates);
+	os_free(real_rates);
+	return reply;
+}
+
+
+static DBusMessage * wpas_dbus_get_bss_security_prop(
+	DBusMessage *message, struct wpa_ie_data *ie_data)
+{
+	DBusMessage *reply;
+	DBusMessageIter iter, iter_dict, variant_iter;
+	const char *group;
+	const char *pairwise[2]; /* max 2 pairwise ciphers is supported */
+	const char *key_mgmt[7]; /* max 7 key managements may be supported */
+	int n;
+
+	if (message == NULL)
+		reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
+	else
+		reply = dbus_message_new_method_return(message);
+	if (!reply)
+		goto nomem;
+
+	dbus_message_iter_init_append(reply, &iter);
+	if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
+					      "a{sv}", &variant_iter))
+		goto nomem;
+
+	if (!wpa_dbus_dict_open_write(&variant_iter, &iter_dict))
+		goto nomem;
+
+	/* KeyMgmt */
+	n = 0;
+	if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK)
+		key_mgmt[n++] = "wpa-psk";
+	if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_PSK)
+		key_mgmt[n++] = "wpa-ft-psk";
+	if (ie_data->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
+		key_mgmt[n++] = "wpa-psk-sha256";
+	if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X)
+		key_mgmt[n++] = "wpa-eap";
+	if (ie_data->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
+		key_mgmt[n++] = "wpa-ft-eap";
+	if (ie_data->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
+		key_mgmt[n++] = "wpa-eap-sha256";
+	if (ie_data->key_mgmt & WPA_KEY_MGMT_NONE)
+		key_mgmt[n++] = "wpa-none";
+
+	if (!wpa_dbus_dict_append_string_array(&iter_dict, "KeyMgmt",
+					       key_mgmt, n))
+		goto nomem;
+
+	/* Group */
+	switch (ie_data->group_cipher) {
+	case WPA_CIPHER_WEP40:
+		group = "wep40";
+		break;
+	case WPA_CIPHER_TKIP:
+		group = "tkip";
+		break;
+	case WPA_CIPHER_CCMP:
+		group = "ccmp";
+		break;
+	case WPA_CIPHER_WEP104:
+		group = "wep104";
+		break;
+	default:
+		group = "";
+		break;
+	}
+
+	if (!wpa_dbus_dict_append_string(&iter_dict, "Group", group))
+		goto nomem;
+
+	/* Pairwise */
+	n = 0;
+	if (ie_data->pairwise_cipher & WPA_CIPHER_TKIP)
+		pairwise[n++] = "tkip";
+	if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP)
+		pairwise[n++] = "ccmp";
+
+	if (!wpa_dbus_dict_append_string_array(&iter_dict, "Pairwise",
+					       pairwise, n))
+		goto nomem;
+
+	/* Management group (RSN only) */
+	if (ie_data->proto == WPA_PROTO_RSN) {
+		switch (ie_data->mgmt_group_cipher) {
+#ifdef CONFIG_IEEE80211W
+		case WPA_CIPHER_AES_128_CMAC:
+			group = "aes128cmac";
+			break;
+#endif /* CONFIG_IEEE80211W */
+		default:
+			group = "";
+			break;
+		}
+
+		if (!wpa_dbus_dict_append_string(&iter_dict, "MgmtGroup",
+						 group))
+			goto nomem;
+	}
+
+	if (!wpa_dbus_dict_close_write(&variant_iter, &iter_dict))
+		goto nomem;
+	if (!dbus_message_iter_close_container(&iter, &variant_iter))
+		goto nomem;
+
+	return reply;
+
+nomem:
+	if (reply)
+		dbus_message_unref(reply);
+
+	return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY, NULL);
+}
+
+
+/**
+ * wpas_dbus_getter_bss_wpa - Return the WPA options of a BSS
+ * @message: Pointer to incoming dbus message
+ * @bss: a pair of interface describing structure and bss's id
+ * Returns: a dbus message containing the WPA options of requested bss
+ *
+ * Getter for "WPA" property.
+ */
+DBusMessage * wpas_dbus_getter_bss_wpa(DBusMessage *message,
+				       struct bss_handler_args *bss)
+{
+	struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
+	struct wpa_ie_data wpa_data;
+	const u8 *ie;
+
+	if (!res) {
+		wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_wpa[dbus]: no "
+			   "bss with id %d found", bss->id);
+		return NULL;
+	}
+
+	os_memset(&wpa_data, 0, sizeof(wpa_data));
+	ie = wpa_bss_get_vendor_ie(res, WPA_IE_VENDOR_TYPE);
+	if (ie) {
+		if (wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0)
+			return wpas_dbus_error_unknown_error(message,
+							     "invalid WPA IE");
+	}
+
+	return wpas_dbus_get_bss_security_prop(message, &wpa_data);
+}
+
+
+/**
+ * wpas_dbus_getter_bss_rsn - Return the RSN options of a BSS
+ * @message: Pointer to incoming dbus message
+ * @bss: a pair of interface describing structure and bss's id
+ * Returns: a dbus message containing the RSN options of requested bss
+ *
+ * Getter for "RSN" property.
+ */
+DBusMessage * wpas_dbus_getter_bss_rsn(DBusMessage *message,
+				       struct bss_handler_args *bss)
+{
+	struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
+	struct wpa_ie_data wpa_data;
+	const u8 *ie;
+
+	if (!res) {
+		wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_rsn[dbus]: no "
+			   "bss with id %d found", bss->id);
+		return NULL;
+	}
+
+	os_memset(&wpa_data, 0, sizeof(wpa_data));
+	ie = wpa_bss_get_ie(res, WLAN_EID_RSN);
+	if (ie) {
+		if (wpa_parse_wpa_ie(ie, 2 + ie[1], &wpa_data) < 0)
+			return wpas_dbus_error_unknown_error(message,
+							     "invalid RSN IE");
+	}
+
+	return wpas_dbus_get_bss_security_prop(message, &wpa_data);
+}
+
+
+/**
+ * wpas_dbus_getter_bss_ies - Return all IEs of a BSS
+ * @message: Pointer to incoming dbus message
+ * @bss: a pair of interface describing structure and bss's id
+ * Returns: a dbus message containing IEs byte array
+ *
+ * Getter for "IEs" property.
+ */
+DBusMessage * wpas_dbus_getter_bss_ies(DBusMessage *message,
+				       struct bss_handler_args *bss)
+{
+	struct wpa_bss *res = wpa_bss_get_id(bss->wpa_s, bss->id);
+
+	if (!res) {
+		wpa_printf(MSG_ERROR, "wpas_dbus_getter_bss_ies[dbus]: no "
+			   "bss with id %d found", bss->id);
+		return NULL;
+	}
+
+	return wpas_dbus_simple_array_property_getter(message, DBUS_TYPE_BYTE,
+						      res + 1, res->ie_len);
+}
+
+
+/**
+ * wpas_dbus_getter_enabled - Check whether network is enabled or disabled
+ * @message: Pointer to incoming dbus message
+ * @wpas_dbus_setter_enabled: wpa_supplicant structure for a network interface
+ * and wpa_ssid structure for a configured network
+ * Returns: DBus message with boolean indicating state of configured network
+ * or DBus error on failure
+ *
+ * Getter for "enabled" property of a configured network.
+ */
+DBusMessage * wpas_dbus_getter_enabled(DBusMessage *message,
+				       struct network_handler_args *net)
+{
+	dbus_bool_t enabled = net->ssid->disabled ? FALSE : TRUE;
+	return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN,
+						&enabled);
+}
+
+
+/**
+ * wpas_dbus_setter_enabled - Mark a configured network as enabled or disabled
+ * @message: Pointer to incoming dbus message
+ * @wpas_dbus_setter_enabled: wpa_supplicant structure for a network interface
+ * and wpa_ssid structure for a configured network
+ * Returns: NULL indicating success or DBus error on failure
+ *
+ * Setter for "Enabled" property of a configured network.
+ */
+DBusMessage * wpas_dbus_setter_enabled(DBusMessage *message,
+				       struct network_handler_args *net)
+{
+	DBusMessage *reply = NULL;
+
+	struct wpa_supplicant *wpa_s;
+	struct wpa_ssid *ssid;
+
+	dbus_bool_t enable;
+
+	reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_BOOLEAN,
+						 &enable);
+
+	if (reply)
+		return reply;
+
+	wpa_s = net->wpa_s;
+	ssid = net->ssid;
+
+	if (enable)
+		wpa_supplicant_enable_network(wpa_s, ssid);
+	else
+		wpa_supplicant_disable_network(wpa_s, ssid);
+
+	return NULL;
+}
+
+
+/**
+ * wpas_dbus_getter_network_properties - Get options for a configured network
+ * @message: Pointer to incoming dbus message
+ * @net: wpa_supplicant structure for a network interface and
+ * wpa_ssid structure for a configured network
+ * Returns: DBus message with network properties or DBus error on failure
+ *
+ * Getter for "Properties" property of a configured network.
+ */
+DBusMessage * wpas_dbus_getter_network_properties(
+	DBusMessage *message, struct network_handler_args *net)
+{
+	DBusMessage *reply = NULL;
+	DBusMessageIter	iter, variant_iter, dict_iter;
+	char **iterator;
+	char **props = wpa_config_get_all(net->ssid, 1);
+	if (!props)
+		return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					      NULL);
+
+	if (message == NULL)
+		reply = dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL);
+	else
+		reply = dbus_message_new_method_return(message);
+	if (!reply) {
+		reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					       NULL);
+		goto out;
+	}
+
+	dbus_message_iter_init_append(reply, &iter);
+
+	if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
+			"a{sv}", &variant_iter) ||
+	    !wpa_dbus_dict_open_write(&variant_iter, &dict_iter)) {
+		dbus_message_unref(reply);
+		reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					       NULL);
+		goto out;
+	}
+
+	iterator = props;
+	while (*iterator) {
+		if (!wpa_dbus_dict_append_string(&dict_iter, *iterator,
+						 *(iterator + 1))) {
+			dbus_message_unref(reply);
+			reply = dbus_message_new_error(message,
+						       DBUS_ERROR_NO_MEMORY,
+						       NULL);
+			goto out;
+		}
+		iterator += 2;
+	}
+
+
+	if (!wpa_dbus_dict_close_write(&variant_iter, &dict_iter) ||
+	    !dbus_message_iter_close_container(&iter, &variant_iter)) {
+		dbus_message_unref(reply);
+		reply = dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					       NULL);
+		goto out;
+	}
+
+out:
+	iterator = props;
+	while (*iterator) {
+		os_free(*iterator);
+		iterator++;
+	}
+	os_free(props);
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_setter_network_properties - Set options for a configured network
+ * @message: Pointer to incoming dbus message
+ * @net: wpa_supplicant structure for a network interface and
+ * wpa_ssid structure for a configured network
+ * Returns: NULL indicating success or DBus error on failure
+ *
+ * Setter for "Properties" property of a configured network.
+ */
+DBusMessage * wpas_dbus_setter_network_properties(
+	DBusMessage *message, struct network_handler_args *net)
+{
+	struct wpa_ssid *ssid = net->ssid;
+
+	DBusMessage *reply = NULL;
+	DBusMessageIter	iter, variant_iter;
+
+	dbus_message_iter_init(message, &iter);
+
+	dbus_message_iter_next(&iter);
+	dbus_message_iter_next(&iter);
+
+	dbus_message_iter_recurse(&iter, &variant_iter);
+
+	reply = set_network_properties(message, net->wpa_s, ssid,
+				       &variant_iter);
+	if (reply)
+		wpa_printf(MSG_DEBUG, "dbus control interface couldn't set "
+			   "network properties");
+
+	return reply;
+}
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.h b/wpa_supplicant/dbus/dbus_new_handlers.h
new file mode 100644
index 0000000..742d33c
--- /dev/null
+++ b/wpa_supplicant/dbus/dbus_new_handlers.h
@@ -0,0 +1,223 @@
+/*
+ * WPA Supplicant / dbus-based control interface
+ * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
+ * Copyright (c) 2009-2010, 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.
+ */
+
+#ifndef CTRL_IFACE_DBUS_NEW_HANDLERS_H
+#define CTRL_IFACE_DBUS_NEW_HANDLERS_H
+
+struct network_handler_args {
+	struct wpa_supplicant *wpa_s;
+	struct wpa_ssid *ssid;
+};
+
+struct bss_handler_args {
+	struct wpa_supplicant *wpa_s;
+	unsigned int id;
+};
+
+DBusMessage * wpas_dbus_simple_property_getter(DBusMessage *message,
+					       const int type,
+					       const void *val);
+
+DBusMessage * wpas_dbus_simple_property_setter(DBusMessage *message,
+					       const int type, void *val);
+
+DBusMessage * wpas_dbus_simple_array_property_getter(DBusMessage *message,
+						     const int type,
+						     const void *array,
+						     size_t array_len);
+
+DBusMessage * wpas_dbus_handler_create_interface(DBusMessage *message,
+						 struct wpa_global *global);
+
+DBusMessage * wpas_dbus_handler_remove_interface(DBusMessage *message,
+						 struct wpa_global *global);
+
+DBusMessage * wpas_dbus_handler_get_interface(DBusMessage *message,
+					      struct wpa_global *global);
+
+DBusMessage * wpas_dbus_getter_debug_level(DBusMessage *message,
+					   struct wpa_global *global);
+
+DBusMessage * wpas_dbus_getter_debug_timestamp(DBusMessage *message,
+					       struct wpa_global *global);
+
+DBusMessage * wpas_dbus_getter_debug_show_keys(DBusMessage *message,
+					       struct wpa_global *global);
+
+DBusMessage * wpas_dbus_setter_debug_level(DBusMessage *message,
+					   struct wpa_global *global);
+
+DBusMessage * wpas_dbus_setter_debug_timestamp(DBusMessage *message,
+					       struct wpa_global *global);
+
+DBusMessage * wpas_dbus_setter_debug_show_keys(DBusMessage *message,
+					       struct wpa_global *global);
+
+DBusMessage * wpas_dbus_getter_interfaces(DBusMessage *message,
+					  struct wpa_global *global);
+
+DBusMessage * wpas_dbus_getter_eap_methods(DBusMessage *message,
+					   void *nothing);
+
+DBusMessage * wpas_dbus_handler_scan(DBusMessage *message,
+				     struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_handler_disconnect(DBusMessage *message,
+					   struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_handler_add_network(DBusMessage *message,
+					    struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_handler_remove_network(DBusMessage *message,
+					       struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_handler_remove_all_networks(
+	DBusMessage *message, struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message,
+					       struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message,
+					 struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_handler_get_blob(DBusMessage *message,
+					 struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_handler_remove_blob(DBusMessage *message,
+					    struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_handler_flush_bss(DBusMessage *message,
+					  struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_getter_capabilities(DBusMessage *message,
+					    struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_getter_state(DBusMessage *message,
+				     struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_getter_scanning(DBusMessage *message,
+					struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_getter_ap_scan(DBusMessage *message,
+				       struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_setter_ap_scan(DBusMessage *message,
+				       struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_getter_bss_expire_age(DBusMessage *message,
+					      struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_setter_bss_expire_age(DBusMessage *message,
+					      struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_getter_bss_expire_count(DBusMessage *message,
+						struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_setter_bss_expire_count(DBusMessage *message,
+						struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_getter_country(DBusMessage *message,
+				       struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_setter_country(DBusMessage *message,
+				       struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_getter_ifname(DBusMessage *message,
+				      struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_getter_driver(DBusMessage *message,
+				      struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_getter_bridge_ifname(DBusMessage *message,
+					     struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_getter_current_bss(DBusMessage *message,
+					   struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_getter_current_network(DBusMessage *message,
+					       struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_getter_current_auth_mode(DBusMessage *message,
+						 struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_getter_bsss(DBusMessage *message,
+				    struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_getter_networks(DBusMessage *message,
+					struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_getter_blobs(DBusMessage *message,
+				     struct wpa_supplicant *bss);
+
+DBusMessage * wpas_dbus_getter_bss_bssid(DBusMessage *message,
+					 struct bss_handler_args *bss);
+
+DBusMessage * wpas_dbus_getter_bss_ssid(DBusMessage *message,
+					struct bss_handler_args *bss);
+
+DBusMessage * wpas_dbus_getter_bss_privacy(DBusMessage *message,
+					   struct bss_handler_args *bss);
+
+DBusMessage * wpas_dbus_getter_bss_mode(DBusMessage *message,
+					struct bss_handler_args *bss);
+
+DBusMessage * wpas_dbus_getter_bss_signal(DBusMessage *message,
+					  struct bss_handler_args *bss);
+
+DBusMessage * wpas_dbus_getter_bss_frequency(DBusMessage *message,
+					     struct bss_handler_args *bss);
+
+DBusMessage * wpas_dbus_getter_bss_rates(DBusMessage *message,
+					 struct bss_handler_args *bss);
+
+DBusMessage * wpas_dbus_getter_bss_wpa(DBusMessage *message,
+				       struct bss_handler_args *bss);
+
+DBusMessage * wpas_dbus_getter_bss_rsn(DBusMessage *message,
+				       struct bss_handler_args *bss);
+
+DBusMessage * wpas_dbus_getter_bss_ies(DBusMessage *message,
+				       struct bss_handler_args *bss);
+
+DBusMessage * wpas_dbus_getter_enabled(DBusMessage *message,
+				       struct network_handler_args *net);
+
+DBusMessage * wpas_dbus_setter_enabled(DBusMessage *message,
+				       struct network_handler_args *net);
+
+DBusMessage * wpas_dbus_getter_network_properties(
+	DBusMessage *message, struct network_handler_args *net);
+
+DBusMessage * wpas_dbus_setter_network_properties(
+	DBusMessage *message, struct network_handler_args *net);
+
+DBusMessage * wpas_dbus_handler_wps_start(DBusMessage *message,
+					  struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_getter_process_credentials(
+	DBusMessage *message, struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_setter_process_credentials(
+	DBusMessage *message, struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_getter_credentials(DBusMessage *message,
+					   struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_error_invalid_args(DBusMessage *message,
+					   const char *arg);
+DBusMessage * wpas_dbus_error_unknown_error(DBusMessage *message,
+					    const char *arg);
+
+#endif /* CTRL_IFACE_DBUS_HANDLERS_NEW_H */
diff --git a/wpa_supplicant/dbus/dbus_new_handlers_wps.c b/wpa_supplicant/dbus/dbus_new_handlers_wps.c
new file mode 100644
index 0000000..c118d73
--- /dev/null
+++ b/wpa_supplicant/dbus/dbus_new_handlers_wps.c
@@ -0,0 +1,332 @@
+/*
+ * WPA Supplicant / dbus-based control interface (WPS)
+ * 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 "includes.h"
+
+#include "common.h"
+#include "../config.h"
+#include "../wpa_supplicant_i.h"
+#include "../wps_supplicant.h"
+#include "dbus_new_helpers.h"
+#include "dbus_new.h"
+#include "dbus_new_handlers.h"
+#include "dbus_dict_helpers.h"
+
+
+struct wps_start_params {
+	int role; /* 0 - not set, 1 - enrollee, 2 - registrar */
+	int type; /* 0 - not set, 1 - pin,      2 - pbc       */
+	u8 *bssid;
+	char *pin;
+};
+
+
+static int wpas_dbus_handler_wps_role(DBusMessage *message,
+				      DBusMessageIter *entry_iter,
+				      struct wps_start_params *params,
+				      DBusMessage **reply)
+{
+	DBusMessageIter variant_iter;
+	char *val;
+
+	dbus_message_iter_recurse(entry_iter, &variant_iter);
+	if (dbus_message_iter_get_arg_type(&variant_iter) !=
+	    DBUS_TYPE_STRING) {
+		wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Wrong Role type, "
+			   "string required");
+		*reply = wpas_dbus_error_invalid_args(message,
+						      "Role must be a string");
+		return -1;
+	}
+	dbus_message_iter_get_basic(&variant_iter, &val);
+	if (os_strcmp(val, "enrollee") == 0)
+		params->role = 1;
+	else if (os_strcmp(val, "registrar") == 0)
+		params->role = 2;
+	else {
+		wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Uknown role %s", val);
+		*reply = wpas_dbus_error_invalid_args(message, val);
+		return -1;
+	}
+	return 0;
+}
+
+
+static int wpas_dbus_handler_wps_type(DBusMessage *message,
+				      DBusMessageIter *entry_iter,
+				      struct wps_start_params *params,
+				      DBusMessage **reply)
+{
+	DBusMessageIter variant_iter;
+	char *val;
+
+	dbus_message_iter_recurse(entry_iter, &variant_iter);
+	if (dbus_message_iter_get_arg_type(&variant_iter) !=
+	    DBUS_TYPE_STRING) {
+		wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Wrong Type type, "
+			   "string required");
+		*reply = wpas_dbus_error_invalid_args(message,
+						      "Type must be a string");
+		return -1;
+	}
+	dbus_message_iter_get_basic(&variant_iter, &val);
+	if (os_strcmp(val, "pin") == 0)
+		params->type = 1;
+	else if (os_strcmp(val, "pbc") == 0)
+		params->type = 2;
+	else {
+		wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Unknown type %s",
+			   val);
+		*reply = wpas_dbus_error_invalid_args(message, val);
+		return -1;
+	}
+	return 0;
+}
+
+
+static int wpas_dbus_handler_wps_bssid(DBusMessage *message,
+				       DBusMessageIter *entry_iter,
+				       struct wps_start_params *params,
+				       DBusMessage **reply)
+{
+	DBusMessageIter variant_iter, array_iter;
+	int len;
+
+	dbus_message_iter_recurse(entry_iter, &variant_iter);
+	if (dbus_message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_ARRAY ||
+	    dbus_message_iter_get_element_type(&variant_iter) !=
+	    DBUS_TYPE_BYTE) {
+		wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Wrong Bssid type, "
+			   "byte array required");
+		*reply = wpas_dbus_error_invalid_args(
+			message, "Bssid must be a byte array");
+		return -1;
+	}
+	dbus_message_iter_recurse(&variant_iter, &array_iter);
+	dbus_message_iter_get_fixed_array(&array_iter, &params->bssid, &len);
+	if (len != ETH_ALEN) {
+		wpa_printf(MSG_DEBUG, "dbus: WPS.Stsrt - Wrong Bssid length "
+			   "%d", len);
+		*reply = wpas_dbus_error_invalid_args(message,
+						      "Bssid is wrong length");
+		return -1;
+	}
+	return 0;
+}
+
+
+static int wpas_dbus_handler_wps_pin(DBusMessage *message,
+				     DBusMessageIter *entry_iter,
+				     struct wps_start_params *params,
+				     DBusMessage **reply)
+{
+	DBusMessageIter variant_iter;
+
+	dbus_message_iter_recurse(entry_iter, &variant_iter);
+	if (dbus_message_iter_get_arg_type(&variant_iter) !=
+	    DBUS_TYPE_STRING) {
+		wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Wrong Pin type, "
+			   "string required");
+		*reply = wpas_dbus_error_invalid_args(message,
+						      "Pin must be a string");
+		return -1;
+	}
+	dbus_message_iter_get_basic(&variant_iter, &params->pin);
+	return 0;
+}
+
+
+static int wpas_dbus_handler_wps_start_entry(DBusMessage *message, char *key,
+					     DBusMessageIter *entry_iter,
+					     struct wps_start_params *params,
+					     DBusMessage **reply)
+{
+	if (os_strcmp(key, "Role") == 0)
+		return wpas_dbus_handler_wps_role(message, entry_iter,
+						  params, reply);
+	else if (os_strcmp(key, "Type") == 0)
+		return wpas_dbus_handler_wps_type(message, entry_iter,
+						  params, reply);
+	else if (os_strcmp(key, "Bssid") == 0)
+		return wpas_dbus_handler_wps_bssid(message, entry_iter,
+						   params, reply);
+	else if (os_strcmp(key, "Pin") == 0)
+		return wpas_dbus_handler_wps_pin(message, entry_iter,
+						 params, reply);
+
+	wpa_printf(MSG_DEBUG, "dbus: WPS.Start - unknown key %s", key);
+	*reply = wpas_dbus_error_invalid_args(message, key);
+	return -1;
+}
+
+
+/**
+ * wpas_dbus_handler_wps_start - Start WPS configuration
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: %wpa_supplicant data structure
+ * Returns: DBus message dictionary on success or DBus error on failure
+ *
+ * Handler for "Start" method call. DBus dictionary argument contains
+ * information about role (enrollee or registrar), authorization method
+ * (pin or push button) and optionally pin and bssid. Returned message
+ * has a dictionary argument which may contain newly generated pin (optional).
+ */
+DBusMessage * wpas_dbus_handler_wps_start(DBusMessage *message,
+					  struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply = NULL;
+	DBusMessageIter iter, dict_iter, entry_iter;
+	struct wps_start_params params;
+	char *key;
+	char npin[9] = { '\0' };
+	int ret;
+
+	os_memset(&params, 0, sizeof(params));
+	dbus_message_iter_init(message, &iter);
+
+	dbus_message_iter_recurse(&iter, &dict_iter);
+	while (dbus_message_iter_get_arg_type(&dict_iter) ==
+	       DBUS_TYPE_DICT_ENTRY) {
+		dbus_message_iter_recurse(&dict_iter, &entry_iter);
+
+		dbus_message_iter_get_basic(&entry_iter, &key);
+		dbus_message_iter_next(&entry_iter);
+
+		if (wpas_dbus_handler_wps_start_entry(message, key,
+						      &entry_iter,
+						      &params, &reply))
+			return reply;
+
+		dbus_message_iter_next(&dict_iter);
+	}
+
+	if (params.role == 0) {
+		wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Role not specified");
+		return wpas_dbus_error_invalid_args(message,
+						    "Role not specified");
+	} else if (params.role == 1 && params.type == 0) {
+		wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Type not specified");
+		return wpas_dbus_error_invalid_args(message,
+						    "Type not specified");
+	} else if (params.role == 2 && params.pin == NULL) {
+		wpa_printf(MSG_DEBUG, "dbus: WPS.Start - Pin required for "
+			   "registrar role");
+		return wpas_dbus_error_invalid_args(
+			message, "Pin required for registrar role.");
+	}
+
+	if (params.role == 2)
+		ret = wpas_wps_start_reg(wpa_s, params.bssid, params.pin,
+					 NULL);
+	else if (params.type == 1) {
+		ret = wpas_wps_start_pin(wpa_s, params.bssid, params.pin, 0,
+					 DEV_PW_DEFAULT);
+		if (ret > 0)
+			os_snprintf(npin, sizeof(npin), "%08d", ret);
+	} else
+		ret = wpas_wps_start_pbc(wpa_s, params.bssid, 0);
+
+	if (ret < 0) {
+		wpa_printf(MSG_DEBUG, "dbus: WPS.Start wpas_wps_failed in "
+			   "role %s and key %s",
+			   (params.role == 1 ? "enrollee" : "registrar"),
+			   (params.type == 0 ? "" :
+			    (params.type == 1 ? "pin" : "pbc")));
+		return wpas_dbus_error_unknown_error(message,
+						     "WPS start failed");
+	}
+
+	reply = dbus_message_new_method_return(message);
+	if (!reply) {
+		return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					      NULL);
+	}
+
+	dbus_message_iter_init_append(reply, &iter);
+	if (!wpa_dbus_dict_open_write(&iter, &dict_iter)) {
+		dbus_message_unref(reply);
+		return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					      NULL);
+	}
+
+	if (os_strlen(npin) > 0) {
+		if (!wpa_dbus_dict_append_string(&dict_iter, "Pin", npin)) {
+			dbus_message_unref(reply);
+			return dbus_message_new_error(message,
+						      DBUS_ERROR_NO_MEMORY,
+						      NULL);
+		}
+	}
+
+	if (!wpa_dbus_dict_close_write(&iter, &dict_iter)) {
+		dbus_message_unref(reply);
+		return dbus_message_new_error(message, DBUS_ERROR_NO_MEMORY,
+					      NULL);
+	}
+
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_getter_process_credentials - Check if credentials are processed
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: %wpa_supplicant data structure
+ * Returns: DBus message with a boolean on success or DBus error on failure
+ *
+ * Getter for "ProcessCredentials" property. Returns returned boolean will be
+ * true if wps_cred_processing configuration field is not equal to 1 or false
+ * if otherwise.
+ */
+DBusMessage * wpas_dbus_getter_process_credentials(
+	DBusMessage *message, struct wpa_supplicant *wpa_s)
+{
+	dbus_bool_t process = (wpa_s->conf->wps_cred_processing != 1);
+	return wpas_dbus_simple_property_getter(message, DBUS_TYPE_BOOLEAN,
+						&process);
+}
+
+
+/**
+ * wpas_dbus_setter_process_credentials - Set credentials_processed conf param
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: %wpa_supplicant data structure
+ * Returns: NULL on success or DBus error on failure
+ *
+ * Setter for "ProcessCredentials" property. Sets credentials_processed on 2
+ * if boolean argument is true or on 1 if otherwise.
+ */
+DBusMessage * wpas_dbus_setter_process_credentials(
+	DBusMessage *message, struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply = NULL;
+	dbus_bool_t process_credentials, old_pc;
+
+	reply = wpas_dbus_simple_property_setter(message, DBUS_TYPE_BOOLEAN,
+						 &process_credentials);
+	if (reply)
+		return reply;
+
+	old_pc = (wpa_s->conf->wps_cred_processing != 1);
+	wpa_s->conf->wps_cred_processing = (process_credentials ? 2 : 1);
+
+	if ((wpa_s->conf->wps_cred_processing != 1) != old_pc)
+		wpa_dbus_mark_property_changed(wpa_s->global->dbus,
+					       wpa_s->dbus_new_path,
+					       WPAS_DBUS_NEW_IFACE_WPS,
+					       "ProcessCredentials");
+
+	return NULL;
+}
diff --git a/wpa_supplicant/dbus/dbus_new_helpers.c b/wpa_supplicant/dbus/dbus_new_helpers.c
new file mode 100644
index 0000000..6e6e842
--- /dev/null
+++ b/wpa_supplicant/dbus/dbus_new_helpers.c
@@ -0,0 +1,886 @@
+/*
+ * 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 "utils/common.h"
+#include "utils/eloop.h"
+#include "dbus_common.h"
+#include "dbus_common_i.h"
+#include "dbus_new.h"
+#include "dbus_new_helpers.h"
+
+
+/**
+ * recursive_iter_copy - Reads arguments from one iterator and
+ * writes to another recursively
+ * @from: iterator to read from
+ * @to: iterator to write to
+ *
+ * Copies one iterator's elements to another. If any element in
+ * iterator is of container type, its content is copied recursively
+ */
+static void recursive_iter_copy(DBusMessageIter *from, DBusMessageIter *to)
+{
+
+	char *subtype = NULL;
+	int type;
+
+	/* iterate over iterator to copy */
+	while ((type = dbus_message_iter_get_arg_type(from)) !=
+	       DBUS_TYPE_INVALID) {
+
+		/* simply copy basic type entries */
+		if (dbus_type_is_basic(type)) {
+			if (dbus_type_is_fixed(type)) {
+				/*
+				 * According to DBus documentation all
+				 * fixed-length types are guaranteed to fit
+				 * 8 bytes
+				 */
+				dbus_uint64_t v;
+				dbus_message_iter_get_basic(from, &v);
+				dbus_message_iter_append_basic(to, type, &v);
+			} else {
+				char *v;
+				dbus_message_iter_get_basic(from, &v);
+				dbus_message_iter_append_basic(to, type, &v);
+			}
+		} else {
+			/* recursively copy container type entries */
+			DBusMessageIter write_subiter, read_subiter;
+
+			dbus_message_iter_recurse(from, &read_subiter);
+
+			if (type == DBUS_TYPE_VARIANT ||
+			    type == DBUS_TYPE_ARRAY) {
+				subtype = dbus_message_iter_get_signature(
+					&read_subiter);
+			}
+
+			dbus_message_iter_open_container(to, type, subtype,
+							 &write_subiter);
+
+			recursive_iter_copy(&read_subiter, &write_subiter);
+
+			dbus_message_iter_close_container(to, &write_subiter);
+			if (subtype)
+				dbus_free(subtype);
+		}
+
+		dbus_message_iter_next(from);
+	}
+}
+
+
+static unsigned int fill_dict_with_properties(
+	DBusMessageIter *dict_iter, const struct wpa_dbus_property_desc *props,
+	const char *interface, const void *user_data)
+{
+	DBusMessage *reply;
+	DBusMessageIter entry_iter, ret_iter;
+	unsigned int counter = 0;
+	const struct wpa_dbus_property_desc *dsc;
+
+	for (dsc = props; dsc && dsc->dbus_property; dsc++) {
+		if (!os_strncmp(dsc->dbus_interface, interface,
+				WPAS_DBUS_INTERFACE_MAX) &&
+		    dsc->access != W && dsc->getter) {
+			reply = dsc->getter(NULL, user_data);
+			if (!reply)
+				continue;
+
+			if (dbus_message_get_type(reply) ==
+			    DBUS_MESSAGE_TYPE_ERROR) {
+				dbus_message_unref(reply);
+				continue;
+			}
+
+			dbus_message_iter_init(reply, &ret_iter);
+
+			dbus_message_iter_open_container(dict_iter,
+							 DBUS_TYPE_DICT_ENTRY,
+							 NULL, &entry_iter);
+			dbus_message_iter_append_basic(
+				&entry_iter, DBUS_TYPE_STRING,
+				&dsc->dbus_property);
+
+			recursive_iter_copy(&ret_iter, &entry_iter);
+
+			dbus_message_iter_close_container(dict_iter,
+							  &entry_iter);
+			dbus_message_unref(reply);
+			counter++;
+		}
+	}
+
+	return counter;
+}
+
+
+/**
+ * get_all_properties - Responds for GetAll properties calls on object
+ * @message: Message with GetAll call
+ * @interface: interface name which properties will be returned
+ * @property_dsc: list of object's properties
+ * Returns: Message with dict of variants as argument with properties values
+ *
+ * Iterates over all properties registered with object and execute getters
+ * of those, which are readable and which interface matches interface
+ * specified as argument. Returned message contains one dict argument
+ * with properties names as keys and theirs values as values.
+ */
+static DBusMessage * get_all_properties(
+	DBusMessage *message, char *interface,
+	struct wpa_dbus_object_desc *obj_dsc)
+{
+	/* Create and initialize the return message */
+	DBusMessage *reply = dbus_message_new_method_return(message);
+	DBusMessageIter iter, dict_iter;
+	int props_num;
+
+	dbus_message_iter_init_append(reply, &iter);
+
+	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+					 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+					 DBUS_TYPE_STRING_AS_STRING
+					 DBUS_TYPE_VARIANT_AS_STRING
+					 DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+					 &dict_iter);
+
+	props_num = fill_dict_with_properties(&dict_iter, obj_dsc->properties,
+					      interface, obj_dsc->user_data);
+
+	dbus_message_iter_close_container(&iter, &dict_iter);
+
+	if (props_num == 0) {
+		dbus_message_unref(reply);
+		reply = dbus_message_new_error(message,
+					       DBUS_ERROR_INVALID_ARGS,
+					       "No readable properties in "
+					       "this interface");
+	}
+
+	return reply;
+}
+
+
+static int is_signature_correct(DBusMessage *message,
+				const struct wpa_dbus_method_desc *method_dsc)
+{
+	/* According to DBus documentation max length of signature is 255 */
+#define MAX_SIG_LEN 256
+	char registered_sig[MAX_SIG_LEN], *pos;
+	const char *sig = dbus_message_get_signature(message);
+	int ret;
+	const struct wpa_dbus_argument *arg;
+
+	pos = registered_sig;
+	*pos = '\0';
+
+	for (arg = method_dsc->args; arg && arg->name; arg++) {
+		if (arg->dir == ARG_IN) {
+			size_t blen = registered_sig + MAX_SIG_LEN - pos;
+			ret = os_snprintf(pos, blen, "%s", arg->type);
+			if (ret < 0 || (size_t) ret >= blen)
+				return 0;
+			pos += ret;
+		}
+	}
+
+	return !os_strncmp(registered_sig, sig, MAX_SIG_LEN);
+}
+
+
+static DBusMessage * properties_get_all(DBusMessage *message, char *interface,
+					struct wpa_dbus_object_desc *obj_dsc)
+{
+	if (os_strcmp(dbus_message_get_signature(message), "s") != 0)
+		return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
+					      NULL);
+
+	return get_all_properties(message, interface, obj_dsc);
+}
+
+
+static DBusMessage * properties_get(DBusMessage *message,
+				    const struct wpa_dbus_property_desc *dsc,
+				    void *user_data)
+{
+	if (os_strcmp(dbus_message_get_signature(message), "ss"))
+		return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
+					      NULL);
+
+	if (dsc->access != W && dsc->getter)
+		return dsc->getter(message, user_data);
+
+	return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
+				      "Property is write-only");
+}
+
+
+static DBusMessage * properties_set(DBusMessage *message,
+				    const struct wpa_dbus_property_desc *dsc,
+				    void *user_data)
+{
+	if (os_strcmp(dbus_message_get_signature(message), "ssv"))
+		return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
+					      NULL);
+
+	if (dsc->access != R && dsc->setter)
+		return dsc->setter(message, user_data);
+
+	return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
+				      "Property is read-only");
+}
+
+
+static DBusMessage *
+properties_get_or_set(DBusMessage *message, DBusMessageIter *iter,
+		      char *interface,
+		      struct wpa_dbus_object_desc *obj_dsc)
+{
+	const struct wpa_dbus_property_desc *property_dsc;
+	char *property;
+	const char *method;
+
+	method = dbus_message_get_member(message);
+	property_dsc = obj_dsc->properties;
+
+	/* Second argument: property name (DBUS_TYPE_STRING) */
+	if (!dbus_message_iter_next(iter) ||
+	    dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING) {
+		return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
+					      NULL);
+	}
+	dbus_message_iter_get_basic(iter, &property);
+
+	while (property_dsc && property_dsc->dbus_property) {
+		/* compare property names and
+		 * interfaces */
+		if (!os_strncmp(property_dsc->dbus_property, property,
+				WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) &&
+		    !os_strncmp(property_dsc->dbus_interface, interface,
+				WPAS_DBUS_INTERFACE_MAX))
+			break;
+
+		property_dsc++;
+	}
+	if (property_dsc == NULL || property_dsc->dbus_property == NULL) {
+		wpa_printf(MSG_DEBUG, "no property handler for %s.%s on %s",
+			   interface, property,
+			   dbus_message_get_path(message));
+		return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
+					      "No such property");
+	}
+
+	if (os_strncmp(WPA_DBUS_PROPERTIES_GET, method,
+		       WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) == 0)
+		return properties_get(message, property_dsc,
+				      obj_dsc->user_data);
+
+	return properties_set(message, property_dsc, obj_dsc->user_data);
+}
+
+
+static DBusMessage * properties_handler(DBusMessage *message,
+					struct wpa_dbus_object_desc *obj_dsc)
+{
+	DBusMessageIter iter;
+	char *interface;
+	const char *method;
+
+	method = dbus_message_get_member(message);
+	dbus_message_iter_init(message, &iter);
+
+	if (!os_strncmp(WPA_DBUS_PROPERTIES_GET, method,
+			WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) ||
+	    !os_strncmp(WPA_DBUS_PROPERTIES_SET, method,
+			WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) ||
+	    !os_strncmp(WPA_DBUS_PROPERTIES_GETALL, method,
+			WPAS_DBUS_METHOD_SIGNAL_PROP_MAX)) {
+		/* First argument: interface name (DBUS_TYPE_STRING) */
+		if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+		{
+			return dbus_message_new_error(message,
+						      DBUS_ERROR_INVALID_ARGS,
+						      NULL);
+		}
+
+		dbus_message_iter_get_basic(&iter, &interface);
+
+		if (!os_strncmp(WPA_DBUS_PROPERTIES_GETALL, method,
+				WPAS_DBUS_METHOD_SIGNAL_PROP_MAX)) {
+			/* GetAll */
+			return properties_get_all(message, interface, obj_dsc);
+		}
+		/* Get or Set */
+		return properties_get_or_set(message, &iter, interface,
+					     obj_dsc);
+	}
+	return dbus_message_new_error(message, DBUS_ERROR_UNKNOWN_METHOD,
+				      NULL);
+}
+
+
+static DBusMessage * msg_method_handler(DBusMessage *message,
+					struct wpa_dbus_object_desc *obj_dsc)
+{
+	const struct wpa_dbus_method_desc *method_dsc = obj_dsc->methods;
+	const char *method;
+	const char *msg_interface;
+
+	method = dbus_message_get_member(message);
+	msg_interface = dbus_message_get_interface(message);
+
+	/* try match call to any registered method */
+	while (method_dsc && method_dsc->dbus_method) {
+		/* compare method names and interfaces */
+		if (!os_strncmp(method_dsc->dbus_method, method,
+				WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) &&
+		    !os_strncmp(method_dsc->dbus_interface, msg_interface,
+				WPAS_DBUS_INTERFACE_MAX))
+			break;
+
+		method_dsc++;
+	}
+	if (method_dsc == NULL || method_dsc->dbus_method == NULL) {
+		wpa_printf(MSG_DEBUG, "no method handler for %s.%s on %s",
+			   msg_interface, method,
+			   dbus_message_get_path(message));
+		return dbus_message_new_error(message,
+					      DBUS_ERROR_UNKNOWN_METHOD, NULL);
+	}
+
+	if (!is_signature_correct(message, method_dsc)) {
+		return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
+					      NULL);
+	}
+
+	return method_dsc->method_handler(message,
+					  obj_dsc->user_data);
+}
+
+
+/**
+ * message_handler - Handles incoming DBus messages
+ * @connection: DBus connection on which message was received
+ * @message: Received message
+ * @user_data: pointer to description of object to which message was sent
+ * Returns: Returns information whether message was handled or not
+ *
+ * Reads message interface and method name, then checks if they matches one
+ * of the special cases i.e. introspection call or properties get/getall/set
+ * methods and handles it. Else it iterates over registered methods list
+ * and tries to match method's name and interface to those read from message
+ * If appropriate method was found its handler function is called and
+ * response is sent. Otherwise, the DBUS_ERROR_UNKNOWN_METHOD error message
+ * will be sent.
+ */
+static DBusHandlerResult message_handler(DBusConnection *connection,
+					 DBusMessage *message, void *user_data)
+{
+	struct wpa_dbus_object_desc *obj_dsc = user_data;
+	const char *method;
+	const char *path;
+	const char *msg_interface;
+	DBusMessage *reply;
+
+	/* get method, interface and path the message is addressed to */
+	method = dbus_message_get_member(message);
+	path = dbus_message_get_path(message);
+	msg_interface = dbus_message_get_interface(message);
+	if (!method || !path || !msg_interface)
+		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+	wpa_printf(MSG_MSGDUMP, "dbus: %s.%s (%s)",
+		   msg_interface, method, path);
+
+	/* if message is introspection method call */
+	if (!os_strncmp(WPA_DBUS_INTROSPECTION_METHOD, method,
+			WPAS_DBUS_METHOD_SIGNAL_PROP_MAX) &&
+	    !os_strncmp(WPA_DBUS_INTROSPECTION_INTERFACE, msg_interface,
+			WPAS_DBUS_INTERFACE_MAX)) {
+#ifdef CONFIG_CTRL_IFACE_DBUS_INTRO
+		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)) {
+		/* if message is properties method call */
+		reply = properties_handler(message, obj_dsc);
+	} else {
+		reply = msg_method_handler(message, obj_dsc);
+	}
+
+	/* If handler succeed returning NULL, reply empty message */
+	if (!reply)
+		reply = dbus_message_new_method_return(message);
+	if (reply) {
+		if (!dbus_message_get_no_reply(message))
+			dbus_connection_send(connection, reply, NULL);
+		dbus_message_unref(reply);
+	}
+
+	wpa_dbus_flush_all_changed_properties(connection);
+
+	return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+
+/**
+ * free_dbus_object_desc - Frees object description data structure
+ * @connection: DBus connection
+ * @obj_dsc: Object description to free
+ *
+ * Frees each of properties, methods and signals description lists and
+ * the object description structure itself.
+ */
+void free_dbus_object_desc(struct wpa_dbus_object_desc *obj_dsc)
+{
+	if (!obj_dsc)
+		return;
+
+	/* free handler's argument */
+	if (obj_dsc->user_data_free_func)
+		obj_dsc->user_data_free_func(obj_dsc->user_data);
+
+	os_free(obj_dsc->path);
+	os_free(obj_dsc->prop_changed_flags);
+	os_free(obj_dsc);
+}
+
+
+static void free_dbus_object_desc_cb(DBusConnection *connection, void *obj_dsc)
+{
+	free_dbus_object_desc(obj_dsc);
+}
+
+/**
+ * wpa_dbus_ctrl_iface_init - Initialize dbus control interface
+ * @application_data: Pointer to application specific data structure
+ * @dbus_path: DBus path to interface object
+ * @dbus_service: DBus service name to register with
+ * @messageHandler: a pointer to function which will handle dbus messages
+ * coming on interface
+ * Returns: 0 on success, -1 on failure
+ *
+ * Initialize the dbus control interface and start receiving commands from
+ * external programs over the bus.
+ */
+int wpa_dbus_ctrl_iface_init(struct wpas_dbus_priv *iface,
+			     char *dbus_path, char *dbus_service,
+			     struct wpa_dbus_object_desc *obj_desc)
+{
+	DBusError error;
+	int ret = -1;
+	DBusObjectPathVTable wpa_vtable = {
+		&free_dbus_object_desc_cb, &message_handler,
+		NULL, NULL, NULL, NULL
+	};
+
+	obj_desc->connection = iface->con;
+	obj_desc->path = os_strdup(dbus_path);
+
+	/* Register the message handler for the global dbus interface */
+	if (!dbus_connection_register_object_path(iface->con,
+						  dbus_path, &wpa_vtable,
+						  obj_desc)) {
+		wpa_printf(MSG_ERROR, "dbus: Could not set up message "
+			   "handler");
+		return -1;
+	}
+
+	/* Register our service with the message bus */
+	dbus_error_init(&error);
+	switch (dbus_bus_request_name(iface->con, dbus_service,
+				      0, &error)) {
+	case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
+		ret = 0;
+		break;
+	case DBUS_REQUEST_NAME_REPLY_EXISTS:
+	case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
+	case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
+		wpa_printf(MSG_ERROR, "dbus: Could not request service name: "
+			   "already registered");
+		break;
+	default:
+		wpa_printf(MSG_ERROR, "dbus: Could not request service name: "
+			   "%s %s", error.name, error.message);
+		break;
+	}
+	dbus_error_free(&error);
+
+	if (ret != 0)
+		return -1;
+
+	wpa_printf(MSG_DEBUG, "Providing DBus service '%s'.", dbus_service);
+
+	return 0;
+}
+
+
+/**
+ * wpa_dbus_register_object_per_iface - Register a new object with dbus
+ * @ctrl_iface: pointer to dbus private data
+ * @path: DBus path to object
+ * @ifname: interface name
+ * @obj_desc: description of object's methods, signals and properties
+ * Returns: 0 on success, -1 on error
+ *
+ * Registers a new interface with dbus and assigns it a dbus object path.
+ */
+int wpa_dbus_register_object_per_iface(
+	struct wpas_dbus_priv *ctrl_iface,
+	const char *path, const char *ifname,
+	struct wpa_dbus_object_desc *obj_desc)
+{
+	DBusConnection *con;
+	DBusError error;
+
+	DBusObjectPathVTable vtable = {
+		&free_dbus_object_desc_cb, &message_handler,
+		NULL, NULL, NULL, NULL
+	};
+
+	/* Do nothing if the control interface is not turned on */
+	if (ctrl_iface == NULL)
+		return 0;
+
+	con = ctrl_iface->con;
+	obj_desc->connection = con;
+	obj_desc->path = os_strdup(path);
+
+	dbus_error_init(&error);
+	/* Register the message handler for the interface functions */
+	if (!dbus_connection_try_register_object_path(con, path, &vtable,
+						      obj_desc, &error)) {
+		if (!os_strcmp(error.name, DBUS_ERROR_OBJECT_PATH_IN_USE)) {
+			wpa_printf(MSG_DEBUG, "dbus: %s", error.message);
+		} else {
+			wpa_printf(MSG_ERROR, "dbus: Could not set up message "
+				   "handler for interface %s object %s",
+				   ifname, path);
+			wpa_printf(MSG_ERROR, "dbus error: %s", error.name);
+			wpa_printf(MSG_ERROR, "dbus: %s", error.message);
+		}
+		dbus_error_free(&error);
+		return -1;
+	}
+
+	dbus_error_free(&error);
+	return 0;
+}
+
+
+static void flush_object_timeout_handler(void *eloop_ctx, void *timeout_ctx);
+
+
+/**
+ * wpa_dbus_unregister_object_per_iface - Unregisters DBus object
+ * @ctrl_iface: Pointer to dbus private data
+ * @path: DBus path to object which will be unregistered
+ * Returns: Zero on success and -1 on failure
+ *
+ * Unregisters DBus object given by its path
+ */
+int wpa_dbus_unregister_object_per_iface(
+	struct wpas_dbus_priv *ctrl_iface, const char *path)
+{
+	DBusConnection *con = ctrl_iface->con;
+	struct wpa_dbus_object_desc *obj_desc = NULL;
+
+	dbus_connection_get_object_path_data(con, path, (void **) &obj_desc);
+	if (!obj_desc) {
+		wpa_printf(MSG_ERROR, "dbus: %s: Could not obtain object's "
+			   "private data: %s", __func__, path);
+	} else {
+		eloop_cancel_timeout(flush_object_timeout_handler, con,
+				     obj_desc);
+	}
+
+	if (!dbus_connection_unregister_object_path(con, path))
+		return -1;
+
+	return 0;
+}
+
+
+static void put_changed_properties(const struct wpa_dbus_object_desc *obj_dsc,
+				   const char *interface,
+				   DBusMessageIter *dict_iter)
+{
+	DBusMessage *getter_reply;
+	DBusMessageIter prop_iter, entry_iter;
+	const struct wpa_dbus_property_desc *dsc;
+	int i;
+
+	for (dsc = obj_dsc->properties, i = 0; dsc && dsc->dbus_property;
+	     dsc++, i++) {
+		if (obj_dsc->prop_changed_flags == NULL ||
+		    !obj_dsc->prop_changed_flags[i])
+			continue;
+		if (os_strcmp(dsc->dbus_interface, interface) != 0)
+			continue;
+		obj_dsc->prop_changed_flags[i] = 0;
+
+		getter_reply = dsc->getter(NULL, obj_dsc->user_data);
+		if (!getter_reply ||
+		    dbus_message_get_type(getter_reply) ==
+		    DBUS_MESSAGE_TYPE_ERROR) {
+			wpa_printf(MSG_ERROR, "dbus: %s: Cannot get new value "
+				   "of property %s", __func__,
+				   dsc->dbus_property);
+			continue;
+		}
+
+		if (!dbus_message_iter_init(getter_reply, &prop_iter) ||
+		    !dbus_message_iter_open_container(dict_iter,
+						      DBUS_TYPE_DICT_ENTRY,
+						      NULL, &entry_iter) ||
+		    !dbus_message_iter_append_basic(&entry_iter,
+						    DBUS_TYPE_STRING,
+						    &dsc->dbus_property))
+			goto err;
+
+		recursive_iter_copy(&prop_iter, &entry_iter);
+
+		if (!dbus_message_iter_close_container(dict_iter, &entry_iter))
+			goto err;
+
+		dbus_message_unref(getter_reply);
+	}
+
+	return;
+
+err:
+	wpa_printf(MSG_ERROR, "dbus: %s: Cannot construct signal", __func__);
+}
+
+
+static void send_prop_changed_signal(
+	DBusConnection *con, const char *path, const char *interface,
+	const struct wpa_dbus_object_desc *obj_dsc)
+{
+	DBusMessage *msg;
+	DBusMessageIter signal_iter, dict_iter;
+
+	msg = dbus_message_new_signal(path, interface, "PropertiesChanged");
+	if (msg == NULL)
+		return;
+
+	dbus_message_iter_init_append(msg, &signal_iter);
+
+	if (!dbus_message_iter_open_container(&signal_iter, DBUS_TYPE_ARRAY,
+					      "{sv}", &dict_iter))
+		goto err;
+
+	put_changed_properties(obj_dsc, interface, &dict_iter);
+
+	if (!dbus_message_iter_close_container(&signal_iter, &dict_iter))
+		goto err;
+
+	dbus_connection_send(con, msg, NULL);
+
+out:
+	dbus_message_unref(msg);
+	return;
+
+err:
+	wpa_printf(MSG_DEBUG, "dbus: %s: Failed to construct signal",
+		   __func__);
+	goto out;
+}
+
+
+static void flush_object_timeout_handler(void *eloop_ctx, void *timeout_ctx)
+{
+	DBusConnection *con = eloop_ctx;
+	struct wpa_dbus_object_desc *obj_desc = timeout_ctx;
+
+	wpa_printf(MSG_DEBUG, "dbus: %s: Timeout - sending changed properties "
+		   "of object %s", __func__, obj_desc->path);
+	wpa_dbus_flush_object_changed_properties(con, obj_desc->path);
+}
+
+
+static void recursive_flush_changed_properties(DBusConnection *con,
+					       const char *path)
+{
+	char **objects = NULL;
+	char subobj_path[WPAS_DBUS_OBJECT_PATH_MAX];
+	int i;
+
+	wpa_dbus_flush_object_changed_properties(con, path);
+
+	if (!dbus_connection_list_registered(con, path, &objects))
+		goto out;
+
+	for (i = 0; objects[i]; i++) {
+		os_snprintf(subobj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+			    "%s/%s", path, objects[i]);
+		recursive_flush_changed_properties(con, subobj_path);
+	}
+
+out:
+	dbus_free_string_array(objects);
+}
+
+
+/**
+ * wpa_dbus_flush_all_changed_properties - Send all PropertiesChanged signals
+ * @con: DBus connection
+ *
+ * Traverses through all registered objects and sends PropertiesChanged for
+ * each properties.
+ */
+void wpa_dbus_flush_all_changed_properties(DBusConnection *con)
+{
+	recursive_flush_changed_properties(con, WPAS_DBUS_NEW_PATH);
+}
+
+
+/**
+ * wpa_dbus_flush_object_changed_properties - Send PropertiesChanged for object
+ * @con: DBus connection
+ * @path: path to a DBus object for which PropertiesChanged will be sent.
+ *
+ * Iterates over all properties registered with object and for each interface
+ * containing properties marked as changed, sends a PropertiesChanged signal
+ * containing names and new values of properties that have changed.
+ *
+ * You need to call this function after wpa_dbus_mark_property_changed()
+ * if you want to send PropertiesChanged signal immediately (i.e., without
+ * waiting timeout to expire). PropertiesChanged signal for an object is sent
+ * automatically short time after first marking property as changed. All
+ * PropertiesChanged signals are sent automatically after responding on DBus
+ * message, so if you marked a property changed as a result of DBus call
+ * (e.g., param setter), you usually do not need to call this function.
+ */
+void wpa_dbus_flush_object_changed_properties(DBusConnection *con,
+					      const char *path)
+{
+	struct wpa_dbus_object_desc *obj_desc = NULL;
+	const struct wpa_dbus_property_desc *dsc;
+	int i;
+
+	dbus_connection_get_object_path_data(con, path, (void **) &obj_desc);
+	if (!obj_desc)
+		return;
+	eloop_cancel_timeout(flush_object_timeout_handler, con, obj_desc);
+
+	dsc = obj_desc->properties;
+	for (dsc = obj_desc->properties, i = 0; dsc && dsc->dbus_property;
+	     dsc++, i++) {
+		if (obj_desc->prop_changed_flags == NULL ||
+		    !obj_desc->prop_changed_flags[i])
+			continue;
+		send_prop_changed_signal(con, path, dsc->dbus_interface,
+					 obj_desc);
+	}
+}
+
+
+#define WPA_DBUS_SEND_PROP_CHANGED_TIMEOUT 5000
+
+
+/**
+ * wpa_dbus_mark_property_changed - Mark a property as changed and
+ * @iface: dbus priv struct
+ * @path: path to DBus object which property has changed
+ * @interface: interface containing changed property
+ * @property: property name which has changed
+ *
+ * Iterates over all properties registered with an object and marks the one
+ * given in parameters as changed. All parameters registered for an object
+ * within a single interface will be aggregated together and sent in one
+ * PropertiesChanged signal when function
+ * wpa_dbus_flush_object_changed_properties() is called.
+ */
+void wpa_dbus_mark_property_changed(struct wpas_dbus_priv *iface,
+				    const char *path, const char *interface,
+				    const char *property)
+{
+	struct wpa_dbus_object_desc *obj_desc = NULL;
+	const struct wpa_dbus_property_desc *dsc;
+	int i = 0;
+
+	if (iface == NULL)
+		return;
+
+	dbus_connection_get_object_path_data(iface->con, path,
+					     (void **) &obj_desc);
+	if (!obj_desc) {
+		wpa_printf(MSG_ERROR, "dbus: wpa_dbus_property_changed: "
+			   "could not obtain object's private data: %s", path);
+		return;
+	}
+
+	for (dsc = obj_desc->properties; dsc && dsc->dbus_property; dsc++, i++)
+		if (os_strcmp(property, dsc->dbus_property) == 0 &&
+		    os_strcmp(interface, dsc->dbus_interface) == 0) {
+			if (obj_desc->prop_changed_flags)
+				obj_desc->prop_changed_flags[i] = 1;
+			break;
+		}
+
+	if (!dsc || !dsc->dbus_property) {
+		wpa_printf(MSG_ERROR, "dbus: wpa_dbus_property_changed: "
+			   "no property %s in object %s", property, path);
+		return;
+	}
+
+	if (!eloop_is_timeout_registered(flush_object_timeout_handler,
+					 iface->con, obj_desc->path)) {
+		eloop_register_timeout(0, WPA_DBUS_SEND_PROP_CHANGED_TIMEOUT,
+				       flush_object_timeout_handler,
+				       iface->con, obj_desc);
+	}
+}
+
+
+/**
+ * wpa_dbus_get_object_properties - Put object's properties into dictionary
+ * @iface: dbus priv struct
+ * @path: path to DBus object which properties will be obtained
+ * @interface: interface name which properties will be obtained
+ * @dict_iter: correct, open DBus dictionary iterator.
+ *
+ * Iterates over all properties registered with object and execute getters
+ * of those, which are readable and which interface matches interface
+ * specified as argument. Obtained properties values are stored in
+ * dict_iter dictionary.
+ */
+void wpa_dbus_get_object_properties(struct wpas_dbus_priv *iface,
+				    const char *path, const char *interface,
+				    DBusMessageIter *dict_iter)
+{
+	struct wpa_dbus_object_desc *obj_desc = NULL;
+
+	dbus_connection_get_object_path_data(iface->con, path,
+					     (void **) &obj_desc);
+	if (!obj_desc) {
+		wpa_printf(MSG_ERROR, "dbus: wpa_dbus_get_object_properties: "
+			   "could not obtain object's private data: %s", path);
+		return;
+	}
+
+	fill_dict_with_properties(dict_iter, obj_desc->properties,
+				  interface, obj_desc->user_data);
+}
diff --git a/wpa_supplicant/dbus/dbus_new_helpers.h b/wpa_supplicant/dbus/dbus_new_helpers.h
new file mode 100644
index 0000000..7038b63
--- /dev/null
+++ b/wpa_supplicant/dbus/dbus_new_helpers.h
@@ -0,0 +1,148 @@
+/*
+ * 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.
+ */
+
+#ifndef WPA_DBUS_CTRL_H
+#define WPA_DBUS_CTRL_H
+
+#include <dbus/dbus.h>
+
+typedef DBusMessage * (* WPADBusMethodHandler)(DBusMessage *message,
+					       void *user_data);
+typedef void (* WPADBusArgumentFreeFunction)(void *handler_arg);
+
+typedef DBusMessage * (* WPADBusPropertyAccessor)(DBusMessage *message,
+						  const void *user_data);
+
+struct wpa_dbus_object_desc {
+	DBusConnection *connection;
+	char *path;
+
+	/* list of methods, properties and signals registered with object */
+	const struct wpa_dbus_method_desc *methods;
+	const struct wpa_dbus_signal_desc *signals;
+	const struct wpa_dbus_property_desc *properties;
+
+	/* property changed flags */
+	u8 *prop_changed_flags;
+
+	/* argument for method handlers and properties
+	 * getter and setter functions */
+	void *user_data;
+	/* function used to free above argument */
+	WPADBusArgumentFreeFunction user_data_free_func;
+};
+
+enum dbus_prop_access { R, W, RW };
+
+enum dbus_arg_direction { ARG_IN, ARG_OUT };
+
+struct wpa_dbus_argument {
+	char *name;
+	char *type;
+	enum dbus_arg_direction dir;
+};
+
+#define END_ARGS { NULL, NULL, ARG_IN }
+
+/**
+ * struct wpa_dbus_method_desc - DBus method description
+ */
+struct wpa_dbus_method_desc {
+	/* method name */
+	const char *dbus_method;
+	/* method interface */
+	const char *dbus_interface;
+	/* method handling function */
+	WPADBusMethodHandler method_handler;
+	/* array of arguments */
+	struct wpa_dbus_argument args[3];
+};
+
+/**
+ * struct wpa_dbus_signal_desc - DBus signal description
+ */
+struct wpa_dbus_signal_desc {
+	/* signal name */
+	const char *dbus_signal;
+	/* signal interface */
+	const char *dbus_interface;
+	/* array of arguments */
+	struct wpa_dbus_argument args[3];
+};
+
+/**
+ * struct wpa_dbus_property_desc - DBus property description
+ */
+struct wpa_dbus_property_desc {
+	/* property name */
+	const char *dbus_property;
+	/* property interface */
+	const char *dbus_interface;
+	/* property type signature in DBus type notation */
+	const char *type;
+	/* property getter function */
+	WPADBusPropertyAccessor getter;
+	/* property setter function */
+	WPADBusPropertyAccessor setter;
+	/* property access permissions */
+	enum dbus_prop_access access;
+};
+
+
+#define WPAS_DBUS_OBJECT_PATH_MAX 150
+#define WPAS_DBUS_INTERFACE_MAX 150
+#define WPAS_DBUS_METHOD_SIGNAL_PROP_MAX 50
+#define WPAS_DBUS_AUTH_MODE_MAX 64
+
+#define WPA_DBUS_INTROSPECTION_INTERFACE "org.freedesktop.DBus.Introspectable"
+#define WPA_DBUS_INTROSPECTION_METHOD "Introspect"
+#define WPA_DBUS_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
+#define WPA_DBUS_PROPERTIES_GET "Get"
+#define WPA_DBUS_PROPERTIES_SET "Set"
+#define WPA_DBUS_PROPERTIES_GETALL "GetAll"
+
+void free_dbus_object_desc(struct wpa_dbus_object_desc *obj_dsc);
+
+int wpa_dbus_ctrl_iface_init(struct wpas_dbus_priv *iface, char *dbus_path,
+			     char *dbus_service,
+			     struct wpa_dbus_object_desc *obj_desc);
+
+int wpa_dbus_register_object_per_iface(
+	struct wpas_dbus_priv *ctrl_iface,
+	const char *path, const char *ifname,
+	struct wpa_dbus_object_desc *obj_desc);
+
+int wpa_dbus_unregister_object_per_iface(
+	struct wpas_dbus_priv *ctrl_iface,
+	const char *path);
+
+void wpa_dbus_get_object_properties(struct wpas_dbus_priv *iface,
+				    const char *path, const char *interface,
+				    DBusMessageIter *dict_iter);
+
+
+void wpa_dbus_flush_all_changed_properties(DBusConnection *con);
+
+void wpa_dbus_flush_object_changed_properties(DBusConnection *con,
+					      const char *path);
+
+void wpa_dbus_mark_property_changed(struct wpas_dbus_priv *iface,
+				    const char *path, const char *interface,
+				    const char *property);
+
+DBusMessage * wpa_dbus_introspect(DBusMessage *message,
+				  struct wpa_dbus_object_desc *obj_dsc);
+
+#endif /* WPA_DBUS_CTRL_H */
diff --git a/wpa_supplicant/dbus/dbus_new_introspect.c b/wpa_supplicant/dbus/dbus_new_introspect.c
new file mode 100644
index 0000000..fd433df
--- /dev/null
+++ b/wpa_supplicant/dbus/dbus_new_introspect.c
@@ -0,0 +1,278 @@
+/*
+ * wpa_supplicant - D-Bus introspection
+ * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
+ * Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
+ * Copyright (c) 2010, Jouni Malinen <j@w1.fi>
+ *
+ * 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 "utils/common.h"
+#include "utils/list.h"
+#include "utils/wpabuf.h"
+#include "dbus_common_i.h"
+#include "dbus_new_helpers.h"
+
+
+struct interfaces {
+	struct dl_list list;
+	char *dbus_interface;
+	struct wpabuf *xml;
+};
+
+
+static struct interfaces * add_interface(struct dl_list *list,
+					 const char *dbus_interface)
+{
+	struct interfaces *iface;
+
+	dl_list_for_each(iface, list, struct interfaces, list) {
+		if (os_strcmp(iface->dbus_interface, dbus_interface) == 0)
+			return iface; /* already in the list */
+	}
+
+	iface = os_zalloc(sizeof(struct interfaces));
+	if (!iface)
+		return NULL;
+	iface->xml = wpabuf_alloc(6000);
+	if (iface->xml == NULL) {
+		os_free(iface);
+		return NULL;
+	}
+	wpabuf_printf(iface->xml, "<interface name=\"%s\">", dbus_interface);
+	dl_list_add_tail(list, &iface->list);
+	iface->dbus_interface = os_strdup(dbus_interface);
+	return iface;
+}
+
+
+static void add_arg(struct wpabuf *xml, const char *name, const char *type,
+		    const char *direction)
+{
+	wpabuf_printf(xml, "<arg name=\"%s\"", name);
+	if (type)
+		wpabuf_printf(xml, " type=\"%s\"", type);
+	if (direction)
+		wpabuf_printf(xml, " direction=\"%s\"", direction);
+	wpabuf_put_str(xml, "/>");
+}
+
+
+static void add_entry(struct wpabuf *xml, const char *type, const char *name,
+		      const struct wpa_dbus_argument *args, int include_dir)
+{
+	const struct wpa_dbus_argument *arg;
+
+	if (args == NULL || args->name == NULL) {
+		wpabuf_printf(xml, "<%s name=\"%s\"/>", type, name);
+		return;
+	}
+	wpabuf_printf(xml, "<%s name=\"%s\">", type, name);
+	for (arg = args; arg && arg->name; arg++) {
+		add_arg(xml, arg->name, arg->type,
+			include_dir ? (arg->dir == ARG_IN ? "in" : "out") :
+			NULL);
+	}
+	wpabuf_printf(xml, "</%s>", type);
+}
+
+
+static void add_property(struct wpabuf *xml,
+			 const struct wpa_dbus_property_desc *dsc)
+{
+	wpabuf_printf(xml, "<property name=\"%s\" type=\"%s\" access=\"%s\"/>",
+		      dsc->dbus_property, dsc->type,
+		      (dsc->access == R ? "read" :
+		       (dsc->access == W ? "write" : "readwrite")));
+}
+
+
+static void extract_interfaces_methods(
+	struct dl_list *list, const struct wpa_dbus_method_desc *methods)
+{
+	const struct wpa_dbus_method_desc *dsc;
+	struct interfaces *iface;
+	for (dsc = methods; dsc && dsc->dbus_method; dsc++) {
+		iface = add_interface(list, dsc->dbus_interface);
+		if (iface)
+			add_entry(iface->xml, "method", dsc->dbus_method,
+				  dsc->args, 1);
+	}
+}
+
+
+static void extract_interfaces_signals(
+	struct dl_list *list, const struct wpa_dbus_signal_desc *signals)
+{
+	const struct wpa_dbus_signal_desc *dsc;
+	struct interfaces *iface;
+	for (dsc = signals; dsc && dsc->dbus_signal; dsc++) {
+		iface = add_interface(list, dsc->dbus_interface);
+		if (iface)
+			add_entry(iface->xml, "signal", dsc->dbus_signal,
+				  dsc->args, 0);
+	}
+}
+
+
+static void extract_interfaces_properties(
+	struct dl_list *list, const struct wpa_dbus_property_desc *properties)
+{
+	const struct wpa_dbus_property_desc *dsc;
+	struct interfaces *iface;
+	for (dsc = properties; dsc && dsc->dbus_property; dsc++) {
+		iface = add_interface(list, dsc->dbus_interface);
+		if (iface)
+			add_property(iface->xml, dsc);
+	}
+}
+
+
+/**
+ * extract_interfaces - Extract interfaces from methods, signals and props
+ * @list: Interface list to be filled
+ * @obj_dsc: Description of object from which interfaces will be extracted
+ *
+ * Iterates over all methods, signals, and properties registered with an
+ * object and collects all declared DBus interfaces and create interfaces'
+ * node in XML root node for each. Returned list elements contain interface
+ * name and XML node of corresponding interface.
+ */
+static void extract_interfaces(struct dl_list *list,
+			       struct wpa_dbus_object_desc *obj_dsc)
+{
+	extract_interfaces_methods(list, obj_dsc->methods);
+	extract_interfaces_signals(list, obj_dsc->signals);
+	extract_interfaces_properties(list, obj_dsc->properties);
+}
+
+
+static void add_interfaces(struct dl_list *list, struct wpabuf *xml)
+{
+	struct interfaces *iface, *n;
+	dl_list_for_each_safe(iface, n, list, struct interfaces, list) {
+		if (wpabuf_len(iface->xml) + 20 < wpabuf_tailroom(xml)) {
+			wpabuf_put_buf(xml, iface->xml);
+			wpabuf_put_str(xml, "</interface>");
+		}
+		dl_list_del(&iface->list);
+		wpabuf_free(iface->xml);
+		os_free(iface->dbus_interface);
+		os_free(iface);
+	}
+}
+
+
+static void add_child_nodes(struct wpabuf *xml, DBusConnection *con,
+			    const char *path)
+{
+	char **children;
+	int i;
+
+	/* add child nodes to introspection tree */
+	dbus_connection_list_registered(con, path, &children);
+	for (i = 0; children[i]; i++)
+		wpabuf_printf(xml, "<node name=\"%s\"/>", children[i]);
+	dbus_free_string_array(children);
+}
+
+
+static void add_introspectable_interface(struct wpabuf *xml)
+{
+	wpabuf_printf(xml, "<interface name=\"%s\">"
+		      "<method name=\"%s\">"
+		      "<arg name=\"data\" type=\"s\" direction=\"out\"/>"
+		      "</method>"
+		      "</interface>",
+		      WPA_DBUS_INTROSPECTION_INTERFACE,
+		      WPA_DBUS_INTROSPECTION_METHOD);
+}
+
+
+static void add_properties_interface(struct wpabuf *xml)
+{
+	wpabuf_printf(xml, "<interface name=\"%s\">",
+		      WPA_DBUS_PROPERTIES_INTERFACE);
+
+	wpabuf_printf(xml, "<method name=\"%s\">", WPA_DBUS_PROPERTIES_GET);
+	add_arg(xml, "interface", "s", "in");
+	add_arg(xml, "propname", "s", "in");
+	add_arg(xml, "value", "v", "out");
+	wpabuf_put_str(xml, "</method>");
+
+	wpabuf_printf(xml, "<method name=\"%s\">", WPA_DBUS_PROPERTIES_GETALL);
+	add_arg(xml, "interface", "s", "in");
+	add_arg(xml, "props", "a{sv}", "out");
+	wpabuf_put_str(xml, "</method>");
+
+	wpabuf_printf(xml, "<method name=\"%s\">", WPA_DBUS_PROPERTIES_SET);
+	add_arg(xml, "interface", "s", "in");
+	add_arg(xml, "propname", "s", "in");
+	add_arg(xml, "value", "v", "in");
+	wpabuf_put_str(xml, "</method>");
+
+	wpabuf_put_str(xml, "</interface>");
+}
+
+
+static void add_wpas_interfaces(struct wpabuf *xml,
+				struct wpa_dbus_object_desc *obj_dsc)
+{
+	struct dl_list ifaces;
+	dl_list_init(&ifaces);
+	extract_interfaces(&ifaces, obj_dsc);
+	add_interfaces(&ifaces, xml);
+}
+
+
+/**
+ * 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 wpabuf *xml;
+
+	xml = wpabuf_alloc(8000);
+	if (xml == NULL)
+		return NULL;
+
+	wpabuf_put_str(xml, "<?xml version=\"1.0\"?>\n");
+	wpabuf_put_str(xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE);
+	wpabuf_put_str(xml, "<node>");
+
+	add_introspectable_interface(xml);
+	add_properties_interface(xml);
+	add_wpas_interfaces(xml, obj_dsc);
+	add_child_nodes(xml, obj_dsc->connection,
+			dbus_message_get_path(message));
+
+	wpabuf_put_str(xml, "</node>\n");
+
+	reply = dbus_message_new_method_return(message);
+	if (reply) {
+		const char *intro_str = wpabuf_head(xml);
+		dbus_message_append_args(reply, DBUS_TYPE_STRING, &intro_str,
+					 DBUS_TYPE_INVALID);
+	}
+	wpabuf_free(xml);
+
+	return reply;
+}
diff --git a/wpa_supplicant/dbus/dbus_old.c b/wpa_supplicant/dbus/dbus_old.c
new file mode 100644
index 0000000..6a00f3e
--- /dev/null
+++ b/wpa_supplicant/dbus/dbus_old.c
@@ -0,0 +1,697 @@
+/*
+ * WPA Supplicant / dbus-based control interface
+ * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
+ *
+ * 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 "includes.h"
+#include <dbus/dbus.h>
+
+#include "common.h"
+#include "eloop.h"
+#include "wps/wps.h"
+#include "../config.h"
+#include "../wpa_supplicant_i.h"
+#include "../bss.h"
+#include "dbus_old.h"
+#include "dbus_old_handlers.h"
+#include "dbus_common.h"
+#include "dbus_common_i.h"
+
+
+/**
+ * wpas_dbus_decompose_object_path - Decompose an interface object path into parts
+ * @path: The dbus object path
+ * @network: (out) the configured network this object path refers to, if any
+ * @bssid: (out) the scanned bssid this object path refers to, if any
+ * Returns: The object path of the network interface this path refers to
+ *
+ * For a given object path, decomposes the object path into object id, network,
+ * and BSSID parts, if those parts exist.
+ */
+char * wpas_dbus_decompose_object_path(const char *path, char **network,
+				       char **bssid)
+{
+	const unsigned int dev_path_prefix_len =
+		strlen(WPAS_DBUS_PATH_INTERFACES "/");
+	char *obj_path_only;
+	char *next_sep;
+
+	/* Be a bit paranoid about path */
+	if (!path || strncmp(path, WPAS_DBUS_PATH_INTERFACES "/",
+			     dev_path_prefix_len))
+		return NULL;
+
+	/* Ensure there's something at the end of the path */
+	if ((path + dev_path_prefix_len)[0] == '\0')
+		return NULL;
+
+	obj_path_only = os_strdup(path);
+	if (obj_path_only == NULL)
+		return NULL;
+
+	next_sep = strchr(obj_path_only + dev_path_prefix_len, '/');
+	if (next_sep != NULL) {
+		const char *net_part = strstr(next_sep,
+					      WPAS_DBUS_NETWORKS_PART "/");
+		const char *bssid_part = strstr(next_sep,
+						WPAS_DBUS_BSSIDS_PART "/");
+
+		if (network && net_part) {
+			/* Deal with a request for a configured network */
+			const char *net_name = net_part +
+				strlen(WPAS_DBUS_NETWORKS_PART "/");
+			*network = NULL;
+			if (strlen(net_name))
+				*network = os_strdup(net_name);
+		} else if (bssid && bssid_part) {
+			/* Deal with a request for a scanned BSSID */
+			const char *bssid_name = bssid_part +
+				strlen(WPAS_DBUS_BSSIDS_PART "/");
+			if (strlen(bssid_name))
+				*bssid = os_strdup(bssid_name);
+			else
+				*bssid = NULL;
+		}
+
+		/* Cut off interface object path before "/" */
+		*next_sep = '\0';
+	}
+
+	return obj_path_only;
+}
+
+
+/**
+ * wpas_dbus_new_invalid_iface_error - Return a new invalid interface error message
+ * @message: Pointer to incoming dbus message this error refers to
+ * Returns: A dbus error message
+ *
+ * Convenience function to create and return an invalid interface error
+ */
+DBusMessage * wpas_dbus_new_invalid_iface_error(DBusMessage *message)
+{
+	return dbus_message_new_error(message, WPAS_ERROR_INVALID_IFACE,
+				      "wpa_supplicant knows nothing about "
+				      "this interface.");
+}
+
+
+/**
+ * wpas_dbus_new_invalid_network_error - Return a new invalid network error message
+ * @message: Pointer to incoming dbus message this error refers to
+ * Returns: a dbus error message
+ *
+ * Convenience function to create and return an invalid network error
+ */
+DBusMessage * wpas_dbus_new_invalid_network_error(DBusMessage *message)
+{
+	return dbus_message_new_error(message, WPAS_ERROR_INVALID_NETWORK,
+				      "The requested network does not exist.");
+}
+
+
+/**
+ * wpas_dbus_new_invalid_bssid_error - Return a new invalid bssid error message
+ * @message: Pointer to incoming dbus message this error refers to
+ * Returns: a dbus error message
+ *
+ * Convenience function to create and return an invalid bssid error
+ */
+static DBusMessage * wpas_dbus_new_invalid_bssid_error(DBusMessage *message)
+{
+	return dbus_message_new_error(message, WPAS_ERROR_INVALID_BSSID,
+				      "The BSSID requested was invalid.");
+}
+
+
+/**
+ * wpas_dispatch_network_method - dispatch messages for configured networks
+ * @message: the incoming dbus message
+ * @wpa_s: a network interface's data
+ * @network_id: id of the configured network we're interested in
+ * Returns: a reply dbus message, or a dbus error message
+ *
+ * This function dispatches all incoming dbus messages for configured networks.
+ */
+static DBusMessage * wpas_dispatch_network_method(DBusMessage *message,
+						  struct wpa_supplicant *wpa_s,
+						  int network_id)
+{
+	DBusMessage *reply = NULL;
+	const char *method = dbus_message_get_member(message);
+	struct wpa_ssid *ssid;
+
+	ssid = wpa_config_get_network(wpa_s->conf, network_id);
+	if (ssid == NULL)
+		return wpas_dbus_new_invalid_network_error(message);
+
+	if (!strcmp(method, "set"))
+		reply = wpas_dbus_iface_set_network(message, wpa_s, ssid);
+	else if (!strcmp(method, "enable"))
+		reply = wpas_dbus_iface_enable_network(message, wpa_s, ssid);
+	else if (!strcmp(method, "disable"))
+		reply = wpas_dbus_iface_disable_network(message, wpa_s, ssid);
+
+	return reply;
+}
+
+
+/**
+ * wpas_dispatch_bssid_method - dispatch messages for scanned networks
+ * @message: the incoming dbus message
+ * @wpa_s: a network interface's data
+ * @bssid: bssid of the scanned network we're interested in
+ * Returns: a reply dbus message, or a dbus error message
+ *
+ * This function dispatches all incoming dbus messages for scanned networks.
+ */
+static DBusMessage * wpas_dispatch_bssid_method(DBusMessage *message,
+						struct wpa_supplicant *wpa_s,
+						const char *bssid_txt)
+{
+	u8 bssid[ETH_ALEN];
+	struct wpa_bss *bss;
+
+	if (hexstr2bin(bssid_txt, bssid, ETH_ALEN) < 0)
+		return wpas_dbus_new_invalid_bssid_error(message);
+
+	bss = wpa_bss_get_bssid(wpa_s, bssid);
+	if (bss == NULL)
+		return wpas_dbus_new_invalid_bssid_error(message);
+
+	/* Dispatch the method call against the scanned bssid */
+	if (os_strcmp(dbus_message_get_member(message), "properties") == 0)
+		return wpas_dbus_bssid_properties(message, wpa_s, bss);
+
+	return NULL;
+}
+
+
+/**
+ * wpas_iface_message_handler - Dispatch messages for interfaces or networks
+ * @connection: Connection to the system message bus
+ * @message: An incoming dbus message
+ * @user_data: A pointer to a dbus control interface data structure
+ * Returns: Whether or not the message was handled
+ *
+ * This function dispatches all incoming dbus messages for network interfaces,
+ * or objects owned by them, such as scanned BSSIDs and configured networks.
+ */
+static DBusHandlerResult wpas_iface_message_handler(DBusConnection *connection,
+						    DBusMessage *message,
+						    void *user_data)
+{
+	struct wpa_supplicant *wpa_s = user_data;
+	const char *method = dbus_message_get_member(message);
+	const char *path = dbus_message_get_path(message);
+	const char *msg_interface = dbus_message_get_interface(message);
+	char *iface_obj_path = NULL;
+	char *network = NULL;
+	char *bssid = NULL;
+	DBusMessage *reply = NULL;
+
+	/* Caller must specify a message interface */
+	if (!msg_interface)
+		goto out;
+
+	iface_obj_path = wpas_dbus_decompose_object_path(path, &network,
+	                                                 &bssid);
+	if (iface_obj_path == NULL) {
+		reply = wpas_dbus_new_invalid_iface_error(message);
+		goto out;
+	}
+
+	/* Make sure the message's object path actually refers to the
+	 * wpa_supplicant structure it's supposed to (which is wpa_s)
+	 */
+	if (wpa_supplicant_get_iface_by_dbus_path(wpa_s->global,
+	                                          iface_obj_path) != wpa_s) {
+		reply = wpas_dbus_new_invalid_iface_error(message);
+		goto out;
+	}
+
+	if (network && !strcmp(msg_interface, WPAS_DBUS_IFACE_NETWORK)) {
+		/* A method for one of this interface's configured networks */
+		int nid = strtoul(network, NULL, 10);
+		if (errno != EINVAL)
+			reply = wpas_dispatch_network_method(message, wpa_s,
+							     nid);
+		else
+			reply = wpas_dbus_new_invalid_network_error(message);
+	} else if (bssid && !strcmp(msg_interface, WPAS_DBUS_IFACE_BSSID)) {
+		/* A method for one of this interface's scanned BSSIDs */
+		reply = wpas_dispatch_bssid_method(message, wpa_s, bssid);
+	} else if (!strcmp(msg_interface, WPAS_DBUS_IFACE_INTERFACE)) {
+		/* A method for an interface only. */
+		if (!strcmp(method, "scan"))
+			reply = wpas_dbus_iface_scan(message, wpa_s);
+		else if (!strcmp(method, "scanResults"))
+			reply = wpas_dbus_iface_scan_results(message, wpa_s);
+		else if (!strcmp(method, "addNetwork"))
+			reply = wpas_dbus_iface_add_network(message, wpa_s);
+		else if (!strcmp(method, "removeNetwork"))
+			reply = wpas_dbus_iface_remove_network(message, wpa_s);
+		else if (!strcmp(method, "selectNetwork"))
+			reply = wpas_dbus_iface_select_network(message, wpa_s);
+		else if (!strcmp(method, "capabilities"))
+			reply = wpas_dbus_iface_capabilities(message, wpa_s);
+		else if (!strcmp(method, "disconnect"))
+			reply = wpas_dbus_iface_disconnect(message, wpa_s);
+		else if (!strcmp(method, "setAPScan"))
+			reply = wpas_dbus_iface_set_ap_scan(message, wpa_s);
+		else if (!strcmp(method, "setSmartcardModules"))
+			reply = wpas_dbus_iface_set_smartcard_modules(message,
+								      wpa_s);
+		else if (!strcmp(method, "state"))
+			reply = wpas_dbus_iface_get_state(message, wpa_s);
+		else if (!strcmp(method, "scanning"))
+			reply = wpas_dbus_iface_get_scanning(message, wpa_s);
+		else if (!strcmp(method, "setBlobs"))
+			reply = wpas_dbus_iface_set_blobs(message, wpa_s);
+		else if (!strcmp(method, "removeBlobs"))
+			reply = wpas_dbus_iface_remove_blobs(message, wpa_s);
+#ifdef CONFIG_WPS
+		else if (!os_strcmp(method, "wpsPbc"))
+			reply = wpas_dbus_iface_wps_pbc(message, wpa_s);
+		else if (!os_strcmp(method, "wpsPin"))
+			reply = wpas_dbus_iface_wps_pin(message, wpa_s);
+		else if (!os_strcmp(method, "wpsReg"))
+			reply = wpas_dbus_iface_wps_reg(message, wpa_s);
+#endif /* CONFIG_WPS */
+		else if (!os_strcmp(method, "flush"))
+			reply = wpas_dbus_iface_flush(message, wpa_s);
+	}
+
+	/* If the message was handled, send back the reply */
+	if (reply) {
+		if (!dbus_message_get_no_reply(message))
+			dbus_connection_send(connection, reply, NULL);
+		dbus_message_unref(reply);
+	}
+
+out:
+	os_free(iface_obj_path);
+	os_free(network);
+	os_free(bssid);
+	return reply ? DBUS_HANDLER_RESULT_HANDLED :
+		DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+
+/**
+ * wpas_message_handler - dispatch incoming dbus messages
+ * @connection: connection to the system message bus
+ * @message: an incoming dbus message
+ * @user_data: a pointer to a dbus control interface data structure
+ * Returns: whether or not the message was handled
+ *
+ * This function dispatches all incoming dbus messages to the correct
+ * handlers, depending on what the message's target object path is,
+ * and what the method call is.
+ */
+static DBusHandlerResult wpas_message_handler(DBusConnection *connection,
+	DBusMessage *message, void *user_data)
+{
+	struct wpas_dbus_priv *ctrl_iface = user_data;
+	const char *method;
+	const char *path;
+	const char *msg_interface;
+	DBusMessage *reply = NULL;
+
+	method = dbus_message_get_member(message);
+	path = dbus_message_get_path(message);
+	msg_interface = dbus_message_get_interface(message);
+	if (!method || !path || !ctrl_iface || !msg_interface)
+		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+	/* Validate the method interface */
+	if (strcmp(msg_interface, WPAS_DBUS_INTERFACE) != 0)
+		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+	if (!strcmp(path, WPAS_DBUS_PATH)) {
+		/* dispatch methods against our global dbus interface here */
+		if (!strcmp(method, "addInterface")) {
+			reply = wpas_dbus_global_add_interface(
+				message, ctrl_iface->global);
+		} else if (!strcmp(method, "removeInterface")) {
+			reply = wpas_dbus_global_remove_interface(
+				message, ctrl_iface->global);
+		} else if (!strcmp(method, "getInterface")) {
+			reply = wpas_dbus_global_get_interface(
+				message, ctrl_iface->global);
+		} else if (!strcmp(method, "setDebugParams")) {
+			reply = wpas_dbus_global_set_debugparams(
+				message, ctrl_iface->global);
+		}
+	}
+
+	/* If the message was handled, send back the reply */
+	if (reply) {
+		if (!dbus_message_get_no_reply(message))
+			dbus_connection_send(connection, reply, NULL);
+		dbus_message_unref(reply);
+	}
+
+	return reply ? DBUS_HANDLER_RESULT_HANDLED :
+		DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+
+/**
+ * wpa_supplicant_dbus_notify_scan_results - Send a scan results signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * Returns: 0 on success, -1 on failure
+ *
+ * Notify listeners that this interface has updated scan results.
+ */
+void wpa_supplicant_dbus_notify_scan_results(struct wpa_supplicant *wpa_s)
+{
+	struct wpas_dbus_priv *iface = wpa_s->global->dbus;
+	DBusMessage *_signal;
+
+	/* Do nothing if the control interface is not turned on */
+	if (iface == NULL)
+		return;
+
+	_signal = dbus_message_new_signal(wpa_s->dbus_path,
+					  WPAS_DBUS_IFACE_INTERFACE,
+					  "ScanResultsAvailable");
+	if (_signal == NULL) {
+		wpa_printf(MSG_ERROR, "dbus: Not enough memory to send scan "
+			   "results signal");
+		return;
+	}
+	dbus_connection_send(iface->con, _signal, NULL);
+	dbus_message_unref(_signal);
+}
+
+
+/**
+ * wpa_supplicant_dbus_notify_state_change - Send a state change signal
+ * @wpa_s: %wpa_supplicant network interface data
+ * @new_state: new state wpa_supplicant is entering
+ * @old_state: old state wpa_supplicant is leaving
+ * Returns: 0 on success, -1 on failure
+ *
+ * Notify listeners that wpa_supplicant has changed state
+ */
+void wpa_supplicant_dbus_notify_state_change(struct wpa_supplicant *wpa_s,
+					     enum wpa_states new_state,
+					     enum wpa_states old_state)
+{
+	struct wpas_dbus_priv *iface;
+	DBusMessage *_signal = NULL;
+	const char *new_state_str, *old_state_str;
+
+	if (wpa_s->dbus_path == NULL)
+		return; /* Skip signal since D-Bus setup is not yet ready */
+
+	/* Do nothing if the control interface is not turned on */
+	if (wpa_s->global == NULL)
+		return;
+	iface = wpa_s->global->dbus;
+	if (iface == NULL)
+		return;
+
+	/* Only send signal if state really changed */
+	if (new_state == old_state)
+		return;
+
+	_signal = dbus_message_new_signal(wpa_s->dbus_path,
+					  WPAS_DBUS_IFACE_INTERFACE,
+					  "StateChange");
+	if (_signal == NULL) {
+		wpa_printf(MSG_ERROR,
+		           "dbus: wpa_supplicant_dbus_notify_state_change: "
+		           "could not create dbus signal; likely out of "
+		           "memory");
+		return;
+	}
+
+	new_state_str = wpa_supplicant_state_txt(new_state);
+	old_state_str = wpa_supplicant_state_txt(old_state);
+	if (new_state_str == NULL || old_state_str == NULL) {
+		wpa_printf(MSG_ERROR,
+		           "dbus: wpa_supplicant_dbus_notify_state_change: "
+		           "Could not convert state strings");
+		goto out;
+	}
+
+	if (!dbus_message_append_args(_signal,
+	                              DBUS_TYPE_STRING, &new_state_str,
+	                              DBUS_TYPE_STRING, &old_state_str,
+	                              DBUS_TYPE_INVALID)) {
+		wpa_printf(MSG_ERROR,
+		           "dbus: wpa_supplicant_dbus_notify_state_change: "
+		           "Not enough memory to construct state change "
+		           "signal");
+		goto out;
+	}
+
+	dbus_connection_send(iface->con, _signal, NULL);
+
+out:
+	dbus_message_unref(_signal);
+}
+
+
+/**
+ * wpa_supplicant_dbus_notify_scanning - send scanning status
+ * @wpa_s: %wpa_supplicant network interface data
+ * Returns: 0 on success, -1 on failure
+ *
+ * Notify listeners of interface scanning state changes
+ */
+void wpa_supplicant_dbus_notify_scanning(struct wpa_supplicant *wpa_s)
+{
+	struct wpas_dbus_priv *iface = wpa_s->global->dbus;
+	DBusMessage *_signal;
+	dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
+
+	/* Do nothing if the control interface is not turned on */
+	if (iface == NULL)
+		return;
+
+	_signal = dbus_message_new_signal(wpa_s->dbus_path,
+					  WPAS_DBUS_IFACE_INTERFACE,
+					  "Scanning");
+	if (_signal == NULL) {
+		wpa_printf(MSG_ERROR, "dbus: Not enough memory to send scan "
+			   "results signal");
+		return;
+	}
+
+	if (dbus_message_append_args(_signal,
+	                             DBUS_TYPE_BOOLEAN, &scanning,
+	                             DBUS_TYPE_INVALID)) {
+		dbus_connection_send(iface->con, _signal, NULL);
+	} else {
+		wpa_printf(MSG_ERROR, "dbus: Not enough memory to construct "
+			   "signal");
+	}
+	dbus_message_unref(_signal);
+}
+
+
+#ifdef CONFIG_WPS
+void wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s,
+					 const struct wps_credential *cred)
+{
+	struct wpas_dbus_priv *iface;
+	DBusMessage *_signal = NULL;
+
+	/* Do nothing if the control interface is not turned on */
+	if (wpa_s->global == NULL)
+		return;
+	iface = wpa_s->global->dbus;
+	if (iface == NULL)
+		return;
+
+	_signal = dbus_message_new_signal(wpa_s->dbus_path,
+					  WPAS_DBUS_IFACE_INTERFACE,
+					  "WpsCred");
+	if (_signal == NULL) {
+		wpa_printf(MSG_ERROR,
+		           "dbus: wpa_supplicant_dbus_notify_wps_cred: "
+		           "Could not create dbus signal; likely out of "
+		           "memory");
+		return;
+	}
+
+	if (!dbus_message_append_args(_signal,
+	                              DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
+				      &cred->cred_attr, cred->cred_attr_len,
+	                              DBUS_TYPE_INVALID)) {
+		wpa_printf(MSG_ERROR,
+		           "dbus: wpa_supplicant_dbus_notify_wps_cred: "
+		           "Not enough memory to construct signal");
+		goto out;
+	}
+
+	dbus_connection_send(iface->con, _signal, NULL);
+
+out:
+	dbus_message_unref(_signal);
+}
+#else /* CONFIG_WPS */
+void wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s,
+					 const struct wps_credential *cred)
+{
+}
+#endif /* CONFIG_WPS */
+
+
+/**
+ * wpa_supplicant_dbus_ctrl_iface_init - Initialize dbus control interface
+ * @global: Pointer to global data from wpa_supplicant_init()
+ * Returns: 0 on success, -1 on failure
+ *
+ * Initialize the dbus control interface and start receiving commands from
+ * external programs over the bus.
+ */
+int wpa_supplicant_dbus_ctrl_iface_init(struct wpas_dbus_priv *iface)
+{
+	DBusError error;
+	int ret = -1;
+	DBusObjectPathVTable wpas_vtable = {
+		NULL, &wpas_message_handler, NULL, NULL, NULL, NULL
+	};
+
+	/* Register the message handler for the global dbus interface */
+	if (!dbus_connection_register_object_path(iface->con,
+						  WPAS_DBUS_PATH, &wpas_vtable,
+						  iface)) {
+		wpa_printf(MSG_ERROR, "dbus: Could not set up message "
+			   "handler");
+		return -1;
+	}
+
+	/* Register our service with the message bus */
+	dbus_error_init(&error);
+	switch (dbus_bus_request_name(iface->con, WPAS_DBUS_SERVICE,
+				      0, &error)) {
+	case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
+		ret = 0;
+		break;
+	case DBUS_REQUEST_NAME_REPLY_EXISTS:
+	case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
+	case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
+		wpa_printf(MSG_ERROR, "dbus: Could not request service name: "
+			   "already registered");
+		break;
+	default:
+		wpa_printf(MSG_ERROR, "dbus: Could not request service name: "
+			   "%s %s", error.name, error.message);
+		break;
+	}
+	dbus_error_free(&error);
+
+	if (ret != 0)
+		return -1;
+
+	wpa_printf(MSG_DEBUG, "Providing DBus service '" WPAS_DBUS_SERVICE
+		   "'.");
+
+	return 0;
+}
+
+
+/**
+ * wpas_dbus_register_new_iface - Register a new interface with dbus
+ * @wpa_s: %wpa_supplicant interface description structure to register
+ * Returns: 0 on success, -1 on error
+ *
+ * Registers a new interface with dbus and assigns it a dbus object path.
+ */
+int wpas_dbus_register_iface(struct wpa_supplicant *wpa_s)
+{
+	struct wpas_dbus_priv *ctrl_iface = wpa_s->global->dbus;
+	DBusConnection * con;
+	u32 next;
+	DBusObjectPathVTable vtable = {
+		NULL, &wpas_iface_message_handler, NULL, NULL, NULL, NULL
+	};
+
+	/* Do nothing if the control interface is not turned on */
+	if (ctrl_iface == NULL)
+		return 0;
+
+	con = ctrl_iface->con;
+	next = ctrl_iface->next_objid++;
+
+	/* Create and set the interface's object path */
+	wpa_s->dbus_path = os_zalloc(WPAS_DBUS_OBJECT_PATH_MAX);
+	if (wpa_s->dbus_path == NULL)
+		return -1;
+	os_snprintf(wpa_s->dbus_path, WPAS_DBUS_OBJECT_PATH_MAX,
+		    WPAS_DBUS_PATH_INTERFACES "/%u",
+		    next);
+
+	/* Register the message handler for the interface functions */
+	if (!dbus_connection_register_fallback(con, wpa_s->dbus_path, &vtable,
+					       wpa_s)) {
+		wpa_printf(MSG_ERROR, "dbus: Could not set up message "
+			   "handler for interface %s", wpa_s->ifname);
+		return -1;
+	}
+
+	return 0;
+}
+
+
+/**
+ * wpas_dbus_unregister_iface - Unregister an interface from dbus
+ * @wpa_s: wpa_supplicant interface structure
+ * Returns: 0 on success, -1 on failure
+ *
+ * Unregisters the interface with dbus
+ */
+int wpas_dbus_unregister_iface(struct wpa_supplicant *wpa_s)
+{
+	struct wpas_dbus_priv *ctrl_iface;
+	DBusConnection *con;
+
+	/* Do nothing if the control interface is not turned on */
+	if (wpa_s == NULL || wpa_s->global == NULL)
+		return 0;
+	ctrl_iface = wpa_s->global->dbus;
+	if (ctrl_iface == NULL)
+		return 0;
+
+	con = ctrl_iface->con;
+	if (!dbus_connection_unregister_object_path(con, wpa_s->dbus_path))
+		return -1;
+
+	os_free(wpa_s->dbus_path);
+	wpa_s->dbus_path = NULL;
+
+	return 0;
+}
+
+
+/**
+ * wpa_supplicant_get_iface_by_dbus_path - Get a new network interface
+ * @global: Pointer to global data from wpa_supplicant_init()
+ * @path: Pointer to a dbus object path representing an interface
+ * Returns: Pointer to the interface or %NULL if not found
+ */
+struct wpa_supplicant * wpa_supplicant_get_iface_by_dbus_path(
+	struct wpa_global *global, const char *path)
+{
+	struct wpa_supplicant *wpa_s;
+
+	for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
+		if (strcmp(wpa_s->dbus_path, path) == 0)
+			return wpa_s;
+	}
+	return NULL;
+}
diff --git a/wpa_supplicant/dbus/dbus_old.h b/wpa_supplicant/dbus/dbus_old.h
new file mode 100644
index 0000000..a9840c2
--- /dev/null
+++ b/wpa_supplicant/dbus/dbus_old.h
@@ -0,0 +1,131 @@
+/*
+ * WPA Supplicant / dbus-based control interface
+ * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
+ *
+ * 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.
+ */
+
+#ifndef CTRL_IFACE_DBUS_H
+#define CTRL_IFACE_DBUS_H
+
+struct wps_credential;
+
+#ifdef CONFIG_CTRL_IFACE_DBUS
+
+#define WPAS_DBUS_OBJECT_PATH_MAX 150
+
+#define WPAS_DBUS_SERVICE	"fi.epitest.hostap.WPASupplicant"
+#define WPAS_DBUS_PATH		"/fi/epitest/hostap/WPASupplicant"
+#define WPAS_DBUS_INTERFACE	"fi.epitest.hostap.WPASupplicant"
+
+#define WPAS_DBUS_PATH_INTERFACES	WPAS_DBUS_PATH "/Interfaces"
+#define WPAS_DBUS_IFACE_INTERFACE	WPAS_DBUS_INTERFACE ".Interface"
+
+#define WPAS_DBUS_NETWORKS_PART "Networks"
+#define WPAS_DBUS_IFACE_NETWORK	WPAS_DBUS_INTERFACE ".Network"
+
+#define WPAS_DBUS_BSSIDS_PART	"BSSIDs"
+#define WPAS_DBUS_IFACE_BSSID	WPAS_DBUS_INTERFACE ".BSSID"
+
+
+/* Errors */
+#define WPAS_ERROR_INVALID_NETWORK \
+	WPAS_DBUS_IFACE_INTERFACE ".InvalidNetwork"
+#define WPAS_ERROR_INVALID_BSSID \
+	WPAS_DBUS_IFACE_INTERFACE ".InvalidBSSID"
+
+#define WPAS_ERROR_INVALID_OPTS \
+	WPAS_DBUS_INTERFACE ".InvalidOptions"
+#define WPAS_ERROR_INVALID_IFACE \
+	WPAS_DBUS_INTERFACE ".InvalidInterface"
+
+#define WPAS_ERROR_ADD_ERROR \
+	WPAS_DBUS_INTERFACE ".AddError"
+#define WPAS_ERROR_EXISTS_ERROR \
+	WPAS_DBUS_INTERFACE ".ExistsError"
+#define WPAS_ERROR_REMOVE_ERROR \
+	WPAS_DBUS_INTERFACE ".RemoveError"
+
+#define WPAS_ERROR_SCAN_ERROR \
+	WPAS_DBUS_IFACE_INTERFACE ".ScanError"
+#define WPAS_ERROR_ADD_NETWORK_ERROR \
+	WPAS_DBUS_IFACE_INTERFACE ".AddNetworkError"
+#define WPAS_ERROR_INTERNAL_ERROR \
+	WPAS_DBUS_IFACE_INTERFACE ".InternalError"
+#define WPAS_ERROR_REMOVE_NETWORK_ERROR \
+	WPAS_DBUS_IFACE_INTERFACE ".RemoveNetworkError"
+
+#define WPAS_ERROR_WPS_PBC_ERROR \
+	WPAS_DBUS_IFACE_INTERFACE ".WpsPbcError"
+#define WPAS_ERROR_WPS_PIN_ERROR \
+	WPAS_DBUS_IFACE_INTERFACE ".WpsPinError"
+#define WPAS_ERROR_WPS_REG_ERROR \
+	WPAS_DBUS_IFACE_INTERFACE ".WpsRegError"
+
+#define WPAS_DBUS_BSSID_FORMAT "%02x%02x%02x%02x%02x%02x"
+
+struct wpa_global;
+struct wpa_supplicant;
+
+int wpa_supplicant_dbus_ctrl_iface_init(struct wpas_dbus_priv *iface);
+void wpa_supplicant_dbus_notify_scan_results(struct wpa_supplicant *wpa_s);
+void wpa_supplicant_dbus_notify_scanning(struct wpa_supplicant *wpa_s);
+void wpa_supplicant_dbus_notify_state_change(struct wpa_supplicant *wpa_s,
+					     enum wpa_states new_state,
+					     enum wpa_states old_state);
+void wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s,
+					 const struct wps_credential *cred);
+
+char * wpas_dbus_decompose_object_path(const char *path, char **network,
+                                       char **bssid);
+
+int wpas_dbus_register_iface(struct wpa_supplicant *wpa_s);
+int wpas_dbus_unregister_iface(struct wpa_supplicant *wpa_s);
+
+
+/* Methods internal to the dbus control interface */
+struct wpa_supplicant * wpa_supplicant_get_iface_by_dbus_path(
+	struct wpa_global *global, const char *path);
+
+#else /* CONFIG_CTRL_IFACE_DBUS */
+
+static inline void
+wpa_supplicant_dbus_notify_scan_results(struct wpa_supplicant *wpa_s)
+{
+}
+
+static inline void
+wpa_supplicant_dbus_notify_scanning(struct wpa_supplicant *wpa_s)
+{
+}
+
+#define wpa_supplicant_dbus_notify_state_change(w,n,o) do { } while (0)
+
+static inline void
+wpa_supplicant_dbus_notify_wps_cred(struct wpa_supplicant *wpa_s,
+				    const struct wps_credential *cred)
+{
+}
+
+static inline int
+wpas_dbus_register_iface(struct wpa_supplicant *wpa_s)
+{
+	return 0;
+}
+
+static inline int
+wpas_dbus_unregister_iface(struct wpa_supplicant *wpa_s)
+{
+	return 0;
+}
+
+#endif /* CONFIG_CTRL_IFACE_DBUS */
+
+#endif /* CTRL_IFACE_DBUS_H */
diff --git a/wpa_supplicant/dbus/dbus_old_handlers.c b/wpa_supplicant/dbus/dbus_old_handlers.c
new file mode 100644
index 0000000..de66140
--- /dev/null
+++ b/wpa_supplicant/dbus/dbus_old_handlers.c
@@ -0,0 +1,1468 @@
+/*
+ * WPA Supplicant / dbus-based control interface
+ * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
+ *
+ * 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 "includes.h"
+#include <dbus/dbus.h>
+
+#include "common.h"
+#include "eap_peer/eap_methods.h"
+#include "common/ieee802_11_defs.h"
+#include "eapol_supp/eapol_supp_sm.h"
+#include "rsn_supp/wpa.h"
+#include "../config.h"
+#include "../wpa_supplicant_i.h"
+#include "../driver_i.h"
+#include "../notify.h"
+#include "../wpas_glue.h"
+#include "../bss.h"
+#include "../scan.h"
+#include "dbus_old.h"
+#include "dbus_old_handlers.h"
+#include "dbus_dict_helpers.h"
+
+extern int wpa_debug_level;
+extern int wpa_debug_show_keys;
+extern int wpa_debug_timestamp;
+
+/**
+ * wpas_dbus_new_invalid_opts_error - Return a new invalid options error message
+ * @message: Pointer to incoming dbus message this error refers to
+ * Returns: a dbus error message
+ *
+ * Convenience function to create and return an invalid options error
+ */
+DBusMessage * wpas_dbus_new_invalid_opts_error(DBusMessage *message,
+					       const char *arg)
+{
+	DBusMessage *reply;
+
+	reply = dbus_message_new_error(message, WPAS_ERROR_INVALID_OPTS,
+				       "Did not receive correct message "
+				       "arguments.");
+	if (arg != NULL)
+		dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg,
+					 DBUS_TYPE_INVALID);
+
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_new_success_reply - Return a new success reply message
+ * @message: Pointer to incoming dbus message this reply refers to
+ * Returns: a dbus message containing a single UINT32 that indicates
+ *          success (ie, a value of 1)
+ *
+ * Convenience function to create and return a success reply message
+ */
+DBusMessage * wpas_dbus_new_success_reply(DBusMessage *message)
+{
+	DBusMessage *reply;
+	unsigned int success = 1;
+
+	reply = dbus_message_new_method_return(message);
+	dbus_message_append_args(reply, DBUS_TYPE_UINT32, &success,
+				 DBUS_TYPE_INVALID);
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_global_add_interface - Request registration of a network interface
+ * @message: Pointer to incoming dbus message
+ * @global: %wpa_supplicant global data structure
+ * Returns: The object path of the new interface object,
+ *          or a dbus error message with more information
+ *
+ * Handler function for "addInterface" method call. Handles requests
+ * by dbus clients to register a network interface that wpa_supplicant
+ * will manage.
+ */
+DBusMessage * wpas_dbus_global_add_interface(DBusMessage *message,
+					     struct wpa_global *global)
+{
+	char *ifname = NULL;
+	char *driver = NULL;
+	char *driver_param = NULL;
+	char *confname = NULL;
+	char *bridge_ifname = NULL;
+	DBusMessage *reply = NULL;
+	DBusMessageIter iter;
+
+	dbus_message_iter_init(message, &iter);
+
+	/* First argument: interface name (DBUS_TYPE_STRING)
+	 *    Required; must be non-zero length
+	 */
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+		goto error;
+	dbus_message_iter_get_basic(&iter, &ifname);
+	if (!os_strlen(ifname))
+		goto error;
+
+	/* Second argument: dict of options */
+	if (dbus_message_iter_next(&iter)) {
+		DBusMessageIter iter_dict;
+		struct wpa_dbus_dict_entry entry;
+
+		if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
+			goto error;
+		while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
+			if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
+				goto error;
+			if (!strcmp(entry.key, "driver") &&
+			    (entry.type == DBUS_TYPE_STRING)) {
+				driver = os_strdup(entry.str_value);
+				wpa_dbus_dict_entry_clear(&entry);
+				if (driver == NULL)
+					goto error;
+			} else if (!strcmp(entry.key, "driver-params") &&
+				   (entry.type == DBUS_TYPE_STRING)) {
+				driver_param = os_strdup(entry.str_value);
+				wpa_dbus_dict_entry_clear(&entry);
+				if (driver_param == NULL)
+					goto error;
+			} else if (!strcmp(entry.key, "config-file") &&
+				   (entry.type == DBUS_TYPE_STRING)) {
+				confname = os_strdup(entry.str_value);
+				wpa_dbus_dict_entry_clear(&entry);
+				if (confname == NULL)
+					goto error;
+			} else if (!strcmp(entry.key, "bridge-ifname") &&
+				   (entry.type == DBUS_TYPE_STRING)) {
+				bridge_ifname = os_strdup(entry.str_value);
+				wpa_dbus_dict_entry_clear(&entry);
+				if (bridge_ifname == NULL)
+					goto error;
+			} else {
+				wpa_dbus_dict_entry_clear(&entry);
+				goto error;
+			}
+		}
+	}
+
+	/*
+	 * Try to get the wpa_supplicant record for this iface, return
+	 * an error if we already control it.
+	 */
+	if (wpa_supplicant_get_iface(global, ifname) != NULL) {
+		reply = dbus_message_new_error(message,
+					       WPAS_ERROR_EXISTS_ERROR,
+					       "wpa_supplicant already "
+					       "controls this interface.");
+	} else {
+		struct wpa_supplicant *wpa_s;
+		struct wpa_interface iface;
+		os_memset(&iface, 0, sizeof(iface));
+		iface.ifname = ifname;
+		iface.driver = driver;
+		iface.driver_param = driver_param;
+		iface.confname = confname;
+		iface.bridge_ifname = bridge_ifname;
+		/* Otherwise, have wpa_supplicant attach to it. */
+		if ((wpa_s = wpa_supplicant_add_iface(global, &iface))) {
+			const char *path = wpa_s->dbus_path;
+			reply = dbus_message_new_method_return(message);
+			dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
+			                         &path, DBUS_TYPE_INVALID);
+		} else {
+			reply = dbus_message_new_error(message,
+						       WPAS_ERROR_ADD_ERROR,
+						       "wpa_supplicant "
+						       "couldn't grab this "
+						       "interface.");
+		}
+	}
+
+out:
+	os_free(driver);
+	os_free(driver_param);
+	os_free(confname);
+	os_free(bridge_ifname);
+	return reply;
+
+error:
+	reply = wpas_dbus_new_invalid_opts_error(message, NULL);
+	goto out;
+}
+
+
+/**
+ * wpas_dbus_global_remove_interface - Request deregistration of an interface
+ * @message: Pointer to incoming dbus message
+ * @global: wpa_supplicant global data structure
+ * Returns: a dbus message containing a UINT32 indicating success (1) or
+ *          failure (0), or returns a dbus error message with more information
+ *
+ * Handler function for "removeInterface" method call.  Handles requests
+ * by dbus clients to deregister a network interface that wpa_supplicant
+ * currently manages.
+ */
+DBusMessage * wpas_dbus_global_remove_interface(DBusMessage *message,
+						struct wpa_global *global)
+{
+	struct wpa_supplicant *wpa_s;
+	char *path;
+	DBusMessage *reply = NULL;
+
+	if (!dbus_message_get_args(message, NULL,
+				   DBUS_TYPE_OBJECT_PATH, &path,
+				   DBUS_TYPE_INVALID)) {
+		reply = wpas_dbus_new_invalid_opts_error(message, NULL);
+		goto out;
+	}
+
+	wpa_s = wpa_supplicant_get_iface_by_dbus_path(global, path);
+	if (wpa_s == NULL) {
+		reply = wpas_dbus_new_invalid_iface_error(message);
+		goto out;
+	}
+
+	if (!wpa_supplicant_remove_iface(global, wpa_s)) {
+		reply = wpas_dbus_new_success_reply(message);
+	} else {
+		reply = dbus_message_new_error(message,
+					       WPAS_ERROR_REMOVE_ERROR,
+					       "wpa_supplicant couldn't "
+					       "remove this interface.");
+	}
+
+out:
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_global_get_interface - Get the object path for an interface name
+ * @message: Pointer to incoming dbus message
+ * @global: %wpa_supplicant global data structure
+ * Returns: The object path of the interface object,
+ *          or a dbus error message with more information
+ *
+ * Handler function for "getInterface" method call. Handles requests
+ * by dbus clients for the object path of an specific network interface.
+ */
+DBusMessage * wpas_dbus_global_get_interface(DBusMessage *message,
+					     struct wpa_global *global)
+{
+	DBusMessage *reply = NULL;
+	const char *ifname;
+	const char *path;
+	struct wpa_supplicant *wpa_s;
+
+	if (!dbus_message_get_args(message, NULL,
+	                           DBUS_TYPE_STRING, &ifname,
+	                           DBUS_TYPE_INVALID)) {
+		reply = wpas_dbus_new_invalid_opts_error(message, NULL);
+		goto out;
+	}
+
+	wpa_s = wpa_supplicant_get_iface(global, ifname);
+	if (wpa_s == NULL) {
+		reply = wpas_dbus_new_invalid_iface_error(message);
+		goto out;
+	}
+
+	path = wpa_s->dbus_path;
+	reply = dbus_message_new_method_return(message);
+	dbus_message_append_args(reply,
+	                         DBUS_TYPE_OBJECT_PATH, &path,
+	                         DBUS_TYPE_INVALID);
+
+out:
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_global_set_debugparams- Set the debug params
+ * @message: Pointer to incoming dbus message
+ * @global: %wpa_supplicant global data structure
+ * Returns: a dbus message containing a UINT32 indicating success (1) or
+ *          failure (0), or returns a dbus error message with more information
+ *
+ * Handler function for "setDebugParams" method call. Handles requests
+ * by dbus clients for the object path of an specific network interface.
+ */
+DBusMessage * wpas_dbus_global_set_debugparams(DBusMessage *message,
+					       struct wpa_global *global)
+{
+	DBusMessage *reply = NULL;
+	int debug_level;
+	dbus_bool_t debug_timestamp;
+	dbus_bool_t debug_show_keys;
+
+	if (!dbus_message_get_args(message, NULL,
+	                           DBUS_TYPE_INT32, &debug_level,
+	                           DBUS_TYPE_BOOLEAN, &debug_timestamp,
+	                           DBUS_TYPE_BOOLEAN, &debug_show_keys,
+	                           DBUS_TYPE_INVALID)) {
+		return wpas_dbus_new_invalid_opts_error(message, NULL);
+	}
+
+	if (wpa_supplicant_set_debug_params(global, debug_level,
+					    debug_timestamp ? 1 : 0,
+					    debug_show_keys ? 1 : 0)) {
+		return wpas_dbus_new_invalid_opts_error(message, NULL);
+	}
+
+	reply = wpas_dbus_new_success_reply(message);
+
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_iface_scan - Request a wireless scan on an interface
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: a dbus message containing a UINT32 indicating success (1) or
+ *          failure (0)
+ *
+ * Handler function for "scan" method call of a network device. Requests
+ * that wpa_supplicant perform a wireless scan as soon as possible
+ * on a particular wireless interface.
+ */
+DBusMessage * wpas_dbus_iface_scan(DBusMessage *message,
+				   struct wpa_supplicant *wpa_s)
+{
+	wpa_s->scan_req = 2;
+	wpa_supplicant_req_scan(wpa_s, 0, 0);
+	return wpas_dbus_new_success_reply(message);
+}
+
+
+/**
+ * wpas_dbus_iface_scan_results - Get the results of a recent scan request
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: a dbus message containing a dbus array of objects paths, or returns
+ *          a dbus error message if not scan results could be found
+ *
+ * Handler function for "scanResults" method call of a network device. Returns
+ * a dbus message containing the object paths of wireless networks found.
+ */
+DBusMessage * wpas_dbus_iface_scan_results(DBusMessage *message,
+					   struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply = NULL;
+	DBusMessageIter iter;
+	DBusMessageIter sub_iter;
+	struct wpa_bss *bss;
+
+	/* Create and initialize the return message */
+	reply = dbus_message_new_method_return(message);
+	dbus_message_iter_init_append(reply, &iter);
+	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+					 DBUS_TYPE_OBJECT_PATH_AS_STRING,
+					 &sub_iter);
+
+	/* Loop through scan results and append each result's object path */
+	dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) {
+		char path_buf[WPAS_DBUS_OBJECT_PATH_MAX];
+		char *path = path_buf;
+
+		/* Construct the object path for this network.  Note that ':'
+		 * is not a valid character in dbus object paths.
+		 */
+		os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
+			    "%s/" WPAS_DBUS_BSSIDS_PART "/"
+			    WPAS_DBUS_BSSID_FORMAT,
+			    wpa_s->dbus_path, MAC2STR(bss->bssid));
+		dbus_message_iter_append_basic(&sub_iter,
+					       DBUS_TYPE_OBJECT_PATH, &path);
+	}
+
+	dbus_message_iter_close_container(&iter, &sub_iter);
+
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_bssid_properties - Return the properties of a scanned network
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * @res: wpa_supplicant scan result for which to get properties
+ * Returns: a dbus message containing the properties for the requested network
+ *
+ * Handler function for "properties" method call of a scanned network.
+ * Returns a dbus message containing the the properties.
+ */
+DBusMessage * wpas_dbus_bssid_properties(DBusMessage *message,
+					 struct wpa_supplicant *wpa_s,
+					 struct wpa_bss *bss)
+{
+	DBusMessage *reply;
+	DBusMessageIter iter, iter_dict;
+	const u8 *ie;
+
+	/* Dump the properties into a dbus message */
+	reply = dbus_message_new_method_return(message);
+
+	dbus_message_iter_init_append(reply, &iter);
+	if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
+		goto error;
+
+	if (!wpa_dbus_dict_append_byte_array(&iter_dict, "bssid",
+					     (const char *) bss->bssid,
+					     ETH_ALEN))
+		goto error;
+
+	ie = wpa_bss_get_ie(bss, WLAN_EID_SSID);
+	if (ie) {
+		if (!wpa_dbus_dict_append_byte_array(&iter_dict, "ssid",
+						     (const char *) (ie + 2),
+						     ie[1]))
+		goto error;
+	}
+
+	ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
+	if (ie) {
+		if (!wpa_dbus_dict_append_byte_array(&iter_dict, "wpaie",
+						     (const char *) ie,
+						     ie[1] + 2))
+			goto error;
+	}
+
+	ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
+	if (ie) {
+		if (!wpa_dbus_dict_append_byte_array(&iter_dict, "rsnie",
+						     (const char *) ie,
+						     ie[1] + 2))
+			goto error;
+	}
+
+	ie = wpa_bss_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE);
+	if (ie) {
+		if (!wpa_dbus_dict_append_byte_array(&iter_dict, "wpsie",
+						     (const char *) ie,
+						     ie[1] + 2))
+			goto error;
+	}
+
+	if (bss->freq) {
+		if (!wpa_dbus_dict_append_int32(&iter_dict, "frequency",
+						bss->freq))
+			goto error;
+	}
+	if (!wpa_dbus_dict_append_uint16(&iter_dict, "capabilities",
+					 bss->caps))
+		goto error;
+	if (!(bss->flags & WPA_BSS_QUAL_INVALID) &&
+	    !wpa_dbus_dict_append_int32(&iter_dict, "quality", bss->qual))
+		goto error;
+	if (!(bss->flags & WPA_BSS_NOISE_INVALID) &&
+	    !wpa_dbus_dict_append_int32(&iter_dict, "noise", bss->noise))
+		goto error;
+	if (!(bss->flags & WPA_BSS_LEVEL_INVALID) &&
+	    !wpa_dbus_dict_append_int32(&iter_dict, "level", bss->level))
+		goto error;
+	if (!wpa_dbus_dict_append_int32(&iter_dict, "maxrate",
+					wpa_bss_get_max_rate(bss) * 500000))
+		goto error;
+
+	if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
+		goto error;
+
+	return reply;
+
+error:
+	if (reply)
+		dbus_message_unref(reply);
+	return dbus_message_new_error(message, WPAS_ERROR_INTERNAL_ERROR,
+				      "an internal error occurred returning "
+				      "BSSID properties.");
+}
+
+
+/**
+ * wpas_dbus_iface_capabilities - Return interface capabilities
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: A dbus message containing a dict of strings
+ *
+ * Handler function for "capabilities" method call of an interface.
+ */
+DBusMessage * wpas_dbus_iface_capabilities(DBusMessage *message,
+					   struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply = NULL;
+	struct wpa_driver_capa capa;
+	int res;
+	DBusMessageIter iter, iter_dict;
+	char **eap_methods;
+	size_t num_items;
+	dbus_bool_t strict = FALSE;
+	DBusMessageIter iter_dict_entry, iter_dict_val, iter_array;
+
+	if (!dbus_message_get_args(message, NULL,
+				   DBUS_TYPE_BOOLEAN, &strict,
+				   DBUS_TYPE_INVALID))
+		strict = FALSE;
+
+	reply = dbus_message_new_method_return(message);
+
+	dbus_message_iter_init_append(reply, &iter);
+	if (!wpa_dbus_dict_open_write(&iter, &iter_dict))
+		goto error;
+
+	/* EAP methods */
+	eap_methods = eap_get_names_as_string_array(&num_items);
+	if (eap_methods) {
+		dbus_bool_t success = FALSE;
+		size_t i = 0;
+
+		success = wpa_dbus_dict_append_string_array(
+			&iter_dict, "eap", (const char **) eap_methods,
+			num_items);
+
+		/* free returned method array */
+		while (eap_methods[i])
+			os_free(eap_methods[i++]);
+		os_free(eap_methods);
+
+		if (!success)
+			goto error;
+	}
+
+	res = wpa_drv_get_capa(wpa_s, &capa);
+
+	/***** pairwise cipher */
+	if (res < 0) {
+		if (!strict) {
+			const char *args[] = {"CCMP", "TKIP", "NONE"};
+			if (!wpa_dbus_dict_append_string_array(
+				    &iter_dict, "pairwise", args,
+				    sizeof(args) / sizeof(char*)))
+				goto error;
+		}
+	} else {
+		if (!wpa_dbus_dict_begin_string_array(&iter_dict, "pairwise",
+						      &iter_dict_entry,
+						      &iter_dict_val,
+						      &iter_array))
+			goto error;
+
+		if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
+			if (!wpa_dbus_dict_string_array_add_element(
+				    &iter_array, "CCMP"))
+				goto error;
+		}
+
+		if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
+			if (!wpa_dbus_dict_string_array_add_element(
+				    &iter_array, "TKIP"))
+				goto error;
+		}
+
+		if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
+			if (!wpa_dbus_dict_string_array_add_element(
+				    &iter_array, "NONE"))
+				goto error;
+		}
+
+		if (!wpa_dbus_dict_end_string_array(&iter_dict,
+						    &iter_dict_entry,
+						    &iter_dict_val,
+						    &iter_array))
+			goto error;
+	}
+
+	/***** group cipher */
+	if (res < 0) {
+		if (!strict) {
+			const char *args[] = {
+				"CCMP", "TKIP", "WEP104", "WEP40"
+			};
+			if (!wpa_dbus_dict_append_string_array(
+				    &iter_dict, "group", args,
+				    sizeof(args) / sizeof(char*)))
+				goto error;
+		}
+	} else {
+		if (!wpa_dbus_dict_begin_string_array(&iter_dict, "group",
+						      &iter_dict_entry,
+						      &iter_dict_val,
+						      &iter_array))
+			goto error;
+
+		if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
+			if (!wpa_dbus_dict_string_array_add_element(
+				    &iter_array, "CCMP"))
+				goto error;
+		}
+
+		if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
+			if (!wpa_dbus_dict_string_array_add_element(
+				    &iter_array, "TKIP"))
+				goto error;
+		}
+
+		if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) {
+			if (!wpa_dbus_dict_string_array_add_element(
+				    &iter_array, "WEP104"))
+				goto error;
+		}
+
+		if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) {
+			if (!wpa_dbus_dict_string_array_add_element(
+				    &iter_array, "WEP40"))
+				goto error;
+		}
+
+		if (!wpa_dbus_dict_end_string_array(&iter_dict,
+						    &iter_dict_entry,
+						    &iter_dict_val,
+						    &iter_array))
+			goto error;
+	}
+
+	/***** key management */
+	if (res < 0) {
+		if (!strict) {
+			const char *args[] = {
+				"WPA-PSK", "WPA-EAP", "IEEE8021X", "WPA-NONE",
+				"NONE"
+			};
+			if (!wpa_dbus_dict_append_string_array(
+				    &iter_dict, "key_mgmt", args,
+				    sizeof(args) / sizeof(char*)))
+				goto error;
+		}
+	} else {
+		if (!wpa_dbus_dict_begin_string_array(&iter_dict, "key_mgmt",
+						      &iter_dict_entry,
+						      &iter_dict_val,
+						      &iter_array))
+			goto error;
+
+		if (!wpa_dbus_dict_string_array_add_element(&iter_array,
+							    "NONE"))
+			goto error;
+
+		if (!wpa_dbus_dict_string_array_add_element(&iter_array,
+							    "IEEE8021X"))
+			goto error;
+
+		if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
+				     WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
+			if (!wpa_dbus_dict_string_array_add_element(
+				    &iter_array, "WPA-EAP"))
+				goto error;
+		}
+
+		if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
+				     WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
+			if (!wpa_dbus_dict_string_array_add_element(
+				    &iter_array, "WPA-PSK"))
+				goto error;
+		}
+
+		if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
+			if (!wpa_dbus_dict_string_array_add_element(
+				    &iter_array, "WPA-NONE"))
+				goto error;
+		}
+
+		if (!wpa_dbus_dict_end_string_array(&iter_dict,
+						    &iter_dict_entry,
+						    &iter_dict_val,
+						    &iter_array))
+			goto error;
+	}
+
+	/***** WPA protocol */
+	if (res < 0) {
+		if (!strict) {
+			const char *args[] = { "RSN", "WPA" };
+			if (!wpa_dbus_dict_append_string_array(
+				    &iter_dict, "proto", args,
+				    sizeof(args) / sizeof(char*)))
+				goto error;
+		}
+	} else {
+		if (!wpa_dbus_dict_begin_string_array(&iter_dict, "proto",
+						      &iter_dict_entry,
+						      &iter_dict_val,
+						      &iter_array))
+			goto error;
+
+		if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
+				     WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
+			if (!wpa_dbus_dict_string_array_add_element(
+				    &iter_array, "RSN"))
+				goto error;
+		}
+
+		if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
+				     WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
+			if (!wpa_dbus_dict_string_array_add_element(
+				    &iter_array, "WPA"))
+				goto error;
+		}
+
+		if (!wpa_dbus_dict_end_string_array(&iter_dict,
+						    &iter_dict_entry,
+						    &iter_dict_val,
+						    &iter_array))
+			goto error;
+	}
+
+	/***** auth alg */
+	if (res < 0) {
+		if (!strict) {
+			const char *args[] = { "OPEN", "SHARED", "LEAP" };
+			if (!wpa_dbus_dict_append_string_array(
+				    &iter_dict, "auth_alg", args,
+				    sizeof(args) / sizeof(char*)))
+				goto error;
+		}
+	} else {
+		if (!wpa_dbus_dict_begin_string_array(&iter_dict, "auth_alg",
+						      &iter_dict_entry,
+						      &iter_dict_val,
+						      &iter_array))
+			goto error;
+
+		if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) {
+			if (!wpa_dbus_dict_string_array_add_element(
+				    &iter_array, "OPEN"))
+				goto error;
+		}
+
+		if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) {
+			if (!wpa_dbus_dict_string_array_add_element(
+				    &iter_array, "SHARED"))
+				goto error;
+		}
+
+		if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) {
+			if (!wpa_dbus_dict_string_array_add_element(
+				    &iter_array, "LEAP"))
+				goto error;
+		}
+
+		if (!wpa_dbus_dict_end_string_array(&iter_dict,
+						    &iter_dict_entry,
+						    &iter_dict_val,
+						    &iter_array))
+			goto error;
+	}
+
+	if (!wpa_dbus_dict_close_write(&iter, &iter_dict))
+		goto error;
+
+	return reply;
+
+error:
+	if (reply)
+		dbus_message_unref(reply);
+	return dbus_message_new_error(message, WPAS_ERROR_INTERNAL_ERROR,
+				      "an internal error occurred returning "
+				      "interface capabilities.");
+}
+
+
+/**
+ * wpas_dbus_iface_add_network - Add a new configured network
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: A dbus message containing the object path of the new network
+ *
+ * Handler function for "addNetwork" method call of a network interface.
+ */
+DBusMessage * wpas_dbus_iface_add_network(DBusMessage *message,
+					  struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply = NULL;
+	struct wpa_ssid *ssid;
+	char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf;
+
+	ssid = wpa_config_add_network(wpa_s->conf);
+	if (ssid == NULL) {
+		reply = dbus_message_new_error(message,
+					       WPAS_ERROR_ADD_NETWORK_ERROR,
+					       "wpa_supplicant could not add "
+					       "a network on this interface.");
+		goto out;
+	}
+	wpas_notify_network_added(wpa_s, ssid);
+	ssid->disabled = 1;
+	wpa_config_set_network_defaults(ssid);
+
+	/* Construct the object path for this network. */
+	os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX,
+		    "%s/" WPAS_DBUS_NETWORKS_PART "/%d",
+		    wpa_s->dbus_path, ssid->id);
+
+	reply = dbus_message_new_method_return(message);
+	dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH,
+				 &path, DBUS_TYPE_INVALID);
+
+out:
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_iface_remove_network - Remove a configured network
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: A dbus message containing a UINT32 indicating success (1) or
+ *          failure (0)
+ *
+ * Handler function for "removeNetwork" method call of a network interface.
+ */
+DBusMessage * wpas_dbus_iface_remove_network(DBusMessage *message,
+					     struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply = NULL;
+	const char *op;
+	char *iface = NULL, *net_id = NULL;
+	int id;
+	struct wpa_ssid *ssid;
+
+	if (!dbus_message_get_args(message, NULL,
+	                           DBUS_TYPE_OBJECT_PATH, &op,
+	                           DBUS_TYPE_INVALID)) {
+		reply = wpas_dbus_new_invalid_opts_error(message, NULL);
+		goto out;
+	}
+
+	/* Extract the network ID */
+	iface = wpas_dbus_decompose_object_path(op, &net_id, NULL);
+	if (iface == NULL) {
+		reply = wpas_dbus_new_invalid_network_error(message);
+		goto out;
+	}
+
+	/* Ensure the network is actually a child of this interface */
+	if (os_strcmp(iface, wpa_s->dbus_path) != 0) {
+		reply = wpas_dbus_new_invalid_network_error(message);
+		goto out;
+	}
+
+	id = strtoul(net_id, NULL, 10);
+	ssid = wpa_config_get_network(wpa_s->conf, id);
+	if (ssid == NULL) {
+		reply = wpas_dbus_new_invalid_network_error(message);
+		goto out;
+	}
+
+	wpas_notify_network_removed(wpa_s, ssid);
+
+	if (wpa_config_remove_network(wpa_s->conf, id) < 0) {
+		reply = dbus_message_new_error(message,
+					       WPAS_ERROR_REMOVE_NETWORK_ERROR,
+					       "error removing the specified "
+					       "on this interface.");
+		goto out;
+	}
+
+	if (ssid == wpa_s->current_ssid)
+		wpa_supplicant_deauthenticate(wpa_s,
+					      WLAN_REASON_DEAUTH_LEAVING);
+	reply = wpas_dbus_new_success_reply(message);
+
+out:
+	os_free(iface);
+	os_free(net_id);
+	return reply;
+}
+
+
+static const char *dont_quote[] = {
+	"key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
+	"opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path",
+	"bssid", NULL
+};
+
+
+static dbus_bool_t should_quote_opt(const char *key)
+{
+	int i = 0;
+	while (dont_quote[i] != NULL) {
+		if (strcmp(key, dont_quote[i]) == 0)
+			return FALSE;
+		i++;
+	}
+	return TRUE;
+}
+
+
+/**
+ * wpas_dbus_iface_set_network - Set options for a configured network
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * @ssid: wpa_ssid structure for a configured network
+ * Returns: a dbus message containing a UINT32 indicating success (1) or
+ *          failure (0)
+ *
+ * Handler function for "set" method call of a configured network.
+ */
+DBusMessage * wpas_dbus_iface_set_network(DBusMessage *message,
+					  struct wpa_supplicant *wpa_s,
+					  struct wpa_ssid *ssid)
+{
+	DBusMessage *reply = NULL;
+	struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
+	DBusMessageIter	iter, iter_dict;
+
+	dbus_message_iter_init(message, &iter);
+
+	if (!wpa_dbus_dict_open_read(&iter, &iter_dict)) {
+		reply = wpas_dbus_new_invalid_opts_error(message, NULL);
+		goto out;
+	}
+
+	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
+		char *value = NULL;
+		size_t size = 50;
+		int ret;
+
+		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
+			reply = wpas_dbus_new_invalid_opts_error(message,
+								 NULL);
+			goto out;
+		}
+
+		/* Type conversions, since wpa_supplicant wants strings */
+		if (entry.type == DBUS_TYPE_ARRAY &&
+		    entry.array_type == DBUS_TYPE_BYTE) {
+			if (entry.array_len <= 0)
+				goto error;
+
+			size = entry.array_len * 2 + 1;
+			value = os_zalloc(size);
+			if (value == NULL)
+				goto error;
+			ret = wpa_snprintf_hex(value, size,
+					       (u8 *) entry.bytearray_value,
+					       entry.array_len);
+			if (ret <= 0)
+				goto error;
+		} else if (entry.type == DBUS_TYPE_STRING) {
+			if (should_quote_opt(entry.key)) {
+				size = os_strlen(entry.str_value);
+				/* Zero-length option check */
+				if (size <= 0)
+					goto error;
+				size += 3;  /* For quotes and terminator */
+				value = os_zalloc(size);
+				if (value == NULL)
+					goto error;
+				ret = os_snprintf(value, size, "\"%s\"",
+						  entry.str_value);
+				if (ret < 0 || (size_t) ret != (size - 1))
+					goto error;
+			} else {
+				value = os_strdup(entry.str_value);
+				if (value == NULL)
+					goto error;
+			}
+		} else if (entry.type == DBUS_TYPE_UINT32) {
+			value = os_zalloc(size);
+			if (value == NULL)
+				goto error;
+			ret = os_snprintf(value, size, "%u",
+					  entry.uint32_value);
+			if (ret <= 0)
+				goto error;
+		} else if (entry.type == DBUS_TYPE_INT32) {
+			value = os_zalloc(size);
+			if (value == NULL)
+				goto error;
+			ret = os_snprintf(value, size, "%d",
+					  entry.int32_value);
+			if (ret <= 0)
+				goto error;
+		} else
+			goto error;
+
+		if (wpa_config_set(ssid, entry.key, value, 0) < 0)
+			goto error;
+
+		if ((os_strcmp(entry.key, "psk") == 0 &&
+		     value[0] == '"' && ssid->ssid_len) ||
+		    (os_strcmp(entry.key, "ssid") == 0 && ssid->passphrase))
+			wpa_config_update_psk(ssid);
+		else if (os_strcmp(entry.key, "priority") == 0)
+			wpa_config_update_prio_list(wpa_s->conf);
+
+		os_free(value);
+		wpa_dbus_dict_entry_clear(&entry);
+		continue;
+
+	error:
+		os_free(value);
+		reply = wpas_dbus_new_invalid_opts_error(message, entry.key);
+		wpa_dbus_dict_entry_clear(&entry);
+		break;
+	}
+
+	if (!reply)
+		reply = wpas_dbus_new_success_reply(message);
+
+out:
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_iface_enable_network - Mark a configured network as enabled
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * @ssid: wpa_ssid structure for a configured network
+ * Returns: A dbus message containing a UINT32 indicating success (1) or
+ *          failure (0)
+ *
+ * Handler function for "enable" method call of a configured network.
+ */
+DBusMessage * wpas_dbus_iface_enable_network(DBusMessage *message,
+					     struct wpa_supplicant *wpa_s,
+					     struct wpa_ssid *ssid)
+{
+	wpa_supplicant_enable_network(wpa_s, ssid);
+	return wpas_dbus_new_success_reply(message);
+}
+
+
+/**
+ * wpas_dbus_iface_disable_network - Mark a configured network as disabled
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * @ssid: wpa_ssid structure for a configured network
+ * Returns: A dbus message containing a UINT32 indicating success (1) or
+ *          failure (0)
+ *
+ * Handler function for "disable" method call of a configured network.
+ */
+DBusMessage * wpas_dbus_iface_disable_network(DBusMessage *message,
+					      struct wpa_supplicant *wpa_s,
+					      struct wpa_ssid *ssid)
+{
+	wpa_supplicant_disable_network(wpa_s, ssid);
+	return wpas_dbus_new_success_reply(message);
+}
+
+
+/**
+ * wpas_dbus_iface_select_network - Attempt association with a configured network
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: A dbus message containing a UINT32 indicating success (1) or
+ *          failure (0)
+ *
+ * Handler function for "selectNetwork" method call of network interface.
+ */
+DBusMessage * wpas_dbus_iface_select_network(DBusMessage *message,
+					     struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply = NULL;
+	const char *op;
+	struct wpa_ssid *ssid;
+	char *iface_obj_path = NULL;
+	char *network = NULL;
+
+	if (os_strlen(dbus_message_get_signature(message)) == 0) {
+		/* Any network */
+		ssid = NULL;
+	} else {
+		int nid;
+
+		if (!dbus_message_get_args(message, NULL,
+					   DBUS_TYPE_OBJECT_PATH, &op,
+					   DBUS_TYPE_INVALID)) {
+			reply = wpas_dbus_new_invalid_opts_error(message,
+								 NULL);
+			goto out;
+		}
+
+		/* Extract the network number */
+		iface_obj_path = wpas_dbus_decompose_object_path(op,
+								 &network,
+								 NULL);
+		if (iface_obj_path == NULL) {
+			reply = wpas_dbus_new_invalid_iface_error(message);
+			goto out;
+		}
+		/* Ensure the object path really points to this interface */
+		if (os_strcmp(iface_obj_path, wpa_s->dbus_path) != 0) {
+			reply = wpas_dbus_new_invalid_network_error(message);
+			goto out;
+		}
+
+		nid = strtoul(network, NULL, 10);
+		if (errno == EINVAL) {
+			reply = wpas_dbus_new_invalid_network_error(message);
+			goto out;
+		}
+
+		ssid = wpa_config_get_network(wpa_s->conf, nid);
+		if (ssid == NULL) {
+			reply = wpas_dbus_new_invalid_network_error(message);
+			goto out;
+		}
+	}
+
+	/* Finally, associate with the network */
+	wpa_supplicant_select_network(wpa_s, ssid);
+
+	reply = wpas_dbus_new_success_reply(message);
+
+out:
+	os_free(iface_obj_path);
+	os_free(network);
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_iface_disconnect - Terminate the current connection
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: A dbus message containing a UINT32 indicating success (1) or
+ *          failure (0)
+ *
+ * Handler function for "disconnect" method call of network interface.
+ */
+DBusMessage * wpas_dbus_iface_disconnect(DBusMessage *message,
+					 struct wpa_supplicant *wpa_s)
+{
+	wpa_s->disconnected = 1;
+	wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
+
+	return wpas_dbus_new_success_reply(message);
+}
+
+
+/**
+ * wpas_dbus_iface_set_ap_scan - Control roaming mode
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: A dbus message containing a UINT32 indicating success (1) or
+ *          failure (0)
+ *
+ * Handler function for "setAPScan" method call.
+ */
+DBusMessage * wpas_dbus_iface_set_ap_scan(DBusMessage *message,
+					  struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply = NULL;
+	dbus_uint32_t ap_scan = 1;
+
+	if (!dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &ap_scan,
+				   DBUS_TYPE_INVALID)) {
+		reply = wpas_dbus_new_invalid_opts_error(message, NULL);
+		goto out;
+	}
+
+	if (wpa_supplicant_set_ap_scan(wpa_s, ap_scan)) {
+		reply = wpas_dbus_new_invalid_opts_error(message, NULL);
+		goto out;
+	}
+
+	reply = wpas_dbus_new_success_reply(message);
+
+out:
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_iface_set_smartcard_modules - Set smartcard related module paths
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: A dbus message containing a UINT32 indicating success (1) or
+ *          failure (0)
+ *
+ * Handler function for "setSmartcardModules" method call.
+ */
+DBusMessage * wpas_dbus_iface_set_smartcard_modules(
+	DBusMessage *message, struct wpa_supplicant *wpa_s)
+{
+	DBusMessageIter iter, iter_dict;
+	char *opensc_engine_path = NULL;
+	char *pkcs11_engine_path = NULL;
+	char *pkcs11_module_path = NULL;
+	struct wpa_dbus_dict_entry entry;
+
+	if (!dbus_message_iter_init(message, &iter))
+		goto error;
+
+	if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
+		goto error;
+
+	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
+		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry))
+			goto error;
+		if (!strcmp(entry.key, "opensc_engine_path") &&
+		    (entry.type == DBUS_TYPE_STRING)) {
+			opensc_engine_path = os_strdup(entry.str_value);
+			if (opensc_engine_path == NULL)
+				goto error;
+		} else if (!strcmp(entry.key, "pkcs11_engine_path") &&
+			   (entry.type == DBUS_TYPE_STRING)) {
+			pkcs11_engine_path = os_strdup(entry.str_value);
+			if (pkcs11_engine_path == NULL)
+				goto error;
+		} else if (!strcmp(entry.key, "pkcs11_module_path") &&
+				 (entry.type == DBUS_TYPE_STRING)) {
+			pkcs11_module_path = os_strdup(entry.str_value);
+			if (pkcs11_module_path == NULL)
+				goto error;
+		} else {
+			wpa_dbus_dict_entry_clear(&entry);
+			goto error;
+		}
+		wpa_dbus_dict_entry_clear(&entry);
+	}
+
+	os_free(wpa_s->conf->opensc_engine_path);
+	wpa_s->conf->opensc_engine_path = opensc_engine_path;
+	os_free(wpa_s->conf->pkcs11_engine_path);
+	wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path;
+	os_free(wpa_s->conf->pkcs11_module_path);
+	wpa_s->conf->pkcs11_module_path = pkcs11_module_path;
+
+	wpa_sm_set_eapol(wpa_s->wpa, NULL);
+	eapol_sm_deinit(wpa_s->eapol);
+	wpa_s->eapol = NULL;
+	wpa_supplicant_init_eapol(wpa_s);
+	wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
+
+	return wpas_dbus_new_success_reply(message);
+
+error:
+	os_free(opensc_engine_path);
+	os_free(pkcs11_engine_path);
+	os_free(pkcs11_module_path);
+	return wpas_dbus_new_invalid_opts_error(message, NULL);
+}
+
+
+/**
+ * wpas_dbus_iface_get_state - Get interface state
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: A dbus message containing a STRING representing the current
+ *          interface state
+ *
+ * Handler function for "state" method call.
+ */
+DBusMessage * wpas_dbus_iface_get_state(DBusMessage *message,
+					struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply = NULL;
+	const char *str_state;
+
+	reply = dbus_message_new_method_return(message);
+	if (reply != NULL) {
+		str_state = wpa_supplicant_state_txt(wpa_s->wpa_state);
+		dbus_message_append_args(reply, DBUS_TYPE_STRING, &str_state,
+					 DBUS_TYPE_INVALID);
+	}
+
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_iface_get_scanning - Get interface scanning state
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: wpa_supplicant structure for a network interface
+ * Returns: A dbus message containing whether the interface is scanning
+ *
+ * Handler function for "scanning" method call.
+ */
+DBusMessage * wpas_dbus_iface_get_scanning(DBusMessage *message,
+					   struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply = NULL;
+	dbus_bool_t scanning = wpa_s->scanning ? TRUE : FALSE;
+
+	reply = dbus_message_new_method_return(message);
+	if (reply != NULL) {
+		dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &scanning,
+					 DBUS_TYPE_INVALID);
+	} else {
+		wpa_printf(MSG_ERROR, "dbus: Not enough memory to return "
+			   "scanning state");
+	}
+
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_iface_set_blobs - Store named binary blobs (ie, for certificates)
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: %wpa_supplicant data structure
+ * Returns: A dbus message containing a UINT32 indicating success (1) or
+ *          failure (0)
+ *
+ * Asks wpa_supplicant to internally store a one or more binary blobs.
+ */
+DBusMessage * wpas_dbus_iface_set_blobs(DBusMessage *message,
+					struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply = NULL;
+	struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING };
+	DBusMessageIter	iter, iter_dict;
+
+	dbus_message_iter_init(message, &iter);
+
+	if (!wpa_dbus_dict_open_read(&iter, &iter_dict))
+		return wpas_dbus_new_invalid_opts_error(message, NULL);
+
+	while (wpa_dbus_dict_has_dict_entry(&iter_dict)) {
+		struct wpa_config_blob *blob;
+
+		if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) {
+			reply = wpas_dbus_new_invalid_opts_error(message,
+								 NULL);
+			break;
+		}
+
+		if (entry.type != DBUS_TYPE_ARRAY ||
+		    entry.array_type != DBUS_TYPE_BYTE) {
+			reply = wpas_dbus_new_invalid_opts_error(
+				message, "Byte array expected.");
+			break;
+		}
+
+		if ((entry.array_len <= 0) || (entry.array_len > 65536) ||
+		    !strlen(entry.key)) {
+			reply = wpas_dbus_new_invalid_opts_error(
+				message, "Invalid array size.");
+			break;
+		}
+
+		blob = os_zalloc(sizeof(*blob));
+		if (blob == NULL) {
+			reply = dbus_message_new_error(
+				message, WPAS_ERROR_ADD_ERROR,
+				"Not enough memory to add blob.");
+			break;
+		}
+		blob->data = os_zalloc(entry.array_len);
+		if (blob->data == NULL) {
+			reply = dbus_message_new_error(
+				message, WPAS_ERROR_ADD_ERROR,
+				"Not enough memory to add blob data.");
+			os_free(blob);
+			break;
+		}
+
+		blob->name = os_strdup(entry.key);
+		blob->len = entry.array_len;
+		os_memcpy(blob->data, (u8 *) entry.bytearray_value,
+				entry.array_len);
+		if (blob->name == NULL || blob->data == NULL) {
+			wpa_config_free_blob(blob);
+			reply = dbus_message_new_error(
+				message, WPAS_ERROR_ADD_ERROR,
+				"Error adding blob.");
+			break;
+		}
+
+		/* Success */
+		if (!wpa_config_remove_blob(wpa_s->conf, blob->name))
+			wpas_notify_blob_removed(wpa_s, blob->name);
+		wpa_config_set_blob(wpa_s->conf, blob);
+		wpas_notify_blob_added(wpa_s, blob->name);
+
+		wpa_dbus_dict_entry_clear(&entry);
+	}
+	wpa_dbus_dict_entry_clear(&entry);
+
+	return reply ? reply : wpas_dbus_new_success_reply(message);
+}
+
+
+/**
+ * wpas_dbus_iface_remove_blob - Remove named binary blobs
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: %wpa_supplicant data structure
+ * Returns: A dbus message containing a UINT32 indicating success (1) or
+ *          failure (0)
+ *
+ * Asks wpa_supplicant to remove one or more previously stored binary blobs.
+ */
+DBusMessage * wpas_dbus_iface_remove_blobs(DBusMessage *message,
+					   struct wpa_supplicant *wpa_s)
+{
+	DBusMessageIter iter, array;
+	char *err_msg = NULL;
+
+	dbus_message_iter_init(message, &iter);
+
+	if ((dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY) ||
+	    (dbus_message_iter_get_element_type (&iter) != DBUS_TYPE_STRING))
+		return wpas_dbus_new_invalid_opts_error(message, NULL);
+
+	dbus_message_iter_recurse(&iter, &array);
+	while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRING) {
+		const char *name;
+
+		dbus_message_iter_get_basic(&array, &name);
+		if (!os_strlen(name))
+			err_msg = "Invalid blob name.";
+
+		if (wpa_config_remove_blob(wpa_s->conf, name) != 0)
+			err_msg = "Error removing blob.";
+		else
+			wpas_notify_blob_removed(wpa_s, name);
+		dbus_message_iter_next(&array);
+	}
+
+	if (err_msg)
+		return dbus_message_new_error(message, WPAS_ERROR_REMOVE_ERROR,
+					      err_msg);
+
+	return wpas_dbus_new_success_reply(message);
+}
+
+
+/**
+ * wpas_dbus_iface_flush - Clear BSS of old or all inactive entries
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: %wpa_supplicant data structure
+ * Returns: a dbus message containing a UINT32 indicating success (1) or
+ *          failure (0), or returns a dbus error message with more information
+ *
+ * Handler function for "flush" method call. Handles requests for an
+ * interface with an optional "age" parameter that specifies the minimum
+ * age of a BSS to be flushed.
+ */
+DBusMessage * wpas_dbus_iface_flush(DBusMessage *message,
+				    struct wpa_supplicant *wpa_s)
+{
+	int flush_age = 0;
+
+	if (os_strlen(dbus_message_get_signature(message)) != 0 &&
+	    !dbus_message_get_args(message, NULL,
+				   DBUS_TYPE_INT32, &flush_age,
+				   DBUS_TYPE_INVALID)) {
+		return wpas_dbus_new_invalid_opts_error(message, NULL);
+	}
+
+	if (flush_age == 0)
+		wpa_bss_flush(wpa_s);
+	else
+		wpa_bss_flush_by_age(wpa_s, flush_age);
+
+	return wpas_dbus_new_success_reply(message);
+}
diff --git a/wpa_supplicant/dbus/dbus_old_handlers.h b/wpa_supplicant/dbus/dbus_old_handlers.h
new file mode 100644
index 0000000..009e807
--- /dev/null
+++ b/wpa_supplicant/dbus/dbus_old_handlers.h
@@ -0,0 +1,107 @@
+/*
+ * WPA Supplicant / dbus-based control interface
+ * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
+ *
+ * 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.
+ */
+
+#ifndef CTRL_IFACE_DBUS_HANDLERS_H
+#define CTRL_IFACE_DBUS_HANDLERS_H
+
+struct wpa_bss;
+
+DBusMessage * wpas_dbus_new_invalid_iface_error(DBusMessage *message);
+DBusMessage * wpas_dbus_new_invalid_network_error(DBusMessage *message);
+
+DBusMessage * wpas_dbus_global_add_interface(DBusMessage *message,
+					     struct wpa_global *global);
+
+DBusMessage * wpas_dbus_global_remove_interface(DBusMessage *message,
+						struct wpa_global *global);
+
+DBusMessage * wpas_dbus_global_get_interface(DBusMessage *message,
+					     struct wpa_global *global);
+
+DBusMessage * wpas_dbus_global_set_debugparams(DBusMessage *message,
+					       struct wpa_global *global);
+
+DBusMessage * wpas_dbus_iface_scan(DBusMessage *message,
+				   struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_iface_scan_results(DBusMessage *message,
+					   struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_bssid_properties(DBusMessage *message,
+					 struct wpa_supplicant *wpa_s,
+					 struct wpa_bss *bss);
+
+DBusMessage * wpas_dbus_iface_capabilities(DBusMessage *message,
+					   struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_iface_add_network(DBusMessage *message,
+					  struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_iface_remove_network(DBusMessage *message,
+					     struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_iface_set_network(DBusMessage *message,
+					  struct wpa_supplicant *wpa_s,
+					  struct wpa_ssid *ssid);
+
+DBusMessage * wpas_dbus_iface_enable_network(DBusMessage *message,
+					     struct wpa_supplicant *wpa_s,
+					     struct wpa_ssid *ssid);
+
+DBusMessage * wpas_dbus_iface_disable_network(DBusMessage *message,
+					      struct wpa_supplicant *wpa_s,
+					      struct wpa_ssid *ssid);
+
+DBusMessage * wpas_dbus_iface_select_network(DBusMessage *message,
+                                             struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_iface_disconnect(DBusMessage *message,
+					 struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_iface_set_ap_scan(DBusMessage *message,
+                                          struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_iface_set_smartcard_modules(
+	DBusMessage *message, struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_iface_get_state(DBusMessage *message,
+					struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_iface_get_scanning(DBusMessage *message,
+					   struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_iface_set_blobs(DBusMessage *message,
+				        struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_iface_remove_blobs(DBusMessage *message,
+					   struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_iface_wps_pbc(DBusMessage *message,
+				      struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_iface_wps_pin(DBusMessage *message,
+				      struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_iface_wps_reg(DBusMessage *message,
+				      struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_iface_flush(DBusMessage *message,
+				    struct wpa_supplicant *wpa_s);
+
+DBusMessage * wpas_dbus_new_success_reply(DBusMessage *message);
+DBusMessage * wpas_dbus_new_invalid_opts_error(DBusMessage *message,
+					       const char *arg);
+
+#endif /* CTRL_IFACE_DBUS_HANDLERS_H */
+
diff --git a/wpa_supplicant/dbus/dbus_old_handlers_wps.c b/wpa_supplicant/dbus/dbus_old_handlers_wps.c
new file mode 100644
index 0000000..c04b844
--- /dev/null
+++ b/wpa_supplicant/dbus/dbus_old_handlers_wps.c
@@ -0,0 +1,163 @@
+/*
+ * WPA Supplicant / dbus-based control interface (WPS)
+ * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
+ *
+ * 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 "includes.h"
+#include <dbus/dbus.h>
+
+#include "common.h"
+#include "../config.h"
+#include "../wpa_supplicant_i.h"
+#include "../wps_supplicant.h"
+#include "dbus_old.h"
+#include "dbus_old_handlers.h"
+
+/**
+ * wpas_dbus_iface_wps_pbc - Request credentials using WPS PBC method
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: %wpa_supplicant data structure
+ * Returns: A dbus message containing a UINT32 indicating success (1) or
+ *          failure (0)
+ *
+ * Handler function for "wpsPbc" method call
+ */
+DBusMessage * wpas_dbus_iface_wps_pbc(DBusMessage *message,
+				      struct wpa_supplicant *wpa_s)
+{
+	char *arg_bssid = NULL;
+	u8 bssid[ETH_ALEN];
+	int ret = 0;
+
+	if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg_bssid,
+				   DBUS_TYPE_INVALID))
+		return wpas_dbus_new_invalid_opts_error(message, NULL);
+
+	if (!os_strcmp(arg_bssid, "any"))
+		ret = wpas_wps_start_pbc(wpa_s, NULL, 0);
+	else if (!hwaddr_aton(arg_bssid, bssid))
+		ret = wpas_wps_start_pbc(wpa_s, bssid, 0);
+	else {
+		return wpas_dbus_new_invalid_opts_error(message,
+							"Invalid BSSID");
+	}
+
+	if (ret < 0) {
+		return dbus_message_new_error(message,
+					      WPAS_ERROR_WPS_PBC_ERROR,
+					      "Could not start PBC "
+					      "negotiation");
+	}
+
+	return wpas_dbus_new_success_reply(message);
+}
+
+
+/**
+ * wpas_dbus_iface_wps_pin - Establish the PIN number of the enrollee
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: %wpa_supplicant data structure
+ * Returns: A dbus message containing a UINT32 indicating success (1) or
+ *          failure (0)
+ *
+ * Handler function for "wpsPin" method call
+ */
+DBusMessage * wpas_dbus_iface_wps_pin(DBusMessage *message,
+				      struct wpa_supplicant *wpa_s)
+{
+	DBusMessage *reply = NULL;
+	char *arg_bssid;
+	char *pin = NULL;
+	u8 bssid[ETH_ALEN], *_bssid = NULL;
+	int ret = 0;
+
+	if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg_bssid,
+				   DBUS_TYPE_STRING, &pin, DBUS_TYPE_INVALID))
+		return wpas_dbus_new_invalid_opts_error(message, NULL);
+
+	if (!os_strcmp(arg_bssid, "any"))
+		_bssid = NULL;
+	else if (!hwaddr_aton(arg_bssid, bssid))
+		_bssid = bssid;
+	else {
+		return wpas_dbus_new_invalid_opts_error(message,
+							"Invalid BSSID");
+	}
+
+	if (os_strlen(pin) > 0)
+		ret = wpas_wps_start_pin(wpa_s, _bssid, pin, 0,
+					 DEV_PW_DEFAULT);
+	else
+		ret = wpas_wps_start_pin(wpa_s, _bssid, NULL, 0,
+					 DEV_PW_DEFAULT);
+
+	if (ret < 0) {
+		return dbus_message_new_error(message,
+					      WPAS_ERROR_WPS_PIN_ERROR,
+					      "Could not init PIN");
+	}
+
+	reply = dbus_message_new_method_return(message);
+	if (reply == NULL)
+		return NULL;
+
+	if (ret == 0) {
+		dbus_message_append_args(reply, DBUS_TYPE_STRING, &pin,
+					 DBUS_TYPE_INVALID);
+	} else {
+		char npin[9];
+		os_snprintf(npin, sizeof(npin), "%08d", ret);
+		dbus_message_append_args(reply, DBUS_TYPE_STRING, &npin,
+					 DBUS_TYPE_INVALID);
+	}
+	return reply;
+}
+
+
+/**
+ * wpas_dbus_iface_wps_reg - Request credentials using the PIN of the AP
+ * @message: Pointer to incoming dbus message
+ * @wpa_s: %wpa_supplicant data structure
+ * Returns: A dbus message containing a UINT32 indicating success (1) or
+ *          failure (0)
+ *
+ * Handler function for "wpsReg" method call
+ */
+DBusMessage * wpas_dbus_iface_wps_reg(DBusMessage *message,
+				      struct wpa_supplicant *wpa_s)
+{
+	char *arg_bssid;
+	char *pin = NULL;
+	u8 bssid[ETH_ALEN];
+	int ret = 0;
+
+	if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg_bssid,
+				   DBUS_TYPE_STRING, &pin, DBUS_TYPE_INVALID))
+		return wpas_dbus_new_invalid_opts_error(message, NULL);
+
+	if (!os_strcmp(arg_bssid, "any"))
+		ret = wpas_wps_start_reg(wpa_s, NULL, pin, NULL);
+	else if (!hwaddr_aton(arg_bssid, bssid))
+		ret = wpas_wps_start_reg(wpa_s, bssid, pin, NULL);
+	else {
+		return wpas_dbus_new_invalid_opts_error(message,
+							"Invalid BSSID");
+	}
+
+	if (ret < 0) {
+		return dbus_message_new_error(message,
+					      WPAS_ERROR_WPS_PBC_ERROR,
+					      "Could not request credentials");
+	}
+
+	return wpas_dbus_new_success_reply(message);
+}
diff --git a/wpa_supplicant/dbus/fi.epitest.hostap.WPASupplicant.service b/wpa_supplicant/dbus/fi.epitest.hostap.WPASupplicant.service
new file mode 100644
index 0000000..a9ce1ec
--- /dev/null
+++ b/wpa_supplicant/dbus/fi.epitest.hostap.WPASupplicant.service
@@ -0,0 +1,4 @@
+[D-BUS Service]
+Name=fi.epitest.hostap.WPASupplicant
+Exec=/sbin/wpa_supplicant -u
+User=root
diff --git a/wpa_supplicant/dbus/fi.w1.wpa_supplicant1.service b/wpa_supplicant/dbus/fi.w1.wpa_supplicant1.service
new file mode 100644
index 0000000..df78471
--- /dev/null
+++ b/wpa_supplicant/dbus/fi.w1.wpa_supplicant1.service
@@ -0,0 +1,4 @@
+[D-BUS Service]
+Name=fi.w1.wpa_supplicant1
+Exec=/sbin/wpa_supplicant -u
+User=root