summary refs log tree commit diff
path: root/src/system-settings
diff options
context:
space:
mode:
Diffstat (limited to 'src/system-settings')
-rw-r--r--src/system-settings/Makefile.am61
-rw-r--r--src/system-settings/Makefile.in661
-rw-r--r--src/system-settings/nm-default-wired-connection.c308
-rw-r--r--src/system-settings/nm-default-wired-connection.h59
-rw-r--r--src/system-settings/nm-inotify-helper.c212
-rw-r--r--src/system-settings/nm-inotify-helper.h54
-rw-r--r--src/system-settings/nm-polkit-helpers.h32
-rw-r--r--src/system-settings/nm-sysconfig-connection.c658
-rw-r--r--src/system-settings/nm-sysconfig-connection.h56
-rw-r--r--src/system-settings/nm-sysconfig-settings.c1520
-rw-r--r--src/system-settings/nm-sysconfig-settings.h71
-rw-r--r--src/system-settings/nm-system-config-error.c59
-rw-r--r--src/system-settings/nm-system-config-error.h45
-rw-r--r--src/system-settings/nm-system-config-interface.c163
-rw-r--r--src/system-settings/nm-system-config-interface.h145
15 files changed, 4104 insertions, 0 deletions
diff --git a/src/system-settings/Makefile.am b/src/system-settings/Makefile.am
new file mode 100644
index 00000000..3b616b90
--- /dev/null
+++ b/src/system-settings/Makefile.am
@@ -0,0 +1,61 @@
+INCLUDES = -I${top_srcdir} \
+           -I${top_srcdir}/include \
+           -I${top_srcdir}/libnm-util \
+           -I${top_srcdir}/libnm-glib \
+           -I${top_srcdir}/src/logging \
+           -I${top_srcdir}/src \
+           -I${top_builddir}/marshallers
+
+noinst_LTLIBRARIES = libsystem-settings.la
+
+BUILT_SOURCES = \
+	nm-settings-system-glue.h
+
+libsystem_settings_la_SOURCES = \
+	nm-sysconfig-settings.c \
+	nm-sysconfig-settings.h \
+	nm-inotify-helper.c \
+	nm-inotify-helper.h \
+	nm-polkit-helpers.h \
+	nm-system-config-error.c \
+	nm-system-config-error.h \
+	nm-system-config-interface.c \
+	nm-system-config-interface.h \
+	nm-sysconfig-connection.c \
+	nm-sysconfig-connection.h \
+	nm-default-wired-connection.c \
+	nm-default-wired-connection.h
+
+libsystem_settings_la_CPPFLAGS = \
+	$(DBUS_CFLAGS) \
+	$(GLIB_CFLAGS) \
+	$(GMODULE_CFLAGS) \
+	$(POLKIT_CFLAGS) \
+	-DG_DISABLE_DEPRECATED	\
+	-DBINDIR=\"$(bindir)\" \
+	-DSBINDIR=\"$(sbindir)\" \
+	-DLIBEXECDIR=\"$(libexecdir)\" \
+	-DDATADIR=\"$(datadir)\" \
+	-DSYSCONFDIR=\"$(sysconfdir)\" \
+	-DLOCALSTATEDIR=\"$(localstatedir)\" \
+	-DGNOMELOCALEDIR=\"$(datadir)/locale\" \
+	-DPLUGINDIR=\"$(pkglibdir)\"
+
+libsystem_settings_la_LIBADD = \
+	$(top_builddir)/libnm-util/libnm-util.la \
+	$(top_builddir)/libnm-glib/libnm-glib.la \
+	$(top_builddir)/marshallers/libmarshallers.la \
+	$(top_builddir)/src/logging/libnm-logging.la \
+	$(DBUS_LIBS) \
+	$(GLIB_LIBS) \
+	$(GMODULE_LIBS) \
+	$(POLKIT_LIBS)
+
+libsystem_settings_la_LDFLAGS = -rdynamic
+
+nm-settings-system-glue.h: $(top_srcdir)/introspection/nm-settings-system.xml
+	dbus-binding-tool --prefix=nm_settings_system --mode=glib-server --output=$@ $<
+
+CLEANFILES = \
+	$(BUILT_SOURCES)
+
diff --git a/src/system-settings/Makefile.in b/src/system-settings/Makefile.in
new file mode 100644
index 00000000..d86d4188
--- /dev/null
+++ b/src/system-settings/Makefile.in
@@ -0,0 +1,661 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/system-settings
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \
+	$(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/intltool.m4 \
+	$(top_srcdir)/m4/libnl-check.m4 $(top_srcdir)/m4/libtool.m4 \
+	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+	$(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libsystem_settings_la_DEPENDENCIES =  \
+	$(top_builddir)/libnm-util/libnm-util.la \
+	$(top_builddir)/libnm-glib/libnm-glib.la \
+	$(top_builddir)/marshallers/libmarshallers.la \
+	$(top_builddir)/src/logging/libnm-logging.la \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am_libsystem_settings_la_OBJECTS =  \
+	libsystem_settings_la-nm-sysconfig-settings.lo \
+	libsystem_settings_la-nm-inotify-helper.lo \
+	libsystem_settings_la-nm-system-config-error.lo \
+	libsystem_settings_la-nm-system-config-interface.lo \
+	libsystem_settings_la-nm-sysconfig-connection.lo \
+	libsystem_settings_la-nm-default-wired-connection.lo
+libsystem_settings_la_OBJECTS = $(am_libsystem_settings_la_OBJECTS)
+libsystem_settings_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+	$(libsystem_settings_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) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+	--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+	$(LDFLAGS) -o $@
+SOURCES = $(libsystem_settings_la_SOURCES)
+DIST_SOURCES = $(libsystem_settings_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_LIBS = @DBUS_LIBS@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DHCLIENT_PATH = @DHCLIENT_PATH@
+DHCPCD_PATH = @DHCPCD_PATH@
+DISABLE_DEPRECATED = @DISABLE_DEPRECATED@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIO_CFLAGS = @GIO_CFLAGS@
+GIO_LIBS = @GIO_LIBS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GMODULE_CFLAGS = @GMODULE_CFLAGS@
+GMODULE_LIBS = @GMODULE_LIBS@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+GUDEV_CFLAGS = @GUDEV_CFLAGS@
+GUDEV_LIBS = @GUDEV_LIBS@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+IPTABLES_PATH = @IPTABLES_PATH@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBDL = @LIBDL@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBM = @LIBM@
+LIBNL_CFLAGS = @LIBNL_CFLAGS@
+LIBNL_LIBS = @LIBNL_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_LIBS = @NSS_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+POFILES = @POFILES@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@
+RANLIB = @RANLIB@
+RESOLVCONF_PATH = @RESOLVCONF_PATH@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SYSTEM_CA_PATH = @SYSTEM_CA_PATH@
+UDEV_BASE_DIR = @UDEV_BASE_DIR@
+USE_NLS = @USE_NLS@
+UUID_CFLAGS = @UUID_CFLAGS@
+UUID_LIBS = @UUID_LIBS@
+VERSION = @VERSION@
+XGETTEXT = @XGETTEXT@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+INCLUDES = -I${top_srcdir} \
+           -I${top_srcdir}/include \
+           -I${top_srcdir}/libnm-util \
+           -I${top_srcdir}/libnm-glib \
+           -I${top_srcdir}/src/logging \
+           -I${top_srcdir}/src \
+           -I${top_builddir}/marshallers
+
+noinst_LTLIBRARIES = libsystem-settings.la
+BUILT_SOURCES = \
+	nm-settings-system-glue.h
+
+libsystem_settings_la_SOURCES = \
+	nm-sysconfig-settings.c \
+	nm-sysconfig-settings.h \
+	nm-inotify-helper.c \
+	nm-inotify-helper.h \
+	nm-polkit-helpers.h \
+	nm-system-config-error.c \
+	nm-system-config-error.h \
+	nm-system-config-interface.c \
+	nm-system-config-interface.h \
+	nm-sysconfig-connection.c \
+	nm-sysconfig-connection.h \
+	nm-default-wired-connection.c \
+	nm-default-wired-connection.h
+
+libsystem_settings_la_CPPFLAGS = \
+	$(DBUS_CFLAGS) \
+	$(GLIB_CFLAGS) \
+	$(GMODULE_CFLAGS) \
+	$(POLKIT_CFLAGS) \
+	-DG_DISABLE_DEPRECATED	\
+	-DBINDIR=\"$(bindir)\" \
+	-DSBINDIR=\"$(sbindir)\" \
+	-DLIBEXECDIR=\"$(libexecdir)\" \
+	-DDATADIR=\"$(datadir)\" \
+	-DSYSCONFDIR=\"$(sysconfdir)\" \
+	-DLOCALSTATEDIR=\"$(localstatedir)\" \
+	-DGNOMELOCALEDIR=\"$(datadir)/locale\" \
+	-DPLUGINDIR=\"$(pkglibdir)\"
+
+libsystem_settings_la_LIBADD = \
+	$(top_builddir)/libnm-util/libnm-util.la \
+	$(top_builddir)/libnm-glib/libnm-glib.la \
+	$(top_builddir)/marshallers/libmarshallers.la \
+	$(top_builddir)/src/logging/libnm-logging.la \
+	$(DBUS_LIBS) \
+	$(GLIB_LIBS) \
+	$(GMODULE_LIBS) \
+	$(POLKIT_LIBS)
+
+libsystem_settings_la_LDFLAGS = -rdynamic
+CLEANFILES = \
+	$(BUILT_SOURCES)
+
+all: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/system-settings/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --gnu src/system-settings/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
+libsystem-settings.la: $(libsystem_settings_la_OBJECTS) $(libsystem_settings_la_DEPENDENCIES) 
+	$(libsystem_settings_la_LINK)  $(libsystem_settings_la_OBJECTS) $(libsystem_settings_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystem_settings_la-nm-default-wired-connection.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystem_settings_la-nm-inotify-helper.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystem_settings_la-nm-sysconfig-connection.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystem_settings_la-nm-sysconfig-settings.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystem_settings_la-nm-system-config-error.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsystem_settings_la-nm-system-config-interface.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@	depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@	depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@	depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LTCOMPILE) -c -o $@ $<
+
+libsystem_settings_la-nm-sysconfig-settings.lo: nm-sysconfig-settings.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystem_settings_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsystem_settings_la-nm-sysconfig-settings.lo -MD -MP -MF $(DEPDIR)/libsystem_settings_la-nm-sysconfig-settings.Tpo -c -o libsystem_settings_la-nm-sysconfig-settings.lo `test -f 'nm-sysconfig-settings.c' || echo '$(srcdir)/'`nm-sysconfig-settings.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libsystem_settings_la-nm-sysconfig-settings.Tpo $(DEPDIR)/libsystem_settings_la-nm-sysconfig-settings.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-sysconfig-settings.c' object='libsystem_settings_la-nm-sysconfig-settings.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystem_settings_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsystem_settings_la-nm-sysconfig-settings.lo `test -f 'nm-sysconfig-settings.c' || echo '$(srcdir)/'`nm-sysconfig-settings.c
+
+libsystem_settings_la-nm-inotify-helper.lo: nm-inotify-helper.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystem_settings_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsystem_settings_la-nm-inotify-helper.lo -MD -MP -MF $(DEPDIR)/libsystem_settings_la-nm-inotify-helper.Tpo -c -o libsystem_settings_la-nm-inotify-helper.lo `test -f 'nm-inotify-helper.c' || echo '$(srcdir)/'`nm-inotify-helper.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libsystem_settings_la-nm-inotify-helper.Tpo $(DEPDIR)/libsystem_settings_la-nm-inotify-helper.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-inotify-helper.c' object='libsystem_settings_la-nm-inotify-helper.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystem_settings_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsystem_settings_la-nm-inotify-helper.lo `test -f 'nm-inotify-helper.c' || echo '$(srcdir)/'`nm-inotify-helper.c
+
+libsystem_settings_la-nm-system-config-error.lo: nm-system-config-error.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystem_settings_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsystem_settings_la-nm-system-config-error.lo -MD -MP -MF $(DEPDIR)/libsystem_settings_la-nm-system-config-error.Tpo -c -o libsystem_settings_la-nm-system-config-error.lo `test -f 'nm-system-config-error.c' || echo '$(srcdir)/'`nm-system-config-error.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libsystem_settings_la-nm-system-config-error.Tpo $(DEPDIR)/libsystem_settings_la-nm-system-config-error.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-system-config-error.c' object='libsystem_settings_la-nm-system-config-error.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystem_settings_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsystem_settings_la-nm-system-config-error.lo `test -f 'nm-system-config-error.c' || echo '$(srcdir)/'`nm-system-config-error.c
+
+libsystem_settings_la-nm-system-config-interface.lo: nm-system-config-interface.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystem_settings_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsystem_settings_la-nm-system-config-interface.lo -MD -MP -MF $(DEPDIR)/libsystem_settings_la-nm-system-config-interface.Tpo -c -o libsystem_settings_la-nm-system-config-interface.lo `test -f 'nm-system-config-interface.c' || echo '$(srcdir)/'`nm-system-config-interface.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libsystem_settings_la-nm-system-config-interface.Tpo $(DEPDIR)/libsystem_settings_la-nm-system-config-interface.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-system-config-interface.c' object='libsystem_settings_la-nm-system-config-interface.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystem_settings_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsystem_settings_la-nm-system-config-interface.lo `test -f 'nm-system-config-interface.c' || echo '$(srcdir)/'`nm-system-config-interface.c
+
+libsystem_settings_la-nm-sysconfig-connection.lo: nm-sysconfig-connection.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystem_settings_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsystem_settings_la-nm-sysconfig-connection.lo -MD -MP -MF $(DEPDIR)/libsystem_settings_la-nm-sysconfig-connection.Tpo -c -o libsystem_settings_la-nm-sysconfig-connection.lo `test -f 'nm-sysconfig-connection.c' || echo '$(srcdir)/'`nm-sysconfig-connection.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libsystem_settings_la-nm-sysconfig-connection.Tpo $(DEPDIR)/libsystem_settings_la-nm-sysconfig-connection.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-sysconfig-connection.c' object='libsystem_settings_la-nm-sysconfig-connection.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystem_settings_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsystem_settings_la-nm-sysconfig-connection.lo `test -f 'nm-sysconfig-connection.c' || echo '$(srcdir)/'`nm-sysconfig-connection.c
+
+libsystem_settings_la-nm-default-wired-connection.lo: nm-default-wired-connection.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystem_settings_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libsystem_settings_la-nm-default-wired-connection.lo -MD -MP -MF $(DEPDIR)/libsystem_settings_la-nm-default-wired-connection.Tpo -c -o libsystem_settings_la-nm-default-wired-connection.lo `test -f 'nm-default-wired-connection.c' || echo '$(srcdir)/'`nm-default-wired-connection.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libsystem_settings_la-nm-default-wired-connection.Tpo $(DEPDIR)/libsystem_settings_la-nm-default-wired-connection.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='nm-default-wired-connection.c' object='libsystem_settings_la-nm-default-wired-connection.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libsystem_settings_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libsystem_settings_la-nm-default-wired-connection.lo `test -f 'nm-default-wired-connection.c' || echo '$(srcdir)/'`nm-default-wired-connection.c
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	set x; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+	      END { if (nonempty) { for (i in files) print i; }; }'`; \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+install: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) 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:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+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."
+	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+	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: all check install install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-libtool clean-noinstLTLIBRARIES 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
+
+
+nm-settings-system-glue.h: $(top_srcdir)/introspection/nm-settings-system.xml
+	dbus-binding-tool --prefix=nm_settings_system --mode=glib-server --output=$@ $<
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/system-settings/nm-default-wired-connection.c b/src/system-settings/nm-default-wired-connection.c
new file mode 100644
index 00000000..54e00d62
--- /dev/null
+++ b/src/system-settings/nm-default-wired-connection.c
@@ -0,0 +1,308 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service
+ *
+ * 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.
+ *
+ * (C) Copyright 2008 Novell, Inc.
+ * (C) Copyright 2009 Red Hat, Inc.
+ */
+
+#include <netinet/ether.h>
+
+#include <glib/gi18n.h>
+
+#include <NetworkManager.h>
+#include <nm-setting-connection.h>
+#include <nm-setting-wired.h>
+#include <nm-utils.h>
+
+#include "nm-dbus-glib-types.h"
+#include "nm-marshal.h"
+#include "nm-default-wired-connection.h"
+#include "nm-settings-connection-interface.h"
+
+static NMSettingsConnectionInterface *parent_settings_connection_iface;
+
+static void settings_connection_interface_init (NMSettingsConnectionInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (NMDefaultWiredConnection, nm_default_wired_connection, NM_TYPE_SYSCONFIG_CONNECTION, 0,
+                        G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_CONNECTION_INTERFACE,
+                                               settings_connection_interface_init))
+
+#define NM_DEFAULT_WIRED_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEFAULT_WIRED_CONNECTION, NMDefaultWiredConnectionPrivate))
+
+typedef struct {
+	NMDevice *device;
+	GByteArray *mac;
+	gboolean read_only;
+} NMDefaultWiredConnectionPrivate;
+
+enum {
+	PROP_0,
+	PROP_MAC,
+	PROP_DEVICE,
+	PROP_READ_ONLY,
+	LAST_PROP
+};
+
+enum {
+	TRY_UPDATE,
+	DELETED,
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+
+NMDefaultWiredConnection *
+nm_default_wired_connection_new (const GByteArray *mac,
+                                 NMDevice *device,
+                                 gboolean read_only)
+{
+
+	g_return_val_if_fail (mac != NULL, NULL);
+	g_return_val_if_fail (mac->len == ETH_ALEN, NULL);
+	g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
+
+	return g_object_new (NM_TYPE_DEFAULT_WIRED_CONNECTION,
+	                     NM_DEFAULT_WIRED_CONNECTION_MAC, mac,
+	                     NM_DEFAULT_WIRED_CONNECTION_DEVICE, device,
+	                     NM_DEFAULT_WIRED_CONNECTION_READ_ONLY, read_only,
+	                     NULL);
+}
+
+NMDevice *
+nm_default_wired_connection_get_device (NMDefaultWiredConnection *wired)
+{
+	g_return_val_if_fail (NM_IS_DEFAULT_WIRED_CONNECTION (wired), NULL);
+
+	return NM_DEFAULT_WIRED_CONNECTION_GET_PRIVATE (wired)->device;
+}
+
+static gboolean
+update (NMSettingsConnectionInterface *connection,
+	    NMSettingsConnectionInterfaceUpdateFunc callback,
+	    gpointer user_data)
+{
+	NMDefaultWiredConnection *self = NM_DEFAULT_WIRED_CONNECTION (connection);
+
+	/* Keep the object alive over try-update since it might get removed
+	 * from the settings service there, but we still need it for the callback.
+	 */
+	g_object_ref (connection);
+	g_signal_emit (self, signals[TRY_UPDATE], 0);
+	callback (connection, NULL, user_data);
+	g_object_unref (connection);
+	return TRUE;
+}
+
+static gboolean 
+do_delete (NMSettingsConnectionInterface *connection,
+	       NMSettingsConnectionInterfaceDeleteFunc callback,
+	       gpointer user_data)
+{
+	NMDefaultWiredConnection *self = NM_DEFAULT_WIRED_CONNECTION (connection);
+	NMDefaultWiredConnectionPrivate *priv = NM_DEFAULT_WIRED_CONNECTION_GET_PRIVATE (connection);
+
+	g_signal_emit (self, signals[DELETED], 0, priv->mac);
+	return parent_settings_connection_iface->delete (connection, callback, user_data);
+}
+
+/****************************************************************/
+
+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
+nm_default_wired_connection_init (NMDefaultWiredConnection *self)
+{
+}
+
+static GObject *
+constructor (GType type,
+             guint n_construct_params,
+             GObjectConstructParam *construct_params)
+{
+	GObject *object;
+	NMDefaultWiredConnectionPrivate *priv;
+	NMSettingConnection *s_con;
+	NMSettingWired *s_wired;
+	char *id, *uuid;
+
+	object = G_OBJECT_CLASS (nm_default_wired_connection_parent_class)->constructor (type, n_construct_params, construct_params);
+	if (!object)
+		return NULL;
+
+	priv = NM_DEFAULT_WIRED_CONNECTION_GET_PRIVATE (object);
+
+	s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ());
+
+	id = g_strdup_printf (_("Auto %s"), nm_device_get_iface (priv->device));
+	uuid = nm_utils_uuid_generate ();
+
+	g_object_set (s_con,
+		      NM_SETTING_CONNECTION_ID, id,
+		      NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
+		      NM_SETTING_CONNECTION_AUTOCONNECT, TRUE,
+		      NM_SETTING_CONNECTION_UUID, uuid,
+		      NM_SETTING_CONNECTION_READ_ONLY, priv->read_only,
+		      NULL);
+
+	g_free (id);
+	g_free (uuid);
+
+	nm_connection_add_setting (NM_CONNECTION (object), NM_SETTING (s_con));
+
+	/* Lock the connection to the specific device */
+	s_wired = NM_SETTING_WIRED (nm_setting_wired_new ());
+	g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, priv->mac, NULL);
+	nm_connection_add_setting (NM_CONNECTION (object), NM_SETTING (s_wired));
+
+	return object;
+}
+
+static void
+finalize (GObject *object)
+{
+	NMDefaultWiredConnectionPrivate *priv = NM_DEFAULT_WIRED_CONNECTION_GET_PRIVATE (object);
+
+	g_object_unref (priv->device);
+	g_byte_array_free (priv->mac, TRUE);
+
+	G_OBJECT_CLASS (nm_default_wired_connection_parent_class)->finalize (object);
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+              GValue *value, GParamSpec *pspec)
+{
+	NMDefaultWiredConnectionPrivate *priv = NM_DEFAULT_WIRED_CONNECTION_GET_PRIVATE (object);
+
+	switch (prop_id) {
+	case PROP_MAC:
+		g_value_set_pointer (value, priv->mac);
+		break;
+	case PROP_DEVICE:
+		g_value_set_object (value, priv->device);
+		break;
+	case PROP_READ_ONLY:
+		g_value_set_boolean (value, priv->read_only);
+		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)
+{
+	NMDefaultWiredConnectionPrivate *priv = NM_DEFAULT_WIRED_CONNECTION_GET_PRIVATE (object);
+	GByteArray *array;
+
+	switch (prop_id) {
+	case PROP_MAC:
+		/* Construct only */
+		array = g_value_get_pointer (value);
+		if (priv->mac) {
+			g_byte_array_free (priv->mac, TRUE);
+			priv->mac = NULL;
+		}
+		if (array) {
+			g_return_if_fail (array->len == ETH_ALEN);
+			priv->mac = g_byte_array_sized_new (array->len);
+			g_byte_array_append (priv->mac, array->data, ETH_ALEN);
+		}
+		break;
+	case PROP_DEVICE:
+		if (priv->device)
+			g_object_unref (priv->device);
+		priv->device = g_value_dup_object (value);
+		break;
+	case PROP_READ_ONLY:
+		priv->read_only = g_value_get_boolean (value);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nm_default_wired_connection_class_init (NMDefaultWiredConnectionClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (NMDefaultWiredConnectionPrivate));
+
+	/* Virtual methods */
+	object_class->constructor = constructor;
+	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_MAC,
+		 g_param_spec_pointer (NM_DEFAULT_WIRED_CONNECTION_MAC,
+		                       "MAC",
+		                       "MAC Address",
+		                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+	g_object_class_install_property
+		(object_class, PROP_DEVICE,
+		 g_param_spec_object (NM_DEFAULT_WIRED_CONNECTION_DEVICE,
+		                       "Device",
+		                       "Device",
+		                       NM_TYPE_DEVICE,
+		                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+	g_object_class_install_property
+		(object_class, PROP_READ_ONLY,
+		 g_param_spec_boolean (NM_DEFAULT_WIRED_CONNECTION_READ_ONLY,
+		                       "ReadOnly",
+		                       "Read Only",
+		                       FALSE,
+		                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+	/* Signals */
+	signals[TRY_UPDATE] =
+		g_signal_new ("try-update",
+			      G_OBJECT_CLASS_TYPE (object_class),
+			      G_SIGNAL_RUN_LAST,
+			      0, NULL, NULL,
+			      g_cclosure_marshal_VOID__VOID,
+			      G_TYPE_NONE, 0);
+
+	/* The 'deleted' signal is used to signal intentional deletions (like
+	 * updating or user-requested deletion) rather than using the
+	 * superclass' 'removed' signal, since that signal doesn't have the
+	 * semantics we want; it gets emitted as a side-effect of various operations
+	 * and is meant more for D-Bus clients instead of in-service uses.
+	 */
+	signals[DELETED] =
+		g_signal_new ("deleted",
+			      G_OBJECT_CLASS_TYPE (object_class),
+			      G_SIGNAL_RUN_LAST,
+			      0, NULL, NULL,
+			      g_cclosure_marshal_VOID__POINTER,
+			      G_TYPE_NONE, 1, G_TYPE_POINTER);
+}
diff --git a/src/system-settings/nm-default-wired-connection.h b/src/system-settings/nm-default-wired-connection.h
new file mode 100644
index 00000000..de89b675
--- /dev/null
+++ b/src/system-settings/nm-default-wired-connection.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service
+ *
+ * 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.
+ *
+ * (C) Copyright 2008 Novell, Inc.
+ * (C) Copyright 2009 Red Hat, Inc.
+ */
+
+#ifndef NM_DEFAULT_WIRED_CONNECTION_H
+#define NM_DEFAULT_WIRED_CONNECTION_H
+
+#include "nm-sysconfig-connection.h"
+#include "nm-device.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_DEFAULT_WIRED_CONNECTION            (nm_default_wired_connection_get_type ())
+#define NM_DEFAULT_WIRED_CONNECTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEFAULT_WIRED_CONNECTION, NMDefaultWiredConnection))
+#define NM_DEFAULT_WIRED_CONNECTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEFAULT_WIRED_CONNECTION, NMDefaultWiredConnectionClass))
+#define NM_IS_DEFAULT_WIRED_CONNECTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEFAULT_WIRED_CONNECTION))
+#define NM_IS_DEFAULT_WIRED_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DEFAULT_WIRED_CONNECTION))
+#define NM_DEFAULT_WIRED_CONNECTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEFAULT_WIRED_CONNECTION, NMDefaultWiredConnectionClass))
+
+#define NM_DEFAULT_WIRED_CONNECTION_MAC   "mac"
+#define NM_DEFAULT_WIRED_CONNECTION_DEVICE "device"
+#define NM_DEFAULT_WIRED_CONNECTION_READ_ONLY "read-only"
+
+typedef struct {
+	NMSysconfigConnection parent;
+} NMDefaultWiredConnection;
+
+typedef struct {
+	NMSysconfigConnectionClass parent;
+} NMDefaultWiredConnectionClass;
+
+GType nm_default_wired_connection_get_type (void);
+
+NMDefaultWiredConnection *nm_default_wired_connection_new (const GByteArray *mac,
+                                                           NMDevice *device,
+                                                           gboolean read_only);
+
+NMDevice *nm_default_wired_connection_get_device (NMDefaultWiredConnection *wired);
+
+G_END_DECLS
+
+#endif /* NM_DEFAULT_WIRED_CONNECTION_H */
diff --git a/src/system-settings/nm-inotify-helper.c b/src/system-settings/nm-inotify-helper.c
new file mode 100644
index 00000000..0ee168e5
--- /dev/null
+++ b/src/system-settings/nm-inotify-helper.c
@@ -0,0 +1,212 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service
+ *
+ * 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.
+ *
+ * (C) Copyright 2008 Red Hat, Inc.
+ */
+
+#include <unistd.h>
+#include <string.h>
+#include <sys/inotify.h>
+#include <glib.h>
+
+#include "nm-marshal.h"
+#include "nm-inotify-helper.h"
+#include "nm-logging.h"
+
+G_DEFINE_TYPE (NMInotifyHelper, nm_inotify_helper, G_TYPE_OBJECT)
+
+#define NM_INOTIFY_HELPER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_INOTIFY_HELPER, NMInotifyHelperPrivate))
+
+typedef struct {
+	int ifd;
+
+	GHashTable *wd_refs;
+} NMInotifyHelperPrivate;
+
+/* Signals */
+enum {
+	EVENT,
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+int
+nm_inotify_helper_add_watch (NMInotifyHelper *self, const char *path)
+{
+	NMInotifyHelperPrivate *priv = NM_INOTIFY_HELPER_GET_PRIVATE (self);
+	int wd;
+	guint32 refcount;
+
+	g_return_val_if_fail (priv->ifd >= 0, -1);
+
+	/* We only care about modifications since we're just trying to get change
+	 * notifications on hardlinks.
+	 */
+
+	wd = inotify_add_watch (priv->ifd, path, IN_CLOSE_WRITE);
+	if (wd < 0)
+		return -1;
+
+	refcount = GPOINTER_TO_UINT (g_hash_table_lookup (priv->wd_refs, GINT_TO_POINTER (wd)));
+	refcount++;
+	g_hash_table_replace (priv->wd_refs, GINT_TO_POINTER (wd), GUINT_TO_POINTER (refcount));
+
+	return wd;
+}
+
+void
+nm_inotify_helper_remove_watch (NMInotifyHelper *self, int wd)
+{
+	NMInotifyHelperPrivate *priv = NM_INOTIFY_HELPER_GET_PRIVATE (self);
+	guint32 refcount;
+
+	g_return_if_fail (priv->ifd >= 0);
+
+	refcount = GPOINTER_TO_UINT (g_hash_table_lookup (priv->wd_refs, GINT_TO_POINTER (wd)));
+	if (!refcount)
+		return;
+
+	refcount--;
+	if (!refcount) {
+		g_hash_table_remove (priv->wd_refs, GINT_TO_POINTER (wd));
+		inotify_rm_watch (priv->ifd, wd);
+	} else
+		g_hash_table_replace (priv->wd_refs, GINT_TO_POINTER (wd), GUINT_TO_POINTER (refcount));
+}
+
+static gboolean
+inotify_event_handler (GIOChannel *channel, GIOCondition cond, gpointer user_data)
+{
+	NMInotifyHelper *self = NM_INOTIFY_HELPER (user_data);
+	struct inotify_event evt;
+
+	/* read the notifications from the watch descriptor */
+	while (g_io_channel_read_chars (channel, (gchar *) &evt, sizeof (struct inotify_event), NULL, NULL) == G_IO_STATUS_NORMAL) {
+		gchar filename[PATH_MAX + 1];
+
+		filename[0] = '\0';
+		if (evt.len > 0) {
+			g_io_channel_read_chars (channel,
+			                        filename,
+			                        evt.len > PATH_MAX ? PATH_MAX : evt.len,
+			                        NULL, NULL);
+		}
+
+		if (!(evt.mask & IN_IGNORED))
+			g_signal_emit (self, signals[EVENT], 0, &evt, &filename[0]);
+	}
+
+	return TRUE;
+}
+
+static gboolean
+init_inotify (NMInotifyHelper *self)
+{
+	NMInotifyHelperPrivate *priv = NM_INOTIFY_HELPER_GET_PRIVATE (self);
+	GIOChannel *channel;
+	guint source_id;
+
+	priv->ifd = inotify_init ();
+	if (priv->ifd == -1) {
+		nm_log_warn (LOGD_SYS_SET, "couldn't initialize inotify");
+		return FALSE;
+	}
+
+	/* Watch the inotify descriptor for file/directory change events */
+	channel = g_io_channel_unix_new (priv->ifd);
+	if (!channel) {
+		nm_log_warn (LOGD_SYS_SET, "couldn't create new GIOChannel");
+		close (priv->ifd);
+		priv->ifd = -1;
+		return FALSE;
+	}
+
+	g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, NULL);
+	g_io_channel_set_encoding (channel, NULL, NULL); 
+
+	source_id = g_io_add_watch (channel,
+	                            G_IO_IN | G_IO_ERR,
+	                            (GIOFunc) inotify_event_handler,
+	                            (gpointer) self);
+	g_io_channel_unref (channel);
+	return TRUE;
+}
+
+NMInotifyHelper *
+nm_inotify_helper_get (void)
+{
+	static NMInotifyHelper *singleton = NULL;
+
+	if (!singleton) {
+		singleton = (NMInotifyHelper *) g_object_new (NM_TYPE_INOTIFY_HELPER, NULL);
+		if (!singleton)
+			return NULL;
+
+		if (!init_inotify (singleton)) {
+			g_object_unref (singleton);
+			return NULL;
+		}
+	} else
+		g_object_ref (singleton);
+
+	g_assert (singleton);
+	return singleton;
+}
+
+static void
+nm_inotify_helper_init (NMInotifyHelper *self)
+{
+	NMInotifyHelperPrivate *priv = NM_INOTIFY_HELPER_GET_PRIVATE (self);
+
+	priv->wd_refs = g_hash_table_new (g_direct_hash, g_direct_equal);
+}
+
+static void
+finalize (GObject *object)
+{
+	NMInotifyHelperPrivate *priv = NM_INOTIFY_HELPER_GET_PRIVATE (object);
+
+	if (priv->ifd >= 0)
+		close (priv->ifd);
+
+	g_hash_table_destroy (priv->wd_refs);
+
+	G_OBJECT_CLASS (nm_inotify_helper_parent_class)->finalize (object);
+}
+
+static void
+nm_inotify_helper_class_init (NMInotifyHelperClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (NMInotifyHelperPrivate));
+
+	/* Virtual methods */
+	object_class->finalize = finalize;
+
+	/* Signals */
+	signals[EVENT] =
+		g_signal_new ("event",
+		              G_OBJECT_CLASS_TYPE (object_class),
+		              G_SIGNAL_RUN_LAST,
+		              G_STRUCT_OFFSET (NMInotifyHelperClass, event),
+		              NULL, NULL,
+		              _nm_marshal_VOID__POINTER_STRING,
+		              G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_STRING);
+}
+
diff --git a/src/system-settings/nm-inotify-helper.h b/src/system-settings/nm-inotify-helper.h
new file mode 100644
index 00000000..10d43ac9
--- /dev/null
+++ b/src/system-settings/nm-inotify-helper.h
@@ -0,0 +1,54 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service
+ *
+ * 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.
+ *
+ * (C) Copyright 2008 Red Hat, Inc.
+ */
+
+#ifndef __INOTIFY_HELPER_H__
+#define __INOTIFY_HELPER_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <sys/inotify.h>
+
+#define NM_TYPE_INOTIFY_HELPER            (nm_inotify_helper_get_type ())
+#define NM_INOTIFY_HELPER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_INOTIFY_HELPER, NMInotifyHelper))
+#define NM_INOTIFY_HELPER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_INOTIFY_HELPER, NMInotifyHelperClass))
+#define NM_IS_INOTIFY_HELPER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_INOTIFY_HELPER))
+#define NM_IS_INOTIFY_HELPER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_INOTIFY_HELPER))
+#define NM_INOTIFY_HELPER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_INOTIFY_HELPER, NMInotifyHelperClass))
+
+typedef struct {
+	GObject parent;
+} NMInotifyHelper;
+
+typedef struct {
+	GObjectClass parent;
+
+	/* signals */
+	void (* event) (NMInotifyHelper *helper, struct inotify_event *evt, const char *filename);
+} NMInotifyHelperClass;
+
+GType nm_inotify_helper_get_type (void);
+
+NMInotifyHelper * nm_inotify_helper_get (void);
+
+int nm_inotify_helper_add_watch (NMInotifyHelper *helper, const char *path);
+
+void nm_inotify_helper_remove_watch (NMInotifyHelper *helper, int wd);
+
+#endif  /* __INOTIFY_HELPER_H__ */
diff --git a/src/system-settings/nm-polkit-helpers.h b/src/system-settings/nm-polkit-helpers.h
new file mode 100644
index 00000000..c26fcc2c
--- /dev/null
+++ b/src/system-settings/nm-polkit-helpers.h
@@ -0,0 +1,32 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service
+ *
+ * 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.
+ *
+ * (C) Copyright 2008 Novell, Inc.
+ * (C) Copyright 2008 Red Hat, Inc.
+ */
+
+#ifndef NM_POLKIT_HELPERS_H
+#define NM_POLKIT_HELPERS_H
+
+#include <polkit/polkit.h>
+
+#define NM_SYSCONFIG_POLICY_ACTION_CONNECTION_MODIFY    "org.freedesktop.network-manager-settings.system.modify"
+#define NM_SYSCONFIG_POLICY_ACTION_WIFI_SHARE_PROTECTED "org.freedesktop.network-manager-settings.system.wifi.share.protected"
+#define NM_SYSCONFIG_POLICY_ACTION_WIFI_SHARE_OPEN      "org.freedesktop.network-manager-settings.system.wifi.share.open"
+#define NM_SYSCONFIG_POLICY_ACTION_HOSTNAME_MODIFY      "org.freedesktop.network-manager-settings.system.hostname.modify"
+
+#endif /* NM_POLKIT_HELPERS_H */
diff --git a/src/system-settings/nm-sysconfig-connection.c b/src/system-settings/nm-sysconfig-connection.c
new file mode 100644
index 00000000..f46895ac
--- /dev/null
+++ b/src/system-settings/nm-sysconfig-connection.c
@@ -0,0 +1,658 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service
+ *
+ * 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.
+ *
+ * (C) Copyright 2008 Novell, Inc.
+ * (C) Copyright 2008 - 2009 Red Hat, Inc.
+ */
+
+#include <NetworkManager.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include "nm-sysconfig-connection.h"
+#include "nm-system-config-error.h"
+#include "nm-dbus-glib-types.h"
+#include "nm-settings-connection-interface.h"
+#include "nm-settings-interface.h"
+#include "nm-polkit-helpers.h"
+#include "nm-logging.h"
+
+
+static void settings_connection_interface_init (NMSettingsConnectionInterface *klass);
+
+G_DEFINE_TYPE_EXTENDED (NMSysconfigConnection, nm_sysconfig_connection, NM_TYPE_EXPORTED_CONNECTION, 0,
+                        G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_CONNECTION_INTERFACE,
+                                               settings_connection_interface_init))
+
+#define NM_SYSCONFIG_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
+                                                NM_TYPE_SYSCONFIG_CONNECTION, \
+                                                NMSysconfigConnectionPrivate))
+
+typedef struct {
+	PolkitAuthority *authority;
+	GSList *pk_calls;
+	NMConnection *secrets;
+} NMSysconfigConnectionPrivate;
+
+/**************************************************************/
+
+static void
+ignore_cb (NMSettingsConnectionInterface *connection,
+           GError *error,
+           gpointer user_data)
+{
+}
+
+gboolean
+nm_sysconfig_connection_update (NMSysconfigConnection *self,
+                                NMConnection *new,
+                                gboolean signal_update,
+                                GError **error)
+{
+	NMSysconfigConnectionPrivate *priv;
+	GHashTable *new_settings;
+	gboolean success = FALSE;
+
+	g_return_val_if_fail (self != NULL, FALSE);
+	g_return_val_if_fail (NM_IS_SYSCONFIG_CONNECTION (self), FALSE);
+	g_return_val_if_fail (new != NULL, FALSE);
+	g_return_val_if_fail (NM_IS_CONNECTION (new), FALSE);
+
+	priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
+
+	/* Do nothing if there's nothing to update */
+	if (nm_connection_compare (NM_CONNECTION (self),
+	                           NM_CONNECTION (new),
+	                           NM_SETTING_COMPARE_FLAG_EXACT))
+		return TRUE;
+
+	new_settings = nm_connection_to_hash (new);
+	g_assert (new_settings);
+	if (nm_connection_replace_settings (NM_CONNECTION (self), new_settings, error)) {
+		/* Copy the connection to keep its secrets around even if NM
+		 * calls nm_connection_clear_secrets().
+		 */
+		if (priv->secrets)
+			g_object_unref (priv->secrets);
+		priv->secrets = nm_connection_duplicate (NM_CONNECTION (self));
+
+		if (signal_update) {
+			nm_settings_connection_interface_update (NM_SETTINGS_CONNECTION_INTERFACE (self),
+			                                         ignore_cb,
+			                                         NULL);
+		}
+		success = TRUE;
+	}
+	g_hash_table_destroy (new_settings);
+	return success;
+}
+
+/**************************************************************/
+
+static GValue *
+string_to_gvalue (const char *str)
+{
+	GValue *val = g_slice_new0 (GValue);
+
+	g_value_init (val, G_TYPE_STRING);
+	g_value_set_string (val, str);
+	return val;
+}
+
+static GValue *
+byte_array_to_gvalue (const GByteArray *array)
+{
+	GValue *val;
+
+	val = g_slice_new0 (GValue);
+	g_value_init (val, DBUS_TYPE_G_UCHAR_ARRAY);
+	g_value_set_boxed (val, array);
+
+	return val;
+}
+
+static void
+copy_one_secret (gpointer key, gpointer value, gpointer user_data)
+{
+	const char *value_str = (const char *) value;
+
+	if (value_str) {
+		g_hash_table_insert ((GHashTable *) user_data,
+		                     g_strdup ((char *) key),
+		                     string_to_gvalue (value_str));
+	}
+}
+
+static void
+add_secrets (NMSetting *setting,
+             const char *key,
+             const GValue *value,
+             GParamFlags flags,
+             gpointer user_data)
+{
+	GHashTable *secrets = user_data;
+
+	if (!(flags & NM_SETTING_PARAM_SECRET))
+		return;
+
+	/* Copy secrets into the returned hash table */
+	if (G_VALUE_HOLDS_STRING (value)) {
+		const char *tmp;
+
+		tmp = g_value_get_string (value);
+		if (tmp)
+			g_hash_table_insert (secrets, g_strdup (key), string_to_gvalue (tmp));
+	} else if (G_VALUE_HOLDS (value, DBUS_TYPE_G_MAP_OF_STRING)) {
+		/* Flatten the string hash by pulling its keys/values out */
+		g_hash_table_foreach (g_value_get_boxed (value), copy_one_secret, secrets);
+	} else if (G_VALUE_TYPE (value) == DBUS_TYPE_G_UCHAR_ARRAY) {
+		GByteArray *array;
+
+		array = g_value_get_boxed (value);
+		if (array)
+			g_hash_table_insert (secrets, g_strdup (key), byte_array_to_gvalue (array));
+	}
+}
+
+static void
+destroy_gvalue (gpointer data)
+{
+	GValue *value = (GValue *) data;
+
+	g_value_unset (value);
+	g_slice_free (GValue, value);
+}
+
+static gboolean
+get_secrets (NMSettingsConnectionInterface *connection,
+	         const char *setting_name,
+             const char **hints,
+             gboolean request_new,
+             NMSettingsConnectionInterfaceGetSecretsFunc callback,
+             gpointer user_data)
+{
+	NMSysconfigConnection *self = NM_SYSCONFIG_CONNECTION (connection);
+	NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
+	GHashTable *settings = NULL;
+	GHashTable *secrets = NULL;
+	NMSetting *setting;
+	GError *error = NULL;
+
+	/* Use priv->secrets to work around the fact that nm_connection_clear_secrets()
+	 * will clear secrets on this object's settings.  priv->secrets should be
+	 * a complete copy of this object and kept in sync by
+	 * nm_sysconfig_connection_update().
+	 */
+	if (!priv->secrets) {
+		error = g_error_new (NM_SETTINGS_INTERFACE_ERROR,
+		                     NM_SETTINGS_INTERFACE_ERROR_INVALID_CONNECTION,
+		                     "%s.%d - Internal error; secrets cache invalid.",
+		                     __FILE__, __LINE__);
+		(*callback) (connection, NULL, error, user_data);
+		g_error_free (error);
+		return TRUE;
+	}
+
+	setting = nm_connection_get_setting_by_name (priv->secrets, setting_name);
+	if (!setting) {
+		error = g_error_new (NM_SETTINGS_INTERFACE_ERROR,
+		                     NM_SETTINGS_INTERFACE_ERROR_INVALID_SETTING,
+		                     "%s.%d - Connection didn't have requested setting '%s'.",
+		                     __FILE__, __LINE__, setting_name);
+		(*callback) (connection, NULL, error, user_data);
+		g_error_free (error);
+		return TRUE;
+	}
+
+	/* Returned secrets are a{sa{sv}}; this is the outer a{s...} hash that
+	 * will contain all the individual settings hashes.
+	 */
+	settings = g_hash_table_new_full (g_str_hash, g_str_equal,
+	                                  g_free, (GDestroyNotify) g_hash_table_destroy);
+
+	/* Add the secrets from this setting to the inner secrets hash for this setting */
+	secrets = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, destroy_gvalue);
+	nm_setting_enumerate_values (setting, add_secrets, secrets);
+
+	g_hash_table_insert (settings, g_strdup (setting_name), secrets);
+	callback (connection, settings, NULL, user_data);
+	g_hash_table_destroy (settings);
+	return TRUE;
+}
+
+/**************************************************************/
+
+typedef struct {
+	NMSysconfigConnection *self;
+	DBusGMethodInvocation *context;
+	PolkitSubject *subject;
+	GCancellable *cancellable;
+	gboolean disposed;
+
+	/* Update */
+	NMConnection *connection;
+
+	/* Secrets */
+	char *setting_name;
+	char **hints;
+	gboolean request_new;
+} PolkitCall;
+
+static PolkitCall *
+polkit_call_new (NMSysconfigConnection *self,
+                 DBusGMethodInvocation *context,
+                 NMConnection *connection,
+                 const char *setting_name,
+                 const char **hints,
+                 gboolean request_new)
+{
+	PolkitCall *call;
+	char *sender;
+
+	g_return_val_if_fail (self != NULL, NULL);
+	g_return_val_if_fail (context != NULL, NULL);
+
+	call = g_malloc0 (sizeof (PolkitCall));
+	call->self = self;
+	call->context = context;
+	call->cancellable = g_cancellable_new ();
+	call->connection = connection;
+	call->setting_name = g_strdup (setting_name);
+	if (hints)
+		call->hints = g_strdupv ((char **) hints);
+	call->request_new = request_new;
+
+ 	sender = dbus_g_method_get_sender (context);
+	call->subject = polkit_system_bus_name_new (sender);
+	g_free (sender);
+
+	return call;
+}
+
+static void
+polkit_call_free (PolkitCall *call)
+{
+	if (call->connection)
+		g_object_unref (call->connection);
+	g_free (call->setting_name);
+	if (call->hints)
+		g_strfreev (call->hints);
+
+	g_object_unref (call->subject);
+	g_object_unref (call->cancellable);
+	g_free (call);
+}
+
+static void
+con_update_cb (NMSettingsConnectionInterface *connection,
+               GError *error,
+               gpointer user_data)
+{
+	PolkitCall *call = user_data;
+
+	if (error)
+		dbus_g_method_return_error (call->context, error);
+	else
+		dbus_g_method_return (call->context);
+
+	polkit_call_free (call);
+}
+
+static void
+pk_update_cb (GObject *object, GAsyncResult *result, gpointer user_data)
+{
+	PolkitCall *call = user_data;
+	NMSysconfigConnection *self = call->self;
+	NMSysconfigConnectionPrivate *priv;
+	PolkitAuthorizationResult *pk_result;
+	GError *error = NULL;
+
+	/* If our NMSysconfigConnection is already gone, do nothing */
+	if (call->disposed) {
+		error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR,
+		                             NM_SYSCONFIG_SETTINGS_ERROR_GENERAL,
+		                             "Request was canceled.");
+		dbus_g_method_return_error (call->context, error);
+		g_error_free (error);
+		polkit_call_free (call);
+		return;
+	}
+
+	priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
+
+	priv->pk_calls = g_slist_remove (priv->pk_calls, call);
+
+	pk_result = polkit_authority_check_authorization_finish (priv->authority,
+	                                                         result,
+	                                                         &error);
+	/* Some random error happened */
+	if (error) {
+		dbus_g_method_return_error (call->context, error);
+		g_error_free (error);
+		polkit_call_free (call);
+		return;
+	}
+
+	/* Caller didn't successfully authenticate */
+	if (!polkit_authorization_result_get_is_authorized (pk_result)) {
+		error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR,
+		                             NM_SYSCONFIG_SETTINGS_ERROR_NOT_PRIVILEGED,
+		                             "Insufficient privileges.");
+		dbus_g_method_return_error (call->context, error);
+		g_error_free (error);
+		polkit_call_free (call);
+		goto out;
+	}
+
+	/* Update our settings internally so the update() call will save the new
+	 * ones.  We don't let nm_sysconfig_connection_update() handle the update
+	 * signal since we need our own callback after the update is done.
+	 */
+	if (!nm_sysconfig_connection_update (self, call->connection, FALSE, &error)) {
+		/* Shouldn't really happen since we've already validated the settings */
+		dbus_g_method_return_error (call->context, error);
+		g_error_free (error);
+		polkit_call_free (call);
+		goto out;
+	}
+
+	/* Caller is authenticated, now we can finally try to commit the update */
+	nm_settings_connection_interface_update (NM_SETTINGS_CONNECTION_INTERFACE (self),
+	                                         con_update_cb,
+	                                         call);
+
+out:
+	g_object_unref (pk_result);
+}
+
+static void
+dbus_update (NMExportedConnection *exported,
+             GHashTable *new_settings,
+             DBusGMethodInvocation *context)
+{
+	NMSysconfigConnection *self = NM_SYSCONFIG_CONNECTION (exported);
+	NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
+	PolkitCall *call;
+	NMConnection *tmp;
+	GError *error = NULL;
+
+	/* Check if the settings are valid first */
+	tmp = nm_connection_new_from_hash (new_settings, &error);
+	if (!tmp) {
+		g_assert (error);
+		dbus_g_method_return_error (context, error);
+		g_error_free (error);
+		return;
+	}
+
+	call = polkit_call_new (self, context, tmp, NULL, NULL, FALSE);
+	g_assert (call);
+	polkit_authority_check_authorization (priv->authority,
+	                                      call->subject,
+	                                      NM_SYSCONFIG_POLICY_ACTION_CONNECTION_MODIFY,
+	                                      NULL,
+	                                      POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
+	                                      call->cancellable,
+	                                      pk_update_cb,
+	                                      call);
+	priv->pk_calls = g_slist_prepend (priv->pk_calls, call);
+}
+
+static void
+con_delete_cb (NMSettingsConnectionInterface *connection,
+               GError *error,
+               gpointer user_data)
+{
+	PolkitCall *call = user_data;
+
+	if (error)
+		dbus_g_method_return_error (call->context, error);
+	else
+		dbus_g_method_return (call->context);
+
+	polkit_call_free (call);
+}
+
+static void
+pk_delete_cb (GObject *object, GAsyncResult *result, gpointer user_data)
+{
+	PolkitCall *call = user_data;
+	NMSysconfigConnection *self = call->self;
+	NMSysconfigConnectionPrivate *priv;
+	PolkitAuthorizationResult *pk_result;
+	GError *error = NULL;
+
+	/* If our NMSysconfigConnection is already gone, do nothing */
+	if (call->disposed) {
+		error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR,
+		                             NM_SYSCONFIG_SETTINGS_ERROR_GENERAL,
+		                             "Request was canceled.");
+		dbus_g_method_return_error (call->context, error);
+		g_error_free (error);
+		polkit_call_free (call);
+		return;
+	}
+
+	priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
+
+	priv->pk_calls = g_slist_remove (priv->pk_calls, call);
+
+	pk_result = polkit_authority_check_authorization_finish (priv->authority,
+	                                                         result,
+	                                                         &error);
+	/* Some random error happened */
+	if (error) {
+		dbus_g_method_return_error (call->context, error);
+		g_error_free (error);
+		polkit_call_free (call);
+		return;
+	}
+
+	/* Caller didn't successfully authenticate */
+	if (!polkit_authorization_result_get_is_authorized (pk_result)) {
+		error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR,
+		                             NM_SYSCONFIG_SETTINGS_ERROR_NOT_PRIVILEGED,
+		                             "Insufficient privileges.");
+		dbus_g_method_return_error (call->context, error);
+		g_error_free (error);
+		polkit_call_free (call);
+		goto out;
+	}
+
+	/* Caller is authenticated, now we can finally try to delete */
+	nm_settings_connection_interface_delete (NM_SETTINGS_CONNECTION_INTERFACE (self),
+	                                         con_delete_cb,
+	                                         call);
+
+out:
+	g_object_unref (pk_result);
+}
+
+static void
+dbus_delete (NMExportedConnection *exported,
+             DBusGMethodInvocation *context)
+{
+	NMSysconfigConnection *self = NM_SYSCONFIG_CONNECTION (exported);
+	NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
+	PolkitCall *call;
+
+	call = polkit_call_new (self, context, NULL, NULL, NULL, FALSE);
+	g_assert (call);
+	polkit_authority_check_authorization (priv->authority,
+	                                      call->subject,
+	                                      NM_SYSCONFIG_POLICY_ACTION_CONNECTION_MODIFY,
+	                                      NULL,
+	                                      POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
+	                                      call->cancellable,
+	                                      pk_delete_cb,
+	                                      call);
+	priv->pk_calls = g_slist_prepend (priv->pk_calls, call);
+}
+
+static void
+con_secrets_cb (NMSettingsConnectionInterface *connection,
+                GHashTable *secrets,
+                GError *error,
+                gpointer user_data)
+{
+	PolkitCall *call = user_data;
+
+	if (error)
+		dbus_g_method_return_error (call->context, error);
+	else
+		dbus_g_method_return (call->context, secrets);
+
+	polkit_call_free (call);
+}
+
+static void
+pk_secrets_cb (GObject *object, GAsyncResult *result, gpointer user_data)
+{
+	PolkitCall *call = user_data;
+	NMSysconfigConnection *self = call->self;
+	NMSysconfigConnectionPrivate *priv;
+	PolkitAuthorizationResult *pk_result;
+	GError *error = NULL;
+
+	/* If our NMSysconfigConnection is already gone, do nothing */
+	if (call->disposed) {
+		error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR,
+		                             NM_SYSCONFIG_SETTINGS_ERROR_GENERAL,
+		                             "Request was canceled.");
+		dbus_g_method_return_error (call->context, error);
+		g_error_free (error);
+		polkit_call_free (call);
+		return;
+	}
+
+	priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
+
+	priv->pk_calls = g_slist_remove (priv->pk_calls, call);
+
+	pk_result = polkit_authority_check_authorization_finish (priv->authority,
+	                                                         result,
+	                                                         &error);
+	/* Some random error happened */
+	if (error) {
+		dbus_g_method_return_error (call->context, error);
+		g_error_free (error);
+		polkit_call_free (call);
+		return;
+	}
+
+	/* Caller didn't successfully authenticate */
+	if (!polkit_authorization_result_get_is_authorized (pk_result)) {
+		error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR,
+		                             NM_SYSCONFIG_SETTINGS_ERROR_NOT_PRIVILEGED,
+		                             "Insufficient privileges.");
+		dbus_g_method_return_error (call->context, error);
+		g_error_free (error);
+		polkit_call_free (call);
+		goto out;
+	}
+
+	/* Caller is authenticated, now we can finally try to update */
+	nm_settings_connection_interface_get_secrets (NM_SETTINGS_CONNECTION_INTERFACE (self),
+	                                              call->setting_name,
+	                                              (const char **) call->hints,
+	                                              call->request_new,
+	                                              con_secrets_cb,
+	                                              call);
+
+out:
+	g_object_unref (pk_result);
+}
+
+static void
+dbus_get_secrets (NMExportedConnection *exported,
+                  const gchar *setting_name,
+                  const gchar **hints,
+                  gboolean request_new,
+                  DBusGMethodInvocation *context)
+{
+	NMSysconfigConnection *self = NM_SYSCONFIG_CONNECTION (exported);
+	NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
+	PolkitCall *call;
+
+	call = polkit_call_new (self, context, NULL, setting_name, hints, request_new);
+	g_assert (call);
+	polkit_authority_check_authorization (priv->authority,
+	                                      call->subject,
+	                                      NM_SYSCONFIG_POLICY_ACTION_CONNECTION_MODIFY,
+	                                      NULL,
+	                                      POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
+	                                      call->cancellable,
+	                                      pk_secrets_cb,
+	                                      call);
+	priv->pk_calls = g_slist_prepend (priv->pk_calls, call);
+}
+
+/**************************************************************/
+
+static void
+settings_connection_interface_init (NMSettingsConnectionInterface *iface)
+{
+	iface->get_secrets = get_secrets;
+}
+
+static void
+nm_sysconfig_connection_init (NMSysconfigConnection *self)
+{
+	NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
+
+	priv->authority = polkit_authority_get ();
+	if (!priv->authority) {
+		nm_log_err (LOGD_SYS_SET, "%s: error creating PolicyKit authority");
+	}
+}
+
+static void
+dispose (GObject *object)
+{
+	NMSysconfigConnection *self = NM_SYSCONFIG_CONNECTION (object);
+	NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self);
+	GSList *iter;
+
+	if (priv->secrets)
+		g_object_unref (priv->secrets);
+
+	/* Cancel PolicyKit requests */
+	for (iter = priv->pk_calls; iter; iter = g_slist_next (iter)) {
+		PolkitCall *call = iter->data;
+
+		call->disposed = TRUE;
+		g_cancellable_cancel (call->cancellable);
+	}
+	g_slist_free (priv->pk_calls);
+	priv->pk_calls = NULL;
+
+	G_OBJECT_CLASS (nm_sysconfig_connection_parent_class)->dispose (object);
+}
+
+static void
+nm_sysconfig_connection_class_init (NMSysconfigConnectionClass *class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (class);
+	NMExportedConnectionClass *ec_class = NM_EXPORTED_CONNECTION_CLASS (class);
+
+	g_type_class_add_private (class, sizeof (NMSysconfigConnectionPrivate));
+
+	/* Virtual methods */
+	object_class->dispose = dispose;
+	ec_class->update = dbus_update;
+	ec_class->delete = dbus_delete;
+	ec_class->get_secrets = dbus_get_secrets;
+}
diff --git a/src/system-settings/nm-sysconfig-connection.h b/src/system-settings/nm-sysconfig-connection.h
new file mode 100644
index 00000000..0431dc95
--- /dev/null
+++ b/src/system-settings/nm-sysconfig-connection.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service
+ *
+ * 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.
+ *
+ * (C) Copyright 2008 Novell, Inc.
+ */
+
+#ifndef NM_SYSCONFIG_CONNECTION_H
+#define NM_SYSCONFIG_CONNECTION_H
+
+#include <nm-connection.h>
+#include <nm-exported-connection.h>
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_SYSCONFIG_CONNECTION            (nm_sysconfig_connection_get_type ())
+#define NM_SYSCONFIG_CONNECTION(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SYSCONFIG_CONNECTION, NMSysconfigConnection))
+#define NM_SYSCONFIG_CONNECTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SYSCONFIG_CONNECTION, NMSysconfigConnectionClass))
+#define NM_IS_SYSCONFIG_CONNECTION(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SYSCONFIG_CONNECTION))
+#define NM_IS_SYSCONFIG_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SYSCONFIG_CONNECTION))
+#define NM_SYSCONFIG_CONNECTION_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SYSCONFIG_CONNECTION, NMSysconfigConnectionClass))
+
+typedef struct {
+	NMExportedConnection parent;
+} NMSysconfigConnection;
+
+typedef struct {
+	NMExportedConnectionClass parent;
+} NMSysconfigConnectionClass;
+
+GType nm_sysconfig_connection_get_type (void);
+
+/* Called by a system-settings plugin to update a connection is out of sync
+ * with it's backing storage.
+ */
+gboolean nm_sysconfig_connection_update (NMSysconfigConnection *self,
+                                         NMConnection *new_settings,
+                                         gboolean signal_update,
+                                         GError **error);
+
+G_END_DECLS
+
+#endif /* NM_SYSCONFIG_CONNECTION_H */
diff --git a/src/system-settings/nm-sysconfig-settings.c b/src/system-settings/nm-sysconfig-settings.c
new file mode 100644
index 00000000..4bcfb04b
--- /dev/null
+++ b/src/system-settings/nm-sysconfig-settings.c
@@ -0,0 +1,1520 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service
+ *
+ * Søren Sandmann <sandmann@daimi.au.dk>
+ * Dan Williams <dcbw@redhat.com>
+ * Tambet Ingo <tambet@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.
+ *
+ * (C) Copyright 2007 - 2010 Red Hat, Inc.
+ * (C) Copyright 2008 Novell, Inc.
+ */
+
+#include <unistd.h>
+#include <string.h>
+#include <gmodule.h>
+#include <net/ethernet.h>
+#include <netinet/ether.h>
+
+#include <NetworkManager.h>
+#include <nm-connection.h>
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <nm-settings-system-interface.h>
+
+#include <nm-setting-8021x.h>
+#include <nm-setting-bluetooth.h>
+#include <nm-setting-cdma.h>
+#include <nm-setting-connection.h>
+#include <nm-setting-gsm.h>
+#include <nm-setting-ip4-config.h>
+#include <nm-setting-ip6-config.h>
+#include <nm-setting-olpc-mesh.h>
+#include <nm-setting-ppp.h>
+#include <nm-setting-pppoe.h>
+#include <nm-setting-serial.h>
+#include <nm-setting-vpn.h>
+#include <nm-setting-wired.h>
+#include <nm-setting-wireless.h>
+#include <nm-setting-wireless-security.h>
+
+#include "../nm-device-ethernet.h"
+#include "nm-dbus-glib-types.h"
+#include "nm-sysconfig-settings.h"
+#include "nm-sysconfig-connection.h"
+#include "nm-polkit-helpers.h"
+#include "nm-system-config-error.h"
+#include "nm-default-wired-connection.h"
+#include "nm-logging.h"
+
+#define CONFIG_KEY_NO_AUTO_DEFAULT "no-auto-default"
+
+/* LINKER CRACKROCK */
+#define EXPORT(sym) void * __export_##sym = &sym;
+
+#include "nm-inotify-helper.h"
+EXPORT(nm_inotify_helper_get_type)
+EXPORT(nm_inotify_helper_get)
+EXPORT(nm_inotify_helper_add_watch)
+EXPORT(nm_inotify_helper_remove_watch)
+
+EXPORT(nm_sysconfig_connection_get_type)
+EXPORT(nm_sysconfig_connection_update)
+/* END LINKER CRACKROCK */
+
+static void claim_connection (NMSysconfigSettings *self,
+                              NMSettingsConnectionInterface *connection,
+                              gboolean do_export);
+
+static void impl_settings_save_hostname (NMSysconfigSettings *self,
+                                         const char *hostname,
+                                         DBusGMethodInvocation *context);
+
+static void impl_settings_get_permissions (NMSysconfigSettings *self,
+                                           DBusGMethodInvocation *context);
+
+#include "nm-settings-system-glue.h"
+
+static void unmanaged_specs_changed (NMSystemConfigInterface *config, gpointer user_data);
+
+typedef struct {
+	PolkitAuthority *authority;
+	guint auth_changed_id;
+	char *config_file;
+
+	GSList *pk_calls;
+	GSList *permissions_calls;
+
+	GSList *plugins;
+	gboolean connections_loaded;
+	GHashTable *connections;
+	GSList *unmanaged_specs;
+} NMSysconfigSettingsPrivate;
+
+static void settings_system_interface_init (NMSettingsSystemInterface *klass);
+
+G_DEFINE_TYPE_WITH_CODE (NMSysconfigSettings, nm_sysconfig_settings, NM_TYPE_SETTINGS_SERVICE,
+                         G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_SYSTEM_INTERFACE,
+                                                settings_system_interface_init))
+
+#define NM_SYSCONFIG_SETTINGS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SYSCONFIG_SETTINGS, NMSysconfigSettingsPrivate))
+
+enum {
+	PROPERTIES_CHANGED,
+
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+enum {
+	PROP_0,
+	PROP_UNMANAGED_SPECS,
+
+	LAST_PROP
+};
+
+static void
+load_connections (NMSysconfigSettings *self)
+{
+	NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+	GSList *iter;
+
+	if (priv->connections_loaded)
+		return;
+
+	for (iter = priv->plugins; iter; iter = g_slist_next (iter)) {
+		NMSystemConfigInterface *plugin = NM_SYSTEM_CONFIG_INTERFACE (iter->data);
+		GSList *plugin_connections;
+		GSList *elt;
+
+		plugin_connections = nm_system_config_interface_get_connections (plugin);
+
+		// FIXME: ensure connections from plugins loaded with a lower priority
+		// get rejected when they conflict with connections from a higher
+		// priority plugin.
+
+		for (elt = plugin_connections; elt; elt = g_slist_next (elt))
+			claim_connection (self, NM_SETTINGS_CONNECTION_INTERFACE (elt->data), TRUE);
+
+		g_slist_free (plugin_connections);
+	}
+
+	priv->connections_loaded = TRUE;
+
+	/* FIXME: Bad hack */
+	unmanaged_specs_changed (NULL, self);
+}
+
+static GSList *
+list_connections (NMSettingsService *settings)
+{
+	NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (settings);
+	GHashTableIter iter;
+	gpointer key;
+	GSList *list = NULL;
+
+	load_connections (NM_SYSCONFIG_SETTINGS (settings));
+
+	g_hash_table_iter_init (&iter, priv->connections);
+	while (g_hash_table_iter_next (&iter, &key, NULL))
+		list = g_slist_prepend (list, NM_EXPORTED_CONNECTION (key));
+	return g_slist_reverse (list);
+}
+
+static void
+clear_unmanaged_specs (NMSysconfigSettings *self)
+{
+	NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+
+	g_slist_foreach (priv->unmanaged_specs, (GFunc) g_free, NULL);
+	g_slist_free (priv->unmanaged_specs);
+	priv->unmanaged_specs = NULL;
+}
+
+static char*
+uscore_to_wincaps (const char *uscore)
+{
+	const char *p;
+	GString *str;
+	gboolean last_was_uscore;
+
+	last_was_uscore = TRUE;
+  
+	str = g_string_new (NULL);
+	p = uscore;
+	while (p && *p) {
+		if (*p == '-' || *p == '_')
+			last_was_uscore = TRUE;
+		else {
+			if (last_was_uscore) {
+				g_string_append_c (str, g_ascii_toupper (*p));
+				last_was_uscore = FALSE;
+			} else
+				g_string_append_c (str, *p);
+		}
+		++p;
+	}
+
+	return g_string_free (str, FALSE);
+}
+
+static void
+notify (GObject *object, GParamSpec *pspec)
+{
+	GValue *value;
+	GHashTable *hash;
+
+	value = g_slice_new0 (GValue);
+	hash = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_free, NULL);
+
+	g_value_init (value, pspec->value_type);
+	g_object_get_property (object, pspec->name, value);
+	g_hash_table_insert (hash, uscore_to_wincaps (pspec->name), value);
+	g_signal_emit (object, signals[PROPERTIES_CHANGED], 0, hash);
+	g_hash_table_destroy (hash);
+	g_value_unset (value);
+	g_slice_free (GValue, value);
+}
+
+const GSList *
+nm_sysconfig_settings_get_unmanaged_specs (NMSysconfigSettings *self)
+{
+	NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+
+	load_connections (self);
+	return priv->unmanaged_specs;
+}
+
+static NMSystemConfigInterface *
+get_plugin (NMSysconfigSettings *self, guint32 capability)
+{
+	NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+	GSList *iter;
+
+	g_return_val_if_fail (self != NULL, NULL);
+
+	/* Do any of the plugins support setting the hostname? */
+	for (iter = priv->plugins; iter; iter = iter->next) {
+		NMSystemConfigInterfaceCapabilities caps = NM_SYSTEM_CONFIG_INTERFACE_CAP_NONE;
+
+		g_object_get (G_OBJECT (iter->data), NM_SYSTEM_CONFIG_INTERFACE_CAPABILITIES, &caps, NULL);
+		if (caps & capability)
+			return NM_SYSTEM_CONFIG_INTERFACE (iter->data);
+	}
+
+	return NULL;
+}
+
+char *
+nm_sysconfig_settings_get_hostname (NMSysconfigSettings *self)
+{
+	NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+	GSList *iter;
+	char *hostname = NULL;
+
+	/* Hostname returned is the hostname returned from the first plugin
+	 * that provides one.
+	 */
+	for (iter = priv->plugins; iter; iter = iter->next) {
+		NMSystemConfigInterfaceCapabilities caps = NM_SYSTEM_CONFIG_INTERFACE_CAP_NONE;
+
+		g_object_get (G_OBJECT (iter->data), NM_SYSTEM_CONFIG_INTERFACE_CAPABILITIES, &caps, NULL);
+		if (caps & NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME) {
+			g_object_get (G_OBJECT (iter->data), NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME, &hostname, NULL);
+			if (hostname && strlen (hostname))
+				return hostname;
+			g_free (hostname);
+		}
+	}
+
+	return hostname;
+}
+
+static void
+plugin_connection_added (NMSystemConfigInterface *config,
+                         NMSettingsConnectionInterface *connection,
+                         gpointer user_data)
+{
+	claim_connection (NM_SYSCONFIG_SETTINGS (user_data), connection, TRUE);
+}
+
+static gboolean
+find_unmanaged_device (NMSysconfigSettings *self, const char *needle)
+{
+	NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+	GSList *iter;
+
+	for (iter = priv->unmanaged_specs; iter; iter = g_slist_next (iter)) {
+		if (!strcmp ((const char *) iter->data, needle))
+			return TRUE;
+	}
+	return FALSE;
+}
+
+static void
+unmanaged_specs_changed (NMSystemConfigInterface *config,
+                         gpointer user_data)
+{
+	NMSysconfigSettings *self = NM_SYSCONFIG_SETTINGS (user_data);
+	NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+	GSList *iter;
+
+	clear_unmanaged_specs (self);
+
+	/* Ask all the plugins for their unmanaged specs */
+	for (iter = priv->plugins; iter; iter = g_slist_next (iter)) {
+		GSList *specs, *specs_iter;
+
+		specs = nm_system_config_interface_get_unmanaged_specs (NM_SYSTEM_CONFIG_INTERFACE (iter->data));
+		for (specs_iter = specs; specs_iter; specs_iter = specs_iter->next) {
+			if (!find_unmanaged_device (self, (const char *) specs_iter->data)) {
+				priv->unmanaged_specs = g_slist_prepend (priv->unmanaged_specs, specs_iter->data);
+			} else
+				g_free (specs_iter->data);
+		}
+
+		g_slist_free (specs);
+	}
+
+	g_object_notify (G_OBJECT (self), NM_SYSCONFIG_SETTINGS_UNMANAGED_SPECS);
+}
+
+static void
+hostname_changed (NMSystemConfigInterface *config,
+                  GParamSpec *pspec,
+                  gpointer user_data)
+{
+	g_object_notify (G_OBJECT (user_data), NM_SETTINGS_SYSTEM_INTERFACE_HOSTNAME);
+}
+
+static void
+add_plugin (NMSysconfigSettings *self, NMSystemConfigInterface *plugin)
+{
+	NMSysconfigSettingsPrivate *priv;
+	char *pname = NULL;
+	char *pinfo = NULL;
+
+	g_return_if_fail (NM_IS_SYSCONFIG_SETTINGS (self));
+	g_return_if_fail (NM_IS_SYSTEM_CONFIG_INTERFACE (plugin));
+
+	priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+
+	priv->plugins = g_slist_append (priv->plugins, g_object_ref (plugin));
+
+	g_signal_connect (plugin, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED,
+	                  G_CALLBACK (plugin_connection_added), self);
+	g_signal_connect (plugin, "notify::hostname", G_CALLBACK (hostname_changed), self);
+
+	nm_system_config_interface_init (plugin, NULL);
+
+	g_object_get (G_OBJECT (plugin),
+	              NM_SYSTEM_CONFIG_INTERFACE_NAME, &pname,
+	              NM_SYSTEM_CONFIG_INTERFACE_INFO, &pinfo,
+	              NULL);
+
+	g_signal_connect (plugin, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED,
+	                  G_CALLBACK (unmanaged_specs_changed), self);
+
+	nm_log_info (LOGD_SYS_SET, "Loaded plugin %s: %s", pname, pinfo);
+	g_free (pname);
+	g_free (pinfo);
+}
+
+static GObject *
+find_plugin (GSList *list, const char *pname)
+{
+	GSList *iter;
+	GObject *obj = NULL;
+
+	g_return_val_if_fail (pname != NULL, FALSE);
+
+	for (iter = list; iter && !obj; iter = g_slist_next (iter)) {
+		NMSystemConfigInterface *plugin = NM_SYSTEM_CONFIG_INTERFACE (iter->data);
+		char *list_pname = NULL;
+
+		g_object_get (G_OBJECT (plugin),
+		              NM_SYSTEM_CONFIG_INTERFACE_NAME,
+		              &list_pname,
+		              NULL);
+		if (list_pname && !strcmp (pname, list_pname))
+			obj = G_OBJECT (plugin);
+
+		g_free (list_pname);
+	}
+
+	return obj;
+}
+
+static gboolean
+load_plugins (NMSysconfigSettings *self, const char *plugins, GError **error)
+{
+	GSList *list = NULL;
+	char **plist;
+	char **iter;
+	gboolean success = TRUE;
+
+	plist = g_strsplit (plugins, ",", 0);
+	if (!plist)
+		return FALSE;
+
+	for (iter = plist; *iter; iter++) {
+		GModule *plugin;
+		char *full_name, *path;
+		const char *pname = *iter;
+		GObject *obj;
+		GObject * (*factory_func) (void);
+
+		/* ifcfg-fedora was renamed ifcfg-rh; handle old configs here */
+		if (!strcmp (pname, "ifcfg-fedora"))
+			pname = "ifcfg-rh";
+
+		obj = find_plugin (list, pname);
+		if (obj)
+			continue;
+
+		full_name = g_strdup_printf ("nm-settings-plugin-%s", pname);
+		path = g_module_build_path (PLUGINDIR, full_name);
+
+		plugin = g_module_open (path, G_MODULE_BIND_LOCAL);
+		if (!plugin) {
+			g_set_error (error, 0, 0,
+			             "Could not load plugin '%s': %s",
+			             pname, g_module_error ());
+			g_free (full_name);
+			g_free (path);
+			success = FALSE;
+			break;
+		}
+
+		g_free (full_name);
+		g_free (path);
+
+		if (!g_module_symbol (plugin, "nm_system_config_factory", (gpointer) (&factory_func))) {
+			g_set_error (error, 0, 0,
+			             "Could not find plugin '%s' factory function.",
+			             pname);
+			success = FALSE;
+			break;
+		}
+
+		obj = (*factory_func) ();
+		if (!obj || !NM_IS_SYSTEM_CONFIG_INTERFACE (obj)) {
+			g_set_error (error, 0, 0,
+			             "Plugin '%s' returned invalid system config object.",
+			             pname);
+			success = FALSE;
+			break;
+		}
+
+		g_module_make_resident (plugin);
+		g_object_weak_ref (obj, (GWeakNotify) g_module_close, plugin);
+		add_plugin (self, NM_SYSTEM_CONFIG_INTERFACE (obj));
+		list = g_slist_append (list, obj);
+	}
+
+	g_strfreev (plist);
+
+	g_slist_foreach (list, (GFunc) g_object_unref, NULL);
+	g_slist_free (list);
+
+	return success;
+}
+
+static void
+connection_removed (NMSettingsConnectionInterface *connection,
+                    gpointer user_data)
+{
+	NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (user_data);
+
+	g_hash_table_remove (priv->connections, connection);
+}
+
+static void
+claim_connection (NMSysconfigSettings *self,
+                  NMSettingsConnectionInterface *connection,
+                  gboolean do_export)
+{
+	NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+
+	g_return_if_fail (NM_IS_SYSCONFIG_SETTINGS (self));
+	g_return_if_fail (NM_IS_SETTINGS_CONNECTION_INTERFACE (connection));
+
+	if (g_hash_table_lookup (priv->connections, connection))
+		/* A plugin is lying to us. */
+		return;
+
+	g_hash_table_insert (priv->connections, g_object_ref (connection), GINT_TO_POINTER (1));
+	g_signal_connect (connection,
+	                  NM_SETTINGS_CONNECTION_INTERFACE_REMOVED,
+	                  G_CALLBACK (connection_removed),
+	                  self);
+
+	if (do_export) {
+		nm_settings_service_export_connection (NM_SETTINGS_SERVICE (self), connection);
+		g_signal_emit_by_name (self, NM_SETTINGS_INTERFACE_NEW_CONNECTION, connection);
+	}
+}
+
+static void
+remove_connection (NMSysconfigSettings *self,
+                   NMSettingsConnectionInterface *connection,
+                   gboolean do_signal)
+{
+	NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+
+	g_return_if_fail (NM_IS_SYSCONFIG_SETTINGS (self));
+	g_return_if_fail (NM_IS_SETTINGS_CONNECTION_INTERFACE (connection));
+
+	if (g_hash_table_lookup (priv->connections, connection)) {
+		g_signal_emit_by_name (G_OBJECT (connection), NM_SETTINGS_CONNECTION_INTERFACE_REMOVED);
+		g_hash_table_remove (priv->connections, connection);
+	}
+}
+
+typedef struct {
+	NMSysconfigSettings *self;
+	DBusGMethodInvocation *context;
+	PolkitSubject *subject;
+	GCancellable *cancellable;
+	gboolean disposed;
+
+	NMConnection *connection;
+	NMSettingsAddConnectionFunc callback;
+	gpointer callback_data;
+
+	char *hostname;
+
+	NMSettingsSystemPermissions permissions;
+	guint32 permissions_calls;
+} PolkitCall;
+
+#include "nm-dbus-manager.h"
+
+static PolkitCall *
+polkit_call_new (NMSysconfigSettings *self,
+                 DBusGMethodInvocation *context,
+                 NMConnection *connection,
+                 NMSettingsAddConnectionFunc callback,
+                 gpointer callback_data,
+                 const char *hostname)
+{
+	PolkitCall *call;
+	char *sender;
+
+	g_return_val_if_fail (self != NULL, NULL);
+	g_return_val_if_fail (context != NULL, NULL);
+
+	call = g_malloc0 (sizeof (PolkitCall));
+	call->self = self;
+	call->cancellable = g_cancellable_new ();
+	call->context = context;
+	if (connection)
+		call->connection = g_object_ref (connection);
+	if (callback) {
+		call->callback = callback;
+		call->callback_data = callback_data;
+	}
+	if (hostname)
+		call->hostname = g_strdup (hostname);
+
+ 	sender = dbus_g_method_get_sender (context);
+	call->subject = polkit_system_bus_name_new (sender);
+	g_free (sender);
+
+	return call;
+}
+
+static void
+polkit_call_free (PolkitCall *call)
+{
+	if (call->connection)
+		g_object_unref (call->connection);
+	g_object_unref (call->cancellable);
+	g_free (call->hostname);
+	g_object_unref (call->subject);
+	g_free (call);
+}
+
+static gboolean
+add_new_connection (NMSysconfigSettings *self,
+                    NMConnection *connection,
+                    GError **error)
+{
+	NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+	GError *tmp_error = NULL, *last_error = NULL;
+	GSList *iter;
+	gboolean success = FALSE;
+
+	/* Here's how it works:
+	   1) plugin writes a connection.
+	   2) plugin notices that a new connection is available for reading.
+	   3) plugin reads the new connection (the one it wrote in 1) and emits 'connection-added' signal.
+	   4) NMSysconfigSettings receives the signal and adds it to it's connection list.
+	*/
+
+	for (iter = priv->plugins; iter && !success; iter = iter->next) {
+		success = nm_system_config_interface_add_connection (NM_SYSTEM_CONFIG_INTERFACE (iter->data),
+		                                                     connection,
+		                                                     &tmp_error);
+		g_clear_error (&last_error);
+		if (!success) {
+			last_error = tmp_error;
+			tmp_error = NULL;
+		}
+	}
+
+	if (!success)
+		*error = last_error;
+	return success;
+}
+
+static void
+pk_add_cb (GObject *object, GAsyncResult *result, gpointer user_data)
+{
+	PolkitCall *call = user_data;
+	NMSysconfigSettings *self = call->self;
+	NMSysconfigSettingsPrivate *priv;
+	PolkitAuthorizationResult *pk_result;
+	GError *error = NULL, *add_error = NULL;
+
+	/* If NMSysconfigSettings is already gone, do nothing */
+	if (call->disposed) {
+		error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR,
+		                             NM_SYSCONFIG_SETTINGS_ERROR_GENERAL,
+		                             "Request was canceled.");
+		dbus_g_method_return_error (call->context, error);
+		g_error_free (error);
+		polkit_call_free (call);
+		return;
+	}
+
+	priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+
+	priv->pk_calls = g_slist_remove (priv->pk_calls, call);
+
+	pk_result = polkit_authority_check_authorization_finish (priv->authority,
+	                                                         result,
+	                                                         &error);
+	/* Some random error happened */
+	if (error) {
+		call->callback (NM_SETTINGS_INTERFACE (self), error, call->callback_data);
+		goto out;
+	}
+
+	/* Caller didn't successfully authenticate */
+	if (!polkit_authorization_result_get_is_authorized (pk_result)) {
+		error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR,
+		                             NM_SYSCONFIG_SETTINGS_ERROR_NOT_PRIVILEGED,
+		                             "Insufficient privileges.");
+		call->callback (NM_SETTINGS_INTERFACE (self), error, call->callback_data);
+		goto out;
+	}
+
+	if (add_new_connection (self, call->connection, &add_error))
+		call->callback (NM_SETTINGS_INTERFACE (self), NULL, call->callback_data);
+	else {
+		error = g_error_new (NM_SYSCONFIG_SETTINGS_ERROR,
+		                     NM_SYSCONFIG_SETTINGS_ERROR_ADD_FAILED,
+		                     "Saving connection failed: (%d) %s",
+		                     add_error ? add_error->code : -1,
+		                     (add_error && add_error->message) ? add_error->message : "(unknown)");
+		g_error_free (add_error);
+		call->callback (NM_SETTINGS_INTERFACE (self), error, call->callback_data);
+	}
+
+out:
+	g_clear_error (&error);
+	polkit_call_free (call);
+	if (pk_result)
+		g_object_unref (pk_result);
+}
+
+static void
+add_connection (NMSettingsService *service,
+	            NMConnection *connection,
+	            DBusGMethodInvocation *context, /* Only present for D-Bus calls */
+	            NMSettingsAddConnectionFunc callback,
+	            gpointer user_data)
+{
+	NMSysconfigSettings *self = NM_SYSCONFIG_SETTINGS (service);
+	NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+	PolkitCall *call;
+	GError *error = NULL;
+
+	/* Do any of the plugins support adding? */
+	if (!get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS)) {
+		error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR,
+		                             NM_SYSCONFIG_SETTINGS_ERROR_ADD_NOT_SUPPORTED,
+		                             "None of the registered plugins support add.");
+		callback (NM_SETTINGS_INTERFACE (service), error, user_data);
+		g_error_free (error);
+		return;
+	}
+
+	call = polkit_call_new (self, context, connection, callback, user_data, NULL);
+	g_assert (call);
+	polkit_authority_check_authorization (priv->authority,
+	                                      call->subject,
+	                                      NM_SYSCONFIG_POLICY_ACTION_CONNECTION_MODIFY,
+	                                      NULL,
+	                                      POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
+	                                      call->cancellable,
+	                                      pk_add_cb,
+	                                      call);
+	priv->pk_calls = g_slist_append (priv->pk_calls, call);
+}
+
+static void
+pk_hostname_cb (GObject *object, GAsyncResult *result, gpointer user_data)
+{
+	PolkitCall *call = user_data;
+	NMSysconfigSettings *self = call->self;
+	NMSysconfigSettingsPrivate *priv;
+	PolkitAuthorizationResult *pk_result;
+	GError *error = NULL;
+	GSList *iter;
+	gboolean success = FALSE;
+
+	/* If our NMSysconfigConnection is already gone, do nothing */
+	if (call->disposed) {
+		error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR,
+		                             NM_SYSCONFIG_SETTINGS_ERROR_GENERAL,
+		                             "Request was canceled.");
+		dbus_g_method_return_error (call->context, error);
+		g_error_free (error);
+		polkit_call_free (call);
+		return;
+	}
+
+	priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+
+	priv->pk_calls = g_slist_remove (priv->pk_calls, call);
+
+	pk_result = polkit_authority_check_authorization_finish (priv->authority,
+	                                                         result,
+	                                                         &error);
+	/* Some random error happened */
+	if (error) {
+		dbus_g_method_return_error (call->context, error);
+		goto out;
+	}
+
+	/* Caller didn't successfully authenticate */
+	if (!polkit_authorization_result_get_is_authorized (pk_result)) {
+		error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR,
+		                             NM_SYSCONFIG_SETTINGS_ERROR_NOT_PRIVILEGED,
+		                             "Insufficient privileges.");
+		dbus_g_method_return_error (call->context, error);
+		goto out;
+	}
+
+	/* Set the hostname in all plugins */
+	for (iter = priv->plugins; iter; iter = iter->next) {
+		NMSystemConfigInterfaceCapabilities caps = NM_SYSTEM_CONFIG_INTERFACE_CAP_NONE;
+
+		g_object_get (G_OBJECT (iter->data), NM_SYSTEM_CONFIG_INTERFACE_CAPABILITIES, &caps, NULL);
+		if (caps & NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME) {
+			g_object_set (G_OBJECT (iter->data), NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME, call->hostname, NULL);
+			success = TRUE;
+		}
+	}
+
+	if (success) {
+		dbus_g_method_return (call->context);
+	} else {
+		error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR,
+		                             NM_SYSCONFIG_SETTINGS_ERROR_SAVE_HOSTNAME_FAILED,
+		                             "Saving the hostname failed.");
+		dbus_g_method_return_error (call->context, error);
+	}
+
+out:
+	g_clear_error (&error);
+	polkit_call_free (call);
+	if (pk_result)
+		g_object_unref (pk_result);
+}
+
+static void
+impl_settings_save_hostname (NMSysconfigSettings *self,
+                             const char *hostname,
+                             DBusGMethodInvocation *context)
+{
+	NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+	PolkitCall *call;
+	GError *error = NULL;
+
+	/* Do any of the plugins support setting the hostname? */
+	if (!get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME)) {
+		error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR,
+		                             NM_SYSCONFIG_SETTINGS_ERROR_SAVE_HOSTNAME_NOT_SUPPORTED,
+		                             "None of the registered plugins support setting the hostname.");
+		dbus_g_method_return_error (context, error);
+		g_error_free (error);
+		return;
+	}
+
+	call = polkit_call_new (self, context, NULL, NULL, NULL, hostname);
+	g_assert (call);
+	polkit_authority_check_authorization (priv->authority,
+	                                      call->subject,
+	                                      NM_SYSCONFIG_POLICY_ACTION_HOSTNAME_MODIFY,
+	                                      NULL,
+	                                      POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
+	                                      call->cancellable,
+	                                      pk_hostname_cb,
+	                                      call);
+	priv->pk_calls = g_slist_append (priv->pk_calls, call);
+}
+
+static void
+pk_authority_changed_cb (GObject *object, gpointer user_data)
+{
+	/* Let clients know they should re-check their authorization */
+	g_signal_emit_by_name (NM_SYSCONFIG_SETTINGS (user_data),
+                           NM_SETTINGS_SYSTEM_INTERFACE_CHECK_PERMISSIONS);
+}
+
+typedef struct {
+	PolkitCall *pk_call;
+	const char *pk_action;
+	GCancellable *cancellable;
+	NMSettingsSystemPermissions permission;
+	gboolean disposed;
+} PermissionsCall;
+
+static void
+permission_call_done (GObject *object, GAsyncResult *result, gpointer user_data)
+{
+	PermissionsCall *call = user_data;
+	PolkitCall *pk_call = call->pk_call;
+	NMSysconfigSettings *self = pk_call->self;
+	NMSysconfigSettingsPrivate *priv;
+	PolkitAuthorizationResult *pk_result;
+	GError *error = NULL;
+
+	/* If NMSysconfigSettings is gone, just skip to the end */
+	if (call->disposed)
+		goto done;
+
+	priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+
+	priv->permissions_calls = g_slist_remove (priv->permissions_calls, call);
+
+	pk_result = polkit_authority_check_authorization_finish (priv->authority,
+	                                                         result,
+	                                                         &error);
+	/* Some random error happened */
+	if (error) {
+		nm_log_err (LOGD_SYS_SET, "error checking '%s' permission: (%d) %s",
+		            __FILE__, __LINE__, __func__,
+		            call->pk_action,
+		            error ? error->code : -1,
+		            error && error->message ? error->message : "(unknown)");
+		if (error)
+			g_error_free (error);
+	} else {
+		/* If the caller is authorized, or the caller could authorize via a
+		 * challenge, then authorization is possible.  Otherwise, caller is out of
+		 * luck.
+		 */
+		if (   polkit_authorization_result_get_is_authorized (pk_result)
+		    || polkit_authorization_result_get_is_challenge (pk_result))
+		    pk_call->permissions |= call->permission;
+	}
+
+	g_object_unref (pk_result);
+
+done:
+	pk_call->permissions_calls--;
+	if (pk_call->permissions_calls == 0) {
+		if (call->disposed) {
+			error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR,
+			                             NM_SYSCONFIG_SETTINGS_ERROR_GENERAL,
+			                             "Request was canceled.");
+			dbus_g_method_return_error (pk_call->context, error);
+			g_error_free (error);
+		} else {
+			/* All the permissions calls are done, return the full permissions
+			 * bitfield back to the user.
+			 */
+			dbus_g_method_return (pk_call->context, pk_call->permissions);
+		}
+
+		polkit_call_free (pk_call);
+	}
+	memset (call, 0, sizeof (PermissionsCall));
+	g_free (call);
+}
+
+static void
+start_permission_check (NMSysconfigSettings *self,
+                        PolkitCall *pk_call,
+                        const char *pk_action,
+                        NMSettingsSystemPermissions permission)
+{
+	NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+	PermissionsCall *call;
+
+	g_return_if_fail (pk_call != NULL);
+	g_return_if_fail (pk_action != NULL);
+	g_return_if_fail (permission != NM_SETTINGS_SYSTEM_PERMISSION_NONE);
+
+	call = g_malloc0 (sizeof (PermissionsCall));
+	call->pk_call = pk_call;
+	call->pk_action = pk_action;
+	call->permission = permission;
+	call->cancellable = g_cancellable_new ();
+
+	pk_call->permissions_calls++;
+
+	polkit_authority_check_authorization (priv->authority,
+	                                      pk_call->subject,
+	                                      pk_action,
+	                                      NULL,
+	                                      0,
+	                                      call->cancellable,
+	                                      permission_call_done,
+	                                      call);
+	priv->permissions_calls = g_slist_append (priv->permissions_calls, call);
+}
+
+static void
+impl_settings_get_permissions (NMSysconfigSettings *self,
+                               DBusGMethodInvocation *context)
+{
+	PolkitCall *call;
+
+	call = polkit_call_new (self, context, NULL, NULL, NULL, FALSE);
+	g_assert (call);
+
+	/* Start checks for the various permissions */
+
+	/* Only check for connection-modify if one of our plugins supports it. */
+	if (get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS)) {
+		start_permission_check (self, call,
+		                        NM_SYSCONFIG_POLICY_ACTION_CONNECTION_MODIFY,
+		                        NM_SETTINGS_SYSTEM_PERMISSION_CONNECTION_MODIFY);
+	}
+
+	/* Only check for hostname-modify if one of our plugins supports it. */
+	if (get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME)) {
+		start_permission_check (self, call,
+		                        NM_SYSCONFIG_POLICY_ACTION_HOSTNAME_MODIFY,
+		                        NM_SETTINGS_SYSTEM_PERMISSION_HOSTNAME_MODIFY);
+	}
+
+	// FIXME: hook these into plugin permissions like the modify permissions */
+	start_permission_check (self, call,
+	                        NM_SYSCONFIG_POLICY_ACTION_WIFI_SHARE_OPEN,
+	                        NM_SETTINGS_SYSTEM_PERMISSION_WIFI_SHARE_OPEN);
+	start_permission_check (self, call,
+	                        NM_SYSCONFIG_POLICY_ACTION_WIFI_SHARE_PROTECTED,
+	                        NM_SETTINGS_SYSTEM_PERMISSION_WIFI_SHARE_PROTECTED);
+}
+
+static gboolean
+get_permissions (NMSettingsSystemInterface *settings,
+                 NMSettingsSystemGetPermissionsFunc callback,
+                 gpointer user_data)
+{
+	NMSysconfigSettings *self = NM_SYSCONFIG_SETTINGS (settings);
+	NMSettingsSystemPermissions permissions = NM_SETTINGS_SYSTEM_PERMISSION_NONE;
+
+	/* Local caller (ie, NM) gets full permissions by default because it doesn't
+	 * need authorization.  However, permissions are still subject to plugin's
+	 * restrictions.  i.e. if no plugins support connection-modify, then even
+	 * the local caller won't get that permission.
+	 */
+
+	/* Only check for connection-modify if one of our plugins supports it. */
+	if (get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS))
+		permissions |= NM_SETTINGS_SYSTEM_PERMISSION_CONNECTION_MODIFY;
+
+	/* Only check for hostname-modify if one of our plugins supports it. */
+	if (get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME))
+		permissions |= NM_SETTINGS_SYSTEM_PERMISSION_HOSTNAME_MODIFY;
+
+	// FIXME: hook these into plugin permissions like the modify permissions */
+	permissions |= NM_SETTINGS_SYSTEM_PERMISSION_WIFI_SHARE_OPEN;
+	permissions |= NM_SETTINGS_SYSTEM_PERMISSION_WIFI_SHARE_PROTECTED;
+
+	callback (settings, permissions, NULL, user_data);
+	return TRUE;
+}
+
+static gboolean
+have_connection_for_device (NMSysconfigSettings *self, GByteArray *mac)
+{
+	NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+	GHashTableIter iter;
+	gpointer key;
+	NMSettingConnection *s_con;
+	NMSettingWired *s_wired;
+	const GByteArray *setting_mac;
+	gboolean ret = FALSE;
+
+	g_return_val_if_fail (NM_IS_SYSCONFIG_SETTINGS (self), FALSE);
+	g_return_val_if_fail (mac != NULL, FALSE);
+
+	/* Find a wired connection locked to the given MAC address, if any */
+	g_hash_table_iter_init (&iter, priv->connections);
+	while (g_hash_table_iter_next (&iter, &key, NULL)) {
+		NMConnection *connection = NM_CONNECTION (key);
+		const char *connection_type;
+
+		s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
+		connection_type = nm_setting_connection_get_connection_type (s_con);
+
+		if (   strcmp (connection_type, NM_SETTING_WIRED_SETTING_NAME)
+		    && strcmp (connection_type, NM_SETTING_PPPOE_SETTING_NAME))
+			continue;
+
+		s_wired = (NMSettingWired *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED);
+
+		/* No wired setting; therefore the PPPoE connection applies to any device */
+		if (!s_wired && !strcmp (connection_type, NM_SETTING_PPPOE_SETTING_NAME)) {
+			ret = TRUE;
+			break;
+		}
+
+		setting_mac = nm_setting_wired_get_mac_address (s_wired);
+		if (setting_mac) {
+			/* A connection mac-locked to this device */
+			if (!memcmp (setting_mac->data, mac->data, ETH_ALEN)) {
+				ret = TRUE;
+				break;
+			}
+		} else {
+			/* A connection that applies to any wired device */
+			ret = TRUE;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+/* Search through the list of blacklisted MAC addresses in the config file. */
+static gboolean
+is_mac_auto_wired_blacklisted (NMSysconfigSettings *self, const GByteArray *mac)
+{
+	NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+	GKeyFile *config;
+	char **list, **iter;
+	gboolean found = FALSE;
+
+	g_return_val_if_fail (mac != NULL, FALSE);
+
+	if (!priv->config_file)
+		return FALSE;
+
+	config = g_key_file_new ();
+	if (!config) {
+		nm_log_warn (LOGD_SYS_SET, "not enough memory to load config file.");
+		return FALSE;
+	}
+
+	g_key_file_set_list_separator (config, ',');
+	if (!g_key_file_load_from_file (config, priv->config_file, G_KEY_FILE_NONE, NULL))
+		goto out;
+
+	list = g_key_file_get_string_list (config, "main", CONFIG_KEY_NO_AUTO_DEFAULT, NULL, NULL);
+	for (iter = list; iter && *iter; iter++) {
+		struct ether_addr *candidate;
+
+		candidate = ether_aton (*iter);
+		if (candidate && !memcmp (mac->data, candidate->ether_addr_octet, ETH_ALEN)) {
+			found = TRUE;
+			break;
+		}
+	}
+
+	if (list)
+		g_strfreev (list);
+
+out:
+	g_key_file_free (config);
+	return found;
+}
+
+#define DEFAULT_WIRED_TAG "default-wired"
+
+static void
+default_wired_deleted (NMDefaultWiredConnection *wired,
+                       const GByteArray *mac,
+                       NMSysconfigSettings *self)
+{
+	NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+	NMSettingConnection *s_con;
+	char *tmp;
+	GKeyFile *config;
+	char **list, **iter, **updated;
+	gboolean found = FALSE;
+	gsize len = 0, i;
+	char *data;
+
+	/* If there was no config file specified, there's nothing to do */
+	if (!priv->config_file)
+		goto cleanup;
+
+	/* When the default wired connection is removed (either deleted or saved
+	 * to a new persistent connection by a plugin), write the MAC address of
+	 * the wired device to the config file and don't create a new default wired
+	 * connection for that device again.
+	 */
+
+	s_con = (NMSettingConnection *) nm_connection_get_setting (NM_CONNECTION (wired),
+	                                                           NM_TYPE_SETTING_CONNECTION);
+	g_assert (s_con);
+
+	/* Ignore removals of read-only connections, since they couldn't have
+	 * been removed by the user.
+	 */
+	if (nm_setting_connection_get_read_only (s_con))
+		goto cleanup;
+
+	config = g_key_file_new ();
+	if (!config)
+		goto cleanup;
+
+	g_key_file_set_list_separator (config, ',');
+	g_key_file_load_from_file (config, priv->config_file, G_KEY_FILE_KEEP_COMMENTS, NULL);
+
+	list = g_key_file_get_string_list (config, "main", CONFIG_KEY_NO_AUTO_DEFAULT, &len, NULL);
+	/* Traverse entire list to get count of # items */
+	for (iter = list; iter && *iter; iter++) {
+		struct ether_addr *candidate;
+
+		candidate = ether_aton (*iter);
+		if (candidate && !memcmp (mac->data, candidate->ether_addr_octet, ETH_ALEN))
+			found = TRUE;
+	}
+
+	/* Add this device's MAC to the list */
+	if (!found) {
+		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]);
+
+		/* New list; size + 1 for the new element, + 1 again for ending NULL */
+		updated = g_malloc0 (sizeof (char*) * (len + 2));
+
+		/* Copy original list and add new MAC */
+		for (i = 0; list && list[i]; i++)
+			updated[i] = list[i];
+		updated[i++] = tmp;
+		updated[i] = NULL;
+
+		g_key_file_set_string_list (config,
+		                            "main", CONFIG_KEY_NO_AUTO_DEFAULT,
+		                            (const char **) updated,
+		                            len + 2);
+		/* g_free() not g_strfreev() since 'updated' isn't a deep-copy */
+		g_free (updated);
+		g_free (tmp);
+
+		data = g_key_file_to_data (config, &len, NULL);
+		if (data) {
+			g_file_set_contents (priv->config_file, data, len, NULL);
+			g_free (data);
+		}
+	}
+
+	if (list)
+		g_strfreev (list);
+	g_key_file_free (config);
+
+cleanup:
+	g_object_set_data (G_OBJECT (nm_default_wired_connection_get_device (wired)),
+	                   DEFAULT_WIRED_TAG,
+	                   NULL);
+}
+
+static void
+delete_cb (NMSettingsConnectionInterface *connection, GError *error, gpointer user_data)
+{
+}
+
+static gboolean
+default_wired_try_update (NMDefaultWiredConnection *wired,
+                          NMSysconfigSettings *self)
+{
+	GError *error = NULL;
+	NMSettingConnection *s_con;
+	const char *id;
+
+	/* Try to move this default wired conneciton to a plugin so that it has
+	 * persistent storage.
+	 */
+
+	s_con = (NMSettingConnection *) nm_connection_get_setting (NM_CONNECTION (wired),
+	                                                           NM_TYPE_SETTING_CONNECTION);
+	g_assert (s_con);
+	id = nm_setting_connection_get_id (s_con);
+	g_assert (id);
+
+	remove_connection (self, NM_SETTINGS_CONNECTION_INTERFACE (wired), FALSE);
+	if (add_new_connection (self, NM_CONNECTION (wired), &error)) {
+		nm_settings_connection_interface_delete (NM_SETTINGS_CONNECTION_INTERFACE (wired),
+		                                         delete_cb,
+		                                         NULL);
+
+		g_object_set_data (G_OBJECT (nm_default_wired_connection_get_device (wired)),
+		                   DEFAULT_WIRED_TAG,
+		                   NULL);
+		nm_log_info (LOGD_SYS_SET, "Saved default wired connection '%s' to persistent storage", id);
+		return FALSE;
+	}
+
+	nm_log_warn (LOGD_SYS_SET, "couldn't save default wired connection '%s': %d / %s",
+	             id,
+	             error ? error->code : -1,
+	             (error && error->message) ? error->message : "(unknown)");
+
+	/* If there was an error, don't destroy the default wired connection,
+	 * but add it back to the system settings service. Connection is already
+	 * exported on the bus, don't export it again, thus do_export == FALSE.
+	 */
+	claim_connection (self, NM_SETTINGS_CONNECTION_INTERFACE (wired), FALSE);
+	return TRUE;
+}
+
+void
+nm_sysconfig_settings_device_added (NMSysconfigSettings *self, NMDevice *device)
+{
+	GByteArray *mac = NULL;
+	struct ether_addr tmp;
+	NMDefaultWiredConnection *wired;
+	NMSettingConnection *s_con;
+	gboolean read_only = TRUE;
+	const char *id;
+
+	if (nm_device_get_device_type (device) != NM_DEVICE_TYPE_ETHERNET)
+		return;
+
+	/* If the device isn't managed or it already has a default wired connection,
+	 * ignore it.
+	 */
+	if (   !nm_device_get_managed (device)
+	    || g_object_get_data (G_OBJECT (device), DEFAULT_WIRED_TAG))
+		return;
+
+	nm_device_ethernet_get_address (NM_DEVICE_ETHERNET (device), &tmp);
+
+	mac = g_byte_array_sized_new (ETH_ALEN);
+	g_byte_array_append (mac, tmp.ether_addr_octet, ETH_ALEN);
+
+	if (   have_connection_for_device (self, mac)
+	    || is_mac_auto_wired_blacklisted (self, mac))
+		goto ignore;
+
+	if (get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS))
+		read_only = FALSE;
+
+	wired = nm_default_wired_connection_new (mac, device, read_only);
+	if (!wired)
+		goto ignore;
+
+	s_con = (NMSettingConnection *) nm_connection_get_setting (NM_CONNECTION (wired),
+	                                                           NM_TYPE_SETTING_CONNECTION);
+	g_assert (s_con);
+	id = nm_setting_connection_get_id (s_con);
+	g_assert (id);
+
+	nm_log_info (LOGD_SYS_SET, "Added default wired connection '%s' for %s",
+	             id, nm_device_get_udi (device));
+
+	g_signal_connect (wired, "try-update", (GCallback) default_wired_try_update, self);
+	g_signal_connect (wired, "deleted", (GCallback) default_wired_deleted, self);
+	claim_connection (self, NM_SETTINGS_CONNECTION_INTERFACE (wired), TRUE);
+	g_object_unref (wired);
+
+	g_object_set_data (G_OBJECT (device), DEFAULT_WIRED_TAG, wired);
+
+ignore:
+	g_byte_array_free (mac, TRUE);
+}
+
+void
+nm_sysconfig_settings_device_removed (NMSysconfigSettings *self, NMDevice *device)
+{
+	NMDefaultWiredConnection *connection;
+
+	if (nm_device_get_device_type (device) != NM_DEVICE_TYPE_ETHERNET)
+		return;
+
+	connection = (NMDefaultWiredConnection *) g_object_get_data (G_OBJECT (device), DEFAULT_WIRED_TAG);
+	if (connection)
+		remove_connection (self, NM_SETTINGS_CONNECTION_INTERFACE (connection), TRUE);
+}
+
+NMSysconfigSettings *
+nm_sysconfig_settings_new (const char *config_file,
+                           const char *plugins,
+                           DBusGConnection *bus,
+                           GError **error)
+{
+	NMSysconfigSettings *self;
+	NMSysconfigSettingsPrivate *priv;
+
+	self = g_object_new (NM_TYPE_SYSCONFIG_SETTINGS,
+	                     NM_SETTINGS_SERVICE_BUS, bus,
+	                     NM_SETTINGS_SERVICE_SCOPE, NM_CONNECTION_SCOPE_SYSTEM,
+	                     NULL);
+	if (!self)
+		return NULL;
+
+	priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+
+	priv->config_file = g_strdup (config_file);
+
+	if (plugins) {
+		/* Load the plugins; fail if a plugin is not found. */
+		if (!load_plugins (self, plugins, error)) {
+			g_object_unref (self);
+			return NULL;
+		}
+		unmanaged_specs_changed (NULL, self);
+	}
+
+	return self;
+}
+
+/***************************************************************/
+
+static void
+dispose (GObject *object)
+{
+	NMSysconfigSettings *self = NM_SYSCONFIG_SETTINGS (object);
+	NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+	GSList *iter;
+
+	if (priv->auth_changed_id) {
+		g_signal_handler_disconnect (priv->authority, priv->auth_changed_id);
+		priv->auth_changed_id = 0;
+	}
+
+	/* Cancel PolicyKit requests */
+	for (iter = priv->pk_calls; iter; iter = g_slist_next (iter)) {
+		PolkitCall *call = iter->data;
+
+		call->disposed = TRUE;
+		g_cancellable_cancel (call->cancellable);
+	}
+	g_slist_free (priv->pk_calls);
+	priv->pk_calls = NULL;
+
+	/* Cancel PolicyKit permissions requests */
+	for (iter = priv->permissions_calls; iter; iter = g_slist_next (iter)) {
+		PermissionsCall *call = iter->data;
+
+		call->disposed = TRUE;
+		g_cancellable_cancel (call->cancellable);
+	}
+	g_slist_free (priv->permissions_calls);
+	priv->permissions_calls = NULL;
+
+	G_OBJECT_CLASS (nm_sysconfig_settings_parent_class)->dispose (object);
+}
+
+static void
+finalize (GObject *object)
+{
+	NMSysconfigSettings *self = NM_SYSCONFIG_SETTINGS (object);
+	NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+
+	g_hash_table_destroy (priv->connections);
+
+	clear_unmanaged_specs (self);
+
+	g_slist_foreach (priv->plugins, (GFunc) g_object_unref, NULL);
+	g_slist_free (priv->plugins);
+
+	g_free (priv->config_file);
+
+	G_OBJECT_CLASS (nm_sysconfig_settings_parent_class)->finalize (object);
+}
+
+static void
+settings_system_interface_init (NMSettingsSystemInterface *iface)
+{
+	iface->get_permissions = get_permissions;
+
+	dbus_g_object_type_install_info (G_TYPE_FROM_INTERFACE (iface),
+	                                 &dbus_glib_nm_settings_system_object_info);
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+			  GValue *value, GParamSpec *pspec)
+{
+	NMSysconfigSettings *self = NM_SYSCONFIG_SETTINGS (object);
+	const GSList *specs, *iter;
+	GSList *copy = NULL;
+
+	switch (prop_id) {
+	case PROP_UNMANAGED_SPECS:
+		specs = nm_sysconfig_settings_get_unmanaged_specs (self);
+		for (iter = specs; iter; iter = g_slist_next (iter))
+			copy = g_slist_append (copy, g_strdup (iter->data));
+		g_value_take_boxed (value, copy);
+		break;
+	case NM_SETTINGS_SYSTEM_INTERFACE_PROP_HOSTNAME:
+		g_value_take_string (value, nm_sysconfig_settings_get_hostname (self));
+
+		/* Don't ever pass NULL through D-Bus */
+		if (!g_value_get_string (value))
+			g_value_set_static_string (value, "");
+		break;
+	case NM_SETTINGS_SYSTEM_INTERFACE_PROP_CAN_MODIFY:
+		g_value_set_boolean (value, !!get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nm_sysconfig_settings_class_init (NMSysconfigSettingsClass *class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (class);
+	NMSettingsServiceClass *ss_class = NM_SETTINGS_SERVICE_CLASS (class);
+	
+	g_type_class_add_private (class, sizeof (NMSysconfigSettingsPrivate));
+
+	/* virtual methods */
+	object_class->notify = notify;
+	object_class->get_property = get_property;
+	object_class->dispose = dispose;
+	object_class->finalize = finalize;
+	ss_class->list_connections = list_connections;
+	ss_class->add_connection = add_connection;
+
+	/* properties */
+	g_object_class_install_property
+		(object_class, PROP_UNMANAGED_SPECS,
+		 g_param_spec_boxed (NM_SYSCONFIG_SETTINGS_UNMANAGED_SPECS,
+							 "Unamanged device specs",
+							 "Unmanaged device specs",
+							 DBUS_TYPE_G_LIST_OF_STRING,
+							 G_PARAM_READABLE));
+
+	g_object_class_override_property (object_class,
+									  NM_SETTINGS_SYSTEM_INTERFACE_PROP_HOSTNAME,
+									  NM_SETTINGS_SYSTEM_INTERFACE_HOSTNAME);
+
+	g_object_class_override_property (object_class,
+									  NM_SETTINGS_SYSTEM_INTERFACE_PROP_CAN_MODIFY,
+									  NM_SETTINGS_SYSTEM_INTERFACE_CAN_MODIFY);
+
+	/* signals */
+	signals[PROPERTIES_CHANGED] = 
+	                g_signal_new ("properties-changed",
+	                              G_OBJECT_CLASS_TYPE (object_class),
+	                              G_SIGNAL_RUN_FIRST,
+	                              G_STRUCT_OFFSET (NMSysconfigSettingsClass, properties_changed),
+	                              NULL, NULL,
+	                              g_cclosure_marshal_VOID__BOXED,
+	                              G_TYPE_NONE, 1, DBUS_TYPE_G_MAP_OF_VARIANT);
+
+	dbus_g_error_domain_register (NM_SYSCONFIG_SETTINGS_ERROR,
+	                              NM_DBUS_IFACE_SETTINGS_SYSTEM,
+	                              NM_TYPE_SYSCONFIG_SETTINGS_ERROR);
+
+	dbus_g_error_domain_register (NM_SETTINGS_INTERFACE_ERROR,
+	                              NM_DBUS_IFACE_SETTINGS,
+	                              NM_TYPE_SETTINGS_INTERFACE_ERROR);
+
+	/* And register all the settings errors with D-Bus */
+	dbus_g_error_domain_register (NM_CONNECTION_ERROR, NULL, NM_TYPE_CONNECTION_ERROR);
+	dbus_g_error_domain_register (NM_SETTING_802_1X_ERROR, NULL, NM_TYPE_SETTING_802_1X_ERROR);
+	dbus_g_error_domain_register (NM_SETTING_BLUETOOTH_ERROR, NULL, NM_TYPE_SETTING_BLUETOOTH_ERROR);
+	dbus_g_error_domain_register (NM_SETTING_CDMA_ERROR, NULL, NM_TYPE_SETTING_CDMA_ERROR);
+	dbus_g_error_domain_register (NM_SETTING_CONNECTION_ERROR, NULL, NM_TYPE_SETTING_CONNECTION_ERROR);
+	dbus_g_error_domain_register (NM_SETTING_GSM_ERROR, NULL, NM_TYPE_SETTING_GSM_ERROR);
+	dbus_g_error_domain_register (NM_SETTING_IP4_CONFIG_ERROR, NULL, NM_TYPE_SETTING_IP4_CONFIG_ERROR);
+	dbus_g_error_domain_register (NM_SETTING_IP6_CONFIG_ERROR, NULL, NM_TYPE_SETTING_IP6_CONFIG_ERROR);
+	dbus_g_error_domain_register (NM_SETTING_OLPC_MESH_ERROR, NULL, NM_TYPE_SETTING_OLPC_MESH_ERROR);
+	dbus_g_error_domain_register (NM_SETTING_PPP_ERROR, NULL, NM_TYPE_SETTING_PPP_ERROR);
+	dbus_g_error_domain_register (NM_SETTING_PPPOE_ERROR, NULL, NM_TYPE_SETTING_PPPOE_ERROR);
+	dbus_g_error_domain_register (NM_SETTING_SERIAL_ERROR, NULL, NM_TYPE_SETTING_SERIAL_ERROR);
+	dbus_g_error_domain_register (NM_SETTING_VPN_ERROR, NULL, NM_TYPE_SETTING_VPN_ERROR);
+	dbus_g_error_domain_register (NM_SETTING_WIRED_ERROR, NULL, NM_TYPE_SETTING_WIRED_ERROR);
+	dbus_g_error_domain_register (NM_SETTING_WIRELESS_SECURITY_ERROR, NULL, NM_TYPE_SETTING_WIRELESS_SECURITY_ERROR);
+	dbus_g_error_domain_register (NM_SETTING_WIRELESS_ERROR, NULL, NM_TYPE_SETTING_WIRELESS_ERROR);
+	dbus_g_error_domain_register (NM_SETTING_ERROR, NULL, NM_TYPE_SETTING_ERROR);
+}
+
+static void
+nm_sysconfig_settings_init (NMSysconfigSettings *self)
+{
+	NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+
+	priv->connections = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL);
+
+	priv->authority = polkit_authority_get ();
+	if (priv->authority) {
+		priv->auth_changed_id = g_signal_connect (priv->authority,
+		                                          "changed",
+		                                          G_CALLBACK (pk_authority_changed_cb),
+		                                          self);
+	} else
+		nm_log_warn (LOGD_SYS_SET, "failed to create PolicyKit authority.");
+}
+
diff --git a/src/system-settings/nm-sysconfig-settings.h b/src/system-settings/nm-sysconfig-settings.h
new file mode 100644
index 00000000..ae2ba683
--- /dev/null
+++ b/src/system-settings/nm-sysconfig-settings.h
@@ -0,0 +1,71 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service
+ *
+ * Søren Sandmann <sandmann@daimi.au.dk>
+ * Dan Williams <dcbw@redhat.com>
+ * Tambet Ingo <tambet@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.
+ *
+ * (C) Copyright 2007 - 2009 Red Hat, Inc.
+ * (C) Copyright 2008 Novell, Inc.
+ */
+
+#ifndef __NM_SYSCONFIG_SETTINGS_H__
+#define __NM_SYSCONFIG_SETTINGS_H__
+
+#include <nm-connection.h>
+#include <nm-settings-service.h>
+
+#include "nm-sysconfig-connection.h"
+#include "nm-system-config-interface.h"
+#include "nm-device.h"
+
+#define NM_TYPE_SYSCONFIG_SETTINGS            (nm_sysconfig_settings_get_type ())
+#define NM_SYSCONFIG_SETTINGS(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SYSCONFIG_SETTINGS, NMSysconfigSettings))
+#define NM_SYSCONFIG_SETTINGS_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  NM_TYPE_SYSCONFIG_SETTINGS, NMSysconfigSettingsClass))
+#define NM_IS_SYSCONFIG_SETTINGS(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SYSCONFIG_SETTINGS))
+#define NM_IS_SYSCONFIG_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  NM_TYPE_SYSCONFIG_SETTINGS))
+#define NM_SYSCONFIG_SETTINGS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  NM_TYPE_SYSCONFIG_SETTINGS, NMSysconfigSettingsClass))
+
+#define NM_SYSCONFIG_SETTINGS_UNMANAGED_SPECS "unmanaged-specs"
+
+typedef struct {
+	NMSettingsService parent_instance;
+} NMSysconfigSettings;
+
+typedef struct {
+	NMSettingsServiceClass parent_class;
+
+	/* Signals */
+	void (*properties_changed) (NMSysconfigSettings *self, GHashTable *properties);
+} NMSysconfigSettingsClass;
+
+GType nm_sysconfig_settings_get_type (void);
+
+NMSysconfigSettings *nm_sysconfig_settings_new (const char *config_file,
+                                                const char *plugins,
+                                                DBusGConnection *bus,
+                                                GError **error);
+
+const GSList *nm_sysconfig_settings_get_unmanaged_specs (NMSysconfigSettings *self);
+
+char *nm_sysconfig_settings_get_hostname (NMSysconfigSettings *self);
+
+void nm_sysconfig_settings_device_added (NMSysconfigSettings *self, NMDevice *device);
+
+void nm_sysconfig_settings_device_removed (NMSysconfigSettings *self, NMDevice *device);
+
+#endif  /* __NM_SYSCONFIG_SETTINGS_H__ */
diff --git a/src/system-settings/nm-system-config-error.c b/src/system-settings/nm-system-config-error.c
new file mode 100644
index 00000000..13d47462
--- /dev/null
+++ b/src/system-settings/nm-system-config-error.c
@@ -0,0 +1,59 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2008 Novell, Inc.
+ * Copyright (C) 2008 Red Hat, Inc.
+ */
+
+#include "nm-system-config-error.h"
+
+GQuark
+nm_sysconfig_settings_error_quark (void)
+{
+	static GQuark ret = 0;
+
+	if (ret == 0)
+		ret = g_quark_from_static_string ("nm_sysconfig_settings_error");
+
+	return ret;
+}
+
+#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
+
+GType
+nm_sysconfig_settings_error_get_type (void)
+{
+	static GType etype = 0;
+
+	if (etype == 0) {
+		static const GEnumValue values[] = {
+			ENUM_ENTRY (NM_SYSCONFIG_SETTINGS_ERROR_GENERAL, "GeneralError"),
+			ENUM_ENTRY (NM_SYSCONFIG_SETTINGS_ERROR_NOT_PRIVILEGED, "NotPrivileged"),
+			ENUM_ENTRY (NM_SYSCONFIG_SETTINGS_ERROR_ADD_NOT_SUPPORTED, "AddNotSupported"),
+			ENUM_ENTRY (NM_SYSCONFIG_SETTINGS_ERROR_UPDATE_NOT_SUPPORTED, "UpdateNotSupported"),
+			ENUM_ENTRY (NM_SYSCONFIG_SETTINGS_ERROR_DELETE_NOT_SUPPORTED, "DeleteNotSupported"),
+			ENUM_ENTRY (NM_SYSCONFIG_SETTINGS_ERROR_ADD_FAILED, "AddFailed"),
+			ENUM_ENTRY (NM_SYSCONFIG_SETTINGS_ERROR_SAVE_HOSTNAME_NOT_SUPPORTED, "SaveHostnameNotSupported"),
+			ENUM_ENTRY (NM_SYSCONFIG_SETTINGS_ERROR_SAVE_HOSTNAME_FAILED, "SaveHostnameFailed"),
+			{ 0, 0, 0 }
+		};
+
+		etype = g_enum_register_static ("NMSysconfigSettingsError", values);
+	}
+
+	return etype;
+}
diff --git a/src/system-settings/nm-system-config-error.h b/src/system-settings/nm-system-config-error.h
new file mode 100644
index 00000000..63896fcd
--- /dev/null
+++ b/src/system-settings/nm-system-config-error.h
@@ -0,0 +1,45 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2008 Novell, Inc.
+ * Copyright (C) 2008 Red Hat, Inc.
+ */
+
+#ifndef NM_SYSTEM_CONFIG_ERROR_H
+#define NM_SYSTEM_CONFIG_ERROR_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+enum {
+	NM_SYSCONFIG_SETTINGS_ERROR_GENERAL = 0,
+	NM_SYSCONFIG_SETTINGS_ERROR_NOT_PRIVILEGED,
+	NM_SYSCONFIG_SETTINGS_ERROR_ADD_NOT_SUPPORTED,
+	NM_SYSCONFIG_SETTINGS_ERROR_UPDATE_NOT_SUPPORTED,
+	NM_SYSCONFIG_SETTINGS_ERROR_DELETE_NOT_SUPPORTED,
+	NM_SYSCONFIG_SETTINGS_ERROR_ADD_FAILED,
+	NM_SYSCONFIG_SETTINGS_ERROR_SAVE_HOSTNAME_NOT_SUPPORTED,
+	NM_SYSCONFIG_SETTINGS_ERROR_SAVE_HOSTNAME_FAILED,
+};
+
+#define NM_SYSCONFIG_SETTINGS_ERROR (nm_sysconfig_settings_error_quark ())
+#define NM_TYPE_SYSCONFIG_SETTINGS_ERROR (nm_sysconfig_settings_error_get_type ())
+
+GQuark nm_sysconfig_settings_error_quark    (void);
+GType  nm_sysconfig_settings_error_get_type (void);
+
+#endif /* NM_SYSTEM_CONFIG_ERROR_H */
diff --git a/src/system-settings/nm-system-config-interface.c b/src/system-settings/nm-system-config-interface.c
new file mode 100644
index 00000000..90fd93ba
--- /dev/null
+++ b/src/system-settings/nm-system-config-interface.c
@@ -0,0 +1,163 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service
+ *
+ * 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) 2007 - 2008 Red Hat, Inc.
+ * Copyright (C) 2008 Novell, Inc.
+ */
+
+#include "nm-system-config-interface.h"
+
+static void
+interface_init (gpointer g_iface)
+{
+	GType iface_type = G_TYPE_FROM_INTERFACE (g_iface);
+	static gboolean initialized = FALSE;
+
+	if (initialized)
+		return;
+
+	/* Properties */
+	g_object_interface_install_property
+		(g_iface,
+		 g_param_spec_string (NM_SYSTEM_CONFIG_INTERFACE_NAME,
+							  "Name",
+							  "Plugin name",
+							  NULL,
+							  G_PARAM_READABLE));
+
+	g_object_interface_install_property
+		(g_iface,
+		 g_param_spec_string (NM_SYSTEM_CONFIG_INTERFACE_INFO,
+							  "Info",
+							  "Plugin information",
+							  NULL,
+							  G_PARAM_READABLE));
+
+	g_object_interface_install_property
+		(g_iface,
+		 g_param_spec_uint (NM_SYSTEM_CONFIG_INTERFACE_CAPABILITIES,
+							  "Capabilities",
+							  "Plugin capabilties",
+							  NM_SYSTEM_CONFIG_INTERFACE_CAP_NONE,
+							  NM_SYSTEM_CONFIG_INTERFACE_CAP_LAST - 1,
+							  NM_SYSTEM_CONFIG_INTERFACE_CAP_NONE,
+							  G_PARAM_READABLE));
+
+	g_object_interface_install_property
+		(g_iface,
+		 g_param_spec_string (NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME,
+							  "Hostname",
+							  "Configured hostname",
+							  NULL,
+							  G_PARAM_READWRITE));
+
+	/* Signals */
+	g_signal_new (NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED,
+				  iface_type,
+				  G_SIGNAL_RUN_FIRST,
+				  G_STRUCT_OFFSET (NMSystemConfigInterface, connection_added),
+				  NULL, NULL,
+				  g_cclosure_marshal_VOID__OBJECT,
+				  G_TYPE_NONE, 1,
+				  NM_TYPE_SETTINGS_CONNECTION_INTERFACE);
+
+	g_signal_new (NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED,
+				  iface_type,
+				  G_SIGNAL_RUN_FIRST,
+				  G_STRUCT_OFFSET (NMSystemConfigInterface, unmanaged_specs_changed),
+				  NULL, NULL,
+				  g_cclosure_marshal_VOID__VOID,
+				  G_TYPE_NONE, 0);
+
+	initialized = TRUE;
+}
+
+
+GType
+nm_system_config_interface_get_type (void)
+{
+	static GType system_config_interface_type = 0;
+
+	if (!system_config_interface_type) {
+		const GTypeInfo system_config_interface_info = {
+			sizeof (NMSystemConfigInterface), /* class_size */
+			interface_init,   /* base_init */
+			NULL,		/* base_finalize */
+			NULL,
+			NULL,		/* class_finalize */
+			NULL,		/* class_data */
+			0,
+			0,              /* n_preallocs */
+			NULL
+		};
+
+		system_config_interface_type = g_type_register_static (G_TYPE_INTERFACE,
+														       "NMSystemConfigInterface",
+														       &system_config_interface_info,
+														       0);
+
+		g_type_interface_add_prerequisite (system_config_interface_type, G_TYPE_OBJECT);
+	}
+
+	return system_config_interface_type;
+}
+
+void
+nm_system_config_interface_init (NMSystemConfigInterface *config,
+                                 gpointer unused)
+{
+	g_return_if_fail (config != NULL);
+
+	if (NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->init)
+		NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->init (config);
+}
+
+GSList *
+nm_system_config_interface_get_connections (NMSystemConfigInterface *config)
+{
+	g_return_val_if_fail (config != NULL, NULL);
+
+	if (NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->get_connections)
+		return NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->get_connections (config);
+	return NULL;
+}
+
+GSList *
+nm_system_config_interface_get_unmanaged_specs (NMSystemConfigInterface *config)
+{
+	g_return_val_if_fail (config != NULL, NULL);
+
+	if (NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->get_unmanaged_specs)
+		return NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->get_unmanaged_specs (config);
+	return NULL;
+}
+
+gboolean
+nm_system_config_interface_add_connection (NMSystemConfigInterface *config,
+                                           NMConnection *connection,
+                                           GError **error)
+{
+	gboolean success = FALSE;
+
+	g_return_val_if_fail (config != NULL, FALSE);
+	g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
+
+	if (NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->add_connection)
+		success = NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->add_connection (config, connection, error);
+
+	return success;
+}
diff --git a/src/system-settings/nm-system-config-interface.h b/src/system-settings/nm-system-config-interface.h
new file mode 100644
index 00000000..c5bbaaa9
--- /dev/null
+++ b/src/system-settings/nm-system-config-interface.h
@@ -0,0 +1,145 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service
+ *
+ * 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) 2007 - 2008 Red Hat, Inc.
+ * Copyright (C) 2008 Novell, Inc.
+ */
+
+#ifndef NM_SYSTEM_CONFIG_INTERFACE_H
+#define NM_SYSTEM_CONFIG_INTERFACE_H
+
+#include <glib.h>
+#include <glib-object.h>
+#include <nm-connection.h>
+#include <nm-settings-connection-interface.h>
+
+G_BEGIN_DECLS
+
+#define PLUGIN_PRINT(pname, fmt, args...) \
+	{ g_message ("   " pname ": " fmt, ##args); }
+
+#define PLUGIN_WARN(pname, fmt, args...) \
+	{ g_warning ("   " pname ": " fmt, ##args); }
+
+
+/* Plugin's factory function that returns a GObject that implements
+ * NMSystemConfigInterface.
+ */
+GObject * nm_system_config_factory (void);
+
+/* NOTE:
+ *   When passing NMConnection objects to NetworkManager, any properties
+ * of that NMConnection's NMSetting objects that are secrets must be set as
+ * GObject data items on the NMSetting object, _not_ inside the NMSetting
+ * object itself.  This is to ensure that the secrets are only given to
+ * NetworkManager itself and not exposed to clients like nm-applet that need
+ * connection details, but not secrets.
+ */
+
+#define NM_TYPE_SYSTEM_CONFIG_INTERFACE      (nm_system_config_interface_get_type ())
+#define NM_SYSTEM_CONFIG_INTERFACE(obj)      (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SYSTEM_CONFIG_INTERFACE, NMSystemConfigInterface))
+#define NM_IS_SYSTEM_CONFIG_INTERFACE(obj)   (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SYSTEM_CONFIG_INTERFACE))
+#define NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NM_TYPE_SYSTEM_CONFIG_INTERFACE, NMSystemConfigInterface))
+
+
+#define NM_SYSTEM_CONFIG_INTERFACE_NAME "name"
+#define NM_SYSTEM_CONFIG_INTERFACE_INFO "info"
+#define NM_SYSTEM_CONFIG_INTERFACE_CAPABILITIES "capabilities"
+#define NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME "hostname"
+
+#define NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED "unmanaged-specs-changed"
+#define NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED "connection-added"
+
+typedef enum {
+	NM_SYSTEM_CONFIG_INTERFACE_CAP_NONE = 0x00000000,
+	NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS = 0x00000001,
+	NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME = 0x00000002,
+
+	NM_SYSTEM_CONFIG_INTERFACE_CAP_LAST = NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME
+} NMSystemConfigInterfaceCapabilities;
+
+typedef enum {
+	NM_SYSTEM_CONFIG_INTERFACE_PROP_FIRST = 0x1000,
+
+	NM_SYSTEM_CONFIG_INTERFACE_PROP_NAME = NM_SYSTEM_CONFIG_INTERFACE_PROP_FIRST,
+	NM_SYSTEM_CONFIG_INTERFACE_PROP_INFO,
+	NM_SYSTEM_CONFIG_INTERFACE_PROP_CAPABILITIES,
+	NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME,
+} NMSystemConfigInterfaceProp;
+
+
+typedef struct _NMSystemConfigInterface NMSystemConfigInterface;
+
+struct _NMSystemConfigInterface {
+	GTypeInterface g_iface;
+
+	/* Called when the plugin is loaded to initialize it */
+	void     (*init) (NMSystemConfigInterface *config);
+
+	/* Returns a GSList of objects that implement NMSettingsConnectionInterface
+	 * that represent connections the plugin knows about.  The returned list
+	 * is freed by the system settings service.
+	 */
+	GSList * (*get_connections) (NMSystemConfigInterface *config);
+
+	/*
+	 * Return a string list of specifications of devices which NetworkManager
+	 * should not manage.  Returned list will be freed by the system settings
+	 * service, and each element must be allocated using g_malloc() or its
+	 * variants (g_strdup, g_strdup_printf, etc).
+	 *
+	 * Each string in the list must follow the format <method>:<data>, where
+	 * the method and data are one of the following:
+	 *
+	 * Method: mac    Data: device MAC address formatted with leading zeros and
+	 *                      lowercase letters, like 00:0a:0b:0c:0d:0e
+	 */
+	GSList * (*get_unmanaged_specs) (NMSystemConfigInterface *config);
+
+	/*
+	 * Add a new connection.
+	 */
+	gboolean (*add_connection) (NMSystemConfigInterface *config,
+	                            NMConnection *connection,
+	                            GError **error);
+
+	/* Signals */
+
+	/* Emitted when a new connection has been found by the plugin */
+	void (*connection_added)   (NMSystemConfigInterface *config,
+	                            NMSettingsConnectionInterface *connection);
+
+	/* Emitted when the list of unmanaged device specifications changes */
+	void (*unmanaged_specs_changed) (NMSystemConfigInterface *config);
+};
+
+GType nm_system_config_interface_get_type (void);
+
+void nm_system_config_interface_init (NMSystemConfigInterface *config,
+                                      gpointer unused);
+
+GSList *nm_system_config_interface_get_connections (NMSystemConfigInterface *config);
+
+GSList *nm_system_config_interface_get_unmanaged_specs (NMSystemConfigInterface *config);
+
+gboolean nm_system_config_interface_add_connection (NMSystemConfigInterface *config,
+                                                    NMConnection *connection,
+                                                    GError **error);
+
+G_END_DECLS
+
+#endif	/* NM_SYSTEM_CONFIG_INTERFACE_H */