about summary refs log tree commit diff
path: root/src/settings/plugins/ifnet
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2011-05-04 21:35:41 +0200
committerMichael Biebl <biebl@debian.org>2011-05-04 21:35:41 +0200
commit9f806e97a24bba61417ae312fcc0da40914266fb (patch)
tree4a25723414ceac11b4cba0558aa16f6f4b459f4b /src/settings/plugins/ifnet
parent8baa1aca8dfd35e3190d7d5655eb83b5b901e263 (diff)
Imported Upstream version 0.8.999 upstream/0.8.999
Diffstat (limited to 'src/settings/plugins/ifnet')
-rw-r--r--src/settings/plugins/ifnet/Makefile.am57
-rw-r--r--src/settings/plugins/ifnet/Makefile.in929
-rw-r--r--src/settings/plugins/ifnet/connection_parser.c3069
-rw-r--r--src/settings/plugins/ifnet/connection_parser.h46
-rw-r--r--src/settings/plugins/ifnet/net_parser.c639
-rw-r--r--src/settings/plugins/ifnet/net_parser.h46
-rw-r--r--src/settings/plugins/ifnet/net_utils.c974
-rw-r--r--src/settings/plugins/ifnet/net_utils.h80
-rw-r--r--src/settings/plugins/ifnet/nm-ifnet-connection.c191
-rw-r--r--src/settings/plugins/ifnet/nm-ifnet-connection.h51
-rw-r--r--src/settings/plugins/ifnet/plugin.c541
-rw-r--r--src/settings/plugins/ifnet/plugin.h47
-rw-r--r--src/settings/plugins/ifnet/tests/Makefile.am18
-rw-r--r--src/settings/plugins/ifnet/tests/Makefile.in723
-rw-r--r--src/settings/plugins/ifnet/tests/hostname2
-rw-r--r--src/settings/plugins/ifnet/tests/net147
-rw-r--r--src/settings/plugins/ifnet/tests/net.all864
-rw-r--r--src/settings/plugins/ifnet/tests/nm-system-settings.conf5
-rw-r--r--src/settings/plugins/ifnet/tests/test_all.c399
-rw-r--r--src/settings/plugins/ifnet/tests/wpa_supplicant.conf864
-rw-r--r--src/settings/plugins/ifnet/wpa_parser.c566
-rw-r--r--src/settings/plugins/ifnet/wpa_parser.h40
22 files changed, 10298 insertions, 0 deletions
diff --git a/src/settings/plugins/ifnet/Makefile.am b/src/settings/plugins/ifnet/Makefile.am
new file mode 100644
index 00000000..9bf8a79a
--- /dev/null
+++ b/src/settings/plugins/ifnet/Makefile.am
@@ -0,0 +1,57 @@
+SUBDIRS = . tests
+INCLUDES = \
+	-I$(top_srcdir)/src/settings \
+	-I$(top_srcdir)/include \
+	-I$(top_srcdir)/libnm-glib \
+	-I$(top_srcdir)/libnm-util
+
+pkglib_LTLIBRARIES = libnm-settings-plugin-ifnet.la
+
+noinst_LTLIBRARIES = lib-ifnet-io.la
+
+libnm_settings_plugin_ifnet_la_SOURCES = \
+	nm-ifnet-connection.c \
+	nm-ifnet-connection.h \
+	plugin.c \
+	plugin.h 
+
+libnm_settings_plugin_ifnet_la_CPPFLAGS = \
+	$(GLIB_CFLAGS) \
+	$(GMODULE_CFLAGS) \
+	$(DBUS_CFLAGS) \
+	$(GUDEV_CFLAGS) \
+	-DG_DISABLE_DEPRECATED \
+	-DSYSCONFDIR=\"$(sysconfdir)\"
+
+libnm_settings_plugin_ifnet_la_LDFLAGS = -module -avoid-version
+
+libnm_settings_plugin_ifnet_la_LIBADD = \
+	$(top_builddir)/libnm-util/libnm-util.la \
+	$(top_builddir)/libnm-glib/libnm-glib.la \
+	lib-ifnet-io.la\
+	$(GLIB_LIBS) \
+	$(GMODULE_LIBS) \
+	$(GUDEV_LIBS) \
+	$(GIO_LIBS)
+
+lib_ifnet_io_la_SOURCES = \
+	net_parser.c\
+	net_parser.h\
+	connection_parser.c \
+	connection_parser.h \
+	net_utils.h\
+	net_utils.c\
+	wpa_parser.h\
+	wpa_parser.c
+
+lib_ifnet_io_la_CPPFLAGS = \
+			   $(GLIB_CFLAGS) \
+		           $(DBUS_CFLAGS) \
+		           -DG_DISABLE_DEPRECATED \
+		           -DSYSCONFDIR=\"$(sysconfdir)\" \
+		           -DSBINDIR=\"$(sbindir)\"
+
+lib_ifnet_io_la_LIBADD = \
+			 $(top_builddir)/libnm-util/libnm-util.la \
+			 $(GLIB_LIBS)\
+			 $(GIO_LIBS)
diff --git a/src/settings/plugins/ifnet/Makefile.in b/src/settings/plugins/ifnet/Makefile.in
new file mode 100644
index 00000000..2bc7bc32
--- /dev/null
+++ b/src/settings/plugins/ifnet/Makefile.in
@@ -0,0 +1,929 @@
+# 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/settings/plugins/ifnet
+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/gettext.m4 $(top_srcdir)/m4/gtk-doc.m4 \
+	$(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \
+	$(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/introspection.m4 \
+	$(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
+	$(top_srcdir)/m4/lib-prefix.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)/m4/nls.m4 \
+	$(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.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 =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(pkglibdir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+lib_ifnet_io_la_DEPENDENCIES =  \
+	$(top_builddir)/libnm-util/libnm-util.la $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1)
+am_lib_ifnet_io_la_OBJECTS = lib_ifnet_io_la-net_parser.lo \
+	lib_ifnet_io_la-connection_parser.lo \
+	lib_ifnet_io_la-net_utils.lo lib_ifnet_io_la-wpa_parser.lo
+lib_ifnet_io_la_OBJECTS = $(am_lib_ifnet_io_la_OBJECTS)
+AM_V_lt = $(am__v_lt_$(V))
+am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
+am__v_lt_0 = --silent
+libnm_settings_plugin_ifnet_la_DEPENDENCIES =  \
+	$(top_builddir)/libnm-util/libnm-util.la \
+	$(top_builddir)/libnm-glib/libnm-glib.la lib-ifnet-io.la \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am_libnm_settings_plugin_ifnet_la_OBJECTS =  \
+	libnm_settings_plugin_ifnet_la-nm-ifnet-connection.lo \
+	libnm_settings_plugin_ifnet_la-plugin.lo
+libnm_settings_plugin_ifnet_la_OBJECTS =  \
+	$(am_libnm_settings_plugin_ifnet_la_OBJECTS)
+libnm_settings_plugin_ifnet_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(AM_CFLAGS) $(CFLAGS) \
+	$(libnm_settings_plugin_ifnet_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_$(V))
+am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
+am__v_CC_0 = @echo "  CC    " $@;
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_$(V))
+am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
+am__v_CCLD_0 = @echo "  CCLD  " $@;
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo "  GEN   " $@;
+SOURCES = $(lib_ifnet_io_la_SOURCES) \
+	$(libnm_settings_plugin_ifnet_la_SOURCES)
+DIST_SOURCES = $(lib_ifnet_io_la_SOURCES) \
+	$(libnm_settings_plugin_ifnet_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@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+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@
+DHCLIENT_VERSION = @DHCLIENT_VERSION@
+DHCPCD_PATH = @DHCPCD_PATH@
+DISABLE_DEPRECATED = @DISABLE_DEPRECATED@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+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@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+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@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@
+INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
+INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@
+INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@
+INTROSPECTION_LIBS = @INTROSPECTION_LIBS@
+INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
+INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
+INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
+IPTABLES_PATH = @IPTABLES_PATH@
+IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@
+IWMX_SDK_LIBS = @IWMX_SDK_LIBS@
+KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBDL = @LIBDL@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBM = @LIBM@
+LIBNL_CFLAGS = @LIBNL_CFLAGS@
+LIBNL_LIBS = @LIBNL_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
+NM_MICRO_VERSION = @NM_MICRO_VERSION@
+NM_MINOR_VERSION = @NM_MINOR_VERSION@
+NM_VERSION = @NM_VERSION@
+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@
+PKGCONFIG_PATH = @PKGCONFIG_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@
+QT_CFLAGS = @QT_CFLAGS@
+QT_LIBS = @QT_LIBS@
+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@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+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@
+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@
+systemdsystemunitdir = @systemdsystemunitdir@
+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/settings \
+	-I$(top_srcdir)/include \
+	-I$(top_srcdir)/libnm-glib \
+	-I$(top_srcdir)/libnm-util
+
+pkglib_LTLIBRARIES = libnm-settings-plugin-ifnet.la
+noinst_LTLIBRARIES = lib-ifnet-io.la
+libnm_settings_plugin_ifnet_la_SOURCES = \
+	nm-ifnet-connection.c \
+	nm-ifnet-connection.h \
+	plugin.c \
+	plugin.h 
+
+libnm_settings_plugin_ifnet_la_CPPFLAGS = \
+	$(GLIB_CFLAGS) \
+	$(GMODULE_CFLAGS) \
+	$(DBUS_CFLAGS) \
+	$(GUDEV_CFLAGS) \
+	-DG_DISABLE_DEPRECATED \
+	-DSYSCONFDIR=\"$(sysconfdir)\"
+
+libnm_settings_plugin_ifnet_la_LDFLAGS = -module -avoid-version
+libnm_settings_plugin_ifnet_la_LIBADD = \
+	$(top_builddir)/libnm-util/libnm-util.la \
+	$(top_builddir)/libnm-glib/libnm-glib.la \
+	lib-ifnet-io.la\
+	$(GLIB_LIBS) \
+	$(GMODULE_LIBS) \
+	$(GUDEV_LIBS) \
+	$(GIO_LIBS)
+
+lib_ifnet_io_la_SOURCES = \
+	net_parser.c\
+	net_parser.h\
+	connection_parser.c \
+	connection_parser.h \
+	net_utils.h\
+	net_utils.c\
+	wpa_parser.h\
+	wpa_parser.c
+
+lib_ifnet_io_la_CPPFLAGS = \
+			   $(GLIB_CFLAGS) \
+		           $(DBUS_CFLAGS) \
+		           -DG_DISABLE_DEPRECATED \
+		           -DSYSCONFDIR=\"$(sysconfdir)\" \
+		           -DSBINDIR=\"$(sbindir)\"
+
+lib_ifnet_io_la_LIBADD = \
+			 $(top_builddir)/libnm-util/libnm-util.la \
+			 $(GLIB_LIBS)\
+			 $(GIO_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/settings/plugins/ifnet/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu src/settings/plugins/ifnet/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
+install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES)
+	@$(NORMAL_INSTALL)
+	test -z "$(pkglibdir)" || $(MKDIR_P) "$(DESTDIR)$(pkglibdir)"
+	@list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \
+	list2=; for p in $$list; do \
+	  if test -f $$p; then \
+	    list2="$$list2 $$p"; \
+	  else :; fi; \
+	done; \
+	test -z "$$list2" || { \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \
+	}
+
+uninstall-pkglibLTLIBRARIES:
+	@$(NORMAL_UNINSTALL)
+	@list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \
+	for p in $$list; do \
+	  $(am__strip_dir) \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \
+	done
+
+clean-pkglibLTLIBRARIES:
+	-test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES)
+	@list='$(pkglib_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
+lib-ifnet-io.la: $(lib_ifnet_io_la_OBJECTS) $(lib_ifnet_io_la_DEPENDENCIES) 
+	$(AM_V_CCLD)$(LINK)  $(lib_ifnet_io_la_OBJECTS) $(lib_ifnet_io_la_LIBADD) $(LIBS)
+libnm-settings-plugin-ifnet.la: $(libnm_settings_plugin_ifnet_la_OBJECTS) $(libnm_settings_plugin_ifnet_la_DEPENDENCIES) 
+	$(AM_V_CCLD)$(libnm_settings_plugin_ifnet_la_LINK) -rpath $(pkglibdir) $(libnm_settings_plugin_ifnet_la_OBJECTS) $(libnm_settings_plugin_ifnet_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib_ifnet_io_la-connection_parser.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib_ifnet_io_la-net_parser.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib_ifnet_io_la-net_utils.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib_ifnet_io_la-wpa_parser.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_settings_plugin_ifnet_la-nm-ifnet-connection.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_settings_plugin_ifnet_la-plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@	$(AM_V_CC)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
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@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@	$(AM_V_CC)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
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@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@	$(AM_V_CC)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
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@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 $@ $<
+
+lib_ifnet_io_la-net_parser.lo: net_parser.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_ifnet_io_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib_ifnet_io_la-net_parser.lo -MD -MP -MF $(DEPDIR)/lib_ifnet_io_la-net_parser.Tpo -c -o lib_ifnet_io_la-net_parser.lo `test -f 'net_parser.c' || echo '$(srcdir)/'`net_parser.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib_ifnet_io_la-net_parser.Tpo $(DEPDIR)/lib_ifnet_io_la-net_parser.Plo
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='net_parser.c' object='lib_ifnet_io_la-net_parser.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_ifnet_io_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib_ifnet_io_la-net_parser.lo `test -f 'net_parser.c' || echo '$(srcdir)/'`net_parser.c
+
+lib_ifnet_io_la-connection_parser.lo: connection_parser.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_ifnet_io_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib_ifnet_io_la-connection_parser.lo -MD -MP -MF $(DEPDIR)/lib_ifnet_io_la-connection_parser.Tpo -c -o lib_ifnet_io_la-connection_parser.lo `test -f 'connection_parser.c' || echo '$(srcdir)/'`connection_parser.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib_ifnet_io_la-connection_parser.Tpo $(DEPDIR)/lib_ifnet_io_la-connection_parser.Plo
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='connection_parser.c' object='lib_ifnet_io_la-connection_parser.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_ifnet_io_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib_ifnet_io_la-connection_parser.lo `test -f 'connection_parser.c' || echo '$(srcdir)/'`connection_parser.c
+
+lib_ifnet_io_la-net_utils.lo: net_utils.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_ifnet_io_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib_ifnet_io_la-net_utils.lo -MD -MP -MF $(DEPDIR)/lib_ifnet_io_la-net_utils.Tpo -c -o lib_ifnet_io_la-net_utils.lo `test -f 'net_utils.c' || echo '$(srcdir)/'`net_utils.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib_ifnet_io_la-net_utils.Tpo $(DEPDIR)/lib_ifnet_io_la-net_utils.Plo
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='net_utils.c' object='lib_ifnet_io_la-net_utils.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_ifnet_io_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib_ifnet_io_la-net_utils.lo `test -f 'net_utils.c' || echo '$(srcdir)/'`net_utils.c
+
+lib_ifnet_io_la-wpa_parser.lo: wpa_parser.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_ifnet_io_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib_ifnet_io_la-wpa_parser.lo -MD -MP -MF $(DEPDIR)/lib_ifnet_io_la-wpa_parser.Tpo -c -o lib_ifnet_io_la-wpa_parser.lo `test -f 'wpa_parser.c' || echo '$(srcdir)/'`wpa_parser.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/lib_ifnet_io_la-wpa_parser.Tpo $(DEPDIR)/lib_ifnet_io_la-wpa_parser.Plo
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='wpa_parser.c' object='lib_ifnet_io_la-wpa_parser.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_ifnet_io_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib_ifnet_io_la-wpa_parser.lo `test -f 'wpa_parser.c' || echo '$(srcdir)/'`wpa_parser.c
+
+libnm_settings_plugin_ifnet_la-nm-ifnet-connection.lo: nm-ifnet-connection.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_settings_plugin_ifnet_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_settings_plugin_ifnet_la-nm-ifnet-connection.lo -MD -MP -MF $(DEPDIR)/libnm_settings_plugin_ifnet_la-nm-ifnet-connection.Tpo -c -o libnm_settings_plugin_ifnet_la-nm-ifnet-connection.lo `test -f 'nm-ifnet-connection.c' || echo '$(srcdir)/'`nm-ifnet-connection.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_settings_plugin_ifnet_la-nm-ifnet-connection.Tpo $(DEPDIR)/libnm_settings_plugin_ifnet_la-nm-ifnet-connection.Plo
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-ifnet-connection.c' object='libnm_settings_plugin_ifnet_la-nm-ifnet-connection.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_settings_plugin_ifnet_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_settings_plugin_ifnet_la-nm-ifnet-connection.lo `test -f 'nm-ifnet-connection.c' || echo '$(srcdir)/'`nm-ifnet-connection.c
+
+libnm_settings_plugin_ifnet_la-plugin.lo: plugin.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_settings_plugin_ifnet_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_settings_plugin_ifnet_la-plugin.lo -MD -MP -MF $(DEPDIR)/libnm_settings_plugin_ifnet_la-plugin.Tpo -c -o libnm_settings_plugin_ifnet_la-plugin.lo `test -f 'plugin.c' || echo '$(srcdir)/'`plugin.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libnm_settings_plugin_ifnet_la-plugin.Tpo $(DEPDIR)/libnm_settings_plugin_ifnet_la-plugin.Plo
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='plugin.c' object='libnm_settings_plugin_ifnet_la-plugin.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_settings_plugin_ifnet_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_settings_plugin_ifnet_la-plugin.lo `test -f 'plugin.c' || echo '$(srcdir)/'`plugin.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:
+	for dir in "$(DESTDIR)$(pkglibdir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+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 \
+	clean-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES
+
+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: uninstall-pkglibLTLIBRARIES
+
+.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 clean-pkglibLTLIBRARIES 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-pkglibLTLIBRARIES 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 uninstall-pkglibLTLIBRARIES
+
+
+# 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/settings/plugins/ifnet/connection_parser.c b/src/settings/plugins/ifnet/connection_parser.c
new file mode 100644
index 00000000..982f94f9
--- /dev/null
+++ b/src/settings/plugins/ifnet/connection_parser.c
@@ -0,0 +1,3069 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Mu Qiao <qiaomuf@gmail.com>
+ *
+ * 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) 1999-2010 Gentoo Foundation, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <netinet/ether.h>
+#include <errno.h>
+#include <ctype.h>
+#include <glib/gi18n.h>
+
+#include <nm-setting-connection.h>
+#include <nm-setting-ip4-config.h>
+#include <nm-setting-ip6-config.h>
+#include <nm-setting-ppp.h>
+#include <nm-setting-pppoe.h>
+#include <nm-setting-wired.h>
+#include <nm-setting-wireless.h>
+#include <nm-setting-8021x.h>
+#include <nm-system-config-interface.h>
+#include <nm-utils.h>
+
+#include "net_utils.h"
+#include "wpa_parser.h"
+#include "connection_parser.h"
+#include "nm-ifnet-connection.h"
+
+static const char *
+get_prefix (void)
+{
+	return _("System");
+}
+
+static void
+update_connection_id (NMConnection *connection, const char *conn_name)
+{
+	gchar *idstr = NULL;
+	gchar *uuid_base = NULL;
+	gchar *uuid = NULL;
+	int name_len;
+	NMSettingConnection *setting;
+
+	name_len = strlen (conn_name);
+	if ((name_len > 2) && (g_str_has_prefix (conn_name, "0x"))) {
+		gchar * conn_name_printable = utils_hexstr2bin (conn_name + 2, name_len - 2);
+		idstr = g_strdup_printf ("%s (%s)", get_prefix (), conn_name_printable);
+		g_free (conn_name_printable);
+	} else
+		idstr = g_strdup_printf ("%s (%s)", get_prefix (), conn_name);
+	uuid_base = idstr;
+	uuid = nm_utils_uuid_generate_from_string (uuid_base);
+	setting =
+	    (NMSettingConnection *) nm_connection_get_setting (connection,
+							       NM_TYPE_SETTING_CONNECTION);
+	g_object_set (setting, NM_SETTING_CONNECTION_ID, idstr,
+		      NM_SETTING_CONNECTION_UUID, uuid, NULL);
+	PLUGIN_PRINT (IFNET_PLUGIN_NAME,
+		      "update_connection_setting_from_config_block: name:%s, id:%s, uuid: %s",
+		      conn_name, idstr, uuid);
+
+	g_free (uuid);
+	g_free (idstr);
+}
+
+static gboolean eap_simple_reader (const char *eap_method,
+                                   const char *ssid,
+                                   NMSetting8021x *s_8021x,
+                                   gboolean phase2,
+                                   GError **error);
+
+static gboolean eap_tls_reader (const char *eap_method,
+                                const char *ssid,
+                                NMSetting8021x *s_8021x,
+                                gboolean phase2,
+                                GError **error);
+
+static gboolean eap_peap_reader (const char *eap_method,
+                                 const char *ssid,
+                                 NMSetting8021x *s_8021x,
+                                 gboolean phase2,
+                                 GError **error);
+
+static gboolean eap_ttls_reader (const char *eap_method,
+                                 const char *ssid,
+                                 NMSetting8021x *s_8021x,
+                                 gboolean phase2,
+                                 GError **error);
+
+typedef struct {
+	const char *method;
+	 gboolean (*reader) (const char *eap_method,
+	                     const char *ssid,
+	                     NMSetting8021x *s_8021x,
+	                     gboolean phase2,
+	                     GError **error);
+	gboolean wifi_phase2_only;
+} EAPReader;
+
+static EAPReader eap_readers[] = {
+	{"md5", eap_simple_reader, TRUE},
+	{"pap", eap_simple_reader, TRUE},
+	{"chap", eap_simple_reader, TRUE},
+	{"mschap", eap_simple_reader, TRUE},
+	{"mschapv2", eap_simple_reader, TRUE},
+	{"leap", eap_simple_reader, TRUE},
+	{"tls", eap_tls_reader, FALSE},
+	{"peap", eap_peap_reader, FALSE},
+	{"ttls", eap_ttls_reader, FALSE},
+	{NULL, NULL}
+};
+
+/* reading identity and password */
+static gboolean
+eap_simple_reader (const char *eap_method,
+                   const char *ssid,
+                   NMSetting8021x *s_8021x,
+                   gboolean phase2,
+                   GError **error)
+{
+	const char *value;
+
+	/* identity */
+	value = wpa_get_value (ssid, "identity");
+	if (!value) {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "Missing IEEE_8021X_IDENTITY for EAP method '%s'.",
+			     eap_method);
+		return FALSE;
+	}
+	g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, value, NULL);
+
+	/* password */
+	value = wpa_get_value (ssid, "password");
+	if (!value) {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "Missing IEEE_8021X_PASSWORD for EAP method '%s'.",
+			     eap_method);
+		return FALSE;
+	}
+
+	g_object_set (s_8021x, NM_SETTING_802_1X_PASSWORD, value, NULL);
+
+	return TRUE;
+}
+
+static gboolean
+eap_tls_reader (const char *eap_method,
+                const char *ssid,
+                NMSetting8021x *s_8021x,
+                gboolean phase2,
+                GError **error)
+{
+	const char *value;
+	const char *ca_cert = NULL;
+	const char *client_cert = NULL;
+	const char *privkey = NULL;
+	const char *privkey_password = NULL;
+	gboolean success = FALSE;
+	NMSetting8021xCKFormat privkey_format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+
+	/* identity */
+	value = wpa_get_value (ssid, "identity");
+	if (!value) {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "Missing IEEE_8021X_IDENTITY for EAP method '%s'.",
+			     eap_method);
+		return FALSE;
+	}
+	g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, value, NULL);
+
+	/* ca cert */
+	ca_cert = wpa_get_value (ssid, phase2 ? "ca_cert2" : "ca_cert");
+	if (ca_cert) {
+		if (phase2) {
+			if (!nm_setting_802_1x_set_phase2_ca_cert (s_8021x,
+								   ca_cert,
+								   NM_SETTING_802_1X_CK_SCHEME_PATH,
+								   NULL, error))
+				goto done;
+		} else {
+			if (!nm_setting_802_1x_set_ca_cert (s_8021x,
+							    ca_cert,
+							    NM_SETTING_802_1X_CK_SCHEME_PATH,
+							    NULL, error))
+				goto done;
+		}
+	} else {
+		PLUGIN_WARN (IFNET_PLUGIN_NAME,
+			     "    warning: missing %s for EAP"
+			     " method '%s'; this is insecure!",
+			     phase2 ? "IEEE_8021X_INNER_CA_CERT" :
+			     "IEEE_8021X_CA_CERT", eap_method);
+	}
+
+	/* Private key password */
+	privkey_password = wpa_get_value (ssid,
+					  phase2 ? "private_key_passwd2" :
+					  "private_key_passwd");
+
+	if (!privkey_password) {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "Missing %s for EAP method '%s'.",
+			     phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD" :
+			     "IEEE_8021X_PRIVATE_KEY_PASSWORD", eap_method);
+		goto done;
+	}
+
+	/* The private key itself */
+	privkey = wpa_get_value (ssid, phase2 ? "private_key2" : "private_key");
+	if (!privkey) {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "Missing %s for EAP method '%s'.",
+			     phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY" :
+			     "IEEE_8021X_PRIVATE_KEY", eap_method);
+		goto done;
+	}
+
+	if (phase2) {
+		if (!nm_setting_802_1x_set_phase2_private_key (s_8021x,
+							       privkey,
+							       privkey_password,
+							       NM_SETTING_802_1X_CK_SCHEME_PATH,
+							       &privkey_format,
+							       error))
+			goto done;
+	} else {
+		if (!nm_setting_802_1x_set_private_key (s_8021x,
+							privkey,
+							privkey_password,
+							NM_SETTING_802_1X_CK_SCHEME_PATH,
+							&privkey_format, error))
+			goto done;
+	}
+
+	/* Only set the client certificate if the private key is not PKCS#12 format,
+	 * as NM (due to supplicant restrictions) requires.  If the key was PKCS#12,
+	 * then nm_setting_802_1x_set_private_key() already set the client certificate
+	 * to the same value as the private key.
+	 */
+	if (privkey_format == NM_SETTING_802_1X_CK_FORMAT_RAW_KEY
+	    || privkey_format == NM_SETTING_802_1X_CK_FORMAT_X509) {
+		client_cert = wpa_get_value (ssid,
+					     phase2 ? "client_cert2" :
+					     "client_cert");
+		if (!client_cert) {
+			g_set_error (error, ifnet_plugin_error_quark (), 0,
+				     "Missing %s for EAP method '%s'.",
+				     phase2 ? "IEEE_8021X_INNER_CLIENT_CERT" :
+				     "IEEE_8021X_CLIENT_CERT", eap_method);
+			goto done;
+		}
+
+		if (phase2) {
+			if (!nm_setting_802_1x_set_phase2_client_cert (s_8021x,
+								       client_cert,
+								       NM_SETTING_802_1X_CK_SCHEME_PATH,
+								       NULL,
+								       error))
+				goto done;
+		} else {
+			if (!nm_setting_802_1x_set_client_cert (s_8021x,
+								client_cert,
+								NM_SETTING_802_1X_CK_SCHEME_PATH,
+								NULL, error))
+				goto done;
+		}
+	}
+
+	success = TRUE;
+
+done:
+	return success;
+}
+
+static gboolean
+eap_peap_reader (const char *eap_method,
+                 const char *ssid,
+                 NMSetting8021x *s_8021x,
+                 gboolean phase2,
+                 GError **error)
+{
+	const char *ca_cert = NULL;
+	const char *inner_auth = NULL;
+	const char *peapver = NULL;
+	char **list = NULL, **iter, *lower;
+	gboolean success = FALSE;
+
+	ca_cert = wpa_get_value (ssid, "ca_cert");
+	if (ca_cert) {
+		if (!nm_setting_802_1x_set_ca_cert (s_8021x,
+						    ca_cert,
+						    NM_SETTING_802_1X_CK_SCHEME_PATH,
+						    NULL, error))
+			goto done;
+	} else {
+		PLUGIN_WARN (IFNET_PLUGIN_NAME, "    warning: missing "
+			     "IEEE_8021X_CA_CERT for EAP method '%s'; this is"
+			     " insecure!", eap_method);
+	}
+
+	peapver = wpa_get_value (ssid, "phase1");
+	/* peap version, default is automatic */
+	if (peapver && strstr (peapver, "peapver")) {
+		if (strstr (peapver, "peapver=0"))
+			g_object_set (s_8021x, NM_SETTING_802_1X_PHASE1_PEAPVER,
+				      "0", NULL);
+		else if (strstr (peapver, "peapver=1"))
+			g_object_set (s_8021x, NM_SETTING_802_1X_PHASE1_PEAPVER,
+				      "1", NULL);
+		else {
+			g_set_error (error, ifnet_plugin_error_quark (), 0,
+				     "Unknown IEEE_8021X_PEAP_VERSION value '%s'",
+				     peapver);
+			goto done;
+		}
+	}
+
+	/* peaplabel */
+	if (peapver && strstr (peapver, "peaplabel=1"))
+		g_object_set (s_8021x, NM_SETTING_802_1X_PHASE1_PEAPLABEL, "1",
+			      NULL);
+
+	inner_auth = wpa_get_value (ssid, "phase2");
+	if (!inner_auth) {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "Missing IEEE_8021X_INNER_AUTH_METHODS.");
+		goto done;
+	}
+	/* Handle options for the inner auth method */
+	list = g_strsplit (inner_auth, " ", 0);
+	for (iter = list; iter && *iter; iter++) {
+		gchar *pos = NULL;
+
+		if (!strlen (*iter))
+			continue;
+
+		if (!(pos = strstr (*iter, "MSCHAPV2"))
+		    || !(pos = strstr (*iter, "MD5"))
+		    || !(pos = strstr (*iter, "GTC"))) {
+			if (!eap_simple_reader
+			    (pos, ssid, s_8021x, TRUE, error))
+				goto done;
+		} else if (!(pos = strstr (*iter, "TLS"))) {
+			if (!eap_tls_reader (pos, ssid, s_8021x, TRUE, error))
+				goto done;
+		} else {
+			g_set_error (error, ifnet_plugin_error_quark (), 0,
+				     "Unknown IEEE_8021X_INNER_AUTH_METHOD '%s'.",
+				     *iter);
+			goto done;
+		}
+
+		pos = strchr (*iter, '=');
+		pos++;
+		lower = g_ascii_strdown (pos, -1);
+		g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, lower,
+			      NULL);
+		g_free (lower);
+		break;
+	}
+
+	if (!nm_setting_802_1x_get_phase2_auth (s_8021x)) {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "No valid IEEE_8021X_INNER_AUTH_METHODS found.");
+		goto done;
+	}
+
+	success = TRUE;
+
+done:
+	if (list)
+		g_strfreev (list);
+	return success;
+}
+
+static gboolean
+eap_ttls_reader (const char *eap_method,
+                 const char *ssid,
+                 NMSetting8021x *s_8021x,
+                 gboolean phase2,
+                 GError **error)
+{
+	gboolean success = FALSE;
+	const char *anon_ident = NULL;
+	const char *ca_cert = NULL;
+	const char *tmp;
+	char **list = NULL, **iter, *inner_auth = NULL;
+
+	/* ca cert */
+	ca_cert = wpa_get_value (ssid, "ca_cert");
+	if (ca_cert) {
+		if (!nm_setting_802_1x_set_ca_cert (s_8021x,
+						    ca_cert,
+						    NM_SETTING_802_1X_CK_SCHEME_PATH,
+						    NULL, error))
+			goto done;
+	} else {
+		PLUGIN_WARN (IFNET_PLUGIN_NAME, "    warning: missing "
+			     "IEEE_8021X_CA_CERT for EAP method '%s'; this is"
+			     " insecure!", eap_method);
+	}
+
+	/* anonymous indentity for tls */
+	anon_ident = wpa_get_value (ssid, "anonymous_identity");
+	if (anon_ident && strlen (anon_ident))
+		g_object_set (s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY,
+			      anon_ident, NULL);
+
+	tmp = wpa_get_value (ssid, "phase2");
+	if (!tmp) {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "Missing IEEE_8021X_INNER_AUTH_METHODS.");
+		goto done;
+	}
+
+	/* Handle options for the inner auth method */
+	inner_auth = g_ascii_strdown (tmp, -1);
+	list = g_strsplit (inner_auth, " ", 0);
+	for (iter = list; iter && *iter; iter++) {
+		gchar *pos = NULL;
+
+		if (!strlen (*iter))
+			continue;
+		if ((pos = strstr (*iter, "mschapv2")) != NULL
+		    || (pos = strstr (*iter, "mschap")) != NULL
+		    || (pos = strstr (*iter, "pap")) != NULL
+		    || (pos = strstr (*iter, "chap")) != NULL) {
+			if (!eap_simple_reader
+			    (pos, ssid, s_8021x, TRUE, error))
+				goto done;
+			g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH,
+				      pos, NULL);
+		} else if ((pos = strstr (*iter, "tls")) != NULL) {
+			if (!eap_tls_reader (pos, ssid, s_8021x, TRUE, error))
+				goto done;
+			g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTHEAP,
+				      "tls", NULL);
+		} else if ((pos = strstr (*iter, "mschapv2")) != NULL
+			   || (pos = strstr (*iter, "md5")) != NULL) {
+			if (!eap_simple_reader
+			    (pos, ssid, s_8021x, TRUE, error)) {
+				PLUGIN_WARN (IFNET_PLUGIN_NAME, "SIMPLE ERROR");
+				goto done;
+			}
+			g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTHEAP,
+				      pos, NULL);
+		} else {
+			g_set_error (error, ifnet_plugin_error_quark (), 0,
+				     "Unknown IEEE_8021X_INNER_AUTH_METHOD '%s'.",
+				     *iter);
+			goto done;
+		}
+		break;
+	}
+
+	success = TRUE;
+done:
+	if (list)
+		g_strfreev (list);
+	g_free (inner_auth);
+	return success;
+}
+
+/* type is already decided by net_parser, this function is just used to
+ * doing tansformation*/
+static const gchar *
+guess_connection_type (const char *conn_name)
+{
+	const gchar *type = ifnet_get_data (conn_name, "type");
+	const gchar *ret_type = NULL;
+
+	if (!g_strcmp0 (type, "ppp"))
+		ret_type = NM_SETTING_PPPOE_SETTING_NAME;
+
+	if (!g_strcmp0 (type, "wireless"))
+		ret_type = NM_SETTING_WIRELESS_SETTING_NAME;
+
+	if (!ret_type)
+		ret_type = NM_SETTING_WIRED_SETTING_NAME;
+
+	PLUGIN_PRINT (IFNET_PLUGIN_NAME,
+		      "guessed connection type (%s) = %s", conn_name, ret_type);
+	return ret_type;
+}
+
+/* Reading mac address for setting connection option.
+ * Unmanaged device mac address is required by NetworkManager*/
+static gboolean
+read_mac_address (const char *conn_name, GByteArray **array, GError **error)
+{
+	const char *value = ifnet_get_data (conn_name, "mac");
+	struct ether_addr *mac;
+
+	if (!value || !strlen (value))
+		return TRUE;
+
+	mac = ether_aton (value);
+	if (!mac) {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "The MAC address '%s' was invalid.", value);
+		return FALSE;
+	}
+
+	*array = g_byte_array_sized_new (ETH_ALEN);
+	g_byte_array_append (*array, (guint8 *) mac->ether_addr_octet, ETH_ALEN);
+	return TRUE;
+}
+
+static void
+make_wired_connection_setting (NMConnection *connection,
+                               const char *conn_name,
+                               GError **error)
+{
+	GByteArray *mac = NULL;
+	NMSettingWired *s_wired = NULL;
+	const char *value = NULL;
+
+	s_wired = NM_SETTING_WIRED (nm_setting_wired_new ());
+
+	/* mtu_xxx */
+	value = ifnet_get_data (conn_name, "mtu");
+	if (value) {
+		long int mtu;
+
+		errno = 0;
+		mtu = strtol (value, NULL, 10);
+		if (errno || mtu < 0 || mtu > 65535) {
+			PLUGIN_WARN (IFNET_PLUGIN_NAME,
+				     "    warning: invalid MTU '%s' for %s",
+				     value, conn_name);
+		} else
+			g_object_set (s_wired, NM_SETTING_WIRED_MTU,
+				      (guint32) mtu, NULL);
+	}
+
+	if (read_mac_address (conn_name, &mac, error)) {
+		if (mac) {
+			g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS,
+				      mac, NULL);
+			g_byte_array_free (mac, TRUE);
+		}
+	} else {
+		g_object_unref (s_wired);
+		s_wired = NULL;
+	}
+	if (s_wired)
+		nm_connection_add_setting (connection, NM_SETTING (s_wired));
+}
+
+/* add NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME, 
+ * NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID in future*/
+static void
+make_ip4_setting (NMConnection *connection,
+                  const char *conn_name,
+                  GError **error)
+{
+
+	NMSettingIP4Config *ip4_setting =
+	    NM_SETTING_IP4_CONFIG (nm_setting_ip4_config_new ());
+	const char *value, *method;
+	gboolean is_static_block = is_static_ip4 (conn_name);
+	ip_block *iblock = NULL;
+
+	/* set dhcp options (dhcp_xxx) */
+	value = ifnet_get_data (conn_name, "dhcp");
+	g_object_set (ip4_setting, NM_SETTING_IP4_CONFIG_IGNORE_AUTO_DNS, value
+		      && strstr (value, "nodns") ? TRUE : FALSE,
+		      NM_SETTING_IP4_CONFIG_IGNORE_AUTO_ROUTES, value
+		      && strstr (value, "nogateway") ? TRUE : FALSE, NULL);
+
+	if (!is_static_block) {
+		method = ifnet_get_data (conn_name, "config");
+		if (!method){
+			g_set_error (error, ifnet_plugin_error_quark (), 0,
+						 "Unknown config for %s", conn_name);
+			g_object_unref (ip4_setting);
+			return;
+		}
+		if (!strcmp (method, "dhcp"))
+			g_object_set (ip4_setting,
+						  NM_SETTING_IP4_CONFIG_METHOD,
+						  NM_SETTING_IP4_CONFIG_METHOD_AUTO,
+						  NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, FALSE, NULL);
+		else if (!strcmp (method, "autoip")){
+			g_object_set (ip4_setting,
+						  NM_SETTING_IP4_CONFIG_METHOD,
+						  NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL,
+						  NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, FALSE, NULL);
+			nm_connection_add_setting (connection, NM_SETTING (ip4_setting));
+			return;
+		} else if (!strcmp (method, "shared")){
+			g_object_set (ip4_setting,
+						  NM_SETTING_IP4_CONFIG_METHOD,
+						  NM_SETTING_IP4_CONFIG_METHOD_SHARED,
+						  NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, FALSE, NULL);
+			nm_connection_add_setting (connection, NM_SETTING (ip4_setting));
+			return;
+		} else {
+			g_set_error (error, ifnet_plugin_error_quark (), 0,
+						 "Unknown config for %s", conn_name);
+			g_object_unref (ip4_setting);
+			return;
+		}
+		PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Using %s method for %s",
+					  method, conn_name);
+	}else {
+		iblock = convert_ip4_config_block (conn_name);
+		if (!iblock) {
+			g_set_error (error, ifnet_plugin_error_quark (), 0,
+				     "Ifnet plugin: can't aquire ip configuration for %s",
+				     conn_name);
+			g_object_unref (ip4_setting);
+			return;
+		}
+		/************** add all ip settings to the connection**********/
+		while (iblock) {
+			ip_block *current_iblock;
+			NMIP4Address *ip4_addr = nm_ip4_address_new ();
+
+			nm_ip4_address_set_address (ip4_addr, iblock->ip);
+			nm_ip4_address_set_prefix (ip4_addr,
+						   nm_utils_ip4_netmask_to_prefix
+						   (iblock->netmask));
+			/* currently all the IPs has the same gateway */
+			nm_ip4_address_set_gateway (ip4_addr, iblock->gateway);
+			if (iblock->gateway)
+				g_object_set (ip4_setting,
+					      NM_SETTING_IP4_CONFIG_IGNORE_AUTO_ROUTES,
+					      TRUE, NULL);
+			if (!nm_setting_ip4_config_add_address (ip4_setting, ip4_addr))
+				PLUGIN_WARN (IFNET_PLUGIN_NAME,
+					     "ignoring duplicate IP4 address");
+			nm_ip4_address_unref (ip4_addr);
+			current_iblock = iblock;
+			iblock = iblock->next;
+			destroy_ip_block (current_iblock);
+
+		}
+		g_object_set (ip4_setting,
+		              NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
+		              NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, !has_default_ip4_route (conn_name),
+		              NULL);
+	}
+
+	/* add dhcp hostname and client id */
+	if (!is_static_block && !strcmp (method, "dhcp")) {
+		gchar *dhcp_hostname, *client_id;
+
+		get_dhcp_hostname_and_client_id (&dhcp_hostname, &client_id);
+		if (dhcp_hostname) {
+			g_object_set (ip4_setting,
+				      NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME,
+				      dhcp_hostname, NULL);
+			PLUGIN_PRINT (IFNET_PLUGIN_NAME, "DHCP hostname: %s",
+				      dhcp_hostname);
+			g_free (dhcp_hostname);
+		}
+		if (client_id) {
+			g_object_set (ip4_setting,
+				      NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID,
+				      client_id, NULL);
+			PLUGIN_PRINT (IFNET_PLUGIN_NAME, "DHCP client id: %s",
+				      client_id);
+			g_free (client_id);
+		}
+	}
+
+	/* add all IPv4 dns servers, IPv6 servers will be ignored */
+	set_ip4_dns_servers (ip4_setting, conn_name);
+
+	/* DNS searches */
+	value = ifnet_get_data (conn_name, "dns_search");
+	if (value) {
+		char *stripped = g_strdup (value);
+		char **searches = NULL;
+
+		strip_string (stripped, '"');
+
+		searches = g_strsplit (stripped, " ", 0);
+		if (searches) {
+			char **item;
+
+			for (item = searches; *item; item++) {
+				if (strlen (*item)) {
+					if (!nm_setting_ip4_config_add_dns_search (ip4_setting, *item))
+						PLUGIN_WARN
+						    (IFNET_PLUGIN_NAME,
+						     "    warning: duplicate DNS domain '%s'",
+						     *item);
+				}
+			}
+			g_strfreev (searches);
+		}
+	}
+
+	/* static routes */
+	iblock = convert_ip4_routes_block (conn_name);
+	while (iblock) {
+		ip_block *current_iblock = iblock;
+		const char *metric_str;
+		char *stripped;
+		long int metric;
+		NMIP4Route *route = nm_ip4_route_new ();
+
+		nm_ip4_route_set_dest (route, iblock->ip);
+		nm_ip4_route_set_next_hop (route, iblock->gateway);
+		nm_ip4_route_set_prefix (route,
+					 nm_utils_ip4_netmask_to_prefix
+					 (iblock->netmask));
+		if ((metric_str = ifnet_get_data (conn_name, "metric")) != NULL) {
+			metric = strtol (metric_str, NULL, 10);
+			nm_ip4_route_set_metric (route, (guint32) metric);
+		} else {
+			metric_str = ifnet_get_global_data ("metric");
+			if (metric_str) {
+				stripped = g_strdup (metric_str);
+				strip_string (stripped, '"');
+				metric = strtol (metric_str, NULL, 10);
+				nm_ip4_route_set_metric (route,
+							 (guint32) metric);
+				g_free (stripped);
+			}
+		}
+
+		if (!nm_setting_ip4_config_add_route (ip4_setting, route))
+			PLUGIN_WARN (IFNET_PLUGIN_NAME,
+				     "warning: duplicate IP4 route");
+		PLUGIN_PRINT (IFNET_PLUGIN_NAME,
+			      "new IP4 route:%d\n", iblock->ip);
+
+		nm_ip4_route_unref (route);
+
+		current_iblock = iblock;
+		iblock = iblock->next;
+		destroy_ip_block (current_iblock);
+	}
+
+	/* Finally add setting to connection */
+	nm_connection_add_setting (connection, NM_SETTING (ip4_setting));
+}
+
+static void
+make_ip6_setting (NMConnection *connection,
+                  const char *conn_name,
+                  GError **error)
+{
+	NMSettingIP6Config *s_ip6 = NULL;
+	gboolean is_static_block = is_static_ip6 (conn_name);
+
+	// used to disable IPv6
+	gboolean ipv6_enabled = FALSE;
+	gchar *method = NM_SETTING_IP6_CONFIG_METHOD_MANUAL;
+	const char *value;
+	ip6_block *iblock;
+	gboolean never_default = !has_default_ip6_route (conn_name);
+
+	s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
+	if (!s_ip6) {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "Could not allocate IP6 setting");
+		return;
+	}
+
+	value = ifnet_get_data (conn_name, "enable_ipv6");
+	if (value && is_true (value))
+		ipv6_enabled = TRUE;
+
+	//FIXME Handle other methods that NM supports in future
+	// Currently only Manual and DHCP are supported
+	if (!ipv6_enabled) {
+		g_object_set (s_ip6,
+			      NM_SETTING_IP6_CONFIG_METHOD,
+			      NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL);
+		goto done;
+	} else if (!is_static_block) {
+		// config_eth* contains "dhcp6"
+		method = NM_SETTING_IP6_CONFIG_METHOD_AUTO;
+		never_default = FALSE;
+	}
+	// else if (!has_ip6_address(conn_name))
+	// doesn't have "dhcp6" && doesn't have any ipv6 address
+	// method = NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL;
+	else
+		// doesn't have "dhcp6" && has at least one ipv6 address
+		method = NM_SETTING_IP6_CONFIG_METHOD_MANUAL;
+	PLUGIN_PRINT (IFNET_PLUGIN_NAME, "IPv6 for %s enabled, using %s",
+		      conn_name, method);
+
+	g_object_set (s_ip6,
+		      NM_SETTING_IP6_CONFIG_METHOD, method,
+		      NM_SETTING_IP6_CONFIG_IGNORE_AUTO_DNS, FALSE,
+		      NM_SETTING_IP6_CONFIG_IGNORE_AUTO_ROUTES, FALSE,
+		      NM_SETTING_IP6_CONFIG_NEVER_DEFAULT, never_default, NULL);
+
+	/* Make manual settings */
+	if (!strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) {
+		ip6_block *current_iblock;
+
+		iblock = convert_ip6_config_block (conn_name);
+		if (!iblock) {
+			g_set_error (error, ifnet_plugin_error_quark (), 0,
+				     "Ifnet plugin: can't aquire ip6 configuration for %s",
+				     conn_name);
+			goto error;
+		}
+		/* add all IPv6 addresses */
+		while (iblock) {
+			NMIP6Address *ip6_addr = nm_ip6_address_new ();
+
+			nm_ip6_address_set_address (ip6_addr, iblock->ip);
+			nm_ip6_address_set_prefix (ip6_addr, iblock->prefix);
+			if (nm_setting_ip6_config_add_address (s_ip6, ip6_addr)) {
+				PLUGIN_PRINT (IFNET_PLUGIN_NAME,
+					      "ipv6 addresses count: %d",
+					      nm_setting_ip6_config_get_num_addresses
+					      (s_ip6));
+			} else {
+				PLUGIN_WARN (IFNET_PLUGIN_NAME,
+					     "ignoring duplicate IP4 address");
+			}
+			nm_ip6_address_unref (ip6_addr);
+			current_iblock = iblock;
+			iblock = iblock->next;
+			destroy_ip6_block (current_iblock);
+		}
+
+	} else if (!strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO)) {
+		/* - autoconf or DHCPv6 stuff goes here */
+	}
+	// DNS Servers, set NM_SETTING_IP6_CONFIG_IGNORE_AUTO_DNS TRUE here
+	set_ip6_dns_servers (s_ip6, conn_name);
+
+	/* DNS searches ('DOMAIN' key) are read by make_ip4_setting() and included in NMSettingIP4Config */
+
+	// Add routes
+	iblock = convert_ip6_routes_block (conn_name);
+	if (iblock)
+		g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_IGNORE_AUTO_ROUTES,
+			      TRUE, NULL);
+	/* Add all IPv6 routes */
+	while (iblock) {
+		ip6_block *current_iblock = iblock;
+		const char *metric_str;
+		char *stripped;
+		long int metric = 1;
+		NMIP6Route *route = nm_ip6_route_new ();
+
+		nm_ip6_route_set_dest (route, iblock->ip);
+		nm_ip6_route_set_next_hop (route, iblock->next_hop);
+		nm_ip6_route_set_prefix (route, iblock->prefix);
+		/* metric is not per routes configuration right now 
+		 * global metric is also supported (metric="x") */
+		if ((metric_str = ifnet_get_data (conn_name, "metric")) != NULL) {
+			metric = strtol (metric_str, NULL, 10);
+			nm_ip6_route_set_metric (route, (guint32) metric);
+		} else {
+			metric_str = ifnet_get_global_data ("metric");
+			if (metric_str) {
+				stripped = g_strdup (metric_str);
+				strip_string (stripped, '"');
+				metric = strtol (metric_str, NULL, 10);
+				nm_ip6_route_set_metric (route,
+							 (guint32) metric);
+				g_free (stripped);
+			} else
+				nm_ip6_route_set_metric (route, (guint32) 1);
+		}
+
+		if (!nm_setting_ip6_config_add_route (s_ip6, route))
+			PLUGIN_WARN (IFNET_PLUGIN_NAME,
+				     "    warning: duplicate IP6 route");
+		PLUGIN_PRINT (IFNET_PLUGIN_NAME, "    info: new IP6 route");
+		nm_ip6_route_unref (route);
+
+		current_iblock = iblock;
+		iblock = iblock->next;
+		destroy_ip6_block (current_iblock);
+	}
+
+done:
+	nm_connection_add_setting (connection, NM_SETTING (s_ip6));
+	return;
+
+error:
+	g_object_unref (s_ip6);
+	PLUGIN_WARN (IFNET_PLUGIN_NAME, "    warning: Ignore IPv6 for %s",
+		     conn_name);
+	return;
+}
+
+static NMSetting *
+make_wireless_connection_setting (const char *conn_name,
+                                  NMSetting8021x **s_8021x,
+                                  GError **error)
+{
+	GByteArray *array, *mac = NULL;
+	NMSettingWireless *wireless_setting = NULL;
+	gboolean adhoc = FALSE;
+	const char *value;
+	const char *type;
+
+	/* PPP over WIFI is not supported yet */
+	g_return_val_if_fail (conn_name != NULL
+			      && strcmp (ifnet_get_data (conn_name, "type"),
+					 "ppp") != 0, NULL);
+	type = ifnet_get_data (conn_name, "type");
+	if (strcmp (type, "ppp") == 0) {
+		PLUGIN_WARN (IFNET_PLUGIN_NAME,
+			     "PPP over WIFI is not supported yet");
+		return NULL;
+	}
+
+	wireless_setting = NM_SETTING_WIRELESS (nm_setting_wireless_new ());
+	if (read_mac_address (conn_name, &mac, error)) {
+		if (mac) {
+			g_object_set (wireless_setting,
+				      NM_SETTING_WIRELESS_MAC_ADDRESS, mac,
+				      NULL);
+			g_byte_array_free (mac, TRUE);
+
+		}
+	} else {
+		g_object_unref (wireless_setting);
+		return NULL;
+	}
+
+	/* handle ssid (hex and ascii) */
+	if (conn_name) {
+		gsize ssid_len = 0, value_len = strlen (conn_name);
+		const char *p;
+		char *tmp, *converted = NULL;
+
+		ssid_len = value_len;
+		if ((value_len > 2) && (g_str_has_prefix (conn_name, "0x"))) {
+			/* Hex representation */
+			if (value_len % 2) {
+				g_set_error (error, ifnet_plugin_error_quark (),
+					     0,
+					     "Invalid SSID '%s' size (looks like hex but length not multiple of 2)",
+					     conn_name);
+				goto error;
+			}
+			// ignore "0x"
+			p = conn_name + 2;
+			if (!is_hex (p)) {
+				g_set_error (error,
+					     ifnet_plugin_error_quark (),
+					     0,
+					     "Invalid SSID '%s' character (looks like hex SSID but '%c' isn't a hex digit)",
+					     conn_name, *p);
+				goto error;
+
+			}
+			tmp = utils_hexstr2bin (p, value_len - 2);
+			ssid_len = (value_len - 2) / 2;
+			converted = g_malloc0 (ssid_len + 1);
+			memcpy (converted, tmp, ssid_len);
+			g_free (tmp);
+		}
+
+		if (ssid_len > 32 || ssid_len == 0) {
+			g_set_error (error, ifnet_plugin_error_quark (), 0,
+				     "Invalid SSID '%s' (size %zu not between 1 and 32 inclusive)",
+				     conn_name, ssid_len);
+			goto error;
+		}
+		array = g_byte_array_sized_new (ssid_len);
+		g_byte_array_append (array, (const guint8 *) (converted ? converted : conn_name), ssid_len);
+		g_object_set (wireless_setting, NM_SETTING_WIRELESS_SSID, array, NULL);
+		g_byte_array_free (array, TRUE);
+		g_free (converted);
+	} else {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "Missing SSID");
+		goto error;
+	}
+
+	/* mode=0: infrastructure 
+	 * mode=1: adhoc */
+	value = wpa_get_value (conn_name, "mode");
+	if (value)
+		adhoc = strcmp (value, "1") == 0 ? TRUE : FALSE;
+
+	if (exist_ssid (conn_name)) {
+		const char *mode = adhoc ? "adhoc" : "infrastructure";
+
+		g_object_set (wireless_setting, NM_SETTING_WIRELESS_MODE, mode,
+			      NULL);
+		PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Using mode: %s", mode);
+	}
+
+	/* BSSID setting */
+	value = wpa_get_value (conn_name, "bssid");
+	if (value) {
+		struct ether_addr *eth;
+		GByteArray *bssid;
+
+		eth = ether_aton (value);
+		if (!eth) {
+			g_set_error (error, ifnet_plugin_error_quark (), 0,
+				     "Invalid BSSID '%s'", value);
+			goto error;
+		}
+
+		bssid = g_byte_array_sized_new (ETH_ALEN);
+		g_byte_array_append (bssid, eth->ether_addr_octet, ETH_ALEN);
+		g_object_set (wireless_setting, NM_SETTING_WIRELESS_BSSID,
+			      bssid, NULL);
+		g_byte_array_free (bssid, TRUE);
+
+	}
+
+	/* mtu_ssid="xx" */
+	value = ifnet_get_data (conn_name, "mtu");
+	if (value) {
+		long int mtu;
+
+		errno = 0;
+		mtu = strtol (value, NULL, 10);
+		if (errno || mtu < 0 || mtu > 50000) {
+			PLUGIN_WARN (IFNET_PLUGIN_NAME,
+				     "    warning: invalid MTU '%s' for %s",
+				     value, conn_name);
+		} else
+			g_object_set (wireless_setting, NM_SETTING_WIRELESS_MTU,
+				      (guint32) mtu, NULL);
+
+	}
+
+	PLUGIN_PRINT (IFNET_PLUGIN_NAME, "wireless_setting added for %s",
+		      conn_name);
+	return NM_SETTING (wireless_setting);
+error:
+	if (wireless_setting)
+		g_object_unref (wireless_setting);
+	return NULL;
+
+}
+
+static NMSettingWirelessSecurity *
+make_leap_setting (const char *ssid, GError **error)
+{
+	NMSettingWirelessSecurity *wsec;
+	const char *value;
+
+	wsec =
+	    NM_SETTING_WIRELESS_SECURITY (nm_setting_wireless_security_new ());
+
+	value = wpa_get_value (ssid, "key_mgmt");
+	if (!value || strcmp (value, "IEEE8021X"))
+		goto error;	/* Not LEAP */
+
+	value = wpa_get_value (ssid, "eap");
+	if (!value || strcasecmp (value, "LEAP"))
+		goto error;	/* Not LEAP */
+
+	value = wpa_get_value (ssid, "password");
+	if (value && strlen (value))
+		g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD,
+			      value, NULL);
+
+	value = wpa_get_value (ssid, "identity");
+	if (!value || !strlen (value)) {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "Missing LEAP identity");
+		goto error;
+	}
+	g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, value,
+		      NULL);
+
+	g_object_set (wsec,
+		      NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x",
+		      NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "leap", NULL);
+
+	return wsec;
+error:
+	if (wsec)
+		g_object_unref (wsec);
+	return NULL;
+}
+
+static gboolean
+add_one_wep_key (const char *ssid,
+                 const char *key,
+                 int key_idx,
+                 NMSettingWirelessSecurity *s_wsec,
+                 GError **error)
+{
+	const char *value;
+	char *converted = NULL;
+	gboolean success = FALSE;
+
+	g_return_val_if_fail (ssid != NULL, FALSE);
+	g_return_val_if_fail (key != NULL, FALSE);
+	g_return_val_if_fail (key_idx >= 0 && key_idx <= 3, FALSE);
+	g_return_val_if_fail (s_wsec != NULL, FALSE);
+
+	value = wpa_get_value (ssid, key);
+	if (!value)
+		return TRUE;
+
+	/* Validate keys */
+	if (strlen (value) == 10 || strlen (value) == 26) {
+		/* Hexadecimal WEP key */
+		if (!is_hex (value)) {
+			g_set_error (error, ifnet_plugin_error_quark (),
+				     0, "Invalid hexadecimal WEP key.");
+			goto out;
+		}
+		converted = g_strdup (value);
+	} else if (value[0] == '"'
+		   && (strlen (value) == 7 || strlen (value) == 15)) {
+		/* ASCII passphrase */
+		char *tmp = g_strdup (value);
+		char *p = strip_string (tmp, '"');
+
+		if (!is_ascii (p)) {
+			g_set_error (error, ifnet_plugin_error_quark (),
+				     0, "Invalid ASCII WEP passphrase.");
+			g_free (tmp);
+			goto out;
+
+		}
+
+		converted = utils_bin2hexstr (tmp, strlen (tmp), strlen (tmp) * 2);
+		g_free (tmp);
+	} else {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "Invalid WEP key length. Key: %s", value);
+		goto out;
+	}
+
+	if (converted) {
+		nm_setting_wireless_security_set_wep_key (s_wsec, key_idx, converted);
+		g_free (converted);
+		success = TRUE;
+	}
+
+out:
+	return success;
+}
+
+static gboolean
+add_wep_keys (const char *ssid,
+              NMSettingWirelessSecurity *s_wsec,
+              GError **error)
+{
+	if (!add_one_wep_key (ssid, "wep_key0", 0, s_wsec, error))
+		return FALSE;
+	if (!add_one_wep_key (ssid, "wep_key1", 1, s_wsec, error))
+		return FALSE;
+	if (!add_one_wep_key (ssid, "wep_key2", 2, s_wsec, error))
+		return FALSE;
+	if (!add_one_wep_key (ssid, "wep_key3", 3, s_wsec, error))
+		return FALSE;
+	return TRUE;
+
+}
+
+static NMSettingWirelessSecurity *
+make_wep_setting (const char *ssid, GError **error)
+{
+	const char *auth_alg, *value;
+	int default_key_idx = 0;
+	NMSettingWirelessSecurity *s_wireless_sec;
+
+	s_wireless_sec =
+	    NM_SETTING_WIRELESS_SECURITY (nm_setting_wireless_security_new ());
+	g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,
+		      "none", NULL);
+
+	/* default key index */
+	value = wpa_get_value (ssid, "wep_tx_keyidx");
+	if (value) {
+		default_key_idx = atoi (value);
+		if (default_key_idx >= 0 && default_key_idx <= 3) {
+			g_object_set (s_wireless_sec,
+				      NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX,
+				      default_key_idx, NULL);
+			PLUGIN_PRINT (IFNET_PLUGIN_NAME,
+				      "Default key index: %d", default_key_idx);
+		} else {
+			g_set_error (error, ifnet_plugin_error_quark (), 0,
+				     "Invalid default WEP key '%s'", value);
+			goto error;
+		}
+	}
+
+	if (!add_wep_keys (ssid, s_wireless_sec, error))
+		goto error;
+
+	/* If there's a default key, ensure that key exists */
+	if ((default_key_idx == 1)
+	    && !nm_setting_wireless_security_get_wep_key (s_wireless_sec, 1)) {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "Default WEP key index was 2, but no valid KEY2 exists.");
+		goto error;
+	} else if ((default_key_idx == 2)
+		   && !nm_setting_wireless_security_get_wep_key (s_wireless_sec,
+								 2)) {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "Default WEP key index was 3, but no valid KEY3 exists.");
+		goto error;
+	} else if ((default_key_idx == 3)
+		   && !nm_setting_wireless_security_get_wep_key (s_wireless_sec,
+								 3)) {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "Default WEP key index was 4, but no valid KEY4 exists.");
+		goto error;
+	}
+
+	/* authentication algorithms */
+	auth_alg = wpa_get_value (ssid, "auth_alg");
+	if (auth_alg) {
+		if (strcmp (auth_alg, "OPEN") == 0) {
+			g_object_set (s_wireless_sec,
+				      NM_SETTING_WIRELESS_SECURITY_AUTH_ALG,
+				      "open", NULL);
+			PLUGIN_PRINT (IFNET_PLUGIN_NAME,
+				      "WEP: Use open system authentication");
+		} else if (strcmp (auth_alg, "SHARED") == 0) {
+			g_object_set (s_wireless_sec,
+				      NM_SETTING_WIRELESS_SECURITY_AUTH_ALG,
+				      "shared", NULL);
+			PLUGIN_PRINT (IFNET_PLUGIN_NAME,
+				      "WEP: Use shared system authentication");
+		} else {
+			g_set_error (error, ifnet_plugin_error_quark (), 0,
+				     "Invalid WEP authentication algorithm '%s'",
+				     auth_alg);
+			goto error;
+		}
+
+	}
+
+	if (!nm_setting_wireless_security_get_wep_key (s_wireless_sec, 0)
+	    && !nm_setting_wireless_security_get_wep_key (s_wireless_sec, 1)
+	    && !nm_setting_wireless_security_get_wep_key (s_wireless_sec, 2)
+	    && !nm_setting_wireless_security_get_wep_key (s_wireless_sec, 3)
+	    && !nm_setting_wireless_security_get_wep_tx_keyidx (s_wireless_sec)) {
+		if (auth_alg && !strcmp (auth_alg, "shared")) {
+			g_set_error (error, ifnet_plugin_error_quark (), 0,
+				     "WEP Shared Key authentication is invalid for "
+				     "unencrypted connections.");
+			goto error;
+		}
+		/* Unencrypted */
+		g_object_unref (s_wireless_sec);
+		s_wireless_sec = NULL;
+	}
+	return s_wireless_sec;
+
+error:
+	if (s_wireless_sec)
+		g_object_unref (s_wireless_sec);
+	return NULL;
+}
+
+static char *
+parse_wpa_psk (const char *psk, GError **error)
+{
+	char *hashed = NULL;
+	gboolean quoted = FALSE;
+
+	if (!psk) {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "Missing WPA_PSK for WPA-PSK key management");
+		return NULL;
+	}
+
+	/* Passphrase must be between 10 and 66 characters in length becuase WPA
+	 * hex keys are exactly 64 characters (no quoting), and WPA passphrases
+	 * are between 8 and 63 characters (inclusive), plus optional quoting if
+	 * the passphrase contains spaces.
+	 */
+
+	if (psk[0] == '"' && psk[strlen (psk) - 1] == '"')
+		quoted = TRUE;
+	if (!quoted && (strlen (psk) == 64)) {
+		/* Verify the hex PSK; 64 digits */
+		if (!is_hex (psk)) {
+			g_set_error (error, ifnet_plugin_error_quark (),
+				     0,
+				     "Invalid WPA_PSK (contains non-hexadecimal characters)");
+			goto out;
+		}
+		hashed = g_strdup (psk);
+	} else {
+		char *stripped = g_strdup (psk);
+
+		strip_string (stripped, '"');
+
+		/* Length check */
+		if (strlen (stripped) < 8 || strlen (stripped) > 63) {
+			g_set_error (error, ifnet_plugin_error_quark (), 0,
+				     "Invalid WPA_PSK (passphrases must be between "
+				     "8 and 63 characters long (inclusive))");
+			g_free (stripped);
+			goto out;
+		}
+
+		hashed = g_strdup (stripped);
+		g_free (stripped);
+	}
+
+	if (!hashed) {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "Invalid WPA_PSK (doesn't look like a passphrase or hex key)");
+		goto out;
+	}
+
+out:
+	return hashed;
+}
+
+static gboolean
+fill_wpa_ciphers (const char *ssid,
+                  NMSettingWirelessSecurity *wsec,
+                  gboolean group,
+                  gboolean adhoc)
+{
+	const char *value;
+	char **list = NULL, **iter;
+	int i = 0;
+
+	value = wpa_get_value (ssid, group ? "group" : "pairwise");
+	if (!value)
+		return TRUE;
+
+	list = g_strsplit_set (value, " ", 0);
+	for (iter = list; iter && *iter; iter++, i++) {
+		/* Ad-Hoc configurations cannot have pairwise ciphers, and can only
+		 * have one group cipher.  Ignore any additional group ciphers and
+		 * any pairwise ciphers specified.
+		 */
+		if (adhoc) {
+			if (group && (i > 0)) {
+				PLUGIN_WARN (IFNET_PLUGIN_NAME,
+					     "    warning: ignoring group cipher '%s' (only one group cipher allowed in Ad-Hoc mode)",
+					     *iter);
+				continue;
+			} else if (!group) {
+				PLUGIN_WARN (IFNET_PLUGIN_NAME,
+					     "    warning: ignoring pairwise cipher '%s' (pairwise not used in Ad-Hoc mode)",
+					     *iter);
+				continue;
+			}
+		}
+
+		if (!strcmp (*iter, "CCMP")) {
+			if (group)
+				nm_setting_wireless_security_add_group (wsec,
+									"ccmp");
+			else
+				nm_setting_wireless_security_add_pairwise (wsec,
+									   "ccmp");
+		} else if (!strcmp (*iter, "TKIP")) {
+			if (group)
+				nm_setting_wireless_security_add_group (wsec,
+									"tkip");
+			else
+				nm_setting_wireless_security_add_pairwise (wsec,
+									   "tkip");
+		} else if (group && !strcmp (*iter, "WEP104"))
+			nm_setting_wireless_security_add_group (wsec, "wep104");
+		else if (group && !strcmp (*iter, "WEP40"))
+			nm_setting_wireless_security_add_group (wsec, "wep40");
+		else {
+			PLUGIN_WARN (IFNET_PLUGIN_NAME,
+				     "    warning: ignoring invalid %s cipher '%s'",
+				     group ? "CIPHER_GROUP" : "CIPHER_PAIRWISE",
+				     *iter);
+		}
+	}
+
+	if (list)
+		g_strfreev (list);
+	return TRUE;
+}
+
+static NMSetting8021x *
+fill_8021x (const char *ssid,
+            const char *key_mgmt,
+            gboolean wifi,
+            GError **error)
+{
+	NMSetting8021x *s_8021x;
+	const char *value;
+	char **list, **iter;
+
+	value = wpa_get_value (ssid, "eap");
+	if (!value) {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "Missing IEEE_8021X_EAP_METHODS for key management '%s'",
+			     key_mgmt);
+		return NULL;
+	}
+
+	list = g_strsplit (value, " ", 0);
+
+	s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
+	/* Validate and handle each EAP method */
+	for (iter = list; iter && *iter; iter++) {
+		EAPReader *eap = &eap_readers[0];
+		gboolean found = FALSE;
+		char *lower = NULL;
+
+		lower = g_ascii_strdown (*iter, -1);
+		while (eap->method && !found) {
+			if (strcmp (eap->method, lower))
+				goto next;
+
+			/* Some EAP methods don't provide keying material, thus they
+			 * cannot be used with WiFi unless they are an inner method
+			 * used with TTLS or PEAP or whatever.
+			 */
+			if (wifi && eap->wifi_phase2_only) {
+				PLUGIN_WARN (IFNET_PLUGIN_NAME,
+					     "    warning: ignored invalid "
+					     "IEEE_8021X_EAP_METHOD '%s'; not allowed for wifi.",
+					     lower);
+				goto next;
+			}
+
+			/* Parse EAP method specific options */
+			if (!(*eap->reader)
+			    (lower, ssid, s_8021x, FALSE, error)) {
+				g_free (lower);
+				goto error;
+			}
+			nm_setting_802_1x_add_eap_method (s_8021x, lower);
+			found = TRUE;
+
+		next:
+			eap++;
+		}
+
+		if (!found) {
+			PLUGIN_WARN (IFNET_PLUGIN_NAME,
+				     "    warning: ignored unknown"
+				     "IEEE_8021X_EAP_METHOD '%s'.", lower);
+		}
+		g_free (lower);
+	}
+	g_strfreev (list);
+
+	if (nm_setting_802_1x_get_num_eap_methods (s_8021x) == 0) {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "No valid EAP methods found in IEEE_8021X_EAP_METHODS.");
+		goto error;
+	}
+
+	return s_8021x;
+
+error:
+	g_object_unref (s_8021x);
+	return NULL;
+}
+
+static NMSettingWirelessSecurity *
+make_wpa_setting (const char *ssid,
+                  NMSetting8021x **s_8021x,
+                  GError **error)
+{
+	NMSettingWirelessSecurity *wsec;
+	const char *value;
+	char *lower;
+	gboolean adhoc = FALSE;
+
+	if (!exist_ssid (ssid)) {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "No security info found for ssid: %s", ssid);
+		return NULL;
+	}
+
+	wsec =
+	    NM_SETTING_WIRELESS_SECURITY (nm_setting_wireless_security_new ());
+
+	/* mode=1: adhoc
+	 * mode=0: infrastructure */
+	value = wpa_get_value (ssid, "mode");
+	if (value)
+		adhoc = strcmp (value, "1") == 0 ? TRUE : FALSE;
+
+	value = wpa_get_value (ssid, "key_mgmt");
+	/* Not WPA or Dynamic WEP */
+	if (!value)
+		goto error;
+	if (strcmp (value, "WPA-PSK") && strcmp (value, "WPA-EAP"))
+		goto error;
+	/* Pairwise and Group ciphers */
+	fill_wpa_ciphers (ssid, wsec, FALSE, adhoc);
+	fill_wpa_ciphers (ssid, wsec, TRUE, adhoc);
+
+	/* WPA and/or RSN */
+	if (adhoc) {
+		/* Ad-Hoc mode only supports WPA proto for now */
+		nm_setting_wireless_security_add_proto (wsec, "wpa");
+	} else {
+		nm_setting_wireless_security_add_proto (wsec, "wpa");
+		nm_setting_wireless_security_add_proto (wsec, "rsn");
+
+	}
+
+	if (!strcmp (value, "WPA-PSK")) {
+		char *psk = parse_wpa_psk (wpa_get_value (ssid, "psk"), error);
+
+		if (!psk)
+			goto error;
+		g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_PSK, psk,
+			      NULL);
+		g_free (psk);
+
+		if (adhoc)
+			g_object_set (wsec,
+				      NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,
+				      "wpa-none", NULL);
+		else
+			g_object_set (wsec,
+				      NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,
+				      "wpa-psk", NULL);
+	} else if (!strcmp (value, "WPA-EAP") || !strcmp (value, "IEEE8021X")) {
+		if (adhoc) {
+			g_set_error (error, ifnet_plugin_error_quark (), 0,
+				     "Ad-Hoc mode cannot be used with KEY_MGMT type '%s'",
+				     value);
+			goto error;
+		}
+		*s_8021x = fill_8021x (ssid, value, TRUE, error);
+		if (!*s_8021x)
+			goto error;
+
+		lower = g_ascii_strdown (value, -1);
+		g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,
+			      lower, NULL);
+		g_free (lower);
+	} else {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "Unknown wireless KEY_MGMT type '%s'", value);
+		goto error;
+	}
+	return wsec;
+error:
+	if (wsec)
+		g_object_unref (wsec);
+	return NULL;
+}
+
+static NMSettingWirelessSecurity *
+make_wireless_security_setting (const char *conn_name,
+                                NMSetting8021x **s_8021x,
+                                GError ** error)
+{
+	NMSettingWirelessSecurity *wsec = NULL;
+	const char *ssid;
+	gboolean adhoc = FALSE;
+	const char *value;
+
+	g_return_val_if_fail (conn_name != NULL
+			      && strcmp (ifnet_get_data (conn_name, "type"),
+					 "ppp") != 0, NULL);
+	if (!wpa_get_value (conn_name, "ssid"))
+		return NULL;
+	PLUGIN_PRINT (IFNET_PLUGIN_NAME,
+		      "updating wireless security settings (%s).", conn_name);
+
+	ssid = conn_name;
+	value = wpa_get_value (ssid, "mode");
+	if (value)
+		adhoc = strcmp (value, "1") == 0 ? TRUE : FALSE;
+
+	if (!adhoc) {
+		wsec = make_leap_setting (ssid, error);
+		if (error && *error)
+			goto error;
+	}
+	if (!wsec) {
+		wsec = make_wpa_setting (ssid, s_8021x, error);
+		if (error && *error)
+			goto error;
+	}
+	if (!wsec) {
+		wsec = make_wep_setting (ssid, error);
+		if (error && *error)
+			goto error;
+	}
+
+	if (!wsec) {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "Can't handle security information for ssid: %s",
+			     conn_name);
+	}
+
+	return wsec;
+error:
+	return NULL;
+}
+
+/* Currently only support username and password */
+static void
+make_pppoe_connection_setting (NMConnection *connection,
+                               const char *conn_name,
+                               GError **error)
+{
+	NMSettingPPPOE *s_pppoe;
+	NMSettingPPP *s_ppp;
+	const char *value;
+
+	s_pppoe = NM_SETTING_PPPOE (nm_setting_pppoe_new ());
+
+	/* username */
+	value = ifnet_get_data (conn_name, "username");
+	if (!value) {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "ppp requires at lease a username");
+		return;
+	}
+	g_object_set (s_pppoe, NM_SETTING_PPPOE_USERNAME, value, NULL);
+
+	/* password */
+	value = ifnet_get_data (conn_name, "password");
+	if (!value) {
+		value = "";
+	}
+
+	g_object_set (s_pppoe, NM_SETTING_PPPOE_PASSWORD, value, NULL);
+	nm_connection_add_setting (connection, NM_SETTING (s_pppoe));
+
+	/* PPP setting */
+	s_ppp = (NMSettingPPP *) nm_setting_ppp_new ();
+	nm_connection_add_setting (connection, NM_SETTING (s_ppp));
+}
+
+NMConnection *
+ifnet_update_connection_from_config_block (const char *conn_name, GError **error)
+{
+	const gchar *type = NULL;
+	NMConnection *connection = NULL;
+	NMSettingConnection *setting = NULL;
+	NMSetting8021x *s_8021x = NULL;
+	NMSettingWirelessSecurity *wsec = NULL;
+	gboolean auto_conn = TRUE;
+	const char *value = NULL;
+	gboolean success = FALSE;
+
+	connection = nm_connection_new ();
+	if (!connection)
+		return NULL;
+	setting =
+	    (NMSettingConnection *) nm_connection_get_setting (connection,
+							       NM_TYPE_SETTING_CONNECTION);
+	if (!setting) {
+		setting = NM_SETTING_CONNECTION (nm_setting_connection_new ());
+		g_assert (setting);
+		nm_connection_add_setting (connection, NM_SETTING (setting));
+	}
+
+	type = guess_connection_type (conn_name);
+	value = ifnet_get_data (conn_name, "auto");
+	if (value && !strcmp (value, "false"))
+		auto_conn = FALSE;
+	update_connection_id (connection, conn_name);
+	g_object_set (setting, NM_SETTING_CONNECTION_TYPE, type,
+		      NM_SETTING_CONNECTION_READ_ONLY, FALSE,
+		      NM_SETTING_CONNECTION_AUTOCONNECT, auto_conn, NULL);
+
+	if (!strcmp (NM_SETTING_WIRED_SETTING_NAME, type)
+	    || !strcmp (NM_SETTING_PPPOE_SETTING_NAME, type)) {
+		/* wired setting */
+		make_wired_connection_setting (connection, conn_name, error);
+		if (error && *error) {
+			PLUGIN_WARN (IFNET_PLUGIN_NAME,
+				     "Found error: %s", (*error)->message);
+			goto error;
+		}
+		/* pppoe setting */
+		if (!strcmp (NM_SETTING_PPPOE_SETTING_NAME, type))
+			make_pppoe_connection_setting (connection, conn_name,
+						       error);
+		if (error && *error) {
+			PLUGIN_WARN (IFNET_PLUGIN_NAME,
+				     "Found error: %s", (*error)->message);
+			goto error;
+		}
+	} else if (!strcmp (NM_SETTING_WIRELESS_SETTING_NAME, type)) {
+		/* wireless setting */
+		NMSetting *wireless_setting;
+
+		wireless_setting = make_wireless_connection_setting (conn_name, &s_8021x, error);
+		if (!wireless_setting)
+			goto error;
+		nm_connection_add_setting (connection, wireless_setting);
+
+		if (error && *error) {
+			PLUGIN_WARN (IFNET_PLUGIN_NAME,
+				     "Found error: %s", (*error)->message);
+			goto error;
+		}
+
+		/* wireless security setting */
+		wsec = make_wireless_security_setting (conn_name, &s_8021x, error);
+		if (wsec) {
+			nm_connection_add_setting (connection,
+						   NM_SETTING (wsec));
+			if (s_8021x)
+				nm_connection_add_setting (connection,
+							   NM_SETTING
+							   (s_8021x));
+			g_object_set (wireless_setting, NM_SETTING_WIRELESS_SEC,
+				      NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
+				      NULL);
+		}
+
+		if (error && *error) {
+			PLUGIN_WARN (IFNET_PLUGIN_NAME,
+				     "Found error: %s", (*error)->message);
+			goto error;
+		}
+
+	} else
+		goto error;
+
+	/* IPv4 setting */
+	make_ip4_setting (connection, conn_name, error);
+	if (error && *error)
+		PLUGIN_WARN (IFNET_PLUGIN_NAME,
+			     "Found error: %s", (*error)->message);
+
+	/* IPv6 setting */
+	make_ip6_setting (connection, conn_name, error);
+	if (error && *error)
+		PLUGIN_WARN (IFNET_PLUGIN_NAME,
+			     "Found error: %s", (*error)->message);
+
+	success = nm_connection_verify (connection, error);
+	if (error && *error)
+		PLUGIN_WARN (IFNET_PLUGIN_NAME,
+			     "Found error: %s", (*error)->message);
+	PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Connection verified %s:%d", conn_name, success);
+	if (!success)
+		goto error;
+	return connection;
+
+error:
+	g_object_unref (setting);
+	g_object_unref (connection);
+	return NULL;
+}
+
+typedef NMSetting8021xCKScheme (*SchemeFunc) (NMSetting8021x * setting);
+typedef const char *(*PathFunc) (NMSetting8021x * setting);
+typedef const GByteArray *(*BlobFunc) (NMSetting8021x * setting);
+
+typedef struct ObjectType {
+	const char *setting_key;
+	SchemeFunc scheme_func;
+	PathFunc path_func;
+	BlobFunc blob_func;
+	const char *conn_name_key;
+	const char *suffix;
+} ObjectType;
+
+static const ObjectType ca_type = {
+	NM_SETTING_802_1X_CA_CERT,
+	nm_setting_802_1x_get_ca_cert_scheme,
+	nm_setting_802_1x_get_ca_cert_path,
+	nm_setting_802_1x_get_ca_cert_blob,
+	"ca_cert",
+	"ca-cert.der"
+};
+
+static const ObjectType phase2_ca_type = {
+	NM_SETTING_802_1X_PHASE2_CA_CERT,
+	nm_setting_802_1x_get_phase2_ca_cert_scheme,
+	nm_setting_802_1x_get_phase2_ca_cert_path,
+	nm_setting_802_1x_get_phase2_ca_cert_blob,
+	"ca_cert2",
+	"inner-ca-cert.der"
+};
+
+static const ObjectType client_type = {
+	NM_SETTING_802_1X_CLIENT_CERT,
+	nm_setting_802_1x_get_client_cert_scheme,
+	nm_setting_802_1x_get_client_cert_path,
+	nm_setting_802_1x_get_client_cert_blob,
+	"client_cert",
+	"client-cert.der"
+};
+
+static const ObjectType phase2_client_type = {
+	NM_SETTING_802_1X_PHASE2_CLIENT_CERT,
+	nm_setting_802_1x_get_phase2_client_cert_scheme,
+	nm_setting_802_1x_get_phase2_client_cert_path,
+	nm_setting_802_1x_get_phase2_client_cert_blob,
+	"client_cert2",
+	"inner-client-cert.der"
+};
+
+static const ObjectType pk_type = {
+	NM_SETTING_802_1X_PRIVATE_KEY,
+	nm_setting_802_1x_get_private_key_scheme,
+	nm_setting_802_1x_get_private_key_path,
+	nm_setting_802_1x_get_private_key_blob,
+	"private_key",
+	"private-key.pem"
+};
+
+static const ObjectType phase2_pk_type = {
+	NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
+	nm_setting_802_1x_get_phase2_private_key_scheme,
+	nm_setting_802_1x_get_phase2_private_key_path,
+	nm_setting_802_1x_get_phase2_private_key_blob,
+	"private_key2",
+	"inner-private-key.pem"
+};
+
+static const ObjectType p12_type = {
+	NM_SETTING_802_1X_PRIVATE_KEY,
+	nm_setting_802_1x_get_private_key_scheme,
+	nm_setting_802_1x_get_private_key_path,
+	nm_setting_802_1x_get_private_key_blob,
+	"private_key",
+	"private-key.p12"
+};
+
+static const ObjectType phase2_p12_type = {
+	NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
+	nm_setting_802_1x_get_phase2_private_key_scheme,
+	nm_setting_802_1x_get_phase2_private_key_path,
+	nm_setting_802_1x_get_phase2_private_key_blob,
+	"private_key2",
+	"inner-private-key.p12"
+};
+
+static gboolean
+write_object (NMSetting8021x *s_8021x,
+              const char *conn_name,
+              const GByteArray *override_data,
+              const ObjectType *objtype,
+              GError **error)
+{
+	NMSetting8021xCKScheme scheme;
+	const char *path = NULL;
+	const GByteArray *blob = NULL;
+
+	g_return_val_if_fail (conn_name != NULL, FALSE);
+	g_return_val_if_fail (objtype != NULL, FALSE);
+	if (override_data)
+		/* if given explicit data to save, always use that instead of asking
+		 * the setting what to do.
+		 */
+		blob = override_data;
+	else {
+		scheme = (*(objtype->scheme_func)) (s_8021x);
+		switch (scheme) {
+		case NM_SETTING_802_1X_CK_SCHEME_BLOB:
+			blob = (*(objtype->blob_func)) (s_8021x);
+			break;
+		case NM_SETTING_802_1X_CK_SCHEME_PATH:
+			path = (*(objtype->path_func)) (s_8021x);
+			break;
+		default:
+			break;
+		}
+	}
+
+	/* If the object path was specified, prefer that over any raw cert data that
+	 * may have been sent.
+	 */
+	if (path) {
+		wpa_set_data (conn_name, (gchar *) objtype->conn_name_key,
+			      (gchar *) path);
+		return TRUE;
+	}
+
+	/* does not support writing encryption data now */
+	if (blob) {
+		PLUGIN_WARN (IFNET_PLUGIN_NAME,
+			     "    warning: Currently we do not support certs writing.");
+	}
+
+	return TRUE;
+}
+
+static gboolean
+write_8021x_certs (NMSetting8021x *s_8021x,
+                   gboolean phase2,
+                   const char *conn_name,
+                   GError **error)
+{
+	char *password = NULL;
+	const ObjectType *otype = NULL;
+	gboolean is_pkcs12 = FALSE, success = FALSE;
+	const GByteArray *blob = NULL;
+	GByteArray *enc_key = NULL;
+	gchar *generated_pw = NULL;
+
+	/* CA certificate */
+	if (phase2)
+		otype = &phase2_ca_type;
+	else
+		otype = &ca_type;
+
+	if (!write_object (s_8021x, conn_name, NULL, otype, error))
+		return FALSE;
+
+	/* Private key */
+	if (phase2) {
+		if (nm_setting_802_1x_get_phase2_private_key_scheme (s_8021x) !=
+		    NM_SETTING_802_1X_CK_SCHEME_UNKNOWN) {
+			if (nm_setting_802_1x_get_phase2_private_key_format
+			    (s_8021x) == NM_SETTING_802_1X_CK_FORMAT_PKCS12)
+				is_pkcs12 = TRUE;
+		}
+		password = (char *)
+		    nm_setting_802_1x_get_phase2_private_key_password (s_8021x);
+	} else {
+		if (nm_setting_802_1x_get_private_key_scheme (s_8021x) !=
+		    NM_SETTING_802_1X_CK_SCHEME_UNKNOWN) {
+			if (nm_setting_802_1x_get_private_key_format (s_8021x)
+			    == NM_SETTING_802_1X_CK_FORMAT_PKCS12)
+				is_pkcs12 = TRUE;
+		}
+		password = (char *)
+		    nm_setting_802_1x_get_private_key_password (s_8021x);
+	}
+
+	if (is_pkcs12)
+		otype = phase2 ? &phase2_p12_type : &p12_type;
+	else
+		otype = phase2 ? &phase2_pk_type : &pk_type;
+
+	if ((*(otype->scheme_func)) (s_8021x) ==
+	    NM_SETTING_802_1X_CK_SCHEME_BLOB)
+		blob = (*(otype->blob_func)) (s_8021x);
+
+	/* Only do the private key re-encrypt dance if we got the raw key data, which
+	 * by definition will be unencrypted.  If we're given a direct path to the
+	 * private key file, it'll be encrypted, so we don't need to re-encrypt.
+	 */
+	if (blob && !is_pkcs12) {
+		/* Encrypt the unencrypted private key with the fake password */
+		enc_key =
+		    nm_utils_rsa_key_encrypt (blob, password, &generated_pw,
+					      error);
+		if (!enc_key)
+			goto out;
+
+		if (generated_pw)
+			password = generated_pw;
+	}
+
+	/* Save the private key */
+	if (!write_object
+	    (s_8021x, conn_name, enc_key ? enc_key : blob, otype, error))
+		goto out;
+
+	if (phase2)
+		wpa_set_data (conn_name, "private_key_passwd2", password);
+	else
+		wpa_set_data (conn_name, "private_key_passwd", password);
+
+	/* Client certificate */
+	if (is_pkcs12) {
+		wpa_set_data (conn_name,
+			      phase2 ? "client_cert2" : "client_cert", NULL);
+	} else {
+		if (phase2)
+			otype = &phase2_client_type;
+		else
+			otype = &client_type;
+
+		/* Save the client certificate */
+		if (!write_object (s_8021x, conn_name, NULL, otype, error))
+			goto out;
+	}
+
+	success = TRUE;
+out:
+	if (generated_pw) {
+		memset (generated_pw, 0, strlen (generated_pw));
+		g_free (generated_pw);
+	}
+	if (enc_key) {
+		memset (enc_key->data, 0, enc_key->len);
+		g_byte_array_free (enc_key, TRUE);
+	}
+	return success;
+}
+
+static gboolean
+write_8021x_setting (NMConnection *connection,
+                     const char *conn_name,
+                     gboolean wired,
+                     GError **error)
+{
+	NMSetting8021x *s_8021x;
+	const char *value;
+	char *tmp = NULL;
+	gboolean success = FALSE;
+	GString *phase2_auth;
+	GString *phase1;
+
+	s_8021x =
+	    (NMSetting8021x *) nm_connection_get_setting (connection,
+							  NM_TYPE_SETTING_802_1X);
+
+	if (!s_8021x) {
+		return TRUE;
+	}
+
+	PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Adding 8021x setting for %s",
+		      conn_name);
+
+	/* If wired, write KEY_MGMT */
+	if (wired)
+		wpa_set_data (conn_name, "key_mgmt", "IEEE8021X");
+
+	/* EAP method */
+	if (nm_setting_802_1x_get_num_eap_methods (s_8021x)) {
+		value = nm_setting_802_1x_get_eap_method (s_8021x, 0);
+		if (value)
+			tmp = g_ascii_strup (value, -1);
+	}
+	wpa_set_data (conn_name, "eap", tmp ? tmp : NULL);
+	g_free (tmp);
+
+	wpa_set_data (conn_name, "identity",
+		      (gchar *) nm_setting_802_1x_get_identity (s_8021x));
+
+	wpa_set_data (conn_name, "anonymous_identity", (gchar *)
+		      nm_setting_802_1x_get_anonymous_identity (s_8021x));
+
+	wpa_set_data (conn_name, "password",
+		      (gchar *) nm_setting_802_1x_get_password (s_8021x));
+
+	phase1 = g_string_new (NULL);
+
+	/* PEAP version */
+	wpa_set_data (conn_name, "phase1", NULL);
+	value = nm_setting_802_1x_get_phase1_peapver (s_8021x);
+	if (value && (!strcmp (value, "0") || !strcmp (value, "1")))
+		g_string_append_printf (phase1, "peapver=%s ", value);
+
+	/* PEAP label */
+	value = nm_setting_802_1x_get_phase1_peaplabel (s_8021x);
+	if (value && !strcmp (value, "1"))
+		g_string_append_printf (phase1, "peaplabel=%s ", value);
+	if (phase1->len) {
+		tmp = g_strstrip (g_strdup (phase1->str));
+		wpa_set_data (conn_name, "phase1", tmp);
+		g_free (tmp);
+	}
+
+	/* Phase2 auth methods */
+	wpa_set_data (conn_name, "phase2", NULL);
+	phase2_auth = g_string_new (NULL);
+
+	value = nm_setting_802_1x_get_phase2_auth (s_8021x);
+	if (value) {
+		tmp = g_ascii_strup (value, -1);
+		g_string_append_printf (phase2_auth, "auth=%s ", tmp);
+		g_free (tmp);
+	}
+
+	/* Phase2 auth heap */
+	value = nm_setting_802_1x_get_phase2_autheap (s_8021x);
+	if (value) {
+		tmp = g_ascii_strup (value, -1);
+		g_string_append_printf (phase2_auth, "autheap=%s ", tmp);
+		g_free (tmp);
+	}
+	tmp = g_strstrip (g_strdup (phase2_auth->str));
+	wpa_set_data (conn_name, "phase2", phase2_auth->len ? tmp : NULL);
+	g_free (tmp);
+
+	g_string_free (phase2_auth, TRUE);
+	g_string_free (phase1, TRUE);
+
+	success = write_8021x_certs (s_8021x, FALSE, conn_name, error);
+	if (success) {
+		/* phase2/inner certs */
+		success = write_8021x_certs (s_8021x, TRUE, conn_name, error);
+	}
+
+	return success;
+}
+
+static gboolean
+write_wireless_security_setting (NMConnection * connection,
+				 gchar * conn_name,
+				 gboolean adhoc,
+				 gboolean * no_8021x, GError ** error)
+{
+	NMSettingWirelessSecurity *s_wsec;
+	const char *key_mgmt, *auth_alg, *key, *cipher, *psk;
+	gboolean wep = FALSE, wpa = FALSE;
+	char *tmp;
+	guint32 i, num;
+	GString *str;
+
+	s_wsec =
+	    (NMSettingWirelessSecurity *) nm_connection_get_setting (connection,
+								     NM_TYPE_SETTING_WIRELESS_SECURITY);
+	if (!s_wsec) {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "Missing '%s' setting",
+			     NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
+		return FALSE;
+	}
+
+	key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec);
+	g_assert (key_mgmt);
+
+	auth_alg = nm_setting_wireless_security_get_auth_alg (s_wsec);
+
+	if (!strcmp (key_mgmt, "none")) {
+		wpa_set_data (conn_name, "key_mgmt", "NONE");
+		wep = TRUE;
+		*no_8021x = TRUE;
+	} else if (!strcmp (key_mgmt, "wpa-none")
+		   || !strcmp (key_mgmt, "wpa-psk")) {
+		wpa_set_data (conn_name, "key_mgmt", "WPA-PSK");
+		wpa = TRUE;
+		*no_8021x = TRUE;
+	} else if (!strcmp (key_mgmt, "ieee8021x")) {
+		wpa_set_data (conn_name, "key_mgmt", "IEEE8021X");
+	} else if (!strcmp (key_mgmt, "wpa-eap")) {
+		wpa_set_data (conn_name, "key_mgmt", "WPA-EAP");
+		wpa = TRUE;
+	} else
+		PLUGIN_WARN (IFNET_PLUGIN_NAME, "Unknown key_mgmt: %s", key_mgmt);
+
+	if (auth_alg) {
+		if (!strcmp (auth_alg, "shared"))
+			wpa_set_data (conn_name, "auth_alg", "SHARED");
+		else if (!strcmp (auth_alg, "open"))
+			wpa_set_data (conn_name, "auth_alg", "OPEN");
+		else if (!strcmp (auth_alg, "leap")) {
+			wpa_set_data (conn_name, "auth_alg", "LEAP");
+			wpa_set_data (conn_name, "eap", "LEAP");
+			wpa_set_data (conn_name, "identity", (gchar *)
+				      nm_setting_wireless_security_get_leap_username
+				      (s_wsec));
+			wpa_set_data (conn_name, "password", (gchar *)
+				      nm_setting_wireless_security_get_leap_password
+				      (s_wsec));
+			*no_8021x = TRUE;
+		}
+	} else
+		wpa_set_data (conn_name, "auth_alg", NULL);
+
+	/* Default WEP TX key index */
+	wpa_set_data (conn_name, "wep_tx_keyidx", NULL);
+	if (wep) {
+		tmp =
+		    g_strdup_printf ("%d",
+				     nm_setting_wireless_security_get_wep_tx_keyidx
+				     (s_wsec));
+		wpa_set_data (conn_name, "wep_tx_keyidx", tmp);
+		g_free (tmp);
+	}
+
+	/* WEP keys */
+	for (i = 0; i < 4; i++) {
+		int length;
+
+		key = nm_setting_wireless_security_get_wep_key (s_wsec, i);
+		if (!key)
+			continue;
+		tmp = g_strdup_printf ("wep_key%d", i);
+		length = strlen (key);
+		if (length == 10 || length == 26 || length == 58)
+			wpa_set_data (conn_name, tmp, (gchar *) key);
+		else {
+			gchar *tmp_key = g_strdup_printf ("\"%s\"", key);
+
+			wpa_set_data (conn_name, tmp, tmp_key);
+			g_free (tmp_key);
+		}
+		g_free (tmp);
+	}
+
+	/* WPA Pairwise ciphers */
+	wpa_set_data (conn_name, "pairwise", NULL);
+	str = g_string_new (NULL);
+	num = nm_setting_wireless_security_get_num_pairwise (s_wsec);
+	for (i = 0; i < num; i++) {
+		if (i > 0)
+			g_string_append_c (str, ' ');
+		cipher = nm_setting_wireless_security_get_pairwise (s_wsec, i);
+		tmp = g_ascii_strup (cipher, -1);
+		g_string_append (str, tmp);
+		g_free (tmp);
+	}
+	if (strlen (str->str))
+		wpa_set_data (conn_name, "pairwise", str->str);
+	g_string_free (str, TRUE);
+
+	/* WPA Group ciphers */
+	wpa_set_data (conn_name, "group", NULL);
+	str = g_string_new (NULL);
+	num = nm_setting_wireless_security_get_num_groups (s_wsec);
+	for (i = 0; i < num; i++) {
+		if (i > 0)
+			g_string_append_c (str, ' ');
+		cipher = nm_setting_wireless_security_get_group (s_wsec, i);
+		tmp = g_ascii_strup (cipher, -1);
+		g_string_append (str, tmp);
+		g_free (tmp);
+	}
+	if (strlen (str->str))
+		wpa_set_data (conn_name, "group", str->str);
+	g_string_free (str, TRUE);
+
+	/* WPA Passphrase */
+	if (wpa) {
+		GString *quoted = NULL;
+
+		psk = nm_setting_wireless_security_get_psk (s_wsec);
+		if (psk && (strlen (psk) != 64)) {
+			quoted = g_string_sized_new (strlen (psk) + 2);
+			g_string_append_c (quoted, '"');
+			g_string_append (quoted, psk);
+			g_string_append_c (quoted, '"');
+		}
+		/* psk will be lost here if we don't check it for NULL */
+		if (psk)
+			wpa_set_data (conn_name, "psk",
+					  quoted ? quoted->str : (gchar *) psk);
+		if (quoted)
+			g_string_free (quoted, TRUE);
+	} else
+		wpa_set_data (conn_name, "psk", NULL);
+
+	return TRUE;
+}
+
+/* remove old ssid and add new one*/
+static void
+update_wireless_ssid (NMConnection *connection,
+                      const char *conn_name,
+                      const char *ssid,
+                      gboolean hex)
+{
+	if(strcmp (conn_name, ssid)){
+		ifnet_delete_network (conn_name);
+		wpa_delete_security (conn_name);
+	}
+
+	ifnet_add_network (ssid, "wireless");
+	wpa_add_security (ssid);
+}
+
+static gboolean
+write_wireless_setting (NMConnection *connection,
+                        const char *conn_name,
+                        gboolean *no_8021x,
+                        const char **out_new_name,
+                        GError **error)
+{
+	NMSettingWireless *s_wireless;
+	const GByteArray *ssid, *mac, *bssid;
+	const char *mode;
+	char buf[33];
+	guint32 mtu, i;
+	gboolean adhoc = FALSE, hex_ssid = FALSE;
+	gchar *ssid_str, *tmp;
+
+	s_wireless = (NMSettingWireless *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS);
+	if (!s_wireless) {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "Missing '%s' setting",
+			     NM_SETTING_WIRELESS_SETTING_NAME);
+		return FALSE;
+	}
+
+	ssid = nm_setting_wireless_get_ssid (s_wireless);
+	if (!ssid) {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "Missing SSID in '%s' setting",
+			     NM_SETTING_WIRELESS_SETTING_NAME);
+		return FALSE;
+	}
+	if (!ssid->len || ssid->len > 32) {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "Invalid SSID in '%s' setting",
+			     NM_SETTING_WIRELESS_SETTING_NAME);
+		return FALSE;
+	}
+
+	/* If the SSID contains any non-alnum characters, we need to use
+	 * the hex notation of the SSID instead. (Because openrc doesn't
+	 * support these characters, see bug #356337)
+	 */
+	for (i = 0; i < ssid->len; i++) {
+		if (!isalnum (ssid->data[i])) {
+			hex_ssid = TRUE;
+			break;
+		}
+	}
+
+	if (hex_ssid) {
+		GString *str;
+
+		/* Hex SSIDs don't get quoted */
+		str = g_string_sized_new (ssid->len * 2 + 3);
+		g_string_append (str, "0x");
+		for (i = 0; i < ssid->len; i++)
+			g_string_append_printf (str, "%02X", ssid->data[i]);
+		update_wireless_ssid (connection, conn_name, str->str, hex_ssid);
+		ssid_str = g_string_free (str, FALSE);
+	} else {
+		/* Printable SSIDs get quoted */
+		memset (buf, 0, sizeof (buf));
+		memcpy (buf, ssid->data, ssid->len);
+		g_strstrip (buf);
+		update_wireless_ssid (connection, conn_name, buf, hex_ssid);
+		ssid_str = g_strdup (buf);
+	}
+
+	ifnet_set_data (ssid_str, "mac", NULL);
+	mac = nm_setting_wireless_get_mac_address (s_wireless);
+	if (mac) {
+		tmp = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
+				       mac->data[0], mac->data[1], mac->data[2],
+				       mac->data[3], mac->data[4],
+				       mac->data[5]);
+		ifnet_set_data (ssid_str, "mac", tmp);
+		g_free (tmp);
+	}
+
+	ifnet_set_data (ssid_str, "mtu", NULL);
+	mtu = nm_setting_wireless_get_mtu (s_wireless);
+	if (mtu) {
+		tmp = g_strdup_printf ("%u", mtu);
+		ifnet_set_data (ssid_str, "mtu", tmp);
+		g_free (tmp);
+	}
+
+	ifnet_set_data (ssid_str, "mode", NULL);
+	mode = nm_setting_wireless_get_mode (s_wireless);
+	if (!mode || !strcmp (mode, "infrastructure")) {
+		wpa_set_data (ssid_str, "mode", "0");
+	} else if (!strcmp (mode, "adhoc")) {
+		wpa_set_data (ssid_str, "mode", "1");
+		adhoc = TRUE;
+	} else {
+		PLUGIN_WARN (IFNET_PLUGIN_NAME,
+			     "Invalid mode '%s' in '%s' setting",
+			     mode, NM_SETTING_WIRELESS_SETTING_NAME);
+		return FALSE;
+	}
+
+	wpa_set_data (ssid_str, "bssid", NULL);
+	bssid = nm_setting_wireless_get_bssid (s_wireless);
+	if (bssid) {
+		tmp = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
+				       bssid->data[0], bssid->data[1],
+				       bssid->data[2], bssid->data[3],
+				       bssid->data[4], bssid->data[5]);
+		wpa_set_data (ssid_str, "bssid", tmp);
+		g_free (tmp);
+	}
+
+	if (nm_setting_wireless_get_security (s_wireless)) {
+		if (!write_wireless_security_setting
+		    (connection, ssid_str, adhoc, no_8021x, error))
+			return FALSE;
+	} else
+		wpa_delete_security (ssid_str);
+
+	if (out_new_name)
+		*out_new_name = ifnet_get_data (ssid_str, "name");
+	g_free (ssid_str);
+	return TRUE;
+}
+
+static gboolean
+write_wired_setting (NMConnection *connection,
+                     const char *conn_name,
+                     GError **error)
+{
+	NMSettingWired *s_wired;
+	const GByteArray *mac;
+	char *tmp;
+	guint32 mtu;
+
+	s_wired =
+	    (NMSettingWired *) nm_connection_get_setting (connection,
+							  NM_TYPE_SETTING_WIRED);
+	if (!s_wired) {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "Missing '%s' setting",
+			     NM_SETTING_WIRED_SETTING_NAME);
+		return FALSE;
+	}
+
+	ifnet_set_data (conn_name, "mac", NULL);
+	mac = nm_setting_wired_get_mac_address (s_wired);
+	if (mac) {
+		tmp = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
+				       mac->data[0], mac->data[1], mac->data[2],
+				       mac->data[3], mac->data[4],
+				       mac->data[5]);
+		ifnet_set_data (conn_name, "mac", tmp);
+		g_free (tmp);
+	}
+
+	ifnet_set_data (conn_name, "mtu", NULL);
+	mtu = nm_setting_wired_get_mtu (s_wired);
+	if (mtu) {
+		tmp = g_strdup_printf ("%u", mtu);
+		ifnet_set_data (conn_name, "mtu", tmp);
+		g_free (tmp);
+	}
+	//FIXME may add connection type in future
+	//ifnet_set_data (conn_name, "TYPE", TYPE_ETHERNET);
+
+	return TRUE;
+}
+
+static void
+write_connection_setting (NMSettingConnection *s_con, const char *conn_name)
+{
+	ifnet_set_data (conn_name, "auto",
+			nm_setting_connection_get_autoconnect (s_con) ? "true" :
+			"false");
+}
+
+static gboolean
+write_ip4_setting (NMConnection *connection, const char *conn_name, GError **error)
+{
+	NMSettingIP4Config *s_ip4;
+	const char *value;
+	char *tmp;
+	guint32 i, num;
+	GString *searches;
+	GString *ips;
+	GString *routes;
+	GString *dns;
+	gboolean has_def_route = FALSE;
+	gboolean success = FALSE;
+
+	s_ip4 =
+	    (NMSettingIP4Config *) nm_connection_get_setting (connection,
+							      NM_TYPE_SETTING_IP4_CONFIG);
+	if (!s_ip4) {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "Missing '%s' setting",
+			     NM_SETTING_IP4_CONFIG_SETTING_NAME);
+		return FALSE;
+	}
+	routes = g_string_new (NULL);
+
+	value = nm_setting_ip4_config_get_method (s_ip4);
+	g_assert (value);
+	if (!strcmp (value, NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) {
+
+		num = nm_setting_ip4_config_get_num_addresses (s_ip4);
+		ips = g_string_new (NULL);
+		/* IPv4 addresses */
+		for (i = 0; i < num; i++) {
+			char buf[INET_ADDRSTRLEN + 1];
+			NMIP4Address *addr;
+			guint32 ip;
+
+			addr = nm_setting_ip4_config_get_address (s_ip4, i);
+
+			memset (buf, 0, sizeof (buf));
+			ip = nm_ip4_address_get_address (addr);
+			inet_ntop (AF_INET, (const void *) &ip, &buf[0],
+				   sizeof (buf));
+			g_string_append_printf (ips, "\"%s", &buf[0]);
+
+			tmp =
+			    g_strdup_printf ("%u",
+					     nm_ip4_address_get_prefix (addr));
+			g_string_append_printf (ips, "/%s\" ", tmp);
+			g_free (tmp);
+
+			/* only the first gateway will be written */
+			if (!has_def_route && nm_ip4_address_get_gateway (addr)) {
+				memset (buf, 0, sizeof (buf));
+				ip = nm_ip4_address_get_gateway (addr);
+				inet_ntop (AF_INET, (const void *) &ip, &buf[0],
+					   sizeof (buf));
+				g_string_append_printf (routes,
+							"\"default via %s\" ",
+							&buf[0]);
+				has_def_route = TRUE;
+			}
+		}
+		ifnet_set_data (conn_name, "config", ips->str);
+		g_string_free (ips, TRUE);
+	} else if (!strcmp (value, NM_SETTING_IP4_CONFIG_METHOD_SHARED))
+		ifnet_set_data (conn_name, "config", "shared");
+	else if (!strcmp (value, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL))
+		ifnet_set_data (conn_name, "config", "autoip");
+	else
+		ifnet_set_data (conn_name, "config", "dhcp");
+
+	/* DNS Servers */
+	num = nm_setting_ip4_config_get_num_dns (s_ip4);
+	if (num > 0) {
+		dns = g_string_new (NULL);
+		for (i = 0; i < num; i++) {
+			char buf[INET_ADDRSTRLEN + 1];
+			guint32 ip;
+
+			ip = nm_setting_ip4_config_get_dns (s_ip4, i);
+
+			memset (buf, 0, sizeof (buf));
+			inet_ntop (AF_INET, (const void *) &ip, &buf[0],
+				   sizeof (buf));
+			g_string_append_printf (dns, " %s", buf);
+		}
+		ifnet_set_data (conn_name, "dns_servers", dns->str);
+		g_string_free (dns, TRUE);
+	} else
+		ifnet_set_data (conn_name, "dns_servers", NULL);
+
+	/* DNS Searches */
+	num = nm_setting_ip4_config_get_num_dns_searches (s_ip4);
+	if (num > 0) {
+		searches = g_string_new (NULL);
+		for (i = 0; i < num; i++) {
+			if (i > 0)
+				g_string_append_c (searches, ' ');
+			g_string_append (searches,
+					 nm_setting_ip4_config_get_dns_search
+					 (s_ip4, i));
+		}
+		ifnet_set_data (conn_name, "dns_search", searches->str);
+		g_string_free (searches, TRUE);
+	} else
+		ifnet_set_data (conn_name, "dns_search", NULL);
+	/* FIXME Will be implemented when configuration supports it
+	   if (!strcmp(value, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) {
+	   value = nm_setting_ip4_config_get_dhcp_hostname(s_ip4);
+	   if (value)
+	   ifnet_set_data(conn_name, "DHCP_HOSTNAME", value,
+	   FALSE);
+
+	   value = nm_setting_ip4_config_get_dhcp_client_id(s_ip4);
+	   if (value)
+	   ifnet_set_data(conn_name, "DHCP_CLIENT_ID", value,
+	   FALSE);
+	   }
+	 */
+
+	/* Static routes */
+	num = nm_setting_ip4_config_get_num_routes (s_ip4);
+	if (num > 0) {
+		for (i = 0; i < num; i++) {
+			char buf[INET_ADDRSTRLEN + 1];
+			NMIP4Route *route;
+			guint32 ip;
+
+			route = nm_setting_ip4_config_get_route (s_ip4, i);
+
+			memset (buf, 0, sizeof (buf));
+			ip = nm_ip4_route_get_dest (route);
+			inet_ntop (AF_INET, (const void *) &ip, &buf[0],
+				   sizeof (buf));
+			g_string_append_printf (routes, "\"%s", buf);
+
+			tmp =
+			    g_strdup_printf ("%u",
+					     nm_ip4_route_get_prefix (route));
+			g_string_append_printf (routes, "/%s via ", tmp);
+			g_free (tmp);
+
+			memset (buf, 0, sizeof (buf));
+			ip = nm_ip4_route_get_next_hop (route);
+			inet_ntop (AF_INET, (const void *) &ip, &buf[0],
+				   sizeof (buf));
+			g_string_append_printf (routes, "%s\" ", buf);
+		}
+	}
+	if (routes->len > 0)
+		ifnet_set_data (conn_name, "routes", routes->str);
+	else
+		ifnet_set_data (conn_name, "routes", NULL);
+	g_string_free (routes, TRUE);
+
+	success = TRUE;
+
+	return success;
+}
+
+static gboolean
+write_route6_file (NMSettingIP6Config *s_ip6, const char *conn_name, GError **error)
+{
+	char dest[INET6_ADDRSTRLEN + 1];
+	char next_hop[INET6_ADDRSTRLEN + 1];
+	NMIP6Route *route;
+	const struct in6_addr *ip;
+	guint32 prefix;
+	guint32 i, num;
+	GString *routes_string;
+	const char *old_routes;
+
+	g_return_val_if_fail (s_ip6 != NULL, FALSE);
+	num = nm_setting_ip6_config_get_num_routes (s_ip6);
+	if (num == 0) {
+		return TRUE;
+	}
+
+	old_routes = ifnet_get_data (conn_name, "routes");
+	routes_string = g_string_new (old_routes);
+	if (old_routes)
+		g_string_append (routes_string, "\" ");
+	for (i = 0; i < num; i++) {
+		route = nm_setting_ip6_config_get_route (s_ip6, i);
+
+		memset (dest, 0, sizeof (dest));
+		ip = nm_ip6_route_get_dest (route);
+		inet_ntop (AF_INET6, (const void *) ip, &dest[0],
+			   sizeof (dest));
+
+		prefix = nm_ip6_route_get_prefix (route);
+
+		memset (next_hop, 0, sizeof (next_hop));
+		ip = nm_ip6_route_get_next_hop (route);
+		inet_ntop (AF_INET6, (const void *) ip, &next_hop[0],
+			   sizeof (next_hop));
+
+		g_string_append_printf (routes_string, "\"%s/%u via %s\" ",
+					dest, prefix, next_hop);
+	}
+	if (num > 0)
+		ifnet_set_data (conn_name, "routes", routes_string->str);
+	g_string_free (routes_string, TRUE);
+
+	return TRUE;
+}
+
+static gboolean
+write_ip6_setting (NMConnection *connection, const char *conn_name, GError **error)
+{
+	NMSettingIP6Config *s_ip6;
+	const char *value;
+	char *prefix;
+	guint32 i, num;
+	GString *searches;
+	char buf[INET6_ADDRSTRLEN + 1];
+	NMIP6Address *addr;
+	const struct in6_addr *ip;
+
+	s_ip6 =
+	    (NMSettingIP6Config *) nm_connection_get_setting (connection,
+							      NM_TYPE_SETTING_IP6_CONFIG);
+	if (!s_ip6) {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "Missing '%s' setting",
+			     NM_SETTING_IP6_CONFIG_SETTING_NAME);
+		return FALSE;
+	}
+
+	value = nm_setting_ip6_config_get_method (s_ip6);
+	g_assert (value);
+	if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) {
+		ifnet_set_data (conn_name, "enable_ipv6", "false");
+		return TRUE;
+	} else if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) {
+		/* nothing to do now */
+	} else {
+		// if (!strcmp(value, NM_SETTING_IP6_CONFIG_METHOD_AUTO)) {
+		const char *config = ifnet_get_data (conn_name, "config");
+		gchar *tmp;
+
+		if (!config)
+			tmp = g_strdup_printf ("dhcp6");
+		else
+			tmp = g_strdup_printf ("%s\" \"dhcp6\"", config);
+		ifnet_set_data (conn_name, "config", tmp);
+		g_free (tmp);
+	}
+	/* else if (!strcmp(value, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) {
+	   } else if (!strcmp(value, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)) {
+	   } else if (!strcmp(value, NM_SETTING_IP6_CONFIG_METHOD_SHARED)) {
+	   } */
+
+	/* Remember to set IPv6 enabled */
+	ifnet_set_data (conn_name, "enable_ipv6", "true");
+
+	if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) {
+		const char *config = ifnet_get_data (conn_name, "config");
+		gchar *tmp;
+		GString *ip_str;
+
+		if (!config)
+			config = "";
+		num = nm_setting_ip6_config_get_num_addresses (s_ip6);
+
+		/* IPv6 addresses */
+		ip_str = g_string_new (NULL);
+		for (i = 0; i < num; i++) {
+			addr = nm_setting_ip6_config_get_address (s_ip6, i);
+			ip = nm_ip6_address_get_address (addr);
+			prefix =
+			    g_strdup_printf ("%u",
+					     nm_ip6_address_get_prefix (addr));
+			memset (buf, 0, sizeof (buf));
+			inet_ntop (AF_INET6, (const void *) ip, buf,
+				   sizeof (buf));
+			g_string_append_printf (ip_str, "\"%s/", buf);
+			g_string_append_printf (ip_str, "%s\" ", prefix);
+			g_free (prefix);
+		}
+		tmp = g_strdup_printf ("%s\" %s", config, ip_str->str);
+		ifnet_set_data (conn_name, "config", tmp);
+		g_free (tmp);
+		g_string_free (ip_str, TRUE);
+	}
+
+	/* DNS Servers */
+	num = nm_setting_ip6_config_get_num_dns (s_ip6);
+	if (num > 0) {
+		const char *dns_servers = ifnet_get_data (conn_name, "dns_servers");
+		gchar *tmp;
+		GString *dns_string = g_string_new (NULL);
+
+		if (!dns_servers)
+			dns_servers = "";
+		for (i = 0; i < num; i++) {
+			ip = nm_setting_ip6_config_get_dns (s_ip6, i);
+
+			memset (buf, 0, sizeof (buf));
+			inet_ntop (AF_INET6, (const void *) ip, buf,
+				   sizeof (buf));
+			if (!strstr (dns_servers, buf))
+				g_string_append_printf (dns_string, "%s ", buf);
+		}
+		tmp = g_strdup_printf ("%s %s", dns_servers, dns_string->str);
+		ifnet_set_data (conn_name, "dns_servers", tmp);
+		g_free (tmp);
+		g_string_free (dns_string, TRUE);
+
+	} else
+		/* DNS Searches */
+		num = nm_setting_ip6_config_get_num_dns_searches (s_ip6);
+	if (num > 0) {
+		const char *ip4_domains;
+
+		ip4_domains = ifnet_get_data (conn_name, "dns_search");
+		if (!ip4_domains)
+			ip4_domains = "";
+		searches = g_string_new (ip4_domains);
+		for (i = 0; i < num; i++) {
+			const gchar *search = NULL;
+
+			search =
+			    nm_setting_ip6_config_get_dns_search (s_ip6, i);
+			if (search && !strstr (searches->str, search)) {
+				if (searches->len > 0)
+					g_string_append_c (searches, ' ');
+				g_string_append (searches, search);
+			}
+		}
+		ifnet_set_data (conn_name, "dns_search", searches->str);
+		g_string_free (searches, TRUE);
+	}
+
+	write_route6_file (s_ip6, conn_name, error);
+	if (error && *error)
+		return FALSE;
+	return TRUE;
+}
+
+static gboolean
+write_pppoe_setting (const char *conn_name, NMSettingPPPOE * s_pppoe)
+{
+	const gchar *value;
+
+	value = nm_setting_pppoe_get_username (s_pppoe);
+	if (!value) {
+		return FALSE;
+	}
+	ifnet_set_data (conn_name, "username", (gchar *) value);
+
+	value = nm_setting_pppoe_get_password (s_pppoe);
+	/* password could be NULL here */
+	if (value) {
+		ifnet_set_data (conn_name, "password", (gchar *) value);
+	}
+	return TRUE;
+}
+
+gboolean
+ifnet_update_parsers_by_connection (NMConnection *connection,
+                                    const char *conn_name,
+                                    const char *config_file,
+                                    const char *wpa_file,
+                                    gchar **out_new_name,
+                                    GError **error)
+{
+	NMSettingConnection *s_con;
+	NMSettingIP6Config *s_ip6;
+	gboolean success = FALSE;
+	const char *type;
+	gboolean no_8021x = FALSE;
+	gboolean wired = FALSE, pppoe = TRUE;
+	const char *new_name = NULL;
+
+	s_con =
+	    NM_SETTING_CONNECTION (nm_connection_get_setting
+				   (connection, NM_TYPE_SETTING_CONNECTION));
+	if (!s_con) {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "Missing '%s' setting",
+			     NM_SETTING_CONNECTION_SETTING_NAME);
+		return FALSE;
+	}
+
+
+	type = nm_setting_connection_get_connection_type (s_con);
+	if (!type) {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "Missing connection type!");
+		goto out;
+	}
+
+	if (!strcmp (type, NM_SETTING_WIRED_SETTING_NAME)) {
+		/* Writing wired setting */
+		if (!write_wired_setting (connection, conn_name, error))
+			goto out;
+		wired = TRUE;
+		no_8021x = TRUE;
+	} else if (!strcmp (type, NM_SETTING_WIRELESS_SETTING_NAME)) {
+		/* Writing wireless setting */
+		if (!write_wireless_setting (connection, conn_name, &no_8021x, &new_name, error))
+			goto out;
+	} else if (!strcmp (type, NM_SETTING_PPPOE_SETTING_NAME)) {
+		NMSettingPPPOE *s_pppoe;
+
+		/* Writing pppoe setting */
+		s_pppoe = NM_SETTING_PPPOE (nm_connection_get_setting (connection, NM_TYPE_SETTING_PPPOE));
+		if (!write_pppoe_setting (conn_name, s_pppoe))
+			goto out;
+		pppoe = TRUE;
+		wired = TRUE;
+		no_8021x = TRUE;
+	} else {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "Can't write connection type '%s'", type);
+		goto out;
+	}
+
+	/* connection name may have been updated; use it when writing out
+	 * the rest of the settings.
+	 */
+	if (new_name)
+		conn_name = new_name;
+
+	//FIXME wired connection doesn't support 8021x now
+	if (!no_8021x) {
+		if (!write_8021x_setting (connection, conn_name, wired, error))
+			goto out;
+	}
+
+	/* IPv4 Setting */
+	if (!write_ip4_setting (connection, conn_name, error))
+		goto out;
+
+	s_ip6 = (NMSettingIP6Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG);
+	if (s_ip6) {
+		/* IPv6 Setting */
+		if (!write_ip6_setting (connection, conn_name, error))
+			goto out;
+	}
+
+	/* Connection Setting */
+	write_connection_setting (s_con, conn_name);
+
+	/* connection id will be displayed in nm-applet */
+	update_connection_id (connection, conn_name);
+
+	success = ifnet_flush_to_file (config_file);
+	if (success)
+		wpa_flush_to_file (wpa_file);
+
+	if (out_new_name)
+		*out_new_name = g_strdup (conn_name);
+
+out:
+	return success;
+}
+
+gboolean
+ifnet_delete_connection_in_parsers (const char *conn_name,
+                                    const char *config_file,
+                                    const char *wpa_file)
+{
+	gboolean result = FALSE;
+
+	ifnet_delete_network (conn_name);
+	result = ifnet_flush_to_file (config_file);
+	if (result) {
+		/* connection may not have security information
+		 * so simply ignore the return value*/
+		wpa_delete_security (conn_name);
+		wpa_flush_to_file (wpa_file);
+	}
+
+	return result;
+}
+
+/* get the available wired name(eth*). */
+static gchar *
+get_wired_name ()
+{
+	int i = 0;
+
+	for (; i < 256; i++) {
+		gchar *conn_name = g_strdup_printf ("eth%d", i);
+
+		if (!ifnet_has_network (conn_name)) {
+			return conn_name;
+		} else
+			g_free (conn_name);
+	}
+	return NULL;
+}
+
+/* get the available pppoe name(ppp*). */
+static gchar *
+get_ppp_name ()
+{
+	int i = 0;
+
+	for (; i < 256; i++) {
+		gchar *conn_name = g_strdup_printf ("ppp%d", i);
+
+		if (!ifnet_has_network (conn_name)) {
+			return conn_name;
+		} else
+			g_free (conn_name);
+	}
+	return NULL;
+}
+
+/* get wireless ssid */
+static gchar *
+get_wireless_name (NMConnection * connection)
+{
+	NMSettingWireless *s_wireless;
+	const GByteArray *ssid;
+	gboolean hex_ssid = FALSE;
+	gchar *result = NULL;
+	char buf[33];
+	int i = 0;
+
+	s_wireless =
+	    (NMSettingWireless *) nm_connection_get_setting (connection,
+							     NM_TYPE_SETTING_WIRELESS);
+	if (!s_wireless)
+		return NULL;
+
+	ssid = nm_setting_wireless_get_ssid (s_wireless);
+	if (!ssid->len || ssid->len > 32) {
+		return NULL;
+	}
+
+	for (i = 0; i < ssid->len; i++) {
+		if (!isprint (ssid->data[i])) {
+			hex_ssid = TRUE;
+			break;
+		}
+	}
+
+	if (hex_ssid) {
+		GString *str;
+
+		str = g_string_sized_new (ssid->len * 2 + 3);
+		g_string_append (str, "0x");
+		for (i = 0; i < ssid->len; i++)
+			g_string_append_printf (str, "%02X", ssid->data[i]);
+		result = g_strdup (str->str);
+		g_string_free (str, TRUE);
+	} else {
+		memset (buf, 0, sizeof (buf));
+		memcpy (buf, ssid->data, ssid->len);
+		result = g_strdup_printf ("%s", buf);
+		g_strstrip (result);
+	}
+
+	return result;
+}
+
+char *
+ifnet_add_new_connection (NMConnection *connection,
+                          const char *config_file,
+                          const char *wpa_file,
+                          GError **error)
+{
+	NMSettingConnection *s_con;
+	gboolean success = FALSE;
+	const char *type;
+	gchar *new_type, *new_name = NULL;
+
+	s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
+	g_assert (s_con);
+	type = nm_setting_connection_get_connection_type (s_con);
+	g_assert (type);
+
+	PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Adding %s connection", type);
+
+	/* get name and type
+	 * Wireless type: wireless
+	 * Wired type: wired
+	 * PPPoE type: ppp*/
+	if (!strcmp (type, NM_SETTING_WIRED_SETTING_NAME)) {
+		new_name = get_wired_name ();
+		if (!new_name)
+			goto out;
+		new_type = "wired";
+	} else if (!strcmp (type, NM_SETTING_WIRELESS_SETTING_NAME)) {
+		new_name = get_wireless_name (connection);
+		new_type = "wireless";
+	} else if (!strcmp (type, NM_SETTING_PPPOE_SETTING_NAME)) {
+		new_name = get_ppp_name ();
+		if (!new_name)
+			goto out;
+		new_type = "ppp";
+	} else {
+		g_set_error (error, ifnet_plugin_error_quark (), 0,
+			     "Can't write connection type '%s'", type);
+		goto out;
+	}
+
+	if (ifnet_add_network (new_name, new_type)) {
+		success = ifnet_update_parsers_by_connection (connection,
+		                                              new_name,
+		                                              config_file,
+		                                              wpa_file,
+		                                              NULL,
+		                                              error);
+	}
+
+	PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Added new connection: %s, result: %s",
+	              new_name, success ? "success" : "fail");
+
+out:
+	if (!success)
+		g_free (new_name);
+	return success ? new_name : NULL;
+}
diff --git a/src/settings/plugins/ifnet/connection_parser.h b/src/settings/plugins/ifnet/connection_parser.h
new file mode 100644
index 00000000..b617b605
--- /dev/null
+++ b/src/settings/plugins/ifnet/connection_parser.h
@@ -0,0 +1,46 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* 
+ * Mu Qiao <qiaomuf@gmail.com>
+ *
+ * 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) 1999-2010 Gentoo Foundation, Inc.
+ */
+
+#ifndef _CONNECTION_PARSER_H
+#define _CONNECTION_PARSER_H
+#include <nm-connection.h>
+#include "net_parser.h"
+
+NMConnection *ifnet_update_connection_from_config_block (const char *conn_name,
+                                                         GError **error);
+
+/* nm_conn_name is used to update nm_ifnet_connection's priv data */
+gboolean ifnet_update_parsers_by_connection (NMConnection *connection,
+                                             const char *conn_name,
+                                             const char *config_file,
+                                             const char *wpa_file,
+                                             gchar **out_new_name,
+                                             GError **error);
+
+gboolean ifnet_delete_connection_in_parsers (const char *conn_name,
+                                             const char *config_file,
+                                             const char *wpa_file);
+
+char * ifnet_add_new_connection (NMConnection *connection,
+                                 const char *config_file,
+                                 const char *wpa_file,
+                                 GError ** error);
+#endif
diff --git a/src/settings/plugins/ifnet/net_parser.c b/src/settings/plugins/ifnet/net_parser.c
new file mode 100644
index 00000000..a48103db
--- /dev/null
+++ b/src/settings/plugins/ifnet/net_parser.c
@@ -0,0 +1,639 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Mu Qiao <qiaomuf@gmail.com>
+ *
+ * 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) 1999-2010 Gentoo Foundation, Inc.
+ */
+
+#include <string.h>
+#include <nm-system-config-interface.h>
+#include <stdio.h>
+#include "net_parser.h"
+#include "net_utils.h"
+
+/* Save all the connection information */
+static GHashTable *conn_table;
+
+/* Save global settings which are used for writing*/
+static GHashTable *global_settings_table;
+
+/* Save functions */
+static GList *functions_list;
+
+/* Used to decide whether to write changes to file*/
+static gboolean net_parser_data_changed = FALSE;
+
+static GHashTable *
+add_new_connection_config (const gchar * type, const gchar * name)
+{
+	GHashTable *new_conn;
+	gchar *new_name;
+
+	if (!name)
+		return NULL;
+
+	/* Return existing connection */
+	if ((new_conn = g_hash_table_lookup (conn_table, name)) != NULL)
+		return new_conn;
+	new_conn = g_hash_table_new (g_str_hash, g_str_equal);
+	new_name = g_strdup (name);
+	g_hash_table_insert (new_conn, g_strdup ("name"), new_name);
+	g_hash_table_insert (new_conn, g_strdup ("type"), g_strdup (type));
+	g_hash_table_insert (conn_table, new_name, new_conn);
+	return new_conn;
+}
+
+gboolean
+ifnet_add_network (const char *name, const char *type)
+{
+	if (ifnet_has_network (name))
+		return TRUE;
+	if (add_new_connection_config (type, name)) {
+		PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Adding network for %s", name);
+		net_parser_data_changed = TRUE;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+gboolean
+ifnet_has_network (const char *conn_name)
+{
+	return g_hash_table_lookup (conn_table, conn_name) != NULL;
+}
+
+static GHashTable *
+get_connection_config (const char *name)
+{
+	return g_hash_table_lookup (conn_table, name);
+}
+
+/* Ignored name won't be treated as wireless ssid */
+static gchar *ignore_name[] = {
+	"vlan", "bond", "atm", "ath", "ippp", "vpn", "tap", "tun", "1",
+	"br", "nas", "6to4", "timeout", "kvm", "force", NULL
+};
+
+static gboolean
+ignore_connection_name (const char *name)
+{
+	gboolean result = FALSE;
+	guint i = 0;
+
+	/* check ignore_name list */
+	while (ignore_name[i] != NULL) {
+		if (g_ascii_strncasecmp
+		    (name, ignore_name[i], strlen (ignore_name[i])) == 0) {
+			return TRUE;
+		}
+		i++;
+	}
+	/* Ignore mac address based configuration */
+	if (strlen (name) == 12 && is_hex (name))
+		result = TRUE;
+	return result;
+
+}
+
+static gboolean
+is_global_setting (char *key)
+{
+	static gchar *global_settings[] = { "wpa_supplicant_", NULL };
+	int i;
+
+	for (i = 0; global_settings[i] != NULL; i++) {
+		if (strstr (key, global_settings[i]))
+			return 1;
+	}
+	return 0;
+}
+
+/* Parse a complete line */
+/* Connection type is determined here */
+static void
+init_block_by_line (gchar * buf)
+{
+	gchar **key_value;
+	gchar *pos;
+	gchar *data;
+	gchar *tmp;
+	GHashTable *conn;
+
+	key_value = g_strsplit (buf, "=", 2);
+	if (g_strv_length (key_value) != 2) {
+		PLUGIN_WARN (IFNET_PLUGIN_NAME, "Can't handle this line: %s\n",
+			     buf);
+		g_strfreev (key_value);
+		return;
+	}
+	pos = g_strrstr (key_value[0], "_");
+	if (pos == NULL || is_global_setting (key_value[0])) {
+		/* global data */
+		PLUGIN_PRINT (IFNET_PLUGIN_NAME, "global:%s-%s\n", key_value[0],
+			      key_value[1]);
+		g_hash_table_insert (global_settings_table,
+				     g_strdup (key_value[0]),
+				     g_strdup (key_value[1]));
+		g_strfreev (key_value);
+		return;
+	}
+	*pos++ = '\0';
+	if ((conn = get_connection_config (pos)) == NULL) {
+		if (g_ascii_strncasecmp (pos, "eth", 3) == 0
+		    && strlen (pos) == 4)
+			/* wired connection */
+			conn = add_new_connection_config ("wired", pos);
+		else if (g_ascii_strncasecmp (pos, "ppp", 3) == 0
+			 && strlen (pos) == 4)
+			/* pppoe connection */
+			conn = add_new_connection_config ("ppp", pos);
+		else if (ignore_connection_name (pos)) {
+			/* ignored connection */
+			conn = add_new_connection_config ("ignore", pos);
+		} else
+			/* wireless connection */
+			conn = add_new_connection_config ("wireless", pos);
+	}
+	data = g_strdup (key_value[1]);
+	tmp = strip_string (data, '(');
+	tmp = strip_string (tmp, ')');
+	strip_string (tmp, '"');
+	strip_string (tmp, '\'');
+	if (conn)
+		g_hash_table_insert (conn, g_strdup (key_value[0]),
+				     g_strdup (tmp));
+	g_free (data);
+	g_strfreev (key_value);
+}
+
+static void
+destroy_connection_config (GHashTable * conn)
+{
+	gpointer key, value;
+	GHashTableIter iter;
+
+	g_hash_table_iter_init (&iter, conn);
+	while (g_hash_table_iter_next (&iter, &key, &value)) {
+		g_free (key);
+		g_free (value);
+	}
+
+	g_hash_table_destroy (conn);
+}
+
+// read settings from /etc/NetworkManager/nm-system-settings.conf
+const char *
+ifnet_get_global_setting (const char *group, const char *key)
+{
+	GError *error = NULL;
+	GKeyFile *keyfile = g_key_file_new ();
+	gchar *result = NULL;
+
+	if (!g_key_file_load_from_file (keyfile,
+					IFNET_SYSTEM_SETTINGS_KEY_FILE,
+					G_KEY_FILE_NONE, &error)) {
+		PLUGIN_WARN (IFNET_PLUGIN_NAME,
+			     "loading system config file (%s) caused error: (%d) %s",
+			     IFNET_SYSTEM_SETTINGS_KEY_FILE,
+			     error ? error->code : -1, error
+			     && error->message ? error->message : "(unknown)");
+	} else {
+		result = g_key_file_get_string (keyfile, group, key, &error);
+	}
+	g_key_file_free (keyfile);
+	return result;
+}
+
+static void
+strip_function (GIOChannel * channel, gchar * line)
+{
+
+	int counter = 0;
+	gchar *p, *tmp;
+	gboolean begin = FALSE;
+	GString *function_str = g_string_new (line);
+
+	g_string_append (function_str, "\n");
+	while (1) {
+		p = line;
+		while (*p != '\0') {
+			if (*p == '{') {
+				counter++;
+				begin = TRUE;
+			} else if (*p == '}')
+				counter--;
+			p++;
+		}
+		if (begin && counter == 0) {
+			g_free (line);
+			goto done;
+		}
+		while (1) {
+			g_free (line);
+			if (g_io_channel_read_line
+			    (channel, &line, NULL, NULL,
+			     NULL) == G_IO_STATUS_EOF)
+				goto done;
+			g_string_append (function_str, line);
+			tmp = g_strdup (line);
+			g_strstrip (tmp);
+			if (tmp[0] != '#' && tmp[0] != '\0') {
+				g_free (tmp);
+				break;
+			} else
+				g_free (tmp);
+		}
+	}
+done:
+	functions_list =
+	    g_list_append (functions_list, g_strdup (function_str->str));
+	g_string_free (function_str, TRUE);
+}
+
+static gboolean
+is_function (gchar * line)
+{
+	static gchar *func_names[] =
+	    { "preup", "predown", "postup", "postdown", "failup", "faildown",
+		NULL,
+	};
+	int i;
+
+	for (i = 0; func_names[i]; i++) {
+		if (g_str_has_prefix (line, func_names[i])) {
+			PLUGIN_PRINT (IFNET_PLUGIN_NAME,
+				      "Ignoring function: %s", func_names[i]);
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+gboolean
+ifnet_init (gchar * config_file)
+{
+	GIOChannel *channel = NULL;
+	gchar *line;
+
+	/* Handle multiple lines with brackets */
+	gboolean complete = TRUE;
+
+	/* line buffer */
+	GString *buf;
+
+	net_parser_data_changed = FALSE;
+
+	conn_table = g_hash_table_new (g_str_hash, g_str_equal);
+	global_settings_table = g_hash_table_new (g_str_hash, g_str_equal);
+	functions_list = NULL;
+
+	if (g_file_test (config_file, G_FILE_TEST_IS_REGULAR))
+		channel = g_io_channel_new_file (config_file, "r", NULL);
+	if (channel == NULL) {
+		PLUGIN_WARN (IFNET_PLUGIN_NAME,
+			     "Error: Can't open %s\n", config_file);
+		return FALSE;
+	}
+
+	buf = g_string_new (NULL);
+	while (g_io_channel_read_line
+	       (channel, &line, NULL, NULL, NULL) != G_IO_STATUS_EOF) {
+		g_strstrip (line);
+		/* convert multiple lines to a complete line and
+		 * pass it to init_block_by_line() */
+		if (is_function (line)) {
+			strip_function (channel, line);
+			continue;
+		}
+		if (line[0] != '#' && line[0] != '\0') {
+			gchar *pos = NULL;
+
+			if (!complete) {
+				complete =
+				    g_strrstr (line,
+					       ")") == NULL ? FALSE : TRUE;
+				if ((pos = strchr (line, '#')) != NULL)
+					*pos = '\0';
+				g_strstrip (line);
+				if (line[0] != '\0') {
+					g_string_append_printf (buf,
+								" %s", line);
+				}
+				g_free (line);
+				if (!complete)
+					continue;
+			} else {
+				complete =
+				    (g_strrstr (line, "(") != NULL
+				     && g_strrstr (line, ")") != NULL)
+				    || g_strrstr (line, "(") == NULL;
+				if ((pos = strchr (line, '#')) != NULL)
+					*pos = '\0';
+				g_strstrip (line);
+				if (line[0] != '\0')
+					g_string_append (buf, line);
+				g_free (line);
+				if (!complete)
+					continue;
+			}
+			init_block_by_line (buf->str);
+			g_string_free (buf, TRUE);
+			buf = g_string_new (NULL);
+		} else
+			/* Blank line or comment line */
+			g_free (line);
+	}
+
+	g_string_free (buf, TRUE);
+	g_io_channel_shutdown (channel, FALSE, NULL);
+	g_io_channel_unref (channel);
+	return TRUE;
+}
+
+const char *
+ifnet_get_data (const char *conn_name, const char *key)
+{
+	GHashTable *conn = g_hash_table_lookup (conn_table, conn_name);
+
+	if (conn)
+		return g_hash_table_lookup (conn, key);
+	return NULL;
+}
+
+void
+ifnet_set_data (const char *conn_name, const char *key, const char *value)
+{
+	gpointer old_key = NULL, old_value = NULL;
+	GHashTable *conn = g_hash_table_lookup (conn_table, conn_name);
+	gchar * stripped = NULL;
+
+	if (!conn) {
+		PLUGIN_WARN (IFNET_PLUGIN_NAME, "%s does not exsit!", conn_name);
+		return;
+	}
+	if (value){
+		stripped = g_strdup (value);
+		strip_string (stripped, '"');
+	}
+	/* Remove existing key value pair */
+	if (g_hash_table_lookup_extended (conn, key, &old_key, &old_value)) {
+		if (stripped && !strcmp(old_value, stripped)){
+			g_free (stripped);
+			return;
+		}
+		g_hash_table_remove (conn, old_key);
+		g_free (old_key);
+		g_free (old_value);
+	} else if (!value)
+		return;
+	if (stripped)
+		g_hash_table_insert (conn, g_strdup (key), stripped);
+	net_parser_data_changed = TRUE;
+}
+
+// Remember to free return value
+const char *
+ifnet_get_global_data (const gchar * key)
+{
+	return g_hash_table_lookup (global_settings_table, key);
+}
+
+// Return names of legal connections
+GList *
+ifnet_get_connection_names (void)
+{
+	GList *names = g_hash_table_get_keys (conn_table);
+	GList *result = NULL;
+
+	while (names) {
+		if (!ignore_connection_name (names->data))
+			result = g_list_prepend (result, names->data);
+		names = names->next;
+	}
+	g_list_free (names);
+	return g_list_reverse (result);
+}
+
+/* format IP and route for writing */
+static void
+format_ips (gchar * value, gchar ** out_line, gchar * key, gchar * name)
+{
+	gchar **ipset;
+	guint length, i;
+	GString *formated_string = g_string_new (NULL);
+
+	strip_string (value, '"');
+	ipset = g_strsplit (value, "\" \"", 0);
+	length = g_strv_length (ipset);
+
+	//only one line
+	if (length < 2) {
+		*out_line =
+		    g_strdup_printf ("%s_%s=( \"%s\" )\n", key, name, value);
+		goto done;
+	}
+	// Multiple lines
+	g_string_append_printf (formated_string, "%s_%s=(\n", key, name);
+	for (i = 0; i < length; i++)
+		g_string_append_printf (formated_string,
+					"\t\"%s\"\n", ipset[i]);
+	g_string_append (formated_string, ")\n");
+	*out_line = g_strdup (formated_string->str);
+done:
+	g_string_free (formated_string, TRUE);
+	g_strfreev (ipset);
+}
+
+gboolean
+ifnet_flush_to_file (const char *config_file)
+{
+	GIOChannel *channel;
+	GError **error = NULL;
+	gpointer key, value, name, network;
+	GHashTableIter iter, iter_network;
+	GList *list_iter;
+	gchar *out_line;
+	gsize bytes_written;
+	gboolean result = FALSE;
+
+	if (!net_parser_data_changed)
+		return TRUE;
+	if (!conn_table || !global_settings_table)
+		return FALSE;
+
+	channel = g_io_channel_new_file (config_file, "w", NULL);
+	if (!channel) {
+		PLUGIN_WARN (IFNET_PLUGIN_NAME,
+			     "Can't open file %s for writing", config_file);
+		return FALSE;
+	}
+	g_hash_table_iter_init (&iter, global_settings_table);
+	PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Writing to %s", config_file);
+	g_io_channel_write_chars (channel,
+				  "#Generated by NetworkManager\n"
+				  "###### Global Configuration ######\n",
+				  -1, &bytes_written, error);
+	/* Writing global data */
+	while (g_hash_table_iter_next (&iter, &key, &value)) {
+		out_line =
+		    g_strdup_printf ("%s=%s\n", (gchar *) key, (gchar *) value);
+		g_io_channel_write_chars (channel, out_line, -1,
+					  &bytes_written, error);
+		if (bytes_written == 0 || (error && *error))
+			break;
+		g_free (out_line);
+	}
+	if (error && *error) {
+		PLUGIN_WARN (IFNET_PLUGIN_NAME,
+			     "Found error: %s", (*error)->message);
+		goto done;
+	}
+
+	/* Writing connection data */
+	g_io_channel_write_chars (channel,
+				  "\n###### Connection Configuration ######\n",
+				  -1, &bytes_written, error);
+	g_hash_table_iter_init (&iter, conn_table);
+	while (g_hash_table_iter_next (&iter, &name, &network)) {
+		g_hash_table_iter_init (&iter_network, (GHashTable *) network);
+		g_io_channel_write_chars (channel,
+					  "#----------------------------------\n",
+					  -1, &bytes_written, error);
+
+		while (g_hash_table_iter_next (&iter_network, &key, &value)) {
+			if (!g_str_has_prefix ((gchar *) key, "name")
+			    && !g_str_has_prefix ((gchar *) key, "type")) {
+				/* These keys contain brackets */
+				if (strcmp
+				    ((gchar *) key,
+				     "config") == 0
+				    || strcmp ((gchar *) key,
+					       "routes") == 0
+				    || strcmp ((gchar *) key,
+					       "pppd") == 0
+				    || strcmp ((gchar *) key, "chat") == 0)
+					format_ips (value, &out_line, (gchar *)
+						    key, (gchar *)
+						    name);
+				else
+					out_line =
+					    g_strdup_printf
+					    ("%s_%s=\"%s\"\n",
+					     (gchar *) key,
+					     (gchar *) name, (gchar *) value);
+				g_io_channel_write_chars
+				    (channel, out_line, -1,
+				     &bytes_written, error);
+				if (bytes_written == 0 || (error && *error))
+					break;
+				g_free (out_line);
+			}
+		}
+	}
+	if (error && *error) {
+		PLUGIN_WARN (IFNET_PLUGIN_NAME,
+			     "Found error: %s", (*error)->message);
+		goto done;
+	}
+
+	/* Writing reserved functions */
+	if (functions_list) {
+		g_io_channel_write_chars (channel,
+					  "\n###### Reserved Functions ######\n",
+					  -1, &bytes_written, error);
+		/* Writing functions */
+		for (list_iter = functions_list; list_iter;
+		     list_iter = g_list_next (list_iter)) {
+			out_line =
+			    g_strdup_printf ("%s\n", (gchar *) list_iter->data);
+			g_io_channel_write_chars (channel, out_line, -1,
+						  &bytes_written, error);
+			if (bytes_written == 0 || (error && *error))
+				break;
+			g_free (out_line);
+		}
+		if (error && *error) {
+			PLUGIN_WARN (IFNET_PLUGIN_NAME,
+				     "Found error: %s", (*error)->message);
+			goto done;
+		}
+	}
+
+	g_io_channel_flush (channel, error);
+	if (error && *error) {
+		PLUGIN_WARN (IFNET_PLUGIN_NAME,
+			     "Found error: %s", (*error)->message);
+		goto done;
+	}
+	result = TRUE;
+	net_parser_data_changed = FALSE;
+done:
+	g_io_channel_shutdown (channel, FALSE, NULL);
+	g_io_channel_unref (channel);
+	return result;
+}
+
+gboolean
+ifnet_delete_network (const char *conn_name)
+{
+	GHashTable *network = NULL;
+
+	g_return_val_if_fail (conn_table != NULL && conn_name != NULL, FALSE);
+	PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Deleting network for %s", conn_name);
+	network = g_hash_table_lookup (conn_table, conn_name);
+	if (!network)
+		return FALSE;
+	g_hash_table_remove (conn_table, conn_name);
+	destroy_connection_config (network);
+	net_parser_data_changed = TRUE;
+	return TRUE;
+}
+
+void
+ifnet_destroy (void)
+{
+	GHashTableIter iter;
+	gpointer key;
+	gpointer value;
+	GList *list_iter;
+
+	/* Destroy connection setting */
+	if (conn_table) {
+		g_hash_table_iter_init (&iter, conn_table);
+		while (g_hash_table_iter_next (&iter, &key, &value)) {
+			destroy_connection_config ((GHashTable *)
+						   value);
+		}
+		g_hash_table_destroy (conn_table);
+		conn_table = NULL;
+	}
+
+	/* Destroy global data */
+	if (global_settings_table) {
+		g_hash_table_iter_init (&iter, global_settings_table);
+		while (g_hash_table_iter_next (&iter, &key, &value)) {
+			g_free (key);
+			g_free (value);
+		}
+		g_hash_table_destroy (global_settings_table);
+		global_settings_table = NULL;
+	}
+	for (list_iter = functions_list; list_iter;
+	     list_iter = g_list_next (list_iter))
+		g_free (list_iter->data);
+	g_list_free (functions_list);
+}
diff --git a/src/settings/plugins/ifnet/net_parser.h b/src/settings/plugins/ifnet/net_parser.h
new file mode 100644
index 00000000..0411e939
--- /dev/null
+++ b/src/settings/plugins/ifnet/net_parser.h
@@ -0,0 +1,46 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Mu Qiao <qiaomuf@gmail.com>
+ *
+ * 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) 1999-2010 Gentoo Foundation, Inc.
+ */
+
+#ifndef _NET_PARSER_H
+#define _NET_PARSER_H
+
+#include <glib.h>
+
+#define CONF_NET_FILE "/etc/conf.d/net"
+#define IFNET_SYSTEM_SETTINGS_KEY_FILE "/etc/NetworkManager/nm-system-settings.conf"
+#define IFNET_KEY_FILE_GROUP "ifnet"
+
+gboolean ifnet_init (gchar * config_file);
+void ifnet_destroy (void);
+
+/* Reader functions */
+GList *ifnet_get_connection_names (void);
+const char *ifnet_get_data (const char *conn_name, const char *key);
+const char *ifnet_get_global_data (const char *key);
+const char *ifnet_get_global_setting (const char *group, const char *key);
+gboolean ifnet_has_network (const char *conn_name);
+
+/* Writer functions */
+gboolean ifnet_flush_to_file (const char *config_file);
+void ifnet_set_data (const char *conn_name, const char *key, const char *value);
+gboolean ifnet_add_network (const char *name, const char *type);
+gboolean ifnet_delete_network (const char *conn_name);
+#endif
diff --git a/src/settings/plugins/ifnet/net_utils.c b/src/settings/plugins/ifnet/net_utils.c
new file mode 100644
index 00000000..83f86ab5
--- /dev/null
+++ b/src/settings/plugins/ifnet/net_utils.c
@@ -0,0 +1,974 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Mu Qiao <qiaomuf@gmail.com>
+ *
+ * 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) 1999-2010 Gentoo Foundation, Inc.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <nm-utils.h>
+#include <nm-system-config-interface.h>
+#include "net_utils.h"
+#include "wpa_parser.h"
+#include "net_parser.h"
+
+/* emit heading and tailing blank space, tab, character t */
+gchar *
+strip_string (gchar * str, gchar t)
+{
+	gchar *ret = str;
+	gint length = 0;
+	guint i = 0;
+
+	while (ret[i] != '\0'
+	       && (ret[i] == '\t' || ret[i] == ' ' || ret[i] == t)) {
+		length++;
+		i++;
+	}
+	i = 0;
+	while (ret[i + length] != '\0') {
+		ret[i] = ret[i + length];
+		i++;
+	}
+	ret[i] = '\0';
+	length = strlen (ret);
+	while ((length - 1) >= 0
+	       && (ret[length - 1] == ' ' || ret[length - 1] == '\n'
+		   || ret[length - 1] == '\t' || ret[length - 1] == t))
+		length--;
+	ret[length] = '\0';
+	return ret;
+}
+
+gboolean
+is_hex (const char *value)
+{
+	const char *p = value;
+
+	if (!p)
+		return FALSE;
+	while (*p) {
+		if (!isxdigit (*p++))
+			return FALSE;
+	}
+	return TRUE;
+}
+
+gboolean
+is_ascii (const char *value)
+{
+	const char *p = value;
+
+	while (*p) {
+		if (!isascii (*p++))
+			return FALSE;
+	}
+	return TRUE;
+
+}
+
+gboolean
+is_true (const char *str)
+{
+	if (!g_ascii_strcasecmp (str, "yes")
+	    || !g_ascii_strcasecmp (str, "true"))
+		return TRUE;
+	return FALSE;
+}
+
+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;
+}
+
+/* free return value by caller */
+gchar *
+utils_hexstr2bin (const gchar * hex, size_t len)
+{
+	size_t i;
+	int a;
+	const gchar *ipos = hex;
+	gchar *buf = NULL;
+	gchar *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;
+}
+
+/* free return value by caller */
+gchar *
+utils_bin2hexstr (const gchar * bytes, int len, int final_len)
+{
+	static gchar hex_digits[] = "0123456789abcdef";
+	gchar *result;
+	int i;
+	gsize buflen = (len * 2) + 1;
+
+	g_return_val_if_fail (bytes != NULL, NULL);
+	g_return_val_if_fail (len > 0, NULL);
+	g_return_val_if_fail (len < 4096, NULL);	/* Arbitrary limit */
+	if (final_len > -1)
+		g_return_val_if_fail (final_len < buflen, NULL);
+
+	result = g_malloc0 (buflen);
+	for (i = 0; i < len; i++) {
+		result[2 * i] = hex_digits[(bytes[i] >> 4) & 0xf];
+		result[2 * i + 1] = hex_digits[bytes[i] & 0xf];
+	}
+	/* Cut converted key off at the correct length for this cipher type */
+	if (final_len > -1)
+		result[final_len] = '\0';
+	else
+		result[buflen - 1] = '\0';
+
+	return result;
+}
+
+GQuark
+ifnet_plugin_error_quark (void)
+{
+	static GQuark error_quark = 0;
+
+	if (G_UNLIKELY (error_quark == 0))
+		error_quark =
+		    g_quark_from_static_string ("ifnet-plugin-error-quark");
+	return error_quark;
+}
+
+static char *
+find_default_gateway_str (char *str)
+{
+	char *tmp;
+
+	if ((tmp = strstr (str, "default via ")) != NULL) {
+		return tmp + strlen ("default via ");
+	} else if ((tmp = strstr (str, "default gw ")) != NULL) {
+		return tmp + strlen ("default gw ");
+	}
+	return NULL;
+}
+
+static char *
+find_gateway_str (char *str)
+{
+	char *tmp;
+
+	if ((tmp = strstr (str, "via ")) != NULL) {
+		return tmp + strlen ("via ");
+	} else if ((tmp = strstr (str, "gw ")) != NULL) {
+		return tmp + strlen ("gw ");
+	}
+	return NULL;
+}
+
+gboolean
+reload_parsers (void)
+{
+	ifnet_destroy ();
+	wpa_parser_destroy ();
+	if (!ifnet_init (CONF_NET_FILE))
+		return FALSE;
+	wpa_parser_init (WPA_SUPPLICANT_CONF);
+	return TRUE;
+}
+
+gchar *
+read_hostname (const char *path)
+{
+	gchar *contents = NULL, *result = NULL, *tmp;
+	gchar **all_lines = NULL;
+	guint line_num, i;
+
+	if (!g_file_get_contents (path, &contents, NULL, NULL))
+		return NULL;
+	all_lines = g_strsplit (contents, "\n", 0);
+	line_num = g_strv_length (all_lines);
+	for (i = 0; i < line_num; i++) {
+		g_strstrip (all_lines[i]);
+		if (all_lines[i][0] == '#' || all_lines[i][0] == '\0')
+			continue;
+		if (g_str_has_prefix (all_lines[i], "hostname")) {
+			tmp = strstr (all_lines[i], "=");
+			tmp++;
+			tmp = strip_string (tmp, '"');
+			result = g_strdup (tmp);
+			break;
+		}
+
+	}
+	g_strfreev (all_lines);
+	g_free (contents);
+	return result;
+}
+
+gboolean
+write_hostname (const gchar *hostname, const char *path)
+{
+	gboolean result;
+	char *contents;
+
+	contents = g_strdup_printf ("#Generated by NetworkManager\n"
+	                            "hostname=\"%s\"\n", hostname);
+	result = g_file_set_contents (path, contents, -1, NULL);
+	g_free (contents);
+	return result;
+}
+
+gboolean
+is_static_ip4 (const char *conn_name)
+{
+	const char *data = ifnet_get_data (conn_name, "config");
+	const char *dhcp6;
+
+	if (!data)
+		return FALSE;
+	if (!strcmp (data, "shared"))
+		return FALSE;
+	if (!strcmp (data, "autoip"))
+		return FALSE;
+	dhcp6 = strstr (data, "dhcp6");
+	if (dhcp6) {
+		gchar *dhcp4;
+
+		if (strstr (data, "dhcp "))
+			return FALSE;
+		dhcp4 = strstr (data, "dhcp");
+		if (!dhcp4)
+			return TRUE;
+		if (dhcp4[4] == '\0')
+			return FALSE;
+		return TRUE;
+	}
+	return strstr (data, "dhcp") == NULL ? TRUE : FALSE;
+}
+
+gboolean
+is_static_ip6 (const char *conn_name)
+{
+	const char *data = ifnet_get_data (conn_name, "config");
+
+	if (!data)
+		return TRUE;
+	return strstr (data, "dhcp6") == NULL ? TRUE : FALSE;
+}
+
+gboolean
+is_ip4_address (const char *in_address)
+{
+	const char *pattern =
+	    "\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.((\\{\\d{1,3}\\.\\.\\d{1,3}\\})|\\d{1,3})$";
+	gchar *address = g_strdup (in_address);
+	gboolean result = FALSE;
+	gchar *tmp;
+	GRegex *regex = g_regex_new (pattern, 0, 0, NULL);
+	GMatchInfo *match_info;
+
+	if (!address)
+		goto done;
+	g_strstrip (address);
+	if ((tmp = strstr (address, "/")) != NULL)
+		*tmp = '\0';
+	if ((tmp = strstr (address, " ")) != NULL)
+		*tmp = '\0';
+	g_regex_match (regex, address, 0, &match_info);
+	result = g_match_info_matches (match_info);
+done:
+	if (match_info)
+		g_match_info_free (match_info);
+	g_regex_unref (regex);
+	g_free (address);
+	return result;
+}
+
+gboolean
+is_ip6_address (const char *in_address)
+{
+	struct in6_addr tmp_ip6_addr;
+	gchar *tmp, *address;
+	gboolean result = FALSE;
+
+	if (!in_address)
+		return FALSE;
+	address = g_strdup (in_address);
+	g_strstrip (address);
+	if ((tmp = strchr (address, '/')) != NULL)
+		*tmp = '\0';
+	if (inet_pton (AF_INET6, address, &tmp_ip6_addr))
+		result = TRUE;
+	g_free (address);
+	return result;
+
+}
+
+gboolean
+has_ip6_address (const char *conn_name)
+{
+	gchar **ipset;
+	guint length;
+	guint i;
+
+	g_return_val_if_fail (conn_name != NULL, FALSE);
+	ipset = g_strsplit (ifnet_get_data (conn_name, "config"), "\" \"", 0);
+	length = g_strv_length (ipset);
+	for (i = 0; i < length; i++) {
+		if (!is_ip6_address (ipset[i]))
+			continue;
+		else {
+			g_strfreev (ipset);
+			return TRUE;
+		}
+
+	}
+	g_strfreev (ipset);
+	return FALSE;
+}
+
+gboolean
+has_default_route (const char *conn_name, gboolean (*check_fn) (const char *))
+{
+	char *routes = NULL, *end, *tmp;
+	gboolean success = FALSE;
+
+	g_return_val_if_fail (conn_name != NULL, FALSE);
+
+	routes = g_strdup (ifnet_get_data (conn_name, "routes"));
+	if (!routes)
+		return FALSE;
+	tmp = find_default_gateway_str (routes);
+	if (tmp) {
+		g_strstrip (tmp);
+		if ((end = strstr (tmp, "\"")) != NULL)
+			*end = '\0';
+		if (check_fn (tmp))
+			success = TRUE;
+	}
+
+	g_free (routes);
+	return success;
+}
+
+static ip_block *
+create_ip4_block (gchar * ip)
+{
+	ip_block *iblock = g_slice_new0 (ip_block);
+	struct in_addr tmp_ip4_addr;
+	int i;
+	guint length;
+	gchar **ip_mask;
+
+	/* prefix format */
+	if (strstr (ip, "/")) {
+		gchar *prefix;
+
+		ip_mask = g_strsplit (ip, "/", 0);
+		length = g_strv_length (ip_mask);
+		if (!inet_pton (AF_INET, ip_mask[0], &tmp_ip4_addr))
+			goto error;
+		iblock->ip = tmp_ip4_addr.s_addr;
+		prefix = ip_mask[1];
+		i = 0;
+		while (i < length && isdigit (prefix[i]))
+			i++;
+		prefix[i] = '\0';
+		iblock->netmask = nm_utils_ip4_prefix_to_netmask ((guint32)
+								  atoi (ip_mask
+									[1]));
+	} else if (strstr (ip, "netmask")) {
+		ip_mask = g_strsplit (ip, " ", 0);
+		length = g_strv_length (ip_mask);
+		if (!inet_pton (AF_INET, ip_mask[0], &tmp_ip4_addr))
+			goto error;
+		iblock->ip = tmp_ip4_addr.s_addr;
+		i = 0;
+		while (i < length && !strstr (ip_mask[++i], "netmask")) ;
+		while (i < length && ip_mask[++i][0] == '\0') ;
+		if (i >= length)
+			goto error;
+		if (!inet_pton (AF_INET, ip_mask[i], &tmp_ip4_addr))
+			goto error;
+		iblock->netmask = tmp_ip4_addr.s_addr;
+	} else {
+		g_slice_free (ip_block, iblock);
+		if (!is_ip6_address (ip) && !strstr (ip, "dhcp"))
+			PLUGIN_WARN (IFNET_PLUGIN_NAME,
+				     "Can't handle ipv4 address: %s, missing netmask or prefix",
+				     ip);
+		return NULL;
+	}
+	g_strfreev (ip_mask);
+	return iblock;
+error:
+	if (!is_ip6_address (ip))
+		PLUGIN_WARN (IFNET_PLUGIN_NAME, "Can't handle IPv4 address: %s",
+			     ip);
+	g_strfreev (ip_mask);
+	g_slice_free (ip_block, iblock);
+	return NULL;
+}
+
+static ip6_block *
+create_ip6_block (gchar * ip)
+{
+	ip6_block *iblock = g_slice_new0 (ip6_block);
+	gchar *dup_ip = g_strdup (ip);
+	struct in6_addr *tmp_ip6_addr = g_slice_new0 (struct in6_addr);
+	gchar *prefix = NULL;
+
+	if ((prefix = strstr (dup_ip, "/")) != NULL) {
+		*prefix = '\0';
+		prefix++;
+	}
+	if (!inet_pton (AF_INET6, dup_ip, tmp_ip6_addr)) {
+		goto error;
+	}
+	iblock->ip = tmp_ip6_addr;
+	if (prefix) {
+		errno = 0;
+		iblock->prefix = strtol (prefix, NULL, 10);
+		if (errno || iblock->prefix <= 0 || iblock->prefix > 128) {
+			goto error;
+		}
+	} else
+		iblock->prefix = 64;
+	g_free (dup_ip);
+	return iblock;
+error:
+	if (!is_ip4_address (ip))
+		PLUGIN_WARN (IFNET_PLUGIN_NAME, "Can't handle IPv6 address: %s",
+			     ip);
+	g_slice_free (ip6_block, iblock);
+	g_slice_free (struct in6_addr, tmp_ip6_addr);
+
+	g_free (dup_ip);
+	return NULL;
+}
+
+static guint32
+get_ip4_gateway (gchar * gateway)
+{
+	gchar *tmp, *split;
+	struct in_addr tmp_ip4_addr;
+
+	if (!gateway)
+		return 0;
+	tmp = find_gateway_str (gateway);
+	if (!tmp) {
+		PLUGIN_WARN (IFNET_PLUGIN_NAME,
+			     "Couldn't obtain gateway in \"%s\"", gateway);
+		return 0;
+	}
+	tmp = g_strdup (tmp);
+	strip_string (tmp, ' ');
+	strip_string (tmp, '"');
+	if ((split = strstr (tmp, "\"")) != NULL)
+		*split = '\0';
+	if (!inet_pton (AF_INET, tmp, &tmp_ip4_addr))
+		goto error;
+	g_free (tmp);
+	return tmp_ip4_addr.s_addr;
+error:
+	if (!is_ip6_address (tmp))
+		PLUGIN_WARN (IFNET_PLUGIN_NAME, "Can't handle IPv4 gateway: %s",
+			     tmp);
+	g_free (tmp);
+	return 0;
+}
+
+static struct in6_addr *
+get_ip6_next_hop (gchar * next_hop)
+{
+	gchar *tmp;
+	struct in6_addr *tmp_ip6_addr = g_slice_new0 (struct in6_addr);
+
+	if (!next_hop)
+		return 0;
+	tmp = find_gateway_str (next_hop);
+	if (!tmp) {
+		PLUGIN_WARN (IFNET_PLUGIN_NAME,
+			     "Couldn't obtain next_hop in \"%s\"", next_hop);
+		return 0;
+	}
+	tmp = g_strdup (tmp);
+	strip_string (tmp, ' ');
+	strip_string (tmp, '"');
+	g_strstrip (tmp);
+	if (!inet_pton (AF_INET6, tmp, tmp_ip6_addr))
+		goto error;
+	g_free (tmp);
+	return tmp_ip6_addr;
+error:
+	if (!is_ip4_address (tmp))
+		PLUGIN_WARN (IFNET_PLUGIN_NAME,
+			     "Can't handle IPv6 next_hop: %s", tmp);
+	g_free (tmp);
+	g_slice_free (struct in6_addr, tmp_ip6_addr);
+
+	return NULL;
+}
+
+ip_block *
+convert_ip4_config_block (const char *conn_name)
+{
+	gchar **ipset;
+	guint length;
+	guint i;
+	gchar *ip;
+	guint32 def_gateway = 0;
+	const char *routes;
+	gchar *pos;
+	ip_block *start = NULL, *current = NULL, *iblock = NULL;
+	const char *pattern =
+	    "((\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.)\\{(\\d{1,3})\\.\\.(\\d{1,3})\\}(/\\d{1,2}))";
+
+	g_return_val_if_fail (conn_name != NULL, NULL);
+
+	ipset = g_strsplit (ifnet_get_data (conn_name, "config"), "\" \"", 0);
+	length = g_strv_length (ipset);
+
+	routes = ifnet_get_data (conn_name, "routes");
+	if (routes)
+		def_gateway = get_ip4_gateway (strstr (routes, "default"));
+
+	for (i = 0; i < length; i++) {
+		ip = ipset[i];
+		ip = strip_string (ip, '"');
+		//Handle ip like 192.168.4.{1..3}
+		if ((pos = strchr (ip, '{')) != NULL) {
+			gchar *ip_start, *ip_prefix;
+			gchar *begin_str, *end_str;
+			int begin, end, j;
+			GRegex *regex;
+			GMatchInfo *match_info;
+
+			regex = g_regex_new (pattern, 0, 0, NULL);
+			g_regex_match (regex, ip, 0, &match_info);
+			g_regex_unref (regex);
+
+			if (!g_match_info_matches (match_info)) {
+				g_match_info_free (match_info);
+				continue;
+			}
+			begin_str = g_match_info_fetch (match_info, 3);
+			end_str = g_match_info_fetch (match_info, 4);
+			begin = atoi (begin_str);
+			end = atoi (end_str);
+			ip_start = g_match_info_fetch (match_info, 2);
+			ip_prefix = g_match_info_fetch (match_info, 5);
+			if (end < begin || begin < 1 || end > 254) {
+				g_match_info_free (match_info);
+				continue;
+			}
+
+			for (j = begin; j <= end; j++) {
+				char suf[4];
+				gchar *newip;
+
+				sprintf (suf, "%d", j);
+				newip =
+				    g_strconcat (ip_start, suf, ip_prefix,
+						 NULL);
+				iblock = create_ip4_block (newip);
+				if (iblock == NULL) {
+					g_free (newip);
+					continue;
+				}
+				if (!iblock->gateway && def_gateway != 0)
+					iblock->gateway = def_gateway;
+				if (start == NULL)
+					start = current = iblock;
+				else {
+					current->next = iblock;
+					current = iblock;
+				}
+				g_free (newip);
+			}
+			g_free (begin_str);
+			g_free (end_str);
+			g_free (ip_start);
+			g_free (ip_prefix);
+			g_match_info_free (match_info);
+		} else {
+			iblock = create_ip4_block (ip);
+			if (iblock == NULL)
+				continue;
+			if (!iblock->gateway && def_gateway != 0)
+				iblock->gateway = def_gateway;
+			if (start == NULL)
+				start = current = iblock;
+			else {
+				current->next = iblock;
+				current = iblock;
+			}
+		}
+	}
+	g_strfreev (ipset);
+	return start;
+}
+
+ip6_block *
+convert_ip6_config_block (const char *conn_name)
+{
+	gchar **ipset;
+	guint length;
+	guint i;
+	gchar *ip;
+	ip6_block *start = NULL, *current = NULL, *iblock = NULL;
+
+	g_return_val_if_fail (conn_name != NULL, NULL);
+	ipset = g_strsplit (ifnet_get_data (conn_name, "config"), "\" \"", 0);
+	length = g_strv_length (ipset);
+	for (i = 0; i < length; i++) {
+		ip = ipset[i];
+		ip = strip_string (ip, '"');
+		iblock = create_ip6_block (ip);
+		if (iblock == NULL)
+			continue;
+		if (start == NULL)
+			start = current = iblock;
+		else {
+			current->next = iblock;
+			current = iblock;
+		}
+	}
+	g_strfreev (ipset);
+	return start;
+}
+
+ip_block *
+convert_ip4_routes_block (const char *conn_name)
+{
+	gchar **ipset;
+	guint length;
+	guint i;
+	gchar *ip;
+	const char *routes;
+	ip_block *start = NULL, *current = NULL, *iblock = NULL;
+
+	g_return_val_if_fail (conn_name != NULL, NULL);
+
+	routes = ifnet_get_data (conn_name, "routes");
+	if (!routes)
+		return NULL;
+	ipset = g_strsplit (routes, "\" \"", 0);
+	length = g_strv_length (ipset);
+	for (i = 0; i < length; i++) {
+		ip = ipset[i];
+		if (find_default_gateway_str (ip) || strstr (ip, "::")
+		    || !find_gateway_str (ip))
+			continue;
+		ip = strip_string (ip, '"');
+		iblock = create_ip4_block (ip);
+		if (iblock == NULL)
+			continue;
+		iblock->gateway = get_ip4_gateway (ip);
+		if (start == NULL)
+			start = current = iblock;
+		else {
+			current->next = iblock;
+			current = iblock;
+		}
+	}
+	g_strfreev (ipset);
+	return start;
+}
+
+ip6_block *
+convert_ip6_routes_block (const char *conn_name)
+{
+	gchar **ipset;
+	guint length;
+	guint i;
+	gchar *ip, *tmp_addr;
+	const char *routes;
+	ip6_block *start = NULL, *current = NULL, *iblock = NULL;
+	struct in6_addr *tmp_ip6_addr;
+
+	g_return_val_if_fail (conn_name != NULL, NULL);
+	routes = ifnet_get_data (conn_name, "routes");
+	if (!routes)
+		return NULL;
+	ipset = g_strsplit (routes, "\" \"", 0);
+	length = g_strv_length (ipset);
+	for (i = 0; i < length; i++) {
+		ip = ipset[i];
+		ip = strip_string (ip, '"');
+		if (ip[0] == '\0')
+			continue;
+		if ((tmp_addr = find_default_gateway_str (ip)) != NULL) {
+			if (!is_ip6_address (tmp_addr))
+				continue;
+			else {
+				tmp_ip6_addr = g_slice_new0 (struct in6_addr);
+
+				if (inet_pton (AF_INET6, "::", tmp_ip6_addr)) {
+					iblock = g_slice_new0 (ip6_block);
+					iblock->ip = tmp_ip6_addr;
+					iblock->prefix = 128;
+				} else {
+					g_slice_free (struct in6_addr,
+						      tmp_ip6_addr);
+					continue;
+				}
+			}
+		} else
+			iblock = create_ip6_block (ip);
+		if (iblock == NULL)
+			continue;
+		iblock->next_hop = get_ip6_next_hop (ip);
+		if (iblock->next_hop == NULL) {
+			destroy_ip6_block (iblock);
+			continue;
+		}
+		if (start == NULL)
+			start = current = iblock;
+		else {
+			current->next = iblock;
+			current = iblock;
+		}
+	}
+	g_strfreev (ipset);
+	return start;
+}
+
+void
+destroy_ip_block (ip_block * iblock)
+{
+	g_slice_free (ip_block, iblock);
+}
+
+void
+destroy_ip6_block (ip6_block * iblock)
+{
+	g_slice_free (struct in6_addr, iblock->ip);
+	g_slice_free (struct in6_addr, iblock->next_hop);
+
+	g_slice_free (ip6_block, iblock);
+}
+
+void
+set_ip4_dns_servers (NMSettingIP4Config *s_ip4, const char *conn_name)
+{
+	const char *dns_servers;
+	gchar **server_list, *stripped;
+	guint length, i;
+	struct in_addr tmp_ip4_addr;
+	guint32 new_dns;
+
+	dns_servers = ifnet_get_data (conn_name, "dns_servers");
+	if (!dns_servers)
+		return;
+	stripped = g_strdup (dns_servers);
+	strip_string (stripped, '"');
+	server_list = g_strsplit (stripped, " ", 0);
+	g_free (stripped);
+
+	length = g_strv_length (server_list);
+	if (length)
+		g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_IGNORE_AUTO_DNS,
+			      TRUE, NULL);
+	for (i = 0; i < length; i++) {
+		g_strstrip (server_list[i]);
+		if (server_list[i][0] == '\0')
+			continue;
+		if (!inet_pton (AF_INET, server_list[i], &tmp_ip4_addr)) {
+			if (!is_ip6_address (server_list[i]))
+				PLUGIN_WARN (IFNET_PLUGIN_NAME,
+					     "ignored dns: %s\n",
+					     server_list[i]);
+			continue;
+		}
+		new_dns = tmp_ip4_addr.s_addr;
+		if (new_dns && !nm_setting_ip4_config_add_dns (s_ip4, new_dns))
+			PLUGIN_WARN (IFNET_PLUGIN_NAME,
+				     "warning: duplicate DNS server %s",
+				     server_list[i]);
+	}
+	g_strfreev (server_list);
+}
+
+void
+set_ip6_dns_servers (NMSettingIP6Config *s_ip6, const char *conn_name)
+{
+	const char *dns_servers;
+	gchar **server_list, *stripped;
+	guint length, i;
+	struct in6_addr tmp_ip6_addr;
+
+	dns_servers = ifnet_get_data (conn_name, "dns_servers");
+	if (!dns_servers)
+		return;
+
+	stripped = g_strdup (dns_servers);
+	strip_string (stripped, '"');
+	server_list = g_strsplit (stripped, " ", 0);
+	g_free (stripped);
+
+	length = g_strv_length (server_list);
+	if (length)
+		g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_IGNORE_AUTO_DNS,
+			      TRUE, NULL);
+	for (i = 0; i < length; i++) {
+		g_strstrip (server_list[i]);
+		if (server_list[i][0] == '\0')
+			continue;
+		if (!inet_pton (AF_INET6, server_list[i], &tmp_ip6_addr)) {
+			if (is_ip6_address (server_list[i]))
+				PLUGIN_WARN (IFNET_PLUGIN_NAME,
+					     "ignored dns: %s\n",
+					     server_list[i]);
+			continue;
+		}
+		if (!IN6_IS_ADDR_UNSPECIFIED (&tmp_ip6_addr)
+		    && !nm_setting_ip6_config_add_dns (s_ip6, &tmp_ip6_addr))
+			PLUGIN_WARN (IFNET_PLUGIN_NAME,
+				     "warning: duplicate DNS server %s",
+				     server_list[i]);
+	}
+	g_strfreev (server_list);
+}
+
+gboolean
+is_managed (const char *conn_name)
+{
+	gchar *config;
+
+	g_return_val_if_fail (conn_name != NULL, FALSE);
+	config = (gchar *) ifnet_get_data (conn_name, "managed");
+	if (!config)
+		return TRUE;
+	if (strcmp (config, "false") == 0)
+		return FALSE;
+	return TRUE;
+}
+
+void
+get_dhcp_hostname_and_client_id (char **hostname, char **client_id)
+{
+	const char *dhcp_client;
+	const gchar *dhcpcd_conf = "/etc/dhcpcd.conf";
+	const gchar *dhclient_conf = "/etc/dhcp/dhclient.conf";
+	gchar *line = NULL, *tmp = NULL, *contents = NULL;
+	gchar **all_lines;
+	guint line_num, i;
+
+	*hostname = NULL;
+	*client_id = NULL;
+	dhcp_client = ifnet_get_global_setting ("main", "dhcp");
+	if (dhcp_client) {
+		if (!strcmp (dhcp_client, "dhclient"))
+			g_file_get_contents (dhclient_conf, &contents, NULL,
+					     NULL);
+		else if (!strcmp (dhcp_client, "dhcpcd"))
+			g_file_get_contents (dhcpcd_conf, &contents, NULL,
+					     NULL);
+	} else {
+		if (g_file_test (dhclient_conf, G_FILE_TEST_IS_REGULAR))
+			g_file_get_contents (dhclient_conf, &contents, NULL,
+					     NULL);
+		else if (g_file_test (dhcpcd_conf, G_FILE_TEST_IS_REGULAR))
+			g_file_get_contents (dhcpcd_conf, &contents, NULL,
+					     NULL);
+	}
+	if (!contents)
+		return;
+	all_lines = g_strsplit (contents, "\n", 0);
+	line_num = g_strv_length (all_lines);
+	for (i = 0; i < line_num; i++) {
+		line = all_lines[i];
+		// dhcpcd.conf
+		g_strstrip (line);
+		if (g_str_has_prefix (line, "hostname")) {
+			tmp = line + strlen ("hostname");
+			g_strstrip (tmp);
+			if (tmp[0] != '\0')
+				*hostname = g_strdup (tmp);
+			else
+				PLUGIN_PRINT (IFNET_PLUGIN_NAME,
+					      "dhcpcd hostname not defined, ignoring");
+		} else if (g_str_has_prefix (line, "clientid")) {
+			tmp = line + strlen ("clientid");
+			g_strstrip (tmp);
+			if (tmp[0] != '\0')
+				*client_id = g_strdup (tmp);
+			else
+				PLUGIN_PRINT (IFNET_PLUGIN_NAME,
+					      "dhcpcd clientid not defined, ignoring");
+		}
+		// dhclient.conf
+		else if ((tmp = strstr (line, "send host-name")) != NULL) {
+			tmp += strlen ("send host-name");
+			g_strstrip (tmp);
+			strip_string (tmp, ';');
+			strip_string (tmp, '"');
+			if (tmp[0] != '\0')
+				*hostname = g_strdup (tmp);
+			else
+				PLUGIN_PRINT (IFNET_PLUGIN_NAME,
+					      "dhclient hostname not defined, ignoring");
+		} else if ((tmp = strstr (line, "send dhcp-client-identifier"))
+			   != NULL) {
+			tmp += strlen ("send dhcp-client-identifier");
+			g_strstrip (tmp);
+			strip_string (tmp, ';');
+			if (tmp[0] != '\0')
+				*client_id = g_strdup (tmp);
+			else
+				PLUGIN_PRINT (IFNET_PLUGIN_NAME,
+					      "dhclient clientid not defined, ignoring");
+		}
+	}
+	g_strfreev (all_lines);
+	g_free (contents);
+}
diff --git a/src/settings/plugins/ifnet/net_utils.h b/src/settings/plugins/ifnet/net_utils.h
new file mode 100644
index 00000000..42f8d672
--- /dev/null
+++ b/src/settings/plugins/ifnet/net_utils.h
@@ -0,0 +1,80 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Mu Qiao <qiaomuf@gmail.com>
+ *
+ * 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) 1999-2010 Gentoo Foundation, Inc.
+ */
+
+#ifndef _IFNET_UTILS_H
+#define _IFNET_UTILS_H
+#define IFNET_PLUGIN_NAME "SCPlugin-Ifnet"
+#include <glib.h>
+#include <arpa/inet.h>
+#include <nm-setting-ip6-config.h>
+#include <nm-setting-ip4-config.h>
+#include "net_parser.h"
+#define has_default_ip4_route(conn_name) has_default_route((conn_name), &is_ip4_address)
+#define has_default_ip6_route(conn_name) has_default_route((conn_name), &is_ip6_address)
+
+typedef struct _ip_block {
+	guint32 ip;
+	guint32 netmask;
+	guint32 gateway;
+	struct _ip_block *next;
+} ip_block;
+
+typedef struct _ip6_block {
+	struct in6_addr *ip;
+	long int prefix;
+	struct in6_addr *next_hop;
+	struct _ip6_block *next;
+} ip6_block;
+
+gchar *read_hostname (const char *path);
+gboolean write_hostname (const char *hostname, const char *path);
+gboolean is_static_ip4 (const char *conn_name);
+gboolean is_static_ip6 (const char *conn_name);
+gboolean is_ip4_address (const char *in_address);
+gboolean is_ip6_address (const char *in_address);
+gboolean has_ip6_address (const char *conn_name);
+gboolean has_default_route (const char *conn_name, gboolean (*check_fn) (const char *));
+gboolean reload_parsers (void);
+
+ip_block *convert_ip4_config_block (const char *conn_name);
+ip6_block *convert_ip6_config_block (const char *conn_name);
+ip_block *convert_ip4_routes_block (const char *conn_name);
+ip6_block *convert_ip6_routes_block (const char *conn_name);
+void destroy_ip_block (ip_block * iblock);
+void destroy_ip6_block (ip6_block * iblock);
+
+void set_ip4_dns_servers (NMSettingIP4Config * s_ip4, const char *conn_name);
+void set_ip6_dns_servers (NMSettingIP6Config * s_ip6, const char *conn_name);
+
+gchar *strip_string (gchar *str, gchar t);
+gboolean is_managed (const char *conn_name);
+
+GQuark ifnet_plugin_error_quark (void);
+gchar *utils_hexstr2bin (const gchar * hex, size_t len);
+gchar *utils_bin2hexstr (const gchar * bytes, int len, int final_len);
+
+gboolean is_hex (const char *value);
+gboolean is_ascii (const char *value);
+gboolean is_true (const char *str);
+
+void get_dhcp_hostname_and_client_id (char **hostname, char **client_id);
+
+#endif
diff --git a/src/settings/plugins/ifnet/nm-ifnet-connection.c b/src/settings/plugins/ifnet/nm-ifnet-connection.c
new file mode 100644
index 00000000..8b7a153c
--- /dev/null
+++ b/src/settings/plugins/ifnet/nm-ifnet-connection.c
@@ -0,0 +1,191 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Mu Qiao <qiaomuf@gmail.com>
+ *
+ * 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) 1999-2010 Gentoo Foundation, Inc.
+ */
+
+#include <string.h>
+#include <glib/gstdio.h>
+#include <NetworkManager.h>
+#include <nm-utils.h>
+#include <nm-setting-wireless-security.h>
+#include <nm-settings-connection.h>
+#include <nm-system-config-interface.h>
+#include <nm-settings-error.h>
+#include "nm-ifnet-connection.h"
+#include "connection_parser.h"
+#include "net_parser.h"
+#include "net_utils.h"
+#include "wpa_parser.h"
+#include "plugin.h"
+
+G_DEFINE_TYPE (NMIfnetConnection, nm_ifnet_connection, NM_TYPE_SETTINGS_CONNECTION)
+
+#define NM_IFNET_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_IFNET_CONNECTION, NMIfnetConnectionPrivate))
+enum {
+	PROP_ZERO,
+	PROP_CONN_NAME,
+	_PROP_END,
+};
+
+enum {
+	IFNET_SETUP_MONITORS,
+	IFNET_CANCEL_MONITORS,
+	IFNET_LAST_SIGNAL
+};
+
+static guint signals[IFNET_LAST_SIGNAL] = { 0 };
+
+typedef struct {
+	gchar *conn_name;
+	NMSystemConfigInterface *config;
+} NMIfnetConnectionPrivate;
+
+NMIfnetConnection *
+nm_ifnet_connection_new (const char *conn_name, NMConnection *source)
+{
+	NMConnection *tmp;
+	GObject *object;
+	GError *error = NULL;
+
+	g_return_val_if_fail (conn_name != NULL, NULL);
+
+	if (source)
+		tmp = g_object_ref (source);
+	else {
+		tmp = ifnet_update_connection_from_config_block (conn_name, &error);
+		if (!tmp){
+			g_error_free (error);
+			return NULL;
+		}
+	}
+
+	object = (GObject *) g_object_new (NM_TYPE_IFNET_CONNECTION, NULL);
+	if (!object) {
+		g_object_unref (tmp);
+		return NULL;
+	}
+
+	NM_IFNET_CONNECTION_GET_PRIVATE (object)->conn_name = g_strdup (conn_name);
+	nm_settings_connection_replace_settings (NM_SETTINGS_CONNECTION (object), tmp, NULL);
+	g_object_unref (tmp);
+
+	return NM_IFNET_CONNECTION (object);
+}
+
+static void
+nm_ifnet_connection_init (NMIfnetConnection * connection)
+{
+}
+
+static void
+commit_changes (NMSettingsConnection *connection,
+                NMSettingsConnectionCommitFunc callback,
+	            gpointer user_data)
+{
+	GError *error = NULL;
+	NMIfnetConnectionPrivate *priv = NM_IFNET_CONNECTION_GET_PRIVATE (connection);
+	gchar *new_name = NULL;
+
+	g_signal_emit (connection, signals[IFNET_CANCEL_MONITORS], 0);
+	if (!ifnet_update_parsers_by_connection (NM_CONNECTION (connection),
+	                                         priv->conn_name,
+	                                         CONF_NET_FILE,
+	                                         WPA_SUPPLICANT_CONF,
+	                                         &new_name,
+	                                         &error)) {
+		PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Failed to update %s", priv->conn_name);
+		reload_parsers ();
+		callback (connection, error, user_data);
+		g_error_free (error);
+		g_signal_emit (connection, signals[IFNET_SETUP_MONITORS], 0);
+		return;
+	}
+
+	g_free (priv->conn_name);
+	priv->conn_name = new_name;
+
+	NM_SETTINGS_CONNECTION_CLASS (nm_ifnet_connection_parent_class)->commit_changes (connection, callback, user_data);
+	PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Successfully updated %s", priv->conn_name);
+
+	g_signal_emit (connection, signals[IFNET_SETUP_MONITORS], 0);
+}
+
+static void 
+do_delete (NMSettingsConnection *connection,
+	       NMSettingsConnectionDeleteFunc callback,
+	       gpointer user_data)
+{
+	GError *error = NULL;
+	NMIfnetConnectionPrivate *priv = NM_IFNET_CONNECTION_GET_PRIVATE (connection);
+
+	g_signal_emit (connection, signals[IFNET_CANCEL_MONITORS], 0);
+	if (!ifnet_delete_connection_in_parsers
+	    (priv->conn_name, CONF_NET_FILE, WPA_SUPPLICANT_CONF)) {
+		PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Failed to delete %s",
+			      priv->conn_name);
+		reload_parsers ();
+		callback (connection, error, user_data);
+		g_error_free (error);
+		g_signal_emit (connection, signals[IFNET_SETUP_MONITORS], 0);
+		return;
+	}
+
+	NM_SETTINGS_CONNECTION_CLASS (nm_ifnet_connection_parent_class)->delete (connection, callback, user_data);
+
+	PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Successfully deleted %s",
+		      priv->conn_name);
+	g_signal_emit (connection, signals[IFNET_SETUP_MONITORS], 0);
+}
+
+static void
+finalize (GObject * object)
+{
+	NMIfnetConnectionPrivate *priv =
+	    NM_IFNET_CONNECTION_GET_PRIVATE (object);
+	g_return_if_fail (priv);
+
+	g_free (priv->conn_name);
+	G_OBJECT_CLASS (nm_ifnet_connection_parent_class)->finalize (object);
+}
+
+static void
+nm_ifnet_connection_class_init (NMIfnetConnectionClass * ifnet_connection_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (ifnet_connection_class);
+	NMSettingsConnectionClass *settings_class = NM_SETTINGS_CONNECTION_CLASS (ifnet_connection_class);
+
+	g_type_class_add_private (ifnet_connection_class,
+				  sizeof (NMIfnetConnectionPrivate));
+
+	object_class->finalize = finalize;
+	settings_class->delete = do_delete;
+	settings_class->commit_changes = commit_changes;
+
+	signals[IFNET_SETUP_MONITORS] =
+	    g_signal_new ("ifnet_setup_monitors",
+			  G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST,
+			  0, NULL, NULL, g_cclosure_marshal_VOID__VOID,
+			  G_TYPE_NONE, 0);
+	signals[IFNET_CANCEL_MONITORS] =
+	    g_signal_new ("ifnet_cancel_monitors",
+			  G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST,
+			  0, NULL, NULL, g_cclosure_marshal_VOID__VOID,
+			  G_TYPE_NONE, 0);
+
+}
diff --git a/src/settings/plugins/ifnet/nm-ifnet-connection.h b/src/settings/plugins/ifnet/nm-ifnet-connection.h
new file mode 100644
index 00000000..9423f20d
--- /dev/null
+++ b/src/settings/plugins/ifnet/nm-ifnet-connection.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Mu Qiao <qiaomuf@gmail.com>
+ *
+ * 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) 1999-2010 Gentoo Foundation, Inc.
+ */
+
+#ifndef NM_IFNET_CONNECTION_H
+#define NM_IFNET_CONNECTION_H
+
+#include <nm-settings-connection.h>
+#include "net_parser.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_IFNET_CONNECTION            (nm_ifnet_connection_get_type ())
+#define NM_IFNET_CONNECTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_IFNET_CONNECTION, NMIfnetConnection))
+#define NM_IFNET_CONNECTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_IFNET_CONNECTION, NMIfnetConnectionClass))
+#define NM_IS_IFNET_CONNECTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_IFNET_CONNECTION))
+#define NM_IS_IFNET_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_IFNET_CONNECTION))
+#define NM_IFNET_CONNECTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_IFNET_CONNECTION, NMIfnetConnectionClass))
+
+typedef struct {
+	NMSettingsConnection parent;
+} NMIfnetConnection;
+
+typedef struct {
+	NMSettingsConnectionClass parent;
+} NMIfnetConnectionClass;
+
+GType nm_ifnet_connection_get_type (void);
+
+NMIfnetConnection *nm_ifnet_connection_new (const char *conn_name,
+                                            NMConnection *source);
+
+G_END_DECLS
+#endif				/* NM_IFNET_CONNECTION_H */
diff --git a/src/settings/plugins/ifnet/plugin.c b/src/settings/plugins/ifnet/plugin.c
new file mode 100644
index 00000000..69b7bc80
--- /dev/null
+++ b/src/settings/plugins/ifnet/plugin.c
@@ -0,0 +1,541 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service (ifnet)
+ *
+ * Mu Qiao <qiaomuf@gmail.com>
+ *
+ * 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) 1999-2010 Gentoo Foundation, Inc.
+ */
+
+#include <string.h>
+
+#include <gmodule.h>
+#include <glib.h>
+#include <gio/gio.h>
+
+#include <nm-utils.h>
+#include <nm-setting-connection.h>
+
+#include "NetworkManager.h"
+#include "nm-system-config-interface.h"
+#include "nm-ifnet-connection.h"
+
+#include "plugin.h"
+#include "net_utils.h"
+#include "net_parser.h"
+#include "wpa_parser.h"
+#include "connection_parser.h"
+
+#define IFNET_PLUGIN_NAME_PRINT "ifnet"
+#define IFNET_PLUGIN_INFO "(C) 1999-2010 Gentoo Foundation, Inc. To report bugs please use bugs.gentoo.org with [networkmanager] or [qiaomuf] prefix."
+#define IFNET_SYSTEM_HOSTNAME_FILE "/etc/conf.d/hostname"
+#define IFNET_MANAGE_WELL_KNOWN_DEFAULT TRUE
+#define IFNET_KEY_FILE_KEY_MANAGED "managed"
+
+typedef struct {
+	GHashTable *config_connections;
+	gchar *hostname;
+	gboolean unmanaged_well_known;
+
+	GFileMonitor *hostname_monitor;
+	GFileMonitor *net_monitor;
+	GFileMonitor *wpa_monitor;
+
+} SCPluginIfnetPrivate;
+
+typedef void (*FileChangedFn) (gpointer user_data);
+
+typedef struct {
+	FileChangedFn callback;
+	gpointer user_data;
+} FileMonitorInfo;
+
+static void system_config_interface_init (NMSystemConfigInterface *class);
+
+static void reload_connections (gpointer config);
+
+G_DEFINE_TYPE_EXTENDED (SCPluginIfnet, sc_plugin_ifnet, G_TYPE_OBJECT, 0,
+                        G_IMPLEMENT_INTERFACE (NM_TYPE_SYSTEM_CONFIG_INTERFACE, system_config_interface_init))
+#define SC_PLUGIN_IFNET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SC_TYPE_PLUGIN_IFNET, SCPluginIfnetPrivate))
+/*
+static void
+ignore_cb(NMSettingsConnectionInterface * connection,
+	  GError * error, gpointer user_data)
+{
+}
+*/
+static const char *
+get_hostname (NMSystemConfigInterface * config)
+{
+	return SC_PLUGIN_IFNET_GET_PRIVATE (config)->hostname;
+}
+
+static void
+update_system_hostname (gpointer config)
+{
+	SCPluginIfnetPrivate *priv = SC_PLUGIN_IFNET_GET_PRIVATE (config);
+
+	if (priv->hostname)
+		g_free (priv->hostname);
+	priv->hostname = read_hostname (IFNET_SYSTEM_HOSTNAME_FILE);
+
+	g_object_notify (G_OBJECT (config),
+			 NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME);
+	PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Hostname updated to: %s",
+		      priv->hostname);
+}
+
+static void
+write_system_hostname (NMSystemConfigInterface * config,
+		       const gchar * newhostname)
+{
+	SCPluginIfnetPrivate *priv = SC_PLUGIN_IFNET_GET_PRIVATE (config);
+
+	g_return_if_fail (newhostname);
+	PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Write system hostname: %s",
+		      newhostname);
+	if (write_hostname (newhostname, IFNET_SYSTEM_HOSTNAME_FILE)) {
+		g_free (priv->hostname);
+		priv->hostname = g_strdup (newhostname);
+		g_object_notify (G_OBJECT (config),
+				 NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME);
+	} else
+		PLUGIN_WARN (IFNET_PLUGIN_NAME,
+			     "Write system hostname: %s failed", newhostname);
+}
+
+static gboolean
+is_managed_plugin ()
+{
+	const char *result = NULL;
+
+	result = ifnet_get_global_setting (IFNET_KEY_FILE_GROUP, IFNET_KEY_FILE_KEY_MANAGED);
+	if (result)
+		return is_true (result);
+	return IFNET_MANAGE_WELL_KNOWN_DEFAULT;
+}
+
+static void
+file_changed (GFileMonitor * monitor,
+	      GFile * file,
+	      GFile * other_file,
+	      GFileMonitorEvent event_type, gpointer user_data)
+{
+	FileMonitorInfo *info;
+
+	switch (event_type) {
+	case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
+		info = (FileMonitorInfo *) user_data;
+		info->callback (info->user_data);
+		break;
+	default:
+		break;
+	}
+}
+
+static GFileMonitor *
+monitor_file_changes (const char *filename,
+		      FileChangedFn callback, gpointer user_data)
+{
+	GFile *file;
+	GFileMonitor *monitor;
+	FileMonitorInfo *info;
+	GError **error = NULL;
+
+	if (!g_file_test (filename, G_FILE_TEST_IS_REGULAR))
+		return NULL;
+	file = g_file_new_for_path (filename);
+	monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, error);
+	g_object_unref (file);
+
+	if (monitor) {
+		info = g_new0 (FileMonitorInfo, 1);
+		info->callback = callback;
+		info->user_data = user_data;
+		g_object_weak_ref (G_OBJECT (monitor), (GWeakNotify) g_free,
+				   info);
+		g_signal_connect (monitor, "changed", G_CALLBACK (file_changed),
+				  info);
+	} else
+		PLUGIN_WARN (IFNET_PLUGIN_NAME,
+			     "Monitoring %s failed, error: %s", filename,
+			     error == NULL ? "nothing" : (*error)->message);
+
+	return monitor;
+}
+
+/* Callback for nm_settings_connection_replace_and_commit. Report any errors
+ * encountered when commiting connection settings updates. */
+static void
+commit_cb (NMSettingsConnection *connection, GError *error, gpointer unused) 
+{
+	if (error) {
+		PLUGIN_WARN (IFNET_PLUGIN_NAME, "    error updating: %s",
+	             	 (error && error->message) ? error->message : "(unknown)");
+	} else {
+		NMSettingConnection *s_con;
+
+		s_con = (NMSettingConnection *) nm_connection_get_setting (NM_CONNECTION (connection),
+		                                                           NM_TYPE_SETTING_CONNECTION);
+		g_assert (s_con);
+		PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Connection %s updated",
+		              nm_setting_connection_get_id (s_con));
+	}
+}
+
+static void
+setup_monitors (NMIfnetConnection * connection, gpointer user_data)
+{
+	SCPluginIfnet *self = SC_PLUGIN_IFNET (user_data);
+	SCPluginIfnetPrivate *priv = SC_PLUGIN_IFNET_GET_PRIVATE (self);
+
+	priv->hostname_monitor =
+	    monitor_file_changes (IFNET_SYSTEM_HOSTNAME_FILE,
+				  update_system_hostname, user_data);
+	priv->net_monitor =
+	    monitor_file_changes (CONF_NET_FILE, reload_connections, user_data);
+	priv->wpa_monitor =
+	    monitor_file_changes (WPA_SUPPLICANT_CONF, reload_connections,
+				  user_data);
+}
+
+static void
+cancel_monitors (NMIfnetConnection * connection, gpointer user_data)
+{
+	SCPluginIfnet *self = SC_PLUGIN_IFNET (user_data);
+	SCPluginIfnetPrivate *priv = SC_PLUGIN_IFNET_GET_PRIVATE (self);
+
+	if (priv->hostname_monitor) {
+		g_file_monitor_cancel (priv->hostname_monitor);
+		g_object_unref (priv->hostname_monitor);
+	}
+	if (priv->net_monitor) {
+		g_file_monitor_cancel (priv->net_monitor);
+		g_object_unref (priv->net_monitor);
+	}
+	if (priv->wpa_monitor) {
+		g_file_monitor_cancel (priv->wpa_monitor);
+		g_object_unref (priv->wpa_monitor);
+	}
+}
+
+static void
+reload_connections (gpointer config)
+{
+	SCPluginIfnet *self = SC_PLUGIN_IFNET (config);
+	SCPluginIfnetPrivate *priv = SC_PLUGIN_IFNET_GET_PRIVATE (self);
+	GList *conn_names = NULL, *n_iter = NULL;
+
+	/* save names for removing unused connections */
+	GHashTable *new_conn_names = NULL;
+	GHashTableIter iter;
+	gpointer key;
+	gpointer value;
+
+	if (priv->unmanaged_well_known)
+		return;
+
+	if (!reload_parsers ())
+		return;
+
+	PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Loading connections");
+
+	conn_names = ifnet_get_connection_names ();
+	new_conn_names = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
+	for (n_iter = conn_names; n_iter; n_iter = g_list_next (n_iter)) {
+		NMIfnetConnection *new;
+		NMIfnetConnection *old;
+		const char *conn_name = n_iter->data;
+
+		/* read the new connection */
+		new = nm_ifnet_connection_new (conn_name, NULL);
+		if (!new)
+			continue;
+
+		g_signal_connect (G_OBJECT (new), "ifnet_setup_monitors",
+		                  G_CALLBACK (setup_monitors), config);
+		g_signal_connect (G_OBJECT (new), "ifnet_cancel_monitors",
+		                  G_CALLBACK (cancel_monitors), config);
+
+		old = g_hash_table_lookup (priv->config_connections, conn_name);
+		if (old && new) {
+			const char *auto_refresh;
+
+			auto_refresh = ifnet_get_global_setting (IFNET_KEY_FILE_GROUP, "auto_refresh");
+			if (auto_refresh && is_true (auto_refresh)) {
+				if (!nm_connection_compare (NM_CONNECTION (old),
+				                            NM_CONNECTION (new),
+				                            NM_SETTING_COMPARE_FLAG_EXACT)) {
+					PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Auto refreshing %s", conn_name);
+
+					/* Remove and re-add to disconnect and reconnect with new settings */
+					nm_settings_connection_signal_remove (NM_SETTINGS_CONNECTION (old));
+					g_hash_table_remove (priv->config_connections, conn_name);
+					g_hash_table_insert (priv->config_connections, g_strdup (conn_name), new);
+					if (is_managed_plugin () && is_managed (conn_name))
+						g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, new);
+				}
+			} else {
+				/* Update existing connection with new settings */
+				nm_settings_connection_replace_and_commit (NM_SETTINGS_CONNECTION (old),
+				                                           NM_CONNECTION (new),
+				                                           commit_cb, NULL);
+				g_object_unref (new);
+			}
+			g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED);
+		} else if (new) {
+			g_hash_table_insert (priv->config_connections, g_strdup (conn_name), new);
+			if (is_managed_plugin () && is_managed (conn_name))
+				g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, new);
+		}
+		g_hash_table_insert (new_conn_names, (gpointer) conn_name, (gpointer) conn_name);
+	}
+
+	/* remove unused connections */
+	g_hash_table_iter_init (&iter, priv->config_connections);
+	while (g_hash_table_iter_next (&iter, &key, &value)) {
+		if (!g_hash_table_lookup (new_conn_names, key)) {
+			nm_settings_connection_signal_remove (NM_SETTINGS_CONNECTION (value));
+			g_hash_table_remove (priv->config_connections, key);
+		}
+	}
+	g_hash_table_destroy (new_conn_names);
+	g_list_free (conn_names);
+}
+
+static NMSettingsConnection *
+add_connection (NMSystemConfigInterface *config,
+                NMConnection *source,
+                GError **error)
+{
+	NMIfnetConnection *connection = NULL;
+	char *conn_name;
+
+	conn_name = ifnet_add_new_connection (source, CONF_NET_FILE, WPA_SUPPLICANT_CONF, error);
+	if (conn_name)
+		connection = nm_ifnet_connection_new (conn_name, source);
+	reload_connections (config);
+	return connection ? NM_SETTINGS_CONNECTION (connection) : NULL;
+}
+
+static void
+check_unmanaged (gpointer key, gpointer data, gpointer user_data)
+{
+	GSList **list = (GSList **) user_data;
+	gchar *conn_name = (gchar *) key;
+	const char *unmanaged_spec;
+	GSList *iter;
+
+	if (is_managed (conn_name))
+		return;
+	PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Checking unmanaged: %s", conn_name);
+	unmanaged_spec = ifnet_get_data (conn_name, "mac");
+	if (!unmanaged_spec)
+		return;
+
+	/* Just return if the unmanaged spec is already in the list */
+	for (iter = *list; iter; iter = g_slist_next (iter)) {
+		if (!strcmp ((char *) iter->data, unmanaged_spec))
+			return;
+	}
+
+	PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Add unmanaged: %s", unmanaged_spec);
+	*list =
+	    g_slist_prepend (*list, g_strdup_printf ("mac:%s", unmanaged_spec));
+}
+
+static GSList *
+get_unmanaged_specs (NMSystemConfigInterface * config)
+{
+	SCPluginIfnetPrivate *priv = SC_PLUGIN_IFNET_GET_PRIVATE (config);
+	GSList *list = NULL;
+
+	g_return_val_if_fail (priv->config_connections != NULL, NULL);
+	PLUGIN_PRINT (IFNET_PLUGIN_NAME, "getting unmanaged specs...");
+	g_hash_table_foreach (priv->config_connections, check_unmanaged, &list);
+	return list;
+}
+
+static void
+SCPluginIfnet_init (NMSystemConfigInterface * config)
+{
+	SCPluginIfnet *self = SC_PLUGIN_IFNET (config);
+	SCPluginIfnetPrivate *priv = SC_PLUGIN_IFNET_GET_PRIVATE (self);
+
+	PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Initializing!");
+	if (!priv->config_connections)
+		priv->config_connections =
+		    g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
+					   g_object_unref);
+	priv->unmanaged_well_known = !is_managed_plugin ();
+	PLUGIN_PRINT (IFNET_PLUGIN_NAME, "management mode: %s",
+		      priv->unmanaged_well_known ? "unmanaged" : "managed");
+	// GFileMonitor setup
+	setup_monitors (NULL, config);
+	reload_connections (config);
+	/* Read hostname */
+	update_system_hostname (self);
+
+	PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Initialzation complete!");
+}
+
+static GSList *
+get_connections (NMSystemConfigInterface * config)
+{
+	SCPluginIfnetPrivate *priv = SC_PLUGIN_IFNET_GET_PRIVATE (config);
+	GSList *connections = NULL;
+	GHashTableIter iter;
+	gpointer key, value;
+
+	PLUGIN_PRINT (IFNET_PLUGIN_NAME, "(%d) ... get_connections.",
+		      GPOINTER_TO_UINT (config));
+	if (priv->unmanaged_well_known) {
+		PLUGIN_PRINT (IFNET_PLUGIN_NAME,
+			      "(%d) ... get_connections (managed=false): return empty list.",
+			      GPOINTER_TO_UINT (config));
+		return NULL;
+	}
+
+	g_hash_table_iter_init (&iter, priv->config_connections);
+	while (g_hash_table_iter_next (&iter, &key, &value))
+		if (is_managed ((gchar *) key))
+			connections = g_slist_prepend (connections, value);
+	PLUGIN_PRINT (IFNET_PLUGIN_NAME, "(%d) connections count: %d",
+		      GPOINTER_TO_UINT (config), g_slist_length (connections));
+	return connections;
+}
+
+static void
+system_config_interface_init (NMSystemConfigInterface *class)
+{
+	class->init = SCPluginIfnet_init;
+	class->get_connections = get_connections;
+	class->get_unmanaged_specs = get_unmanaged_specs;
+	class->add_connection = add_connection;
+}
+
+static void
+sc_plugin_ifnet_init (SCPluginIfnet * plugin)
+{
+}
+
+static void
+get_property (GObject * object, guint prop_id, GValue * value,
+	      GParamSpec * pspec)
+{
+	NMSystemConfigInterface *self = NM_SYSTEM_CONFIG_INTERFACE (object);
+
+	switch (prop_id) {
+	case NM_SYSTEM_CONFIG_INTERFACE_PROP_NAME:
+		g_value_set_string (value, IFNET_PLUGIN_NAME_PRINT);
+		break;
+	case NM_SYSTEM_CONFIG_INTERFACE_PROP_INFO:
+		g_value_set_string (value, IFNET_PLUGIN_INFO);
+		break;
+	case NM_SYSTEM_CONFIG_INTERFACE_PROP_CAPABILITIES:
+		g_value_set_uint (value,
+				  NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS
+				  |
+				  NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME);
+		break;
+	case NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME:
+		g_value_set_string (value, get_hostname (self));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+set_property (GObject * object, guint prop_id, const GValue * value,
+	      GParamSpec * pspec)
+{
+	switch (prop_id) {
+	case NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME:{
+			const gchar *hostname = g_value_get_string (value);
+
+			if (hostname && strlen (hostname) < 1)
+				hostname = NULL;
+			write_system_hostname (NM_SYSTEM_CONFIG_INTERFACE
+					       (object), hostname);
+			break;
+		}
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+dispose (GObject * object)
+{
+	SCPluginIfnet *plugin = SC_PLUGIN_IFNET (object);
+	SCPluginIfnetPrivate *priv = SC_PLUGIN_IFNET_GET_PRIVATE (plugin);
+
+	cancel_monitors (NULL, object);
+	if (priv->config_connections) {
+		g_hash_table_remove_all (priv->config_connections);
+		g_hash_table_destroy (priv->config_connections);
+	}
+
+	g_free (priv->hostname);
+	ifnet_destroy ();
+	wpa_parser_destroy ();
+	G_OBJECT_CLASS (sc_plugin_ifnet_parent_class)->dispose (object);
+}
+
+static void
+sc_plugin_ifnet_class_init (SCPluginIfnetClass * req_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (req_class);
+
+	g_type_class_add_private (req_class, sizeof (SCPluginIfnetPrivate));
+
+	object_class->dispose = dispose;
+	object_class->get_property = get_property;
+	object_class->set_property = set_property;
+
+	g_object_class_override_property (object_class,
+					  NM_SYSTEM_CONFIG_INTERFACE_PROP_NAME,
+					  NM_SYSTEM_CONFIG_INTERFACE_NAME);
+
+	g_object_class_override_property (object_class,
+					  NM_SYSTEM_CONFIG_INTERFACE_PROP_INFO,
+					  NM_SYSTEM_CONFIG_INTERFACE_INFO);
+
+	g_object_class_override_property (object_class,
+					  NM_SYSTEM_CONFIG_INTERFACE_PROP_CAPABILITIES,
+					  NM_SYSTEM_CONFIG_INTERFACE_CAPABILITIES);
+
+	g_object_class_override_property (object_class,
+					  NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME,
+					  NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME);
+}
+
+G_MODULE_EXPORT GObject *
+nm_system_config_factory (void)
+{
+	static SCPluginIfnet *singleton = NULL;
+
+	if (!singleton)
+		singleton
+		    =
+		    SC_PLUGIN_IFNET (g_object_new (SC_TYPE_PLUGIN_IFNET, NULL));
+	else
+		g_object_ref (singleton);
+	return G_OBJECT (singleton);
+}
diff --git a/src/settings/plugins/ifnet/plugin.h b/src/settings/plugins/ifnet/plugin.h
new file mode 100644
index 00000000..83099b63
--- /dev/null
+++ b/src/settings/plugins/ifnet/plugin.h
@@ -0,0 +1,47 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service (ifnet)
+ *
+ * Mu Qiao <qiaomuf@gmail.com>
+ *
+ * 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) 1999-2010 Gentoo Foundation, Inc.
+ */
+
+#ifndef _PLUGIN_H_
+#define _PLUGIN_H_
+
+#include <glib-object.h>
+
+#define SC_TYPE_PLUGIN_IFNET            (sc_plugin_ifnet_get_type ())
+#define SC_PLUGIN_IFNET(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), SC_TYPE_PLUGIN_IFNET, SCPluginIfnet))
+#define SC_PLUGIN_IFNET_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), SC_TYPE_PLUGIN_IFNET, SCPluginIfnetClass))
+#define SC_IS_PLUGIN_IFNET(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SC_TYPE_PLUGIN_IFNET))
+#define SC_IS_PLUGIN_IFNET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SC_TYPE_PLUGIN_IFNET))
+#define SC_PLUGIN_IFNET_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), SC_TYPE_PLUGIN_IFNET, SCPluginIfnetClass))
+
+typedef struct _SCPluginIfnet SCPluginIfnet;
+typedef struct _SCPluginIfnetClass SCPluginIfnetClass;
+
+struct _SCPluginIfnet {
+	GObject parent;
+};
+
+struct _SCPluginIfnetClass {
+	GObjectClass parent;
+};
+
+GType sc_plugin_ifnet_get_type (void);
+#endif
diff --git a/src/settings/plugins/ifnet/tests/Makefile.am b/src/settings/plugins/ifnet/tests/Makefile.am
new file mode 100644
index 00000000..20a26805
--- /dev/null
+++ b/src/settings/plugins/ifnet/tests/Makefile.am
@@ -0,0 +1,18 @@
+INCLUDES=-I$(srcdir)/../ \
+	 -I$(top_srcdir)/libnm-glib \
+	 -I$(top_srcdir)/libnm-util \
+	 -I$(top_srcdir)/include \
+	 -I$(top_srcdir)/src/settings
+TESTS = check_ifnet
+check_PROGRAMS = check_ifnet
+check_ifnet_SOURCES = test_all.c 
+check_ifnet_CPPFLAGS = $(CHECK_CFLAGS) $(GLIB_CFLAGS)
+check_ifnet_LDADD = $(top_builddir)/libnm-util/libnm-util.la \
+		    $(builddir)/../lib-ifnet-io.la \
+		    $(CHECK_LIBS) \
+		    $(GLIB_LIBS)
+EXTRA_DIST = hostname \
+			 net \
+			 net.all \
+			 nm-system-settings.conf \
+			 wpa_supplicant.conf
diff --git a/src/settings/plugins/ifnet/tests/Makefile.in b/src/settings/plugins/ifnet/tests/Makefile.in
new file mode 100644
index 00000000..17b80c36
--- /dev/null
+++ b/src/settings/plugins/ifnet/tests/Makefile.in
@@ -0,0 +1,723 @@
+# 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@
+TESTS = check_ifnet$(EXEEXT)
+check_PROGRAMS = check_ifnet$(EXEEXT)
+subdir = src/settings/plugins/ifnet/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/gettext.m4 $(top_srcdir)/m4/gtk-doc.m4 \
+	$(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \
+	$(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/introspection.m4 \
+	$(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
+	$(top_srcdir)/m4/lib-prefix.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)/m4/nls.m4 \
+	$(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.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 =
+am_check_ifnet_OBJECTS = check_ifnet-test_all.$(OBJEXT)
+check_ifnet_OBJECTS = $(am_check_ifnet_OBJECTS)
+am__DEPENDENCIES_1 =
+check_ifnet_DEPENDENCIES = $(top_builddir)/libnm-util/libnm-util.la \
+	$(builddir)/../lib-ifnet-io.la $(am__DEPENDENCIES_1)
+AM_V_lt = $(am__v_lt_$(V))
+am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
+am__v_lt_0 = --silent
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_$(V))
+am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
+am__v_CC_0 = @echo "  CC    " $@;
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_$(V))
+am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
+am__v_CCLD_0 = @echo "  CCLD  " $@;
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo "  GEN   " $@;
+SOURCES = $(check_ifnet_SOURCES)
+DIST_SOURCES = $(check_ifnet_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+am__tty_colors = \
+red=; grn=; lgn=; blu=; std=
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+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@
+DHCLIENT_VERSION = @DHCLIENT_VERSION@
+DHCPCD_PATH = @DHCPCD_PATH@
+DISABLE_DEPRECATED = @DISABLE_DEPRECATED@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+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@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+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@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@
+INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
+INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@
+INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@
+INTROSPECTION_LIBS = @INTROSPECTION_LIBS@
+INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
+INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
+INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
+IPTABLES_PATH = @IPTABLES_PATH@
+IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@
+IWMX_SDK_LIBS = @IWMX_SDK_LIBS@
+KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBDL = @LIBDL@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBM = @LIBM@
+LIBNL_CFLAGS = @LIBNL_CFLAGS@
+LIBNL_LIBS = @LIBNL_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
+NM_MICRO_VERSION = @NM_MICRO_VERSION@
+NM_MINOR_VERSION = @NM_MINOR_VERSION@
+NM_VERSION = @NM_VERSION@
+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@
+PKGCONFIG_PATH = @PKGCONFIG_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@
+QT_CFLAGS = @QT_CFLAGS@
+QT_LIBS = @QT_LIBS@
+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@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+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@
+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@
+systemdsystemunitdir = @systemdsystemunitdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+INCLUDES = -I$(srcdir)/../ \
+	 -I$(top_srcdir)/libnm-glib \
+	 -I$(top_srcdir)/libnm-util \
+	 -I$(top_srcdir)/include \
+	 -I$(top_srcdir)/src/settings
+
+check_ifnet_SOURCES = test_all.c 
+check_ifnet_CPPFLAGS = $(CHECK_CFLAGS) $(GLIB_CFLAGS)
+check_ifnet_LDADD = $(top_builddir)/libnm-util/libnm-util.la \
+		    $(builddir)/../lib-ifnet-io.la \
+		    $(CHECK_LIBS) \
+		    $(GLIB_LIBS)
+
+EXTRA_DIST = hostname \
+			 net \
+			 net.all \
+			 nm-system-settings.conf \
+			 wpa_supplicant.conf
+
+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/settings/plugins/ifnet/tests/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu src/settings/plugins/ifnet/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-checkPROGRAMS:
+	@list='$(check_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
+check_ifnet$(EXEEXT): $(check_ifnet_OBJECTS) $(check_ifnet_DEPENDENCIES) 
+	@rm -f check_ifnet$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(check_ifnet_OBJECTS) $(check_ifnet_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check_ifnet-test_all.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@	$(AM_V_CC)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
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@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@	$(AM_V_CC)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
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@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@	$(AM_V_CC)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
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@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 $@ $<
+
+check_ifnet-test_all.o: test_all.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(check_ifnet_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT check_ifnet-test_all.o -MD -MP -MF $(DEPDIR)/check_ifnet-test_all.Tpo -c -o check_ifnet-test_all.o `test -f 'test_all.c' || echo '$(srcdir)/'`test_all.c
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/check_ifnet-test_all.Tpo $(DEPDIR)/check_ifnet-test_all.Po
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='test_all.c' object='check_ifnet-test_all.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(check_ifnet_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o check_ifnet-test_all.o `test -f 'test_all.c' || echo '$(srcdir)/'`test_all.c
+
+check_ifnet-test_all.obj: test_all.c
+@am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(check_ifnet_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT check_ifnet-test_all.obj -MD -MP -MF $(DEPDIR)/check_ifnet-test_all.Tpo -c -o check_ifnet-test_all.obj `if test -f 'test_all.c'; then $(CYGPATH_W) 'test_all.c'; else $(CYGPATH_W) '$(srcdir)/test_all.c'; fi`
+@am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/check_ifnet-test_all.Tpo $(DEPDIR)/check_ifnet-test_all.Po
+@am__fastdepCC_FALSE@	$(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='test_all.c' object='check_ifnet-test_all.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(check_ifnet_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o check_ifnet-test_all.obj `if test -f 'test_all.c'; then $(CYGPATH_W) 'test_all.c'; else $(CYGPATH_W) '$(srcdir)/test_all.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
+
+check-TESTS: $(TESTS)
+	@failed=0; all=0; xfail=0; xpass=0; skip=0; \
+	srcdir=$(srcdir); export srcdir; \
+	list=' $(TESTS) '; \
+	$(am__tty_colors); \
+	if test -n "$$list"; then \
+	  for tst in $$list; do \
+	    if test -f ./$$tst; then dir=./; \
+	    elif test -f $$tst; then dir=; \
+	    else dir="$(srcdir)/"; fi; \
+	    if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
+	      all=`expr $$all + 1`; \
+	      case " $(XFAIL_TESTS) " in \
+	      *[\ \	]$$tst[\ \	]*) \
+		xpass=`expr $$xpass + 1`; \
+		failed=`expr $$failed + 1`; \
+		col=$$red; res=XPASS; \
+	      ;; \
+	      *) \
+		col=$$grn; res=PASS; \
+	      ;; \
+	      esac; \
+	    elif test $$? -ne 77; then \
+	      all=`expr $$all + 1`; \
+	      case " $(XFAIL_TESTS) " in \
+	      *[\ \	]$$tst[\ \	]*) \
+		xfail=`expr $$xfail + 1`; \
+		col=$$lgn; res=XFAIL; \
+	      ;; \
+	      *) \
+		failed=`expr $$failed + 1`; \
+		col=$$red; res=FAIL; \
+	      ;; \
+	      esac; \
+	    else \
+	      skip=`expr $$skip + 1`; \
+	      col=$$blu; res=SKIP; \
+	    fi; \
+	    echo "$${col}$$res$${std}: $$tst"; \
+	  done; \
+	  if test "$$all" -eq 1; then \
+	    tests="test"; \
+	    All=""; \
+	  else \
+	    tests="tests"; \
+	    All="All "; \
+	  fi; \
+	  if test "$$failed" -eq 0; then \
+	    if test "$$xfail" -eq 0; then \
+	      banner="$$All$$all $$tests passed"; \
+	    else \
+	      if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
+	      banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
+	    fi; \
+	  else \
+	    if test "$$xpass" -eq 0; then \
+	      banner="$$failed of $$all $$tests failed"; \
+	    else \
+	      if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
+	      banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
+	    fi; \
+	  fi; \
+	  dashes="$$banner"; \
+	  skipped=""; \
+	  if test "$$skip" -ne 0; then \
+	    if test "$$skip" -eq 1; then \
+	      skipped="($$skip test was not run)"; \
+	    else \
+	      skipped="($$skip tests were not run)"; \
+	    fi; \
+	    test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+	      dashes="$$skipped"; \
+	  fi; \
+	  report=""; \
+	  if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+	    report="Please report to $(PACKAGE_BUGREPORT)"; \
+	    test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+	      dashes="$$report"; \
+	  fi; \
+	  dashes=`echo "$$dashes" | sed s/./=/g`; \
+	  if test "$$failed" -eq 0; then \
+	    echo "$$grn$$dashes"; \
+	  else \
+	    echo "$$red$$dashes"; \
+	  fi; \
+	  echo "$$banner"; \
+	  test -z "$$skipped" || echo "$$skipped"; \
+	  test -z "$$report" || echo "$$report"; \
+	  echo "$$dashes$$std"; \
+	  test "$$failed" -eq 0; \
+	else :; fi
+
+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
+check-am: all-am
+	$(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
+	$(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile
+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-checkPROGRAMS clean-generic clean-libtool \
+	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-TESTS check-am clean \
+	clean-checkPROGRAMS clean-generic clean-libtool 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
+
+
+# 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/settings/plugins/ifnet/tests/hostname b/src/settings/plugins/ifnet/tests/hostname
new file mode 100644
index 00000000..25c76165
--- /dev/null
+++ b/src/settings/plugins/ifnet/tests/hostname
@@ -0,0 +1,2 @@
+#Generated by NetworkManager
+hostname="gentoo"
diff --git a/src/settings/plugins/ifnet/tests/net b/src/settings/plugins/ifnet/tests/net
new file mode 100644
index 00000000..e7550002
--- /dev/null
+++ b/src/settings/plugins/ifnet/tests/net
@@ -0,0 +1,147 @@
+# This blank configuration will automatically use DHCP for any net.*
+# scripts in /etc/init.d.  To create a more complete configuration,
+# please review /etc/conf.d/net.example and save your configuration
+# in /etc/conf.d/net (this file :]!).
+
+config_eth0=(
+"202.117.16.121    netmask    255.255.255.0 brd 202.117.16.255"
+"192.168.4.121/24"
+"dhcp6"
+)
+routes_eth0=( "default via     202.117.16.1" 
+		"192.168.4.0/24 via 192.168.4.1")
+dns_servers_eth0="202.117.0.20    202.117.0.21"
+dns_search_eth0="p12.edu.cn p13.edu.cn"
+
+config_eth1=(
+	"dhcp"
+)
+enable_ipv6_eth1="true"
+routes_eth1=( "default via 202.117.16.1" )
+dns_servers_eth1="202.117.0.20 202.117.0.21"
+config_eth2=(
+"202.117.16.1211    netmask    255.255.255.0 brd 202.117.16.255"
+"192.168.4.121/24"
+"4321:0:1:2:3:4:567:89ab/64"
+)
+routes_eth2=("default via  4321:0:1:2:3:4:567:89ab")
+enable_ipv6_eth2="true"
+config_eth3=("nufjlsjlll")
+managed_eth4=("false")
+routes_eth4=("default via 4321:0:1:2:3:4:567:89ab")
+config_eth5=("dhcp")
+config_eth6=("192.168.4.{1..101}/24")
+
+config_eth7=( "dhcp" )
+auto_eth7="true"
+
+
+config_myxjtu2=("202.117.16.121/24 brd 202.117.16.255")
+routes_myxjtu2=("default via 202.117.16.1")
+dns_servers_myxjtu2="202.117.0.20 202.117.0.21"
+#key_myxjtu2="[1] s:xjtud key [1] enc restricted"
+#key_eth6="[1] aaaa-4444-3d [2] s:xjtudlc key [1] enc open"
+
+
+username_ppp0='user'
+password_ppp0='password'
+
+config_qiaomuf=("dhcp")
+
+config_1xtest=("dhcp")
+
+config_0xab3ace=("dhcp")
+
+modules=( "iproute2" )
+	config_kvm0=( "null" )
+	config_kvm1=( "null" )
+
+	tuntap_kvm0="tap"
+	tuntap_kvm1="tap"
+	tunctl_kvm0="-u user"
+	tunctl_kvm1="-u user"
+
+bridge_br0="eth0 kvm0 kvm1"
+config_br0=( "192.168.1.10/24" )
+	brctl_br0=( "setfd 0")
+	dhcp_eth1="nosendhost nontp -I"
+
+predown() {
+	# The default in the script is to test for NFS root and disallow
+	# downing interfaces in that case.  Note that if you specify a
+	# predown() function you will override that logic.  Here it is, in
+	# case you still want it...
+	if is_net_fs /; then
+		eerror "root filesystem is network mounted -- can't stop ${IFACE}"
+		return 1
+	fi
+
+	# Remember to return 0 on success
+	return 0
+}
+
+postup() {
+	# This function could be used, for example, to register with a
+	# dynamic DNS service.  Another possibility would be to
+	# send/receive mail once the interface is brought up.
+
+	# Here is an example that allows the use of iproute rules
+	# which have been configured using the rules_eth0 variable.
+	#rules_eth0=" \
+	#	'from 24.80.102.112/32 to 192.168.1.0/24 table localnet priority 100' \
+	#	'from 216.113.223.51/32 to 192.168.1.0/24 table localnet priority 100' \
+	#"
+	eval set -- \$rules_${IFVAR}
+	if [ $# != 0 ]; then
+		einfo "Adding IP policy routing rules"
+		eindent
+		# Ensure that the kernel supports policy routing
+		if ! ip rule list | grep -q "^"; then
+			eerror "You need to enable IP Policy Routing (CONFIG_IP_MULTIPLE_TABLES)"
+			eerror "in your kernel to use ip rules"
+		else
+			for x; do
+				ebegin "${x}"
+				ip rule add ${x}
+				eend $?
+			done
+		fi
+		eoutdent
+		# Flush the cache
+		ip route flush cache dev "${IFACE}"
+	fi
+
+}
+
+postdown() {
+	# Enable Wake-On-LAN for every interface except for lo
+	# Probably a good idea to set ifdown="no" in /etc/conf.d/net
+	# as well ;)
+	[ "${IFACE}" != "lo" ] && ethtool -s "${IFACE}" wol g
+
+	Automatically erase any ip rules created in the example postup above
+	if interface_exists "${IFACE}"; then
+		# Remove any rules for this interface
+		local rule
+		ip rule list | grep " iif ${IFACE}[ ]*" | {
+			while read rule; do
+				rule="${rule#*:}"	
+				ip rule del ${rule}
+			done
+		}
+		# Flush the route cache
+		ip route flush cache dev "${IFACE}"
+	fi
+
+	# Return 0 always
+	return 0
+}
+
+failup() {
+       # This function is mostly here for completeness... I haven't
+       # thought of anything nifty to do with it yet ;-)
+}
+
+faildown() 
+{}
+
diff --git a/src/settings/plugins/ifnet/tests/net.all b/src/settings/plugins/ifnet/tests/net.all
new file mode 100644
index 00000000..a30a1b95
--- /dev/null
+++ b/src/settings/plugins/ifnet/tests/net.all
@@ -0,0 +1,864 @@
+##############################################################################
+# QUICK-START
+#
+# The quickest start is if you want to use DHCP.
+# In that case, everything should work out of the box, no configuration
+# necessary, though the startup script will warn you that you haven't
+# specified anything.
+
+# WARNING :- some examples have a mixture of IPv4 (ie 192.168.0.1) and IPv6
+# (ie 4321:0:1:2:3:4:567:89ab) internet addresses. They only work if you have
+# the relevant kernel option enabled. So if you don't have an IPv6 enabled
+# kernel then remove the IPv6 address from your config.
+
+# If you want to use a static address or use DHCP explicitly, jump
+# down to the section labelled INTERFACE HANDLERS.
+#
+# If you want to do anything more fancy, you should take the time to
+# read through the rest of this file.
+
+##############################################################################
+# MODULES
+#
+# We now support modular networking scripts which means we can easily
+# add support for new interface types and modules while keeping
+# compatability with existing ones.
+# 
+# Modules load by default if the package they need is installed.  If
+# you specify a module here that doesn't have it's package installed
+# then you get an error stating which package you need to install.
+# Ideally, you only use the modules setting when you have two or more
+# packages installed that supply the same service.
+#
+# In other words, you probably should DO NOTHING HERE...
+
+# Prefer ifconfig over iproute2
+modules=( "ifconfig" )
+
+# You can also specify other modules for an interface
+# In this case we prefer udhcpc over dhcpcd
+modules_eth0=( "udhcpc" )
+
+# You can also specify which modules not to use - for example you may be
+# using a supplicant or linux-wlan-ng to control wireless configuration but
+# you still want to configure network settings per ESSID associated with.
+modules=( "!iwconfig" "!wpa_supplicant" )
+# IMPORTANT: If you need the above, please disable modules in that order
+
+
+##############################################################################
+# INTERFACE HANDLERS
+# 
+# We provide two interface handlers presently: ifconfig and iproute2.
+# You need one of these to do any kind of network configuration.
+# For ifconfig support, emerge sys-apps/net-tools
+# For iproute2 support, emerge sys-apps/iproute2
+
+# If you don't specify an interface then we prefer iproute2 if it's installed
+# To prefer ifconfig over iproute2
+modules=( "ifconfig" )
+
+# For a static configuration, use something like this
+# (They all do exactly the same thing btw)
+config_eth0=( "192.168.0.2/24" )
+config_eth0=( "192.168.0.2 netmask 255.255.255.0" )
+
+# We can also specify a broadcast
+config_eth0=( "192.168.0.2/24 brd 192.168.0.255" )
+config_eth0=( "192.168.0.2 netmask 255.255.255.0 broadcast 192.168.0.255" )
+
+# If you need more than one address, you can use something like this
+# NOTE: ifconfig creates an aliased device for each extra IPv4 address
+#       (eth0:1, eth0:2, etc)
+#       iproute2 does not do this as there is no need to
+config_eth0=(
+	"192.168.0.2/24"
+	"192.168.0.3/24"
+	"192.168.0.4/24"
+)
+# Or you can use sequence expressions
+config_eth0=( "192.168.0.{2..4}/24" )
+# which does the same as above. Be careful though as if you use this and
+# fallbacks, you have to ensure that both end up with the same number of
+# values otherwise your fallback won't work correctly.
+
+# You can also use IPv6 addresses
+# (you should always specify a prefix length with IPv6 here)
+config_eth0=(
+	"192.168.0.2/24"
+	"4321:0:1:2:3:4:567:89ab/64"
+	"4321:0:1:2:3:4:567:89ac/64"
+)
+
+# If you wish to keep existing addresses + routing and the interface is up,
+# you can specify a noop (no operation). If the interface is down or there
+# are no addresses assigned, then we move onto the next step (default dhcp)
+# This is useful when configuring your interface with a kernel command line
+# or similar
+config_eth0=( "noop" "192.168.0.2/24" )
+
+# If you don't want ANY address (only useful when calling for advanced stuff)
+config_eth0=( "null" )
+
+# Here's how to do routing if you need it
+routes_eth0=(
+	"default via 192.168.0.1"		# IPv4 default route
+	"10.0.0.0/8 via 192.168.0.1"		# IPv4 subnet route
+	"::/0"					# IPv6 unicast
+)
+
+# If a specified module fails (like dhcp - see below), you can specify a
+# fallback like so
+fallback_eth0=( "192.168.0.2 netmask 255.255.255.0" )
+fallback_route_eth0=( "default via 192.168.0.1" )
+
+# NOTE: fallback entry must match the entry location in config_eth0
+# As such you can only have one fallback route.
+
+# Some users may need to alter the MTU - here's how
+mtu_eth0="1500"
+
+# Each module described below can set a default base metric, lower is
+# preferred over higher. This is so we can prefer a wired route over a
+# wireless route automaticaly. You can override this by setting
+metric_eth0="100"
+# or on a global basis
+metric="100"
+# The only downside of the global setting is that you have to ensure that
+# there are no conflicting routes yourself. For users with large routing
+# tables you may have to set a global metric as the due to a simple read of
+# the routing table taking over a minute at a time.
+
+##############################################################################
+# OPTIONAL MODULES
+
+# INTERFACE RENAMING
+# There is no consistent device renaming scheme for Linux.
+# The preferred way of naming devices is via the kernel module directly or
+# by using udev (http://www.reactivated.net/udevrules.php)
+
+# If you are unable to write udev rules, then we do provide a way of renaming
+# the interface based on it's MAC address, but it is not optimal.
+# Here is how to rename an interface whose MAC address is 00:11:22:33:44:55
+# to foo1
+rename_001122334455="foo1"
+
+# You can also do this based on current device name - although this is not
+# recommended. Here we rename eth1 to foo2.
+rename_eth1="foo2"
+
+#-----------------------------------------------------------------------------
+# WIRELESS (802.11 support)
+# Wireless can be provided by iwconfig or wpa_supplicant
+
+# iwconfig
+# emerge net-wireless/wireless-tools
+# Wireless options are held in /etc/conf.d/wireless - but could be here too
+# Consult the sample file /etc/conf.d/wireless.example for instructions
+# iwconfig is the default
+
+# wpa_supplicant
+# emerge net-wireless/wpa-supplicant
+# Wireless options are held in /etc/wpa_supplicant.conf
+# Consult the sample file /etc/wpa_supplicant.conf.example for instructions
+# To choose wpa_supplicant over iwconfig
+modules=( "wpa_supplicant" )
+# To configure wpa_supplicant
+wpa_supplicant_eth0="-Dwext" # For generic wireless
+wpa_supplicant_ath0="-Dmadwifi" # For Atheros based cards
+# Consult wpa_supplicant for more drivers
+# By default don't wait for wpa_suppliant to associate and authenticate.
+# If you would like to, so can specify how long in seconds
+associate_timeout_eth0=60
+# A value of 0 means wait forever.
+
+# GENERIC WIRELESS OPTIONS
+# PLEASE READ THE INSTRUCTIONS IN /etc/conf.d/wireless.example FOR
+# HOW TO USE THIS ESSID VARIABLE
+# You can also override any settings found here per ESSID - which is very
+# handy if you use different networks a lot
+config_ESSID=( "dhcp" )
+dhcpcd_ESSID="-t 5"
+
+# Setting name/domain server causes /etc/resolv.conf to be overwritten
+# Note that if DHCP is used, and you want this to take precedence then
+ set dhcp_ESSID="nodns"
+dns_servers_ESSID=( "192.168.0.1" "192.168.0.2" )
+dns_domain_ESSID="some.domain"
+dns_search_ESSID="search.this.domain search.that.domain"
+# Please check the man page for resolv.conf for more information
+# as domain and search are mutually exclusive.
+
+# You can also override any settings found here per MAC address of the AP
+# in case you use Access Points with the same ESSID but need different
+# networking configs. Below is an example - of course you use the same
+# method with other variables
+mac_config_001122334455=( "dhcp" )
+mac_dhcpcd_001122334455="-t 10"
+mac_dns_servers_001122334455=( "192.168.0.1" "192.168.0.2" )
+
+# When an interface has been associated with an Access Point, a global
+# variable called ESSID is set to the Access Point's ESSID for use in the
+# pre/post user functions below (although it's not available in preup as you
+# won't have associated then)
+
+# If you're using anything else to configure wireless on your interface AND
+# you have installed any of the above packages, you need to disable them
+modules=( "!iwconfig" "!wpa_supplicant" )
+
+#-----------------------------------------------------------------------------
+# DHCP
+# DHCP can be provided by dhclient, dhcpcd, pump or udhcpc.
+#
+# dhclient: emerge net-misc/dhcp
+# dhcpcd:   emerge net-misc/dhcpcd
+# pump:     emerge net-misc/pump
+# udhcpc:   emerge net-misc/udhcp
+
+# If you have more than one DHCP client installed, you need to specify which
+# one to use - otherwise we default to dhcpcd if available.
+modules=( "dhclient" ) # to select dhclient over dhcpcd
+#
+# Notes:
+# - All clients send the current hostname to the DHCP server by default
+# - dhcpcd does not daemonize when the lease time is infinite
+# - udhcp-0.9.3-r3 and earlier do not support getting NTP servers 
+# - pump does not support getting NIS servers
+# - DHCP tends to erase any existing device information - so add
+#   static addresses after dhcp if you need them
+# - dhclient and udhcpc can set other resolv.conf options such as "option"
+#   and "sortlist"- see the System module for more details
+
+# Regardless of which DHCP client you prefer, you configure them the
+# same way using one of following depending on which interface modules
+# you're using.
+config_eth0=( "dhcp" )
+
+# For passing custom options to dhcpcd use something like the following.  This
+# example reduces the timeout for retrieving an address from 60 seconds (the
+# default) to 10 seconds.
+dhcpcd_eth0="-t 10"
+
+# dhclient, udhcpc and pump don't have many runtime options
+# You can pass options to them in a similar manner to dhcpcd though
+dhclient_eth0="..."
+udhcpc_eth0="..."
+pump_eth0="..."
+
+# GENERIC DHCP OPTIONS
+# Set generic DHCP options like so
+dhcp_eth0="release nodns nontp nonis nogateway nosendhost"
+
+# This tells the dhcp client to release it's lease when it stops, not to
+# overwrite dns, ntp and nis settings, not to set a default route and not to
+# send the current hostname to the dhcp server and when it starts.
+# You can use any combination of the above options - the default is not to
+# use any of them.
+
+#-----------------------------------------------------------------------------
+# For APIPA support, emerge net-misc/iputils or net-analyzer/arping
+
+# APIPA is a module that tries to find a free address in the range
+# 169.254.0.0-169.254.255.255 by arping a random address in that range on the
+# interface. If no reply is found then we assign that address to the interface
+
+# This is only useful for LANs where there is no DHCP server and you don't
+# connect directly to the internet.
+config_eth0=( "dhcp" )
+fallback_eth0=( "apipa" )
+
+#-----------------------------------------------------------------------------
+# ARPING Gateway configuration 
+# and
+# Automatic Private IP Addressing (APIPA)
+# For arpingnet / apipa support, emerge net-misc/iputils or net-analyzer/arping
+#
+# This is a module that tries to find a gateway IP. If it exists then we use
+# that gateways configuration for our own. For the configuration variables
+# simply ensure that each octet is zero padded and the dots are removed.
+# Below is an example.
+#
+gateways_eth0="192.168.0.1 10.0.0.1"
+config_192168000001=( "192.168.0.2/24" )
+routes_192168000001=( "default via 192.168.0.1" )
+dns_servers_192168000001=( "192.168.0.1" )
+config_010000000001=( "10.0.0.254/8" )
+routes_010000000001=( "default via 10.0.0.1" )
+dns_servers_010000000001=( "10.0.0.1" )
+
+# We can also specify a specific MAC address for each gateway if different
+# networks have the same gateway.
+gateways_eth0="192.168.0.1,00:11:22:AA:BB:CC 10.0.0.1,33:44:55:DD:EE:FF"
+config_192168000001_001122AABBCC=( "192.168.0.2/24" )
+routes_192168000001_001122AABBCC=( "default via 192.168.0.1" )
+dns_servers_192168000001_001122AABBCC=( "192.168.0.1" )
+config_010000000001_334455DDEEFF=( "10.0.0.254/8" )
+routes_010000000001_334455DDEEFF=( "default via 10.0.0.1" )
+dns_servers_010000000001_334455DDEEFF=( "10.0.0.1" )
+
+# If we don't find any gateways (or there are none configured) then we try and
+# use APIPA to find a free address in the range 169.254.0.0-169.254.255.255
+# by arping a random address in that range on the interface. If no reply is
+# found then we assign that address to the interface.
+
+# This is only useful for LANs where there is no DHCP server.
+config_eth0=( "arping" )
+
+# or if no DHCP server can be found
+config_eth0=( "dhcp" )
+fallback_eth0=( "arping" )
+
+# NOTE: We default to sleeping for 1 second the first time we attempt an
+# arping to give the interface time to settle on the LAN. This appears to
+# be a good default for most instances, but if not you can alter it here.
+arping_sleep=5
+arping_sleep_lan=7
+
+# NOTE: We default to waiting 3 seconds to get an arping response. You can
+# change the default wait like so.
+arping_wait=3
+arping_wait_lan=2
+
+#-----------------------------------------------------------------------------
+# VLAN (802.1q support)
+# For VLAN support, emerge net-misc/vconfig
+
+# Specify the VLAN numbers for the interface like so
+# Please ensure your VLAN IDs are NOT zero-padded
+vlans_eth0="1 2"
+
+# You may not want to assign an IP the the physical interface, but we still
+# need it up.
+config_eth0=( "null" )
+
+# You can also configure the VLAN - see for vconfig man page for more details
+vconfig_eth0=( "set_name_type VLAN_PLUS_VID_NO_PAD" )
+vconfig_vlan1=( "set_flag 1" "set_egress_map 2 6" )
+config_vlan1=( "172.16.3.1 netmask 255.255.254.0" )
+config_vlan2=( "172.16.2.1 netmask 255.255.254.0" )
+
+# NOTE: Vlans can be configured with a . in their interface names
+# When configuring vlans with this name type, you need to replace . with a _
+config_eth0.1=( "dhcp" ) - does not work
+config_eth0_1=( "dhcp" ) - does work
+
+# NOTE: Vlans are controlled by their physical interface and not per vlan
+# This means you do not need to create init scripts in /etc/init.d for each
+# vlan, you must need to create one for the physical interface.
+# If you wish to control the configuration of each vlan through a separate
+# script, or wish to rename the vlan interface to something that vconfig
+# cannot then you need to do this.
+vlan_start_eth0="no"
+
+# If you do the above then you may want to depend on eth0 like so
+ RC_NEED_vlan1="net.eth0"
+# NOTE: depend functions only work in /etc/conf.d/net
+# and not in profile configs such as /etc/conf.d/net.foo
+
+#-----------------------------------------------------------------------------
+# Bonding
+# For link bonding/trunking emerge net-misc/ifenslave
+
+# To bond interfaces together
+slaves_bond0="eth0 eth1 eth2"
+config_bond0=( "null" ) # You may not want to assign an IP the the bond
+
+# If any of the slaves require extra configuration - for example wireless or
+# ppp devices - we need to depend function on the bonded interfaces
+RC_NEED_bond0="net.eth0 net.eth1"
+
+
+#-----------------------------------------------------------------------------
+# Classical IP over ATM 
+# For CLIP support emerge net-dialup/linux-atm
+
+# Ensure that you have /etc/atmsigd.conf setup correctly
+# Now setup each clip interface like so
+clip_atm0=( "peer_ip [if.]vpi.vci [opts]" ... )
+#  where "peer_ip" is the IP address of a PVC peer (in case of an ATM connection
+#  with your ISP, your only peer is usually the ISP gateway closest to you),
+#  "if" is the number of the ATM interface which will carry the PVC, "vpi.vci"
+#  is the ATM VC address, and "opts" may optionally specify VC parameters like
+#  qos, pcr, and the like (see "atmarp -s" for further reference). Please also
+#  note quoting: it is meant to distinguish the VCs you want to create. You may,
+#  in example, create an atm0 interface to more peers, like this:
+clip_atm0=( "1.1.1.254 0.8.35" "1.1.1.253 1.8.35" )
+
+#  By default, the PVC will use the LLC/SNAP encapsulation. If you rather need a
+#  null encapsulation (aka "VC mode"), please add the keyword "null" to opts.
+
+
+#-----------------------------------------------------------------------------
+# PPP
+# For PPP support, emerge net-dialup/ppp
+# PPP is used for most dialup connections, including ADSL.
+# The older ADSL module is documented below, but you are encouraged to try
+# this module first.
+#
+# You need to create the PPP net script yourself. Make it like so
+#ln -s net.lo /etc/init.d/net.ppp0
+#
+# We have to instruct ppp0 to actually use ppp
+config_ppp0=( "ppp" )
+#
+# Each PPP interface requires an interface to use as a "Link"
+link_ppp0="/dev/ttyS0" 		# Most PPP links will use a serial port
+link_ppp0="eth0"       		# PPPoE requires an ethernet interface
+link_ppp0="[itf.]vpi.vci"		# PPPoA requires the ATM VC's address
+link_ppp0="/dev/null"			# ISDN links should have this
+link_ppp0="pty 'your_link_command'"	# PPP links over ssh, rsh, etc
+#
+# Here you should specify what pppd plugins you want to use
+# Available plugins are: pppoe, pppoa, capi, dhcpc, minconn, radius,
+#			 radattr, radrealms and winbind 
+plugins_ppp0=(
+	"pppoe"				# Required plugin for PPPoE
+	"pppoa vc-encaps"		# Required plugin for PPPoA with an option
+	"capi"				# Required plugin for ISDN
+)
+#
+# PPP requires at least a username. You can optionally set a password here too
+# If you don't, then it will use the password specified in /etc/ppp/*-secrets
+# against the specified username
+username_ppp0='user'
+password_ppp0='password'
+# NOTE: You can set a blank password like so
+password_ppp0=
+#
+# The PPP daemon has many options you can specify - although there are many
+# and may seem daunting, it is recommended that you read the pppd man page
+# before enabling any of them
+pppd_ppp0=(
+	"maxfail 0"	# WARNING: It's not recommended you use this
+			# if you don't specify maxfail then we assume 0
+	"updetach" 	# If not set, "/etc/init.d/net.ppp0 start" will return
+			# immediately,  without waiting the link to come up
+			# for the first time.
+			# Do not use it for dial-on-demand links!
+	"debug" 	# Enables syslog debugging
+	"noauth"	# Do not require the peer to authenticate itself
+	"defaultroute"	# Make this PPP interface the default route
+	"usepeerdns"	# Use the DNS settings provided by PPP
+
+# On demand options
+	"demand"		# Enable dial on demand
+	"idle 30"		# Link goes down after 30 seconds of inactivity
+	"10.112.112.112:10.112.112.113"	# Phony IP addresses
+	"ipcp-accept-remote"	# Accept the peers idea of remote address
+	"ipcp-accept-local"	# Accept the peers idea of local address
+	"holdoff 3" 	# Wait 3 seconds after link dies before re-starting
+
+# Dead peer detection
+	"lcp-echo-interval 15"	# Send a LCP echo every 15 seconds
+	"lcp-echo-failure 3"	# Make peer dead after 3 consective
+				# echo-requests
+	
+# Compression options - use these to completely disable compression
+#	noaccomp noccp nobsdcomp nodeflate nopcomp novj novjccomp
+
+# Dial-up settings
+	"lock"				# Lock serial port
+	"115200"			# Set the serial port baud rate
+	"modem crtscts"			# Enable hardware flow control
+	"192.168.0.1:192.168.0.2"	# Local and remote IP addresses
+)
+#
+# Dial-up PPP users need to specify at least one telephone number
+phone_number_ppp0=( "12345689" ) # Maximum 2 phone numbers are supported
+# They will also need a chat script - here's a good one
+chat_ppp0=(
+#	'ABORT' 'BUSY'
+#	'ABORT' 'ERROR'
+#	'ABORT' 'NO ANSWER'
+#	'ABORT' 'NO CARRIER'
+#	'ABORT' 'NO DIALTONE'
+#	'ABORT' 'Invalid Login'
+#	'ABORT' 'Login incorrect'
+#	'TIMEOUT' '5'
+#	'' 'ATZ'
+#	'OK' 'AT' # Put your modem initialization string here
+#	'OK' 'ATDT\T'
+#	'TIMEOUT' '60'
+#	'CONNECT' ''
+#	'TIMEOUT' '5'
+#	'~--' ''
+)
+
+# If the link require extra configuration - for example wireless or
+# RFC 268 bridge - we need to depend on the bridge so they get
+# configured correctly.
+RC_NEED_ppp0="net.nas0"
+
+#WARNING: if MTU of the PPP interface is less than 1500 and you use this
+#machine as a router, you should add the following rule to your firewall
+#
+#iptables -I FORWARD 1 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
+
+#-----------------------------------------------------------------------------
+# ADSL
+# For ADSL support, emerge net-dialup/rp-pppoe
+# WARNING: This ADSL module is being deprecated in favour of the PPP module
+# above.
+# You should make the following settings and also put your
+# username/password information in /etc/ppp/pap-secrets
+
+# Configure the interface to use ADSL
+config_eth0=( "adsl" )
+
+# You probably won't need to edit /etc/ppp/pppoe.conf if you set this
+adsl_user_eth0="my-adsl-username"
+
+#-----------------------------------------------------------------------------
+# ISDN
+# For ISDN support, emerge net-dialup/isdn4k-utils
+# You should make the following settings and also put your
+# username/password information in /etc/ppp/pap-secrets
+
+# Configure the interface to use ISDN
+config_ippp0=( "dhcp" )
+# It's important to specify dhcp if you need it!
+config_ippp0=( "192.168.0.1/24" )
+# Otherwise, you can use a static IP
+
+# NOTE: The interface name must be either ippp or isdn followed by a number
+
+# You may need this option to set the default route
+ipppd_eth0="defaultroute"
+
+#-----------------------------------------------------------------------------
+# MAC changer
+# To set a specific MAC address
+mac_eth0="00:11:22:33:44:55"
+
+# For changing MAC addresses using the below, emerge net-analyzer/macchanger
+# - to randomize the last 3 bytes only
+mac_eth0="random-ending"
+# - to randomize between the same physical type of connection (e.g. fibre,
+# copper, wireless) , all vendors
+mac_eth0="random-samekind"
+# - to randomize between any physical type of connection (e.g. fibre, copper,
+# wireless) , all vendors
+mac_eth0="random-anykind"
+# - full randomization - WARNING: some MAC addresses generated by this may NOT
+# act as expected
+mac_eth0="random-full"
+# custom - passes all parameters directly to net-analyzer/macchanger
+mac_eth0="some custom set of parameters"
+
+# You can also set other options based on the MAC address of your network card
+# Handy if you use different docking stations with laptops
+config_001122334455=( "dhcp" )
+
+#-----------------------------------------------------------------------------
+# TUN/TAP
+# For TUN/TAP support emerge net-misc/openvpn or sys-apps/usermode-utilities
+#
+# You must specify if we're a tun or tap device. Then you can give it any
+# name you like - such as vpn
+tuntap_vpn="tun"
+config_vpn=( "192.168.0.1/24")
+
+# Or stick wit the generic names - like tap0
+tuntap_tap0="tap"
+config_tap0=( "192.168.0.1/24")
+
+# For passing custom options to tunctl use something like the following.  This
+# example sets the owner to adm
+tunctl_tun1="-u adm"
+# When using openvpn, there are no options
+
+#-----------------------------------------------------------------------------
+# Bridging (802.1d)
+# For bridging support emerge net-misc/bridge-utils
+
+# To add ports to bridge br0
+bridge_br0="eth0 eth1"
+# or dynamically add them when the interface comes up
+bridge_add_eth0="br0"
+bridge_add_eth1="br0"
+
+# You need to configure the ports to null values so dhcp does not get started 
+config_eth0=( "null" )
+config_eth1=( "null" )
+
+# Finally give the bridge an address - dhcp or a static IP
+config_br0=( "dhcp" ) # may not work when adding ports dynamically
+config_br0=( "192.168.0.1/24" )
+
+# If any of the ports require extra configuration - for example wireless or
+# ppp devices - we need to depend on them like so.
+RC_NEED_br0="net.eth0 net.eth1"
+
+# Below is an example of configuring the bridge
+# Consult "man brctl" for more details
+brctl_br0=( "setfd 0" "sethello 0" "stp off" )
+
+#-----------------------------------------------------------------------------
+# RFC 2684 Bridge Support 
+# For RFC 2684 bridge support emerge net-misc/br2684ctl
+
+# Interface names have to be of the form nas0, nas1, nas2, etc.
+# You have to specify a VPI and VCI for the interface like so
+br2684ctl_nas0="-a 0.38" # UK VPI and VCI
+
+# You may want to configure the encapsulation method as well by adding the -e
+# option to the command above (may need to be before the -a command)
+# -e 0 # LLC (default)
+# -e 1 # VC mux
+
+# Then you can configure the interface as normal
+config_nas0=( "192.168.0.1/24" )
+
+#-----------------------------------------------------------------------------
+# Tunnelling
+# WARNING: For tunnelling it is highly recommended that you
+# emerge sys-apps/iproute2
+#
+# For GRE tunnels
+iptunnel_vpn0="mode gre remote 207.170.82.1 key 0xffffffff ttl 255"
+
+# For IPIP tunnels
+iptunnel_vpn0="mode ipip remote 207.170.82.2 ttl 255"
+
+# To configure the interface
+config_vpn0=( "192.168.0.2 pointopoint 192.168.1.2" )	# ifconfig style
+config_vpn0=( "192.168.0.2 peer 192.168.1.1" )		# iproute2 style
+
+# 6to4 Tunnels allow IPv6 to work over IPv4 addresses, provided you
+# have a non-private address configured on an interface.
+ link_6to4="eth0"		# Interface to base it's addresses on
+ config_6to4=( "ip6to4" )
+# You may want to depend on eth0 like so
+RC_NEED_6to4="net.eth0"
+# To ensure that eth0 is configured before 6to4. Of course, the tunnel could be
+# any name and this also works for any configured interface.
+# NOTE: If you're not using iproute2 then your 6to4 tunnel has to be called
+# sit0 - otherwise use a different name like 6to4 in the example above.
+
+
+#-----------------------------------------------------------------------------
+# System
+# For configuring system specifics such as domain, dns, ntp and nis servers
+# It's rare that you would need todo this, but you can anyway.
+# This is most benefit to wireless users who don't use DHCP so they can change
+# their configs based on ESSID. See wireless.example for more details
+
+# To use dns settings such as these, dns_servers_eth0 must be set!
+# If you omit the _eth0 suffix, then it applies to all interfaces unless
+# overridden by the interface suffix.
+dns_domain_eth0="your.domain"
+dns_servers_eth0="192.168.0.2 192.168.0.3"
+dns_search_eth0="this.domain that.domain"
+dns_options_eth0=( "timeout 1" "rotate" )
+dns_sortlist_eth0="130.155.160.0/255.255.240.0 130.155.0.0"
+# See the man page for resolv.conf for details about the options and sortlist
+# directives
+
+ntp_servers_eth0="192.168.0.2 192.168.0.3"
+
+nis_domain_eth0="domain"
+nis_servers_eth0="192.168.0.2 192.168.0.3"
+
+# NOTE: Setting any of these will stamp on the files in question. So if you
+# don't specify dns_servers but you do specify dns_domain then no nameservers
+# will be listed in /etc/resolv.conf even if there were any there to start
+# with.
+# If this is an issue for you then maybe you should look into a resolv.conf
+# manager like resolvconf-gentoo to manage this file for you. All packages
+# that baselayout supports use resolvconf-gentoo if installed.
+
+#-----------------------------------------------------------------------------
+# Cable in/out detection
+# Sometimes the cable is in, others it's out. Obviously you don't want to
+# restart net.eth0 every time when you plug it in either.
+#
+# netplug is a package that detects this and requires no extra configuration
+# on your part.
+# emerge sys-apps/netplug
+# or
+# emerge sys-apps/ifplugd
+# and you're done :)
+
+# By default we don't wait for netplug/ifplugd to configure the interface.
+# If you would like it to wait so that other services now that network is up
+# then you can specify a timeout here.
+plug_timeout="10"
+# A value of 0 means wait forever.
+
+# If you don't want to use netplug on a specific interface but you have it
+# installed, you can disable it for that interface via the modules statement
+modules_eth0=( "!netplug" )
+# You can do the same for ifplugd
+#
+# You can disable them both with the generic plug
+modules_eth0=( "!plug" )
+
+# To use specific ifplugd options, fex specifying wireless mode
+ifplugd_eth0="--api-mode=wlan"
+# man ifplugd for more options
+
+##############################################################################
+# ADVANCED CONFIGURATION
+# 
+# Four functions can be defined which will be called surrounding the
+# start/stop operations.  The functions are called with the interface
+# name first so that one function can control multiple adapters. An extra two
+# functions can be defined when an interface fails to start or stop.
+#
+# The return values for the preup and predown functions should be 0
+# (success) to indicate that configuration or deconfiguration of the
+# interface can continue.  If preup returns a non-zero value, then
+# interface configuration will be aborted.  If predown returns a
+# non-zero value, then the interface will not be allowed to continue
+# deconfiguration.
+#
+# The return values for the postup, postdown, failup and faildown functions are
+# ignored since there's nothing to do if they indicate failure.
+#
+# ${IFACE} is set to the interface being brought up/down
+# ${IFVAR} is ${IFACE} converted to variable name bash allows
+
+#preup() {
+#	# Test for link on the interface prior to bringing it up.  This
+#	# only works on some network adapters and requires the mii-diag
+#	# package to be installed.
+#	if mii-tool "${IFACE}" 2> /dev/null | grep -q 'no link'; then
+#		ewarn "No link on ${IFACE}, aborting configuration"
+#		return 1
+#	fi 
+#
+#	# Test for link on the interface prior to bringing it up.  This
+#	# only works on some network adapters and requires the ethtool
+#	# package to be installed.
+#	if ethtool "${IFACE}" | grep -q 'Link detected: no'; then
+#		ewarn "No link on ${IFACE}, aborting configuration"
+#		return 1
+#	fi
+#
+#
+#	# Remember to return 0 on success
+#	return 0
+#}
+
+#predown() {
+#	# The default in the script is to test for NFS root and disallow
+#	# downing interfaces in that case.  Note that if you specify a
+#	# predown() function you will override that logic.  Here it is, in
+#	# case you still want it...
+#	if is_net_fs /; then
+#		eerror "root filesystem is network mounted -- can't stop ${IFACE}"
+#		return 1
+#	fi
+#
+#	# Remember to return 0 on success
+#	return 0
+#}
+
+#postup() {
+#	# This function could be used, for example, to register with a
+#	# dynamic DNS service.  Another possibility would be to
+#	# send/receive mail once the interface is brought up.
+
+#	# Here is an example that allows the use of iproute rules
+#	# which have been configured using the rules_eth0 variable.
+#	#rules_eth0=(
+#	#	"from 24.80.102.112/32 to 192.168.1.0/24 table localnet priority 100"
+#	#	"from 216.113.223.51/32 to 192.168.1.0/24 table localnet priority 100"
+#	#)
+#	local x="rules_${IFVAR}[@]"
+#	local -a rules=( "${!x}" )
+#	if [[ -n ${rules} ]] ; then
+#		einfo "Adding IP policy routing rules"
+#		eindent
+#		# Ensure that the kernel supports policy routing
+#		if ! ip rule list | grep -q "^" ; then
+#			eerror "You need to enable IP Policy Routing (CONFIG_IP_MULTIPLE_TABLES)"
+#			eerror "in your kernel to use ip rules"
+#		else
+#			for x in "${rules[@]}" ; do
+#				ebegin "${x}"
+#				ip rule add ${x} dev "${IFACE}"
+#				eend $?
+#			done
+#		fi
+#		eoutdent
+#		# Flush the cache
+#		ip route flush cache dev "${IFACE}"
+#	fi
+
+#}
+
+#postdown() {
+#	# Enable Wake-On-LAN for every interface except for lo
+#	# Probably a good idea to set RC_DOWN_INTERFACE="no" in /etc/conf.d/rc
+#	# as well ;)
+#	[[ ${IFACE} != "lo" ]] && ethtool -s "${IFACE}" wol g
+
+#	Automatically erase any ip rules created in the example postup above
+#	if interface_exists "${IFACE}" ; then
+#		# Remove any rules for this interface
+#		local rule
+#		ip rule list | grep " iif ${IFACE}[ ]*" | {
+#			while read rule ; do
+#				rule="${rule#*:}"	
+#				ip rule del ${rule}
+#			done
+#		}
+#		# Flush the route cache
+#		ip route flush cache dev "${IFACE}"
+#	fi
+
+#	# Return 0 always
+#	return 0
+#}
+
+#failup() {
+#       # This function is mostly here for completeness... I haven't
+#       # thought of anything nifty to do with it yet ;-)
+#}
+
+#faildown() {
+#       # This function is mostly here for completeness... I haven't
+#       # thought of anything nifty to do with it yet ;-)
+#}
+
+##############################################################################
+# FORCING MODULES
+# The Big Fat Warning :- If you use module forcing do not complain to us or
+# file bugs about it not working!
+#
+# Loading modules is a slow affair - we have to check each one for the following
+# 1) Code sanity
+# 2) Has the required package been emerged?
+# 3) Has it modified anything?
+# 4) Have all the dependant modules been loaded?
+
+# Then we have to strip out the conflicting modules based on user preference
+# and default configuration and sort them into the correct order.
+# Finally we check the end result for dependencies.
+
+# This, of course, takes valuable CPU time so we provide module forcing as a
+# means to speed things up. We still do *some* checking but not much.
+
+# It is essential that you force modules in the correct order and supply all
+# the modules you need. You must always supply an interface module - we
+# supply ifconfig or iproute2.
+
+# The Big Fat Warning :- If you use module forcing do not complain to us or
+# file bugs about it not working!
+
+# Now that we've warned you twice, here's how to do it
+modules_force=( "ifconfig" )
+modules_force=( "iproute2" "dhcpcd" )
+
+# We can also apply this to a specific interface
+modules_force_eth1=( "iproute2" )
+
+# The below will not work
+modules_force=( "dhcpcd" )
+# No interface (ifconfig/iproute2)
+modules_force=( "ifconfig" "essidnet" "iwconfig" )
+# Although it will not crash, essidnet will not work as it has to come after
+# iwconfig
+modules_force=( "iproute2" "ifconfig" )
+# The interface will be setup twice which will cause problems
diff --git a/src/settings/plugins/ifnet/tests/nm-system-settings.conf b/src/settings/plugins/ifnet/tests/nm-system-settings.conf
new file mode 100644
index 00000000..39bc87b8
--- /dev/null
+++ b/src/settings/plugins/ifnet/tests/nm-system-settings.conf
@@ -0,0 +1,5 @@
+[main]
+plugins=ifnet,keyfile
+
+[ifnet]
+managed=false
diff --git a/src/settings/plugins/ifnet/tests/test_all.c b/src/settings/plugins/ifnet/tests/test_all.c
new file mode 100644
index 00000000..d114bbba
--- /dev/null
+++ b/src/settings/plugins/ifnet/tests/test_all.c
@@ -0,0 +1,399 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service (ifnet)
+ *
+ * Mu Qiao <qiaomuf@gmail.com>
+ *
+ * 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) 1999-2010 Gentoo Foundation, Inc.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <nm-utils.h>
+
+#include "net_parser.h"
+#include "nm-test-helpers.h"
+#include "net_utils.h"
+#include "wpa_parser.h"
+#include "connection_parser.h"
+
+static void
+test_getdata ()
+{
+	ASSERT (ifnet_get_data ("eth1", "config")
+		&& strcmp (ifnet_get_data ("eth1", "config"), "dhcp") == 0,
+		"get data", "config_eth1 is not correct");
+	ASSERT (ifnet_get_data ("ppp0", "username")
+		&& strcmp (ifnet_get_data ("ppp0", "username"), "user") == 0,
+		"get data", "config_ppp0 username is not correctly read");
+	ASSERT (ifnet_get_data ("ppp0", "password")
+		&& strcmp (ifnet_get_data ("ppp0", "password"),
+			   "password") == 0, "get data",
+		"config_ppp0 password is not correctly read");
+}
+
+static void
+test_read_hostname ()
+{
+	gchar *hostname = read_hostname ("hostname");
+
+	ASSERT (hostname != NULL, "get hostname", "hostname is NULL");
+	ASSERT (strcmp ("gentoo", hostname) == 0,
+		"get hostname",
+		"hostname is not correctly read, read:%s, expected: gentoo",
+		hostname);
+	g_free (hostname);
+}
+
+static void
+test_write_hostname ()
+{
+	gchar *hostname = read_hostname ("hostname");
+	gchar *tmp;
+
+	write_hostname ("gentoo-nm", "hostname");
+	tmp = read_hostname ("hostname");
+	ASSERT (strcmp (tmp, "gentoo-nm") == 0,
+		"write hostname", "write hostname error");
+	write_hostname (hostname, "hostname");
+	g_free (tmp);
+	g_free (hostname);
+}
+
+static void
+test_is_static ()
+{
+	ASSERT (is_static_ip4 ("eth1") == FALSE, "is static",
+		"a dhcp interface is recognized as static");
+	ASSERT (is_static_ip4 ("eth0") == TRUE, "is static",
+		"a static interface is recognized as dhcp");
+	ASSERT (!is_static_ip6 ("eth0") == TRUE, "is static",
+		"a static interface is recognized as dhcp");
+}
+
+static void
+test_has_default_route ()
+{
+	ASSERT (has_default_ip4_route ("eth0"),
+		"has default route", "eth0 should have a default ipv4 route");
+	ASSERT (has_default_ip6_route ("eth4"),
+		"has default route", "eth4 should have a default ipv6 route");
+	ASSERT (!has_default_ip4_route ("eth5")
+		&& !has_default_ip6_route ("eth5"),
+		"has default route", "eth5 shouldn't have a default route");
+}
+
+static void
+test_has_ip6_address ()
+{
+	ASSERT (has_ip6_address ("eth2"), "has ip6 address",
+		"eth2 should have a ipv6 address");
+	ASSERT (!has_ip6_address ("eth0"), "has ip6 address",
+		"eth0 shouldn't have a ipv6 address")
+
+}
+
+static void
+test_is_ip4_address ()
+{
+	gchar *address1 = "192.168.4.232/24";
+	gchar *address2 = "192.168.100.{1..254}/24";
+	gchar *address3 = "192.168.4.2555/24";
+
+	ASSERT (is_ip4_address (address1), "is ip4 address",
+		"%s should be a valid address", address1);
+	ASSERT (is_ip4_address (address2), "is ip4 address",
+		"%s should be a valid address", address2);
+	ASSERT (!is_ip4_address (address3), "is ip4 address",
+		"%s should be an invalid address", address3);
+}
+
+static void
+test_is_ip6_address ()
+{
+	gchar *address1 = "4321:0:1:2:3:4:567:89ac/24";
+
+	ASSERT (is_ip6_address (address1), "is ip6 address",
+		"%s should be a valid address", address1);
+}
+
+static void
+check_ip_block (ip_block * iblock, gchar * ip, gchar * netmask, gchar * gateway)
+{
+	char *str;
+	struct in_addr tmp_ip4_addr;
+
+	str = malloc (INET_ADDRSTRLEN);
+	tmp_ip4_addr.s_addr = iblock->ip;
+	inet_ntop (AF_INET, &tmp_ip4_addr, str, INET_ADDRSTRLEN);
+	ASSERT (strcmp (ip, str) == 0, "check ip",
+		"ip expected:%s, find:%s", ip, str);
+	tmp_ip4_addr.s_addr = iblock->netmask;
+	inet_ntop (AF_INET, &tmp_ip4_addr, str, INET_ADDRSTRLEN);
+	ASSERT (strcmp (netmask, str) == 0, "check netmask",
+		"netmask expected:%s, find:%s", netmask, str);
+	tmp_ip4_addr.s_addr = iblock->gateway;
+	inet_ntop (AF_INET, &tmp_ip4_addr, str, INET_ADDRSTRLEN);
+	ASSERT (strcmp (gateway, str) == 0, "check gateway",
+		"gateway expected:%s, find:%s", gateway, str);
+	free (str);
+}
+
+static void
+test_convert_ipv4_config_block ()
+{
+	ip_block *iblock = convert_ip4_config_block ("eth0");
+	ip_block *tmp = iblock;
+
+	ASSERT (iblock != NULL, "convert ipv4 block",
+		"block eth0 should not be NULL");
+	check_ip_block (iblock, "202.117.16.121", "255.255.255.0",
+			"202.117.16.1");
+	iblock = iblock->next;
+	destroy_ip_block (tmp);
+	ASSERT (iblock != NULL, "convert ipv4 block",
+		"block eth0 should have a second IP address");
+	check_ip_block (iblock, "192.168.4.121", "255.255.255.0",
+			"202.117.16.1");
+	destroy_ip_block (iblock);
+	iblock = convert_ip4_config_block ("eth2");
+	ASSERT (iblock != NULL
+		&& iblock->next == NULL,
+		"convert error IPv4 address", "should only get one address");
+	check_ip_block (iblock, "192.168.4.121", "255.255.255.0", "0.0.0.0");
+	destroy_ip_block (iblock);
+	iblock = convert_ip4_config_block ("eth3");
+	ASSERT (iblock == NULL, "convert config_block",
+		"convert error configuration");
+	destroy_ip_block (iblock);
+	iblock = convert_ip4_config_block ("eth6");
+	ASSERT (iblock != NULL, "convert config_block",
+		"convert error configuration");
+	destroy_ip_block (iblock);
+}
+
+static void
+test_convert_ipv4_routes_block ()
+{
+	ip_block *iblock = convert_ip4_routes_block ("eth0");
+	ip_block *tmp = iblock;
+
+	ASSERT (iblock != NULL, "convert ip4 routes", "should get one route");
+	check_ip_block (iblock, "192.168.4.0", "255.255.255.0", "192.168.4.1");
+	iblock = iblock->next;
+	destroy_ip_block (tmp);
+	ASSERT (iblock == NULL, "convert ip4 routes",
+		"should only get one route");
+}
+
+static void
+test_wpa_parser ()
+{
+	const char *value;
+
+	ASSERT (exist_ssid ("example"), "get wsec",
+		"ssid myxjtu2 is not found");
+	ASSERT (exist_ssid ("static-wep-test"), "exist_ssid",
+		"ssid static-wep-test is not found");
+	value = wpa_get_value ("static-wep-test", "key_mgmt");
+	ASSERT (value
+		&& strcmp (value, "NONE") == 0, "get wpa data",
+		"key_mgmt of static-wep-test should be NONE, find %s", value);
+	value = wpa_get_value ("static-wep-test", "wep_key0");
+	ASSERT (value
+		&& strcmp (value, "\"abcde\"") == 0,
+		"get wpa data",
+		"wep_key0 of static-wep-test should be abcde, find %s", value);
+	ASSERT (exist_ssid ("leap-example"), "get wsec",
+		"ssid leap-example is not found");
+}
+
+static void
+test_strip_string ()
+{
+	gchar *str = "( \"default via     202.117.16.1\" )";
+	gchar *result = g_strdup (str);
+	gchar *result_b = result;
+
+	result = strip_string (result, '(');
+	result = strip_string (result, ')');
+	result = strip_string (result, '"');
+	ASSERT (strcmp (result, "default via     202.117.16.1") ==
+		0, "strip_string",
+		"string isn't stripped, result is: %s", result);
+	g_free (result_b);
+}
+
+static void
+test_is_unmanaged ()
+{
+	ASSERT (is_managed ("eth0"), "test_is_unmanaged",
+		"eth0 should be managed");
+	ASSERT (!is_managed ("eth4"), "test_is_unmanaged",
+		"eth4 should be unmanaged");
+}
+
+static void
+test_new_connection ()
+{
+	GError **error = NULL;
+	NMConnection *connection;
+
+	connection = ifnet_update_connection_from_config_block ("eth2", error);
+	ASSERT (connection != NULL, "new connection",
+		"new connection failed: %s",
+		error == NULL ? "None" : (*error)->message);
+	g_object_unref (connection);
+	connection =
+	    ifnet_update_connection_from_config_block ("qiaomuf", error);
+	ASSERT (connection != NULL, "new connection",
+		"new connection failed: %s", error
+		&& (*error) ? (*error)->message : "NONE");
+	g_object_unref (connection);
+	connection =
+	    ifnet_update_connection_from_config_block ("myxjtu2", error);
+	ASSERT (connection != NULL, "new connection",
+		"new connection failed: %s", error
+		&& (*error) ? (*error)->message : "NONE");
+	g_object_unref (connection);
+}
+
+#define NET_GEN_NAME "net.generate"
+#define SUP_GEN_NAME "wpa_supplicant.conf.generate"
+
+static void
+test_update_connection ()
+{
+	GError **error = NULL;
+	NMConnection *connection;
+	gboolean success;
+
+	connection = ifnet_update_connection_from_config_block ("eth0", error);
+	ASSERT (connection != NULL, "get connection",
+		"get connection failed: %s",
+		error == NULL ? "None" : (*error)->message);
+
+	success = ifnet_update_parsers_by_connection (connection, "eth0",
+	                                              NET_GEN_NAME,
+	                                              SUP_GEN_NAME,
+	                                              NULL,
+	                                              error);
+	ASSERT (success, "update connection", "update connection failed %s", "eth0");
+	g_object_unref (connection);
+
+	connection = ifnet_update_connection_from_config_block ("0xab3ace", error);
+	ASSERT (connection != NULL, "get connection", "get connection failed: %s",
+		error == NULL ? "None" : (*error)->message);
+
+	success = ifnet_update_parsers_by_connection (connection, "0xab3ace",
+	                                              NET_GEN_NAME,
+	                                              SUP_GEN_NAME,
+	                                              NULL,
+	                                              error);
+	ASSERT (success, "update connection", "update connection failed %s", "0xab3ace");
+	g_object_unref (connection);
+
+	unlink (NET_GEN_NAME);
+	unlink (SUP_GEN_NAME);
+}
+
+static void
+test_add_connection ()
+{
+	NMConnection *connection;
+
+	connection = ifnet_update_connection_from_config_block ("eth0", NULL);
+	ASSERT (ifnet_add_new_connection (connection, NET_GEN_NAME, SUP_GEN_NAME, NULL),
+	        "add connection", "add connection failed: %s", "eth0");
+	g_object_unref (connection);
+	connection = ifnet_update_connection_from_config_block ("myxjtu2", NULL);
+	ASSERT (ifnet_add_new_connection (connection, NET_GEN_NAME, SUP_GEN_NAME, NULL),
+	        "add connection", "add connection failed: %s", "myxjtu2");
+	g_object_unref (connection);
+
+	unlink (NET_GEN_NAME);
+	unlink (SUP_GEN_NAME);
+}
+
+static void
+test_delete_connection ()
+{
+	GError *error = NULL;
+	NMConnection *connection;
+
+	connection = ifnet_update_connection_from_config_block ("eth7", &error);
+	ASSERT (connection != NULL, "get connection",
+	        "get connection failed: %s",
+	        error ? error->message : "None");
+	ASSERT (ifnet_delete_connection_in_parsers ("eth7", NET_GEN_NAME, SUP_GEN_NAME),
+	        "delete connection", "delete connection failed: %s", "eth7");
+	g_object_unref (connection);
+	connection = ifnet_update_connection_from_config_block ("qiaomuf", &error);
+	ASSERT (connection != NULL, "get connection",
+	        "get connection failed: %s",
+	        error ? error->message : "None");
+	ASSERT (ifnet_delete_connection_in_parsers ("qiaomuf", NET_GEN_NAME, SUP_GEN_NAME),
+	        "delete connection", "delete connection failed: %s", "qiaomuf");
+	g_object_unref (connection);
+
+	unlink (NET_GEN_NAME);
+	unlink (SUP_GEN_NAME);
+}
+
+static void
+run_all (gboolean run)
+{
+	if (run) {
+		test_strip_string ();
+		test_is_static ();
+		test_has_ip6_address ();
+		test_has_default_route ();
+		test_getdata ();
+		test_read_hostname ();
+		test_write_hostname ();
+		test_is_ip4_address ();
+		test_is_ip6_address ();
+		test_convert_ipv4_config_block ();
+		test_convert_ipv4_routes_block ();
+		test_is_unmanaged ();
+		test_wpa_parser ();
+		test_convert_ipv4_routes_block ();
+		test_new_connection ();
+		test_update_connection ();
+		test_add_connection ();
+		test_delete_connection ();
+	}
+}
+
+int
+main (void)
+{
+//      g_mem_set_vtable(glib_mem_profiler_table);
+//      g_atexit(g_mem_profile);
+	g_type_init ();
+	ifnet_destroy ();
+	wpa_parser_destroy ();
+	ifnet_init ("net");
+	wpa_parser_init ("wpa_supplicant.conf");
+	printf ("Initialization complete\n");
+	run_all (TRUE);
+	ifnet_destroy ();
+	wpa_parser_destroy ();
+	return 0;
+}
diff --git a/src/settings/plugins/ifnet/tests/wpa_supplicant.conf b/src/settings/plugins/ifnet/tests/wpa_supplicant.conf
new file mode 100644
index 00000000..a2595d42
--- /dev/null
+++ b/src/settings/plugins/ifnet/tests/wpa_supplicant.conf
@@ -0,0 +1,864 @@
+##### Example wpa_supplicant configuration file ###############################
+#
+# This file describes configuration file format and lists all available option.
+# Please also take a look at simpler configuration examples in 'examples'
+# subdirectory.
+#
+# Empty lines and lines starting with # are ignored
+
+# NOTE! This file may contain password information and should probably be made
+# readable only by root user on multiuser systems.
+
+# Note: All file paths in this configuration file should use full (absolute,
+# not relative to working directory) path in order to allow working directory
+# to be changed. This can happen if wpa_supplicant is run in the background.
+
+# Whether to allow wpa_supplicant to update (overwrite) configuration
+#
+# This option can be used to allow wpa_supplicant to overwrite configuration
+# file whenever configuration is changed (e.g., new network block is added with
+# wpa_cli or wpa_gui, or a password is changed). This is required for
+# wpa_cli/wpa_gui to be able to store the configuration changes permanently.
+# Please note that overwriting configuration file will remove the comments from
+# it.
+#update_config=1
+
+# global configuration (shared by all network blocks)
+#
+# Parameters for the control interface. If this is specified, wpa_supplicant
+# will open a control interface that is available for external programs to
+# manage wpa_supplicant. The meaning of this string depends on which control
+# interface mechanism is used. For all cases, the existance of this parameter
+# in configuration is used to determine whether the control interface is
+# enabled.
+#
+# For UNIX domain sockets (default on Linux and BSD): This is a directory that
+# will be created for UNIX domain sockets for listening to requests from
+# external programs (CLI/GUI, etc.) for status information and configuration.
+# The socket file will be named based on the interface name, so multiple
+# wpa_supplicant processes can be run at the same time if more than one
+# interface is used.
+# /var/run/wpa_supplicant is the recommended directory for sockets and by
+# default, wpa_cli will use it when trying to connect with wpa_supplicant.
+#
+# Access control for the control interface can be configured by setting the
+# directory to allow only members of a group to use sockets. This way, it is
+# possible to run wpa_supplicant as root (since it needs to change network
+# configuration and open raw sockets) and still allow GUI/CLI components to be
+# run as non-root users. However, since the control interface can be used to
+# change the network configuration, this access needs to be protected in many
+# cases. By default, wpa_supplicant is configured to use gid 0 (root). If you
+# want to allow non-root users to use the control interface, add a new group
+# and change this value to match with that group. Add users that should have
+# control interface access to this group. If this variable is commented out or
+# not included in the configuration file, group will not be changed from the
+# value it got by default when the directory or socket was created.
+#
+# When configuring both the directory and group, use following format:
+# DIR=/var/run/wpa_supplicant GROUP=wheel
+# DIR=/var/run/wpa_supplicant GROUP=0
+# (group can be either group name or gid)
+#
+# For UDP connections (default on Windows): The value will be ignored. This
+# variable is just used to select that the control interface is to be created.
+# The value can be set to, e.g., udp (ctrl_interface=udp)
+#
+# For Windows Named Pipe: This value can be used to set the security descriptor
+# for controlling access to the control interface. Security descriptor can be
+# set using Security Descriptor String Format (see http://msdn.microsoft.com/
+# library/default.asp?url=/library/en-us/secauthz/security/
+# security_descriptor_string_format.asp). The descriptor string needs to be
+# prefixed with SDDL=. For example, ctrl_interface=SDDL=D: would set an empty
+# DACL (which will reject all connections). See README-Windows.txt for more
+# information about SDDL string format.
+#
+ctrl_interface=/var/run/wpa_supplicant
+
+# IEEE 802.1X/EAPOL version
+# wpa_supplicant is implemented based on IEEE Std 802.1X-2004 which defines
+# EAPOL version 2. However, there are many APs that do not handle the new
+# version number correctly (they seem to drop the frames completely). In order
+# to make wpa_supplicant interoperate with these APs, the version number is set
+# to 1 by default. This configuration value can be used to set it to the new
+# version (2).
+eapol_version=1
+
+# AP scanning/selection
+# By default, wpa_supplicant requests driver to perform AP scanning and then
+# uses the scan results to select a suitable AP. Another alternative is to
+# allow the driver to take care of AP scanning and selection and use
+# wpa_supplicant just to process EAPOL frames based on IEEE 802.11 association
+# information from the driver.
+# 1: wpa_supplicant initiates scanning and AP selection
+# 0: driver takes care of scanning, AP selection, and IEEE 802.11 association
+#    parameters (e.g., WPA IE generation); this mode can also be used with
+#    non-WPA drivers when using IEEE 802.1X mode; do not try to associate with
+#    APs (i.e., external program needs to control association). This mode must
+#    also be used when using wired Ethernet drivers.
+# 2: like 0, but associate with APs using security policy and SSID (but not
+#    BSSID); this can be used, e.g., with ndiswrapper and NDIS drivers to
+#    enable operation with hidden SSIDs and optimized roaming; in this mode,
+#    the network blocks in the configuration file are tried one by one until
+#    the driver reports successful association; each network block should have
+#    explicit security policy (i.e., only one option in the lists) for
+#    key_mgmt, pairwise, group, proto variables
+ap_scan=1
+
+# EAP fast re-authentication
+# By default, fast re-authentication is enabled for all EAP methods that
+# support it. This variable can be used to disable fast re-authentication.
+# Normally, there is no need to disable this.
+fast_reauth=1
+
+# OpenSSL Engine support
+# These options can be used to load OpenSSL engines.
+# The two engines that are supported currently are shown below:
+# They are both from the opensc project (http://www.opensc.org/)
+# By default no engines are loaded.
+# make the opensc engine available
+#opensc_engine_path=/usr/lib64/engine_opensc.so
+# make the pkcs11 engine available
+#pkcs11_engine_path=/usr/lib64/engine_pkcs11.so
+# configure the path to the pkcs11 module required by the pkcs11 engine
+#pkcs11_module_path=/usr/lib64/opensc-pkcs11.so
+
+# Dynamic EAP methods
+# If EAP methods were built dynamically as shared object files, they need to be
+# loaded here before being used in the network blocks. By default, EAP methods
+# are included statically in the build, so these lines are not needed
+#load_dynamic_eap=/usr/lib/wpa_supplicant/eap_tls.so
+#load_dynamic_eap=/usr/lib/wpa_supplicant/eap_md5.so
+
+# Driver interface parameters
+# This field can be used to configure arbitrary driver interace parameters. The
+# format is specific to the selected driver interface. This field is not used
+# in most cases.
+#driver_param="field=value"
+
+# Country code
+# The ISO/IEC alpha2 country code for the country in which this device is
+# currently operating.
+#country=US
+
+# Maximum lifetime for PMKSA in seconds; default 43200
+#dot11RSNAConfigPMKLifetime=43200
+# Threshold for reauthentication (percentage of PMK lifetime); default 70
+#dot11RSNAConfigPMKReauthThreshold=70
+# Timeout for security association negotiation in seconds; default 60
+#dot11RSNAConfigSATimeout=60
+
+# Wi-Fi Protected Setup (WPS) parameters
+
+# Universally Unique IDentifier (UUID; see RFC 4122) of the device
+# If not configured, UUID will be generated based on the local MAC address.
+#uuid=12345678-9abc-def0-1234-56789abcdef0
+
+# Device Name
+# User-friendly description of device; up to 32 octets encoded in UTF-8
+#device_name=Wireless Client
+
+# Manufacturer
+# The manufacturer of the device (up to 64 ASCII characters)
+#manufacturer=Company
+
+# Model Name
+# Model of the device (up to 32 ASCII characters)
+#model_name=cmodel
+
+# Model Number
+# Additional device description (up to 32 ASCII characters)
+#model_number=123
+
+# Serial Number
+# Serial number of the device (up to 32 characters)
+#serial_number=12345
+
+# Primary Device Type
+# Used format: <categ>-<OUI>-<subcateg>
+# categ = Category as an integer value
+# OUI = OUI and type octet as a 4-octet hex-encoded value; 0050F204 for
+#       default WPS OUI
+# subcateg = OUI-specific Sub Category as an integer value
+# Examples:
+#   1-0050F204-1 (Computer / PC)
+#   1-0050F204-2 (Computer / Server)
+#   5-0050F204-1 (Storage / NAS)
+#   6-0050F204-1 (Network Infrastructure / AP)
+#device_type=1-0050F204-1
+
+# OS Version
+# 4-octet operating system version number (hex string)
+#os_version=01020300
+
+# Credential processing
+#   0 = process received credentials internally (default)
+#   1 = do not process received credentials; just pass them over ctrl_iface to
+#	external program(s)
+#   2 = process received credentials internally and pass them over ctrl_iface
+#	to external program(s)
+#wps_cred_processing=0
+
+# network block
+#
+# Each network (usually AP's sharing the same SSID) is configured as a separate
+# block in this configuration file. The network blocks are in preference order
+# (the first match is used).
+#
+# network block fields:
+#
+# disabled:
+#	0 = this network can be used (default)
+#	1 = this network block is disabled (can be enabled through ctrl_iface,
+#	    e.g., with wpa_cli or wpa_gui)
+#
+# id_str: Network identifier string for external scripts. This value is passed
+#	to external action script through wpa_cli as WPA_ID_STR environment
+#	variable to make it easier to do network specific configuration.
+#
+# ssid: SSID (mandatory); either as an ASCII string with double quotation or
+#	as hex string; network name
+#
+# scan_ssid:
+#	0 = do not scan this SSID with specific Probe Request frames (default)
+#	1 = scan with SSID-specific Probe Request frames (this can be used to
+#	    find APs that do not accept broadcast SSID or use multiple SSIDs;
+#	    this will add latency to scanning, so enable this only when needed)
+#
+# bssid: BSSID (optional); if set, this network block is used only when
+#	associating with the AP using the configured BSSID
+#
+# priority: priority group (integer)
+# By default, all networks will get same priority group (0). If some of the
+# networks are more desirable, this field can be used to change the order in
+# which wpa_supplicant goes through the networks when selecting a BSS. The
+# priority groups will be iterated in decreasing priority (i.e., the larger the
+# priority value, the sooner the network is matched against the scan results).
+# Within each priority group, networks will be selected based on security
+# policy, signal strength, etc.
+# Please note that AP scanning with scan_ssid=1 and ap_scan=2 mode are not
+# using this priority to select the order for scanning. Instead, they try the
+# networks in the order that used in the configuration file.
+#
+# mode: IEEE 802.11 operation mode
+# 0 = infrastructure (Managed) mode, i.e., associate with an AP (default)
+# 1 = IBSS (ad-hoc, peer-to-peer)
+# Note: IBSS can only be used with key_mgmt NONE (plaintext and static WEP)
+# and key_mgmt=WPA-NONE (fixed group key TKIP/CCMP). In addition, ap_scan has
+# to be set to 2 for IBSS. WPA-None requires following network block options:
+# proto=WPA, key_mgmt=WPA-NONE, pairwise=NONE, group=TKIP (or CCMP, but not
+# both), and psk must also be set.
+#
+# frequency: Channel frequency in megahertz (MHz) for IBSS, e.g.,
+# 2412 = IEEE 802.11b/g channel 1. This value is used to configure the initial
+# channel for IBSS (adhoc) networks. It is ignored in the infrastructure mode.
+# In addition, this value is only used by the station that creates the IBSS. If
+# an IBSS network with the configured SSID is already present, the frequency of
+# the network will be used instead of this configured value.
+#
+# proto: list of accepted protocols
+# WPA = WPA/IEEE 802.11i/D3.0
+# RSN = WPA2/IEEE 802.11i (also WPA2 can be used as an alias for RSN)
+# If not set, this defaults to: WPA RSN
+#
+# key_mgmt: list of accepted authenticated key management protocols
+# WPA-PSK = WPA pre-shared key (this requires 'psk' field)
+# WPA-EAP = WPA using EAP authentication
+# IEEE8021X = IEEE 802.1X using EAP authentication and (optionally) dynamically
+#	generated WEP keys
+# NONE = WPA is not used; plaintext or static WEP could be used
+# WPA-PSK-SHA256 = Like WPA-PSK but using stronger SHA256-based algorithms
+# WPA-EAP-SHA256 = Like WPA-EAP but using stronger SHA256-based algorithms
+# If not set, this defaults to: WPA-PSK WPA-EAP
+#
+# auth_alg: list of allowed IEEE 802.11 authentication algorithms
+# OPEN = Open System authentication (required for WPA/WPA2)
+# SHARED = Shared Key authentication (requires static WEP keys)
+# LEAP = LEAP/Network EAP (only used with LEAP)
+# If not set, automatic selection is used (Open System with LEAP enabled if
+# LEAP is allowed as one of the EAP methods).
+#
+# pairwise: list of accepted pairwise (unicast) ciphers for WPA
+# CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0]
+# TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0]
+# NONE = Use only Group Keys (deprecated, should not be included if APs support
+#	pairwise keys)
+# If not set, this defaults to: CCMP TKIP
+#
+# group: list of accepted group (broadcast/multicast) ciphers for WPA
+# CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0]
+# TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0]
+# WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key
+# WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key [IEEE 802.11]
+# If not set, this defaults to: CCMP TKIP WEP104 WEP40
+#
+# psk: WPA preshared key; 256-bit pre-shared key
+# The key used in WPA-PSK mode can be entered either as 64 hex-digits, i.e.,
+# 32 bytes or as an ASCII passphrase (in which case, the real PSK will be
+# generated using the passphrase and SSID). ASCII passphrase must be between
+# 8 and 63 characters (inclusive).
+# This field is not needed, if WPA-EAP is used.
+# Note: Separate tool, wpa_passphrase, can be used to generate 256-bit keys
+# from ASCII passphrase. This process uses lot of CPU and wpa_supplicant
+# startup and reconfiguration time can be optimized by generating the PSK only
+# only when the passphrase or SSID has actually changed.
+#
+# eapol_flags: IEEE 802.1X/EAPOL options (bit field)
+# Dynamic WEP key required for non-WPA mode
+# bit0 (1): require dynamically generated unicast WEP key
+# bit1 (2): require dynamically generated broadcast WEP key
+# 	(3 = require both keys; default)
+# Note: When using wired authentication, eapol_flags must be set to 0 for the
+# authentication to be completed successfully.
+#
+# mixed_cell: This option can be used to configure whether so called mixed
+# cells, i.e., networks that use both plaintext and encryption in the same
+# SSID, are allowed when selecting a BSS form scan results.
+# 0 = disabled (default)
+# 1 = enabled
+#
+# proactive_key_caching:
+# Enable/disable opportunistic PMKSA caching for WPA2.
+# 0 = disabled (default)
+# 1 = enabled
+#
+# wep_key0..3: Static WEP key (ASCII in double quotation, e.g. "abcde" or
+# hex without quotation, e.g., 0102030405)
+# wep_tx_keyidx: Default WEP key index (TX) (0..3)
+#
+# peerkey: Whether PeerKey negotiation for direct links (IEEE 802.11e DLS) is
+# allowed. This is only used with RSN/WPA2.
+# 0 = disabled (default)
+# 1 = enabled
+#peerkey=1
+#
+# wpa_ptk_rekey: Maximum lifetime for PTK in seconds. This can be used to
+# enforce rekeying of PTK to mitigate some attacks against TKIP deficiencies.
+#
+# Following fields are only used with internal EAP implementation.
+# eap: space-separated list of accepted EAP methods
+#	MD5 = EAP-MD5 (unsecure and does not generate keying material ->
+#			cannot be used with WPA; to be used as a Phase 2 method
+#			with EAP-PEAP or EAP-TTLS)
+#       MSCHAPV2 = EAP-MSCHAPv2 (cannot be used separately with WPA; to be used
+#		as a Phase 2 method with EAP-PEAP or EAP-TTLS)
+#       OTP = EAP-OTP (cannot be used separately with WPA; to be used
+#		as a Phase 2 method with EAP-PEAP or EAP-TTLS)
+#       GTC = EAP-GTC (cannot be used separately with WPA; to be used
+#		as a Phase 2 method with EAP-PEAP or EAP-TTLS)
+#	TLS = EAP-TLS (client and server certificate)
+#	PEAP = EAP-PEAP (with tunnelled EAP authentication)
+#	TTLS = EAP-TTLS (with tunnelled EAP or PAP/CHAP/MSCHAP/MSCHAPV2
+#			 authentication)
+#	If not set, all compiled in methods are allowed.
+#
+# identity: Identity string for EAP
+#	This field is also used to configure user NAI for
+#	EAP-PSK/PAX/SAKE/GPSK.
+# anonymous_identity: Anonymous identity string for EAP (to be used as the
+#	unencrypted identity with EAP types that support different tunnelled
+#	identity, e.g., EAP-TTLS)
+# password: Password string for EAP. This field can include either the
+#	plaintext password (using ASCII or hex string) or a NtPasswordHash
+#	(16-byte MD4 hash of password) in hash:<32 hex digits> format.
+#	NtPasswordHash can only be used when the password is for MSCHAPv2 or
+#	MSCHAP (EAP-MSCHAPv2, EAP-TTLS/MSCHAPv2, EAP-TTLS/MSCHAP, LEAP).
+#	EAP-PSK (128-bit PSK), EAP-PAX (128-bit PSK), and EAP-SAKE (256-bit
+#	PSK) is also configured using this field. For EAP-GPSK, this is a
+#	variable length PSK.
+# ca_cert: File path to CA certificate file (PEM/DER). This file can have one
+#	or more trusted CA certificates. If ca_cert and ca_path are not
+#	included, server certificate will not be verified. This is insecure and
+#	a trusted CA certificate should always be configured when using
+#	EAP-TLS/TTLS/PEAP. Full path should be used since working directory may
+#	change when wpa_supplicant is run in the background.
+#	On Windows, trusted CA certificates can be loaded from the system
+#	certificate store by setting this to cert_store://<name>, e.g.,
+#	ca_cert="cert_store://CA" or ca_cert="cert_store://ROOT".
+#	Note that when running wpa_supplicant as an application, the user
+#	certificate store (My user account) is used, whereas computer store
+#	(Computer account) is used when running wpasvc as a service.
+# ca_path: Directory path for CA certificate files (PEM). This path may
+#	contain multiple CA certificates in OpenSSL format. Common use for this
+#	is to point to system trusted CA list which is often installed into
+#	directory like /etc/ssl/certs. If configured, these certificates are
+#	added to the list of trusted CAs. ca_cert may also be included in that
+#	case, but it is not required.
+# client_cert: File path to client certificate file (PEM/DER)
+#	Full path should be used since working directory may change when
+#	wpa_supplicant is run in the background.
+#	Alternatively, a named configuration blob can be used by setting this
+#	to blob://<blob name>.
+# private_key: File path to client private key file (PEM/DER/PFX)
+#	When PKCS#12/PFX file (.p12/.pfx) is used, client_cert should be
+#	commented out. Both the private key and certificate will be read from
+#	the PKCS#12 file in this case. Full path should be used since working
+#	directory may change when wpa_supplicant is run in the background.
+#	Windows certificate store can be used by leaving client_cert out and
+#	configuring private_key in one of the following formats:
+#	cert://substring_to_match
+#	hash://certificate_thumbprint_in_hex
+#	for example: private_key="hash://63093aa9c47f56ae88334c7b65a4"
+#	Note that when running wpa_supplicant as an application, the user
+#	certificate store (My user account) is used, whereas computer store
+#	(Computer account) is used when running wpasvc as a service.
+#	Alternatively, a named configuration blob can be used by setting this
+#	to blob://<blob name>.
+# private_key_passwd: Password for private key file (if left out, this will be
+#	asked through control interface)
+# dh_file: File path to DH/DSA parameters file (in PEM format)
+#	This is an optional configuration file for setting parameters for an
+#	ephemeral DH key exchange. In most cases, the default RSA
+#	authentication does not use this configuration. However, it is possible
+#	setup RSA to use ephemeral DH key exchange. In addition, ciphers with
+#	DSA keys always use ephemeral DH keys. This can be used to achieve
+#	forward secrecy. If the file is in DSA parameters format, it will be
+#	automatically converted into DH params.
+# subject_match: Substring to be matched against the subject of the
+#	authentication server certificate. If this string is set, the server
+#	sertificate is only accepted if it contains this string in the subject.
+#	The subject string is in following format:
+#	/C=US/ST=CA/L=San Francisco/CN=Test AS/emailAddress=as@example.com
+# altsubject_match: Semicolon separated string of entries to be matched against
+#	the alternative subject name of the authentication server certificate.
+#	If this string is set, the server sertificate is only accepted if it
+#	contains one of the entries in an alternative subject name extension.
+#	altSubjectName string is in following format: TYPE:VALUE
+#	Example: EMAIL:server@example.com
+#	Example: DNS:server.example.com;DNS:server2.example.com
+#	Following types are supported: EMAIL, DNS, URI
+# phase1: Phase1 (outer authentication, i.e., TLS tunnel) parameters
+#	(string with field-value pairs, e.g., "peapver=0" or
+#	"peapver=1 peaplabel=1")
+#	'peapver' can be used to force which PEAP version (0 or 1) is used.
+#	'peaplabel=1' can be used to force new label, "client PEAP encryption",
+#	to be used during key derivation when PEAPv1 or newer. Most existing
+#	PEAPv1 implementation seem to be using the old label, "client EAP
+#	encryption", and wpa_supplicant is now using that as the default value.
+#	Some servers, e.g., Radiator, may require peaplabel=1 configuration to
+#	interoperate with PEAPv1; see eap_testing.txt for more details.
+#	'peap_outer_success=0' can be used to terminate PEAP authentication on
+#	tunneled EAP-Success. This is required with some RADIUS servers that
+#	implement draft-josefsson-pppext-eap-tls-eap-05.txt (e.g.,
+#	Lucent NavisRadius v4.4.0 with PEAP in "IETF Draft 5" mode)
+#	include_tls_length=1 can be used to force wpa_supplicant to include
+#	TLS Message Length field in all TLS messages even if they are not
+#	fragmented.
+#	sim_min_num_chal=3 can be used to configure EAP-SIM to require three
+#	challenges (by default, it accepts 2 or 3)
+#	result_ind=1 can be used to enable EAP-SIM and EAP-AKA to use
+#	protected result indication.
+#	'crypto_binding' option can be used to control PEAPv0 cryptobinding
+#	behavior:
+#	 * 0 = do not use cryptobinding (default)
+#	 * 1 = use cryptobinding if server supports it
+#	 * 2 = require cryptobinding
+#	EAP-WSC (WPS) uses following options: pin=<Device Password> or
+#	pbc=1.
+# phase2: Phase2 (inner authentication with TLS tunnel) parameters
+#	(string with field-value pairs, e.g., "auth=MSCHAPV2" for EAP-PEAP or
+#	"autheap=MSCHAPV2 autheap=MD5" for EAP-TTLS)
+# Following certificate/private key fields are used in inner Phase2
+# authentication when using EAP-TTLS or EAP-PEAP.
+# ca_cert2: File path to CA certificate file. This file can have one or more
+#	trusted CA certificates. If ca_cert2 and ca_path2 are not included,
+#	server certificate will not be verified. This is insecure and a trusted
+#	CA certificate should always be configured.
+# ca_path2: Directory path for CA certificate files (PEM)
+# client_cert2: File path to client certificate file
+# private_key2: File path to client private key file
+# private_key2_passwd: Password for private key file
+# dh_file2: File path to DH/DSA parameters file (in PEM format)
+# subject_match2: Substring to be matched against the subject of the
+#	authentication server certificate.
+# altsubject_match2: Substring to be matched against the alternative subject
+#	name of the authentication server certificate.
+#
+# fragment_size: Maximum EAP fragment size in bytes (default 1398).
+#	This value limits the fragment size for EAP methods that support
+#	fragmentation (e.g., EAP-TLS and EAP-PEAP). This value should be set
+#	small enough to make the EAP messages fit in MTU of the network
+#	interface used for EAPOL. The default value is suitable for most
+#	cases.
+#
+# EAP-FAST variables:
+# pac_file: File path for the PAC entries. wpa_supplicant will need to be able
+#	to create this file and write updates to it when PAC is being
+#	provisioned or refreshed. Full path to the file should be used since
+#	working directory may change when wpa_supplicant is run in the
+#	background. Alternatively, a named configuration blob can be used by
+#	setting this to blob://<blob name>
+# phase1: fast_provisioning option can be used to enable in-line provisioning
+#         of EAP-FAST credentials (PAC):
+#         0 = disabled,
+#         1 = allow unauthenticated provisioning,
+#         2 = allow authenticated provisioning,
+#         3 = allow both unauthenticated and authenticated provisioning
+#	fast_max_pac_list_len=<num> option can be used to set the maximum
+#		number of PAC entries to store in a PAC list (default: 10)
+#	fast_pac_format=binary option can be used to select binary format for
+#		storing PAC entries in order to save some space (the default
+#		text format uses about 2.5 times the size of minimal binary
+#		format)
+#
+# wpa_supplicant supports number of "EAP workarounds" to work around
+# interoperability issues with incorrectly behaving authentication servers.
+# These are enabled by default because some of the issues are present in large
+# number of authentication servers. Strict EAP conformance mode can be
+# configured by disabling workarounds with eap_workaround=0.
+
+# Example blocks:
+
+# Simple case: WPA-PSK, PSK as an ASCII passphrase, allow all valid ciphers
+network={
+	ssid="simple"
+	psk="very secret passphrase"
+	priority=5
+}
+
+# Same as previous, but request SSID-specific scanning (for APs that reject
+# broadcast SSID)
+network={
+	ssid="second ssid"
+	scan_ssid=1
+	psk="very secret passphrase"
+	priority=2
+}
+
+# Only WPA-PSK is used. Any valid cipher combination is accepted.
+network={
+	ssid="example"
+	proto=WPA
+	key_mgmt=WPA-PSK
+	pairwise=CCMP TKIP
+	group=CCMP TKIP WEP104 WEP40
+	psk=06b4be19da289f475aa46a33cb793029d4ab3db7a23ee92382eb0106c72ac7bb
+	priority=2
+}
+
+# WPA-Personal(PSK) with TKIP and enforcement for frequent PTK rekeying
+network={
+	ssid="example"
+	proto=WPA
+	key_mgmt=WPA-PSK
+	pairwise=TKIP
+	group=TKIP
+	psk="not so secure passphrase"
+	wpa_ptk_rekey=600
+}
+
+# Only WPA-EAP is used. Both CCMP and TKIP is accepted. An AP that used WEP104
+# or WEP40 as the group cipher will not be accepted.
+network={
+	ssid="example"
+	proto=RSN
+	key_mgmt=WPA-EAP
+	pairwise=CCMP TKIP
+	group=CCMP TKIP
+	eap=TLS
+	identity="user@example.com"
+	ca_cert="/etc/cert/ca.pem"
+	client_cert="/etc/cert/user.pem"
+	private_key="/etc/cert/user.prv"
+	private_key_passwd="password"
+	priority=1
+}
+
+# EAP-PEAP/MSCHAPv2 configuration for RADIUS servers that use the new peaplabel
+# (e.g., Radiator)
+network={
+	ssid="example"
+	key_mgmt=WPA-EAP
+	eap=PEAP
+	identity="user@example.com"
+	password="foobar"
+	ca_cert="/etc/cert/ca.pem"
+	phase1="peaplabel=1"
+	phase2="auth=MSCHAPV2"
+	priority=10
+}
+
+# EAP-TTLS/EAP-MD5-Challenge configuration with anonymous identity for the
+# unencrypted use. Real identity is sent only within an encrypted TLS tunnel.
+network={
+	ssid="example"
+	key_mgmt=WPA-EAP
+	eap=TTLS
+	identity="user@example.com"
+	anonymous_identity="anonymous@example.com"
+	password="foobar"
+	ca_cert="/etc/cert/ca.pem"
+	priority=2
+}
+
+# EAP-TTLS/MSCHAPv2 configuration with anonymous identity for the unencrypted
+# use. Real identity is sent only within an encrypted TLS tunnel.
+network={
+	ssid="example"
+	key_mgmt=WPA-EAP
+	eap=TTLS
+	identity="user@example.com"
+	anonymous_identity="anonymous@example.com"
+	password="foobar"
+	ca_cert="/etc/cert/ca.pem"
+	phase2="auth=MSCHAPV2"
+}
+
+# WPA-EAP, EAP-TTLS with different CA certificate used for outer and inner
+# authentication.
+network={
+	ssid="example"
+	key_mgmt=WPA-EAP
+	eap=TTLS
+	# Phase1 / outer authentication
+	anonymous_identity="anonymous@example.com"
+	ca_cert="/etc/cert/ca.pem"
+	# Phase 2 / inner authentication
+	phase2="autheap=TLS"
+	ca_cert2="/etc/cert/ca2.pem"
+	client_cert2="/etc/cer/user.pem"
+	private_key2="/etc/cer/user.prv"
+	private_key2_passwd="password"
+	priority=2
+}
+
+# Both WPA-PSK and WPA-EAP is accepted. Only CCMP is accepted as pairwise and
+# group cipher.
+network={
+	ssid="example"
+	bssid=00:11:22:33:44:55
+	proto=WPA RSN
+	key_mgmt=WPA-PSK WPA-EAP
+	pairwise=CCMP
+	group=CCMP
+	psk=06b4be19da289f475aa46a33cb793029d4ab3db7a23ee92382eb0106c72ac7bb
+}
+
+# Special characters in SSID, so use hex string. Default to WPA-PSK, WPA-EAP
+# and all valid ciphers.
+network={
+	ssid=00010203
+	psk=000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+}
+
+
+# EAP-SIM with a GSM SIM or USIM
+network={
+	ssid="eap-sim-test"
+	key_mgmt=WPA-EAP
+	eap=SIM
+	pin="1234"
+	pcsc=""
+}
+
+
+# EAP-PSK
+network={
+	ssid="eap-psk-test"
+	key_mgmt=WPA-EAP
+	eap=PSK
+	anonymous_identity="eap_psk_user"
+	password=06b4be19da289f475aa46a33cb793029
+	identity="eap_psk_user@example.com"
+}
+
+
+# IEEE 802.1X/EAPOL with dynamically generated WEP keys (i.e., no WPA) using
+# EAP-TLS for authentication and key generation; require both unicast and
+# broadcast WEP keys.
+network={
+	ssid="1xtest"
+	key_mgmt=IEEE8021X
+	eap=TLS
+	identity="user@example.com"
+	ca_cert="/etc/cert/ca.pem"
+	client_cert="/etc/cert/user.pem"
+	private_key="/etc/cert/user.prv"
+	private_key_passwd="password"
+	eapol_flags=3
+}
+
+
+# LEAP with dynamic WEP keys
+network={
+	ssid="leap-example"
+	key_mgmt=IEEE8021X
+	eap=LEAP
+	identity="user"
+	password="foobar"
+}
+
+# EAP-IKEv2 using shared secrets for both server and peer authentication
+network={
+	ssid="ikev2-example"
+	key_mgmt=WPA-EAP
+	eap=IKEV2
+	identity="user"
+	password="foobar"
+}
+
+# EAP-FAST with WPA (WPA or WPA2)
+network={
+	ssid="eap-fast-test"
+	key_mgmt=WPA-EAP
+	eap=FAST
+	anonymous_identity="FAST-000102030405"
+	identity="username"
+	password="password"
+	phase1="fast_provisioning=1"
+	pac_file="/etc/wpa_supplicant.eap-fast-pac"
+}
+
+network={
+	ssid="eap-fast-test"
+	key_mgmt=WPA-EAP
+	eap=FAST
+	anonymous_identity="FAST-000102030405"
+	identity="username"
+	password="password"
+	phase1="fast_provisioning=1"
+	pac_file="blob://eap-fast-pac"
+}
+
+# Plaintext connection (no WPA, no IEEE 802.1X)
+network={
+	ssid="plaintext-test"
+	key_mgmt=NONE
+}
+
+
+# Shared WEP key connection (no WPA, no IEEE 802.1X)
+network={
+	ssid="static-wep-test"
+	key_mgmt=NONE
+	wep_key0="abcde"
+	wep_key1=0102030405
+	wep_key2="1234567890123"
+	wep_tx_keyidx=0
+	priority=5
+}
+
+
+# Shared WEP key connection (no WPA, no IEEE 802.1X) using Shared Key
+# IEEE 802.11 authentication
+network={
+	ssid="static-wep-test2"
+	key_mgmt=NONE
+	wep_key0="abcde"
+	wep_key1=0102030405
+	wep_key2="1234567890123"
+	wep_tx_keyidx=0
+	priority=5
+	auth_alg=SHARED
+}
+
+
+# IBSS/ad-hoc network with WPA-None/TKIP.
+network={
+	ssid="test adhoc"
+	mode=1
+	frequency=2412
+	proto=WPA
+	key_mgmt=WPA-NONE
+	pairwise=NONE
+	group=TKIP
+	psk="secret passphrase"
+}
+
+
+# Catch all example that allows more or less all configuration modes
+network={
+	ssid="example"
+	scan_ssid=1
+	key_mgmt=WPA-EAP WPA-PSK IEEE8021X NONE
+	pairwise=CCMP TKIP
+	group=CCMP TKIP WEP104 WEP40
+	psk="very secret passphrase"
+	eap=TTLS PEAP TLS
+	identity="user@example.com"
+	password="foobar"
+	ca_cert="/etc/cert/ca.pem"
+	client_cert="/etc/cert/user.pem"
+	private_key="/etc/cert/user.prv"
+	private_key_passwd="password"
+	phase1="peaplabel=0"
+}
+
+# Example of EAP-TLS with smartcard (openssl engine)
+network={
+	ssid="example"
+	key_mgmt=WPA-EAP
+	eap=TLS
+	proto=RSN
+	pairwise=CCMP TKIP
+	group=CCMP TKIP
+	identity="user@example.com"
+	ca_cert="/etc/cert/ca.pem"
+	client_cert="/etc/cert/user.pem"
+
+	engine=1
+
+	# The engine configured here must be available. Look at
+	# OpenSSL engine support in the global section.
+	# The key available through the engine must be the private key
+	# matching the client certificate configured above.
+
+	# use the opensc engine
+	#engine_id="opensc"
+	#key_id="45"
+
+	# use the pkcs11 engine
+	engine_id="pkcs11"
+	key_id="id_45"
+
+	# Optional PIN configuration; this can be left out and PIN will be
+	# asked through the control interface
+	pin="1234"
+}
+
+# Example configuration showing how to use an inlined blob as a CA certificate
+# data instead of using external file
+network={
+	ssid="example"
+	key_mgmt=WPA-EAP
+	eap=TTLS
+	identity="user@example.com"
+	anonymous_identity="anonymous@example.com"
+	password="foobar"
+	ca_cert="blob://exampleblob"
+	priority=20
+}
+
+blob-base64-exampleblob={
+SGVsbG8gV29ybGQhCg==
+}
+
+
+# Wildcard match for SSID (plaintext APs only). This example select any
+# open AP regardless of its SSID.
+network={
+	key_mgmt=NONE
+}
+network={
+  ssid="myxjtu2"
+  scan_ssid=1
+  key_mgmt=WPA-PSK
+  psk="xjtudlc3731"
+  disabled=0
+  key_mgmt=NONE
+  wep_key0="12345"
+  wep_key1=1234567890
+  wep_key2="zxcvb"
+  wep_tx_keyidx=1
+  auth_alg=OPEN
+  mode=1
+}
+network={
+	ssid=ab3ace
+	key_mgmt=WPA-EAP
+	eap=TTLS
+	identity="user@example.com"
+	anonymous_identity="anonymous@example.com"
+	password="foobar"
+	ca_cert="blob://exampleblob"
+	priority=20
+}
diff --git a/src/settings/plugins/ifnet/wpa_parser.c b/src/settings/plugins/ifnet/wpa_parser.c
new file mode 100644
index 00000000..da2bc3bb
--- /dev/null
+++ b/src/settings/plugins/ifnet/wpa_parser.c
@@ -0,0 +1,566 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Mu Qiao <qiaomuf@gmail.com>
+ *
+ * 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) 1999-2010 Gentoo Foundation, Inc.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <nm-system-config-interface.h>
+#include "wpa_parser.h"
+#include "net_parser.h"
+#include "net_utils.h"
+
+/* Security information */
+static GHashTable *wsec_table = NULL;
+
+/* Global information used for writing */
+static GHashTable *wsec_global_table = NULL;
+
+static gboolean wpa_parser_data_changed = FALSE;
+
+static long
+wpa_get_long (GHashTable *table, const char *key)
+{
+	return atol (g_hash_table_lookup (table, key));
+}
+
+static void
+destroy_security (GHashTable * network)
+{
+	gpointer key, value;
+	GHashTableIter iter;
+
+	g_return_if_fail (network);
+	g_hash_table_iter_init (&iter, network);
+	while (g_hash_table_iter_next (&iter, &key, &value)) {
+		g_free (key);
+		g_free (value);
+	}
+
+	g_hash_table_destroy (network);
+}
+
+static GHashTable *
+add_security (GHashTable *security)
+{
+	GHashTable *oldsecurity;
+	const char *ssid, *value;
+	char *ssid_key;
+	gboolean is_hex_ssid;
+
+	/* Every security information should have a ssid */
+	ssid = g_hash_table_lookup (security, "ssid");
+	if (!ssid) {
+		destroy_security (security);
+		return NULL;
+	}
+
+	/* Hex format begins with " */
+	is_hex_ssid = (ssid[0] != '"');
+	if ((value = g_hash_table_lookup (security, "disabled")) != NULL) {
+		if (strcmp (value, "1") == 0)
+			return NULL;
+	}
+
+	/* Default priority is 1 */
+	if (g_hash_table_lookup (security, "priority") == NULL)
+		g_hash_table_insert (security, g_strdup ("priority"),
+				     g_strdup ("1"));
+
+	oldsecurity = g_hash_table_lookup (wsec_table, ssid);
+	/* Security with lower priority will be ignored */
+	if (oldsecurity != NULL) {
+		if (wpa_get_long (oldsecurity, "priority") >=
+		    wpa_get_long (security, "priority")) {
+			destroy_security (security);
+			return NULL;
+		} else {
+			g_hash_table_remove (wsec_table, ssid);
+			destroy_security (oldsecurity);
+		}
+	}
+
+	/* format ssid */
+	ssid_key =
+	    is_hex_ssid ? g_strdup_printf ("0x%s",
+					   ssid) :
+	    strip_string (g_strdup (ssid), '"');
+	g_hash_table_insert (wsec_table, ssid_key, security);
+	return security;
+}
+
+static void
+add_key_value (GHashTable * network, gchar * line)
+{
+	gchar **key_value;
+
+	if (g_str_has_prefix (line, "network={"))
+		line += 9;
+	strip_string (line, '{');
+	strip_string (line, '}');
+	if (line[0] == '\0')
+		return;
+	key_value = g_strsplit (line, "=", 2);
+	if (g_strv_length (key_value) != 2) {
+		g_strfreev (key_value);
+		return;
+	}
+	g_strstrip (key_value[0]);
+	g_strstrip (key_value[1]);
+
+	/* Reserve quotes for psk, wep_key, ssid 
+	 * Quotes will determine whether they are hex format */
+	if (strcmp (key_value[0], "psk") != 0
+	    && !g_str_has_prefix (key_value[0], "wep_key")
+	    && strcmp (key_value[0], "ssid") != 0)
+		strip_string (key_value[1], '"');
+	g_hash_table_insert (network, g_strdup (key_value[0]),
+			     g_strdup (key_value[1]));
+	g_strfreev (key_value);
+}
+
+static void
+add_one_wep_key (GHashTable * table, int key_num, gchar * one_wep_key)
+{
+	if (one_wep_key[0] == 's') {
+		//asc key
+		g_hash_table_insert (table,
+				     g_strdup_printf ("wep_key%d", key_num - 1),
+				     g_strdup_printf ("\"%s\"",
+						      one_wep_key + 2));
+	} else {
+		gchar buf[30];
+		int i = 0, j = 0;
+
+		//hex key
+		while (one_wep_key[i] != '\0') {
+			if (one_wep_key[i] != '-')
+				buf[j++] = one_wep_key[i];
+			i++;
+		}
+		buf[j] = '\0';
+		g_hash_table_insert (table,
+				     g_strdup_printf ("wep_key%d", key_num - 1),
+				     g_strdup (buf));
+
+	}
+}
+
+/* Reading wep security information from /etc/conf.d/net. 
+ * This should not be used in futre, use wpa_supplicant instead. */
+static void
+add_keys_from_net ()
+{
+	GList *names = ifnet_get_connection_names ();
+	GList *iter = names;
+	gchar *wep_keys = "(\\[([1-4])\\]\\s+(s:\\w{5}|s:\\w{13}|"
+	    "([\\da-fA-F]{4}\\-){2}[\\da-fA-F]{2}|"
+	    "([\\da-fA-F]{4}\\-){6}[\\da-fA-F]{2})\\s+)";
+	gchar *key_method =
+	    "\\s+key\\s+\\[([1-4])\\]\\s+enc\\s+(open|restricted)";
+	GRegex *regex_keys = g_regex_new (wep_keys, 0, 0, NULL);
+	GRegex *regex_method = g_regex_new (key_method, 0, 0, NULL);
+	GMatchInfo *keys_info;
+	GMatchInfo *method_info;
+
+	while (iter) {
+		gchar *conn_name = iter->data;
+		GHashTable *table;
+		const char *key_str;
+
+		if ((key_str = ifnet_get_data (conn_name, "key")) == NULL) {
+			iter = g_list_next (iter);
+			continue;
+		}
+
+		wpa_add_security (conn_name);
+		table = _get_hash_table (conn_name);
+		/* Give lowest priority */
+		wpa_set_data (conn_name, "priority", "0");
+		g_regex_match (regex_keys, key_str, 0, &keys_info);
+		/* add wep keys */
+		while (g_match_info_matches (keys_info)) {
+			gchar *key_num = g_match_info_fetch (keys_info, 2);
+			gchar *one_wep_key = g_match_info_fetch (keys_info, 3);
+
+			add_one_wep_key (table, atoi (key_num), one_wep_key);
+			g_free (key_num);
+			g_free (one_wep_key);
+			g_match_info_next (keys_info, NULL);
+		}
+		g_match_info_free (keys_info);
+
+		g_regex_match (regex_method, key_str, 0, &method_info);
+		/* set default key index and auth alg */
+		if (g_match_info_matches (method_info)) {
+			gchar *default_idx =
+			    g_match_info_fetch (method_info, 1);
+			gchar *method = g_match_info_fetch (method_info, 2);
+
+			default_idx[0]--;
+			g_hash_table_insert (table, g_strdup ("wep_tx_keyidx"),
+					     default_idx);
+			g_hash_table_insert (table, g_strdup ("auth_alg"),
+					     g_ascii_strup (method, -1));
+		}
+		g_match_info_free (method_info);
+		add_security (table);
+		iter = g_list_next (iter);
+	}
+	g_list_free (names);
+	g_regex_unref (regex_keys);
+	g_regex_unref (regex_method);
+}
+
+static void
+add_global_data (gchar * line)
+{
+	gchar **key_value;
+
+	g_strstrip (line);
+	key_value = g_strsplit (line, "=", 2);
+	if (g_strv_length (key_value) != 2) {
+		PLUGIN_WARN (IFNET_PLUGIN_NAME, "Can't handle this line: %s\n",
+			     line);
+		g_strfreev (key_value);
+		return;
+	}
+	g_hash_table_insert (wsec_global_table,
+			     g_strdup (g_strstrip (key_value[0])),
+			     g_strdup (g_strstrip (key_value[1])));
+	g_strfreev (key_value);
+}
+
+void
+wpa_parser_init (const char *wpa_supplicant_conf)
+{
+	GIOChannel *channel = NULL;
+	gchar *line;
+	gboolean complete = FALSE;
+
+	wpa_parser_data_changed = FALSE;
+	wsec_table = g_hash_table_new (g_str_hash, g_str_equal);
+	wsec_global_table = g_hash_table_new (g_str_hash, g_str_equal);
+
+	if (g_file_test (wpa_supplicant_conf, G_FILE_TEST_IS_REGULAR))
+		channel =
+		    g_io_channel_new_file (wpa_supplicant_conf, "r", NULL);
+	if (channel == NULL) {
+		PLUGIN_WARN (IFNET_PLUGIN_NAME,
+			     "Can't open %s for wireless security",
+			     wpa_supplicant_conf);
+		return;
+	}
+
+	while (g_io_channel_read_line (channel, &line, NULL, NULL, NULL)
+	       != G_IO_STATUS_EOF) {
+		g_strstrip (line);
+		if (line[0] != '#' && line[0] != '\0') {
+			if (strstr (line, "network={") == NULL) {
+				add_global_data (line);
+				g_free (line);
+				continue;
+			} else {
+				GHashTable *network =
+				    g_hash_table_new (g_str_hash, g_str_equal);
+				gchar *tmp;
+
+				do {
+					if (line[0] == '#' || line[0] == '\0') {
+						g_free (line);
+						continue;
+					}
+					/* ignore inline comments */
+					if ((tmp = strchr (line, '#')) != NULL)
+						*tmp = '\0';
+					if (strstr (line, "}") != NULL)
+						complete = TRUE;
+					add_key_value (network, line);
+					g_free (line);
+				} while (complete == FALSE
+					 &&
+					 g_io_channel_read_line
+					 (channel, &line, NULL,
+					  NULL, NULL) != G_IO_STATUS_EOF);
+				add_security (network);
+				//EOF in inner loop
+				if (complete == FALSE) {
+					g_free (line);
+					break;
+				}
+				complete = FALSE;
+			}
+		} else
+			g_free (line);
+	}
+
+	g_io_channel_shutdown (channel, FALSE, NULL);
+	g_io_channel_unref (channel);
+
+	add_keys_from_net ();
+}
+
+const char *
+wpa_get_value (const char *ssid, const char *key)
+{
+	GHashTable *target = g_hash_table_lookup (wsec_table, ssid);
+
+	if (target)
+		return g_hash_table_lookup (target, key);
+	return NULL;
+}
+
+gboolean
+exist_ssid (const char *ssid)
+{
+	return g_hash_table_lookup (wsec_table, ssid) != NULL;
+}
+
+GHashTable *
+_get_hash_table (const char *ssid)
+{
+	return g_hash_table_lookup (wsec_table, ssid);
+}
+
+static gchar *quoted_keys[] =
+    { "identity", "cert", "private", "phase", "password", NULL };
+
+/* tell whether the key needs quotes when writing is performed */
+static gboolean
+need_quote (gchar * key)
+{
+	int i = 0;
+
+	while (quoted_keys[i] != NULL) {
+		if (strstr (key, quoted_keys[i]))
+			return TRUE;
+		i++;
+	}
+	return FALSE;
+}
+
+gboolean
+wpa_flush_to_file (const char *config_file)
+{
+	GIOChannel *channel;
+	GError **error = NULL;
+	gpointer key, value, ssid, security;
+	GHashTableIter iter, iter_security;
+	gchar *out_line;
+	gsize bytes_written;
+	gboolean result = FALSE;
+
+	if (!wpa_parser_data_changed)
+		return TRUE;
+	if (!wsec_table || !wsec_global_table)
+		return FALSE;
+
+	channel = g_io_channel_new_file (config_file, "w", NULL);
+	if (!channel) {
+		PLUGIN_WARN (IFNET_PLUGIN_NAME,
+			     "Can't open file %s for writing", config_file);
+		return FALSE;
+	}
+	g_hash_table_iter_init (&iter, wsec_global_table);
+	PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Writing to %s", config_file);
+	g_io_channel_write_chars (channel,
+				  "#Generated by NetworkManager\n"
+				  "###### Global Configuration ######\n",
+				  -1, &bytes_written, error);
+
+	/* Writing global information */
+	while (g_hash_table_iter_next (&iter, &key, &value)) {
+		out_line =
+		    g_strdup_printf ("%s=%s\n", (gchar *) key, (gchar *) value);
+		g_io_channel_write_chars (channel, out_line, -1, &bytes_written,
+					  error);
+		if (bytes_written == 0 || (error && *error))
+			break;
+		g_free (out_line);
+	}
+	if (error && *error) {
+		PLUGIN_WARN (IFNET_PLUGIN_NAME, "Found error: %s",
+			     (*error)->message);
+		goto done;
+	}
+	g_io_channel_write_chars (channel,
+				  "\n###### Security Configuration ######\n",
+				  -1, &bytes_written, error);
+
+	g_hash_table_iter_init (&iter, wsec_table);
+	/* Writing security */
+	while (g_hash_table_iter_next (&iter, &ssid, &security)) {
+		g_hash_table_iter_init (&iter_security,
+					(GHashTable *) security);
+		g_io_channel_write_chars (channel, "network={\n", -1,
+					  &bytes_written, error);
+		while (g_hash_table_iter_next (&iter_security, &key, &value)) {
+			out_line =
+			    g_strdup_printf (need_quote ((gchar *) key) ?
+					     "\t%s=\"%s\"\n" : "\t%s=%s\n",
+					     (gchar *) key, (gchar *) value);
+			g_io_channel_write_chars (channel, out_line, -1,
+						  &bytes_written, error);
+			if (bytes_written == 0 || (error && *error))
+				break;
+			g_free (out_line);
+		}
+		g_io_channel_write_chars (channel,
+					  "}\n\n", -1, &bytes_written, error);
+
+	}
+	if (error && *error) {
+		PLUGIN_WARN (IFNET_PLUGIN_NAME, "Found error: %s",
+			     (*error)->message);
+		goto done;
+	}
+	g_io_channel_flush (channel, error);
+
+	if (error && *error) {
+		PLUGIN_WARN (IFNET_PLUGIN_NAME, "Found error: %s",
+			     (*error)->message);
+		goto done;
+	}
+	wpa_parser_data_changed = FALSE;
+	result = TRUE;
+done:
+	g_io_channel_shutdown (channel, FALSE, NULL);
+	g_io_channel_unref (channel);
+	return result;
+}
+
+/* If value is NULL, this method will delete old key value pair */
+void
+wpa_set_data (const char *ssid, const char *key, const char *value)
+{
+	gpointer old_key = NULL, old_value = NULL;
+	GHashTable *security = g_hash_table_lookup (wsec_table, ssid);
+	gchar * stripped = NULL;
+
+	g_return_if_fail (security != NULL);
+
+	if (value){
+		stripped = g_strdup(value);
+		if (strcmp (key, "ssid") != 0 && strcmp (key, "psk") != 0
+			&& !g_str_has_prefix (key, "wep_key"))
+			strip_string (stripped, '"');
+	}
+
+	/* Remove old key value pairs */
+	if (g_hash_table_lookup_extended
+	    (security, key, &old_key, &old_value)) {
+		if (stripped && !strcmp(old_value, stripped)){
+			g_free (stripped);
+			return;
+		}
+		g_hash_table_remove (security, old_key);
+		g_free (old_key);
+		g_free (old_value);
+	} else if (!value)
+		return;
+
+	/* Add new key value */
+	if (stripped)
+		g_hash_table_insert (security, g_strdup (key), stripped);
+	wpa_parser_data_changed = TRUE;
+}
+
+gboolean
+wpa_has_security (const char *ssid)
+{
+	return g_hash_table_lookup (wsec_table, ssid) != NULL;
+}
+
+gboolean
+wpa_add_security (const char *ssid)
+{
+	if (wpa_has_security (ssid))
+		return TRUE;
+	else {
+		GHashTable *security =
+		    g_hash_table_new (g_str_hash, g_str_equal);
+		gchar *ssid_i;
+
+		PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Adding security for %s",
+			      ssid);
+		if (g_str_has_prefix (ssid, "0x")) {
+			/* hex ssid */
+			ssid_i = g_strdup (ssid + 2);
+		} else {
+			/* ascii ssid requires quotes */
+			ssid_i = g_strdup_printf ("\"%s\"", ssid);
+		}
+		g_hash_table_insert (security, strdup ("ssid"), ssid_i);
+		g_hash_table_insert (security, strdup ("priority"),
+				     strdup ("1"));
+		g_hash_table_insert (wsec_table, g_strdup (ssid), security);
+		wpa_parser_data_changed = TRUE;
+		return TRUE;
+	}
+}
+
+gboolean
+wpa_delete_security (const char *ssid)
+{
+	gpointer old_key, old_value;
+
+	g_return_val_if_fail (wsec_table != NULL && ssid != NULL, FALSE);
+	PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Deleting security for %s", ssid);
+	if (!g_hash_table_lookup_extended
+	    (wsec_table, ssid, &old_key, &old_value))
+		return FALSE;
+	g_hash_table_remove (wsec_table, old_key);
+	g_free (old_key);
+	destroy_security ((GHashTable *) old_value);
+	wpa_parser_data_changed = TRUE;
+	return TRUE;
+
+}
+
+void
+wpa_parser_destroy (void)
+{
+	GHashTableIter iter;
+	gpointer key;
+	gpointer value;
+
+	/* Destroy security */
+	if (wsec_table) {
+		g_hash_table_iter_init (&iter, wsec_table);
+		while (g_hash_table_iter_next (&iter, &key, &value)) {
+			destroy_security ((GHashTable *) value);
+			g_free (key);
+		}
+
+		g_hash_table_destroy (wsec_table);
+		wsec_table = NULL;
+	}
+
+	/* Destroy global data */
+	if (wsec_global_table) {
+		g_hash_table_iter_init (&iter, wsec_global_table);
+		while (g_hash_table_iter_next (&iter, &key, &value)) {
+			g_free (key);
+			g_free (value);
+		}
+
+		g_hash_table_destroy (wsec_global_table);
+		wsec_global_table = NULL;
+	}
+}
diff --git a/src/settings/plugins/ifnet/wpa_parser.h b/src/settings/plugins/ifnet/wpa_parser.h
new file mode 100644
index 00000000..7fd77a05
--- /dev/null
+++ b/src/settings/plugins/ifnet/wpa_parser.h
@@ -0,0 +1,40 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Mu Qiao <qiaomuf@gmail.com>
+ *
+ * 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) 1999-2010 Gentoo Foundation, Inc.
+ */
+
+#ifndef _WPA_PARSER_H
+#define _WPA_PARSER_H
+#define WPA_SUPPLICANT_CONF "/etc/wpa_supplicant/wpa_supplicant.conf"
+#include <glib.h>
+void wpa_parser_init (const char *wpa_supplicant_conf);
+void wpa_parser_destroy (void);
+
+/* reader functions */
+const char *wpa_get_value (const char *ssid, const char *key);
+gboolean exist_ssid (const char *ssid);
+GHashTable *_get_hash_table (const char *ssid);
+gboolean wpa_has_security (const char *ssid);
+
+/* writer functions */
+gboolean wpa_flush_to_file (const char *config_file);
+void wpa_set_data (const char *ssid, const char *key, const char *value);
+gboolean wpa_add_security (const char *ssid);
+gboolean wpa_delete_security (const char *ssid);
+#endif