summary refs log tree commit diff
path: root/src/supplicant-manager
diff options
context:
space:
mode:
Diffstat (limited to 'src/supplicant-manager')
-rw-r--r--src/supplicant-manager/Makefile.am35
-rw-r--r--src/supplicant-manager/Makefile.in760
-rw-r--r--src/supplicant-manager/nm-supplicant-config.c1014
-rw-r--r--src/supplicant-manager/nm-supplicant-config.h84
-rw-r--r--src/supplicant-manager/nm-supplicant-interface.c1429
-rw-r--r--src/supplicant-manager/nm-supplicant-interface.h145
-rw-r--r--src/supplicant-manager/nm-supplicant-manager.c343
-rw-r--r--src/supplicant-manager/nm-supplicant-manager.h88
-rw-r--r--src/supplicant-manager/nm-supplicant-settings-verify.c238
-rw-r--r--src/supplicant-manager/nm-supplicant-settings-verify.h37
-rw-r--r--src/supplicant-manager/nm-supplicant-types.h28
-rw-r--r--src/supplicant-manager/tests/Makefile.am27
-rw-r--r--src/supplicant-manager/tests/Makefile.in579
-rw-r--r--src/supplicant-manager/tests/test-supplicant-config.c518
14 files changed, 5325 insertions, 0 deletions
diff --git a/src/supplicant-manager/Makefile.am b/src/supplicant-manager/Makefile.am
new file mode 100644
index 00000000..e59ae843
--- /dev/null
+++ b/src/supplicant-manager/Makefile.am
@@ -0,0 +1,35 @@
+SUBDIRS=. tests
+
+INCLUDES = \
+	-I${top_srcdir}/src \
+	-I${top_srcdir}/src/logging \
+	-I${top_srcdir}/include \
+	-I${top_srcdir}/libnm-util \
+	-I${top_builddir}/marshallers \
+	-I${top_srcdir}/src/named-manager
+
+noinst_LTLIBRARIES = libsupplicant-manager.la
+
+libsupplicant_manager_la_SOURCES = \
+	nm-supplicant-types.h \
+	nm-supplicant-manager.h \
+	nm-supplicant-manager.c \
+	nm-supplicant-config.h \
+	nm-supplicant-config.c \
+	nm-supplicant-interface.c \
+	nm-supplicant-interface.h \
+	nm-supplicant-settings-verify.h \
+	nm-supplicant-settings-verify.c
+
+libsupplicant_manager_la_CPPFLAGS = \
+	$(DBUS_CFLAGS) \
+	$(GLIB_CFLAGS) \
+	-DNM_PKGDATADIR=\"$(pkgdatadir)\" \
+	-DNM_LOCALSTATEDIR=\"$(localstatedir)\"
+
+libsupplicant_manager_la_LIBADD = \
+	$(top_builddir)/marshallers/libmarshallers.la \
+	$(top_builddir)/src/logging/libnm-logging.la \
+	$(DBUS_LIBS) \
+	$(GLIB_LIBS)
+
diff --git a/src/supplicant-manager/Makefile.in b/src/supplicant-manager/Makefile.in
new file mode 100644
index 00000000..9d326ba7
--- /dev/null
+++ b/src/supplicant-manager/Makefile.in
@@ -0,0 +1,760 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/supplicant-manager
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \
+	$(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/intltool.m4 \
+	$(top_srcdir)/m4/libnl-check.m4 $(top_srcdir)/m4/libtool.m4 \
+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libsupplicant_manager_la_DEPENDENCIES =  \
+	$(top_builddir)/marshallers/libmarshallers.la \
+	$(top_builddir)/src/logging/libnm-logging.la \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am_libsupplicant_manager_la_OBJECTS =  \
+	libsupplicant_manager_la-nm-supplicant-manager.lo \
+	libsupplicant_manager_la-nm-supplicant-config.lo \
+	libsupplicant_manager_la-nm-supplicant-interface.lo \
+	libsupplicant_manager_la-nm-supplicant-settings-verify.lo
+libsupplicant_manager_la_OBJECTS =  \
+	$(am_libsupplicant_manager_la_OBJECTS)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
+SOURCES = $(libsupplicant_manager_la_SOURCES)
+DIST_SOURCES = $(libsupplicant_manager_la_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+	html-recursive info-recursive install-data-recursive \
+	install-dvi-recursive install-exec-recursive \
+	install-html-recursive install-info-recursive \
+	install-pdf-recursive install-ps-recursive install-recursive \
+	installcheck-recursive installdirs-recursive pdf-recursive \
+	ps-recursive uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive	\
+  distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+	$(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+	distdir
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+  dir0=`pwd`; \
+  sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+  sed_rest='s,^[^/]*/*,,'; \
+  sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+  sed_butlast='s,/*[^/]*$$,,'; \
+  while test -n "$$dir1"; do \
+    first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+    if test "$$first" != "."; then \
+      if test "$$first" = ".."; then \
+        dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+        dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+      else \
+        first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+        if test "$$first2" = "$$first"; then \
+          dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+        else \
+          dir2="../$$dir2"; \
+        fi; \
+        dir0="$$dir0"/"$$first"; \
+      fi; \
+    fi; \
+    dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+  done; \
+  reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_LIBS = @DBUS_LIBS@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DHCLIENT_PATH = @DHCLIENT_PATH@
+DHCPCD_PATH = @DHCPCD_PATH@
+DISABLE_DEPRECATED = @DISABLE_DEPRECATED@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIO_CFLAGS = @GIO_CFLAGS@
+GIO_LIBS = @GIO_LIBS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GMODULE_CFLAGS = @GMODULE_CFLAGS@
+GMODULE_LIBS = @GMODULE_LIBS@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+GUDEV_CFLAGS = @GUDEV_CFLAGS@
+GUDEV_LIBS = @GUDEV_LIBS@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+IPTABLES_PATH = @IPTABLES_PATH@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBDL = @LIBDL@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBM = @LIBM@
+LIBNL_CFLAGS = @LIBNL_CFLAGS@
+LIBNL_LIBS = @LIBNL_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_LIBS = @NSS_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+POFILES = @POFILES@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@
+RANLIB = @RANLIB@
+RESOLVCONF_PATH = @RESOLVCONF_PATH@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SYSTEM_CA_PATH = @SYSTEM_CA_PATH@
+UDEV_BASE_DIR = @UDEV_BASE_DIR@
+USE_NLS = @USE_NLS@
+UUID_CFLAGS = @UUID_CFLAGS@
+UUID_LIBS = @UUID_LIBS@
+VERSION = @VERSION@
+XGETTEXT = @XGETTEXT@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = . tests
+INCLUDES = \
+	-I${top_srcdir}/src \
+	-I${top_srcdir}/src/logging \
+	-I${top_srcdir}/include \
+	-I${top_srcdir}/libnm-util \
+	-I${top_builddir}/marshallers \
+	-I${top_srcdir}/src/named-manager
+
+noinst_LTLIBRARIES = libsupplicant-manager.la
+libsupplicant_manager_la_SOURCES = \
+	nm-supplicant-types.h \
+	nm-supplicant-manager.h \
+	nm-supplicant-manager.c \
+	nm-supplicant-config.h \
+	nm-supplicant-config.c \
+	nm-supplicant-interface.c \
+	nm-supplicant-interface.h \
+	nm-supplicant-settings-verify.h \
+	nm-supplicant-settings-verify.c
+
+libsupplicant_manager_la_CPPFLAGS = \
+	$(DBUS_CFLAGS) \
+	$(GLIB_CFLAGS) \
+	-DNM_PKGDATADIR=\"$(pkgdatadir)\" \
+	-DNM_LOCALSTATEDIR=\"$(localstatedir)\"
+
+libsupplicant_manager_la_LIBADD = \
+	$(top_builddir)/marshallers/libmarshallers.la \
+	$(top_builddir)/src/logging/libnm-logging.la \
+	$(DBUS_LIBS) \
+	$(GLIB_LIBS)
+
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/supplicant-manager/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu src/supplicant-manager/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+	-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+	@list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+	  dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+	  test "$$dir" != "$$p" || dir=.; \
+	  echo "rm -f \"$${dir}/so_locations\""; \
+	  rm -f "$${dir}/so_locations"; \
+	done
+libsupplicant-manager.la: $(libsupplicant_manager_la_OBJECTS) $(libsupplicant_manager_la_DEPENDENCIES) 
+	$(LINK)  $(libsupplicant_manager_la_OBJECTS) $(libsupplicant_manager_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsupplicant_manager_la-nm-supplicant-config.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsupplicant_manager_la-nm-supplicant-interface.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsupplicant_manager_la-nm-supplicant-manager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsupplicant_manager_la-nm-supplicant-settings-verify.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@	depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@	depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@	depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LTCOMPILE) -c -o $@ $<
+
+libsupplicant_manager_la-nm-supplicant-manager.lo: nm-supplicant-manager.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsupplicant_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsupplicant_manager_la-nm-supplicant-manager.lo -MD -MP -MF $(DEPDIR)/libsupplicant_manager_la-nm-supplicant-manager.Tpo -c -o libsupplicant_manager_la-nm-supplicant-manager.lo `test -f 'nm-supplicant-manager.c' || echo '$(srcdir)/'`nm-supplicant-manager.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libsupplicant_manager_la-nm-supplicant-manager.Tpo $(DEPDIR)/libsupplicant_manager_la-nm-supplicant-manager.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-supplicant-manager.c' object='libsupplicant_manager_la-nm-supplicant-manager.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsupplicant_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsupplicant_manager_la-nm-supplicant-manager.lo `test -f 'nm-supplicant-manager.c' || echo '$(srcdir)/'`nm-supplicant-manager.c
+
+libsupplicant_manager_la-nm-supplicant-config.lo: nm-supplicant-config.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsupplicant_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsupplicant_manager_la-nm-supplicant-config.lo -MD -MP -MF $(DEPDIR)/libsupplicant_manager_la-nm-supplicant-config.Tpo -c -o libsupplicant_manager_la-nm-supplicant-config.lo `test -f 'nm-supplicant-config.c' || echo '$(srcdir)/'`nm-supplicant-config.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libsupplicant_manager_la-nm-supplicant-config.Tpo $(DEPDIR)/libsupplicant_manager_la-nm-supplicant-config.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-supplicant-config.c' object='libsupplicant_manager_la-nm-supplicant-config.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsupplicant_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsupplicant_manager_la-nm-supplicant-config.lo `test -f 'nm-supplicant-config.c' || echo '$(srcdir)/'`nm-supplicant-config.c
+
+libsupplicant_manager_la-nm-supplicant-interface.lo: nm-supplicant-interface.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsupplicant_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsupplicant_manager_la-nm-supplicant-interface.lo -MD -MP -MF $(DEPDIR)/libsupplicant_manager_la-nm-supplicant-interface.Tpo -c -o libsupplicant_manager_la-nm-supplicant-interface.lo `test -f 'nm-supplicant-interface.c' || echo '$(srcdir)/'`nm-supplicant-interface.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libsupplicant_manager_la-nm-supplicant-interface.Tpo $(DEPDIR)/libsupplicant_manager_la-nm-supplicant-interface.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-supplicant-interface.c' object='libsupplicant_manager_la-nm-supplicant-interface.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsupplicant_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsupplicant_manager_la-nm-supplicant-interface.lo `test -f 'nm-supplicant-interface.c' || echo '$(srcdir)/'`nm-supplicant-interface.c
+
+libsupplicant_manager_la-nm-supplicant-settings-verify.lo: nm-supplicant-settings-verify.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsupplicant_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsupplicant_manager_la-nm-supplicant-settings-verify.lo -MD -MP -MF $(DEPDIR)/libsupplicant_manager_la-nm-supplicant-settings-verify.Tpo -c -o libsupplicant_manager_la-nm-supplicant-settings-verify.lo `test -f 'nm-supplicant-settings-verify.c' || echo '$(srcdir)/'`nm-supplicant-settings-verify.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libsupplicant_manager_la-nm-supplicant-settings-verify.Tpo $(DEPDIR)/libsupplicant_manager_la-nm-supplicant-settings-verify.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-supplicant-settings-verify.c' object='libsupplicant_manager_la-nm-supplicant-settings-verify.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsupplicant_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsupplicant_manager_la-nm-supplicant-settings-verify.lo `test -f 'nm-supplicant-settings-verify.c' || echo '$(srcdir)/'`nm-supplicant-settings-verify.c
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+	@fail= failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+	@fail= failcom='exit 1'; \
+	for f in x $$MAKEFLAGS; do \
+	  case $$f in \
+	    *=* | --[!k]*);; \
+	    *k*) failcom='fail=yes';; \
+	  esac; \
+	done; \
+	dot_seen=no; \
+	case "$@" in \
+	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+	  *) list='$(SUBDIRS)' ;; \
+	esac; \
+	rev=''; for subdir in $$list; do \
+	  if test "$$subdir" = "."; then :; else \
+	    rev="$$subdir $$rev"; \
+	  fi; \
+	done; \
+	rev="$$rev ."; \
+	target=`echo $@ | sed s/-recursive//`; \
+	for subdir in $$rev; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done && test -z "$$fail"
+tags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+	done
+ctags-recursive:
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+	done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	set x; \
+	here=`pwd`; \
+	if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+	  include_option=--etags-include; \
+	  empty_fix=.; \
+	else \
+	  include_option=--include; \
+	  empty_fix=; \
+	fi; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test ! -f $$subdir/TAGS || \
+	      set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+	  fi; \
+	done; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+	@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test -d "$(distdir)/$$subdir" \
+	    || $(MKDIR_P) "$(distdir)/$$subdir" \
+	    || exit 1; \
+	  fi; \
+	done
+	@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+	    $(am__relativize); \
+	    new_distdir=$$reldir; \
+	    dir1=$$subdir; dir2="$(top_distdir)"; \
+	    $(am__relativize); \
+	    new_top_distdir=$$reldir; \
+	    echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+	    echo "     am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+	    ($(am__cd) $$subdir && \
+	      $(MAKE) $(AM_MAKEFLAGS) \
+	        top_distdir="$$new_top_distdir" \
+	        distdir="$$new_distdir" \
+		am__remove_distdir=: \
+		am__skip_length_check=: \
+		am__skip_mode_fix=: \
+	        distdir) \
+	      || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(LTLIBRARIES)
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+	mostlyclean-am
+
+distclean: distclean-recursive
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+	install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+	all all-am check check-am clean clean-generic clean-libtool \
+	clean-noinstLTLIBRARIES ctags ctags-recursive distclean \
+	distclean-compile distclean-generic distclean-libtool \
+	distclean-tags distdir dvi dvi-am html html-am info info-am \
+	install install-am install-data install-data-am install-dvi \
+	install-dvi-am install-exec install-exec-am install-html \
+	install-html-am install-info install-info-am install-man \
+	install-pdf install-pdf-am install-ps install-ps-am \
+	install-strip installcheck installcheck-am installdirs \
+	installdirs-am maintainer-clean maintainer-clean-generic \
+	mostlyclean mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \
+	uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/supplicant-manager/nm-supplicant-config.c b/src/supplicant-manager/nm-supplicant-config.c
new file mode 100644
index 00000000..b516de52
--- /dev/null
+++ b/src/supplicant-manager/nm-supplicant-config.c
@@ -0,0 +1,1014 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2006 - 2010 Red Hat, Inc.
+ * Copyright (C) 2007 - 2008 Novell, Inc.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+#include <glib.h>
+#include <netinet/ether.h>
+#include <dbus/dbus-glib.h>
+
+#include "nm-supplicant-config.h"
+#include "nm-supplicant-settings-verify.h"
+#include "nm-logging.h"
+#include "nm-setting.h"
+#include "NetworkManagerUtils.h"
+
+static char *hexstr2bin (const char *hex, size_t len);
+
+#define NM_SUPPLICANT_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
+                                             NM_TYPE_SUPPLICANT_CONFIG, \
+                                             NMSupplicantConfigPrivate))
+
+G_DEFINE_TYPE (NMSupplicantConfig, nm_supplicant_config, G_TYPE_OBJECT)
+
+typedef struct {
+	char *value;
+	guint32 len;	
+	OptType type;
+} ConfigOption;
+
+typedef struct
+{
+	GHashTable *config;
+	GHashTable *blobs;
+	guint32    ap_scan;
+	gboolean   dispose_has_run;
+} NMSupplicantConfigPrivate;
+
+NMSupplicantConfig *
+nm_supplicant_config_new (void)
+{
+	return g_object_new (NM_TYPE_SUPPLICANT_CONFIG, NULL);
+}
+
+static void
+config_option_free (ConfigOption *opt)
+{
+	g_free (opt->value);
+	g_slice_free (ConfigOption, opt);
+}
+
+static void
+blob_free (GByteArray *array)
+{
+	g_byte_array_free (array, TRUE);
+}
+
+static void
+nm_supplicant_config_init (NMSupplicantConfig * self)
+{
+	NMSupplicantConfigPrivate *priv = NM_SUPPLICANT_CONFIG_GET_PRIVATE (self);
+
+	priv->config = g_hash_table_new_full (g_str_hash, g_str_equal,
+	                                      (GDestroyNotify) g_free,
+	                                      (GDestroyNotify) config_option_free);
+
+	priv->blobs = g_hash_table_new_full (g_str_hash, g_str_equal,
+	                                     (GDestroyNotify) g_free,
+	                                     (GDestroyNotify) blob_free);
+
+	priv->ap_scan = 1;
+	priv->dispose_has_run = FALSE;
+}
+
+static gboolean
+nm_supplicant_config_add_option_with_type (NMSupplicantConfig *self,
+                                           const char *key,
+                                           const char *value,
+                                           gint32 len,
+                                           OptType opt_type,
+                                           gboolean secret)
+{
+	NMSupplicantConfigPrivate *priv;
+	ConfigOption *old_opt;
+	ConfigOption *opt;
+	OptType type;
+
+	g_return_val_if_fail (NM_IS_SUPPLICANT_CONFIG (self), FALSE);
+	g_return_val_if_fail (key != NULL, FALSE);
+	g_return_val_if_fail (value != NULL, FALSE);
+
+	priv = NM_SUPPLICANT_CONFIG_GET_PRIVATE (self);
+
+	if (len < 0)
+		len = strlen (value);
+
+	if (opt_type != TYPE_INVALID)
+		type = opt_type;
+	else {
+		type = nm_supplicant_settings_verify_setting (key, value, len);
+		if (type == TYPE_INVALID) {
+			char buf[255];
+			memset (&buf[0], 0, sizeof (buf));
+			memcpy (&buf[0], value, len > 254 ? 254 : len);
+			nm_log_warn (LOGD_SUPPLICANT, "Key '%s' and/or value '%s' invalid.", key, buf);
+			return FALSE;
+		}
+	}
+
+	old_opt = (ConfigOption *) g_hash_table_lookup (priv->config, key);
+	if (old_opt) {
+		nm_log_warn (LOGD_SUPPLICANT, "Key '%s' already in table.", key);
+		return FALSE;
+	}
+
+	opt = g_slice_new0 (ConfigOption);
+	if (opt == NULL) {
+		nm_log_warn (LOGD_SUPPLICANT, "Couldn't allocate memory for new config option.");
+		return FALSE;
+	}
+
+	opt->value = g_malloc0 ((sizeof (char) * len) + 1);
+	if (opt->value == NULL) {
+		nm_log_warn (LOGD_SUPPLICANT, "Couldn't allocate memory for new config option value.");
+		g_slice_free (ConfigOption, opt);
+		return FALSE;
+	}
+	memcpy (opt->value, value, len);
+
+	opt->len = len;
+	opt->type = type;	
+
+	{
+		char buf[255];
+		memset (&buf[0], 0, sizeof (buf));
+		memcpy (&buf[0], opt->value, opt->len > 254 ? 254 : opt->len);
+		nm_log_info (LOGD_SUPPLICANT, "Config: added '%s' value '%s'", key, secret ? "<omitted>" : &buf[0]);
+	}
+
+	g_hash_table_insert (priv->config, g_strdup (key), opt);
+
+	return TRUE;
+}
+
+static gboolean
+nm_supplicant_config_add_option (NMSupplicantConfig *self,
+                                 const char *key,
+                                 const char *value,
+                                 gint32 len,
+                                 gboolean secret)
+{
+	return nm_supplicant_config_add_option_with_type (self, key, value, len, TYPE_INVALID, secret);
+}
+
+static gboolean
+nm_supplicant_config_add_blob (NMSupplicantConfig *self,
+                               const char *key,
+                               const GByteArray *value,
+                               const char *blobid)
+{
+	NMSupplicantConfigPrivate *priv;
+	ConfigOption *old_opt;
+	ConfigOption *opt;
+	OptType type;
+	GByteArray *blob;
+
+	g_return_val_if_fail (NM_IS_SUPPLICANT_CONFIG (self), FALSE);
+	g_return_val_if_fail (key != NULL, FALSE);
+	g_return_val_if_fail (value != NULL, FALSE);
+	g_return_val_if_fail (value->len > 0, FALSE);
+	g_return_val_if_fail (blobid != NULL, FALSE);
+
+	priv = NM_SUPPLICANT_CONFIG_GET_PRIVATE (self);
+
+	type = nm_supplicant_settings_verify_setting (key, (const char *) value->data, value->len);
+	if (type == TYPE_INVALID) {
+		nm_log_warn (LOGD_SUPPLICANT, "Key '%s' and/or it's contained value is invalid.", key);
+		return FALSE;
+	}
+
+	old_opt = (ConfigOption *) g_hash_table_lookup (priv->config, key);
+	if (old_opt) {
+		nm_log_warn (LOGD_SUPPLICANT, "Key '%s' already in table.", key);
+		return FALSE;
+	}
+
+	blob = g_byte_array_sized_new (value->len);
+	if (!blob) {
+		nm_log_warn (LOGD_SUPPLICANT, "Couldn't allocate memory for new config blob.");
+		return FALSE;
+	}
+	g_byte_array_append (blob, value->data, value->len);
+
+	opt = g_slice_new0 (ConfigOption);
+	if (opt == NULL) {
+		nm_log_warn (LOGD_SUPPLICANT, "Couldn't allocate memory for new config option.");
+		g_byte_array_free (blob, TRUE);
+		return FALSE;
+	}
+
+	opt->value = g_strdup_printf ("blob://%s", blobid);
+	if (opt->value == NULL) {
+		nm_log_warn (LOGD_SUPPLICANT, "Couldn't allocate memory for new config option value.");
+		g_byte_array_free (blob, TRUE);
+		g_slice_free (ConfigOption, opt);
+		return FALSE;
+	}
+
+	opt->len = strlen (opt->value);
+	opt->type = type;	
+
+	nm_log_info (LOGD_SUPPLICANT, "Config: added '%s' value '%s'", key, opt->value);
+
+	g_hash_table_insert (priv->config, g_strdup (key), opt);
+	g_hash_table_insert (priv->blobs, g_strdup (blobid), blob);
+
+	return TRUE;
+}
+
+static void
+nm_supplicant_config_finalize (GObject *object)
+{
+	/* Complete object destruction */
+	g_hash_table_destroy (NM_SUPPLICANT_CONFIG_GET_PRIVATE (object)->config);
+	g_hash_table_destroy (NM_SUPPLICANT_CONFIG_GET_PRIVATE (object)->blobs);
+
+	/* Chain up to the parent class */
+	G_OBJECT_CLASS (nm_supplicant_config_parent_class)->finalize (object);
+}
+
+
+static void
+nm_supplicant_config_class_init (NMSupplicantConfigClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	object_class->finalize = nm_supplicant_config_finalize;
+
+	g_type_class_add_private (object_class, sizeof (NMSupplicantConfigPrivate));
+}
+
+guint32
+nm_supplicant_config_get_ap_scan (NMSupplicantConfig * self)
+{
+	g_return_val_if_fail (NM_IS_SUPPLICANT_CONFIG (self), 1);
+
+	return NM_SUPPLICANT_CONFIG_GET_PRIVATE (self)->ap_scan;
+}
+
+void
+nm_supplicant_config_set_ap_scan (NMSupplicantConfig * self,
+                                  guint32 ap_scan)
+{
+	g_return_if_fail (NM_IS_SUPPLICANT_CONFIG (self));
+	g_return_if_fail (ap_scan >= 0 && ap_scan <= 2);
+
+	NM_SUPPLICANT_CONFIG_GET_PRIVATE (self)->ap_scan = ap_scan;
+}
+
+static void
+get_hash_cb (gpointer key, gpointer value, gpointer user_data)
+{
+	ConfigOption *opt = (ConfigOption *) value;
+	GValue *variant;
+	GByteArray *array;
+
+	variant = g_slice_new0 (GValue);
+
+	switch (opt->type) {
+	case TYPE_INT:
+		g_value_init (variant, G_TYPE_INT);
+		g_value_set_int (variant, atoi (opt->value));
+		break;
+	case TYPE_BYTES:
+		array = g_byte_array_sized_new (opt->len);
+		g_byte_array_append (array, (const guint8 *) opt->value, opt->len);
+		g_value_init (variant, DBUS_TYPE_G_UCHAR_ARRAY);
+		g_value_set_boxed (variant, array);
+		g_byte_array_free (array, TRUE);
+		break;
+	case TYPE_KEYWORD:
+	case TYPE_STRING:
+		g_value_init (variant, G_TYPE_STRING);
+		g_value_set_string (variant, opt->value);
+		break;
+	default:
+		g_slice_free (GValue, variant);
+		return;
+	}
+
+	g_hash_table_insert ((GHashTable *) user_data, g_strdup (key), variant);
+}
+
+static void
+destroy_hash_value (gpointer data)
+{
+	GValue *value = (GValue *) data;
+
+	g_value_unset (value);
+	g_slice_free (GValue, value);
+}
+
+GHashTable *
+nm_supplicant_config_get_hash (NMSupplicantConfig * self)
+{
+	NMSupplicantConfigPrivate *priv;
+	GHashTable *hash;
+
+	g_return_val_if_fail (NM_IS_SUPPLICANT_CONFIG (self), NULL);
+
+	hash = g_hash_table_new_full (g_str_hash, g_str_equal,
+	                              (GDestroyNotify) g_free,
+	                              destroy_hash_value);
+
+	priv = NM_SUPPLICANT_CONFIG_GET_PRIVATE (self);
+	g_hash_table_foreach (priv->config, get_hash_cb, hash);
+	return hash;
+}
+
+GHashTable *
+nm_supplicant_config_get_blobs (NMSupplicantConfig * self)
+{
+	g_return_val_if_fail (NM_IS_SUPPLICANT_CONFIG (self), NULL);
+
+	return NM_SUPPLICANT_CONFIG_GET_PRIVATE (self)->blobs;
+}
+
+#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
+#define MAC_ARG(x) ((guint8*)(x))[0],((guint8*)(x))[1],((guint8*)(x))[2],((guint8*)(x))[3],((guint8*)(x))[4],((guint8*)(x))[5]
+
+gboolean
+nm_supplicant_config_add_setting_wireless (NMSupplicantConfig * self,
+                                           NMSettingWireless * setting,
+                                           gboolean is_broadcast,
+                                           guint32 adhoc_freq,
+                                           gboolean has_scan_capa_ssid)
+{
+	NMSupplicantConfigPrivate *priv;
+	gboolean is_adhoc;
+	const char *mode;
+	const GByteArray *id;
+
+	g_return_val_if_fail (NM_IS_SUPPLICANT_CONFIG (self), FALSE);
+	g_return_val_if_fail (setting != NULL, FALSE);
+
+	priv = NM_SUPPLICANT_CONFIG_GET_PRIVATE (self);
+
+	mode = nm_setting_wireless_get_mode (setting);
+	is_adhoc = (mode && !strcmp (mode, "adhoc")) ? TRUE : FALSE;
+	if (is_adhoc)
+		priv->ap_scan = 2;
+	else if (is_broadcast == FALSE) {
+		/* drivers that support scanning specific SSIDs should use
+		 * ap_scan=1, while those that do not should use ap_scan=2.
+		 */
+		priv->ap_scan = has_scan_capa_ssid ? 1 : 2;
+	}
+
+	id = nm_setting_wireless_get_ssid (setting);
+	if (!nm_supplicant_config_add_option (self, "ssid", (char *) id->data, id->len, FALSE)) {
+		nm_log_warn (LOGD_SUPPLICANT, "Error adding SSID to supplicant config.");
+		return FALSE;
+	}
+
+	if (is_adhoc) {
+		if (!nm_supplicant_config_add_option (self, "mode", "1", -1, FALSE)) {
+			nm_log_warn (LOGD_SUPPLICANT, "Error adding mode to supplicant config.");
+			return FALSE;
+		}
+
+		if (adhoc_freq) {
+			char *str_freq;
+
+			str_freq = g_strdup_printf ("%u", adhoc_freq);
+			if (!nm_supplicant_config_add_option (self, "frequency", str_freq, -1, FALSE)) {
+				g_free (str_freq);
+				nm_log_warn (LOGD_SUPPLICANT, "Error adding Ad-Hoc frequency to supplicant config.");
+				return FALSE;
+			}
+			g_free (str_freq);
+		}
+	}
+
+	/* Except for Ad-Hoc networks, request that the driver probe for the
+	 * specific SSID we want to associate with.
+	 */
+	if (!is_adhoc) {
+		if (!nm_supplicant_config_add_option (self, "scan_ssid", "1", -1, FALSE))
+			return FALSE;
+	}
+
+	id = nm_setting_wireless_get_bssid (setting);
+	if (id && id->len) {
+		char *str_bssid;
+
+		str_bssid = g_strdup_printf (MAC_FMT, MAC_ARG (id->data));
+		if (!nm_supplicant_config_add_option (self, "bssid",
+		                                      str_bssid, strlen (str_bssid),
+		                                      FALSE)) {
+			g_free (str_bssid);
+			nm_log_warn (LOGD_SUPPLICANT, "Error adding BSSID to supplicant config.");
+			return FALSE;
+		}
+		g_free (str_bssid);
+	}
+
+	// FIXME: band & channel config items
+	
+	return TRUE;
+}
+
+static gboolean
+add_string_val (NMSupplicantConfig *self,
+                const char *field,
+                const char *name,
+                gboolean ucase,
+                gboolean secret)
+{
+	gboolean success;
+	char *value;
+
+	if (!field)
+		return TRUE;
+
+	value = ucase ? g_ascii_strup (field, -1) : g_strdup (field);
+	success = nm_supplicant_config_add_option (self, name, value, strlen (field), secret);
+	if (!success)
+		nm_log_warn (LOGD_SUPPLICANT, "Error adding %s to supplicant config.", name);
+	g_free (value);
+	return success;
+}
+
+#define ADD_STRING_LIST_VAL(setting, setting_name, field, field_plural, name, ucase, secret) \
+	if (nm_setting_##setting_name##_get_num_##field_plural (setting)) { \
+		guint32 k; \
+		GString *str = g_string_new (NULL); \
+		for (k = 0; k < nm_setting_##setting_name##_get_num_##field_plural (setting); k++) { \
+			const char *item = nm_setting_##setting_name##_get_##field (setting, k); \
+			if (!str->len) { \
+				g_string_append (str, item); \
+			} else { \
+				g_string_append_c (str, ' '); \
+				g_string_append (str, item); \
+			} \
+		} \
+		if (ucase) \
+			g_string_ascii_up (str); \
+		if (str->len) \
+			success = nm_supplicant_config_add_option (self, name, str->str, -1, secret); \
+		else \
+			success = TRUE; \
+		g_string_free (str, TRUE); \
+		if (!success) { \
+			nm_log_warn (LOGD_SUPPLICANT, "Error adding %s to supplicant config.", name); \
+			return FALSE; \
+		} \
+	}
+
+static char *
+get_blob_id (const char *name, const char *seed_uid)
+{
+	char *uid = g_strdup_printf ("%s-%s", seed_uid, name);
+	char *p = uid;
+	while (*p) {
+		if (*p == '/') *p = '-';
+		p++;
+	}
+	return uid;
+}
+
+#define ADD_BLOB_VAL(field, name, con_uid) \
+	if (field && field->len) { \
+		char *uid = get_blob_id (name, con_uid); \
+		success = nm_supplicant_config_add_blob (self, name, field, uid); \
+		g_free (uid); \
+		if (!success) { \
+			nm_log_warn (LOGD_SUPPLICANT, "Error adding %s to supplicant config.", name); \
+			return FALSE; \
+		} \
+	}
+
+
+static gboolean
+wep128_passphrase_hash (const char *input,
+                        size_t input_len,
+                        guint8 *out_digest,
+                        size_t *out_digest_len)
+{
+	GChecksum *sum;
+	guint8 data[64];
+	int i;
+
+	g_return_val_if_fail (out_digest != NULL, FALSE);
+	g_return_val_if_fail (out_digest_len != NULL, FALSE);
+	g_return_val_if_fail (*out_digest_len >= 16, FALSE);
+
+	/* Get at least 64 bytes by repeating the passphrase into the buffer */
+	for (i = 0; i < sizeof (data); i++)
+		data[i] = input[i % input_len];
+
+	sum = g_checksum_new (G_CHECKSUM_MD5);
+	g_assert (sum);
+	g_checksum_update (sum, data, sizeof (data));
+	g_checksum_get_digest (sum, out_digest, out_digest_len);
+	g_checksum_free (sum);
+
+	g_assert (*out_digest_len == 16);
+	/* WEP104 keys are 13 bytes in length (26 hex characters) */
+	*out_digest_len = 13;
+	return TRUE;
+}
+
+static gboolean
+add_wep_key (NMSupplicantConfig *self,
+             const char *key,
+             const char *name,
+             NMWepKeyType wep_type)
+{
+	char *value;
+	gboolean success;
+	size_t key_len = key ? strlen (key) : 0;
+
+	if (!key || !key_len)
+		return TRUE;
+
+	if (   (wep_type == NM_WEP_KEY_TYPE_UNKNOWN)
+	    || (wep_type == NM_WEP_KEY_TYPE_KEY)) {
+		if ((key_len == 10) || (key_len == 26)) {
+			value = hexstr2bin (key, strlen (key));
+			success = nm_supplicant_config_add_option (self, name, value, key_len / 2, TRUE);
+			g_free (value);
+			if (!success) {
+				nm_log_warn (LOGD_SUPPLICANT, "Error adding %s to supplicant config.", name);
+				return FALSE;
+			}
+		} else if ((key_len == 5) || (key_len == 13)) {
+			if (!nm_supplicant_config_add_option (self, name, key, key_len, TRUE)) {
+				nm_log_warn (LOGD_SUPPLICANT, "Error adding %s to supplicant config.", name);
+				return FALSE;
+			}
+		} else {
+			nm_log_warn (LOGD_SUPPLICANT, "Invalid WEP key '%s'", name);
+			return FALSE;
+		}
+	} else if (wep_type == NM_WEP_KEY_TYPE_PASSPHRASE) {
+		guint8 digest[16];
+		size_t digest_len = sizeof (digest);
+
+		success = wep128_passphrase_hash (key, key_len, digest, &digest_len);
+		if (success)
+			success = nm_supplicant_config_add_option (self, name, (const char *) digest, digest_len, TRUE);
+		if (!success) {
+			nm_log_warn (LOGD_SUPPLICANT, "Error adding %s to supplicant config.", name);
+			return FALSE;
+		}
+	}
+
+	return TRUE;
+}
+
+gboolean
+nm_supplicant_config_add_setting_wireless_security (NMSupplicantConfig *self,
+                                                    NMSettingWirelessSecurity *setting,
+                                                    NMSetting8021x *setting_8021x,
+                                                    const char *connection_uid)
+{
+	char *value;
+	gboolean success;
+	const char *key_mgmt, *auth_alg;
+	const char *psk;
+
+	g_return_val_if_fail (NM_IS_SUPPLICANT_CONFIG (self), FALSE);
+	g_return_val_if_fail (setting != NULL, FALSE);
+	g_return_val_if_fail (connection_uid != NULL, FALSE);
+
+	key_mgmt = nm_setting_wireless_security_get_key_mgmt (setting);
+	if (!add_string_val (self, key_mgmt, "key_mgmt", TRUE, FALSE))
+		return FALSE;
+
+	auth_alg = nm_setting_wireless_security_get_auth_alg (setting);
+	if (!add_string_val (self, auth_alg, "auth_alg", TRUE, FALSE))
+		return FALSE;
+
+	psk = nm_setting_wireless_security_get_psk (setting);
+	if (psk) {
+		size_t psk_len = strlen (psk);
+
+		if (psk_len == 64) {
+			/* Hex PSK */
+			value = hexstr2bin (psk, psk_len);
+			success = nm_supplicant_config_add_option (self, "psk", value, psk_len / 2, TRUE);
+			g_free (value);
+			if (!success) {
+				nm_log_warn (LOGD_SUPPLICANT, "Error adding 'psk' to supplicant config.");
+				return FALSE;
+			}
+		} else if (psk_len >= 8 && psk_len <= 63) {
+			/* Use TYPE_STRING here so that it gets pushed to the
+			 * supplicant as a string, and therefore gets quoted,
+			 * and therefore the supplicant will interpret it as a
+			 * passphrase and not a hex key.
+			 */
+			if (!nm_supplicant_config_add_option_with_type (self, "psk", psk, -1, TYPE_STRING, TRUE)) {
+				nm_log_warn (LOGD_SUPPLICANT, "Error adding 'psk' to supplicant config.");
+				return FALSE;
+			}
+		} else {
+			/* Invalid PSK */
+			nm_log_warn (LOGD_SUPPLICANT, "Invalid PSK length %u: not between 8 and 63 characters inclusive.", (guint32) psk_len);
+			return FALSE;
+		}
+	}
+
+	/* Only WPA-specific things when using WPA */
+	if (   !strcmp (key_mgmt, "wpa-none")
+	    || !strcmp (key_mgmt, "wpa-psk")
+	    || !strcmp (key_mgmt, "wpa-eap")) {
+		ADD_STRING_LIST_VAL (setting, wireless_security, proto, protos, "proto", TRUE, FALSE);
+		ADD_STRING_LIST_VAL (setting, wireless_security, pairwise, pairwise, "pairwise", TRUE, FALSE);
+		ADD_STRING_LIST_VAL (setting, wireless_security, group, groups, "group", TRUE, FALSE);
+	}
+
+	/* WEP keys if required */
+	if (!strcmp (key_mgmt, "none")) {
+		NMWepKeyType wep_type = nm_setting_wireless_security_get_wep_key_type (setting);
+		const char *wep0 = nm_setting_wireless_security_get_wep_key (setting, 0);
+		const char *wep1 = nm_setting_wireless_security_get_wep_key (setting, 1);
+		const char *wep2 = nm_setting_wireless_security_get_wep_key (setting, 2);
+		const char *wep3 = nm_setting_wireless_security_get_wep_key (setting, 3);
+
+		if (!add_wep_key (self, wep0, "wep_key0", wep_type))
+			return FALSE;
+		if (!add_wep_key (self, wep1, "wep_key1", wep_type))
+			return FALSE;
+		if (!add_wep_key (self, wep2, "wep_key2", wep_type))
+			return FALSE;
+		if (!add_wep_key (self, wep3, "wep_key3", wep_type))
+			return FALSE;
+
+		if (wep0 || wep1 || wep2 || wep3) {
+			value = g_strdup_printf ("%d", nm_setting_wireless_security_get_wep_tx_keyidx (setting));
+			success = nm_supplicant_config_add_option (self, "wep_tx_keyidx", value, -1, FALSE);
+			g_free (value);
+			if (!success) {
+				nm_log_warn (LOGD_SUPPLICANT, "Error adding wep_tx_keyidx to supplicant config.");
+				return FALSE;
+			}
+		}
+	}
+
+	if (auth_alg && !strcmp (auth_alg, "leap")) {
+		/* LEAP */
+		if (!strcmp (key_mgmt, "ieee8021x")) {
+			const char *tmp;
+
+			tmp = nm_setting_wireless_security_get_leap_username (setting);
+			if (!add_string_val (self, tmp, "identity", FALSE, FALSE))
+				return FALSE;
+
+			tmp = nm_setting_wireless_security_get_leap_password (setting);
+			if (!add_string_val (self, tmp, "password", FALSE, TRUE))
+				return FALSE;
+
+			if (!add_string_val (self, "leap", "eap", TRUE, FALSE))
+				return FALSE;
+		} else {
+			return FALSE;
+		}
+	} else {
+		/* 802.1x for Dynamic WEP and WPA-Enterprise */
+		if (!strcmp (key_mgmt, "ieee8021x") || !strcmp (key_mgmt, "wpa-eap")) {
+		    if (!setting_8021x)
+		    	return FALSE;
+			if (!nm_supplicant_config_add_setting_8021x (self, setting_8021x, connection_uid, FALSE))
+				return FALSE;
+		}
+	}
+
+	return TRUE;
+}
+
+gboolean
+nm_supplicant_config_add_setting_8021x (NMSupplicantConfig *self,
+                                        NMSetting8021x *setting,
+                                        const char *connection_uid,
+                                        gboolean wired)
+{
+	char *tmp;
+	const char *peapver, *value, *path;
+	gboolean success, added;
+	GString *phase1, *phase2;
+	const GByteArray *array;
+
+	g_return_val_if_fail (NM_IS_SUPPLICANT_CONFIG (self), FALSE);
+	g_return_val_if_fail (setting != NULL, FALSE);
+	g_return_val_if_fail (connection_uid != NULL, FALSE);
+
+	value = nm_setting_802_1x_get_password (setting);
+	if (!add_string_val (self, value, "password", FALSE, TRUE))
+		return FALSE;
+	value = nm_setting_802_1x_get_pin (setting);
+	if (!add_string_val (self, value, "pin", FALSE, TRUE))
+		return FALSE;
+
+	if (wired) {
+		if (!add_string_val (self, "IEEE8021X", "key_mgmt", FALSE, FALSE))
+			return FALSE;
+		/* Wired 802.1x must always use eapol_flags=0 */
+		if (!add_string_val (self, "0", "eapol_flags", FALSE, FALSE))
+			return FALSE;
+	}
+
+	ADD_STRING_LIST_VAL (setting, 802_1x, eap_method, eap_methods, "eap", TRUE, FALSE);
+
+	/* Drop the fragment size a bit for better compatibility */
+	if (!nm_supplicant_config_add_option (self, "fragment_size", "1300", -1, FALSE))
+		return FALSE;
+
+	phase1 = g_string_new (NULL);
+	peapver = nm_setting_802_1x_get_phase1_peapver (setting);
+	if (peapver) {
+		if (!strcmp (peapver, "0"))
+			g_string_append (phase1, "peapver=0");
+		else if (!strcmp (peapver, "1"))
+			g_string_append (phase1, "peapver=1");
+	}
+
+	if (nm_setting_802_1x_get_phase1_peaplabel (setting)) {
+		if (phase1->len)
+			g_string_append_c (phase1, ' ');
+		g_string_append_printf (phase1, "peaplabel=%s", nm_setting_802_1x_get_phase1_peaplabel (setting));
+	}
+
+	if (phase1->len) {
+		if (!add_string_val (self, phase1->str, "phase1", FALSE, FALSE)) {
+			g_string_free (phase1, TRUE);
+			return FALSE;
+		}
+	}
+	g_string_free (phase1, TRUE);
+
+	phase2 = g_string_new (NULL);
+	if (nm_setting_802_1x_get_phase2_auth (setting)) {
+		tmp = g_ascii_strup (nm_setting_802_1x_get_phase2_auth (setting), -1);
+		g_string_append_printf (phase2, "auth=%s", tmp);
+		g_free (tmp);
+	}
+
+	if (nm_setting_802_1x_get_phase2_autheap (setting)) {
+		if (phase2->len)
+			g_string_append_c (phase2, ' ');
+		tmp = g_ascii_strup (nm_setting_802_1x_get_phase2_autheap (setting), -1);
+		g_string_append_printf (phase2, "autheap=%s", tmp);
+		g_free (tmp);
+	}
+
+	if (phase2->len) {
+		if (!add_string_val (self, phase2->str, "phase2", FALSE, FALSE)) {
+			g_string_free (phase2, TRUE);
+			return FALSE;
+		}
+	}
+	g_string_free (phase2, TRUE);
+
+	/* CA path */
+	path = nm_setting_802_1x_get_ca_path (setting);
+	if (nm_setting_802_1x_get_system_ca_certs (setting))
+		path = SYSTEM_CA_PATH;
+	if (path) {
+		if (!add_string_val (self, path, "ca_path", FALSE, FALSE))
+			return FALSE;
+	}
+
+	/* Phase2 CA path */
+	path = nm_setting_802_1x_get_phase2_ca_path (setting);
+	if (nm_setting_802_1x_get_system_ca_certs (setting))
+		path = SYSTEM_CA_PATH;
+	if (path) {
+		if (!add_string_val (self, path, "ca_path2", FALSE, FALSE))
+			return FALSE;
+	}
+
+	/* CA certificate */
+	switch (nm_setting_802_1x_get_ca_cert_scheme (setting)) {
+	case NM_SETTING_802_1X_CK_SCHEME_BLOB:
+		array = nm_setting_802_1x_get_ca_cert_blob (setting);
+		ADD_BLOB_VAL (array, "ca_cert", connection_uid);
+		break;
+	case NM_SETTING_802_1X_CK_SCHEME_PATH:
+		path = nm_setting_802_1x_get_ca_cert_path (setting);
+		if (!add_string_val (self, path, "ca_cert", FALSE, FALSE))
+			return FALSE;
+		break;
+	default:
+		break;
+	}
+
+	/* Phase 2 CA certificate */
+	switch (nm_setting_802_1x_get_phase2_ca_cert_scheme (setting)) {
+	case NM_SETTING_802_1X_CK_SCHEME_BLOB:
+		array = nm_setting_802_1x_get_phase2_ca_cert_blob (setting);
+		ADD_BLOB_VAL (array, "ca_cert2", connection_uid);
+		break;
+	case NM_SETTING_802_1X_CK_SCHEME_PATH:
+		path = nm_setting_802_1x_get_phase2_ca_cert_path (setting);
+		if (!add_string_val (self, path, "ca_cert2", FALSE, FALSE))
+			return FALSE;
+		break;
+	default:
+		break;
+	}
+
+	/* Private key */
+	added = FALSE;
+	switch (nm_setting_802_1x_get_private_key_scheme (setting)) {
+	case NM_SETTING_802_1X_CK_SCHEME_BLOB:
+		array = nm_setting_802_1x_get_private_key_blob (setting);
+		ADD_BLOB_VAL (array, "private_key", connection_uid);
+		added = TRUE;
+		break;
+	case NM_SETTING_802_1X_CK_SCHEME_PATH:
+		path = nm_setting_802_1x_get_private_key_path (setting);
+		if (!add_string_val (self, path, "private_key", FALSE, FALSE))
+			return FALSE;
+		added = TRUE;
+		break;
+	default:
+		break;
+	}
+
+	if (added) {
+		NMSetting8021xCKFormat format;
+		NMSetting8021xCKScheme scheme;
+
+		format = nm_setting_802_1x_get_private_key_format (setting);
+		scheme = nm_setting_802_1x_get_private_key_scheme (setting);
+
+		if (   scheme == NM_SETTING_802_1X_CK_SCHEME_PATH
+		    || format == NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
+			/* Only add the private key password for PKCS#12 blobs and
+			 * all path schemes, since in both of these cases the private key
+			 * isn't decrypted at all.
+			 */
+			value = nm_setting_802_1x_get_private_key_password (setting);
+			if (!add_string_val (self, value, "private_key_passwd", FALSE, TRUE))
+				return FALSE;
+		}
+
+		if (format != NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
+			/* Only add the client cert if the private key is not PKCS#12, as
+			 * wpa_supplicant configuration directs us to do.
+			 */
+			switch (nm_setting_802_1x_get_client_cert_scheme (setting)) {
+			case NM_SETTING_802_1X_CK_SCHEME_BLOB:
+				array = nm_setting_802_1x_get_client_cert_blob (setting);
+				ADD_BLOB_VAL (array, "client_cert", connection_uid);
+				break;
+			case NM_SETTING_802_1X_CK_SCHEME_PATH:
+				path = nm_setting_802_1x_get_client_cert_path (setting);
+				if (!add_string_val (self, path, "client_cert", FALSE, FALSE))
+					return FALSE;
+				break;
+			default:
+				break;
+			}
+		}
+	}
+
+	/* Phase 2 private key */
+	added = FALSE;
+	switch (nm_setting_802_1x_get_phase2_private_key_scheme (setting)) {
+	case NM_SETTING_802_1X_CK_SCHEME_BLOB:
+		array = nm_setting_802_1x_get_phase2_private_key_blob (setting);
+		ADD_BLOB_VAL (array, "private_key2", connection_uid);
+		added = TRUE;
+		break;
+	case NM_SETTING_802_1X_CK_SCHEME_PATH:
+		path = nm_setting_802_1x_get_phase2_private_key_path (setting);
+		if (!add_string_val (self, path, "private_key2", FALSE, FALSE))
+			return FALSE;
+		added = TRUE;
+		break;
+	default:
+		break;
+	}
+
+	if (added) {
+		NMSetting8021xCKFormat format;
+		NMSetting8021xCKScheme scheme;
+
+		format = nm_setting_802_1x_get_phase2_private_key_format (setting);
+		scheme = nm_setting_802_1x_get_phase2_private_key_scheme (setting);
+
+		if (   scheme == NM_SETTING_802_1X_CK_SCHEME_PATH
+		    || format == NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
+			/* Only add the private key password for PKCS#12 blobs and
+			 * all path schemes, since in both of these cases the private key
+			 * isn't decrypted at all.
+			 */
+			value = nm_setting_802_1x_get_phase2_private_key_password (setting);
+			if (!add_string_val (self, value, "private_key_passwd2", FALSE, TRUE))
+				return FALSE;
+		}
+
+		if (format != NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
+			/* Only add the client cert if the private key is not PKCS#12, as
+			 * wpa_supplicant configuration directs us to do.
+			 */
+			switch (nm_setting_802_1x_get_phase2_client_cert_scheme (setting)) {
+			case NM_SETTING_802_1X_CK_SCHEME_BLOB:
+				array = nm_setting_802_1x_get_phase2_client_cert_blob (setting);
+				ADD_BLOB_VAL (array, "client_cert2", connection_uid);
+				break;
+			case NM_SETTING_802_1X_CK_SCHEME_PATH:
+				path = nm_setting_802_1x_get_phase2_client_cert_path (setting);
+				if (!add_string_val (self, path, "client_cert2", FALSE, FALSE))
+					return FALSE;
+				break;
+			default:
+				break;
+			}
+		}
+	}
+
+	value = nm_setting_802_1x_get_identity (setting);
+	if (!add_string_val (self, value, "identity", FALSE, FALSE))
+		return FALSE;
+	value = nm_setting_802_1x_get_anonymous_identity (setting);
+	if (!add_string_val (self, value, "anonymous_identity", FALSE, FALSE))
+		return FALSE;
+
+	return TRUE;
+}
+
+gboolean
+nm_supplicant_config_add_no_security (NMSupplicantConfig *self)
+{
+	return nm_supplicant_config_add_option (self, "key_mgmt", "NONE", -1, FALSE);
+}
+
+/* From hostap, Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi> */
+
+static int hex2num (char c)
+{
+	if (c >= '0' && c <= '9')
+		return c - '0';
+	if (c >= 'a' && c <= 'f')
+		return c - 'a' + 10;
+	if (c >= 'A' && c <= 'F')
+		return c - 'A' + 10;
+	return -1;
+}
+
+static int hex2byte (const char *hex)
+{
+	int a, b;
+	a = hex2num(*hex++);
+	if (a < 0)
+		return -1;
+	b = hex2num(*hex++);
+	if (b < 0)
+		return -1;
+	return (a << 4) | b;
+}
+
+static char *
+hexstr2bin (const char *hex, size_t len)
+{
+	size_t       i;
+	int          a;
+	const char * ipos = hex;
+	char *       buf = NULL;
+	char *       opos;
+
+	/* Length must be a multiple of 2 */
+	if ((len % 2) != 0)
+		return NULL;
+
+	opos = buf = g_malloc0 ((len / 2) + 1);
+	for (i = 0; i < len; i += 2) {
+		a = hex2byte (ipos);
+		if (a < 0) {
+			g_free (buf);
+			return NULL;
+		}
+		*opos++ = a;
+		ipos += 2;
+	}
+	return buf;
+}
+
+/* End from hostap */
+
diff --git a/src/supplicant-manager/nm-supplicant-config.h b/src/supplicant-manager/nm-supplicant-config.h
new file mode 100644
index 00000000..dad23e29
--- /dev/null
+++ b/src/supplicant-manager/nm-supplicant-config.h
@@ -0,0 +1,84 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2006 - 2008 Red Hat, Inc.
+ * Copyright (C) 2007 - 2008 Novell, Inc.
+ */
+
+#ifndef NM_SUPPLICANT_CONFIG_H
+#define NM_SUPPLICANT_CONFIG_H
+
+#include <glib-object.h>
+#include <nm-setting-wireless.h>
+#include <nm-setting-wireless-security.h>
+#include <nm-setting-8021x.h>
+#include "nm-supplicant-types.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_SUPPLICANT_CONFIG            (nm_supplicant_config_get_type ())
+#define NM_SUPPLICANT_CONFIG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SUPPLICANT_CONFIG, NMSupplicantConfig))
+#define NM_SUPPLICANT_CONFIG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  NM_TYPE_SUPPLICANT_CONFIG, NMSupplicantConfigClass))
+#define NM_IS_SUPPLICANT_CONFIG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SUPPLICANT_CONFIG))
+#define NM_IS_SUPPLICANT_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  NM_TYPE_SUPPLICANT_CONFIG))
+#define NM_SUPPLICANT_CONFIG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  NM_TYPE_SUPPLICANT_CONFIG, NMSupplicantConfigClass))
+
+struct _NMSupplicantConfig
+{
+	GObject parent;
+};
+
+typedef struct
+{
+	GObjectClass parent;
+} NMSupplicantConfigClass;
+
+
+GType nm_supplicant_config_get_type (void);
+
+NMSupplicantConfig *nm_supplicant_config_new (void);
+
+guint32 nm_supplicant_config_get_ap_scan (NMSupplicantConfig *self);
+
+void nm_supplicant_config_set_ap_scan (NMSupplicantConfig *self,
+                                       guint32 ap_scan);
+
+GHashTable *nm_supplicant_config_get_hash (NMSupplicantConfig *self);
+
+GHashTable *nm_supplicant_config_get_blobs (NMSupplicantConfig *self);
+
+gboolean nm_supplicant_config_add_setting_wireless (NMSupplicantConfig *self,
+                                                    NMSettingWireless *setting,
+                                                    gboolean is_broadcast,
+                                                    guint32 adhoc_freq,
+                                                    gboolean has_scan_capa_ssid);
+
+gboolean nm_supplicant_config_add_setting_wireless_security (NMSupplicantConfig *self,
+                                                             NMSettingWirelessSecurity *setting,
+                                                             NMSetting8021x *setting_8021x,
+                                                             const char *connection_uid);
+
+gboolean nm_supplicant_config_add_no_security (NMSupplicantConfig *self);
+
+gboolean nm_supplicant_config_add_setting_8021x (NMSupplicantConfig *self,
+                                                 NMSetting8021x *setting,
+                                                 const char *connection_uid,
+                                                 gboolean wired);
+
+G_END_DECLS
+
+#endif	/* NM_SUPPLICANT_CONFIG_H */
diff --git a/src/supplicant-manager/nm-supplicant-interface.c b/src/supplicant-manager/nm-supplicant-interface.c
new file mode 100644
index 00000000..a65a458f
--- /dev/null
+++ b/src/supplicant-manager/nm-supplicant-interface.c
@@ -0,0 +1,1429 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2006 - 2008 Red Hat, Inc.
+ * Copyright (C) 2006 - 2008 Novell, Inc.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+
+#include "nm-supplicant-interface.h"
+#include "nm-supplicant-manager.h"
+#include "nm-logging.h"
+#include "nm-marshal.h"
+#include "nm-supplicant-config.h"
+#include "nm-dbus-manager.h"
+#include "nm-call-store.h"
+#include "nm-dbus-glib-types.h"
+#include "nm-glib-compat.h"
+
+#define WPAS_DBUS_IFACE_INTERFACE   WPAS_DBUS_INTERFACE ".Interface"
+#define WPAS_DBUS_IFACE_BSSID       WPAS_DBUS_INTERFACE ".BSSID"
+#define WPAS_DBUS_IFACE_NETWORK	    WPAS_DBUS_INTERFACE ".Network"
+#define WPAS_ERROR_INVALID_IFACE    WPAS_DBUS_INTERFACE ".InvalidInterface"
+#define WPAS_ERROR_EXISTS_ERROR     WPAS_DBUS_INTERFACE ".ExistsError"
+
+
+G_DEFINE_TYPE (NMSupplicantInterface, nm_supplicant_interface, G_TYPE_OBJECT)
+
+
+#define NM_SUPPLICANT_INTERFACE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
+                                                 NM_TYPE_SUPPLICANT_INTERFACE, \
+                                                 NMSupplicantInterfacePrivate))
+
+static void nm_supplicant_interface_set_property (GObject *      object,
+                                                  guint          prop_id,
+                                                  const GValue * value,
+                                                  GParamSpec *   pspec);
+
+static void nm_supplicant_interface_get_property (GObject *      object,
+                                                  guint          prop_id,
+                                                  GValue *       value,
+                                                  GParamSpec *   pspec);
+
+static void nm_supplicant_interface_start (NMSupplicantInterface *self);
+
+static void nm_supplicant_interface_add_to_supplicant (NMSupplicantInterface *self,
+                                                       gboolean get_only);
+
+static void nm_supplicant_interface_smgr_state_changed (NMSupplicantManager *smgr,
+                                                        guint32 new_state,
+                                                        guint32 old_state,
+                                                        gpointer user_data);
+
+static void nm_supplicant_interface_set_state (NMSupplicantInterface *self,
+                                               guint32 new_state);
+
+
+/* Signals */
+enum {
+	STATE,             /* change in the interface's state */
+	REMOVED,           /* interface was removed by the supplicant */
+	SCANNED_AP,        /* interface saw a new access point from a scan */
+	SCAN_REQ_RESULT,   /* result of a wireless scan request */
+	SCAN_RESULTS,      /* scan results returned from supplicant */
+	CONNECTION_STATE,  /* link state of the device's connection */
+	CONNECTION_ERROR,  /* an error occurred during a connection request */
+	LAST_SIGNAL
+};
+static guint nm_supplicant_interface_signals[LAST_SIGNAL] = { 0 };
+
+
+/* Properties */
+enum {
+	PROP_0 = 0,
+	PROP_SUPPLICANT_MANAGER,
+	PROP_DEVICE,
+	PROP_STATE,
+	PROP_CONNECTION_STATE,
+	PROP_SCANNING,
+	LAST_PROP
+};
+
+
+typedef struct
+{
+	NMSupplicantManager * smgr;
+	gulong                smgr_state_sig_handler;
+	NMDBusManager *       dbus_mgr;
+	char *                dev;
+	gboolean              is_wireless;
+
+	char *                object_path;
+	guint32               state;
+	NMCallStore *         assoc_pcalls;
+	NMCallStore *         other_pcalls;
+
+	guint32               con_state;
+	gboolean              scanning;
+
+	DBusGProxy *          iface_proxy;
+	DBusGProxy *          net_proxy;
+
+	guint                 scan_results_timeout;
+	guint32               last_scan;
+
+	NMSupplicantConfig *  cfg;
+
+	gboolean              dispose_has_run;
+} NMSupplicantInterfacePrivate;
+
+static gboolean
+cancel_all_cb (GObject *object, gpointer call_id, gpointer user_data)
+{
+	dbus_g_proxy_cancel_call (DBUS_G_PROXY (object), (DBusGProxyCall *) call_id);
+
+	return TRUE;
+}
+
+static void
+cancel_all_callbacks (NMCallStore *store)
+{
+	nm_call_store_foreach (store, NULL, cancel_all_cb, NULL);
+	nm_call_store_clear (store);
+}
+
+typedef struct {
+	NMSupplicantInterface *interface;
+	DBusGProxy *proxy;
+	NMCallStore *store;
+	DBusGProxyCall *call;
+	gboolean disposing;
+} NMSupplicantInfo;
+
+static NMSupplicantInfo *
+nm_supplicant_info_new (NMSupplicantInterface *interface,
+                        DBusGProxy *proxy,
+                        NMCallStore *store)
+{
+	NMSupplicantInfo *info;
+
+	info = g_slice_new0 (NMSupplicantInfo);
+	info->interface = g_object_ref (interface);
+	info->proxy = g_object_ref (proxy);
+	info->store = store;
+
+	return info;
+}
+
+static void
+nm_supplicant_info_set_call (NMSupplicantInfo *info, DBusGProxyCall *call)
+{
+	g_return_if_fail (info != NULL);
+	g_return_if_fail (call != NULL);
+
+	nm_call_store_add (info->store, G_OBJECT (info->proxy), (gpointer) call);
+	info->call = call;
+}
+
+static void
+nm_supplicant_info_destroy (gpointer user_data)
+{
+	NMSupplicantInfo *info = (NMSupplicantInfo *) user_data;
+
+	/* Guard against double-disposal; since DBusGProxy doesn't guard against
+	 * double-disposal, we could infinite loop here if we're in the middle of
+	 * some wpa_supplicant D-Bus calls.  When the supplicant dies we'll dispose
+	 * of the proxy, which kills all its pending calls, which brings us here.
+	 * Then when we unref the proxy here, its dispose() function will get called
+	 * again, and we get right back here until we segfault because our callstack
+	 * is too long.
+	 */
+	if (!info->disposing) {
+		info->disposing = TRUE;
+
+		if (info->call) {
+			nm_call_store_remove (info->store, G_OBJECT (info->proxy), info->call);
+			info->call = NULL;
+		}
+
+		g_object_unref (info->proxy);
+		info->proxy = NULL;
+		g_object_unref (info->interface);
+		info->interface = NULL;
+
+		memset (info, 0, sizeof (NMSupplicantInfo));
+		g_slice_free (NMSupplicantInfo, info);
+	}
+}
+
+
+NMSupplicantInterface *
+nm_supplicant_interface_new (NMSupplicantManager * smgr, const char *ifname, gboolean is_wireless)
+{
+	NMSupplicantInterface * iface;
+
+	g_return_val_if_fail (NM_IS_SUPPLICANT_MANAGER (smgr), NULL);
+	g_return_val_if_fail (ifname != NULL, NULL);
+
+	iface = g_object_new (NM_TYPE_SUPPLICANT_INTERFACE,
+	                      "supplicant-manager", smgr,
+	                      "device", ifname,
+	                      NULL);
+	if (iface) {
+		NM_SUPPLICANT_INTERFACE_GET_PRIVATE (iface)->is_wireless = is_wireless;
+		nm_supplicant_interface_start (iface);
+	}
+
+	return iface;
+}
+
+static void
+nm_supplicant_interface_init (NMSupplicantInterface * self)
+{
+	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+
+	priv->state = NM_SUPPLICANT_INTERFACE_STATE_INIT;
+	priv->con_state = NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED;
+	priv->assoc_pcalls = nm_call_store_new ();
+	priv->other_pcalls = nm_call_store_new ();
+
+	priv->dispose_has_run = FALSE;
+
+	priv->dbus_mgr = nm_dbus_manager_get ();
+}
+
+
+static void
+nm_supplicant_interface_set_property (GObject *      object,
+                                      guint          prop_id,
+                                      const GValue * value,
+                                      GParamSpec *   pspec)
+{
+	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (object);
+	gulong id;
+
+	switch (prop_id) {
+		case PROP_SUPPLICANT_MANAGER:
+			priv->smgr = NM_SUPPLICANT_MANAGER (g_value_get_object (value));
+			g_object_ref (G_OBJECT (priv->smgr));
+			
+			id = g_signal_connect (priv->smgr,
+			                       "state",
+			                       G_CALLBACK (nm_supplicant_interface_smgr_state_changed),
+			                       object);
+			priv->smgr_state_sig_handler = id;
+			break;
+		case PROP_DEVICE:
+			/* Construct-only */
+			priv->dev = g_strdup (g_value_get_string (value));
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+			break;
+	}
+}
+
+static void
+nm_supplicant_interface_get_property (GObject *     object,
+                                      guint         prop_id,
+                                      GValue *      value,
+                                      GParamSpec *  pspec)
+{
+	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (object);
+
+	switch (prop_id) {
+		case PROP_SUPPLICANT_MANAGER:
+			g_value_set_object (value, G_OBJECT (priv->smgr));
+			break;
+		case PROP_DEVICE:
+			g_value_set_string (value, priv->dev);
+			break;
+		case PROP_STATE:
+			g_value_set_uint (value, priv->state);
+			break;
+		case PROP_CONNECTION_STATE:
+			g_value_set_uint (value, priv->con_state);
+			break;
+		case PROP_SCANNING:
+			g_value_set_boolean (value, priv->scanning);
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+			break;
+	}
+}
+
+static void
+try_remove_iface (DBusGConnection *g_connection,
+                  const char *path)
+{
+	DBusGProxy *proxy;
+
+	g_return_if_fail (g_connection != NULL);
+	g_return_if_fail (path != NULL);
+
+	proxy = dbus_g_proxy_new_for_name (g_connection,
+	                                   WPAS_DBUS_SERVICE,
+	                                   WPAS_DBUS_PATH,
+	                                   WPAS_DBUS_INTERFACE);
+	if (!proxy)
+		return;
+
+	dbus_g_proxy_call_no_reply (proxy, "removeInterface", 
+	                            DBUS_TYPE_G_OBJECT_PATH, path,
+	                            G_TYPE_INVALID);
+	g_object_unref (proxy);
+}
+
+static void
+nm_supplicant_interface_dispose (GObject *object)
+{
+	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (object);
+	guint32 sm_state;
+
+	if (priv->dispose_has_run) {
+		G_OBJECT_CLASS (nm_supplicant_interface_parent_class)->dispose (object);
+		return;
+	}
+
+	priv->dispose_has_run = TRUE;
+
+	/* Ask wpa_supplicant to remove this interface */
+	sm_state = nm_supplicant_manager_get_state (priv->smgr);
+	if (sm_state == NM_SUPPLICANT_MANAGER_STATE_IDLE) {
+		if (priv->object_path) {
+			try_remove_iface (nm_dbus_manager_get_connection (priv->dbus_mgr),
+			                  priv->object_path);
+		}
+	}
+
+	if (priv->iface_proxy)
+		g_object_unref (priv->iface_proxy);
+
+	if (priv->net_proxy)
+		g_object_unref (priv->net_proxy);
+
+	if (priv->scan_results_timeout)
+		g_source_remove (priv->scan_results_timeout);
+
+	if (priv->smgr) {
+		g_signal_handler_disconnect (priv->smgr,
+		                             priv->smgr_state_sig_handler);
+		g_object_unref (priv->smgr);
+	}
+
+	g_free (priv->dev);
+
+	/* Cancel pending calls before unrefing the dbus manager */
+	cancel_all_callbacks (priv->other_pcalls);
+	nm_call_store_destroy (priv->other_pcalls);
+
+	cancel_all_callbacks (priv->assoc_pcalls);
+	nm_call_store_destroy (priv->assoc_pcalls);
+
+	if (priv->dbus_mgr)
+		g_object_unref (priv->dbus_mgr);
+
+	if (priv->cfg)
+		g_object_unref (priv->cfg);
+
+	g_free (priv->object_path);
+
+	/* Chain up to the parent class */
+	G_OBJECT_CLASS (nm_supplicant_interface_parent_class)->dispose (object);
+}
+
+static void
+nm_supplicant_interface_class_init (NMSupplicantInterfaceClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	g_type_class_add_private (object_class, sizeof (NMSupplicantInterfacePrivate));
+
+	object_class->dispose = nm_supplicant_interface_dispose;
+	object_class->set_property = nm_supplicant_interface_set_property;
+	object_class->get_property = nm_supplicant_interface_get_property;
+
+	/* Properties */
+	g_object_class_install_property (object_class,
+	                                 PROP_SUPPLICANT_MANAGER,
+	                                 g_param_spec_object ("supplicant-manager",
+	                                                      "Supplicant Manager",
+	                                                      "Supplicant manager to which this interface belongs",
+	                                                      NM_TYPE_SUPPLICANT_MANAGER,
+	                                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+  
+	g_object_class_install_property (object_class,
+	                                 PROP_DEVICE,
+	                                 g_param_spec_string ("device",
+	                                                      "Device",
+	                                                      "Device which this interface represents to the supplicant",
+	                                                      NULL,
+	                                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+	g_object_class_install_property (object_class,
+	                                 PROP_STATE,
+	                                 g_param_spec_uint ("state",
+	                                                    "State",
+	                                                    "State of the supplicant interface; INIT, READY, or DOWN",
+	                                                    NM_SUPPLICANT_INTERFACE_STATE_INIT,
+	                                                    NM_SUPPLICANT_INTERFACE_STATE_LAST - 1,
+	                                                    NM_SUPPLICANT_INTERFACE_STATE_INIT,
+	                                                    G_PARAM_READABLE));
+
+	g_object_class_install_property (object_class,
+	                                 PROP_SCANNING,
+	                                 g_param_spec_boolean ("scanning",
+	                                                    "Scanning",
+	                                                    "Scanning",
+	                                                    FALSE,
+	                                                    G_PARAM_READABLE));
+
+	/* Signals */
+	nm_supplicant_interface_signals[STATE] =
+		g_signal_new ("state",
+		              G_OBJECT_CLASS_TYPE (object_class),
+		              G_SIGNAL_RUN_LAST,
+		              G_STRUCT_OFFSET (NMSupplicantInterfaceClass, state),
+		              NULL, NULL,
+		              _nm_marshal_VOID__UINT_UINT,
+		              G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
+
+	nm_supplicant_interface_signals[REMOVED] =
+		g_signal_new ("removed",
+		              G_OBJECT_CLASS_TYPE (object_class),
+		              G_SIGNAL_RUN_LAST,
+		              G_STRUCT_OFFSET (NMSupplicantInterfaceClass, removed),
+		              NULL, NULL,
+		              g_cclosure_marshal_VOID__VOID,
+		              G_TYPE_NONE, 0);
+
+	nm_supplicant_interface_signals[SCANNED_AP] =
+		g_signal_new ("scanned-ap",
+		              G_OBJECT_CLASS_TYPE (object_class),
+		              G_SIGNAL_RUN_LAST,
+		              G_STRUCT_OFFSET (NMSupplicantInterfaceClass, scanned_ap),
+		              NULL, NULL,
+		              g_cclosure_marshal_VOID__POINTER,
+		              G_TYPE_NONE, 1, G_TYPE_POINTER);
+
+	nm_supplicant_interface_signals[SCAN_REQ_RESULT] =
+		g_signal_new ("scan-req-result",
+		              G_OBJECT_CLASS_TYPE (object_class),
+		              G_SIGNAL_RUN_LAST,
+		              G_STRUCT_OFFSET (NMSupplicantInterfaceClass, scan_req_result),
+		              NULL, NULL,
+		              g_cclosure_marshal_VOID__BOOLEAN,
+		              G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+
+	nm_supplicant_interface_signals[SCAN_RESULTS] =
+		g_signal_new ("scan-results",
+		              G_OBJECT_CLASS_TYPE (object_class),
+		              G_SIGNAL_RUN_LAST,
+		              G_STRUCT_OFFSET (NMSupplicantInterfaceClass, scan_results),
+		              NULL, NULL,
+		              g_cclosure_marshal_VOID__UINT,
+		              G_TYPE_NONE, 1, G_TYPE_UINT);
+
+	nm_supplicant_interface_signals[CONNECTION_STATE] =
+		g_signal_new ("connection-state",
+		              G_OBJECT_CLASS_TYPE (object_class),
+		              G_SIGNAL_RUN_LAST,
+		              G_STRUCT_OFFSET (NMSupplicantInterfaceClass, connection_state),
+		              NULL, NULL,
+		              _nm_marshal_VOID__UINT_UINT,
+		              G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
+
+	nm_supplicant_interface_signals[CONNECTION_ERROR] =
+		g_signal_new ("connection-error",
+		              G_OBJECT_CLASS_TYPE (object_class),
+		              G_SIGNAL_RUN_LAST,
+		              G_STRUCT_OFFSET (NMSupplicantInterfaceClass, connection_error),
+		              NULL, NULL,
+		              _nm_marshal_VOID__STRING_STRING,
+		              G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING);
+}
+
+static void
+emit_error_helper (NMSupplicantInterface *self,
+				   GError *err)
+{
+	const char *name = NULL;
+
+	if (err->domain == DBUS_GERROR && err->code == DBUS_GERROR_REMOTE_EXCEPTION)
+		name = dbus_g_error_get_name (err);
+
+	g_signal_emit (self,
+	               nm_supplicant_interface_signals[CONNECTION_ERROR],
+	               0,
+	               name,
+	               err->message);
+}
+
+static void
+bssid_properties_cb  (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
+{
+	NMSupplicantInfo *info = (NMSupplicantInfo *) user_data;
+	GError *err = NULL;
+	GHashTable *hash = NULL;
+
+	if (!dbus_g_proxy_end_call (proxy, call_id, &err,
+	                            DBUS_TYPE_G_MAP_OF_VARIANT, &hash,
+	                            G_TYPE_INVALID)) {
+		if (!strstr (err->message, "The BSSID requested was invalid")) {
+			nm_log_warn (LOGD_SUPPLICANT, "Couldn't retrieve BSSID properties: %s.",
+			             err->message);
+		}
+		g_error_free (err);
+	} else {
+		g_signal_emit (info->interface,
+		               nm_supplicant_interface_signals[SCANNED_AP],
+		               0,
+		               hash);
+
+		g_hash_table_destroy (hash);
+	}
+}
+
+static void
+request_bssid_properties (NMSupplicantInterface * self,
+                          const char * op)
+{
+	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+	NMSupplicantInfo *info;
+	DBusGProxy *proxy;
+	DBusGProxyCall *call;
+
+	proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr),
+	                                   WPAS_DBUS_SERVICE,
+	                                   op,
+	                                   WPAS_DBUS_IFACE_BSSID);
+	info = nm_supplicant_info_new (self, proxy, priv->other_pcalls);
+	call = dbus_g_proxy_begin_call (proxy, "properties",
+	                                bssid_properties_cb,
+	                                info,
+	                                nm_supplicant_info_destroy,
+	                                G_TYPE_INVALID);
+	nm_supplicant_info_set_call (info, call);
+	g_object_unref (proxy);
+}
+
+static void
+scan_results_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
+{
+	GError *err = NULL;
+	GPtrArray *array = NULL;
+
+	if (!dbus_g_proxy_end_call (proxy, call_id, &err,
+	                            DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, &array,
+	                            G_TYPE_INVALID)) {
+		nm_log_warn (LOGD_SUPPLICANT, "could not get scan results: %s.", err->message);
+		g_error_free (err);
+	} else {
+		int i;
+		NMSupplicantInfo *info = (NMSupplicantInfo *) user_data;
+
+		/* Notify listeners of the result of the scan */
+		g_signal_emit (info->interface,
+		               nm_supplicant_interface_signals[SCAN_RESULTS],
+		               0,
+		               array->len);
+
+		/* Fire off a "properties" call for each returned BSSID */
+		for (i = 0; i < array->len; i++) {
+			char *op = g_ptr_array_index (array, i);
+
+			request_bssid_properties (info->interface, op);
+			g_free (op);
+		}
+
+		g_ptr_array_free (array, TRUE);
+	}
+}
+
+static gboolean
+request_scan_results (gpointer user_data)
+{
+	NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
+	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+	NMSupplicantInfo *info;
+	DBusGProxyCall *call;
+	GTimeVal cur_time;
+
+	priv->scan_results_timeout = 0;
+
+	g_return_val_if_fail (priv->iface_proxy != NULL, FALSE);
+
+	info = nm_supplicant_info_new (self, priv->iface_proxy, priv->other_pcalls);
+	call = dbus_g_proxy_begin_call (priv->iface_proxy, "scanResults",
+	                                scan_results_cb, 
+	                                info,
+	                                nm_supplicant_info_destroy,
+	                                G_TYPE_INVALID);
+	nm_supplicant_info_set_call (info, call);
+
+	g_get_current_time (&cur_time);
+	priv->last_scan = cur_time.tv_sec;
+	return FALSE;
+}
+
+static void
+wpas_iface_query_scan_results (DBusGProxy *proxy, gpointer user_data)
+{
+	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (user_data);
+	GTimeVal cur_time;
+
+	/* Only query scan results if a query is not queued */
+	if (priv->scan_results_timeout)
+		return;
+
+	g_get_current_time (&cur_time);
+
+	/* Only fetch scan results every 4s max, but initially do it right away */
+	if (priv->last_scan + 4 < cur_time.tv_sec) {
+		priv->scan_results_timeout = g_idle_add (request_scan_results,
+		                                         user_data);
+	} else {
+		priv->scan_results_timeout =
+			g_timeout_add_seconds ((4 - (cur_time.tv_sec - priv->last_scan)),
+			               request_scan_results, user_data);
+	}
+}
+
+static guint32
+wpas_state_string_to_enum (const char * str_state)
+{
+	guint32 enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED;
+
+	if (!strcmp (str_state, "DISCONNECTED"))
+		enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED;
+	else if (!strcmp (str_state, "INACTIVE"))
+		enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_INACTIVE;
+	else if (!strcmp (str_state, "SCANNING"))
+		enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_SCANNING;
+	else if (!strcmp (str_state, "ASSOCIATING"))
+		enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_ASSOCIATING;
+	else if (!strcmp (str_state, "ASSOCIATED"))
+		enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_ASSOCIATED;
+	else if (!strcmp (str_state, "4WAY_HANDSHAKE"))
+		enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_4WAY_HANDSHAKE;
+	else if (!strcmp (str_state, "GROUP_HANDSHAKE"))
+		enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_GROUP_HANDSHAKE;
+	else if (!strcmp (str_state, "COMPLETED"))
+		enum_state = NM_SUPPLICANT_INTERFACE_CON_STATE_COMPLETED;
+
+	return enum_state;
+}
+
+static void
+wpas_iface_handle_state_change (DBusGProxy *proxy,
+                                const char *str_new_state,
+                                const char *str_old_state,
+                                gpointer user_data)
+{
+	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (user_data);
+	guint32 old_state, enum_new_state;
+
+	enum_new_state = wpas_state_string_to_enum (str_new_state);
+	old_state = priv->con_state;
+	priv->con_state = enum_new_state;
+	if (priv->con_state != old_state) {
+		g_signal_emit (user_data,
+		               nm_supplicant_interface_signals[CONNECTION_STATE],
+		               0,
+		               priv->con_state,
+		               old_state);
+	}
+}
+
+
+static void
+iface_state_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
+{
+	GError *err = NULL;
+	char *state_str = NULL;
+
+	if (!dbus_g_proxy_end_call (proxy, call_id, &err,
+	                            G_TYPE_STRING, &state_str,
+	                            G_TYPE_INVALID)) {
+		nm_log_warn (LOGD_SUPPLICANT, "could not get interface state: %s.", err->message);
+		g_error_free (err);
+	} else {
+		NMSupplicantInfo *info = (NMSupplicantInfo *) user_data;
+		NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface);
+
+		priv->con_state = wpas_state_string_to_enum (state_str);
+		g_free (state_str);
+		nm_supplicant_interface_set_state (info->interface, NM_SUPPLICANT_INTERFACE_STATE_READY);
+	}
+}
+
+static void
+wpas_iface_get_state (NMSupplicantInterface *self)
+{
+	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+	NMSupplicantInfo *info;
+	DBusGProxyCall *call;
+
+	info = nm_supplicant_info_new (self, priv->iface_proxy, priv->other_pcalls);
+	call = dbus_g_proxy_begin_call (priv->iface_proxy, "state",
+	                                iface_state_cb,
+	                                info,
+	                                nm_supplicant_info_destroy,
+	                                G_TYPE_INVALID);
+	nm_supplicant_info_set_call (info, call);
+}
+
+static void
+iface_scanning_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
+{
+	NMSupplicantInfo *info = (NMSupplicantInfo *) user_data;
+	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface);
+	gboolean scanning = FALSE;
+
+	if (dbus_g_proxy_end_call (proxy, call_id, NULL,
+	                            G_TYPE_BOOLEAN, &scanning,
+	                            G_TYPE_INVALID)) {
+		if (scanning != priv->scanning) {
+			priv->scanning = scanning;
+			g_object_notify (G_OBJECT (info->interface), "scanning");
+		}
+	}
+}
+
+static void
+wpas_iface_get_scanning (NMSupplicantInterface *self)
+{
+	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+	NMSupplicantInfo *info;
+	DBusGProxyCall *call;
+
+	info = nm_supplicant_info_new (self, priv->iface_proxy, priv->other_pcalls);
+	call = dbus_g_proxy_begin_call (priv->iface_proxy, "scanning",
+	                                iface_scanning_cb,
+	                                info,
+	                                nm_supplicant_info_destroy,
+	                                G_TYPE_INVALID);
+	nm_supplicant_info_set_call (info, call);
+}
+
+static void
+wpas_iface_handle_scanning (DBusGProxy *proxy,
+                            gboolean scanning,
+                            gpointer user_data)
+{
+	NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
+	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+
+	if (scanning != priv->scanning) {
+		priv->scanning = scanning;
+		g_object_notify (G_OBJECT (self), "scanning");
+	}
+}
+
+gboolean
+nm_supplicant_interface_get_scanning (NMSupplicantInterface *self)
+{
+	NMSupplicantInterfacePrivate *priv;
+
+	g_return_val_if_fail (self != NULL, FALSE);
+
+	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+	if (priv->scanning)
+		return TRUE;
+	if (priv->con_state == NM_SUPPLICANT_INTERFACE_CON_STATE_SCANNING)
+		return TRUE;
+	return FALSE;
+}
+
+static void
+nm_supplicant_interface_add_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
+{
+	NMSupplicantInfo *info = (NMSupplicantInfo *) user_data;
+	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface);
+	GError *err = NULL;
+	char *path = NULL;
+
+	if (!dbus_g_proxy_end_call (proxy, call_id, &err,
+	                            DBUS_TYPE_G_OBJECT_PATH, &path,
+	                            G_TYPE_INVALID)) {
+
+		if (dbus_g_error_has_name (err, WPAS_ERROR_INVALID_IFACE)) {
+			/* Interface not added, try to add it */
+			nm_supplicant_interface_add_to_supplicant (info->interface, FALSE);
+		} else if (dbus_g_error_has_name (err, WPAS_ERROR_EXISTS_ERROR)) {
+			/* Interface already added, just try to get the interface */
+			nm_supplicant_interface_add_to_supplicant (info->interface, TRUE);
+		} else {
+			nm_log_err (LOGD_SUPPLICANT, "(%s): error getting interface: %s",
+			            priv->dev, err->message);
+		}
+
+		g_error_free (err);
+	} else {
+		nm_log_dbg (LOGD_SUPPLICANT, "(%s): interface added to supplicant", priv->dev);
+
+		priv->object_path = path;
+
+		priv->iface_proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr),
+		                                               WPAS_DBUS_SERVICE,
+		                                               path,
+		                                               WPAS_DBUS_IFACE_INTERFACE);
+
+		dbus_g_proxy_add_signal (priv->iface_proxy, "ScanResultsAvailable", G_TYPE_INVALID);
+
+		dbus_g_object_register_marshaller (_nm_marshal_VOID__STRING_STRING,
+		                                   G_TYPE_NONE,
+		                                   G_TYPE_STRING, G_TYPE_STRING,
+		                                   G_TYPE_INVALID);
+
+		dbus_g_proxy_add_signal (priv->iface_proxy, "StateChange", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
+
+		dbus_g_proxy_connect_signal (priv->iface_proxy, "ScanResultsAvailable",
+		                             G_CALLBACK (wpas_iface_query_scan_results),
+		                             info->interface,
+		                             NULL);
+
+		dbus_g_proxy_connect_signal (priv->iface_proxy, "StateChange",
+		                             G_CALLBACK (wpas_iface_handle_state_change),
+		                             info->interface,
+		                             NULL);
+
+		dbus_g_proxy_add_signal (priv->iface_proxy, "Scanning", G_TYPE_BOOLEAN, G_TYPE_INVALID);
+
+		dbus_g_proxy_connect_signal (priv->iface_proxy, "Scanning",
+		                             G_CALLBACK (wpas_iface_handle_scanning),
+		                             info->interface,
+		                             NULL);
+
+		/* Interface added to the supplicant; get its initial state. */
+		wpas_iface_get_state (info->interface);
+		wpas_iface_get_scanning (info->interface);
+	}
+}
+
+static void
+nm_supplicant_interface_add_to_supplicant (NMSupplicantInterface * self,
+                                           gboolean get_only)
+{
+	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+	NMSupplicantInfo *info;
+	DBusGProxy *proxy;
+	DBusGProxyCall *call;
+
+	proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr),
+	                                   WPAS_DBUS_SERVICE,
+	                                   WPAS_DBUS_PATH,
+	                                   WPAS_DBUS_INTERFACE);
+	info = nm_supplicant_info_new (self, proxy, priv->other_pcalls);
+
+	if (get_only) {
+		call = dbus_g_proxy_begin_call (proxy, "getInterface",
+		                                nm_supplicant_interface_add_cb,
+		                                info,
+		                                nm_supplicant_info_destroy,
+		                                G_TYPE_STRING, priv->dev,
+		                                G_TYPE_INVALID);
+	} else {
+		GHashTable *hash = g_hash_table_new (g_str_hash, g_str_equal);
+		GValue *driver;
+
+		driver = g_new0 (GValue, 1);
+		g_value_init (driver, G_TYPE_STRING);
+		g_value_set_string (driver, priv->is_wireless ? "wext" : "wired");
+		g_hash_table_insert (hash, "driver", driver);
+
+		call = dbus_g_proxy_begin_call (proxy, "addInterface",
+		                                nm_supplicant_interface_add_cb,
+		                                info,
+		                                nm_supplicant_info_destroy,
+		                                G_TYPE_STRING, priv->dev,
+		                                DBUS_TYPE_G_MAP_OF_VARIANT, hash,
+		                                G_TYPE_INVALID);
+
+		g_value_unset (driver);
+		g_free (driver);
+		g_hash_table_destroy (hash);
+	}
+
+	g_object_unref (proxy);
+
+	nm_supplicant_info_set_call (info, call);
+}
+
+static void
+nm_supplicant_interface_start (NMSupplicantInterface * self)
+{
+	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+	guint32          state;
+
+	/* Can only start the interface from INIT state */
+	g_return_if_fail (priv->state == NM_SUPPLICANT_INTERFACE_STATE_INIT);
+
+	nm_log_dbg (LOGD_SUPPLICANT, "(%s): adding interface to supplicant", priv->dev);
+
+	state = nm_supplicant_manager_get_state (priv->smgr);
+	if (state == NM_SUPPLICANT_MANAGER_STATE_IDLE) {
+		nm_supplicant_interface_set_state (self, NM_SUPPLICANT_INTERFACE_STATE_STARTING);
+		nm_supplicant_interface_add_to_supplicant (self, FALSE);
+	} else if (state == NM_SUPPLICANT_MANAGER_STATE_DOWN) {
+		/* Don't do anything; wait for signal from supplicant manager
+		 * that its state has changed.
+		 */
+	} else
+		nm_log_warn (LOGD_SUPPLICANT, "Unknown supplicant manager state!");
+}
+
+static void
+nm_supplicant_interface_handle_supplicant_manager_idle_state (NMSupplicantInterface * self)
+{
+	switch (NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->state) {
+		case NM_SUPPLICANT_INTERFACE_STATE_INIT:
+			/* Move to STARTING state when supplicant is ready */
+			nm_supplicant_interface_start (self);
+			break;
+		case NM_SUPPLICANT_INTERFACE_STATE_STARTING:
+			/* Don't do anything here, though we should never hit this */
+			break;
+		case NM_SUPPLICANT_INTERFACE_STATE_READY:
+			/* Don't do anything here, though we should never hit this */
+			break;
+		case NM_SUPPLICANT_INTERFACE_STATE_DOWN:
+			/* Don't do anything here; interface can't get out of DOWN state */
+			break;
+		default:
+			nm_log_warn (LOGD_SUPPLICANT, "Unknown supplicant interface state!");
+			break;
+	}
+}
+
+
+static void
+nm_supplicant_interface_set_state (NMSupplicantInterface * self,
+                                   guint32 new_state)
+{
+	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+	guint32 old_state;
+
+	g_return_if_fail (new_state < NM_SUPPLICANT_INTERFACE_STATE_LAST);
+
+	if (new_state == priv->state)
+		return;
+
+	old_state = priv->state;
+	if (new_state == NM_SUPPLICANT_INTERFACE_STATE_DOWN) {
+		/* If the interface is transitioning to DOWN and there's are
+		 * in-progress pending calls, cancel them.
+		 */
+		cancel_all_callbacks (priv->other_pcalls);
+		cancel_all_callbacks (priv->assoc_pcalls);
+	}
+
+	priv->state = new_state;
+	g_signal_emit (self,
+	               nm_supplicant_interface_signals[STATE],
+	               0,
+	               priv->state,
+	               old_state);
+}
+
+static void
+nm_supplicant_interface_smgr_state_changed (NMSupplicantManager * smgr,
+                                            guint32 new_state,
+                                            guint32 old_state,
+                                            gpointer user_data)
+{
+	NMSupplicantInterface * self = NM_SUPPLICANT_INTERFACE (user_data);
+
+	switch (new_state) {
+		case NM_SUPPLICANT_MANAGER_STATE_DOWN:
+			/* The supplicant went away, likely the connection to it is also
+			 * gone.  Therefore, this interface must move to the DOWN state
+			 * and be disposed of.
+			 */
+			nm_supplicant_interface_set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN);
+			break;
+		case NM_SUPPLICANT_MANAGER_STATE_IDLE:
+			/* Handle the supplicant now being available. */
+			nm_supplicant_interface_handle_supplicant_manager_idle_state (self);
+			break;
+		default:
+			nm_log_warn (LOGD_SUPPLICANT, "Unknown supplicant manager state!");
+			break;
+	}
+}
+
+
+static void
+remove_network_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
+{
+	GError *err = NULL;
+	guint tmp;
+
+	if (!dbus_g_proxy_end_call (proxy, call_id, &err, G_TYPE_UINT, &tmp, G_TYPE_INVALID)) {
+		nm_log_dbg (LOGD_SUPPLICANT, "Couldn't remove network from supplicant interface: %s.",
+		            err->message);
+		g_error_free (err);
+	}
+}
+
+static void
+disconnect_cb  (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
+{
+	GError *err = NULL;
+	guint tmp;
+
+	if (!dbus_g_proxy_end_call (proxy, call_id, &err, G_TYPE_UINT, &tmp, G_TYPE_INVALID)) {
+		nm_log_warn (LOGD_SUPPLICANT, "Couldn't disconnect supplicant interface: %s.",
+		             err->message);
+		g_error_free (err);
+	}
+}
+
+void
+nm_supplicant_interface_disconnect (NMSupplicantInterface * self)
+{
+	NMSupplicantInterfacePrivate *priv;
+
+	g_return_if_fail (NM_IS_SUPPLICANT_INTERFACE (self));
+
+	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+
+	/* Clear and cancel all pending calls related to a prior
+	 * connection attempt.
+	 */
+	cancel_all_callbacks (priv->assoc_pcalls);
+
+	/* Don't do anything if there is no connection to the supplicant yet. */
+	if (!priv->iface_proxy)
+		return;
+
+	/* Don't try to disconnect if the supplicant interface is already
+	 * disconnected.
+	 */
+	if (priv->con_state == NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED
+	    || priv->con_state == NM_SUPPLICANT_INTERFACE_CON_STATE_INACTIVE) {
+		if (priv->net_proxy) {
+			g_object_unref (priv->net_proxy);
+			priv->net_proxy = NULL;
+		}
+
+		return;
+	}
+
+	/* Remove any network that was added by NetworkManager */
+	if (priv->net_proxy) {
+		dbus_g_proxy_begin_call (priv->iface_proxy, "removeNetwork",
+		                         remove_network_cb,
+		                         NULL, NULL,
+		                         DBUS_TYPE_G_OBJECT_PATH, dbus_g_proxy_get_path (priv->net_proxy),
+		                         G_TYPE_INVALID);
+
+		g_object_unref (priv->net_proxy);
+		priv->net_proxy = NULL;
+	}
+
+	dbus_g_proxy_begin_call (priv->iface_proxy, "disconnect",
+	                         disconnect_cb,
+	                         NULL, NULL,
+	                         G_TYPE_INVALID);
+}
+
+static void
+select_network_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
+{
+	NMSupplicantInfo *info = (NMSupplicantInfo *) user_data;
+	GError *err = NULL;
+	guint tmp;
+
+	if (!dbus_g_proxy_end_call (proxy, call_id, &err, G_TYPE_UINT, &tmp, G_TYPE_INVALID)) {
+		nm_log_warn (LOGD_SUPPLICANT, "Couldn't select network config: %s.", err->message);
+		emit_error_helper (info->interface, err);
+		g_error_free (err);
+	}
+}
+
+static void
+set_network_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
+{
+	NMSupplicantInfo *info = (NMSupplicantInfo *) user_data;
+	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface);
+	GError *err = NULL;
+	guint tmp;
+
+	if (!dbus_g_proxy_end_call (proxy, call_id, &err, G_TYPE_UINT, &tmp, G_TYPE_INVALID)) {
+		nm_log_warn (LOGD_SUPPLICANT, "Couldn't set network config: %s.", err->message);
+		emit_error_helper (info->interface, err);
+		g_error_free (err);
+	} else {
+		DBusGProxyCall *call;
+
+		info = nm_supplicant_info_new (info->interface, priv->iface_proxy, priv->assoc_pcalls);
+		call = dbus_g_proxy_begin_call (priv->iface_proxy, "selectNetwork",
+		                                select_network_cb,
+		                                info,
+		                                nm_supplicant_info_destroy,
+		                                DBUS_TYPE_G_OBJECT_PATH, dbus_g_proxy_get_path (proxy),
+		                                G_TYPE_INVALID);
+		nm_supplicant_info_set_call (info, call);
+	}
+}
+
+static void
+call_set_network (NMSupplicantInfo *info)
+{
+	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface);
+	GHashTable *config_hash;
+	DBusGProxyCall *call;
+
+	config_hash = nm_supplicant_config_get_hash (priv->cfg);
+	call = dbus_g_proxy_begin_call (priv->net_proxy, "set",
+	                                set_network_cb,
+	                                info,
+	                                nm_supplicant_info_destroy,
+	                                DBUS_TYPE_G_MAP_OF_VARIANT, config_hash,
+	                                G_TYPE_INVALID);
+	nm_supplicant_info_set_call (info, call);
+	g_hash_table_destroy (config_hash);
+}
+
+static void
+set_blobs_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
+{
+	NMSupplicantInfo *info = (NMSupplicantInfo *) user_data;
+	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface);
+	GError *err = NULL;
+	guint tmp;
+
+	if (!dbus_g_proxy_end_call (proxy, call_id, &err, G_TYPE_UINT, &tmp, G_TYPE_INVALID)) {
+		nm_log_warn (LOGD_SUPPLICANT, "Couldn't set network certificates: %s.", err->message);
+		emit_error_helper (info->interface, err);
+		g_error_free (err);
+	} else {
+		info = nm_supplicant_info_new (info->interface, priv->iface_proxy, priv->assoc_pcalls);
+		call_set_network (info);
+	}
+}
+
+static GValue *
+byte_array_to_gvalue (const GByteArray *array)
+{
+	GValue *val;
+
+	val = g_slice_new0 (GValue);
+	g_value_init (val, DBUS_TYPE_G_UCHAR_ARRAY);
+	g_value_set_boxed (val, array);
+
+	return val;
+}
+
+static void
+blob_free (GValue *val)
+{
+	g_value_unset (val);
+	g_slice_free (GValue, val);
+}
+
+static void
+convert_blob (const char *key, const GByteArray *value, GHashTable *hash)
+{
+	GValue *val;
+
+	val = byte_array_to_gvalue (value);
+	g_hash_table_insert (hash, g_strdup (key), val);
+}
+
+static void
+call_set_blobs (NMSupplicantInfo *info, GHashTable *orig_blobs)
+{
+	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface);
+	DBusGProxyCall *call;
+	GHashTable *blobs;
+
+	blobs = g_hash_table_new_full (g_str_hash, g_str_equal,
+	                               (GDestroyNotify) g_free,
+	                               (GDestroyNotify) blob_free);
+	if (!blobs) {
+		const char *msg = "Not enough memory to create blob table.";
+
+		nm_log_warn (LOGD_SUPPLICANT, "%s", msg);
+		g_signal_emit (info->interface,
+		               nm_supplicant_interface_signals[CONNECTION_ERROR],
+		               0, "SendBlobError", msg);
+		return;
+	}
+
+	g_hash_table_foreach (orig_blobs, (GHFunc) convert_blob, blobs);
+
+	call = dbus_g_proxy_begin_call (priv->iface_proxy, "setBlobs",
+	                                set_blobs_cb,
+	                                info,
+	                                nm_supplicant_info_destroy,
+	                                DBUS_TYPE_G_MAP_OF_VARIANT, blobs,
+	                                G_TYPE_INVALID);
+	nm_supplicant_info_set_call (info, call);
+	g_hash_table_destroy (blobs);
+}
+
+static void
+add_network_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
+{
+	NMSupplicantInfo *info = (NMSupplicantInfo *) user_data;
+	GError *err = NULL;
+	char *path = NULL;
+
+	if (!dbus_g_proxy_end_call (proxy, call_id, &err,
+	                            DBUS_TYPE_G_OBJECT_PATH, &path,
+	                            G_TYPE_INVALID)) {
+		nm_log_warn (LOGD_SUPPLICANT, "Couldn't add a network to the supplicant interface: %s.",
+		             err->message);
+		emit_error_helper (info->interface, err);
+		g_error_free (err);
+	} else {
+		NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface);
+		GHashTable *blobs;
+
+		priv->net_proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr),
+		                                             WPAS_DBUS_SERVICE,
+		                                             path,
+		                                             WPAS_DBUS_IFACE_NETWORK);
+		g_free (path);
+
+		info = nm_supplicant_info_new (info->interface,
+		                               priv->net_proxy,
+		                               priv->assoc_pcalls);
+		/* Send any blobs first; if there aren't any jump to sending the
+		 * config settings.
+		 */
+		blobs = nm_supplicant_config_get_blobs (priv->cfg);
+		if (g_hash_table_size (blobs) > 0)
+			call_set_blobs (info, blobs);
+		else
+			call_set_network (info);
+	}
+}
+
+static void
+set_ap_scan_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
+{
+	NMSupplicantInfo *info = (NMSupplicantInfo *) user_data;
+	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (info->interface);
+	GError *err = NULL;
+	guint32 tmp;
+	DBusGProxyCall *call;
+
+	if (!dbus_g_proxy_end_call (proxy, call_id, &err, G_TYPE_UINT, &tmp, G_TYPE_INVALID)) {
+		nm_log_warn (LOGD_SUPPLICANT, "Couldn't send AP scan mode to the supplicant interface: %s.",
+		             err->message);
+		emit_error_helper (info->interface, err);
+		g_error_free (err);
+		return;
+	}
+
+	nm_log_info (LOGD_SUPPLICANT, "Config: set interface ap_scan to %d",
+	             nm_supplicant_config_get_ap_scan (priv->cfg));
+
+	info = nm_supplicant_info_new (info->interface, proxy, info->store);
+	call = dbus_g_proxy_begin_call (proxy, "addNetwork",
+	                                add_network_cb,
+	                                info,
+	                                nm_supplicant_info_destroy,
+	                                G_TYPE_INVALID);
+	nm_supplicant_info_set_call (info, call);
+}
+
+gboolean
+nm_supplicant_interface_set_config (NMSupplicantInterface * self,
+                                    NMSupplicantConfig * cfg)
+{
+	NMSupplicantInterfacePrivate *priv;
+	NMSupplicantInfo *info;
+	DBusGProxyCall *call;
+	guint32 ap_scan;
+
+	g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), FALSE);
+
+	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+
+	nm_supplicant_interface_disconnect (self);
+	
+	if (priv->cfg)
+		g_object_unref (priv->cfg);
+	priv->cfg = cfg;
+
+	if (cfg == NULL)
+		return TRUE;
+
+	g_object_ref (priv->cfg);
+
+	info = nm_supplicant_info_new (self, priv->iface_proxy, priv->other_pcalls);
+	ap_scan = nm_supplicant_config_get_ap_scan (priv->cfg);
+	call = dbus_g_proxy_begin_call (priv->iface_proxy, "setAPScan",
+	                                set_ap_scan_cb,
+	                                info,
+	                                nm_supplicant_info_destroy,
+	                                G_TYPE_UINT, ap_scan,
+	                                G_TYPE_INVALID);
+	nm_supplicant_info_set_call (info, call);
+
+	return call != NULL;
+}
+
+const char *
+nm_supplicant_interface_get_device (NMSupplicantInterface * self)
+{
+	g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), NULL);
+
+	return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->dev;
+}
+
+static void
+scan_request_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data)
+{
+	NMSupplicantInfo *info = (NMSupplicantInfo *) user_data;
+	GError *err = NULL;
+	guint32 success = 0;
+
+	if (!dbus_g_proxy_end_call (proxy, call_id, &err,
+	                            G_TYPE_UINT, &success,
+	                            G_TYPE_INVALID)) {
+		nm_log_warn (LOGD_SUPPLICANT, "Could not get scan request result: %s", err->message);
+		g_error_free (err);
+	} 
+
+	/* Notify listeners of the result of the scan */
+	g_signal_emit (info->interface,
+	               nm_supplicant_interface_signals[SCAN_REQ_RESULT],
+	               0,
+	               success ? TRUE : FALSE);
+}
+
+gboolean
+nm_supplicant_interface_request_scan (NMSupplicantInterface * self)
+{
+	NMSupplicantInterfacePrivate *priv;
+	NMSupplicantInfo *info;
+	DBusGProxyCall *call;
+
+	g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), FALSE);
+
+	priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+
+	info = nm_supplicant_info_new (self, priv->iface_proxy, priv->other_pcalls);
+	call = dbus_g_proxy_begin_call (priv->iface_proxy, "scan",
+	                                scan_request_cb,
+	                                info,
+	                                nm_supplicant_info_destroy,
+	                                G_TYPE_INVALID);
+	nm_supplicant_info_set_call (info, call);
+
+	return call != NULL;
+}
+
+guint32
+nm_supplicant_interface_get_state (NMSupplicantInterface * self)
+{
+	g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), NM_SUPPLICANT_INTERFACE_STATE_DOWN);
+
+	return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->state;
+}
+
+guint32
+nm_supplicant_interface_get_connection_state (NMSupplicantInterface * self)
+{
+	g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED);
+
+	return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->con_state;
+}
+
+const char *
+nm_supplicant_interface_state_to_string (guint32 state)
+{
+	switch (state) {
+	case NM_SUPPLICANT_INTERFACE_STATE_INIT:
+		return "init";
+	case NM_SUPPLICANT_INTERFACE_STATE_STARTING:
+		return "starting";
+	case NM_SUPPLICANT_INTERFACE_STATE_READY:
+		return "ready";
+	case NM_SUPPLICANT_INTERFACE_STATE_DOWN:
+		return "down";
+	default:
+		break;
+	}
+	return "unknown";
+}
+
+const char *
+nm_supplicant_interface_connection_state_to_string (guint32 state)
+{
+	switch (state) {
+	case NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED:
+		return "disconnected";
+	case NM_SUPPLICANT_INTERFACE_CON_STATE_INACTIVE:
+		return "inactive";
+	case NM_SUPPLICANT_INTERFACE_CON_STATE_SCANNING:
+		return "scanning";
+	case NM_SUPPLICANT_INTERFACE_CON_STATE_ASSOCIATING:
+		return "associating";
+	case NM_SUPPLICANT_INTERFACE_CON_STATE_ASSOCIATED:
+		return "associated";
+	case NM_SUPPLICANT_INTERFACE_CON_STATE_4WAY_HANDSHAKE:
+		return "4-way handshake";
+	case NM_SUPPLICANT_INTERFACE_CON_STATE_GROUP_HANDSHAKE:
+		return "group handshake";
+	case NM_SUPPLICANT_INTERFACE_CON_STATE_COMPLETED:
+		return "completed";
+	default:
+		break;
+	}
+	return "unknown";
+}
+
diff --git a/src/supplicant-manager/nm-supplicant-interface.h b/src/supplicant-manager/nm-supplicant-interface.h
new file mode 100644
index 00000000..bee5436f
--- /dev/null
+++ b/src/supplicant-manager/nm-supplicant-interface.h
@@ -0,0 +1,145 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2006 - 2008 Red Hat, Inc.
+ * Copyright (C) 2007 - 2008 Novell, Inc.
+ */
+
+#ifndef NM_SUPPLICANT_INTERFACE_H
+#define NM_SUPPLICANT_INTERFACE_H
+
+#include <glib-object.h>
+#include <dbus/dbus.h>
+#include "nm-supplicant-types.h"
+
+G_BEGIN_DECLS
+
+/*
+ * Supplicant interface states
+ *   The states are linear, ie INIT -> READY -> DOWN and state may only be
+ *   changed in one direction.  If an interface reaches the DOWN state, it
+ *   cannot be re-initialized; it must be torn down and a new one created.
+ *
+ * INIT:  interface has been created, but cannot be used yet; it is waiting
+ *             for pending requests of the supplicant to complete.
+ * READY: interface is ready for use
+ * DOWN:  interface has been removed or has otherwise been made invalid; it
+ *             must be torn down.
+ *
+ * Note: LAST is an invalid state and only used for boundary checking.
+ */
+enum {
+	NM_SUPPLICANT_INTERFACE_STATE_INIT = 0,
+	NM_SUPPLICANT_INTERFACE_STATE_STARTING,
+	NM_SUPPLICANT_INTERFACE_STATE_READY,
+	NM_SUPPLICANT_INTERFACE_STATE_DOWN,
+	NM_SUPPLICANT_INTERFACE_STATE_LAST
+};
+
+
+/*
+ * Supplicant interface connection states
+ *   The wpa_supplicant state for the connection.
+ */
+enum {
+	NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED = 0,
+	NM_SUPPLICANT_INTERFACE_CON_STATE_INACTIVE,
+	NM_SUPPLICANT_INTERFACE_CON_STATE_SCANNING,
+	NM_SUPPLICANT_INTERFACE_CON_STATE_ASSOCIATING,
+	NM_SUPPLICANT_INTERFACE_CON_STATE_ASSOCIATED,
+	NM_SUPPLICANT_INTERFACE_CON_STATE_4WAY_HANDSHAKE,
+	NM_SUPPLICANT_INTERFACE_CON_STATE_GROUP_HANDSHAKE,
+	NM_SUPPLICANT_INTERFACE_CON_STATE_COMPLETED,
+	NM_SUPPLICANT_INTERFACE_CON_STATE_LAST
+};
+
+#define NM_TYPE_SUPPLICANT_INTERFACE            (nm_supplicant_interface_get_type ())
+#define NM_SUPPLICANT_INTERFACE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SUPPLICANT_INTERFACE, NMSupplicantInterface))
+#define NM_SUPPLICANT_INTERFACE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  NM_TYPE_SUPPLICANT_INTERFACE, NMSupplicantInterfaceClass))
+#define NM_IS_SUPPLICANT_INTERFACE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SUPPLICANT_INTERFACE))
+#define NM_IS_SUPPLICANT_INTERFACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  NM_TYPE_SUPPLICANT_INTERFACE))
+#define NM_SUPPLICANT_INTERFACE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  NM_TYPE_SUPPLICANT_INTERFACE, NMSupplicantInterfaceClass))
+
+struct _NMSupplicantInterface {
+	GObject parent;
+};
+
+typedef struct {
+	GObjectClass parent;
+
+	/* Signals */
+
+	/* change in the interface's state */
+	void (*state)            (NMSupplicantInterface * iface,
+	                          guint32 new_state,
+	                          guint32 old_state);
+
+	/* interface was removed by the supplicant */
+	void (*removed)          (NMSupplicantInterface * iface);
+
+	/* interface saw a new access point from a scan */
+	void (*scanned_ap)       (NMSupplicantInterface * iface,
+	                          DBusMessage * message);
+
+	/* result of a wireless scan request */
+	void (*scan_req_result)  (NMSupplicantInterface * iface,
+	                          gboolean success);
+
+	/* scan results returned from supplicant */
+	void (*scan_results)     (NMSupplicantInterface * iface,
+	                          guint num_bssids);
+
+	/* link state of the device's connection */
+	void (*connection_state) (NMSupplicantInterface * iface,
+	                          guint32 new_state,
+	                          guint32 old_state);
+
+	/* an error occurred during a connection request */
+	void (*connection_error) (NMSupplicantInterface * iface,
+	                          const char * name,
+	                          const char * message);
+} NMSupplicantInterfaceClass;
+
+
+GType nm_supplicant_interface_get_type (void);
+
+NMSupplicantInterface * nm_supplicant_interface_new (NMSupplicantManager * smgr,
+                                                     const char *ifname,
+                                                     gboolean is_wireless);
+
+gboolean nm_supplicant_interface_set_config (NMSupplicantInterface * iface,
+                                             NMSupplicantConfig * cfg);
+
+void nm_supplicant_interface_disconnect (NMSupplicantInterface * iface);
+
+const char * nm_supplicant_interface_get_device (NMSupplicantInterface * iface);
+
+gboolean nm_supplicant_interface_request_scan (NMSupplicantInterface * self);
+
+guint32 nm_supplicant_interface_get_state (NMSupplicantInterface * self);
+
+guint32 nm_supplicant_interface_get_connection_state (NMSupplicantInterface * self);
+
+const char *nm_supplicant_interface_state_to_string (guint32 state);
+
+const char *nm_supplicant_interface_connection_state_to_string (guint32 state);
+
+gboolean nm_supplicant_interface_get_scanning (NMSupplicantInterface *self);
+
+G_END_DECLS
+
+#endif	/* NM_SUPPLICANT_INTERFACE_H */
diff --git a/src/supplicant-manager/nm-supplicant-manager.c b/src/supplicant-manager/nm-supplicant-manager.c
new file mode 100644
index 00000000..a2cf58eb
--- /dev/null
+++ b/src/supplicant-manager/nm-supplicant-manager.c
@@ -0,0 +1,343 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2006 - 2008 Red Hat, Inc.
+ * Copyright (C) 2007 - 2008 Novell, Inc.
+ */
+
+#include <string.h>
+#include <glib.h>
+#include <dbus/dbus.h>
+
+#include "nm-supplicant-manager.h"
+#include "nm-supplicant-interface.h"
+#include "nm-dbus-manager.h"
+#include "nm-marshal.h"
+#include "nm-logging.h"
+#include "nm-glib-compat.h"
+
+#define SUPPLICANT_POKE_INTERVAL 120
+
+typedef struct {
+	NMDBusManager *	dbus_mgr;
+	guint32         state;
+	GSList *        ifaces;
+	gboolean        dispose_has_run;
+	guint			poke_id;
+} NMSupplicantManagerPrivate;
+
+#define NM_SUPPLICANT_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
+                                              NM_TYPE_SUPPLICANT_MANAGER, \
+                                              NMSupplicantManagerPrivate))
+
+G_DEFINE_TYPE (NMSupplicantManager, nm_supplicant_manager, G_TYPE_OBJECT)
+
+
+static void nm_supplicant_manager_name_owner_changed (NMDBusManager *dbus_mgr,
+                                                      const char *name,
+                                                      const char *old,
+                                                      const char *new,
+                                                      gpointer user_data);
+
+static void nm_supplicant_manager_set_state (NMSupplicantManager * self,
+                                             guint32 new_state);
+
+static gboolean nm_supplicant_manager_startup (NMSupplicantManager * self);
+
+
+/* Signals */
+enum {
+	STATE,       /* change in the manager's state */
+	LAST_SIGNAL
+};
+static guint nm_supplicant_manager_signals[LAST_SIGNAL] = { 0 };
+
+
+NMSupplicantManager *
+nm_supplicant_manager_get (void)
+{
+	static NMSupplicantManager * singleton = NULL;
+
+	if (!singleton) {
+		singleton = NM_SUPPLICANT_MANAGER (g_object_new (NM_TYPE_SUPPLICANT_MANAGER, NULL));
+	} else {
+		g_object_ref (singleton);
+	}
+
+	g_assert (singleton);
+	return singleton;
+}
+
+static gboolean
+poke_supplicant_cb (gpointer user_data)
+{
+	NMSupplicantManager *self = NM_SUPPLICANT_MANAGER (user_data);
+	NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self);
+	DBusGConnection *g_connection;
+	DBusGProxy *proxy;
+	const char *tmp = "ignoreme";
+
+	g_connection = nm_dbus_manager_get_connection (priv->dbus_mgr);
+	proxy = dbus_g_proxy_new_for_name (g_connection,
+	                                   WPAS_DBUS_SERVICE,
+	                                   WPAS_DBUS_PATH,
+	                                   WPAS_DBUS_INTERFACE);
+	if (!proxy) {
+		nm_log_warn (LOGD_SUPPLICANT, "Error: could not init wpa_supplicant proxy");
+		goto out;
+	}
+
+	nm_log_info (LOGD_SUPPLICANT, "Trying to start the supplicant...");
+	dbus_g_proxy_call_no_reply (proxy, "getInterface", G_TYPE_STRING, tmp, G_TYPE_INVALID);
+	g_object_unref (proxy);
+
+out:
+	/* Reschedule the poke */	
+	priv->poke_id = g_timeout_add_seconds (SUPPLICANT_POKE_INTERVAL,
+	                               poke_supplicant_cb,
+	                               (gpointer) self);
+
+	return FALSE;
+}
+
+static void
+nm_supplicant_manager_init (NMSupplicantManager * self)
+{
+	NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self);
+	gboolean running;
+
+	priv->dispose_has_run = FALSE;
+	priv->state = NM_SUPPLICANT_MANAGER_STATE_DOWN;
+	priv->dbus_mgr = nm_dbus_manager_get ();
+	priv->poke_id = 0;
+
+	running = nm_supplicant_manager_startup (self);
+
+	g_signal_connect (priv->dbus_mgr,
+	                  "name-owner-changed",
+	                  G_CALLBACK (nm_supplicant_manager_name_owner_changed),
+	                  self);
+
+	if (!running) {
+		/* Try to activate the supplicant */
+		priv->poke_id = g_idle_add (poke_supplicant_cb, (gpointer) self);
+	}
+}
+
+static void
+nm_supplicant_manager_dispose (GObject *object)
+{
+	NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (object);
+
+	if (priv->dispose_has_run) {
+		G_OBJECT_CLASS (nm_supplicant_manager_parent_class)->dispose (object);
+		return;
+	}
+
+	priv->dispose_has_run = TRUE;
+
+	if (priv->poke_id) {
+		g_source_remove (priv->poke_id);
+		priv->poke_id = 0;
+	}
+
+	if (priv->dbus_mgr) {
+		g_object_unref (G_OBJECT (priv->dbus_mgr));
+		priv->dbus_mgr = NULL;
+	}
+
+	/* Chain up to the parent class */
+	G_OBJECT_CLASS (nm_supplicant_manager_parent_class)->dispose (object);
+}
+
+static void
+nm_supplicant_manager_class_init (NMSupplicantManagerClass *klass)
+{
+	GObjectClass * object_class = G_OBJECT_CLASS (klass);
+
+	g_type_class_add_private (object_class, sizeof (NMSupplicantManagerPrivate));
+
+	object_class->dispose = nm_supplicant_manager_dispose;
+
+	/* Signals */
+	nm_supplicant_manager_signals[STATE] =
+		g_signal_new ("state",
+		              G_OBJECT_CLASS_TYPE (object_class),
+		              G_SIGNAL_RUN_LAST,
+		              G_STRUCT_OFFSET (NMSupplicantManagerClass, state),
+		              NULL, NULL,
+		              _nm_marshal_VOID__UINT_UINT,
+		              G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
+}
+
+static void
+nm_supplicant_manager_name_owner_changed (NMDBusManager *dbus_mgr,
+                                          const char *name,
+										  const char *old_owner,
+										  const char *new_owner,
+                                          gpointer user_data)
+{
+	NMSupplicantManager * self = (NMSupplicantManager *) user_data;
+	NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self);
+	gboolean old_owner_good = (old_owner && strlen (old_owner));
+	gboolean new_owner_good = (new_owner && strlen (new_owner));
+
+	/* Can't handle the signal if its not from the supplicant service */
+	if (strcmp (WPAS_DBUS_SERVICE, name) != 0)
+		return;
+
+	if (!old_owner_good && new_owner_good) {
+		gboolean running;
+
+		running = nm_supplicant_manager_startup (self);
+
+		if (running && priv->poke_id) {
+			g_source_remove (priv->poke_id);
+			priv->poke_id = 0;
+		}
+	} else if (old_owner_good && !new_owner_good) {
+		nm_supplicant_manager_set_state (self, NM_SUPPLICANT_MANAGER_STATE_DOWN);
+
+		if (priv->poke_id)
+			g_source_remove (priv->poke_id);
+
+		/* Poke the supplicant so that it gets activated by dbus system bus
+		 * activation.
+		 */
+		priv->poke_id = g_idle_add (poke_supplicant_cb, (gpointer) self);
+	}
+}
+
+
+guint32
+nm_supplicant_manager_get_state (NMSupplicantManager * self)
+{
+	g_return_val_if_fail (NM_IS_SUPPLICANT_MANAGER (self), FALSE);
+
+	return NM_SUPPLICANT_MANAGER_GET_PRIVATE (self)->state;
+}
+
+static void
+nm_supplicant_manager_set_state (NMSupplicantManager * self, guint32 new_state)
+{
+	NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self);
+	guint32 old_state;
+
+	if (new_state == priv->state)
+		return;
+
+	old_state = priv->state;
+	priv->state = new_state;
+	g_signal_emit (self,
+	               nm_supplicant_manager_signals[STATE],
+	               0,
+	               priv->state,
+	               old_state);
+}
+
+static gboolean
+nm_supplicant_manager_startup (NMSupplicantManager * self)
+{
+	gboolean running;
+
+	/* FIXME: convert to pending call */
+	running = nm_dbus_manager_name_has_owner (NM_SUPPLICANT_MANAGER_GET_PRIVATE (self)->dbus_mgr,
+	                                          WPAS_DBUS_SERVICE);
+	if (running)
+		nm_supplicant_manager_set_state (self, NM_SUPPLICANT_MANAGER_STATE_IDLE);
+
+	return running;
+}
+
+NMSupplicantInterface *
+nm_supplicant_manager_get_iface (NMSupplicantManager * self,
+								 const char *ifname,
+								 gboolean is_wireless)
+{
+	NMSupplicantManagerPrivate *priv;
+	NMSupplicantInterface * iface = NULL;
+	GSList * elt;
+
+	g_return_val_if_fail (NM_IS_SUPPLICANT_MANAGER (self), NULL);
+	g_return_val_if_fail (ifname != NULL, NULL);
+
+	priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self);
+
+	/* Ensure we don't already have this interface */
+	for (elt = priv->ifaces; elt; elt = g_slist_next (elt)) {
+		NMSupplicantInterface * if_tmp = (NMSupplicantInterface *) elt->data;
+
+		if (!strcmp (ifname, nm_supplicant_interface_get_device (if_tmp))) {
+			iface = if_tmp;
+			break;
+		}
+	}
+
+	if (!iface) {
+		nm_log_dbg (LOGD_SUPPLICANT, "(%s): creating new supplicant interface", ifname);
+		iface = nm_supplicant_interface_new (self, ifname, is_wireless);
+		if (iface)
+			priv->ifaces = g_slist_append (priv->ifaces, iface);
+	} else {
+		nm_log_dbg (LOGD_SUPPLICANT, "(%s): returning existing supplicant interface", ifname);
+	}
+
+	return iface;
+}
+
+void
+nm_supplicant_manager_release_iface (NMSupplicantManager * self,
+                                     NMSupplicantInterface * iface)
+{
+	NMSupplicantManagerPrivate *priv;
+	GSList * elt;
+
+	g_return_if_fail (NM_IS_SUPPLICANT_MANAGER (self));
+	g_return_if_fail (NM_IS_SUPPLICANT_INTERFACE (iface));
+
+	priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self);
+
+	for (elt = priv->ifaces; elt; elt = g_slist_next (elt)) {
+		NMSupplicantInterface * if_tmp = (NMSupplicantInterface *) elt->data;
+
+		if (if_tmp == iface) {
+			/* Remove the iface from the supplicant manager's list and
+			 * dereference to match additional reference in get_iface.
+			 */
+			priv->ifaces = g_slist_remove_link (priv->ifaces, elt);
+			g_slist_free_1 (elt);
+			g_object_unref (iface);
+			break;
+		}
+	}
+}
+
+const char *
+nm_supplicant_manager_state_to_string (guint32 state)
+{
+	switch (state) {
+	case NM_SUPPLICANT_MANAGER_STATE_DOWN:
+		return "down";
+	case NM_SUPPLICANT_MANAGER_STATE_IDLE:
+		return "idle";
+	default:
+		break;
+	}
+	return "unknown";
+}
+
+
diff --git a/src/supplicant-manager/nm-supplicant-manager.h b/src/supplicant-manager/nm-supplicant-manager.h
new file mode 100644
index 00000000..fef2a774
--- /dev/null
+++ b/src/supplicant-manager/nm-supplicant-manager.h
@@ -0,0 +1,88 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2006 - 2008 Red Hat, Inc.
+ * Copyright (C) 2007 - 2008 Novell, Inc.
+ */
+
+#ifndef NM_SUPPLICANT_MANAGER_H
+#define NM_SUPPLICANT_MANAGER_H
+
+#include <glib-object.h>
+#include "nm-supplicant-types.h"
+#include "nm-device.h"
+
+#define WPAS_DBUS_SERVICE	"fi.epitest.hostap.WPASupplicant"
+#define WPAS_DBUS_PATH		"/fi/epitest/hostap/WPASupplicant"
+#define WPAS_DBUS_INTERFACE	"fi.epitest.hostap.WPASupplicant"
+
+
+G_BEGIN_DECLS
+
+/*
+ * Supplicant manager states
+ *   Either state may transition to the other state at any time.
+ *
+ * DOWN: supplicant manager has been created, but cannot be used; the supplicant
+ *           is either not running or has not yet been fully initialized.
+ * IDLE: supplicant manager is ready for use
+ *
+ * Note: LAST is an invalid state and only used for boundary checking.
+ */
+enum {
+	NM_SUPPLICANT_MANAGER_STATE_DOWN = 0,
+	NM_SUPPLICANT_MANAGER_STATE_IDLE,
+	NM_SUPPLICANT_MANAGER_STATE_LAST
+};
+
+
+#define NM_TYPE_SUPPLICANT_MANAGER				(nm_supplicant_manager_get_type ())
+#define NM_SUPPLICANT_MANAGER(obj)				(G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SUPPLICANT_MANAGER, NMSupplicantManager))
+#define NM_SUPPLICANT_MANAGER_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST ((klass),  NM_TYPE_SUPPLICANT_MANAGER, NMSupplicantManagerClass))
+#define NM_IS_SUPPLICANT_MANAGER(obj)			(G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SUPPLICANT_MANAGER))
+#define NM_IS_SUPPLICANT_MANAGER_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE ((klass),  NM_TYPE_SUPPLICANT_MANAGER))
+#define NM_SUPPLICANT_MANAGER_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS ((obj),  NM_TYPE_SUPPLICANT_MANAGER, NMSupplicantManagerClass))
+
+struct _NMSupplicantManager
+{
+	GObject parent;
+};
+
+typedef struct
+{
+	GObjectClass parent;
+
+	/* class members */
+	void (* state)  (NMSupplicantManager * mgr, guint32 new_state, guint32 old_state);
+} NMSupplicantManagerClass;
+
+GType nm_supplicant_manager_get_type (void);
+
+NMSupplicantManager * nm_supplicant_manager_get (void);
+
+guint32 nm_supplicant_manager_get_state (NMSupplicantManager * mgr);
+
+NMSupplicantInterface * nm_supplicant_manager_get_iface (NMSupplicantManager * mgr,
+                                                         const char *ifname,
+														 gboolean is_wireless);
+
+void nm_supplicant_manager_release_iface (NMSupplicantManager * mgr,
+                                          NMSupplicantInterface * iface);
+
+const char *nm_supplicant_manager_state_to_string (guint32 state);
+
+#endif /* NM_SUPPLICANT_MANAGER_H */
diff --git a/src/supplicant-manager/nm-supplicant-settings-verify.c b/src/supplicant-manager/nm-supplicant-settings-verify.c
new file mode 100644
index 00000000..28334655
--- /dev/null
+++ b/src/supplicant-manager/nm-supplicant-settings-verify.c
@@ -0,0 +1,238 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2006 - 2008 Red Hat, Inc.
+ */
+
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "nm-supplicant-settings-verify.h"
+
+struct Opt {
+	const char *     key;
+	const OptType    type;
+	const gint32     int_low;  /* Inclusive */
+	const gint32     int_high; /* Inclusive; max length for strings */
+	const gboolean   str_allowed_multiple;
+	const char **    str_allowed;
+};
+
+
+static gboolean validate_type_int     (const struct Opt * opt,
+                                       const char * value,
+                                       const guint32 len);
+
+static gboolean validate_type_bytes   (const struct Opt * opt,
+                                       const char * value,
+                                       const guint32 len);
+
+static gboolean validate_type_keyword (const struct Opt * opt,
+                                       const char * value,
+                                       const guint32 len);
+
+typedef gboolean (*validate_func)(const struct Opt *, const char *, const guint32);
+
+struct validate_entry {
+	const OptType  type;
+	const validate_func func;
+};
+
+static const struct validate_entry validate_table[] = {
+	{ TYPE_INT,     validate_type_int     },
+	{ TYPE_BYTES,   validate_type_bytes   },
+	{ TYPE_KEYWORD, validate_type_keyword },
+};
+
+
+const char * pairwise_allowed[] = { "CCMP", "TKIP", "NONE", NULL };
+const char * group_allowed[] =    { "CCMP", "TKIP", "WEP104", "WEP40", NULL };
+const char * proto_allowed[] =    { "WPA", "RSN", NULL };
+const char * key_mgmt_allowed[] = { "WPA-PSK", "WPA-EAP", "IEEE8021X", "WPA-NONE",
+                                    "NONE", NULL };
+const char * auth_alg_allowed[] = { "OPEN", "SHARED", "LEAP", NULL };
+const char * eap_allowed[] =      { "LEAP", "MD5", "TLS", "PEAP", "TTLS", "SIM",
+                                    "PSK", "FAST", NULL };
+
+const char * phase1_allowed[] =   {"peapver=0", "peapver=1", "peaplabel=1",
+                                    "peap_outer_success=0", "include_tls_length=1",
+                                    "sim_min_num_chal=3", NULL };
+const char * phase2_allowed[] =   {"auth=PAP", "auth=CHAP", "auth=MSCHAP",
+                                   "auth=MSCHAPV2", "auth=GTC", "auth=OTP",
+                                   "auth=MD5", "auth=TLS", "autheap=MD5",
+                                   "autheap=MSCHAPV2", "autheap=OTP",
+                                   "autheap=GTC", "autheap=TLS", NULL };
+
+static const struct Opt opt_table[] = {
+	{ "ssid",               TYPE_BYTES,   0, 32,FALSE,  NULL },
+	{ "bssid",              TYPE_KEYWORD, 0, 0, FALSE,  NULL },
+	{ "scan_ssid",          TYPE_INT,     0, 1, FALSE,  NULL },
+	{ "mode",               TYPE_INT,     0, 1, FALSE,  NULL },
+	{ "frequency",          TYPE_INT,     2412, 5825, FALSE,  NULL },
+	{ "auth_alg",           TYPE_KEYWORD, 0, 0, FALSE,  auth_alg_allowed },
+	{ "psk",                TYPE_BYTES,   0, 0, FALSE,  NULL },
+	{ "pairwise",           TYPE_KEYWORD, 0, 0, FALSE,  pairwise_allowed },
+	{ "group",              TYPE_KEYWORD, 0, 0, FALSE,  group_allowed },
+	{ "proto",              TYPE_KEYWORD, 0, 0, FALSE,  proto_allowed },
+	{ "key_mgmt",           TYPE_KEYWORD, 0, 0, FALSE,  key_mgmt_allowed },
+	{ "wep_key0",           TYPE_BYTES,   0, 0, FALSE,  NULL },
+	{ "wep_key1",           TYPE_BYTES,   0, 0, FALSE,  NULL },
+	{ "wep_key2",           TYPE_BYTES,   0, 0, FALSE,  NULL },
+	{ "wep_key3",           TYPE_BYTES,   0, 0, FALSE,  NULL },
+	{ "wep_tx_keyidx",      TYPE_INT,     0, 3, FALSE,  NULL },
+	{ "eapol_flags",        TYPE_INT,     0, 3, FALSE,  NULL },
+	{ "eap",                TYPE_KEYWORD, 0, 0, FALSE,  eap_allowed },
+	{ "identity",           TYPE_BYTES,   0, 0, FALSE,  NULL },
+	{ "password",           TYPE_BYTES,   0, 0, FALSE,  NULL },
+	{ "ca_path",            TYPE_BYTES,   0, 0, FALSE,  NULL },
+	{ "ca_cert",            TYPE_BYTES,   0, 65536, FALSE,  NULL },
+	{ "client_cert",        TYPE_BYTES,   0, 65536, FALSE,  NULL },
+	{ "private_key",        TYPE_BYTES,   0, 65536, FALSE,  NULL },
+	{ "private_key_passwd", TYPE_BYTES,   0, 1024, FALSE,  NULL },
+	{ "phase1",             TYPE_KEYWORD, 0, 0, TRUE, phase1_allowed },
+	{ "phase2",             TYPE_KEYWORD, 0, 0, TRUE, phase2_allowed },
+	{ "anonymous_identity", TYPE_BYTES,   0, 0, FALSE,  NULL },
+	{ "ca_path2",           TYPE_BYTES,   0, 0, FALSE,  NULL },
+	{ "ca_cert2",           TYPE_BYTES,   0, 65536, FALSE,  NULL },
+	{ "client_cert2",       TYPE_BYTES,   0, 65536, FALSE,  NULL },
+	{ "private_key2",       TYPE_BYTES,   0, 65536, FALSE,  NULL },
+	{ "private_key2_passwd",TYPE_BYTES,   0, 1024, FALSE,  NULL },
+	{ "pin",                TYPE_BYTES,   0, 0, FALSE,  NULL },
+	{ "pcsc",               TYPE_BYTES,   0, 0, FALSE,  NULL },
+	{ "nai",                TYPE_BYTES,   0, 0, FALSE,  NULL },
+	{ "eappsk",             TYPE_BYTES,   0, 0, FALSE,  NULL },
+	{ "pac_file",           TYPE_BYTES,   0, 0, FALSE,  NULL },
+	{ "engine",             TYPE_INT,     0, 1, FALSE,  NULL },
+	{ "engine_id",          TYPE_BYTES,   0, 0, FALSE,  NULL },
+	{ "key_id",             TYPE_BYTES,   0, 0, FALSE,  NULL },
+	{ "fragment_size",      TYPE_INT,     1, 2000, FALSE,  NULL },
+};
+
+
+static gboolean
+validate_type_int (const struct Opt * opt,
+                   const char * value,
+                   const guint32 len)
+{
+	long int intval;
+
+	g_return_val_if_fail (opt != NULL, FALSE);
+	g_return_val_if_fail (value != NULL, FALSE);
+
+	errno = 0;
+	intval = strtol (value, NULL, 10);
+	if (errno != 0)
+		return FALSE;
+
+	/* strtol returns a long, but we are dealing with ints */
+	if (intval > INT_MAX || intval < INT_MIN)
+		return FALSE;
+	if (intval > opt->int_high || intval < opt->int_low)
+		return FALSE;
+
+	return TRUE;
+}
+
+static gboolean
+validate_type_bytes (const struct Opt * opt,
+                     const char * value,
+                     const guint32 len)
+{
+	guint32 check_len;
+
+	g_return_val_if_fail (opt != NULL, FALSE);
+	g_return_val_if_fail (value != NULL, FALSE);
+
+	check_len = opt->int_high ? opt->int_high : 255;
+	if (len > check_len)
+		return FALSE;
+
+	return TRUE;
+}
+
+static gboolean
+validate_type_keyword (const struct Opt * opt,
+                       const char * value,
+                       const guint32 len)
+{
+	char **		allowed;
+	gchar **	candidates = NULL;
+	char **		candidate;
+	gboolean	found = FALSE;
+
+	g_return_val_if_fail (opt != NULL, FALSE);
+	g_return_val_if_fail (value != NULL, FALSE);
+
+	/* Allow everything */
+	if (!opt->str_allowed)
+		return TRUE;
+
+	candidates = g_strsplit (value, " ", 0);
+	if (!candidates)
+		goto out;
+
+	/* validate each space-separated word in 'value' */
+	for (candidate = candidates; *candidate; candidate++) {
+		found = FALSE;
+		for (allowed = (char **) opt->str_allowed; *allowed; allowed++) {
+			if (strcmp (*candidate, *allowed) == 0) {
+				found = TRUE;
+				break;
+			}
+		}
+		if (!found)
+			break;
+	}
+
+out:
+	g_strfreev (candidates);
+	return found;
+}
+
+OptType
+nm_supplicant_settings_verify_setting (const char * key,
+                                       const char * value,
+                                       const guint32 len)
+{
+	OptType type = TYPE_INVALID;
+	int opt_count = sizeof (opt_table) / sizeof (opt_table[0]);
+	int val_count = sizeof (validate_table) / sizeof (validate_table[0]);
+	int i, j;
+
+	g_return_val_if_fail (key != NULL, FALSE);
+	g_return_val_if_fail (value != NULL, FALSE);
+
+	for (i = 0; i < opt_count; i++) {
+		if (strcmp (opt_table[i].key, key) != 0)
+			continue;
+
+		for (j = 0; j < val_count; j++) {
+			if (validate_table[j].type == opt_table[i].type) {
+				if ((*(validate_table[j].func))(&opt_table[i], value, len)) {
+					type = opt_table[i].type;
+					break;
+				}
+			}
+		}
+	}
+
+	return type;
+}
+
diff --git a/src/supplicant-manager/nm-supplicant-settings-verify.h b/src/supplicant-manager/nm-supplicant-settings-verify.h
new file mode 100644
index 00000000..0939ebdb
--- /dev/null
+++ b/src/supplicant-manager/nm-supplicant-settings-verify.h
@@ -0,0 +1,37 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2006 - 2008 Red Hat, Inc.
+ */
+
+#ifndef NM_SUPPLICANT_SETTINGS_VERIFY_H
+#define NM_SUPPLICANT_SETTINGS_VERIFY_H
+
+typedef enum OptType {
+	TYPE_INVALID = 0,
+	TYPE_INT,
+	TYPE_BYTES,
+	TYPE_KEYWORD,
+	TYPE_STRING
+} OptType;
+
+OptType nm_supplicant_settings_verify_setting (const char * key,
+                                               const char * value,
+                                               const guint32 len);
+
+
+#endif /* NM_SUPPLICANT_SETTINGS_VERIFY_H */
diff --git a/src/supplicant-manager/nm-supplicant-types.h b/src/supplicant-manager/nm-supplicant-types.h
new file mode 100644
index 00000000..16e4a6ba
--- /dev/null
+++ b/src/supplicant-manager/nm-supplicant-types.h
@@ -0,0 +1,28 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2006 - 2008 Red Hat, Inc.
+ */
+
+#ifndef NM_SUPPLICANT_TYPES_H
+#define NM_SUPPLICANT_TYPES_H
+
+typedef struct _NMSupplicantManager NMSupplicantManager;
+typedef struct _NMSupplicantInterface NMSupplicantInterface;
+typedef struct _NMSupplicantConfig NMSupplicantConfig;
+
+#endif  /* NM_SUPPLICANT_TYPES_H */
diff --git a/src/supplicant-manager/tests/Makefile.am b/src/supplicant-manager/tests/Makefile.am
new file mode 100644
index 00000000..b5e4db61
--- /dev/null
+++ b/src/supplicant-manager/tests/Makefile.am
@@ -0,0 +1,27 @@
+INCLUDES = \
+	-I$(top_srcdir)/include \
+	-I$(top_srcdir)/libnm-util \
+	-I$(top_srcdir)/src \
+	-I$(top_srcdir)/src/supplicant-manager
+
+noinst_PROGRAMS = test-supplicant-config
+
+test_supplicant_config_SOURCES = \
+	test-supplicant-config.c
+
+test_supplicant_config_CPPFLAGS = \
+	$(GLIB_CFLAGS) \
+	$(DBUS_CFLAGS)
+
+test_supplicant_config_LDADD = \
+	$(top_builddir)/libnm-util/libnm-util.la \
+	$(top_builddir)/src/supplicant-manager/libsupplicant-manager.la \
+	$(DBUS_LIBS)
+
+if WITH_TESTS
+
+check-local: test-supplicant-config
+	$(abs_builddir)/test-supplicant-config
+
+endif
+
diff --git a/src/supplicant-manager/tests/Makefile.in b/src/supplicant-manager/tests/Makefile.in
new file mode 100644
index 00000000..f919b8b8
--- /dev/null
+++ b/src/supplicant-manager/tests/Makefile.in
@@ -0,0 +1,579 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+noinst_PROGRAMS = test-supplicant-config$(EXEEXT)
+subdir = src/supplicant-manager/tests
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \
+	$(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/intltool.m4 \
+	$(top_srcdir)/m4/libnl-check.m4 $(top_srcdir)/m4/libtool.m4 \
+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+PROGRAMS = $(noinst_PROGRAMS)
+am_test_supplicant_config_OBJECTS =  \
+	test_supplicant_config-test-supplicant-config.$(OBJEXT)
+test_supplicant_config_OBJECTS = $(am_test_supplicant_config_OBJECTS)
+am__DEPENDENCIES_1 =
+test_supplicant_config_DEPENDENCIES =  \
+	$(top_builddir)/libnm-util/libnm-util.la \
+	$(top_builddir)/src/supplicant-manager/libsupplicant-manager.la \
+	$(am__DEPENDENCIES_1)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
+SOURCES = $(test_supplicant_config_SOURCES)
+DIST_SOURCES = $(test_supplicant_config_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_LIBS = @DBUS_LIBS@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DHCLIENT_PATH = @DHCLIENT_PATH@
+DHCPCD_PATH = @DHCPCD_PATH@
+DISABLE_DEPRECATED = @DISABLE_DEPRECATED@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIO_CFLAGS = @GIO_CFLAGS@
+GIO_LIBS = @GIO_LIBS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GMODULE_CFLAGS = @GMODULE_CFLAGS@
+GMODULE_LIBS = @GMODULE_LIBS@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+GUDEV_CFLAGS = @GUDEV_CFLAGS@
+GUDEV_LIBS = @GUDEV_LIBS@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+IPTABLES_PATH = @IPTABLES_PATH@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBDL = @LIBDL@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBM = @LIBM@
+LIBNL_CFLAGS = @LIBNL_CFLAGS@
+LIBNL_LIBS = @LIBNL_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_LIBS = @NSS_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+POFILES = @POFILES@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@
+RANLIB = @RANLIB@
+RESOLVCONF_PATH = @RESOLVCONF_PATH@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SYSTEM_CA_PATH = @SYSTEM_CA_PATH@
+UDEV_BASE_DIR = @UDEV_BASE_DIR@
+USE_NLS = @USE_NLS@
+UUID_CFLAGS = @UUID_CFLAGS@
+UUID_LIBS = @UUID_LIBS@
+VERSION = @VERSION@
+XGETTEXT = @XGETTEXT@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+INCLUDES = \
+	-I$(top_srcdir)/include \
+	-I$(top_srcdir)/libnm-util \
+	-I$(top_srcdir)/src \
+	-I$(top_srcdir)/src/supplicant-manager
+
+test_supplicant_config_SOURCES = \
+	test-supplicant-config.c
+
+test_supplicant_config_CPPFLAGS = \
+	$(GLIB_CFLAGS) \
+	$(DBUS_CFLAGS)
+
+test_supplicant_config_LDADD = \
+	$(top_builddir)/libnm-util/libnm-util.la \
+	$(top_builddir)/src/supplicant-manager/libsupplicant-manager.la \
+	$(DBUS_LIBS)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/supplicant-manager/tests/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu src/supplicant-manager/tests/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstPROGRAMS:
+	@list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
+	echo " rm -f" $$list; \
+	rm -f $$list || exit $$?; \
+	test -n "$(EXEEXT)" || exit 0; \
+	list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+	echo " rm -f" $$list; \
+	rm -f $$list
+test-supplicant-config$(EXEEXT): $(test_supplicant_config_OBJECTS) $(test_supplicant_config_DEPENDENCIES) 
+	@rm -f test-supplicant-config$(EXEEXT)
+	$(LINK) $(test_supplicant_config_OBJECTS) $(test_supplicant_config_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_supplicant_config-test-supplicant-config.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@	depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@	depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@	depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LTCOMPILE) -c -o $@ $<
+
+test_supplicant_config-test-supplicant-config.o: test-supplicant-config.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_supplicant_config_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_supplicant_config-test-supplicant-config.o -MD -MP -MF $(DEPDIR)/test_supplicant_config-test-supplicant-config.Tpo -c -o test_supplicant_config-test-supplicant-config.o `test -f 'test-supplicant-config.c' || echo '$(srcdir)/'`test-supplicant-config.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/test_supplicant_config-test-supplicant-config.Tpo $(DEPDIR)/test_supplicant_config-test-supplicant-config.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='test-supplicant-config.c' object='test_supplicant_config-test-supplicant-config.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_supplicant_config_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_supplicant_config-test-supplicant-config.o `test -f 'test-supplicant-config.c' || echo '$(srcdir)/'`test-supplicant-config.c
+
+test_supplicant_config-test-supplicant-config.obj: test-supplicant-config.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_supplicant_config_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_supplicant_config-test-supplicant-config.obj -MD -MP -MF $(DEPDIR)/test_supplicant_config-test-supplicant-config.Tpo -c -o test_supplicant_config-test-supplicant-config.obj `if test -f 'test-supplicant-config.c'; then $(CYGPATH_W) 'test-supplicant-config.c'; else $(CYGPATH_W) '$(srcdir)/test-supplicant-config.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/test_supplicant_config-test-supplicant-config.Tpo $(DEPDIR)/test_supplicant_config-test-supplicant-config.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='test-supplicant-config.c' object='test_supplicant_config-test-supplicant-config.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_supplicant_config_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_supplicant_config-test-supplicant-config.obj `if test -f 'test-supplicant-config.c'; then $(CYGPATH_W) 'test-supplicant-config.c'; else $(CYGPATH_W) '$(srcdir)/test-supplicant-config.c'; fi`
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	set x; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+@WITH_TESTS_FALSE@check-local:
+check-am: all-am
+	$(MAKE) $(AM_MAKEFLAGS) check-local
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \
+	mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: check-am install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am check-local clean \
+	clean-generic clean-libtool clean-noinstPROGRAMS ctags \
+	distclean distclean-compile distclean-generic \
+	distclean-libtool distclean-tags distdir dvi dvi-am html \
+	html-am info info-am install install-am install-data \
+	install-data-am install-dvi install-dvi-am install-exec \
+	install-exec-am install-html install-html-am install-info \
+	install-info-am install-man install-pdf install-pdf-am \
+	install-ps install-ps-am install-strip installcheck \
+	installcheck-am installdirs maintainer-clean \
+	maintainer-clean-generic mostlyclean mostlyclean-compile \
+	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+	tags uninstall uninstall-am
+
+
+@WITH_TESTS_TRUE@check-local: test-supplicant-config
+@WITH_TESTS_TRUE@	$(abs_builddir)/test-supplicant-config
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/supplicant-manager/tests/test-supplicant-config.c b/src/supplicant-manager/tests/test-supplicant-config.c
new file mode 100644
index 00000000..d0868b5f
--- /dev/null
+++ b/src/supplicant-manager/tests/test-supplicant-config.c
@@ -0,0 +1,518 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2008 - 2009 Red Hat, Inc.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <string.h>
+#include <netinet/ether.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <dbus/dbus-glib.h>
+
+#include <nm-utils.h>
+#include <nm-setting-connection.h>
+#include <nm-setting-wired.h>
+#include <nm-setting-wireless.h>
+#include <nm-setting-wireless-security.h>
+#include <nm-setting-ip4-config.h>
+#include <nm-setting-8021x.h>
+
+#include "nm-test-helpers.h"
+
+#include "nm-supplicant-config.h"
+#include "nm-supplicant-settings-verify.h"
+
+static gboolean
+validate_opt (const char *detail,
+              GHashTable *hash,
+              const char *key,
+              OptType val_type,
+              gconstpointer expected,
+              size_t expected_len)
+{
+	GValue *value;
+	gint int_val;
+	GByteArray *array;
+	const char *s;
+	const unsigned char *expected_array = expected;
+	int result;
+
+	ASSERT (hash != NULL, detail, "hash was NULL");
+
+	value = g_hash_table_lookup (hash, key);
+	ASSERT (value != NULL,
+	        detail, "option '%s' expected but not found in config hash.");
+
+	switch (val_type) {
+	case TYPE_INT:
+		ASSERT (G_VALUE_HOLDS_INT (value),
+		        detail, "config hash item '%s' was not TYPE_INT.", key);
+		int_val = g_value_get_int (value);
+		ASSERT (int_val == GPOINTER_TO_INT (expected),
+		        detail, "unexpected config hash item '%s' value %d (expected %d)",
+		        key, int_val, GPOINTER_TO_INT (expected));
+		break;
+	case TYPE_BYTES:
+		ASSERT (G_VALUE_HOLDS (value, DBUS_TYPE_G_UCHAR_ARRAY),
+		        detail, "config hash item '%s' was not TYPE_BYTES.", key);
+		array = g_value_get_boxed (value);
+		ASSERT (array->len == expected_len,
+		        detail, "unexpected config hash item '%s' length %d (expected %d)",
+		        key, array->len, expected_len);
+		result = memcmp (array->data, expected_array, expected_len);
+		ASSERT (result == 0, detail, "unexpected config hash item '%s' value", key);
+		break;
+	case TYPE_KEYWORD:
+	case TYPE_STRING:
+		ASSERT (G_VALUE_HOLDS_STRING (value),
+		        detail, "config hash item '%s' was not TYPE_STRING or TYPE_KEYWORD.", key);
+		if (expected_len == -1)
+			expected_len = strlen ((const char *) expected);
+		s = g_value_get_string (value);
+		ASSERT (s != NULL, detail, "unexpected NULL config hash string item '%s'.", key);
+		ASSERT (strlen (s) == expected_len,
+		        detail, "unexpected config hash string item '%s' length %d (expected %d)",
+		        key, strlen (s), expected_len);
+		result = strcmp (s, (const char *) expected);
+		ASSERT (result == 0,
+		        detail, "unexpected config hash string item '%s' value '%s' (expected '%s')",
+		        key, s, (const char *) expected);
+		break;
+	default:
+		g_warning ("unknown supplicant config hash item '%s' option type %d",
+		           key, val_type);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static void
+test_wifi_open (void)
+{
+	NMConnection *connection;
+	NMSettingConnection *s_con;
+	NMSettingWireless *s_wifi;
+	NMSettingIP4Config *s_ip4;
+	NMSupplicantConfig *config;
+	GHashTable *hash;
+	char *uuid;
+	gboolean success;
+	GError *error = NULL;
+	GByteArray *ssid;
+	const unsigned char ssid_data[] = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44 };
+	GByteArray *bssid;
+	const unsigned char bssid_data[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 };
+	const char *bssid_str = "11:22:33:44:55:66";
+
+	connection = nm_connection_new ();
+	ASSERT (connection != NULL,
+	        "wifi-open", "failed to allocate new connection");
+
+	/* Connection setting */
+	s_con = (NMSettingConnection *) nm_setting_connection_new ();
+	ASSERT (s_con != NULL,
+	        "wifi-open", "failed to allocate new %s setting",
+	        NM_SETTING_CONNECTION_SETTING_NAME);
+	nm_connection_add_setting (connection, NM_SETTING (s_con));
+
+	uuid = nm_utils_uuid_generate ();
+	g_object_set (s_con,
+	              NM_SETTING_CONNECTION_ID, "Test Wifi Open",
+	              NM_SETTING_CONNECTION_UUID, uuid,
+	              NM_SETTING_CONNECTION_AUTOCONNECT, TRUE,
+	              NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME,
+	              NULL);
+	g_free (uuid);
+
+	/* Wifi setting */
+	s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
+	ASSERT (s_wifi != NULL,
+	        "wifi-open", "failed to allocate new %s setting",
+	        NM_SETTING_WIRELESS_SETTING_NAME);
+	nm_connection_add_setting (connection, NM_SETTING (s_wifi));
+
+	ssid = g_byte_array_sized_new (sizeof (ssid_data));
+	g_byte_array_append (ssid, ssid_data, sizeof (ssid_data));
+	bssid = g_byte_array_sized_new (sizeof (bssid_data));
+	g_byte_array_append (bssid, bssid_data, sizeof (bssid_data));
+
+	g_object_set (s_wifi,
+	              NM_SETTING_WIRELESS_SSID, ssid,
+	              NM_SETTING_WIRELESS_BSSID, bssid,
+	              NM_SETTING_WIRELESS_MODE, "infrastructure",
+	              NM_SETTING_WIRELESS_BAND, "bg",
+	              NULL);
+
+	g_byte_array_free (ssid, TRUE);
+	g_byte_array_free (bssid, TRUE);
+
+	/* IP4 setting */
+	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
+	ASSERT (s_ip4 != NULL,
+	        "wifi-open", "failed to allocate new %s setting",
+	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
+	nm_connection_add_setting (connection, NM_SETTING (s_ip4));
+
+	g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
+
+	ASSERT (nm_connection_verify (connection, &error) == TRUE,
+	        "wifi-open", "failed to verify connection: %s",
+	        (error && error->message) ? error->message : "(unknown)");
+
+	config = nm_supplicant_config_new ();
+	ASSERT (config != NULL,
+	        "wifi-open", "failed to create new supplicant config");
+
+	success = nm_supplicant_config_add_setting_wireless (config, s_wifi, TRUE, 0, TRUE);
+	ASSERT (success == TRUE,
+	        "wifi-open", "failed to add wireless setting to supplicant config.");
+
+	success = nm_supplicant_config_add_no_security (config);
+	ASSERT (success == TRUE,
+	        "wifi-open", "failed to add wireless security to supplicant config.");
+
+	hash = nm_supplicant_config_get_hash (config);
+	ASSERT (hash != NULL,
+	        "wifi-open", "failed to hash supplicant config options.");
+
+	validate_opt ("wifi-open", hash, "scan_ssid", TYPE_INT, GINT_TO_POINTER (1), -1);
+	validate_opt ("wifi-open", hash, "ssid", TYPE_BYTES, ssid_data, sizeof (ssid_data));
+	validate_opt ("wifi-open", hash, "bssid", TYPE_KEYWORD, bssid_str, -1);
+	validate_opt ("wifi-open", hash, "key_mgmt", TYPE_KEYWORD, "NONE", -1);
+
+	g_object_unref (connection);
+}
+
+static void
+test_wifi_wep_key (const char *detail,
+                   NMWepKeyType wep_type,
+                   const char *key_data,
+                   const unsigned char *expected,
+                   size_t expected_size)
+{
+	NMConnection *connection;
+	NMSettingConnection *s_con;
+	NMSettingWireless *s_wifi;
+	NMSettingWirelessSecurity *s_wsec;
+	NMSettingIP4Config *s_ip4;
+	NMSupplicantConfig *config;
+	GHashTable *hash;
+	char *uuid;
+	gboolean success;
+	GError *error = NULL;
+	GByteArray *ssid;
+	const unsigned char ssid_data[] = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44 };
+	GByteArray *bssid;
+	const unsigned char bssid_data[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 };
+	const char *bssid_str = "11:22:33:44:55:66";
+
+	connection = nm_connection_new ();
+	ASSERT (connection != NULL,
+	        detail, "failed to allocate new connection");
+
+	/* Connection setting */
+	s_con = (NMSettingConnection *) nm_setting_connection_new ();
+	ASSERT (s_con != NULL,
+	        detail, "failed to allocate new %s setting",
+	        NM_SETTING_CONNECTION_SETTING_NAME);
+	nm_connection_add_setting (connection, NM_SETTING (s_con));
+
+	uuid = nm_utils_uuid_generate ();
+	g_object_set (s_con,
+	              NM_SETTING_CONNECTION_ID, "Test Wifi WEP Key",
+	              NM_SETTING_CONNECTION_UUID, uuid,
+	              NM_SETTING_CONNECTION_AUTOCONNECT, TRUE,
+	              NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME,
+	              NULL);
+	g_free (uuid);
+
+	/* Wifi setting */
+	s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
+	ASSERT (s_wifi != NULL,
+	        detail, "failed to allocate new %s setting",
+	        NM_SETTING_WIRELESS_SETTING_NAME);
+	nm_connection_add_setting (connection, NM_SETTING (s_wifi));
+
+	ssid = g_byte_array_sized_new (sizeof (ssid_data));
+	g_byte_array_append (ssid, ssid_data, sizeof (ssid_data));
+	bssid = g_byte_array_sized_new (sizeof (bssid_data));
+	g_byte_array_append (bssid, bssid_data, sizeof (bssid_data));
+
+	g_object_set (s_wifi,
+	              NM_SETTING_WIRELESS_SSID, ssid,
+	              NM_SETTING_WIRELESS_BSSID, bssid,
+	              NM_SETTING_WIRELESS_MODE, "infrastructure",
+	              NM_SETTING_WIRELESS_BAND, "bg",
+	              NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
+	              NULL);
+
+	g_byte_array_free (ssid, TRUE);
+	g_byte_array_free (bssid, TRUE);
+
+	/* Wifi Security setting */
+	s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
+	ASSERT (s_wsec != NULL,
+	        detail, "failed to allocate new %s setting",
+	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
+	nm_connection_add_setting (connection, NM_SETTING (s_wsec));
+
+	g_object_set (s_wsec,
+	              NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none",
+	              NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, wep_type,
+	              NULL);
+	nm_setting_wireless_security_set_wep_key (s_wsec, 0, key_data);	
+
+	/* IP4 setting */
+	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
+	ASSERT (s_ip4 != NULL,
+	        detail, "failed to allocate new %s setting",
+	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
+	nm_connection_add_setting (connection, NM_SETTING (s_ip4));
+
+	g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
+
+	ASSERT (nm_connection_verify (connection, &error) == TRUE,
+	        detail, "failed to verify connection: %s",
+	        (error && error->message) ? error->message : "(unknown)");
+
+	config = nm_supplicant_config_new ();
+	ASSERT (config != NULL,
+	        detail, "failed to create new supplicant config");
+
+	success = nm_supplicant_config_add_setting_wireless (config, s_wifi, TRUE, 0, TRUE);
+	ASSERT (success == TRUE,
+	        detail, "failed to add wireless setting to supplicant config.");
+
+	success = nm_supplicant_config_add_setting_wireless_security (config,
+	                                                              s_wsec,
+	                                                              NULL,
+	                                                              "376aced7-b28c-46be-9a62-fcdf072571da");
+	ASSERT (success == TRUE,
+	        detail, "failed to add wireless security to supplicant config.");
+
+	hash = nm_supplicant_config_get_hash (config);
+	ASSERT (hash != NULL,
+	        detail, "failed to hash supplicant config options.");
+
+	validate_opt (detail, hash, "scan_ssid", TYPE_INT, GINT_TO_POINTER (1), -1);
+	validate_opt (detail, hash, "ssid", TYPE_BYTES, ssid_data, sizeof (ssid_data));
+	validate_opt (detail, hash, "bssid", TYPE_KEYWORD, bssid_str, -1);
+	validate_opt (detail, hash, "key_mgmt", TYPE_KEYWORD, "NONE", -1);
+	validate_opt (detail, hash, "wep_tx_keyidx", TYPE_INT, GINT_TO_POINTER (0), -1);
+	validate_opt (detail, hash, "wep_key0", TYPE_BYTES, expected, expected_size);
+
+	g_object_unref (connection);
+}
+
+static void
+test_wifi_wep (void)
+{
+	const char *key1 = "12345";
+	const unsigned char key1_expected[] = { 0x31, 0x32, 0x33, 0x34, 0x35 };
+	const char *key2 = "ascii test$$$";
+	const unsigned char key2_expected[] = { 0x61, 0x73, 0x63, 0x69, 0x69, 0x20, 0x74, 0x65, 0x73, 0x74, 0x24, 0x24, 0x24 };
+	const char *key3 = "abcdef1234";
+	const unsigned char key3_expected[] = { 0xab, 0xcd, 0xef, 0x12, 0x34 };
+	const char *key4 = "96aec785c6392675f87f592972";
+	const unsigned char key4_expected[] = { 0x96, 0xae, 0xc7, 0x85, 0xc6, 0x39, 0x26, 0x75, 0xf8, 0x7f, 0x59, 0x29, 0x72 };
+	const char *key5 = "r34lly l33t w3p p4ssphr4s3 for t3st1ng";
+	const unsigned char key5_expected[] = { 0xce, 0x68, 0x8b, 0x35, 0xf6, 0x0a, 0x2b, 0xbf, 0xc9, 0x8f, 0xed, 0x10, 0xda };
+
+	test_wifi_wep_key ("wifi-wep-ascii-40", NM_WEP_KEY_TYPE_KEY, key1, key1_expected, sizeof (key1_expected));
+	test_wifi_wep_key ("wifi-wep-ascii-104", NM_WEP_KEY_TYPE_KEY, key2, key2_expected, sizeof (key2_expected));
+	test_wifi_wep_key ("wifi-wep-hex-40", NM_WEP_KEY_TYPE_KEY, key3, key3_expected, sizeof (key3_expected));
+	test_wifi_wep_key ("wifi-wep-hex-104", NM_WEP_KEY_TYPE_KEY, key4, key4_expected, sizeof (key4_expected));
+	test_wifi_wep_key ("wifi-wep-passphrase-104", NM_WEP_KEY_TYPE_PASSPHRASE, key5, key5_expected, sizeof (key5_expected));
+
+	test_wifi_wep_key ("wifi-wep-old-hex-104", NM_WEP_KEY_TYPE_UNKNOWN, key4, key4_expected, sizeof (key4_expected));
+}
+
+static void
+test_wifi_wpa_psk (const char *detail,
+                   OptType key_type,
+                   const char *key_data,
+                   const unsigned char *expected,
+                   size_t expected_size)
+{
+	NMConnection *connection;
+	NMSettingConnection *s_con;
+	NMSettingWireless *s_wifi;
+	NMSettingWirelessSecurity *s_wsec;
+	NMSettingIP4Config *s_ip4;
+	NMSupplicantConfig *config;
+	GHashTable *hash;
+	char *uuid;
+	gboolean success;
+	GError *error = NULL;
+	GByteArray *ssid;
+	const unsigned char ssid_data[] = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44 };
+	GByteArray *bssid;
+	const unsigned char bssid_data[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 };
+	const char *bssid_str = "11:22:33:44:55:66";
+
+	connection = nm_connection_new ();
+	ASSERT (connection != NULL,
+	        detail, "failed to allocate new connection");
+
+	/* Connection setting */
+	s_con = (NMSettingConnection *) nm_setting_connection_new ();
+	ASSERT (s_con != NULL,
+	        detail, "failed to allocate new %s setting",
+	        NM_SETTING_CONNECTION_SETTING_NAME);
+	nm_connection_add_setting (connection, NM_SETTING (s_con));
+
+	uuid = nm_utils_uuid_generate ();
+	g_object_set (s_con,
+	              NM_SETTING_CONNECTION_ID, "Test Wifi WEP Key",
+	              NM_SETTING_CONNECTION_UUID, uuid,
+	              NM_SETTING_CONNECTION_AUTOCONNECT, TRUE,
+	              NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME,
+	              NULL);
+	g_free (uuid);
+
+	/* Wifi setting */
+	s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
+	ASSERT (s_wifi != NULL,
+	        detail, "failed to allocate new %s setting",
+	        NM_SETTING_WIRELESS_SETTING_NAME);
+	nm_connection_add_setting (connection, NM_SETTING (s_wifi));
+
+	ssid = g_byte_array_sized_new (sizeof (ssid_data));
+	g_byte_array_append (ssid, ssid_data, sizeof (ssid_data));
+	bssid = g_byte_array_sized_new (sizeof (bssid_data));
+	g_byte_array_append (bssid, bssid_data, sizeof (bssid_data));
+
+	g_object_set (s_wifi,
+	              NM_SETTING_WIRELESS_SSID, ssid,
+	              NM_SETTING_WIRELESS_BSSID, bssid,
+	              NM_SETTING_WIRELESS_MODE, "infrastructure",
+	              NM_SETTING_WIRELESS_BAND, "bg",
+	              NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
+	              NULL);
+
+	g_byte_array_free (ssid, TRUE);
+	g_byte_array_free (bssid, TRUE);
+
+	/* Wifi Security setting */
+	s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
+	ASSERT (s_wsec != NULL,
+	        detail, "failed to allocate new %s setting",
+	        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
+	nm_connection_add_setting (connection, NM_SETTING (s_wsec));
+
+	g_object_set (s_wsec,
+	              NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk",
+	              NM_SETTING_WIRELESS_SECURITY_PSK, key_data,
+	              NULL);
+
+	nm_setting_wireless_security_add_proto (s_wsec, "wpa");
+	nm_setting_wireless_security_add_proto (s_wsec, "rsn");
+	nm_setting_wireless_security_add_pairwise (s_wsec, "tkip");
+	nm_setting_wireless_security_add_pairwise (s_wsec, "ccmp");
+	nm_setting_wireless_security_add_group (s_wsec, "tkip");
+	nm_setting_wireless_security_add_group (s_wsec, "ccmp");
+
+	/* IP4 setting */
+	s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
+	ASSERT (s_ip4 != NULL,
+	        detail, "failed to allocate new %s setting",
+	        NM_SETTING_IP4_CONFIG_SETTING_NAME);
+	nm_connection_add_setting (connection, NM_SETTING (s_ip4));
+
+	g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
+
+	ASSERT (nm_connection_verify (connection, &error) == TRUE,
+	        detail, "failed to verify connection: %s",
+	        (error && error->message) ? error->message : "(unknown)");
+
+	config = nm_supplicant_config_new ();
+	ASSERT (config != NULL,
+	        detail, "failed to create new supplicant config");
+
+	success = nm_supplicant_config_add_setting_wireless (config, s_wifi, TRUE, 0, TRUE);
+	ASSERT (success == TRUE,
+	        detail, "failed to add wireless setting to supplicant config.");
+
+	success = nm_supplicant_config_add_setting_wireless_security (config,
+	                                                              s_wsec,
+	                                                              NULL,
+	                                                              "376aced7-b28c-46be-9a62-fcdf072571da");
+	ASSERT (success == TRUE,
+	        detail, "failed to add wireless security to supplicant config.");
+
+	hash = nm_supplicant_config_get_hash (config);
+	ASSERT (hash != NULL,
+	        detail, "failed to hash supplicant config options.");
+
+	validate_opt (detail, hash, "scan_ssid", TYPE_INT, GINT_TO_POINTER (1), -1);
+	validate_opt (detail, hash, "ssid", TYPE_BYTES, ssid_data, sizeof (ssid_data));
+	validate_opt (detail, hash, "bssid", TYPE_KEYWORD, bssid_str, -1);
+	validate_opt (detail, hash, "key_mgmt", TYPE_KEYWORD, "WPA-PSK", -1);
+	validate_opt (detail, hash, "proto", TYPE_KEYWORD, "WPA RSN", -1);
+	validate_opt (detail, hash, "pairwise", TYPE_KEYWORD, "TKIP CCMP", -1);
+	validate_opt (detail, hash, "group", TYPE_KEYWORD, "TKIP CCMP", -1);
+	validate_opt (detail, hash, "psk", key_type, expected, expected_size);
+
+	g_object_unref (connection);
+}
+
+static void
+test_wifi_wpa_psk_types (void)
+{
+	const char *key1 = "d4721e911461d3cdef9793858e977fcda091779243abb7316c2f11605a160893";
+	const unsigned char key1_expected[] = { 0xd4, 0x72, 0x1e, 0x91, 0x14, 0x61, 0xd3, 0xcd,
+	                                        0xef, 0x97, 0x93, 0x85, 0x8e, 0x97, 0x7f, 0xcd,
+	                                        0xa0, 0x91, 0x77, 0x92, 0x43, 0xab, 0xb7, 0x31,
+	                                        0x6c, 0x2f, 0x11, 0x60, 0x5a, 0x16, 0x08, 0x93 };
+	const char *key2 = "r34lly l33t wp4 p4ssphr4s3 for t3st1ng";
+
+	test_wifi_wpa_psk ("wifi-wpa-psk-hex", TYPE_BYTES, key1, key1_expected, sizeof (key1_expected));
+	test_wifi_wpa_psk ("wifi-wep-psk-passphrase", TYPE_STRING, key2, (gconstpointer) key2, strlen (key2));
+}
+
+int main (int argc, char **argv)
+{
+	GError *error = NULL;
+	DBusGConnection *bus;
+	char *base;
+
+	g_type_init ();
+	bus = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
+
+	if (!nm_utils_init (&error))
+		FAIL ("nm-utils-init", "failed to initialize libnm-util: %s", error->message);
+
+	/* The tests */
+	test_wifi_open ();
+	test_wifi_wep ();
+	test_wifi_wpa_psk_types ();
+
+	base = g_path_get_basename (argv[0]);
+	fprintf (stdout, "%s: SUCCESS\n", base);
+	g_free (base);
+	return 0;
+}
+