summaryrefslogtreecommitdiff
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.in697
-rw-r--r--src/system-settings/nm-default-wired-connection.c309
-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.h47
-rw-r--r--src/system-settings/nm-sysconfig-connection.c662
-rw-r--r--src/system-settings/nm-sysconfig-connection.h56
-rw-r--r--src/system-settings/nm-sysconfig-settings.c1596
-rw-r--r--src/system-settings/nm-sysconfig-settings.h73
-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.c164
-rw-r--r--src/system-settings/nm-system-config-interface.h144
15 files changed, 4238 insertions, 0 deletions
diff --git a/src/system-settings/Makefile.am b/src/system-settings/Makefile.am
new file mode 100644
index 000000000..0b92228f5
--- /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
+ $(AM_V_GEN) 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 000000000..a720c9238
--- /dev/null
+++ b/src/system-settings/Makefile.in
@@ -0,0 +1,697 @@
+# 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)/m4/nls.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+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)
+AM_V_lt = $(am__v_lt_$(V))
+am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
+am__v_lt_0 = --silent
+libsystem_settings_la_LINK = $(LIBTOOL) $(AM_V_lt) --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) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_$(V))
+am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_$(V))
+am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
+am__v_CCLD_0 = @echo " CCLD " $@;
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo " GEN " $@;
+SOURCES = $(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@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_LIBS = @DBUS_LIBS@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DHCLIENT_PATH = @DHCLIENT_PATH@
+DHCLIENT_VERSION = @DHCLIENT_VERSION@
+DHCPCD_PATH = @DHCPCD_PATH@
+DISABLE_DEPRECATED = @DISABLE_DEPRECATED@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIO_CFLAGS = @GIO_CFLAGS@
+GIO_LIBS = @GIO_LIBS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GMODULE_CFLAGS = @GMODULE_CFLAGS@
+GMODULE_LIBS = @GMODULE_LIBS@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+GUDEV_CFLAGS = @GUDEV_CFLAGS@
+GUDEV_LIBS = @GUDEV_LIBS@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+IPTABLES_PATH = @IPTABLES_PATH@
+KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBDL = @LIBDL@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBM = @LIBM@
+LIBNL_CFLAGS = @LIBNL_CFLAGS@
+LIBNL_LIBS = @LIBNL_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
+NM_MICRO_VERSION = @NM_MICRO_VERSION@
+NM_MINOR_VERSION = @NM_MINOR_VERSION@
+NM_VERSION = @NM_VERSION@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_LIBS = @NSS_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKGCONFIG_PATH = @PKGCONFIG_PATH@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POFILES = @POFILES@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@
+RANLIB = @RANLIB@
+RESOLVCONF_PATH = @RESOLVCONF_PATH@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SYSTEM_CA_PATH = @SYSTEM_CA_PATH@
+UDEV_BASE_DIR = @UDEV_BASE_DIR@
+USE_NLS = @USE_NLS@
+UUID_CFLAGS = @UUID_CFLAGS@
+UUID_LIBS = @UUID_LIBS@
+VERSION = @VERSION@
+XGETTEXT = @XGETTEXT@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+systemdsystemunitdir = @systemdsystemunitdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+INCLUDES = -I${top_srcdir} \
+ -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)
+ $(AM_V_CCLD)$(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@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+libsystem_settings_la-nm-sysconfig-settings.lo: nm-sysconfig-settings.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --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_V_at)$(am__mv) $(DEPDIR)/libsystem_settings_la-nm-sysconfig-settings.Tpo $(DEPDIR)/libsystem_settings_la-nm-sysconfig-settings.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@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) $(AM_V_lt) --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@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --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_V_at)$(am__mv) $(DEPDIR)/libsystem_settings_la-nm-inotify-helper.Tpo $(DEPDIR)/libsystem_settings_la-nm-inotify-helper.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@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) $(AM_V_lt) --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@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --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_V_at)$(am__mv) $(DEPDIR)/libsystem_settings_la-nm-system-config-error.Tpo $(DEPDIR)/libsystem_settings_la-nm-system-config-error.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@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) $(AM_V_lt) --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@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --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_V_at)$(am__mv) $(DEPDIR)/libsystem_settings_la-nm-system-config-interface.Tpo $(DEPDIR)/libsystem_settings_la-nm-system-config-interface.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@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) $(AM_V_lt) --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@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --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_V_at)$(am__mv) $(DEPDIR)/libsystem_settings_la-nm-sysconfig-connection.Tpo $(DEPDIR)/libsystem_settings_la-nm-sysconfig-connection.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@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) $(AM_V_lt) --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@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --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_V_at)$(am__mv) $(DEPDIR)/libsystem_settings_la-nm-default-wired-connection.Tpo $(DEPDIR)/libsystem_settings_la-nm-default-wired-connection.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@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) $(AM_V_lt) --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
+ $(AM_V_GEN) 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 000000000..0d19dea01
--- /dev/null
+++ b/src/system-settings/nm-default-wired-connection.c
@@ -0,0 +1,309 @@
+/* -*- 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,
+ NM_SETTING_CONNECTION_TIMESTAMP, (guint64) time (NULL),
+ 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 000000000..de89b6756
--- /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 000000000..0ee168e54
--- /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 000000000..10d43ac99
--- /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 000000000..a37c2eeba
--- /dev/null
+++ b/src/system-settings/nm-polkit-helpers.h
@@ -0,0 +1,47 @@
+/* -*- 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 - 2010 Red Hat, Inc.
+ */
+
+#ifndef NM_POLKIT_HELPERS_H
+#define NM_POLKIT_HELPERS_H
+
+#include <config.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"
+
+/* Fix for polkit 0.97 and later */
+#if !HAVE_POLKIT_AUTHORITY_GET_SYNC
+static inline PolkitAuthority *
+polkit_authority_get_sync (GCancellable *cancellable, GError **error)
+{
+ PolkitAuthority *authority;
+
+ authority = polkit_authority_get ();
+ if (!authority)
+ g_set_error (error, 0, 0, "failed to get the PolicyKit authority");
+ return authority;
+}
+#endif
+
+#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 000000000..73906d20a
--- /dev/null
+++ b/src/system-settings/nm-sysconfig-connection.c
@@ -0,0 +1,662 @@
+/* -*- 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 - 2010 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);
+ GError *error = NULL;
+
+ priv->authority = polkit_authority_get_sync (NULL, NULL);
+ if (!priv->authority) {
+ nm_log_warn (LOGD_SYS_SET, "failed to create PolicyKit authority: (%d) %s",
+ error ? error->code : -1,
+ error && error->message ? error->message : "(unknown)");
+ g_clear_error (&error);
+ }
+}
+
+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 000000000..0431dc95c
--- /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 000000000..1a1fc6fd8
--- /dev/null
+++ b/src/system-settings/nm-sysconfig-settings.c
@@ -0,0 +1,1596 @@
+/* -*- 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 - 2011 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;
+}
+
+/* Returns an allocated string which the caller owns and must eventually free */
+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 NULL;
+}
+
+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 = g_strstrip (*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);
+ NMSettingConnection *s_con;
+ GKeyFile *timestamps_file;
+ const char *connection_uuid;
+ char *data;
+ gsize len;
+ GError *error = NULL;
+
+ /* Remove connection from the table */
+ g_hash_table_remove (priv->connections, connection);
+
+ /* Remove timestamp from timestamps database file */
+ s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (NM_CONNECTION (connection), NM_TYPE_SETTING_CONNECTION));
+ g_assert (s_con);
+ connection_uuid = nm_setting_connection_get_uuid (s_con);
+
+ timestamps_file = g_key_file_new ();
+ if (g_key_file_load_from_file (timestamps_file, NM_SYSCONFIG_SETTINGS_TIMESTAMPS_FILE, G_KEY_FILE_KEEP_COMMENTS, NULL)) {
+ g_key_file_remove_key (timestamps_file, "timestamps", connection_uuid, NULL);
+ data = g_key_file_to_data (timestamps_file, &len, &error);
+ if (data) {
+ g_file_set_contents (NM_SYSCONFIG_SETTINGS_TIMESTAMPS_FILE, data, len, &error);
+ g_free (data);
+ }
+ if (error) {
+ nm_log_warn (LOGD_SYS_SET, "error writing timestamps file '%s': %s", NM_SYSCONFIG_SETTINGS_TIMESTAMPS_FILE, error->message);
+ g_error_free (error);
+ }
+ }
+ g_key_file_free (timestamps_file);
+}
+
+static void
+claim_connection (NMSysconfigSettings *self,
+ NMSettingsConnectionInterface *connection,
+ gboolean do_export)
+{
+ NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+
+ NMSettingConnection *s_con;
+ const char *connection_uuid;
+ guint64 timestamp = 0;
+ GKeyFile *timestamps_file;
+ GError *err = NULL;
+ char *tmp_str;
+
+ 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;
+
+ /* Read timestamp from database file and store it into connection's object data */
+ s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (NM_CONNECTION (connection), NM_TYPE_SETTING_CONNECTION));
+ g_assert (s_con);
+ connection_uuid = nm_setting_connection_get_uuid (s_con);
+
+ timestamps_file = g_key_file_new ();
+ g_key_file_load_from_file (timestamps_file, NM_SYSCONFIG_SETTINGS_TIMESTAMPS_FILE, G_KEY_FILE_KEEP_COMMENTS, NULL);
+ tmp_str = g_key_file_get_value (timestamps_file, "timestamps", connection_uuid, &err);
+ if (tmp_str) {
+ timestamp = g_ascii_strtoull (tmp_str, NULL, 10);
+ g_free (tmp_str);
+ }
+
+ /* Update connection's timestamp */
+ if (!err) {
+ guint64 *ts_ptr = g_new (guint64, 1);
+
+ *ts_ptr = timestamp;
+ g_object_set_data_full (G_OBJECT (connection), NM_SYSCONFIG_SETTINGS_TIMESTAMP_TAG, ts_ptr, g_free);
+ } else {
+ nm_log_dbg (LOGD_SYS_SET, "failed to read connection timestamp for '%s': (%d) %s",
+ connection_uuid, err->code, err->message);
+ g_clear_error (&err);
+ }
+ g_key_file_free (timestamps_file);
+
+ 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",
+ 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;
+
+ if (strcmp(g_strstrip(*iter), "*") == 0) {
+ found = TRUE;
+ break;
+ }
+
+ 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);
+ for (iter = list; iter && *iter; iter++) {
+ struct ether_addr *candidate;
+
+ if (strcmp(g_strstrip(*iter), "*") == 0) {
+ found = TRUE;
+ break;
+ }
+
+ candidate = ether_aton (*iter);
+ if (candidate && !memcmp (mac->data, candidate->ether_addr_octet, ETH_ALEN)) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ /* 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);
+ GError *error = NULL;
+
+ priv->connections = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL);
+
+ priv->authority = polkit_authority_get_sync (NULL, &error);
+ 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: (%d) %s",
+ error ? error->code : -1,
+ error && error->message ? error->message : "(unknown)");
+ g_clear_error (&error);
+ }
+}
+
diff --git a/src/system-settings/nm-sysconfig-settings.h b/src/system-settings/nm-sysconfig-settings.h
new file mode 100644
index 000000000..8b2622a74
--- /dev/null
+++ b/src/system-settings/nm-sysconfig-settings.h
@@ -0,0 +1,73 @@
+/* -*- 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"
+#define NM_SYSCONFIG_SETTINGS_TIMESTAMPS_FILE LOCALSTATEDIR"/lib/NetworkManager/timestamps"
+#define NM_SYSCONFIG_SETTINGS_TIMESTAMP_TAG "timestamp-tag"
+
+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 000000000..13d47462f
--- /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 000000000..63896fcd0
--- /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 000000000..9fb34278d
--- /dev/null
+++ b/src/system-settings/nm-system-config-interface.c
@@ -0,0 +1,164 @@
+/* -*- 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_MODIFY_CONNECTIONS
+ | NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME),
+ 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 000000000..d5634aa6b
--- /dev/null
+++ b/src/system-settings/nm-system-config-interface.h
@@ -0,0 +1,144 @@
+/* -*- 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 - 2010 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);
+
+#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
+
+ /* When adding more capabilities, be sure to update the "Capabilities"
+ * property max value in nm-system-config-interface.c.
+ */
+} 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
+ *
+ * Method: s390-subchannels Data: string of 2 or 3 s390 subchannels
+ * separated by commas (,) that identify the
+ * device, like "0.0.09a0,0.0.09a1,0.0.09a2".
+ * The string may contain only the following
+ * characters: [a-fA-F0-9,.]
+ */
+ 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 */