summary refs log tree commit diff
path: root/system-settings/plugins/ifnet
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2011-04-21 10:42:53 +0200
committerMichael Biebl <biebl@debian.org>2011-04-21 10:42:53 +0200
commit8baa1aca8dfd35e3190d7d5655eb83b5b901e263 (patch)
treea9ac1e67d0c22a48330c76f08fc5291f85307055 /system-settings/plugins/ifnet
parentf75dd6fd1975146623052b843b182dc32c3fbe46 (diff)
Imported Upstream version 0.8.4.0 upstream/0.8.4.0
Diffstat (limited to 'system-settings/plugins/ifnet')
-rw-r--r--system-settings/plugins/ifnet/Makefile.am57
-rw-r--r--system-settings/plugins/ifnet/Makefile.in904
-rw-r--r--system-settings/plugins/ifnet/connection_parser.c2997
-rw-r--r--system-settings/plugins/ifnet/connection_parser.h43
-rw-r--r--system-settings/plugins/ifnet/net_parser.c635
-rw-r--r--system-settings/plugins/ifnet/net_parser.h46
-rw-r--r--system-settings/plugins/ifnet/net_utils.c966
-rw-r--r--system-settings/plugins/ifnet/net_utils.h80
-rw-r--r--system-settings/plugins/ifnet/nm-ifnet-connection.c251
-rw-r--r--system-settings/plugins/ifnet/nm-ifnet-connection.h49
-rw-r--r--system-settings/plugins/ifnet/plugin.c585
-rw-r--r--system-settings/plugins/ifnet/plugin.h47
-rw-r--r--system-settings/plugins/ifnet/tests/Makefile.am13
-rw-r--r--system-settings/plugins/ifnet/tests/Makefile.in693
-rw-r--r--system-settings/plugins/ifnet/tests/test_all.c392
-rw-r--r--system-settings/plugins/ifnet/wpa_parser.c558
-rw-r--r--system-settings/plugins/ifnet/wpa_parser.h40
17 files changed, 8356 insertions, 0 deletions
diff --git a/system-settings/plugins/ifnet/Makefile.am b/system-settings/plugins/ifnet/Makefile.am
new file mode 100644
index 00000000..86d5ea25
--- /dev/null
+++ b/system-settings/plugins/ifnet/Makefile.am
@@ -0,0 +1,57 @@
+SUBDIRS = . tests
+INCLUDES = \
+	-I$(top_srcdir)/src/system-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/system-settings/plugins/ifnet/Makefile.in b/system-settings/plugins/ifnet/Makefile.in
new file mode 100644
index 00000000..73a6e48f
--- /dev/null
+++ b/system-settings/plugins/ifnet/Makefile.in
@@ -0,0 +1,904 @@
+# 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 = system-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/gtk-doc.m4 $(top_srcdir)/m4/intltool.m4 \
+	$(top_srcdir)/m4/libnl-check.m4 $(top_srcdir)/m4/libtool.m4 \
+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+	$(top_srcdir)/m4/nls.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)/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@
+ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_LIBS = @DBUS_LIBS@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DHCLIENT_PATH = @DHCLIENT_PATH@
+DHCLIENT_VERSION = @DHCLIENT_VERSION@
+DHCPCD_PATH = @DHCPCD_PATH@
+DISABLE_DEPRECATED = @DISABLE_DEPRECATED@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIO_CFLAGS = @GIO_CFLAGS@
+GIO_LIBS = @GIO_LIBS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GMODULE_CFLAGS = @GMODULE_CFLAGS@
+GMODULE_LIBS = @GMODULE_LIBS@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+GUDEV_CFLAGS = @GUDEV_CFLAGS@
+GUDEV_LIBS = @GUDEV_LIBS@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+IPTABLES_PATH = @IPTABLES_PATH@
+KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBDL = @LIBDL@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBM = @LIBM@
+LIBNL_CFLAGS = @LIBNL_CFLAGS@
+LIBNL_LIBS = @LIBNL_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+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@
+POFILES = @POFILES@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@
+RANLIB = @RANLIB@
+RESOLVCONF_PATH = @RESOLVCONF_PATH@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SYSTEM_CA_PATH = @SYSTEM_CA_PATH@
+UDEV_BASE_DIR = @UDEV_BASE_DIR@
+USE_NLS = @USE_NLS@
+UUID_CFLAGS = @UUID_CFLAGS@
+UUID_LIBS = @UUID_LIBS@
+VERSION = @VERSION@
+XGETTEXT = @XGETTEXT@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+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/system-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 system-settings/plugins/ifnet/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu system-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/system-settings/plugins/ifnet/connection_parser.c b/system-settings/plugins/ifnet/connection_parser.c
new file mode 100644
index 00000000..f9fae51f
--- /dev/null
+++ b/system-settings/plugins/ifnet/connection_parser.c
@@ -0,0 +1,2997 @@
+/* -*- 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 <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, gchar * conn_name)
+{
+	gchar *idstr = NULL;
+	gchar *uuid_base = NULL;
+	gchar *uuid = NULL;
+	NMSettingConnection *setting;
+
+	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,
+		   gchar * ssid,
+		   NMSetting8021x * s_8021x, gboolean phase2, GError ** error);
+static gboolean eap_tls_reader (const char *eap_method,
+				gchar * ssid,
+				NMSetting8021x * s_8021x,
+				gboolean phase2, GError ** error);
+
+static gboolean eap_peap_reader (const char *eap_method,
+				 gchar * ssid,
+				 NMSetting8021x * s_8021x,
+				 gboolean phase2, GError ** error);
+
+static gboolean eap_ttls_reader (const char *eap_method,
+				 gchar * ssid,
+				 NMSetting8021x * s_8021x,
+				 gboolean phase2, GError ** error);
+
+typedef struct {
+	const char *method;
+	 gboolean (*reader) (const char *eap_method, gchar * 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,
+		   gchar * ssid,
+		   NMSetting8021x * s_8021x, gboolean phase2, GError ** error)
+{
+	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,
+		gchar * ssid,
+		NMSetting8021x * s_8021x, gboolean phase2, GError ** error)
+{
+	char *value;
+	char *ca_cert = NULL;
+	char *client_cert = NULL;
+	char *privkey = NULL;
+	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,
+		 gchar * ssid,
+		 NMSetting8021x * s_8021x, gboolean phase2, GError ** error)
+{
+	char *ca_cert = NULL;
+	char *inner_auth = NULL;
+	char *peapver = NULL;
+	char *lower;
+	char **list = NULL, **iter;
+	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,
+		 gchar * ssid,
+		 NMSetting8021x * s_8021x, gboolean phase2, GError ** error)
+{
+	gboolean success = FALSE;
+	char *anon_ident = NULL;
+	char *ca_cert = NULL;
+	char *tmp;
+	char **list = NULL, **iter;
+	char *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);
+	if (inner_auth)
+		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 (gchar * conn_name)
+{
+	const gchar *type = ifnet_get_data (conn_name, "type");
+	const gchar *name = conn_name;
+	const gchar *ret_type = NULL;
+
+	if (name && !strcmp ("ppp", type))
+		ret_type = NM_SETTING_PPPOE_SETTING_NAME;
+
+	if (name && !strcmp ("wireless", type))
+		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", 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 (gchar * conn_name, GByteArray ** array, GError ** error)
+{
+	gchar *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, gchar * conn_name,
+			       GError ** error)
+{
+	GByteArray *mac = NULL;
+	NMSettingWired *s_wired = NULL;
+	gchar *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, gchar * conn_name, GError ** error)
+{
+
+	NMSettingIP4Config *ip4_setting =
+	    NM_SETTING_IP4_CONFIG (nm_setting_ip4_config_new ());
+	gchar *value;
+	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) {
+		g_object_set (ip4_setting,
+			      NM_SETTING_IP4_CONFIG_METHOD,
+			      NM_SETTING_IP4_CONFIG_METHOD_AUTO,
+			      NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, FALSE, NULL);
+		PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Using DHCP for %s",
+			      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_PRINT (IFNET_PLUGIN_NAME,
+					      "new address: %d", iblock->ip);
+				PLUGIN_PRINT (IFNET_PLUGIN_NAME,
+					      "ipv4 addresses count: %d",
+					      nm_setting_ip4_config_get_num_addresses
+					      (ip4_setting));
+			} else {
+				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) {
+		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 = (gchar *) ifnet_get_data (conn_name, "dns_search");
+	if (value) {
+		char **searches = NULL;
+
+		strip_string (value, '"');
+
+		searches = g_strsplit (value, " ", 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;
+		gchar *metric_str;
+		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) {
+				metric = strtol (metric_str, NULL, 10);
+				nm_ip4_route_set_metric (route,
+							 (guint32) metric);
+				g_free (metric_str);
+			}
+		}
+
+		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, gchar * 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;
+	gchar *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;
+		gchar *metric_str;
+		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) {
+				metric = strtol (metric_str, NULL, 10);
+				nm_ip6_route_set_metric (route,
+							 (guint32) metric);
+				g_free (metric_str);
+			} 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 (gchar * conn_name,
+				  NMSetting8021x ** s_8021x, GError ** error)
+{
+	GByteArray *array, *mac = NULL;
+	NMSettingWireless *wireless_setting = NULL;
+	gboolean adhoc = FALSE;
+	gchar *value;
+	gchar *type;
+
+	/* PPP over WIFI is not supported */
+	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);
+		char *p = conn_name, *tmp;
+		char buf[33];
+
+		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 (conn_name + 2, value_len - 2);
+			ssid_len = (value_len - 2) / 2;
+			memcpy (buf, tmp, ssid_len);
+			g_free (tmp);
+			p = &buf[0];
+		}
+
+		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 *) p, ssid_len);
+		g_object_set (wireless_setting, NM_SETTING_WIRELESS_SSID, array,
+			      NULL);
+		g_byte_array_free (array, TRUE);
+	} 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 (gchar * ssid, GError ** error)
+{
+	NMSettingWirelessSecurity *wsec;
+	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 (gchar * ssid, gchar * key, int key_idx,
+		 NMSettingWirelessSecurity * s_wsec, GError ** error)
+{
+	gchar *value;
+	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;
+	key = NULL;
+	/* Validate keys */
+	if (strlen (value) == 10 || strlen (value) == 26) {
+		/* Hexadecimal WEP key */
+		char *p = value;
+
+		if (!is_hex (p)) {
+			g_set_error (error, ifnet_plugin_error_quark (),
+				     0, "Invalid hexadecimal WEP key.");
+			goto out;
+		}
+		key = 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;
+
+		}
+
+		key = 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 (key) {
+		nm_setting_wireless_security_set_wep_key (s_wsec, key_idx, key);
+		g_free (key);
+		success = TRUE;
+	}
+
+      out:
+	return success;
+
+}
+
+static gboolean
+add_wep_keys (gchar * 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 (gchar * ssid, GError ** error)
+{
+	gchar *auth_alg;
+	int default_key_idx = 0;
+	gchar *value;
+	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 (gchar * psk, GError ** error)
+{
+	gchar *p, *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.
+	 */
+
+	p = psk;
+	if (p[0] == '"' && psk[strlen (psk) - 1] == '"')
+		quoted = TRUE;
+	if (!quoted && (strlen (psk) == 64)) {
+		/* Verify the hex PSK; 64 digits */
+		if (!is_hex (p)) {
+			g_set_error (error, ifnet_plugin_error_quark (),
+				     0,
+				     "Invalid WPA_PSK (contains non-hexadecimal characters)");
+			goto out;
+		}
+		hashed = g_strdup (psk);
+	} else {
+		strip_string (p, '"');
+
+		/* Length check */
+		if (strlen (p) < 8 || strlen (p) > 63) {
+			g_set_error (error, ifnet_plugin_error_quark (), 0,
+				     "Invalid WPA_PSK (passphrases must be between "
+				     "8 and 63 characters long (inclusive))");
+			goto out;
+		}
+
+		hashed = g_strdup (p);
+	}
+
+	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 (gchar * ssid,
+		  NMSettingWirelessSecurity * wsec,
+		  gboolean group, gboolean adhoc)
+{
+	char *value = NULL, *p;
+	char **list = NULL, **iter;
+	int i = 0;
+
+	p = value = wpa_get_value (ssid, group ? "group" : "pairwise");
+	if (!value)
+		return TRUE;
+
+	list = g_strsplit_set (p, " ", 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 (gchar * ssid, gchar * key_mgmt, gboolean wifi, GError ** error)
+{
+	NMSetting8021x *s_8021x;
+	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 (gchar * ssid, NMSetting8021x ** s_8021x, GError ** error)
+{
+	NMSettingWirelessSecurity *wsec;
+	char *value, *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")) {
+		gchar *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 (gchar *
+				conn_name,
+				NMSetting8021x ** s_8021x, GError ** error)
+{
+	NMSettingWirelessSecurity *wsec = NULL;
+	gchar *ssid;
+	gboolean adhoc = FALSE;
+	gchar *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,
+			       gchar * conn_name, GError ** error)
+{
+	NMSettingPPPOE *s_pppoe;
+	NMSettingPPP *s_ppp;
+	gchar *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 (gchar * 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;
+	gchar *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 =
+		    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,
+	      gchar * 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, gchar * 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,
+		     gchar * 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;
+	}
+
+	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, '"');
+		}
+		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, gchar * conn_name,
+		      gchar * ssid, gboolean hex)
+{
+	ifnet_delete_network (conn_name);
+	ifnet_add_connection (ssid, "wireless");
+
+	wpa_delete_security (conn_name);
+	wpa_add_security (ssid);
+}
+
+static gboolean
+write_wireless_setting (NMConnection * connection,
+			gchar ** conn_name_ptr, gboolean * no_8021x,
+			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;
+	gchar *conn_name = *conn_name_ptr;
+
+	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-printable characters, we need to use the
+	 * hex notation of the SSID instead.
+	 */
+	for (i = 0; i < ssid->len; i++) {
+		if (!isprint (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_strdup (str->str);
+		g_string_free (str, TRUE);
+	} 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);
+	*conn_name_ptr = ifnet_get_data (ssid_str, "name");
+	g_free (ssid_str);
+	return TRUE;
+}
+
+static gboolean
+write_wired_setting (NMConnection * connection, gchar * 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, gchar * conn_name)
+{
+	ifnet_set_data (conn_name, "auto",
+			nm_setting_connection_get_autoconnect (s_con) ? "true" :
+			"false");
+}
+
+static gboolean
+write_ip4_setting (NMConnection * connection, gchar * 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
+		ifnet_set_data (conn_name, "config", "dhcp");
+
+	/* DNS Servers */
+	ifnet_set_data (conn_name, "dns_servers", NULL);
+	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, gchar * 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;
+	gchar *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, gchar * 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)) {
+		gchar *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)) {
+		gchar *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) {
+		gchar *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) {
+		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 (gchar * 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,
+				    gchar * conn_name,
+				    gchar ** nm_conn_name,
+				    gchar * config_file,
+				    gchar * wpa_file, GError ** error)
+{
+	NMSettingConnection *s_con;
+	NMSettingIP6Config *s_ip6;
+	gboolean success = FALSE;
+	const char *type;
+	gboolean no_8021x = FALSE;
+	gboolean wired = FALSE, pppoe = TRUE;
+
+	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, error))
+			goto out;
+	} else if (!strcmp (type, NM_SETTING_PPPOE_SETTING_NAME)) {
+		/* Writing pppoe setting */
+		if (!
+		    (write_pppoe_setting
+		     (conn_name,
+		      NM_SETTING_PPPOE (nm_connection_get_setting
+					(connection, NM_TYPE_SETTING_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;
+	}
+
+	//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);
+
+	if (nm_conn_name)
+		*nm_conn_name = g_strdup (conn_name);
+	success = ifnet_flush_to_file (config_file);
+	if (success)
+		wpa_flush_to_file (wpa_file);
+
+      out:
+	return success;
+}
+
+gboolean
+ifnet_delete_connection_in_parsers (gchar * conn_name,
+				    gchar * config_file, gchar * 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_connection (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_connection (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;
+}
+
+gboolean
+ifnet_add_new_connection (NMConnection * connection,
+			  gchar * config_file, gchar * 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));
+	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;
+	}
+	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_connection (new_name, new_type))
+		success =
+		    ifnet_update_parsers_by_connection (connection, new_name,
+							NULL, config_file,
+							wpa_file, error);
+	PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Added new connection: %s, result: %s",
+		      new_name, success ? "success" : "fail");
+
+      out:
+	if (new_name)
+		g_free (new_name);
+	return success;
+}
diff --git a/system-settings/plugins/ifnet/connection_parser.h b/system-settings/plugins/ifnet/connection_parser.h
new file mode 100644
index 00000000..b006954c
--- /dev/null
+++ b/system-settings/plugins/ifnet/connection_parser.h
@@ -0,0 +1,43 @@
+/* -*- 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 (gchar * 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,
+					     gchar * conn_name,
+					     gchar ** nm_conn_name,
+					     gchar * config_file,
+					     gchar * wpa_file, GError ** error);
+
+gboolean ifnet_delete_connection_in_parsers (gchar * conn_name,
+					     gchar * config_file,
+					     gchar * wpa_file);
+gboolean ifnet_add_new_connection (NMConnection * connection,
+				   gchar * config_file, gchar * wpa_file,
+				   GError ** error);
+#endif
diff --git a/system-settings/plugins/ifnet/net_parser.c b/system-settings/plugins/ifnet/net_parser.c
new file mode 100644
index 00000000..b4a381de
--- /dev/null
+++ b/system-settings/plugins/ifnet/net_parser.c
@@ -0,0 +1,635 @@
+/* -*- 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_connection (gchar * name, gchar * type)
+{
+	if (add_new_connection_config (type, name)) {
+		PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Adding network for %s", name);
+		net_parser_data_changed = TRUE;
+		return TRUE;
+	} else
+		return FALSE;
+}
+
+gboolean
+ifnet_has_connection (gchar * conn_name)
+{
+	return g_hash_table_lookup (conn_table, conn_name) != NULL;
+}
+
+static GHashTable *
+get_connection_config (gchar * 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 (gchar * 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
+gchar *
+ifnet_get_global_setting (gchar * group, gchar * 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;
+}
+
+gchar *
+ifnet_get_data (gchar * conn_name, const gchar * 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 (gchar * conn_name, gchar * key, gchar * value)
+{
+	gpointer orin_key = NULL, orin_value = NULL;
+	GHashTable *conn = g_hash_table_lookup (conn_table, conn_name);
+
+	if (!conn) {
+		PLUGIN_WARN (IFNET_PLUGIN_NAME,
+			     "%s does not exsit!", conn_name);
+		return;
+	}
+	/* Remove existing key value pair */
+	if (g_hash_table_lookup_extended (conn, key, &orin_key, &orin_value)) {
+		g_hash_table_remove (conn, orin_key);
+		g_free (orin_key);
+		g_free (orin_value);
+	}
+	if (value)
+		g_hash_table_insert (conn, g_strdup (key),
+				     strip_string (g_strdup (value), '"'));
+	net_parser_data_changed = TRUE;
+}
+
+// Remember to free return value
+gchar *
+ifnet_get_global_data (const gchar * key)
+{
+	gchar *result = g_hash_table_lookup (global_settings_table, key);
+
+	if (result)
+		result = g_strdup (result);
+	else
+		return NULL;
+	strip_string (result, '"');
+	return result;
+}
+
+// Return names of legal connections
+GList *
+ifnet_get_connection_names ()
+{
+	GList *names = g_hash_table_get_keys (conn_table);
+	GList *result = NULL;
+
+	while (names) {
+		if (!ignore_connection_name (names->data))
+			result = g_list_append (result, names->data);
+		names = names->next;
+	}
+	return 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 (gchar * 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 FALSE;
+	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 (gchar * 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/system-settings/plugins/ifnet/net_parser.h b/system-settings/plugins/ifnet/net_parser.h
new file mode 100644
index 00000000..73a44c85
--- /dev/null
+++ b/system-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);
+gchar *ifnet_get_data (gchar * conn_name, const gchar * key);
+gchar *ifnet_get_global_data (const gchar * key);
+gchar *ifnet_get_global_setting (gchar * group, gchar * key);
+gboolean ifnet_has_connection (gchar * conn_name);
+
+/* Writer functions */
+gboolean ifnet_flush_to_file (gchar * config_file);
+void ifnet_set_data (gchar * conn_name, gchar * key, gchar * value);
+gboolean ifnet_add_connection (gchar * name, gchar * type);
+gboolean ifnet_delete_network (gchar * conn_name);
+#endif
diff --git a/system-settings/plugins/ifnet/net_utils.c b/system-settings/plugins/ifnet/net_utils.c
new file mode 100644
index 00000000..2dc253c5
--- /dev/null
+++ b/system-settings/plugins/ifnet/net_utils.c
@@ -0,0 +1,966 @@
+/* -*- 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 (gchar * value)
+{
+	gchar *p;
+
+	if (!value)
+		return FALSE;
+	p = value;
+	while (*p) {
+		if (!isxdigit (*p)) {
+			return FALSE;
+		}
+		p++;
+	}
+	return TRUE;
+}
+
+gboolean
+is_ascii (gchar * value)
+{
+	gchar *p;
+
+	p = value;
+	while (*p) {
+		if (!isascii (*p)) {
+			return FALSE;
+		}
+		p++;
+	}
+	return TRUE;
+
+}
+
+gboolean
+is_true (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 ()
+{
+	ifnet_destroy ();
+	wpa_parser_destroy ();
+	if (!ifnet_init (CONF_NET_FILE))
+		return FALSE;
+	wpa_parser_init (WPA_SUPPLICANT_CONF);
+	return TRUE;
+}
+
+gchar *
+read_hostname (gchar * 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, gchar * path)
+{
+	gchar *contents = g_strdup_printf ("#Generated by NetworkManager\n"
+					   "hostname=\"%s\"\n", hostname);
+	gboolean result = g_file_set_contents (path, contents, -1, NULL);
+
+	g_free (contents);
+	return result;
+}
+
+gboolean
+is_static_ip4 (gchar * conn_name)
+{
+	gchar *data = ifnet_get_data (conn_name, "config");
+	gchar *dhcp6;
+
+	if (!data)
+		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 (gchar * conn_name)
+{
+	gchar *data = ifnet_get_data (conn_name, "config");
+
+	if (!data)
+		return TRUE;
+	return strstr (data, "dhcp6") == NULL ? TRUE : FALSE;
+}
+
+gboolean
+is_ip4_address (gchar * in_address)
+{
+	gchar *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 (gchar * in_address)
+{
+	struct in6_addr tmp_ip6_addr;
+	gchar *tmp;
+	gchar *address = g_strdup (in_address);
+	gboolean result = FALSE;
+
+	if (!address) {
+		g_free (address);
+		return FALSE;
+	}
+	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 (gchar * 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 (gchar * conn_name, gboolean (*check_fn) (gchar *))
+{
+	gchar *routes = NULL, *tmp, *end;
+
+	g_return_val_if_fail (conn_name != NULL, FALSE);
+	tmp = ifnet_get_data (conn_name, "routes");
+	if (!tmp)
+		return FALSE;
+	routes = g_strdup (tmp);
+	tmp = find_default_gateway_str (routes);
+	if (!tmp) {
+		goto error;
+	}
+	g_strstrip (tmp);
+	if ((end = strstr (tmp, "\"")) != NULL)
+		*end = '\0';
+	if (check_fn (tmp)) {
+		g_free (routes);
+		return TRUE;
+	}
+      error:
+	g_free (routes);
+	return FALSE;
+}
+
+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 (gchar * conn_name)
+{
+	gchar **ipset;
+	guint length;
+	guint i;
+	gchar *ip;
+	guint32 def_gateway;
+	gchar *routes;
+	gchar *pos;
+	ip_block *start = NULL, *current = NULL, *iblock = NULL;
+	gchar *pattern =
+	    "((\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.)\\{(\\d{1,3})\\.\\.(\\d{1,3})\\}(/\\d{1,2}))";
+	GRegex *regex = g_regex_new (pattern, 0, 0, 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);
+	routes = ifnet_get_data (conn_name, "routes");
+	if (routes)
+		def_gateway = get_ip4_gateway (strstr (routes, "default"));
+	else
+		def_gateway = 0;
+	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;
+			GMatchInfo *match_info;
+
+			g_regex_match (regex, ip, 0, &match_info);
+			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);
+	g_regex_unref (regex);
+	return start;
+}
+
+ip6_block *
+convert_ip6_config_block (gchar * 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 (gchar * conn_name)
+{
+	gchar **ipset;
+	guint length;
+	guint i;
+	gchar *ip;
+	gchar *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 (gchar * conn_name)
+{
+	gchar **ipset;
+	guint length;
+	guint i;
+	gchar *ip, *tmp_addr;
+	gchar *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, gchar * conn_name)
+{
+	gchar *dns_servers = ifnet_get_data (conn_name, "dns_servers");
+	gchar **server_list;
+	guint length, i;
+	struct in_addr tmp_ip4_addr;
+	guint32 new_dns;
+
+	if (!dns_servers)
+		return;
+	strip_string (dns_servers, '"');
+	server_list = g_strsplit (dns_servers, " ", 0);
+	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, gchar * conn_name)
+{
+	gchar *dns_servers = ifnet_get_data (conn_name, "dns_servers");
+	gchar **server_list;
+	guint length, i;
+	struct in6_addr tmp_ip6_addr;
+
+	if (!dns_servers)
+		return;
+	strip_string (dns_servers, '"');
+	server_list = g_strsplit (dns_servers, " ", 0);
+	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 (gchar * 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)
+{
+	gchar *dhcp_client = NULL;
+	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);
+		g_free (dhcp_client);
+	} 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/system-settings/plugins/ifnet/net_utils.h b/system-settings/plugins/ifnet/net_utils.h
new file mode 100644
index 00000000..ba7af39c
--- /dev/null
+++ b/system-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 (gchar * path);
+gboolean write_hostname (const gchar * hostname, gchar * path);
+gboolean is_static_ip4 (gchar * conn_name);
+gboolean is_static_ip6 (gchar * conn_name);
+gboolean is_ip4_address (gchar * in_address);
+gboolean is_ip6_address (gchar * in_address);
+gboolean has_ip6_address (gchar * conn_name);
+gboolean has_default_route (gchar * conn_name, gboolean (*check_fn) (gchar *));
+gboolean reload_parsers (void);
+
+ip_block *convert_ip4_config_block (gchar * conn_name);
+ip6_block *convert_ip6_config_block (gchar * conn_name);
+ip_block *convert_ip4_routes_block (gchar * conn_name);
+ip6_block *convert_ip6_routes_block (gchar * conn_name);
+void destroy_ip_block (ip_block * iblock);
+void destroy_ip6_block (ip6_block * iblock);
+
+void set_ip4_dns_servers (NMSettingIP4Config * s_ip4, gchar * conn_name);
+void set_ip6_dns_servers (NMSettingIP6Config * s_ip6, gchar * conn_name);
+
+gchar *strip_string (gchar * str, gchar t);
+gboolean is_managed (gchar * 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 (gchar * value);
+gboolean is_ascii (gchar * value);
+gboolean is_true (gchar * str);
+
+void get_dhcp_hostname_and_client_id (char **hostname, char **client_id);
+
+#endif
diff --git a/system-settings/plugins/ifnet/nm-ifnet-connection.c b/system-settings/plugins/ifnet/nm-ifnet-connection.c
new file mode 100644
index 00000000..e47495cf
--- /dev/null
+++ b/system-settings/plugins/ifnet/nm-ifnet-connection.c
@@ -0,0 +1,251 @@
+/* -*- 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-sysconfig-connection.h>
+#include <nm-system-config-interface.h>
+#include <nm-system-config-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"
+
+static NMSettingsConnectionInterface *parent_settings_connection_iface;
+
+static void settings_connection_interface_init (NMSettingsConnectionInterface *
+						klass);
+
+G_DEFINE_TYPE_EXTENDED (NMIfnetConnection, nm_ifnet_connection,
+			NM_TYPE_SYSCONFIG_CONNECTION, 0,
+			G_IMPLEMENT_INTERFACE
+			(NM_TYPE_SETTINGS_CONNECTION_INTERFACE,
+			 settings_connection_interface_init))
+//    G_DEFINE_TYPE(NMIfnetConnection, nm_ifnet_connection,
+//            NM_TYPE_SYSCONFIG_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 (gchar * conn_name)
+{
+	NMConnection *tmp;
+	GObject *object;
+	GError **error = NULL;
+
+	g_return_val_if_fail (conn_name != NULL, NULL);
+	tmp = ifnet_update_connection_from_config_block (conn_name, error);
+	if (!tmp)
+		return NULL;
+	object = (GObject *) g_object_new (NM_TYPE_IFNET_CONNECTION,
+					   NM_IFNET_CONNECTION_CONN_NAME,
+					   conn_name, NULL);
+	if (!object) {
+		g_object_unref (tmp);
+		return NULL;
+	}
+	nm_sysconfig_connection_update (NM_SYSCONFIG_CONNECTION (object), tmp,
+					FALSE, NULL);
+	g_object_unref (tmp);
+	return NM_IFNET_CONNECTION (object);
+}
+
+static void
+nm_ifnet_connection_init (NMIfnetConnection * connection)
+{
+}
+
+static gboolean
+update (NMSettingsConnectionInterface * connection,
+	NMSettingsConnectionInterfaceUpdateFunc callback, gpointer user_data)
+{
+	GError *error = NULL;
+	gchar *new_conn_name = NULL;
+	gboolean result;
+	NMIfnetConnectionPrivate *priv =
+	    NM_IFNET_CONNECTION_GET_PRIVATE (connection);
+	g_signal_emit (connection, signals[IFNET_CANCEL_MONITORS], 0);
+	if (!ifnet_update_parsers_by_connection
+	    (NM_CONNECTION (connection), priv->conn_name, &new_conn_name,
+	     CONF_NET_FILE, WPA_SUPPLICANT_CONF, &error)) {
+		if (new_conn_name)
+			g_free (new_conn_name);
+		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 FALSE;
+	}
+
+	g_free (priv->conn_name);
+	priv->conn_name = new_conn_name;
+	result =
+	    parent_settings_connection_iface->update (connection, callback,
+						      user_data);
+	if (result)
+		PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Successfully updated %s",
+			      priv->conn_name);
+	g_signal_emit (connection, signals[IFNET_SETUP_MONITORS], 0);
+	return result;
+}
+
+static gboolean
+do_delete (NMSettingsConnectionInterface * connection,
+	   NMSettingsConnectionInterfaceDeleteFunc callback, gpointer user_data)
+{
+	GError *error = NULL;
+	gboolean result;
+	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 FALSE;
+	}
+	result =
+	    parent_settings_connection_iface->delete (connection, callback,
+						      user_data);
+	if (result)
+		PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Successfully deleted %s",
+			      priv->conn_name);
+	g_signal_emit (connection, signals[IFNET_SETUP_MONITORS], 0);
+	return result;
+}
+
+static void
+settings_connection_interface_init (NMSettingsConnectionInterface * iface)
+{
+	parent_settings_connection_iface = g_type_interface_peek_parent (iface);
+	iface->update = update;
+	iface->delete = do_delete;
+}
+
+static void
+set_property (GObject * object, guint prop_id,
+	      const GValue * value, GParamSpec * pspec)
+{
+	NMIfnetConnectionPrivate *priv =
+	    NM_IFNET_CONNECTION_GET_PRIVATE (object);
+	g_return_if_fail (priv);
+
+	switch (prop_id) {
+	case PROP_CONN_NAME:
+		if (priv->conn_name)
+			g_free (priv->conn_name);
+		priv->conn_name = g_strdup (g_value_get_pointer (value));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+get_property (GObject * object, guint prop_id,
+	      GValue * value, GParamSpec * pspec)
+{
+	NMIfnetConnectionPrivate *priv =
+	    NM_IFNET_CONNECTION_GET_PRIVATE (object);
+	g_return_if_fail (priv);
+
+	switch (prop_id) {
+	case PROP_CONN_NAME:
+		g_value_set_pointer (value, priv->conn_name);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+finalize (GObject * object)
+{
+	NMIfnetConnectionPrivate *priv =
+	    NM_IFNET_CONNECTION_GET_PRIVATE (object);
+	g_return_if_fail (priv);
+
+	if (priv->conn_name)
+		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);
+
+	g_type_class_add_private (ifnet_connection_class,
+				  sizeof (NMIfnetConnectionPrivate));
+
+	object_class->set_property = set_property;
+	object_class->get_property = get_property;
+	object_class->finalize = finalize;
+
+	/* Properties */
+	g_object_class_install_property
+	    (object_class, PROP_CONN_NAME,
+	     g_param_spec_pointer (NM_IFNET_CONNECTION_CONN_NAME,
+				   "config_block",
+				   "",
+				   G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+	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/system-settings/plugins/ifnet/nm-ifnet-connection.h b/system-settings/plugins/ifnet/nm-ifnet-connection.h
new file mode 100644
index 00000000..8b3d495f
--- /dev/null
+++ b/system-settings/plugins/ifnet/nm-ifnet-connection.h
@@ -0,0 +1,49 @@
+/* -*- 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-sysconfig-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))
+#define NM_IFNET_CONNECTION_CONN_NAME "connection_name"
+    typedef struct {
+	NMSysconfigConnection parent;
+} NMIfnetConnection;
+
+typedef struct {
+	NMSysconfigConnectionClass parent;
+} NMIfnetConnectionClass;
+
+GType nm_ifnet_connection_get_type (void);
+
+NMIfnetConnection *nm_ifnet_connection_new (gchar * conn_name);
+
+G_END_DECLS
+#endif				/* NM_IFNET_CONNECTION_H */
diff --git a/system-settings/plugins/ifnet/plugin.c b/system-settings/plugins/ifnet/plugin.c
new file mode 100644
index 00000000..94f9e791
--- /dev/null
+++ b/system-settings/plugins/ifnet/plugin.c
@@ -0,0 +1,585 @@
+/* -*- 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 *
+					  system_config_interface_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);
+
+	PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Updating hostname");
+
+	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)) {
+		if (priv->hostname)
+			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 ()
+{
+	gchar *result = NULL;
+
+	result =
+	    ifnet_get_global_setting (IFNET_KEY_FILE_GROUP,
+				      IFNET_KEY_FILE_KEY_MANAGED);
+	if (result) {
+		if (is_true (result)) {
+			g_free (result);
+			return TRUE;
+		} else {
+			g_free (result);
+			return FALSE;
+		}
+	}
+	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);
+		PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Monitoring %s", filename);
+
+	} else
+		PLUGIN_WARN (IFNET_PLUGIN_NAME,
+			     "Monitoring %s failed, error: %s", filename,
+			     error == NULL ? "nothing" : (*error)->message);
+
+	return monitor;
+}
+
+static void
+update_old_connection (gchar * conn_name,
+		       NMIfnetConnection * old_conn,
+		       NMIfnetConnection * new_conn,
+		       SCPluginIfnetPrivate * priv)
+{
+	GError **error = NULL;
+
+	if (!nm_sysconfig_connection_update (NM_SYSCONFIG_CONNECTION (old_conn),
+					     NM_CONNECTION (new_conn), TRUE,
+					     error)) {
+		PLUGIN_WARN (IFNET_PLUGIN_NAME, "error updating: %s",
+			     (error
+			      && (*error)) ? (*error)->message : "(unknown)");
+	} else
+		PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Connection %s updated",
+			      conn_name);
+	g_object_unref (new_conn);
+}
+
+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, g_free, NULL);
+	for (n_iter = conn_names; n_iter; n_iter = g_list_next (n_iter)) {
+		NMIfnetConnection *exported;
+		NMIfnetConnection *old;
+		gchar *conn_name = g_strdup (n_iter->data);
+
+		/* add the new connection */
+		exported = nm_ifnet_connection_new (conn_name);
+		if (!exported) {
+			g_free (conn_name);
+			continue;
+		}
+		g_signal_connect (G_OBJECT (exported), "ifnet_setup_monitors",
+				  G_CALLBACK (setup_monitors), config);
+		g_signal_connect (G_OBJECT (exported), "ifnet_cancel_monitors",
+				  G_CALLBACK (cancel_monitors), config);
+		old = g_hash_table_lookup (priv->config_connections, conn_name);
+		if (old && exported) {
+			gchar *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
+							    (exported),
+							    NM_SETTING_COMPARE_FLAG_EXACT))
+				{
+					PLUGIN_PRINT (IFNET_PLUGIN_NAME,
+						      "Auto refreshing %s",
+						      conn_name);
+					g_signal_emit_by_name (old,
+							       NM_SETTINGS_CONNECTION_INTERFACE_REMOVED);
+					g_hash_table_remove
+					    (priv->config_connections,
+					     conn_name);
+					g_hash_table_insert
+					    (priv->config_connections,
+					     g_strdup (conn_name), exported);
+					if (is_managed (conn_name))
+						g_signal_emit_by_name (self,
+								       NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED,
+								       exported);
+				}
+			} else
+				update_old_connection (conn_name, old,
+						       exported, priv);
+			g_signal_emit_by_name (self,
+					       NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED);
+		} else if (exported) {
+			g_hash_table_insert (priv->config_connections,
+					     g_strdup (conn_name), exported);
+			if (is_managed (conn_name))
+				g_signal_emit_by_name (self,
+						       NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED,
+						       exported);
+		}
+		g_hash_table_insert (new_conn_names, conn_name, 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)) {
+			g_signal_emit_by_name (value,
+					       NM_SETTINGS_CONNECTION_INTERFACE_REMOVED);
+			g_hash_table_remove (priv->config_connections, key);
+		}
+	}
+	g_hash_table_remove_all (new_conn_names);
+	g_hash_table_destroy (new_conn_names);
+	g_list_free (conn_names);
+}
+
+static gboolean
+add_connection (NMSystemConfigInterface * config,
+		NMConnection * connection, GError ** error)
+{
+	gboolean result;
+
+	result = ifnet_add_new_connection (connection, CONF_NET_FILE,
+					   WPA_SUPPLICANT_CONF, error);
+	reload_connections (config);
+	return result;
+}
+
+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);
+	/* Now if we're running in managed mode, let NM know there are new connections */
+	if (!priv->unmanaged_well_known) {
+		GHashTableIter iter;
+		gpointer key;
+		gpointer value;
+
+		g_hash_table_iter_init (&iter, priv->config_connections);
+		while (g_hash_table_iter_next (&iter, &key, &value)) {
+			if (is_managed ((gchar *) key))
+				g_signal_emit_by_name
+				    (self,
+				     NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED,
+				     NM_EXPORTED_CONNECTION (value));
+		}
+	}
+	/* Read hostname */
+	update_system_hostname (self);
+
+	PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Initialzation complete!");
+}
+
+static GSList *
+SCPluginIfnet_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 *
+			      system_config_interface_class)
+{
+	system_config_interface_class->init = SCPluginIfnet_init;
+	system_config_interface_class->get_connections =
+	    SCPluginIfnet_get_connections;
+	system_config_interface_class->get_unmanaged_specs =
+	    get_unmanaged_specs;
+	system_config_interface_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);
+	}
+
+	if (priv->hostname)
+		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/system-settings/plugins/ifnet/plugin.h b/system-settings/plugins/ifnet/plugin.h
new file mode 100644
index 00000000..83099b63
--- /dev/null
+++ b/system-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/system-settings/plugins/ifnet/tests/Makefile.am b/system-settings/plugins/ifnet/tests/Makefile.am
new file mode 100644
index 00000000..17a081f5
--- /dev/null
+++ b/system-settings/plugins/ifnet/tests/Makefile.am
@@ -0,0 +1,13 @@
+INCLUDES=-I$(top_srcdir)/system-settings/plugins/ifnet\
+	 -I$(top_srcdir)/libnm-glib \
+	 -I$(top_srcdir)/libnm-util \
+	 -I$(top_srcdir)/include \
+	 -I$(top_srcdir)/src/system-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_srcdir)/libnm-util/libnm-util.la\
+		    $(top_srcdir)/system-settings/plugins/ifnet/lib-ifnet-io.la\
+		    $(CHECK_LIBS)\
+		    $(GLIB_LIBS)
diff --git a/system-settings/plugins/ifnet/tests/Makefile.in b/system-settings/plugins/ifnet/tests/Makefile.in
new file mode 100644
index 00000000..2a1b9897
--- /dev/null
+++ b/system-settings/plugins/ifnet/tests/Makefile.in
@@ -0,0 +1,693 @@
+# 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 = system-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/gtk-doc.m4 $(top_srcdir)/m4/intltool.m4 \
+	$(top_srcdir)/m4/libnl-check.m4 $(top_srcdir)/m4/libtool.m4 \
+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+	$(top_srcdir)/m4/nls.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_srcdir)/libnm-util/libnm-util.la \
+	$(top_srcdir)/system-settings/plugins/ifnet/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)/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@
+ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_LIBS = @DBUS_LIBS@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DHCLIENT_PATH = @DHCLIENT_PATH@
+DHCLIENT_VERSION = @DHCLIENT_VERSION@
+DHCPCD_PATH = @DHCPCD_PATH@
+DISABLE_DEPRECATED = @DISABLE_DEPRECATED@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIO_CFLAGS = @GIO_CFLAGS@
+GIO_LIBS = @GIO_LIBS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GMODULE_CFLAGS = @GMODULE_CFLAGS@
+GMODULE_LIBS = @GMODULE_LIBS@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+GUDEV_CFLAGS = @GUDEV_CFLAGS@
+GUDEV_LIBS = @GUDEV_LIBS@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+IPTABLES_PATH = @IPTABLES_PATH@
+KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBDL = @LIBDL@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBM = @LIBM@
+LIBNL_CFLAGS = @LIBNL_CFLAGS@
+LIBNL_LIBS = @LIBNL_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+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@
+POFILES = @POFILES@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@
+RANLIB = @RANLIB@
+RESOLVCONF_PATH = @RESOLVCONF_PATH@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SYSTEM_CA_PATH = @SYSTEM_CA_PATH@
+UDEV_BASE_DIR = @UDEV_BASE_DIR@
+USE_NLS = @USE_NLS@
+UUID_CFLAGS = @UUID_CFLAGS@
+UUID_LIBS = @UUID_LIBS@
+VERSION = @VERSION@
+XGETTEXT = @XGETTEXT@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+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$(top_srcdir)/system-settings/plugins/ifnet\
+	 -I$(top_srcdir)/libnm-glib \
+	 -I$(top_srcdir)/libnm-util \
+	 -I$(top_srcdir)/include \
+	 -I$(top_srcdir)/src/system-settings
+
+check_ifnet_SOURCES = test_all.c 
+check_ifnet_CPPFLAGS = $(CHECK_CFLAGS) $(GLIB_CFLAGS)
+check_ifnet_LDADD = $(top_srcdir)/libnm-util/libnm-util.la\
+		    $(top_srcdir)/system-settings/plugins/ifnet/lib-ifnet-io.la\
+		    $(CHECK_LIBS)\
+		    $(GLIB_LIBS)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu system-settings/plugins/ifnet/tests/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu system-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/system-settings/plugins/ifnet/tests/test_all.c b/system-settings/plugins/ifnet/tests/test_all.c
new file mode 100644
index 00000000..eff76af2
--- /dev/null
+++ b/system-settings/plugins/ifnet/tests/test_all.c
@@ -0,0 +1,392 @@
+/* -*- 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 ()
+{
+	gchar *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);
+}
+
+static void
+test_update_connection ()
+{
+	GError **error = NULL;
+	NMConnection *connection;
+
+	connection = ifnet_update_connection_from_config_block ("eth0", error);
+	ASSERT (connection != NULL, "get connection",
+		"get connection failed: %s",
+		error == NULL ? "None" : (*error)->message);
+	ASSERT (ifnet_update_parsers_by_connection
+		(connection, "eth0", NULL, "net.generate",
+		 "wpa_supplicant.conf.generate", error),
+		"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);
+	ASSERT (ifnet_update_parsers_by_connection
+		(connection, "0xab3ace", NULL, "net.generate",
+		 "wpa_supplicant.conf.generate", error),
+		"update connection", "update connection failed %s", "0xab3ace");
+	g_object_unref (connection);
+}
+
+static void
+test_add_connection ()
+{
+	GError **error = NULL;
+	NMConnection *connection;
+
+	connection = ifnet_update_connection_from_config_block ("eth0", error);
+	ASSERT (ifnet_add_new_connection
+		(connection, "net.generate",
+		 "wpa_supplicant.conf.generate", error),
+		"add connection", "add connection failed: %s", "eth0");
+	g_object_unref (connection);
+	connection =
+	    ifnet_update_connection_from_config_block ("myxjtu2", error);
+	ASSERT (ifnet_add_new_connection
+		(connection, "net.generate",
+		 "wpa_supplicant.conf.generate", error),
+		"add connection", "add connection failed: %s", "myxjtu2");
+	g_object_unref (connection);
+}
+
+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 == NULL ? "None" : (*error)->message);
+	ASSERT (ifnet_delete_connection_in_parsers
+		("eth7", "net.generate",
+		 "wpa_supplicant.conf.generate"),
+		"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 == NULL ? "None" : (*error)->message);
+	ASSERT (ifnet_delete_connection_in_parsers
+		("qiaomuf", "net.generate",
+		 "wpa_supplicant.conf.generate"),
+		"delete connection", "delete connection failed: %s", "qiaomuf");
+	g_object_unref (connection);
+}
+
+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/system-settings/plugins/ifnet/wpa_parser.c b/system-settings/plugins/ifnet/wpa_parser.c
new file mode 100644
index 00000000..5e94108e
--- /dev/null
+++ b/system-settings/plugins/ifnet/wpa_parser.c
@@ -0,0 +1,558 @@
+/* -*- 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, gchar * 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;
+	gchar *ssid = g_hash_table_lookup (security, "ssid"), *ssid_key;
+	gchar *value;
+	gboolean is_hex_ssid;
+
+	/* Every security information should have a 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;
+		gchar *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 (gchar * 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 ();
+}
+
+gchar *
+wpa_get_value (gchar * ssid, gchar * key)
+{
+	GHashTable *target = g_hash_table_lookup (wsec_table, ssid);
+
+	if (target)
+		return g_hash_table_lookup (target, key);
+	return NULL;
+}
+
+gboolean
+exist_ssid (gchar * ssid)
+{
+	return g_hash_table_lookup (wsec_table, ssid) != NULL;
+}
+
+GHashTable *
+_get_hash_table (gchar * 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 (gchar * 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 FALSE;
+	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 (gchar * ssid, gchar * key, gchar * value)
+{
+	gpointer orig_key = NULL, orig_value = NULL;
+	GHashTable *security = g_hash_table_lookup (wsec_table, ssid);
+
+	g_return_if_fail (security != NULL);
+
+	/* Remove old key value pairs */
+	if (g_hash_table_lookup_extended
+	    (security, key, &orig_key, &orig_value)) {
+		g_hash_table_remove (security, orig_key);
+		g_free (orig_key);
+		g_free (orig_value);
+	}
+
+	/* Add new key value */
+	if (value) {
+		gchar *new_value = g_strdup (value);
+
+		if (strcmp (key, "ssid") != 0 && strcmp (key, "psk") != 0
+		    && !g_str_has_prefix (key, "wep_key"))
+			strip_string (new_value, '"');
+		g_hash_table_insert (security, g_strdup (key), new_value);
+	}
+	wpa_parser_data_changed = TRUE;
+}
+
+gboolean
+wpa_has_security (gchar * ssid)
+{
+	return g_hash_table_lookup (wsec_table, ssid) != NULL;
+}
+
+gboolean
+wpa_add_security (gchar * ssid)
+{
+	if (wpa_has_security (ssid))
+		return FALSE;
+	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 (gchar * ssid)
+{
+	gpointer orig_key, orig_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, &orig_key, &orig_value))
+		return FALSE;
+	g_hash_table_remove (wsec_table, orig_key);
+	g_free (orig_key);
+	destroy_security ((GHashTable *) orig_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/system-settings/plugins/ifnet/wpa_parser.h b/system-settings/plugins/ifnet/wpa_parser.h
new file mode 100644
index 00000000..55b0ec0c
--- /dev/null
+++ b/system-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 (gchar * wpa_supplicant_conf);
+void wpa_parser_destroy (void);
+
+/* reader functions */
+gchar *wpa_get_value (gchar * ssid, gchar * key);
+gboolean exist_ssid (gchar * ssid);
+GHashTable *_get_hash_table (gchar * ssid);
+gboolean wpa_has_security (gchar * ssid);
+
+/* writer functions */
+gboolean wpa_flush_to_file (gchar * config_file);
+void wpa_set_data (gchar * ssid, gchar * key, gchar * value);
+gboolean wpa_add_security (gchar * ssid);
+gboolean wpa_delete_security (gchar * ssid);
+#endif