diff options
author | Michael Biebl <biebl@debian.org> | 2011-04-21 10:42:53 +0200 |
---|---|---|
committer | Michael Biebl <biebl@debian.org> | 2011-04-21 10:42:53 +0200 |
commit | 8baa1aca8dfd35e3190d7d5655eb83b5b901e263 (patch) | |
tree | a9ac1e67d0c22a48330c76f08fc5291f85307055 /src/system-settings | |
parent | f75dd6fd1975146623052b843b182dc32c3fbe46 (diff) |
Imported Upstream version 0.8.4.0upstream/0.8.4.0
Diffstat (limited to 'src/system-settings')
-rw-r--r-- | src/system-settings/Makefile.am | 61 | ||||
-rw-r--r-- | src/system-settings/Makefile.in | 697 | ||||
-rw-r--r-- | src/system-settings/nm-default-wired-connection.c | 309 | ||||
-rw-r--r-- | src/system-settings/nm-default-wired-connection.h | 59 | ||||
-rw-r--r-- | src/system-settings/nm-inotify-helper.c | 212 | ||||
-rw-r--r-- | src/system-settings/nm-inotify-helper.h | 54 | ||||
-rw-r--r-- | src/system-settings/nm-polkit-helpers.h | 47 | ||||
-rw-r--r-- | src/system-settings/nm-sysconfig-connection.c | 662 | ||||
-rw-r--r-- | src/system-settings/nm-sysconfig-connection.h | 56 | ||||
-rw-r--r-- | src/system-settings/nm-sysconfig-settings.c | 1596 | ||||
-rw-r--r-- | src/system-settings/nm-sysconfig-settings.h | 73 | ||||
-rw-r--r-- | src/system-settings/nm-system-config-error.c | 59 | ||||
-rw-r--r-- | src/system-settings/nm-system-config-error.h | 45 | ||||
-rw-r--r-- | src/system-settings/nm-system-config-interface.c | 164 | ||||
-rw-r--r-- | src/system-settings/nm-system-config-interface.h | 144 |
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 */ |