diff options
| author | Michael Biebl <biebl@debian.org> | 2015-01-22 00:29:39 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2015-01-22 00:29:39 +0100 |
| commit | 2c032d8f1c6292c1338a615e6ec40252889ba85c (patch) | |
| tree | 1f77182220b2b0264288ba4a476ab47e5bc48716 /libnm | |
| parent | 33491bc4279481db8ae47213e34a6d695a0e8830 (diff) | |
Imported Upstream version 1.0.0 upstream/1.0.0
Diffstat (limited to 'libnm')
94 files changed, 31181 insertions, 0 deletions
diff --git a/libnm/Makefile.am b/libnm/Makefile.am new file mode 100644 index 00000000..e8915b42 --- /dev/null +++ b/libnm/Makefile.am @@ -0,0 +1,224 @@ +include $(GLIB_MAKEFILE) + +SUBDIRS = . tests + +AM_CPPFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_builddir)/introspection \ + -I$(top_srcdir)/libnm-core \ + -I$(top_builddir)/libnm-core \ + -I$(top_srcdir)/libnm \ + -I$(top_builddir)/libnm \ + -DG_LOG_DOMAIN=\""libnm"\" \ + -DNETWORKMANAGER_COMPILATION \ + -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ + $(GLIB_CFLAGS) \ + $(GUDEV_CFLAGS) \ + -DNMRUNDIR=\"$(nmrundir)\" + +include $(top_srcdir)/libnm-core/Makefile.libnm-core + +# libnm + +lib_LTLIBRARIES = libnm.la + +libnmincludedir = $(includedir)/libnm + +libnminclude_hfiles = \ + NetworkManager.h \ + nm-access-point.h \ + nm-active-connection.h \ + nm-client.h \ + nm-device-adsl.h \ + nm-device-bond.h \ + nm-device-bridge.h \ + nm-device-bt.h \ + nm-device-ethernet.h \ + nm-device-generic.h \ + nm-device-infiniband.h \ + nm-device-modem.h \ + nm-device-olpc-mesh.h \ + nm-device-team.h \ + nm-device-vlan.h \ + nm-device-wifi.h \ + nm-device-wimax.h \ + nm-device.h \ + nm-dhcp-config.h \ + nm-enum-types.h \ + nm-ip-config.h \ + nm-object.h \ + nm-remote-connection.h \ + nm-types.h \ + nm-vpn-connection.h \ + nm-vpn-editor-plugin.h \ + nm-wimax-nsp.h + +libnminclude_nointrospect_hfiles = \ + nm-secret-agent-old.h \ + nm-vpn-plugin-old.h + +libnminclude_HEADERS = \ + $(libnminclude_hfiles) \ + $(libnminclude_nointrospect_hfiles) + +libnm_la_private_headers = \ + nm-dbus-helpers.h \ + nm-device-private.h \ + nm-dhcp4-config.h \ + nm-dhcp6-config.h \ + nm-ip4-config.h \ + nm-ip6-config.h \ + nm-manager.h \ + nm-object-cache.h \ + nm-object-private.h \ + nm-remote-connection-private.h \ + nm-remote-settings.h + +libnm_la_csources = \ + nm-access-point.c \ + nm-active-connection.c \ + nm-client.c \ + nm-dbus-helpers.c \ + nm-device-adsl.c \ + nm-device-bond.c \ + nm-device-bridge.c \ + nm-device-bt.c \ + nm-device-ethernet.c \ + nm-device-generic.c \ + nm-device-infiniband.c \ + nm-device-modem.c \ + nm-device-olpc-mesh.c \ + nm-device-team.c \ + nm-device-vlan.c \ + nm-device-wifi.c \ + nm-device-wimax.c \ + nm-device.c \ + nm-dhcp-config.c \ + nm-dhcp4-config.c \ + nm-dhcp6-config.c \ + nm-enum-types.c \ + nm-ip-config.c \ + nm-ip4-config.c \ + nm-ip6-config.c \ + nm-manager.c \ + nm-object-cache.c \ + nm-object.c \ + nm-remote-connection.c \ + nm-remote-settings.c \ + nm-secret-agent-old.c \ + nm-vpn-connection.c \ + nm-vpn-plugin-old.c \ + nm-vpn-editor-plugin.c \ + nm-wimax-nsp.c + +libnm_la_SOURCES = \ + $(libnm_la_csources) \ + $(libnm_la_private_headers) + +GLIB_GENERATED = nm-enum-types.h nm-enum-types.c +nm_enum_types_sources = $(libnminclude_HEADERS) +GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM --fhead '\#include <nm-core-enum-types.h>\n' +GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM + +libnm_la_LIBADD = \ + $(top_builddir)/libnm-core/libnm-core.la \ + $(top_builddir)/introspection/libnmdbus.la \ + $(GLIB_LIBS) \ + $(UUID_LIBS) \ + $(GUDEV_LIBS) + +SYMBOL_VIS_FILE=$(srcdir)/libnm.ver + +libnm_la_LDFLAGS = -Wl,--version-script=$(SYMBOL_VIS_FILE) \ + -version-info "0:0:0" + +### + +BUILT_SOURCES = $(GLIB_GENERATED) + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libnm.pc + +DISTCLEANFILES = libnm.pc + +EXTRA_DIST = libnm.pc.in libnm.ver + +CLEANFILES = $(BUILT_SOURCES) + +-include $(INTROSPECTION_MAKEFILE) +INTROSPECTION_GIRS = +INTROSPECTION_COMPILER_ARGS = \ + --includedir=$(top_srcdir)/libnm-core \ + --includedir=$(top_builddir)/libnm-core \ + --includedir=$(top_srcdir)/libnm \ + --includedir=$(top_builddir)/libnm + +if HAVE_INTROSPECTION +introspection_sources = \ + $(libnm_core_headers) \ + $(libnminclude_hfiles) \ + $(libnm_core_sources) \ + $(libnm_la_csources) + +NM-1.0.gir: libnm.la +NM_1_0_gir_INCLUDES = Gio-2.0 +NM_1_0_gir_PACKAGES = gio-2.0 gudev-1.0 +NM_1_0_gir_EXPORT_PACKAGES = libnm +NM_1_0_gir_CFLAGS = $(AM_CPPFLAGS) +NM_1_0_gir_LIBS = libnm.la +NM_1_0_gir_FILES = $(introspection_sources) +NM_1_0_gir_SCANNERFLAGS = --warn-all --identifier-prefix=NM --symbol-prefix=nm +INTROSPECTION_GIRS += NM-1.0.gir + +girdir = $(datadir)/gir-1.0 +gir_DATA = $(INTROSPECTION_GIRS) + +typelibdir = $(libdir)/girepository-1.0 +typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib) + +CLEANFILES += $(gir_DATA) $(typelib_DATA) +endif + +check-local: + $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm.so $(SYMBOL_VIS_FILE) + +if BUILD_SETTING_DOCS + +noinst_DATA = \ + nm-property-docs.xml \ + nm-setting-docs-overrides.xml \ + nm-setting-docs.xml \ + nm-keyfile-docs.xml \ + nm-ifcfg-rh-docs.xml + +docs_sources = $(filter-out %/nm-core-enum-types.c,$(libnm_core_sources)) + +nm-setting-docs-overrides.xml: generate-plugin-docs.pl $(docs_sources) + $(srcdir)/generate-plugin-docs.pl dbus $(top_srcdir)/libnm-core $@ + +nm-property-docs.xml: generate-setting-docs.py $(docs_sources) | NM-1.0.gir NM-1.0.typelib libnm.la + export GI_TYPELIB_PATH=$(abs_builddir)$${GI_TYPELIB_PATH:+:$$GI_TYPELIB_PATH}; \ + export LD_LIBRARY_PATH=$(abs_builddir)/.libs$${LD_LIBRARY_PATH:+:$$LD_LIBRARY_PATH}; \ + $(srcdir)/generate-setting-docs.py \ + --gir $(builddir)/NM-1.0.gir \ + --output $@ + +nm-setting-docs.xml: generate-setting-docs.py $(docs_sources) nm-setting-docs-overrides.xml | NM-1.0.gir NM-1.0.typelib libnm.la + export GI_TYPELIB_PATH=$(abs_builddir)$${GI_TYPELIB_PATH:+:$$GI_TYPELIB_PATH}; \ + export LD_LIBRARY_PATH=$(abs_builddir)/.libs$${LD_LIBRARY_PATH:+:$$LD_LIBRARY_PATH}; \ + $(srcdir)/generate-setting-docs.py \ + --gir $(builddir)/NM-1.0.gir \ + --overrides $(builddir)/nm-setting-docs-overrides.xml \ + --output $@ + +nm-keyfile-docs.xml: generate-plugin-docs.pl $(docs_sources) + $(srcdir)/generate-plugin-docs.pl keyfile $(top_srcdir)/libnm-core $@ +nm-ifcfg-rh-docs.xml: generate-plugin-docs.pl $(docs_sources) + $(srcdir)/generate-plugin-docs.pl ifcfg-rh $(top_srcdir)/libnm-core $@ + +CLEANFILES += $(noinst_DATA) +EXTRA_DIST += $(noinst_DATA) + +endif + +EXTRA_DIST += generate-setting-docs.py generate-plugin-docs.pl diff --git a/libnm/Makefile.in b/libnm/Makefile.in new file mode 100644 index 00000000..6e1fad47 --- /dev/null +++ b/libnm/Makefile.in @@ -0,0 +1,1349 @@ +# Makefile.in generated by automake 1.13.4 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 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@ + +# In order for this to work correctly from both libnm-core/ and libnm/, +# we have to specify full pathnames. (We can't just use $(addprefix) from +# libnm/, because that's incompatible with the Makefile.introspection rules.) + + + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +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@ +DIST_COMMON = $(top_srcdir)/libnm-core/Makefile.libnm-core \ + $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(srcdir)/libnm.pc.in $(top_srcdir)/build-aux/depcomp \ + $(libnminclude_HEADERS) +@HAVE_INTROSPECTION_TRUE@am__append_1 = NM-1.0.gir +@HAVE_INTROSPECTION_TRUE@am__append_2 = $(gir_DATA) $(typelib_DATA) +@BUILD_SETTING_DOCS_TRUE@am__append_3 = $(noinst_DATA) +@BUILD_SETTING_DOCS_TRUE@am__append_4 = $(noinst_DATA) +subdir = libnm +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \ + $(top_srcdir)/m4/compiler_warnings.m4 \ + $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gnome-code-coverage.m4 \ + $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ + $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ + $(top_srcdir)/m4/introspection.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/vapigen.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 = libnm.pc +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(girdir)" \ + "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(typelibdir)" \ + "$(DESTDIR)$(libnmincludedir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +am__DEPENDENCIES_1 = +libnm_la_DEPENDENCIES = $(top_builddir)/libnm-core/libnm-core.la \ + $(top_builddir)/introspection/libnmdbus.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +am__objects_1 = nm-access-point.lo nm-active-connection.lo \ + nm-client.lo nm-dbus-helpers.lo nm-device-adsl.lo \ + nm-device-bond.lo nm-device-bridge.lo nm-device-bt.lo \ + nm-device-ethernet.lo nm-device-generic.lo \ + nm-device-infiniband.lo nm-device-modem.lo \ + nm-device-olpc-mesh.lo nm-device-team.lo nm-device-vlan.lo \ + nm-device-wifi.lo nm-device-wimax.lo nm-device.lo \ + nm-dhcp-config.lo nm-dhcp4-config.lo nm-dhcp6-config.lo \ + nm-enum-types.lo nm-ip-config.lo nm-ip4-config.lo \ + nm-ip6-config.lo nm-manager.lo nm-object-cache.lo nm-object.lo \ + nm-remote-connection.lo nm-remote-settings.lo \ + nm-secret-agent-old.lo nm-vpn-connection.lo \ + nm-vpn-plugin-old.lo nm-vpn-editor-plugin.lo nm-wimax-nsp.lo +am__objects_2 = +am_libnm_la_OBJECTS = $(am__objects_1) $(am__objects_2) +libnm_la_OBJECTS = $(am_libnm_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libnm_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libnm_la_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +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_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libnm_la_SOURCES) +DIST_SOURCES = $(libnm_la_SOURCES) +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DATA = $(gir_DATA) $(noinst_DATA) $(pkgconfig_DATA) $(typelib_DATA) +HEADERS = $(libnminclude_HEADERS) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BLUEZ5_CFLAGS = @BLUEZ5_CFLAGS@ +BLUEZ5_LIBS = @BLUEZ5_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CKDB_PATH = @CKDB_PATH@ +CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ +CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ +CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@ +DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DHCLIENT_PATH = @DHCLIENT_PATH@ +DHCPCD_PATH = @DHCPCD_PATH@ +DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@ +DLLTOOL = @DLLTOOL@ +DNSMASQ_PATH = @DNSMASQ_PATH@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GENHTML = @GENHTML@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MAKEFILE = @GLIB_MAKEFILE@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ +GNUTLS_LIBS = @GNUTLS_LIBS@ +GREP = @GREP@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +IPTABLES_PATH = @IPTABLES_PATH@ +IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@ +IWMX_SDK_LIBS = @IWMX_SDK_LIBS@ +KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDL = @LIBDL@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBNDP_CFLAGS = @LIBNDP_CFLAGS@ +LIBNDP_LIBS = @LIBNDP_LIBS@ +LIBNL_CFLAGS = @LIBNL_CFLAGS@ +LIBNL_LIBS = @LIBNL_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ +LIBSOUP_LIBS = @LIBSOUP_LIBS@ +LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@ +LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MM_GLIB_CFLAGS = @MM_GLIB_CFLAGS@ +MM_GLIB_LIBS = @MM_GLIB_LIBS@ +MOC = @MOC@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NEWT_CFLAGS = @NEWT_CFLAGS@ +NEWT_LIBS = @NEWT_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ +NM_MICRO_VERSION = @NM_MICRO_VERSION@ +NM_MINOR_VERSION = @NM_MINOR_VERSION@ +NM_MODIFY_SYSTEM_POLICY = @NM_MODIFY_SYSTEM_POLICY@ +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@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POLKIT_CFLAGS = @POLKIT_CFLAGS@ +POLKIT_LIBS = @POLKIT_LIBS@ +POSUB = @POSUB@ +PPPD_PATH = @PPPD_PATH@ +PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ +PPPOE_PATH = @PPPOE_PATH@ +QT_CFLAGS = @QT_CFLAGS@ +QT_LIBS = @QT_LIBS@ +RANLIB = @RANLIB@ +READLINE_LIBS = @READLINE_LIBS@ +SED = @SED@ +SELINUX_CFLAGS = @SELINUX_CFLAGS@ +SELINUX_LIBS = @SELINUX_LIBS@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@ +SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@ +SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@ +SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@ +SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ +SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@ +SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ +UDEV_DIR = @UDEV_DIR@ +USE_NLS = @USE_NLS@ +UUID_CFLAGS = @UUID_CFLAGS@ +UUID_LIBS = @UUID_LIBS@ +VALGRIND_RULES = @VALGRIND_RULES@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +nmbinary = @nmbinary@ +nmconfdir = @nmconfdir@ +nmdatadir = @nmdatadir@ +nmrundir = @nmrundir@ +nmstatedir = @nmstatedir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +with_dhclient = @with_dhclient@ +with_dhcpcd = @with_dhcpcd@ +with_netconfig = @with_netconfig@ +with_resolvconf = @with_resolvconf@ +with_valgrind = @with_valgrind@ +SUBDIRS = . tests +AM_CPPFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_builddir)/introspection \ + -I$(top_srcdir)/libnm-core \ + -I$(top_builddir)/libnm-core \ + -I$(top_srcdir)/libnm \ + -I$(top_builddir)/libnm \ + -DG_LOG_DOMAIN=\""libnm"\" \ + -DNETWORKMANAGER_COMPILATION \ + -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ + $(GLIB_CFLAGS) \ + $(GUDEV_CFLAGS) \ + -DNMRUNDIR=\"$(nmrundir)\" + +core = $(top_srcdir)/libnm-core +core_build = $(top_builddir)/libnm-core +libnm_core_headers = \ + $(core_build)/nm-core-enum-types.h \ + $(core_build)/nm-version.h \ + $(core)/nm-connection.h \ + $(core)/nm-core-types.h \ + $(core)/nm-dbus-interface.h \ + $(core)/nm-errors.h \ + $(core)/nm-setting-8021x.h \ + $(core)/nm-setting-adsl.h \ + $(core)/nm-setting-bluetooth.h \ + $(core)/nm-setting-bond.h \ + $(core)/nm-setting-bridge-port.h \ + $(core)/nm-setting-bridge.h \ + $(core)/nm-setting-cdma.h \ + $(core)/nm-setting-connection.h \ + $(core)/nm-setting-dcb.h \ + $(core)/nm-setting-generic.h \ + $(core)/nm-setting-gsm.h \ + $(core)/nm-setting-infiniband.h \ + $(core)/nm-setting-ip-config.h \ + $(core)/nm-setting-ip4-config.h \ + $(core)/nm-setting-ip6-config.h \ + $(core)/nm-setting-olpc-mesh.h \ + $(core)/nm-setting-ppp.h \ + $(core)/nm-setting-pppoe.h \ + $(core)/nm-setting-serial.h \ + $(core)/nm-setting-team-port.h \ + $(core)/nm-setting-team.h \ + $(core)/nm-setting-vlan.h \ + $(core)/nm-setting-vpn.h \ + $(core)/nm-setting-wimax.h \ + $(core)/nm-setting-wired.h \ + $(core)/nm-setting-wireless-security.h \ + $(core)/nm-setting-wireless.h \ + $(core)/nm-setting.h \ + $(core)/nm-simple-connection.h \ + $(core)/nm-utils.h \ + $(core)/nm-vpn-dbus-interface.h + +libnm_core_private_headers = \ + $(core)/crypto.h \ + $(core)/nm-connection-private.h \ + $(core)/nm-core-internal.h \ + $(core)/nm-property-compare.h \ + $(core)/nm-setting-private.h \ + $(core)/nm-utils-private.h + +libnm_core_sources = \ + $(core_build)/nm-core-enum-types.c \ + $(core)/crypto.c \ + $(core)/nm-connection.c \ + $(core)/nm-errors.c \ + $(core)/nm-property-compare.c \ + $(core)/nm-setting-8021x.c \ + $(core)/nm-setting-adsl.c \ + $(core)/nm-setting-bluetooth.c \ + $(core)/nm-setting-bond.c \ + $(core)/nm-setting-bridge-port.c \ + $(core)/nm-setting-bridge.c \ + $(core)/nm-setting-cdma.c \ + $(core)/nm-setting-connection.c \ + $(core)/nm-setting-dcb.c \ + $(core)/nm-setting-generic.c \ + $(core)/nm-setting-gsm.c \ + $(core)/nm-setting-infiniband.c \ + $(core)/nm-setting-ip-config.c \ + $(core)/nm-setting-ip4-config.c \ + $(core)/nm-setting-ip6-config.c \ + $(core)/nm-setting-olpc-mesh.c \ + $(core)/nm-setting-ppp.c \ + $(core)/nm-setting-pppoe.c \ + $(core)/nm-setting-serial.c \ + $(core)/nm-setting-team-port.c \ + $(core)/nm-setting-team.c \ + $(core)/nm-setting-vlan.c \ + $(core)/nm-setting-vpn.c \ + $(core)/nm-setting-wimax.c \ + $(core)/nm-setting-wired.c \ + $(core)/nm-setting-wireless-security.c \ + $(core)/nm-setting-wireless.c \ + $(core)/nm-setting.c \ + $(core)/nm-simple-connection.c \ + $(core)/nm-utils.c + + +# libnm +lib_LTLIBRARIES = libnm.la +libnmincludedir = $(includedir)/libnm +libnminclude_hfiles = \ + NetworkManager.h \ + nm-access-point.h \ + nm-active-connection.h \ + nm-client.h \ + nm-device-adsl.h \ + nm-device-bond.h \ + nm-device-bridge.h \ + nm-device-bt.h \ + nm-device-ethernet.h \ + nm-device-generic.h \ + nm-device-infiniband.h \ + nm-device-modem.h \ + nm-device-olpc-mesh.h \ + nm-device-team.h \ + nm-device-vlan.h \ + nm-device-wifi.h \ + nm-device-wimax.h \ + nm-device.h \ + nm-dhcp-config.h \ + nm-enum-types.h \ + nm-ip-config.h \ + nm-object.h \ + nm-remote-connection.h \ + nm-types.h \ + nm-vpn-connection.h \ + nm-vpn-editor-plugin.h \ + nm-wimax-nsp.h + +libnminclude_nointrospect_hfiles = \ + nm-secret-agent-old.h \ + nm-vpn-plugin-old.h + +libnminclude_HEADERS = \ + $(libnminclude_hfiles) \ + $(libnminclude_nointrospect_hfiles) + +libnm_la_private_headers = \ + nm-dbus-helpers.h \ + nm-device-private.h \ + nm-dhcp4-config.h \ + nm-dhcp6-config.h \ + nm-ip4-config.h \ + nm-ip6-config.h \ + nm-manager.h \ + nm-object-cache.h \ + nm-object-private.h \ + nm-remote-connection-private.h \ + nm-remote-settings.h + +libnm_la_csources = \ + nm-access-point.c \ + nm-active-connection.c \ + nm-client.c \ + nm-dbus-helpers.c \ + nm-device-adsl.c \ + nm-device-bond.c \ + nm-device-bridge.c \ + nm-device-bt.c \ + nm-device-ethernet.c \ + nm-device-generic.c \ + nm-device-infiniband.c \ + nm-device-modem.c \ + nm-device-olpc-mesh.c \ + nm-device-team.c \ + nm-device-vlan.c \ + nm-device-wifi.c \ + nm-device-wimax.c \ + nm-device.c \ + nm-dhcp-config.c \ + nm-dhcp4-config.c \ + nm-dhcp6-config.c \ + nm-enum-types.c \ + nm-ip-config.c \ + nm-ip4-config.c \ + nm-ip6-config.c \ + nm-manager.c \ + nm-object-cache.c \ + nm-object.c \ + nm-remote-connection.c \ + nm-remote-settings.c \ + nm-secret-agent-old.c \ + nm-vpn-connection.c \ + nm-vpn-plugin-old.c \ + nm-vpn-editor-plugin.c \ + nm-wimax-nsp.c + +libnm_la_SOURCES = \ + $(libnm_la_csources) \ + $(libnm_la_private_headers) + +GLIB_GENERATED = nm-enum-types.h nm-enum-types.c +nm_enum_types_sources = $(libnminclude_HEADERS) +GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM --fhead '\#include <nm-core-enum-types.h>\n' +GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM +libnm_la_LIBADD = \ + $(top_builddir)/libnm-core/libnm-core.la \ + $(top_builddir)/introspection/libnmdbus.la \ + $(GLIB_LIBS) \ + $(UUID_LIBS) \ + $(GUDEV_LIBS) + +SYMBOL_VIS_FILE = $(srcdir)/libnm.ver +libnm_la_LDFLAGS = -Wl,--version-script=$(SYMBOL_VIS_FILE) \ + -version-info "0:0:0" + + +### +BUILT_SOURCES = $(GLIB_GENERATED) +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libnm.pc +DISTCLEANFILES = libnm.pc +EXTRA_DIST = libnm.pc.in libnm.ver $(am__append_4) \ + generate-setting-docs.py generate-plugin-docs.pl +CLEANFILES = $(BUILT_SOURCES) $(am__append_2) $(am__append_3) +INTROSPECTION_GIRS = $(am__append_1) +INTROSPECTION_COMPILER_ARGS = \ + --includedir=$(top_srcdir)/libnm-core \ + --includedir=$(top_builddir)/libnm-core \ + --includedir=$(top_srcdir)/libnm \ + --includedir=$(top_builddir)/libnm + +@HAVE_INTROSPECTION_TRUE@introspection_sources = \ +@HAVE_INTROSPECTION_TRUE@ $(libnm_core_headers) \ +@HAVE_INTROSPECTION_TRUE@ $(libnminclude_hfiles) \ +@HAVE_INTROSPECTION_TRUE@ $(libnm_core_sources) \ +@HAVE_INTROSPECTION_TRUE@ $(libnm_la_csources) + +@HAVE_INTROSPECTION_TRUE@NM_1_0_gir_INCLUDES = Gio-2.0 +@HAVE_INTROSPECTION_TRUE@NM_1_0_gir_PACKAGES = gio-2.0 gudev-1.0 +@HAVE_INTROSPECTION_TRUE@NM_1_0_gir_EXPORT_PACKAGES = libnm +@HAVE_INTROSPECTION_TRUE@NM_1_0_gir_CFLAGS = $(AM_CPPFLAGS) +@HAVE_INTROSPECTION_TRUE@NM_1_0_gir_LIBS = libnm.la +@HAVE_INTROSPECTION_TRUE@NM_1_0_gir_FILES = $(introspection_sources) +@HAVE_INTROSPECTION_TRUE@NM_1_0_gir_SCANNERFLAGS = --warn-all --identifier-prefix=NM --symbol-prefix=nm +@HAVE_INTROSPECTION_TRUE@girdir = $(datadir)/gir-1.0 +@HAVE_INTROSPECTION_TRUE@gir_DATA = $(INTROSPECTION_GIRS) +@HAVE_INTROSPECTION_TRUE@typelibdir = $(libdir)/girepository-1.0 +@HAVE_INTROSPECTION_TRUE@typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib) +@BUILD_SETTING_DOCS_TRUE@noinst_DATA = \ +@BUILD_SETTING_DOCS_TRUE@ nm-property-docs.xml \ +@BUILD_SETTING_DOCS_TRUE@ nm-setting-docs-overrides.xml \ +@BUILD_SETTING_DOCS_TRUE@ nm-setting-docs.xml \ +@BUILD_SETTING_DOCS_TRUE@ nm-keyfile-docs.xml \ +@BUILD_SETTING_DOCS_TRUE@ nm-ifcfg-rh-docs.xml + +@BUILD_SETTING_DOCS_TRUE@docs_sources = $(filter-out %/nm-core-enum-types.c,$(libnm_core_sources)) +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/libnm-core/Makefile.libnm-core $(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 libnm/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu libnm/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_srcdir)/libnm-core/Makefile.libnm-core: + +$(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): +libnm.pc: $(top_builddir)/config.status $(srcdir)/libnm.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libnm.la: $(libnm_la_OBJECTS) $(libnm_la_DEPENDENCIES) $(EXTRA_libnm_la_DEPENDENCIES) + $(AM_V_CCLD)$(libnm_la_LINK) -rpath $(libdir) $(libnm_la_OBJECTS) $(libnm_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-access-point.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-active-connection.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-client.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-dbus-helpers.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-adsl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-bond.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-bridge.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-bt.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-ethernet.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-generic.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-infiniband.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-modem.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-olpc-mesh.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-team.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-vlan.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-wifi.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-wimax.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-dhcp-config.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-dhcp4-config.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-dhcp6-config.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-enum-types.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-ip-config.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-ip4-config.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-ip6-config.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-manager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-object-cache.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-object.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-remote-connection.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-remote-settings.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-secret-agent-old.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-vpn-connection.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-vpn-editor-plugin.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-vpn-plugin-old.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-wimax-nsp.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-girDATA: $(gir_DATA) + @$(NORMAL_INSTALL) + @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(girdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(girdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(girdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(girdir)" || exit $$?; \ + done + +uninstall-girDATA: + @$(NORMAL_UNINSTALL) + @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(girdir)'; $(am__uninstall_files_from_dir) +install-pkgconfigDATA: $(pkgconfig_DATA) + @$(NORMAL_INSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ + done + +uninstall-pkgconfigDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) +install-typelibDATA: $(typelib_DATA) + @$(NORMAL_INSTALL) + @list='$(typelib_DATA)'; test -n "$(typelibdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(typelibdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(typelibdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(typelibdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(typelibdir)" || exit $$?; \ + done + +uninstall-typelibDATA: + @$(NORMAL_UNINSTALL) + @list='$(typelib_DATA)'; test -n "$(typelibdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(typelibdir)'; $(am__uninstall_files_from_dir) +install-libnmincludeHEADERS: $(libnminclude_HEADERS) + @$(NORMAL_INSTALL) + @list='$(libnminclude_HEADERS)'; test -n "$(libnmincludedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libnmincludedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libnmincludedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libnmincludedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(libnmincludedir)" || exit $$?; \ + done + +uninstall-libnmincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libnminclude_HEADERS)'; test -n "$(libnmincludedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(libnmincludedir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + 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-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + 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" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-local +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-recursive +all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(girdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(typelibdir)" "$(DESTDIR)$(libnmincludedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +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) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) + +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-recursive + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-girDATA install-libnmincludeHEADERS \ + install-pkgconfigDATA install-typelibDATA + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-girDATA uninstall-libLTLIBRARIES \ + uninstall-libnmincludeHEADERS uninstall-pkgconfigDATA \ + uninstall-typelibDATA + +.MAKE: $(am__recursive_targets) all check check-am install install-am \ + install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am check-local clean clean-generic clean-libLTLIBRARIES \ + clean-libtool cscopelist-am ctags ctags-am 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-girDATA \ + install-html install-html-am install-info install-info-am \ + install-libLTLIBRARIES install-libnmincludeHEADERS install-man \ + install-pdf install-pdf-am install-pkgconfigDATA install-ps \ + install-ps-am install-strip install-typelibDATA installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-girDATA \ + uninstall-libLTLIBRARIES uninstall-libnmincludeHEADERS \ + uninstall-pkgconfigDATA uninstall-typelibDATA + +include $(GLIB_MAKEFILE) + +-include $(INTROSPECTION_MAKEFILE) + +@HAVE_INTROSPECTION_TRUE@NM-1.0.gir: libnm.la + +check-local: + $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm.so $(SYMBOL_VIS_FILE) + +@BUILD_SETTING_DOCS_TRUE@nm-setting-docs-overrides.xml: generate-plugin-docs.pl $(docs_sources) +@BUILD_SETTING_DOCS_TRUE@ $(srcdir)/generate-plugin-docs.pl dbus $(top_srcdir)/libnm-core $@ + +@BUILD_SETTING_DOCS_TRUE@nm-property-docs.xml: generate-setting-docs.py $(docs_sources) | NM-1.0.gir NM-1.0.typelib libnm.la +@BUILD_SETTING_DOCS_TRUE@ export GI_TYPELIB_PATH=$(abs_builddir)$${GI_TYPELIB_PATH:+:$$GI_TYPELIB_PATH}; \ +@BUILD_SETTING_DOCS_TRUE@ export LD_LIBRARY_PATH=$(abs_builddir)/.libs$${LD_LIBRARY_PATH:+:$$LD_LIBRARY_PATH}; \ +@BUILD_SETTING_DOCS_TRUE@ $(srcdir)/generate-setting-docs.py \ +@BUILD_SETTING_DOCS_TRUE@ --gir $(builddir)/NM-1.0.gir \ +@BUILD_SETTING_DOCS_TRUE@ --output $@ + +@BUILD_SETTING_DOCS_TRUE@nm-setting-docs.xml: generate-setting-docs.py $(docs_sources) nm-setting-docs-overrides.xml | NM-1.0.gir NM-1.0.typelib libnm.la +@BUILD_SETTING_DOCS_TRUE@ export GI_TYPELIB_PATH=$(abs_builddir)$${GI_TYPELIB_PATH:+:$$GI_TYPELIB_PATH}; \ +@BUILD_SETTING_DOCS_TRUE@ export LD_LIBRARY_PATH=$(abs_builddir)/.libs$${LD_LIBRARY_PATH:+:$$LD_LIBRARY_PATH}; \ +@BUILD_SETTING_DOCS_TRUE@ $(srcdir)/generate-setting-docs.py \ +@BUILD_SETTING_DOCS_TRUE@ --gir $(builddir)/NM-1.0.gir \ +@BUILD_SETTING_DOCS_TRUE@ --overrides $(builddir)/nm-setting-docs-overrides.xml \ +@BUILD_SETTING_DOCS_TRUE@ --output $@ + +@BUILD_SETTING_DOCS_TRUE@nm-keyfile-docs.xml: generate-plugin-docs.pl $(docs_sources) +@BUILD_SETTING_DOCS_TRUE@ $(srcdir)/generate-plugin-docs.pl keyfile $(top_srcdir)/libnm-core $@ +@BUILD_SETTING_DOCS_TRUE@nm-ifcfg-rh-docs.xml: generate-plugin-docs.pl $(docs_sources) +@BUILD_SETTING_DOCS_TRUE@ $(srcdir)/generate-plugin-docs.pl ifcfg-rh $(top_srcdir)/libnm-core $@ + +# 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/libnm/NetworkManager.h b/libnm/NetworkManager.h new file mode 100644 index 00000000..251a0422 --- /dev/null +++ b/libnm/NetworkManager.h @@ -0,0 +1,89 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2014 Red Hat, Inc. + */ + +#ifndef __NETWORKMANAGER_H__ +#define __NETWORKMANAGER_H__ + +#define __NETWORKMANAGER_H_INSIDE__ + +#include <nm-access-point.h> +#include <nm-active-connection.h> +#include <nm-client.h> +#include <nm-connection.h> +#include <nm-core-enum-types.h> +#include <nm-dbus-interface.h> +#include <nm-device-adsl.h> +#include <nm-device-bond.h> +#include <nm-device-bridge.h> +#include <nm-device-bt.h> +#include <nm-device-ethernet.h> +#include <nm-device-generic.h> +#include <nm-device-infiniband.h> +#include <nm-device-modem.h> +#include <nm-device-olpc-mesh.h> +#include <nm-device-team.h> +#include <nm-device-vlan.h> +#include <nm-device-wifi.h> +#include <nm-device-wimax.h> +#include <nm-device.h> +#include <nm-dhcp-config.h> +#include <nm-enum-types.h> +#include <nm-ip-config.h> +#include <nm-object.h> +#include <nm-remote-connection.h> +#include <nm-setting-8021x.h> +#include <nm-setting-adsl.h> +#include <nm-setting-bluetooth.h> +#include <nm-setting-bond.h> +#include <nm-setting-bridge-port.h> +#include <nm-setting-bridge.h> +#include <nm-setting-cdma.h> +#include <nm-setting-connection.h> +#include <nm-setting-dcb.h> +#include <nm-setting-generic.h> +#include <nm-setting-gsm.h> +#include <nm-setting-infiniband.h> +#include <nm-setting-ip-config.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-team-port.h> +#include <nm-setting-team.h> +#include <nm-setting-vlan.h> +#include <nm-setting-vpn.h> +#include <nm-setting-wimax.h> +#include <nm-setting-wired.h> +#include <nm-setting-wireless-security.h> +#include <nm-setting-wireless.h> +#include <nm-setting.h> +#include <nm-simple-connection.h> +#include <nm-utils.h> +#include <nm-version.h> +#include <nm-vpn-connection.h> +#include <nm-vpn-dbus-interface.h> +#include <nm-vpn-editor-plugin.h> +#include <nm-wimax-nsp.h> + +#undef __NETWORKMANAGER_H_INSIDE__ + +#endif /* __NETWORKMANAGER_H__ */ diff --git a/libnm/generate-plugin-docs.pl b/libnm/generate-plugin-docs.pl new file mode 100755 index 00000000..35cfdfc6 --- /dev/null +++ b/libnm/generate-plugin-docs.pl @@ -0,0 +1,198 @@ +#!/usr/bin/env perl +# vim: ft=perl ts=2 sts=2 sw=2 et ai +# -*- Mode: perl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + +# +# 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 2014 Red Hat, Inc. +# + +# +# The script parses nm-setting-*.c files and extracts documentation related +# to setting plugins. The documentation is in a simple format of lines +# "keyword: value". The documentation is enclosed between tags +# ---<plugin-name>--- and ---end--- +# Recognized keywords are: +# "property: " - property name +# "variable: " - name of the variable used by the plugin +# "format: " - format of the value in 'keyfile' plugin +# "default: " - default value when variable is not used +# "values: " - allowed values (e.g. for enumerations) +# "example: " - example(s) +# "description: " - description text +# Value is an arbitrary string that can span over multiple lines. +# +# ifcfg-rh specifics: +# - mark NM extension variables with (+), e.g. variable: UUID(+) +# + +use strict; +use warnings; +use v5.10; +#YAML:XS is based on libyaml C library and it is a good and fast YAML implementation. +#However it may not be present everywhere. So use YAML instead. +#use YAML::XS qw(Load); +use YAML qw(Load); + +# global variables +my @keywords = ("property", "variable", "format", "values", "default", "example", "description"); +my @source_files; +my @data; +my $fo; + +(scalar @ARGV == 3) or die "Usage: $0 <plugin> <srcdir> <output-xml-file>\n"; +my ($plugin, $srcdir, $output) = @ARGV; +my $start_tag = "---$plugin---\\s*\$"; +my $end_tag = '---end---'; + +# get source files to scan for documentation comments (nm-setting-<something>.c) +my $file = "$srcdir/Makefile.libnm-core"; +open my $fh, '<', $file or die "Can't open $file: $!"; +while (my $line = <$fh>) { + chomp $line; + my @strings = $line =~ /\/(nm-setting-[^.]*\.c)(?:\s|$)/g; + push @source_files, @strings +} +close $fh; + +# open output file +open $fo, '>', $output or die "Can't open $output: $!"; + +# write XML header +write_header(); + +# write generated documenation for each setting +foreach my $c_file (@source_files) { + my $path = "$srcdir/$c_file"; + my $setting_name = get_setting_name($path); + write_item("<setting name=\"$setting_name\">"); + scan_doc_comments($path, $start_tag, $end_tag); + write_item("</setting>"); +} + +# write XML footer +write_footer(); + +# close output file +close $fo; + + +### --- subroutines --- ### + +# get setting name from NM_SETTING_*_SETTING_NAME constant in C header file +sub get_setting_name { + my $path = $_[0]; + $path =~ s/c$/h/; # use header file to find out setting name + open my $fh, '<', $path or die "Can't open $path: $!"; + while (my $line = <$fh>) { + if ($line =~ /NM_SETTING_.+SETTING_NAME\s+\"(\S+)\"/) { + return $1; + } + } +} + +# scan source setting file for documentation tags and write them to XML +sub scan_doc_comments { + my($setting_file, $start, $end) = @_; + open my $fi, '<', $setting_file or die "Can't open $setting_file: $!"; + while (<$fi>) { + if (/$start/ .. /$end/) { + next if /$start/; + if (/$end/) { + process_data(); + } else { + push @data, $_; + } + next; + } + # ignore text not inside marks + } + close $fi; +} + +# process plugin property documentation comments (as a YAML document) +sub process_data { + return if not @data; + my $kwd_pat = join("|", @keywords); + my $yaml_literal_seq = "|\n"; + + foreach (@data) { + # make a proper YAML document from @data + $_ =~ s/^\s*\**\s+|\s+$//; # remove leading spaces and *, and traling spaces + # Properly indent the text so that it is a valid YAML, and insert | (for literal text) + if ($_ =~ /^($kwd_pat):\s+/) { + # add | after "keyword:" that allows using literal text (YAML won't break on special character) + # http://learnxinyminutes.com/docs/yaml/ and http://www.yaml.org/spec/1.2/spec.html#id2795688 + $_ =~ s/(^($kwd_pat):)/$1 $yaml_literal_seq/; + } else { + $_ = " " . $_; # indent the text + } + } + my $str = join ("", @data); + my $yaml_data = Load($str); + + # now write a line into the XML + my $name = $yaml_data->{property} // ""; + my $var = $yaml_data->{variable} // $name; # fallback to "property: " + my $format = $yaml_data->{format} // ""; + my $values = $yaml_data->{values} // ""; + my $def = $yaml_data->{default} // ""; + my $exam = $yaml_data->{example} // ""; + my $desc = $yaml_data->{description} // ""; + + chomp($name, $var, $format, $values, $def, $exam, $desc); + escape_xml_chars($name, $var, $format, $values, $def, $exam, $desc); + my $foo = sprintf("<property name=\"%s\" variable=\"%s\" format=\"%s\" values=\"%s\" ". + "default=\"%s\" example=\"%s\" description=\"%s\"/>", + $name, $var, $format, $values, $def, $exam, $desc); + write_item($foo); + @data = (); +} + +# - XML handling - +sub write_header { + (my $header = + qq{<?xml version=\"1.0\"?> + <!DOCTYPE nm-$plugin-docs [ + ]> + + <nm-$plugin-docs> + }) =~ s/^ {7}//mg; + print {$fo} $header; +} + +sub write_footer { + my $footer = "</nm-$plugin-docs>"; + print {$fo} $footer; +} + +sub write_item { + my $str = join("", @_); + print {$fo} $str, "\n"; +} + +sub escape_xml_chars { + # http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references#Predefined%5Fentities%5Fin%5FXML + foreach my $val (@_) { + $val =~ s/&/&/sg; + $val =~ s/</</sg; + $val =~ s/>/>/sg; + $val =~ s/"/"/sg; + $val =~ s/'/'/sg; + } +} + diff --git a/libnm/generate-setting-docs.py b/libnm/generate-setting-docs.py new file mode 100755 index 00000000..e1e35a86 --- /dev/null +++ b/libnm/generate-setting-docs.py @@ -0,0 +1,235 @@ +#!/usr/bin/env python +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA. +# +# Copyright 2009 - 2014 Red Hat, Inc. + +from __future__ import print_function + +from gi.repository import NM, GObject +import argparse, datetime, re, sys +import xml.etree.ElementTree as ET + +dbus_type_name_map = { + 'b': 'boolean', + 's': 'string', + 'i': 'int32', + 'u': 'uint32', + 't': 'uint64', + 'x': 'int64', + 'y': 'byte', + 'as': 'array of string', + 'au': 'array of uint32', + 'ay': 'byte array', + 'a{ss}': 'dict of string to string', + 'a{sv}': 'vardict', + 'aau': 'array of array of uint32', + 'aay': 'array of byte array', + 'a(ayuay)': 'array of legacy IPv6 address struct', + 'a(ayuayu)': 'array of legacy IPv6 route struct', +} + +ns_map = { + 'c': 'http://www.gtk.org/introspection/c/1.0', + 'gi': 'http://www.gtk.org/introspection/core/1.0', + 'glib': 'http://www.gtk.org/introspection/glib/1.0' +} +identifier_key = '{%s}identifier' % ns_map['c'] +nick_key = '{%s}nick' % ns_map['glib'] +symbol_prefix_key = '{%s}symbol-prefix' % ns_map['c'] + +constants = { + 'TRUE': 'TRUE', + 'FALSE': 'FALSE', + 'G_MAXUINT32': 'G_MAXUINT32', + 'NULL': 'NULL' } +setting_names = {} + +def init_constants(girxml, settings): + for const in girxml.findall('./gi:namespace/gi:constant', ns_map): + cname = const.attrib['{%s}type' % ns_map['c']] + cvalue = const.attrib['value'] + if const.find('./gi:type[@name="utf8"]', ns_map) is not None: + cvalue = '"%s"' % cvalue + constants[cname] = cvalue + + for enum in girxml.findall('./gi:namespace/gi:enumeration', ns_map): + for enumval in enum.findall('./gi:member', ns_map): + cname = enumval.attrib[identifier_key] + cvalue = '%s (%s)' % (cname, enumval.attrib['value']) + constants[cname] = cvalue + + for enum in girxml.findall('./gi:namespace/gi:bitfield', ns_map): + for enumval in enum.findall('./gi:member', ns_map): + cname = enumval.attrib[identifier_key] + cvalue = '%s (0x%x)' % (cname, int(enumval.attrib['value'])) + constants[cname] = cvalue + + for setting in settings: + setting_type_name = 'NM' + setting.attrib['name']; + setting_name_symbol = 'NM_' + setting.attrib[symbol_prefix_key].upper() + '_SETTING_NAME' + if constants.has_key(setting_name_symbol): + setting_name = constants[setting_name_symbol] + setting_names[setting_type_name] = setting_name + +def get_prop_type(setting, pspec, propxml): + dbus_type = setting.get_dbus_property_type(pspec.name).dup_string() + prop_type = dbus_type_name_map[dbus_type] + + if GObject.type_is_a(pspec.value_type, GObject.TYPE_ENUM) or GObject.type_is_a(pspec.value_type, GObject.TYPE_FLAGS): + prop_type = "%s (%s)" % (pspec.value_type.name, prop_type) + + return prop_type + +def get_docs(setting, pspec, propxml): + doc_xml = propxml.find('gi:doc', ns_map) + if doc_xml is None: + return None + + doc = doc_xml.text + if 'deprecated' in propxml.attrib: + doc = doc + ' Deprecated: ' + propxml.attrib['deprecated'] + + doc = re.sub(r'\n\s*', r' ', doc) + + # Expand constants + doc = re.sub(r'%([^%]\w*)', lambda match: constants[match.group(1)], doc) + + # #NMSettingWired:mac-address -> "mac-address" + doc = re.sub(r'#[A-Za-z0-9_]*:([A-Za-z0-9_-]*)', r'"\1"', doc) + + # #NMSettingWired setting -> "802-3-ethernet" setting + doc = re.sub(r'#([A-Z]\w*) setting', lambda match: setting_names[match.group(1)] + ' setting', doc) + + # remaining gtk-doc cleanup + doc = doc.replace('%%', '%') + doc = doc.replace('<!-- -->', '') + doc = re.sub(r' Element-.ype:.*', '', doc) + doc = re.sub(r'#([A-Z]\w*)', r'\1', doc) + + # Remove sentences that refer to functions + doc = re.sub(r'\.\s+[^.]*\w\(\)[^.]*\.', r'.', doc) + + return doc + +def get_default_value(setting, pspec, propxml): + default_value = setting.get_property(pspec.name.replace('-', '_')) + if default_value is None: + return default_value + + value_type = get_prop_type(setting, pspec, propxml) + if value_type == 'string' and default_value != '' and pspec.name != 'name': + default_value = '"%s"' % default_value + elif value_type == 'gchar' and default_value != '': + default_value = "'%s'" % default_value + elif value_type == 'boolean': + default_value = str(default_value).upper() + elif value_type == 'byte array': + default_value = '[]' + elif str(default_value).startswith('<'): + default_value = None + + return default_value + +def escape(val): + return str(val).replace('"', '"') + +def usage(): + print("Usage: %s --gir FILE --output FILE" % sys.argv[0]) + exit() + +parser = argparse.ArgumentParser() +parser.add_argument('-g', '--gir', metavar='FILE', help='NM-1.0.gir file') +parser.add_argument('-x', '--overrides', metavar='FILE', help='documentation overrides file') +parser.add_argument('-o', '--output', metavar='FILE', help='output file') + +args = parser.parse_args() +if args.gir is None or args.output is None: + usage() + +girxml = ET.parse(args.gir).getroot() +outfile = open(args.output, mode='w') + +basexml = girxml.find('./gi:namespace/gi:class[@name="Setting"]', ns_map) +settings = girxml.findall('./gi:namespace/gi:class[@parent="Setting"]', ns_map) +# Hack. Need a better way to do this +ipxml = girxml.find('./gi:namespace/gi:class[@name="SettingIPConfig"]', ns_map) +settings.extend(girxml.findall('./gi:namespace/gi:class[@parent="SettingIPConfig"]', ns_map)) +settings = sorted(settings, key=lambda setting: setting.attrib['{%s}symbol-prefix' % ns_map['c']]) + +init_constants(girxml, settings) + +if args.overrides is not None: + overrides = ET.parse(args.overrides).getroot() + +outfile.write("""<?xml version=\"1.0\"?> +<!DOCTYPE nm-setting-docs [ +<!ENTITY quot """> +]> +<nm-setting-docs> +""") + +for settingxml in settings: + if settingxml.attrib.has_key('abstract'): + continue + + new_func = NM.__getattr__(settingxml.attrib['name']) + setting = new_func() + + outfile.write(" <setting name=\"%s\">\n" % setting.props.name) + + setting_properties = { prop.name: prop for prop in GObject.list_properties(setting) } + if args.overrides is None: + setting_overrides = {} + else: + setting_overrides = { override.attrib['name']: override for override in overrides.findall('./setting[@name="%s"]/property' % setting.props.name) } + + properties = sorted(set.union(set(setting_properties.keys()), set(setting_overrides.keys()))) + + for prop in properties: + value_type = None + value_desc = None + default_value = None + + if prop in setting_properties: + pspec = setting_properties[prop] + propxml = settingxml.find('./gi:property[@name="%s"]' % pspec.name, ns_map) + if propxml is None: + propxml = basexml.find('./gi:property[@name="%s"]' % pspec.name, ns_map) + if propxml is None: + propxml = ipxml.find('./gi:property[@name="%s"]' % pspec.name, ns_map) + + value_type = get_prop_type(setting, pspec, propxml) + value_desc = get_docs(setting, pspec, propxml) + default_value = get_default_value(setting, pspec, propxml) + + if prop in setting_overrides: + override = setting_overrides[prop] + if override.attrib['format'] != '': + value_type = override.attrib['format'] + if override.attrib['description'] != '': + value_desc = override.attrib['description'] + + if default_value is not None: + outfile.write(" <property name=\"%s\" type=\"%s\" default=\"%s\" description=\"%s\" />\n" % + (prop, value_type, escape(default_value), escape(value_desc))) + else: + outfile.write(" <property name=\"%s\" type=\"%s\" description=\"%s\" />\n" % + (prop, value_type, escape(value_desc))) + + outfile.write(" </setting>\n") + +outfile.write("</nm-setting-docs>\n") +outfile.close() diff --git a/libnm/libnm.pc.in b/libnm/libnm.pc.in new file mode 100644 index 00000000..6392799a --- /dev/null +++ b/libnm/libnm.pc.in @@ -0,0 +1,13 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libnm +Description: Convenience library for clients of NetworkManager +Version: @VERSION@ +Requires: gio-2.0 dbus-glib-1 +Cflags: -I${includedir}/libnm +Libs: -L${libdir} -lnm + + diff --git a/libnm/libnm.ver b/libnm/libnm.ver new file mode 100644 index 00000000..82bcdb9f --- /dev/null +++ b/libnm/libnm.ver @@ -0,0 +1,846 @@ +libnm_1_0_0 { +global: + nm_802_11_ap_flags_get_type; + nm_802_11_ap_security_flags_get_type; + nm_802_11_mode_get_type; + nm_access_point_connection_valid; + nm_access_point_filter_connections; + nm_access_point_get_bssid; + nm_access_point_get_flags; + nm_access_point_get_frequency; + nm_access_point_get_max_bitrate; + nm_access_point_get_mode; + nm_access_point_get_rsn_flags; + nm_access_point_get_ssid; + nm_access_point_get_strength; + nm_access_point_get_type; + nm_access_point_get_wpa_flags; + nm_active_connection_get_connection; + nm_active_connection_get_connection_type; + nm_active_connection_get_default6; + nm_active_connection_get_default; + nm_active_connection_get_devices; + nm_active_connection_get_dhcp4_config; + nm_active_connection_get_dhcp6_config; + nm_active_connection_get_id; + nm_active_connection_get_ip4_config; + nm_active_connection_get_ip6_config; + nm_active_connection_get_master; + nm_active_connection_get_specific_object_path; + nm_active_connection_get_state; + nm_active_connection_get_type; + nm_active_connection_get_uuid; + nm_active_connection_get_vpn; + nm_active_connection_state_get_type; + nm_agent_manager_error_get_type; + nm_agent_manager_error_quark; + nm_bluetooth_capabilities_get_type; + nm_client_activate_connection_async; + nm_client_activate_connection_finish; + nm_client_add_and_activate_connection_async; + nm_client_add_and_activate_connection_finish; + nm_client_add_connection_async; + nm_client_add_connection_finish; + nm_client_check_connectivity; + nm_client_check_connectivity_async; + nm_client_check_connectivity_finish; + nm_client_deactivate_connection; + nm_client_deactivate_connection_async; + nm_client_deactivate_connection_finish; + nm_client_error_get_type; + nm_client_error_quark; + nm_client_get_activating_connection; + nm_client_get_active_connections; + nm_client_get_connection_by_id; + nm_client_get_connection_by_path; + nm_client_get_connection_by_uuid; + nm_client_get_connections; + nm_client_get_connectivity; + nm_client_get_device_by_iface; + nm_client_get_device_by_path; + nm_client_get_devices; + nm_client_get_logging; + nm_client_get_nm_running; + nm_client_get_permission_result; + nm_client_get_primary_connection; + nm_client_get_startup; + nm_client_get_state; + nm_client_get_type; + nm_client_get_version; + nm_client_load_connections; + nm_client_load_connections_async; + nm_client_load_connections_finish; + nm_client_networking_get_enabled; + nm_client_networking_set_enabled; + nm_client_new; + nm_client_new_async; + nm_client_new_finish; + nm_client_permission_get_type; + nm_client_permission_result_get_type; + nm_client_reload_connections; + nm_client_reload_connections_async; + nm_client_reload_connections_finish; + nm_client_save_hostname; + nm_client_save_hostname_async; + nm_client_save_hostname_finish; + nm_client_set_logging; + nm_client_wimax_get_enabled; + nm_client_wimax_hardware_get_enabled; + nm_client_wimax_set_enabled; + nm_client_wireless_get_enabled; + nm_client_wireless_hardware_get_enabled; + nm_client_wireless_set_enabled; + nm_client_wwan_get_enabled; + nm_client_wwan_hardware_get_enabled; + nm_client_wwan_set_enabled; + nm_connection_add_setting; + nm_connection_clear_secrets; + nm_connection_clear_secrets_with_flags; + nm_connection_clear_settings; + nm_connection_compare; + nm_connection_diff; + nm_connection_dump; + nm_connection_error_get_type; + nm_connection_error_quark; + nm_connection_for_each_setting_value; + nm_connection_get_connection_type; + nm_connection_get_id; + nm_connection_get_interface_name; + nm_connection_get_path; + nm_connection_get_setting; + nm_connection_get_setting_802_1x; + nm_connection_get_setting_adsl; + nm_connection_get_setting_bluetooth; + nm_connection_get_setting_bond; + nm_connection_get_setting_bridge; + nm_connection_get_setting_bridge_port; + nm_connection_get_setting_by_name; + nm_connection_get_setting_cdma; + nm_connection_get_setting_connection; + nm_connection_get_setting_dcb; + nm_connection_get_setting_generic; + nm_connection_get_setting_gsm; + nm_connection_get_setting_infiniband; + nm_connection_get_setting_ip4_config; + nm_connection_get_setting_ip6_config; + nm_connection_get_setting_olpc_mesh; + nm_connection_get_setting_ppp; + nm_connection_get_setting_pppoe; + nm_connection_get_setting_serial; + nm_connection_get_setting_team; + nm_connection_get_setting_team_port; + nm_connection_get_setting_vlan; + nm_connection_get_setting_vpn; + nm_connection_get_setting_wimax; + nm_connection_get_setting_wired; + nm_connection_get_setting_wireless; + nm_connection_get_setting_wireless_security; + nm_connection_get_type; + nm_connection_get_uuid; + nm_connection_get_virtual_device_description; + nm_connection_is_type; + nm_connection_is_virtual; + nm_connection_need_secrets; + nm_connection_normalize; + nm_connection_remove_setting; + nm_connection_replace_settings; + nm_connection_replace_settings_from_connection; + nm_connection_serialization_flags_get_type; + nm_connection_set_path; + nm_connection_to_dbus; + nm_connection_update_secrets; + nm_connection_verify; + nm_connectivity_state_get_type; + nm_crypto_error_get_type; + nm_crypto_error_quark; + nm_device_adsl_get_carrier; + nm_device_adsl_get_type; + nm_device_bond_get_carrier; + nm_device_bond_get_hw_address; + nm_device_bond_get_slaves; + nm_device_bond_get_type; + nm_device_bridge_get_carrier; + nm_device_bridge_get_hw_address; + nm_device_bridge_get_slaves; + nm_device_bridge_get_type; + nm_device_bt_get_capabilities; + nm_device_bt_get_hw_address; + nm_device_bt_get_name; + nm_device_bt_get_type; + nm_device_capabilities_get_type; + nm_device_connection_compatible; + nm_device_connection_valid; + nm_device_delete; + nm_device_delete_async; + nm_device_delete_finish; + nm_device_disambiguate_names; + nm_device_disconnect; + nm_device_disconnect_async; + nm_device_disconnect_finish; + nm_device_error_get_type; + nm_device_error_quark; + nm_device_ethernet_get_carrier; + nm_device_ethernet_get_hw_address; + nm_device_ethernet_get_permanent_hw_address; + nm_device_ethernet_get_speed; + nm_device_ethernet_get_type; + nm_device_filter_connections; + nm_device_generic_get_hw_address; + nm_device_generic_get_type; + nm_device_get_active_connection; + nm_device_get_autoconnect; + nm_device_get_available_connections; + nm_device_get_capabilities; + nm_device_get_description; + nm_device_get_device_type; + nm_device_get_dhcp4_config; + nm_device_get_dhcp6_config; + nm_device_get_driver; + nm_device_get_driver_version; + nm_device_get_firmware_missing; + nm_device_get_firmware_version; + nm_device_get_hw_address; + nm_device_get_iface; + nm_device_get_ip4_config; + nm_device_get_ip6_config; + nm_device_get_ip_iface; + nm_device_get_managed; + nm_device_get_mtu; + nm_device_get_physical_port_id; + nm_device_get_product; + nm_device_get_setting_type; + nm_device_get_state; + nm_device_get_state_reason; + nm_device_get_type; + nm_device_get_type_description; + nm_device_get_udi; + nm_device_get_vendor; + nm_device_infiniband_get_carrier; + nm_device_infiniband_get_hw_address; + nm_device_infiniband_get_type; + nm_device_is_software; + nm_device_modem_capabilities_get_type; + nm_device_modem_get_current_capabilities; + nm_device_modem_get_modem_capabilities; + nm_device_modem_get_type; + nm_device_olpc_mesh_get_active_channel; + nm_device_olpc_mesh_get_companion; + nm_device_olpc_mesh_get_hw_address; + nm_device_olpc_mesh_get_type; + nm_device_set_autoconnect; + nm_device_state_get_type; + nm_device_state_reason_get_type; + nm_device_team_get_carrier; + nm_device_team_get_hw_address; + nm_device_team_get_slaves; + nm_device_team_get_type; + nm_device_type_get_type; + nm_device_vlan_get_carrier; + nm_device_vlan_get_hw_address; + nm_device_vlan_get_parent; + nm_device_vlan_get_type; + nm_device_vlan_get_vlan_id; + nm_device_wifi_capabilities_get_type; + nm_device_wifi_get_access_point_by_path; + nm_device_wifi_get_access_points; + nm_device_wifi_get_active_access_point; + nm_device_wifi_get_bitrate; + nm_device_wifi_get_capabilities; + nm_device_wifi_get_hw_address; + nm_device_wifi_get_mode; + nm_device_wifi_get_permanent_hw_address; + nm_device_wifi_get_type; + nm_device_wifi_request_scan; + nm_device_wifi_request_scan_async; + nm_device_wifi_request_scan_finish; + nm_device_wimax_get_active_nsp; + nm_device_wimax_get_bsid; + nm_device_wimax_get_center_frequency; + nm_device_wimax_get_cinr; + nm_device_wimax_get_hw_address; + nm_device_wimax_get_nsp_by_path; + nm_device_wimax_get_nsps; + nm_device_wimax_get_rssi; + nm_device_wimax_get_tx_power; + nm_device_wimax_get_type; + nm_dhcp_config_get_family; + nm_dhcp_config_get_one_option; + nm_dhcp_config_get_options; + nm_dhcp_config_get_type; + nm_ip_address_equal; + nm_ip_address_get_address; + nm_ip_address_get_address_binary; + nm_ip_address_get_attribute; + nm_ip_address_get_attribute_names; + nm_ip_address_get_family; + nm_ip_address_get_prefix; + nm_ip_address_get_type; + nm_ip_address_new; + nm_ip_address_new_binary; + nm_ip_address_ref; + nm_ip_address_set_address; + nm_ip_address_set_address_binary; + nm_ip_address_set_attribute; + nm_ip_address_set_prefix; + nm_ip_address_unref; + nm_ip_config_get_addresses; + nm_ip_config_get_domains; + nm_ip_config_get_family; + nm_ip_config_get_gateway; + nm_ip_config_get_nameservers; + nm_ip_config_get_routes; + nm_ip_config_get_searches; + nm_ip_config_get_type; + nm_ip_config_get_wins_servers; + nm_ip_route_equal; + nm_ip_route_get_attribute; + nm_ip_route_get_attribute_names; + nm_ip_route_get_dest; + nm_ip_route_get_dest_binary; + nm_ip_route_get_family; + nm_ip_route_get_metric; + nm_ip_route_get_next_hop; + nm_ip_route_get_next_hop_binary; + nm_ip_route_get_prefix; + nm_ip_route_get_type; + nm_ip_route_new; + nm_ip_route_new_binary; + nm_ip_route_ref; + nm_ip_route_set_attribute; + nm_ip_route_set_dest; + nm_ip_route_set_dest_binary; + nm_ip_route_set_metric; + nm_ip_route_set_next_hop; + nm_ip_route_set_next_hop_binary; + nm_ip_route_set_prefix; + nm_ip_route_unref; + nm_manager_error_get_type; + nm_manager_error_quark; + nm_object_get_path; + nm_object_get_type; + nm_remote_connection_commit_changes; + nm_remote_connection_commit_changes_async; + nm_remote_connection_commit_changes_finish; + nm_remote_connection_delete; + nm_remote_connection_delete_async; + nm_remote_connection_delete_finish; + nm_remote_connection_get_secrets; + nm_remote_connection_get_secrets_async; + nm_remote_connection_get_secrets_finish; + nm_remote_connection_get_type; + nm_remote_connection_get_unsaved; + nm_remote_connection_get_visible; + nm_remote_connection_save; + nm_remote_connection_save_async; + nm_remote_connection_save_finish; + nm_secret_agent_capabilities_get_type; + nm_secret_agent_error_get_type; + nm_secret_agent_error_quark; + nm_secret_agent_get_secrets_flags_get_type; + nm_secret_agent_old_delete_secrets; + nm_secret_agent_old_get_registered; + nm_secret_agent_old_get_secrets; + nm_secret_agent_old_get_type; + nm_secret_agent_old_register; + nm_secret_agent_old_register_async; + nm_secret_agent_old_register_finish; + nm_secret_agent_old_save_secrets; + nm_secret_agent_old_unregister; + nm_secret_agent_old_unregister_async; + nm_secret_agent_old_unregister_finish; + nm_setting_802_1x_add_altsubject_match; + nm_setting_802_1x_add_eap_method; + nm_setting_802_1x_add_phase2_altsubject_match; + nm_setting_802_1x_ck_format_get_type; + nm_setting_802_1x_ck_scheme_get_type; + nm_setting_802_1x_clear_altsubject_matches; + nm_setting_802_1x_clear_eap_methods; + nm_setting_802_1x_clear_phase2_altsubject_matches; + nm_setting_802_1x_get_altsubject_match; + nm_setting_802_1x_get_anonymous_identity; + nm_setting_802_1x_get_ca_cert_blob; + nm_setting_802_1x_get_ca_cert_path; + nm_setting_802_1x_get_ca_cert_scheme; + nm_setting_802_1x_get_ca_path; + nm_setting_802_1x_get_client_cert_blob; + nm_setting_802_1x_get_client_cert_path; + nm_setting_802_1x_get_client_cert_scheme; + nm_setting_802_1x_get_eap_method; + nm_setting_802_1x_get_identity; + nm_setting_802_1x_get_num_altsubject_matches; + nm_setting_802_1x_get_num_eap_methods; + nm_setting_802_1x_get_num_phase2_altsubject_matches; + nm_setting_802_1x_get_pac_file; + nm_setting_802_1x_get_password; + nm_setting_802_1x_get_password_flags; + nm_setting_802_1x_get_password_raw; + nm_setting_802_1x_get_password_raw_flags; + nm_setting_802_1x_get_phase1_fast_provisioning; + nm_setting_802_1x_get_phase1_peaplabel; + nm_setting_802_1x_get_phase1_peapver; + nm_setting_802_1x_get_phase2_altsubject_match; + nm_setting_802_1x_get_phase2_auth; + nm_setting_802_1x_get_phase2_autheap; + nm_setting_802_1x_get_phase2_ca_cert_blob; + nm_setting_802_1x_get_phase2_ca_cert_path; + nm_setting_802_1x_get_phase2_ca_cert_scheme; + nm_setting_802_1x_get_phase2_ca_path; + nm_setting_802_1x_get_phase2_client_cert_blob; + nm_setting_802_1x_get_phase2_client_cert_path; + nm_setting_802_1x_get_phase2_client_cert_scheme; + nm_setting_802_1x_get_phase2_private_key_blob; + nm_setting_802_1x_get_phase2_private_key_format; + nm_setting_802_1x_get_phase2_private_key_password; + nm_setting_802_1x_get_phase2_private_key_password_flags; + nm_setting_802_1x_get_phase2_private_key_path; + nm_setting_802_1x_get_phase2_private_key_scheme; + nm_setting_802_1x_get_phase2_subject_match; + nm_setting_802_1x_get_pin; + nm_setting_802_1x_get_pin_flags; + nm_setting_802_1x_get_private_key_blob; + nm_setting_802_1x_get_private_key_format; + nm_setting_802_1x_get_private_key_password; + nm_setting_802_1x_get_private_key_password_flags; + nm_setting_802_1x_get_private_key_path; + nm_setting_802_1x_get_private_key_scheme; + nm_setting_802_1x_get_subject_match; + nm_setting_802_1x_get_system_ca_certs; + nm_setting_802_1x_get_type; + nm_setting_802_1x_new; + nm_setting_802_1x_remove_altsubject_match; + nm_setting_802_1x_remove_altsubject_match_by_value; + nm_setting_802_1x_remove_eap_method; + nm_setting_802_1x_remove_eap_method_by_value; + nm_setting_802_1x_remove_phase2_altsubject_match; + nm_setting_802_1x_remove_phase2_altsubject_match_by_value; + nm_setting_802_1x_set_ca_cert; + nm_setting_802_1x_set_client_cert; + nm_setting_802_1x_set_phase2_ca_cert; + nm_setting_802_1x_set_phase2_client_cert; + nm_setting_802_1x_set_phase2_private_key; + nm_setting_802_1x_set_private_key; + nm_setting_adsl_get_encapsulation; + nm_setting_adsl_get_password; + nm_setting_adsl_get_password_flags; + nm_setting_adsl_get_protocol; + nm_setting_adsl_get_type; + nm_setting_adsl_get_username; + nm_setting_adsl_get_vci; + nm_setting_adsl_get_vpi; + nm_setting_adsl_new; + nm_setting_bluetooth_get_bdaddr; + nm_setting_bluetooth_get_connection_type; + nm_setting_bluetooth_get_type; + nm_setting_bluetooth_new; + nm_setting_bond_add_option; + nm_setting_bond_get_num_options; + nm_setting_bond_get_option; + nm_setting_bond_get_option_by_name; + nm_setting_bond_get_option_default; + nm_setting_bond_get_type; + nm_setting_bond_get_valid_options; + nm_setting_bond_new; + nm_setting_bond_remove_option; + nm_setting_bond_validate_option; + nm_setting_bridge_get_ageing_time; + nm_setting_bridge_get_forward_delay; + nm_setting_bridge_get_hello_time; + nm_setting_bridge_get_mac_address; + nm_setting_bridge_get_max_age; + nm_setting_bridge_get_priority; + nm_setting_bridge_get_stp; + nm_setting_bridge_get_type; + nm_setting_bridge_new; + nm_setting_bridge_port_get_hairpin_mode; + nm_setting_bridge_port_get_path_cost; + nm_setting_bridge_port_get_priority; + nm_setting_bridge_port_get_type; + nm_setting_bridge_port_new; + nm_setting_cdma_get_number; + nm_setting_cdma_get_password; + nm_setting_cdma_get_password_flags; + nm_setting_cdma_get_type; + nm_setting_cdma_get_username; + nm_setting_cdma_new; + nm_setting_compare; + nm_setting_compare_flags_get_type; + nm_setting_connection_add_permission; + nm_setting_connection_add_secondary; + nm_setting_connection_get_autoconnect; + nm_setting_connection_get_autoconnect_priority; + nm_setting_connection_get_connection_type; + nm_setting_connection_get_gateway_ping_timeout; + nm_setting_connection_get_id; + nm_setting_connection_get_interface_name; + nm_setting_connection_get_master; + nm_setting_connection_get_num_permissions; + nm_setting_connection_get_num_secondaries; + nm_setting_connection_get_permission; + nm_setting_connection_get_read_only; + nm_setting_connection_get_secondary; + nm_setting_connection_get_slave_type; + nm_setting_connection_get_timestamp; + nm_setting_connection_get_type; + nm_setting_connection_get_uuid; + nm_setting_connection_get_zone; + nm_setting_connection_is_slave_type; + nm_setting_connection_new; + nm_setting_connection_permissions_user_allowed; + nm_setting_connection_remove_permission; + nm_setting_connection_remove_permission_by_value; + nm_setting_connection_remove_secondary; + nm_setting_connection_remove_secondary_by_value; + nm_setting_dcb_flags_get_type; + nm_setting_dcb_get_app_fcoe_flags; + nm_setting_dcb_get_app_fcoe_mode; + nm_setting_dcb_get_app_fcoe_priority; + nm_setting_dcb_get_app_fip_flags; + nm_setting_dcb_get_app_fip_priority; + nm_setting_dcb_get_app_iscsi_flags; + nm_setting_dcb_get_app_iscsi_priority; + nm_setting_dcb_get_priority_bandwidth; + nm_setting_dcb_get_priority_flow_control; + nm_setting_dcb_get_priority_flow_control_flags; + nm_setting_dcb_get_priority_group_bandwidth; + nm_setting_dcb_get_priority_group_flags; + nm_setting_dcb_get_priority_group_id; + nm_setting_dcb_get_priority_strict_bandwidth; + nm_setting_dcb_get_priority_traffic_class; + nm_setting_dcb_get_type; + nm_setting_dcb_new; + nm_setting_dcb_set_priority_bandwidth; + nm_setting_dcb_set_priority_flow_control; + nm_setting_dcb_set_priority_group_bandwidth; + nm_setting_dcb_set_priority_group_id; + nm_setting_dcb_set_priority_strict_bandwidth; + nm_setting_dcb_set_priority_traffic_class; + nm_setting_diff; + nm_setting_diff_result_get_type; + nm_setting_duplicate; + nm_setting_enumerate_values; + nm_setting_generic_get_type; + nm_setting_generic_new; + nm_setting_get_dbus_property_type; + nm_setting_get_name; + nm_setting_get_secret_flags; + nm_setting_get_type; + nm_setting_gsm_get_apn; + nm_setting_gsm_get_home_only; + nm_setting_gsm_get_network_id; + nm_setting_gsm_get_number; + nm_setting_gsm_get_password; + nm_setting_gsm_get_password_flags; + nm_setting_gsm_get_pin; + nm_setting_gsm_get_pin_flags; + nm_setting_gsm_get_type; + nm_setting_gsm_get_username; + nm_setting_gsm_new; + nm_setting_infiniband_get_mac_address; + nm_setting_infiniband_get_mtu; + nm_setting_infiniband_get_p_key; + nm_setting_infiniband_get_parent; + nm_setting_infiniband_get_transport_mode; + nm_setting_infiniband_get_type; + nm_setting_infiniband_get_virtual_interface_name; + nm_setting_infiniband_new; + nm_setting_ip4_config_get_dhcp_client_id; + nm_setting_ip4_config_get_type; + nm_setting_ip4_config_new; + nm_setting_ip6_config_get_ip6_privacy; + nm_setting_ip6_config_get_type; + nm_setting_ip6_config_new; + nm_setting_ip6_config_privacy_get_type; + nm_setting_ip_config_add_address; + nm_setting_ip_config_add_dns; + nm_setting_ip_config_add_dns_search; + nm_setting_ip_config_add_route; + nm_setting_ip_config_clear_addresses; + nm_setting_ip_config_clear_dns; + nm_setting_ip_config_clear_dns_searches; + nm_setting_ip_config_clear_routes; + nm_setting_ip_config_get_address; + nm_setting_ip_config_get_dhcp_hostname; + nm_setting_ip_config_get_dhcp_send_hostname; + nm_setting_ip_config_get_dns; + nm_setting_ip_config_get_dns_search; + nm_setting_ip_config_get_gateway; + nm_setting_ip_config_get_ignore_auto_dns; + nm_setting_ip_config_get_ignore_auto_routes; + nm_setting_ip_config_get_may_fail; + nm_setting_ip_config_get_method; + nm_setting_ip_config_get_never_default; + nm_setting_ip_config_get_num_addresses; + nm_setting_ip_config_get_num_dns; + nm_setting_ip_config_get_num_dns_searches; + nm_setting_ip_config_get_num_routes; + nm_setting_ip_config_get_route; + nm_setting_ip_config_get_route_metric; + nm_setting_ip_config_get_type; + nm_setting_ip_config_remove_address; + nm_setting_ip_config_remove_address_by_value; + nm_setting_ip_config_remove_dns; + nm_setting_ip_config_remove_dns_by_value; + nm_setting_ip_config_remove_dns_search; + nm_setting_ip_config_remove_dns_search_by_value; + nm_setting_ip_config_remove_route; + nm_setting_ip_config_remove_route_by_value; + nm_setting_lookup_type; + nm_setting_olpc_mesh_get_channel; + nm_setting_olpc_mesh_get_dhcp_anycast_address; + nm_setting_olpc_mesh_get_ssid; + nm_setting_olpc_mesh_get_type; + nm_setting_olpc_mesh_new; + nm_setting_ppp_get_baud; + nm_setting_ppp_get_crtscts; + nm_setting_ppp_get_lcp_echo_failure; + nm_setting_ppp_get_lcp_echo_interval; + nm_setting_ppp_get_mppe_stateful; + nm_setting_ppp_get_mru; + nm_setting_ppp_get_mtu; + nm_setting_ppp_get_no_vj_comp; + nm_setting_ppp_get_noauth; + nm_setting_ppp_get_nobsdcomp; + nm_setting_ppp_get_nodeflate; + nm_setting_ppp_get_refuse_chap; + nm_setting_ppp_get_refuse_eap; + nm_setting_ppp_get_refuse_mschap; + nm_setting_ppp_get_refuse_mschapv2; + nm_setting_ppp_get_refuse_pap; + nm_setting_ppp_get_require_mppe; + nm_setting_ppp_get_require_mppe_128; + nm_setting_ppp_get_type; + nm_setting_ppp_new; + nm_setting_pppoe_get_password; + nm_setting_pppoe_get_password_flags; + nm_setting_pppoe_get_service; + nm_setting_pppoe_get_type; + nm_setting_pppoe_get_username; + nm_setting_pppoe_new; + nm_setting_secret_flags_get_type; + nm_setting_serial_get_baud; + nm_setting_serial_get_bits; + nm_setting_serial_get_parity; + nm_setting_serial_get_send_delay; + nm_setting_serial_get_stopbits; + nm_setting_serial_get_type; + nm_setting_serial_new; + nm_setting_serial_parity_get_type; + nm_setting_set_secret_flags; + nm_setting_team_get_config; + nm_setting_team_get_type; + nm_setting_team_new; + nm_setting_team_port_get_config; + nm_setting_team_port_get_type; + nm_setting_team_port_new; + nm_setting_to_string; + nm_setting_verify; + nm_setting_vlan_add_priority; + nm_setting_vlan_add_priority_str; + nm_setting_vlan_clear_priorities; + nm_setting_vlan_get_flags; + nm_setting_vlan_get_id; + nm_setting_vlan_get_num_priorities; + nm_setting_vlan_get_parent; + nm_setting_vlan_get_priority; + nm_setting_vlan_get_type; + nm_setting_vlan_new; + nm_setting_vlan_remove_priority; + nm_setting_vlan_remove_priority_by_value; + nm_setting_vlan_remove_priority_str_by_value; + nm_setting_vpn_add_data_item; + nm_setting_vpn_add_secret; + nm_setting_vpn_foreach_data_item; + nm_setting_vpn_foreach_secret; + nm_setting_vpn_get_data_item; + nm_setting_vpn_get_num_data_items; + nm_setting_vpn_get_num_secrets; + nm_setting_vpn_get_secret; + nm_setting_vpn_get_service_type; + nm_setting_vpn_get_type; + nm_setting_vpn_get_user_name; + nm_setting_vpn_new; + nm_setting_vpn_remove_data_item; + nm_setting_vpn_remove_secret; + nm_setting_wimax_get_mac_address; + nm_setting_wimax_get_network_name; + nm_setting_wimax_get_type; + nm_setting_wimax_new; + nm_setting_wired_add_mac_blacklist_item; + nm_setting_wired_add_s390_option; + nm_setting_wired_clear_mac_blacklist_items; + nm_setting_wired_get_auto_negotiate; + nm_setting_wired_get_cloned_mac_address; + nm_setting_wired_get_duplex; + nm_setting_wired_get_mac_address; + nm_setting_wired_get_mac_address_blacklist; + nm_setting_wired_get_mac_blacklist_item; + nm_setting_wired_get_mtu; + nm_setting_wired_get_num_mac_blacklist_items; + nm_setting_wired_get_num_s390_options; + nm_setting_wired_get_port; + nm_setting_wired_get_s390_nettype; + nm_setting_wired_get_s390_option; + nm_setting_wired_get_s390_option_by_key; + nm_setting_wired_get_s390_subchannels; + nm_setting_wired_get_speed; + nm_setting_wired_get_type; + nm_setting_wired_get_valid_s390_options; + nm_setting_wired_new; + nm_setting_wired_remove_mac_blacklist_item; + nm_setting_wired_remove_mac_blacklist_item_by_value; + nm_setting_wired_remove_s390_option; + nm_setting_wireless_add_mac_blacklist_item; + nm_setting_wireless_add_seen_bssid; + nm_setting_wireless_ap_security_compatible; + nm_setting_wireless_clear_mac_blacklist_items; + nm_setting_wireless_get_band; + nm_setting_wireless_get_bssid; + nm_setting_wireless_get_channel; + nm_setting_wireless_get_cloned_mac_address; + nm_setting_wireless_get_hidden; + nm_setting_wireless_get_mac_address; + nm_setting_wireless_get_mac_address_blacklist; + nm_setting_wireless_get_mac_blacklist_item; + nm_setting_wireless_get_mode; + nm_setting_wireless_get_mtu; + nm_setting_wireless_get_num_mac_blacklist_items; + nm_setting_wireless_get_num_seen_bssids; + nm_setting_wireless_get_rate; + nm_setting_wireless_get_seen_bssid; + nm_setting_wireless_get_ssid; + nm_setting_wireless_get_tx_power; + nm_setting_wireless_get_type; + nm_setting_wireless_new; + nm_setting_wireless_remove_mac_blacklist_item; + nm_setting_wireless_remove_mac_blacklist_item_by_value; + nm_setting_wireless_security_add_group; + nm_setting_wireless_security_add_pairwise; + nm_setting_wireless_security_add_proto; + nm_setting_wireless_security_clear_groups; + nm_setting_wireless_security_clear_pairwise; + nm_setting_wireless_security_clear_protos; + nm_setting_wireless_security_get_auth_alg; + nm_setting_wireless_security_get_group; + nm_setting_wireless_security_get_key_mgmt; + nm_setting_wireless_security_get_leap_password; + nm_setting_wireless_security_get_leap_password_flags; + nm_setting_wireless_security_get_leap_username; + nm_setting_wireless_security_get_num_groups; + nm_setting_wireless_security_get_num_pairwise; + nm_setting_wireless_security_get_num_protos; + nm_setting_wireless_security_get_pairwise; + nm_setting_wireless_security_get_proto; + nm_setting_wireless_security_get_psk; + nm_setting_wireless_security_get_psk_flags; + nm_setting_wireless_security_get_type; + nm_setting_wireless_security_get_wep_key; + nm_setting_wireless_security_get_wep_key_flags; + nm_setting_wireless_security_get_wep_key_type; + nm_setting_wireless_security_get_wep_tx_keyidx; + nm_setting_wireless_security_new; + nm_setting_wireless_security_remove_group; + nm_setting_wireless_security_remove_group_by_value; + nm_setting_wireless_security_remove_pairwise; + nm_setting_wireless_security_remove_pairwise_by_value; + nm_setting_wireless_security_remove_proto; + nm_setting_wireless_security_remove_proto_by_value; + nm_setting_wireless_security_set_wep_key; + nm_settings_error_get_type; + nm_settings_error_quark; + nm_simple_connection_get_type; + nm_simple_connection_new; + nm_simple_connection_new_clone; + nm_simple_connection_new_from_dbus; + nm_state_get_type; + nm_utils_ap_mode_security_valid; + nm_utils_bin2hexstr; + nm_utils_check_virtual_device_compatibility; + nm_utils_escape_ssid; + nm_utils_file_is_certificate; + nm_utils_file_is_pkcs12; + nm_utils_file_is_private_key; + nm_utils_file_search_in_paths; + nm_utils_hexstr2bin; + nm_utils_hwaddr_atoba; + nm_utils_hwaddr_aton; + nm_utils_hwaddr_canonical; + nm_utils_hwaddr_len; + nm_utils_hwaddr_matches; + nm_utils_hwaddr_ntoa; + nm_utils_hwaddr_valid; + nm_utils_iface_valid_name; + nm_utils_inet4_ntop; + nm_utils_inet6_ntop; + nm_utils_ip4_addresses_from_variant; + nm_utils_ip4_addresses_to_variant; + nm_utils_ip4_dns_from_variant; + nm_utils_ip4_dns_to_variant; + nm_utils_ip4_get_default_prefix; + nm_utils_ip4_netmask_to_prefix; + nm_utils_ip4_prefix_to_netmask; + nm_utils_ip4_routes_from_variant; + nm_utils_ip4_routes_to_variant; + nm_utils_ip6_addresses_from_variant; + nm_utils_ip6_addresses_to_variant; + nm_utils_ip6_dns_from_variant; + nm_utils_ip6_dns_to_variant; + nm_utils_ip6_routes_from_variant; + nm_utils_ip6_routes_to_variant; + nm_utils_ipaddr_valid; + nm_utils_is_empty_ssid; + nm_utils_is_uuid; + nm_utils_same_ssid; + nm_utils_security_type_get_type; + nm_utils_security_valid; + nm_utils_ssid_to_utf8; + nm_utils_uuid_generate; + nm_utils_wep_key_valid; + nm_utils_wifi_channel_to_freq; + nm_utils_wifi_find_next_channel; + nm_utils_wifi_freq_to_channel; + nm_utils_wifi_is_channel_valid; + nm_utils_wifi_strength_bars; + nm_utils_wpa_psk_valid; + nm_vlan_flags_get_type; + nm_vlan_priority_map_get_type; + nm_vpn_connection_get_banner; + nm_vpn_connection_get_type; + nm_vpn_connection_get_vpn_state; + nm_vpn_connection_state_get_type; + nm_vpn_connection_state_reason_get_type; + nm_vpn_editor_get_type; + nm_vpn_editor_get_widget; + nm_vpn_editor_plugin_capability_get_type; + nm_vpn_editor_plugin_export; + nm_vpn_editor_plugin_get_capabilities; + nm_vpn_editor_plugin_get_editor; + nm_vpn_editor_plugin_get_suggested_filename; + nm_vpn_editor_plugin_get_type; + nm_vpn_editor_plugin_import; + nm_vpn_editor_update_connection; + nm_vpn_plugin_error_get_type; + nm_vpn_plugin_error_quark; + nm_vpn_plugin_failure_get_type; + nm_vpn_plugin_old_disconnect; + nm_vpn_plugin_old_failure; + nm_vpn_plugin_old_get_connection; + nm_vpn_plugin_old_get_secret_flags; + nm_vpn_plugin_old_get_state; + nm_vpn_plugin_old_get_type; + nm_vpn_plugin_old_read_vpn_details; + nm_vpn_plugin_old_secrets_required; + nm_vpn_plugin_old_set_ip4_config; + nm_vpn_plugin_old_set_login_banner; + nm_vpn_plugin_old_set_state; + nm_vpn_service_state_get_type; + nm_wep_key_type_get_type; + nm_wimax_nsp_connection_valid; + nm_wimax_nsp_filter_connections; + nm_wimax_nsp_get_name; + nm_wimax_nsp_get_network_type; + nm_wimax_nsp_get_signal_quality; + nm_wimax_nsp_get_type; + nm_wimax_nsp_network_type_get_type; +local: + *; +}; diff --git a/libnm/nm-access-point.c b/libnm/nm-access-point.c new file mode 100644 index 00000000..e20cd997 --- /dev/null +++ b/libnm/nm-access-point.c @@ -0,0 +1,598 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2007 - 2008 Novell, Inc. + * Copyright 2007 - 2011 Red Hat, Inc. + */ + +#include "config.h" + +#include <string.h> + +#include "nm-glib-compat.h" + +#include <nm-connection.h> +#include <nm-setting-connection.h> +#include <nm-setting-wireless.h> +#include <nm-setting-wireless-security.h> +#include <nm-utils.h> + +#include "nm-access-point.h" +#include "nm-dbus-interface.h" +#include "nm-object-private.h" + +G_DEFINE_TYPE (NMAccessPoint, nm_access_point, NM_TYPE_OBJECT) + +#define NM_ACCESS_POINT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_ACCESS_POINT, NMAccessPointPrivate)) + +typedef struct { + NM80211ApFlags flags; + NM80211ApSecurityFlags wpa_flags; + NM80211ApSecurityFlags rsn_flags; + GBytes *ssid; + guint32 frequency; + char *bssid; + NM80211Mode mode; + guint32 max_bitrate; + guint8 strength; +} NMAccessPointPrivate; + +enum { + PROP_0, + PROP_FLAGS, + PROP_WPA_FLAGS, + PROP_RSN_FLAGS, + PROP_SSID, + PROP_FREQUENCY, + PROP_HW_ADDRESS, + PROP_MODE, + PROP_MAX_BITRATE, + PROP_STRENGTH, + PROP_BSSID, + + LAST_PROP +}; + +/** + * nm_access_point_get_flags: + * @ap: a #NMAccessPoint + * + * Gets the flags of the access point. + * + * Returns: the flags + **/ +NM80211ApFlags +nm_access_point_get_flags (NMAccessPoint *ap) +{ + g_return_val_if_fail (NM_IS_ACCESS_POINT (ap), NM_802_11_AP_FLAGS_NONE); + + return NM_ACCESS_POINT_GET_PRIVATE (ap)->flags; +} + +/** + * nm_access_point_get_wpa_flags: + * @ap: a #NMAccessPoint + * + * Gets the WPA (version 1) flags of the access point. + * + * Returns: the WPA flags + **/ +NM80211ApSecurityFlags +nm_access_point_get_wpa_flags (NMAccessPoint *ap) +{ + g_return_val_if_fail (NM_IS_ACCESS_POINT (ap), NM_802_11_AP_SEC_NONE); + + return NM_ACCESS_POINT_GET_PRIVATE (ap)->wpa_flags; +} + +/** + * nm_access_point_get_rsn_flags: + * @ap: a #NMAccessPoint + * + * Gets the RSN (Robust Secure Network, ie WPA version 2) flags of the access + * point. + * + * Returns: the RSN flags + **/ +NM80211ApSecurityFlags +nm_access_point_get_rsn_flags (NMAccessPoint *ap) +{ + g_return_val_if_fail (NM_IS_ACCESS_POINT (ap), NM_802_11_AP_SEC_NONE); + + return NM_ACCESS_POINT_GET_PRIVATE (ap)->rsn_flags; +} + +/** + * nm_access_point_get_ssid: + * @ap: a #NMAccessPoint + * + * Gets the SSID of the access point. + * + * Returns: (transfer none): the #GBytes containing the SSID, or %NULL if the + * SSID is unknown. + **/ +GBytes * +nm_access_point_get_ssid (NMAccessPoint *ap) +{ + NMAccessPointPrivate *priv; + + g_return_val_if_fail (NM_IS_ACCESS_POINT (ap), NULL); + + priv = NM_ACCESS_POINT_GET_PRIVATE (ap); + if (!priv->ssid || g_bytes_get_size (priv->ssid) == 0) + return NULL; + + return priv->ssid; +} + +/** + * nm_access_point_get_frequency: + * @ap: a #NMAccessPoint + * + * Gets the frequency of the access point. + * + * Returns: the frequency + **/ +guint32 +nm_access_point_get_frequency (NMAccessPoint *ap) +{ + g_return_val_if_fail (NM_IS_ACCESS_POINT (ap), 0); + + return NM_ACCESS_POINT_GET_PRIVATE (ap)->frequency; +} + +/** + * nm_access_point_get_bssid: + * @ap: a #NMAccessPoint + * + * Gets the Basic Service Set ID (BSSID) of the Wi-Fi access point. + * + * Returns: the BSSID of the access point. This is an internal string and must + * not be modified or freed. + **/ +const char * +nm_access_point_get_bssid (NMAccessPoint *ap) +{ + g_return_val_if_fail (NM_IS_ACCESS_POINT (ap), NULL); + + return NM_ACCESS_POINT_GET_PRIVATE (ap)->bssid; +} + +/** + * nm_access_point_get_mode: + * @ap: a #NMAccessPoint + * + * Gets the mode of the access point. + * + * Returns: the mode + **/ +NM80211Mode +nm_access_point_get_mode (NMAccessPoint *ap) +{ + g_return_val_if_fail (NM_IS_ACCESS_POINT (ap), 0); + + return NM_ACCESS_POINT_GET_PRIVATE (ap)->mode; +} + +/** + * nm_access_point_get_max_bitrate: + * @ap: a #NMAccessPoint + * + * Gets the maximum bit rate of the access point in kbit/s. + * + * Returns: the maximum bit rate (kbit/s) + **/ +guint32 +nm_access_point_get_max_bitrate (NMAccessPoint *ap) +{ + g_return_val_if_fail (NM_IS_ACCESS_POINT (ap), 0); + + return NM_ACCESS_POINT_GET_PRIVATE (ap)->max_bitrate; +} + +/** + * nm_access_point_get_strength: + * @ap: a #NMAccessPoint + * + * Gets the current signal strength of the access point. + * + * Returns: the signal strength + **/ +guint8 +nm_access_point_get_strength (NMAccessPoint *ap) +{ + g_return_val_if_fail (NM_IS_ACCESS_POINT (ap), 0); + + return NM_ACCESS_POINT_GET_PRIVATE (ap)->strength; +} + +/** + * nm_access_point_connection_valid: + * @ap: an #NMAccessPoint to validate @connection against + * @connection: an #NMConnection to validate against @ap + * + * Validates a given connection against a given Wi-Fi access point to ensure that + * the connection may be activated with that AP. The connection must match the + * @ap's SSID, (if given) BSSID, and other attributes like security settings, + * channel, band, etc. + * + * Returns: %TRUE if the connection may be activated with this Wi-Fi AP, + * %FALSE if it cannot be. + **/ +gboolean +nm_access_point_connection_valid (NMAccessPoint *ap, NMConnection *connection) +{ + NMSettingConnection *s_con; + NMSettingWireless *s_wifi; + NMSettingWirelessSecurity *s_wsec; + const char *ctype, *ap_bssid; + GBytes *setting_ssid; + GBytes *ap_ssid; + const char *setting_bssid; + const char *setting_mode; + NM80211Mode ap_mode; + const char *setting_band; + guint32 ap_freq, setting_chan, ap_chan; + + s_con = nm_connection_get_setting_connection (connection); + g_assert (s_con); + ctype = nm_setting_connection_get_connection_type (s_con); + if (strcmp (ctype, NM_SETTING_WIRELESS_SETTING_NAME) != 0) + return FALSE; + + s_wifi = nm_connection_get_setting_wireless (connection); + if (!s_wifi) + return FALSE; + + /* SSID checks */ + ap_ssid = nm_access_point_get_ssid (ap); + g_warn_if_fail (ap_ssid != NULL); + setting_ssid = nm_setting_wireless_get_ssid (s_wifi); + if (!setting_ssid || !ap_ssid) + return FALSE; + if (!g_bytes_equal (ap_ssid, setting_ssid)) + return FALSE; + + /* BSSID checks */ + ap_bssid = nm_access_point_get_bssid (ap); + g_warn_if_fail (ap_bssid); + setting_bssid = nm_setting_wireless_get_bssid (s_wifi); + if (setting_bssid && ap_bssid) { + if (!nm_utils_hwaddr_matches (ap_bssid, -1, setting_bssid, -1)) + return FALSE; + } + + /* Mode */ + ap_mode = nm_access_point_get_mode (ap); + g_warn_if_fail (ap_mode != NM_802_11_MODE_UNKNOWN); + setting_mode = nm_setting_wireless_get_mode (s_wifi); + if (setting_mode && ap_mode) { + if (!strcmp (setting_mode, "infrastructure") && (ap_mode != NM_802_11_MODE_INFRA)) + return FALSE; + if (!strcmp (setting_mode, "adhoc") && (ap_mode != NM_802_11_MODE_ADHOC)) + return FALSE; + /* Hotspot never matches against APs as it's a device-specific mode. */ + if (!strcmp (setting_mode, "ap")) + return FALSE; + } + + /* Band and Channel/Frequency */ + ap_freq = nm_access_point_get_frequency (ap); + if (ap_freq) { + setting_band = nm_setting_wireless_get_band (s_wifi); + if (g_strcmp0 (setting_band, "a") == 0) { + if (ap_freq < 4915 || ap_freq > 5825) + return FALSE; + } else if (g_strcmp0 (setting_band, "bg") == 0) { + if (ap_freq < 2412 || ap_freq > 2484) + return FALSE; + } + + setting_chan = nm_setting_wireless_get_channel (s_wifi); + if (setting_chan) { + ap_chan = nm_utils_wifi_freq_to_channel (ap_freq); + if (setting_chan != ap_chan) + return FALSE; + } + } + + s_wsec = nm_connection_get_setting_wireless_security (connection); + if (!nm_setting_wireless_ap_security_compatible (s_wifi, + s_wsec, + nm_access_point_get_flags (ap), + nm_access_point_get_wpa_flags (ap), + nm_access_point_get_rsn_flags (ap), + ap_mode)) + return FALSE; + + return TRUE; +} + +/** + * nm_access_point_filter_connections: + * @ap: an #NMAccessPoint to filter connections for + * @connections: (element-type NMConnection): an array of #NMConnections to + * filter + * + * Filters a given array of connections for a given #NMAccessPoint object and + * returns connections which may be activated with the access point. Any + * returned connections will match the @ap's SSID and (if given) BSSID and + * other attributes like security settings, channel, etc. + * + * To obtain the list of connections that are compatible with this access point, + * use nm_client_get_connections() and then filter the returned list for a given + * #NMDevice using nm_device_filter_connections() and finally filter that list + * with this function. + * + * Returns: (transfer container) (element-type NMConnection): an array of + * #NMConnections that could be activated with the given @ap. The array should + * be freed with g_ptr_array_unref() when it is no longer required. + **/ +GPtrArray * +nm_access_point_filter_connections (NMAccessPoint *ap, const GPtrArray *connections) +{ + GPtrArray *filtered; + int i; + + filtered = g_ptr_array_new_with_free_func (g_object_unref); + for (i = 0; i < connections->len; i++) { + NMConnection *candidate = connections->pdata[i]; + + if (nm_access_point_connection_valid (ap, candidate)) + g_ptr_array_add (filtered, g_object_ref (candidate)); + } + + return filtered; +} + +/************************************************************/ + +static void +nm_access_point_init (NMAccessPoint *ap) +{ +} + +static void +finalize (GObject *object) +{ + NMAccessPointPrivate *priv = NM_ACCESS_POINT_GET_PRIVATE (object); + + if (priv->ssid) + g_bytes_unref (priv->ssid); + + g_free (priv->bssid); + + G_OBJECT_CLASS (nm_access_point_parent_class)->finalize (object); +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMAccessPoint *ap = NM_ACCESS_POINT (object); + + switch (prop_id) { + case PROP_FLAGS: + g_value_set_flags (value, nm_access_point_get_flags (ap)); + break; + case PROP_WPA_FLAGS: + g_value_set_flags (value, nm_access_point_get_wpa_flags (ap)); + break; + case PROP_RSN_FLAGS: + g_value_set_flags (value, nm_access_point_get_rsn_flags (ap)); + break; + case PROP_SSID: + g_value_set_boxed (value, nm_access_point_get_ssid (ap)); + break; + case PROP_FREQUENCY: + g_value_set_uint (value, nm_access_point_get_frequency (ap)); + break; + case PROP_HW_ADDRESS: + g_value_set_string (value, nm_access_point_get_bssid (ap)); + break; + case PROP_BSSID: + g_value_set_string (value, nm_access_point_get_bssid (ap)); + break; + case PROP_MODE: + g_value_set_enum (value, nm_access_point_get_mode (ap)); + break; + case PROP_MAX_BITRATE: + g_value_set_uint (value, nm_access_point_get_max_bitrate (ap)); + break; + case PROP_STRENGTH: + g_value_set_uchar (value, nm_access_point_get_strength (ap)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +init_dbus (NMObject *object) +{ + NMAccessPointPrivate *priv = NM_ACCESS_POINT_GET_PRIVATE (object); + const NMPropertiesInfo property_info[] = { + { NM_ACCESS_POINT_FLAGS, &priv->flags }, + { NM_ACCESS_POINT_WPA_FLAGS, &priv->wpa_flags }, + { NM_ACCESS_POINT_RSN_FLAGS, &priv->rsn_flags }, + { NM_ACCESS_POINT_SSID, &priv->ssid }, + { NM_ACCESS_POINT_FREQUENCY, &priv->frequency }, + /* The D-Bus property is HwAddress, but the GObject property is "bssid" */ + { NM_ACCESS_POINT_HW_ADDRESS, &priv->bssid }, + { NM_ACCESS_POINT_MODE, &priv->mode }, + { NM_ACCESS_POINT_MAX_BITRATE, &priv->max_bitrate }, + { NM_ACCESS_POINT_STRENGTH, &priv->strength }, + { NULL }, + }; + + NM_OBJECT_CLASS (nm_access_point_parent_class)->init_dbus (object); + + _nm_object_register_properties (object, + NM_DBUS_INTERFACE_ACCESS_POINT, + property_info); +} + + +static void +nm_access_point_class_init (NMAccessPointClass *ap_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (ap_class); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (ap_class); + + g_type_class_add_private (ap_class, sizeof (NMAccessPointPrivate)); + + _nm_object_class_add_interface (nm_object_class, NM_DBUS_INTERFACE_ACCESS_POINT); + + /* virtual methods */ + object_class->get_property = get_property; + object_class->finalize = finalize; + + nm_object_class->init_dbus = init_dbus; + + /* properties */ + + /** + * NMAccessPoint:flags: + * + * The flags of the access point. + **/ + g_object_class_install_property + (object_class, PROP_FLAGS, + g_param_spec_flags (NM_ACCESS_POINT_FLAGS, "", "", + NM_TYPE_802_11_AP_FLAGS, + NM_802_11_AP_FLAGS_NONE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMAccessPoint:wpa-flags: + * + * The WPA flags of the access point. + **/ + g_object_class_install_property + (object_class, PROP_WPA_FLAGS, + g_param_spec_flags (NM_ACCESS_POINT_WPA_FLAGS, "", "", + NM_TYPE_802_11_AP_SECURITY_FLAGS, + NM_802_11_AP_SEC_NONE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMAccessPoint:rsn-flags: + * + * The RSN flags of the access point. + **/ + g_object_class_install_property + (object_class, PROP_RSN_FLAGS, + g_param_spec_flags (NM_ACCESS_POINT_RSN_FLAGS, "", "", + NM_TYPE_802_11_AP_SECURITY_FLAGS, + NM_802_11_AP_SEC_NONE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMAccessPoint:ssid: + * + * The SSID of the access point, or %NULL if it is not known. + **/ + g_object_class_install_property + (object_class, PROP_SSID, + g_param_spec_boxed (NM_ACCESS_POINT_SSID, "", "", + G_TYPE_BYTES, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMAccessPoint:frequency: + * + * The frequency of the access point. + **/ + g_object_class_install_property + (object_class, PROP_FREQUENCY, + g_param_spec_uint (NM_ACCESS_POINT_FREQUENCY, "", "", + 0, 10000, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMAccessPoint:bssid: + * + * The BSSID of the access point. + **/ + g_object_class_install_property + (object_class, PROP_BSSID, + g_param_spec_string (NM_ACCESS_POINT_BSSID, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMAccessPoint:hw-address: + * + * Alias for #NMAccessPoint:bssid. + * + * Deprecated: 1.0: use #NMAccessPoint:bssid. + **/ + g_object_class_install_property + (object_class, PROP_HW_ADDRESS, + g_param_spec_string (NM_ACCESS_POINT_HW_ADDRESS, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMAccessPoint:mode: + * + * The mode of the access point; either "infrastructure" (a central + * coordinator of the wireless network allowing clients to connect) or + * "ad-hoc" (a network with no central controller). + **/ + g_object_class_install_property + (object_class, PROP_MODE, + g_param_spec_enum (NM_ACCESS_POINT_MODE, "", "", + NM_TYPE_802_11_MODE, + NM_802_11_MODE_INFRA, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMAccessPoint:max-bitrate: + * + * The maximum bit rate of the access point in kbit/s. + **/ + g_object_class_install_property + (object_class, PROP_MAX_BITRATE, + g_param_spec_uint (NM_ACCESS_POINT_MAX_BITRATE, "", "", + 0, G_MAXUINT32, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMAccessPoint:strength: + * + * The current signal strength of the access point. + **/ + g_object_class_install_property + (object_class, PROP_STRENGTH, + g_param_spec_uchar (NM_ACCESS_POINT_STRENGTH, "", "", + 0, G_MAXUINT8, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); +} diff --git a/libnm/nm-access-point.h b/libnm/nm-access-point.h new file mode 100644 index 00000000..6991c19a --- /dev/null +++ b/libnm/nm-access-point.h @@ -0,0 +1,85 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2007 - 2008 Novell, Inc. + * Copyright 2007 - 2011 Red Hat, Inc. + */ + +#ifndef __NM_ACCESS_POINT_H__ +#define __NM_ACCESS_POINT_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include <nm-object.h> + +G_BEGIN_DECLS + +#define NM_TYPE_ACCESS_POINT (nm_access_point_get_type ()) +#define NM_ACCESS_POINT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_ACCESS_POINT, NMAccessPoint)) +#define NM_ACCESS_POINT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_ACCESS_POINT, NMAccessPointClass)) +#define NM_IS_ACCESS_POINT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_ACCESS_POINT)) +#define NM_IS_ACCESS_POINT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_ACCESS_POINT)) +#define NM_ACCESS_POINT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_ACCESS_POINT, NMAccessPointClass)) + +#define NM_ACCESS_POINT_FLAGS "flags" +#define NM_ACCESS_POINT_WPA_FLAGS "wpa-flags" +#define NM_ACCESS_POINT_RSN_FLAGS "rsn-flags" +#define NM_ACCESS_POINT_SSID "ssid" +#define NM_ACCESS_POINT_BSSID "bssid" +#define NM_ACCESS_POINT_FREQUENCY "frequency" +#define NM_ACCESS_POINT_MODE "mode" +#define NM_ACCESS_POINT_MAX_BITRATE "max-bitrate" +#define NM_ACCESS_POINT_STRENGTH "strength" + +/* DEPRECATED */ +#define NM_ACCESS_POINT_HW_ADDRESS "hw-address" + + +struct _NMAccessPoint { + NMObject parent; +}; + +typedef struct { + NMObjectClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMAccessPointClass; + +GType nm_access_point_get_type (void); + +NM80211ApFlags nm_access_point_get_flags (NMAccessPoint *ap); +NM80211ApSecurityFlags nm_access_point_get_wpa_flags (NMAccessPoint *ap); +NM80211ApSecurityFlags nm_access_point_get_rsn_flags (NMAccessPoint *ap); +GBytes * nm_access_point_get_ssid (NMAccessPoint *ap); +const char * nm_access_point_get_bssid (NMAccessPoint *ap); +guint32 nm_access_point_get_frequency (NMAccessPoint *ap); +NM80211Mode nm_access_point_get_mode (NMAccessPoint *ap); +guint32 nm_access_point_get_max_bitrate (NMAccessPoint *ap); +guint8 nm_access_point_get_strength (NMAccessPoint *ap); + +GPtrArray * nm_access_point_filter_connections (NMAccessPoint *ap, + const GPtrArray *connections); + +gboolean nm_access_point_connection_valid (NMAccessPoint *ap, + NMConnection *connection); + +G_END_DECLS + +#endif /* __NM_ACCESS_POINT_H__ */ diff --git a/libnm/nm-active-connection.c b/libnm/nm-active-connection.c new file mode 100644 index 00000000..31f51328 --- /dev/null +++ b/libnm/nm-active-connection.c @@ -0,0 +1,714 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2007 - 2014 Red Hat, Inc. + * Copyright 2008 Novell, Inc. + */ + +#include "config.h" + +#include <string.h> + +#include "nm-dbus-interface.h" +#include "nm-active-connection.h" +#include "nm-object-private.h" +#include "nm-core-internal.h" +#include "nm-device.h" +#include "nm-device-private.h" +#include "nm-connection.h" +#include "nm-vpn-connection.h" +#include "nm-glib-compat.h" +#include "nm-dbus-helpers.h" +#include "nm-dhcp4-config.h" +#include "nm-dhcp6-config.h" +#include "nm-ip4-config.h" +#include "nm-ip6-config.h" +#include "nm-remote-connection.h" + +static GType _nm_active_connection_decide_type (GVariant *value); + +G_DEFINE_TYPE_WITH_CODE (NMActiveConnection, nm_active_connection, NM_TYPE_OBJECT, + _nm_object_register_type_func (g_define_type_id, + _nm_active_connection_decide_type, + NM_DBUS_INTERFACE_ACTIVE_CONNECTION, + "Vpn"); + ) + +#define NM_ACTIVE_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_ACTIVE_CONNECTION, NMActiveConnectionPrivate)) + +typedef struct { + NMRemoteConnection *connection; + char *id; + char *uuid; + char *type; + char *specific_object_path; + GPtrArray *devices; + NMActiveConnectionState state; + gboolean is_default; + NMIPConfig *ip4_config; + NMDhcpConfig *dhcp4_config; + gboolean is_default6; + NMIPConfig *ip6_config; + NMDhcpConfig *dhcp6_config; + gboolean is_vpn; + NMDevice *master; +} NMActiveConnectionPrivate; + +enum { + PROP_0, + PROP_CONNECTION, + PROP_ID, + PROP_UUID, + PROP_TYPE, + PROP_SPECIFIC_OBJECT_PATH, + PROP_DEVICES, + PROP_STATE, + PROP_DEFAULT, + PROP_IP4_CONFIG, + PROP_DHCP4_CONFIG, + PROP_DEFAULT6, + PROP_IP6_CONFIG, + PROP_DHCP6_CONFIG, + PROP_VPN, + PROP_MASTER, + + LAST_PROP +}; + +static GType +_nm_active_connection_decide_type (GVariant *value) +{ + /* @value is the value of the o.fd.NM.ActiveConnection property "VPN" */ + if (g_variant_get_boolean (value)) + return NM_TYPE_VPN_CONNECTION; + else + return NM_TYPE_ACTIVE_CONNECTION; +} + +/** + * nm_active_connection_get_connection: + * @connection: a #NMActiveConnection + * + * Gets the #NMRemoteConnection associated with @connection. + * + * Returns: (transfer none): the #NMRemoteConnection which this + * #NMActiveConnection is an active instance of. + **/ +NMRemoteConnection * +nm_active_connection_get_connection (NMActiveConnection *connection) +{ + g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL); + + return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->connection; +} + +/** + * nm_active_connection_get_id: + * @connection: a #NMActiveConnection + * + * Gets the #NMConnection's ID. + * + * Returns: the ID of the #NMConnection that backs the #NMActiveConnection. + * This is the internal string used by the connection, and must not be modified. + **/ +const char * +nm_active_connection_get_id (NMActiveConnection *connection) +{ + g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL); + + return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->id; +} + +/** + * nm_active_connection_get_uuid: + * @connection: a #NMActiveConnection + * + * Gets the #NMConnection's UUID. + * + * Returns: the UUID of the #NMConnection that backs the #NMActiveConnection. + * This is the internal string used by the connection, and must not be modified. + **/ +const char * +nm_active_connection_get_uuid (NMActiveConnection *connection) +{ + g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL); + + return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->uuid; +} + +/** + * nm_active_connection_get_connection_type: + * @connection: a #NMActiveConnection + * + * Gets the #NMConnection's type. + * + * Returns: the type of the #NMConnection that backs the #NMActiveConnection. + * This is the internal string used by the connection, and must not be modified. + **/ +const char * +nm_active_connection_get_connection_type (NMActiveConnection *connection) +{ + g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL); + + return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->type; +} + +/** + * nm_active_connection_get_specific_object_path: + * @connection: a #NMActiveConnection + * + * Gets the path of the "specific object" used at activation. + * + * Currently there is no single method that will allow you to automatically turn + * this into an appropriate #NMObject; you need to know what kind of object it + * is based on other information. (Eg, if @connection corresponds to a Wi-Fi + * connection, then the specific object will be an #NMAccessPoint, and you can + * resolve it with nm_device_wifi_get_access_point_by_path().) + * + * Returns: the specific object's D-Bus path. This is the internal string used + * by the connection, and must not be modified. + **/ +const char * +nm_active_connection_get_specific_object_path (NMActiveConnection *connection) +{ + g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL); + + return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->specific_object_path; +} + +/** + * nm_active_connection_get_devices: + * @connection: a #NMActiveConnection + * + * Gets the #NMDevices used for the active connections. + * + * Returns: (element-type NMDevice): the #GPtrArray containing #NMDevices. + * This is the internal copy used by the connection, and must not be modified. + **/ +const GPtrArray * +nm_active_connection_get_devices (NMActiveConnection *connection) +{ + g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL); + + return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->devices; +} + +/** + * nm_active_connection_get_state: + * @connection: a #NMActiveConnection + * + * Gets the active connection's state. + * + * Returns: the state + **/ +NMActiveConnectionState +nm_active_connection_get_state (NMActiveConnection *connection) +{ + g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NM_ACTIVE_CONNECTION_STATE_UNKNOWN); + + return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->state; +} + +/** + * nm_active_connection_get_default: + * @connection: a #NMActiveConnection + * + * Whether the active connection is the default IPv4 one (that is, is used for + * the default IPv4 route and DNS information). + * + * Returns: %TRUE if the active connection is the default IPv4 connection + **/ +gboolean +nm_active_connection_get_default (NMActiveConnection *connection) +{ + g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), FALSE); + + return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->is_default; +} + +/** + * nm_active_connection_get_ip4_config: + * @connection: an #NMActiveConnection + * + * Gets the current IPv4 #NMIPConfig associated with the #NMActiveConnection. + * + * Returns: (transfer none): the IPv4 #NMIPConfig, or %NULL if the connection is + * not in the %NM_ACTIVE_CONNECTION_STATE_ACTIVATED state. + **/ +NMIPConfig * +nm_active_connection_get_ip4_config (NMActiveConnection *connection) +{ + g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL); + + return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->ip4_config; +} + +/** + * nm_active_connection_get_dhcp4_config: + * @connection: an #NMActiveConnection + * + * Gets the current IPv4 #NMDhcpConfig (if any) associated with the + * #NMActiveConnection. + * + * Returns: (transfer none): the IPv4 #NMDhcpConfig, or %NULL if the connection + * does not use DHCP, or is not in the %NM_ACTIVE_CONNECTION_STATE_ACTIVATED + * state. + **/ +NMDhcpConfig * +nm_active_connection_get_dhcp4_config (NMActiveConnection *connection) +{ + g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL); + + return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->dhcp4_config; +} + +/** + * nm_active_connection_get_default6: + * @connection: a #NMActiveConnection + * + * Whether the active connection is the default IPv6 one (that is, is used for + * the default IPv6 route and DNS information). + * + * Returns: %TRUE if the active connection is the default IPv6 connection + **/ +gboolean +nm_active_connection_get_default6 (NMActiveConnection *connection) +{ + g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), FALSE); + + return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->is_default6; +} + +/** + * nm_active_connection_get_ip6_config: + * @connection: an #NMActiveConnection + * + * Gets the current IPv6 #NMIPConfig associated with the #NMActiveConnection. + * + * Returns: (transfer none): the IPv6 #NMIPConfig, or %NULL if the connection is + * not in the %NM_ACTIVE_CONNECTION_STATE_ACTIVATED state. + **/ +NMIPConfig * +nm_active_connection_get_ip6_config (NMActiveConnection *connection) +{ + g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL); + + return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->ip6_config; +} + +/** + * nm_active_connection_get_dhcp6_config: + * @connection: an #NMActiveConnection + * + * Gets the current IPv6 #NMDhcpConfig (if any) associated with the + * #NMActiveConnection. + * + * Returns: (transfer none): the IPv6 #NMDhcpConfig, or %NULL if the connection + * does not use DHCPv6, or is not in the %NM_ACTIVE_CONNECTION_STATE_ACTIVATED + * state. + **/ +NMDhcpConfig * +nm_active_connection_get_dhcp6_config (NMActiveConnection *connection) +{ + g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL); + + return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->dhcp6_config; +} + +/** + * nm_active_connection_get_vpn: + * @connection: a #NMActiveConnection + * + * Whether the active connection is a VPN connection. + * + * Returns: %TRUE if the active connection is a VPN connection + **/ +gboolean +nm_active_connection_get_vpn (NMActiveConnection *connection) +{ + g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), FALSE); + + return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->is_vpn; +} + +/** + * nm_active_connection_get_master: + * @connection: a #NMActiveConnection + * + * Gets the master #NMDevice of the connection. + * + * Returns: (transfer none): the master #NMDevice of the #NMActiveConnection. + **/ +NMDevice * +nm_active_connection_get_master (NMActiveConnection *connection) +{ + g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (connection), NULL); + + return NM_ACTIVE_CONNECTION_GET_PRIVATE (connection)->master; +} + +static void +nm_active_connection_init (NMActiveConnection *connection) +{ + NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (connection); + + priv->devices = g_ptr_array_new (); +} + +static void +dispose (GObject *object) +{ + NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object); + + g_clear_pointer (&priv->devices, g_ptr_array_unref); + + g_clear_object (&priv->connection); + g_clear_object (&priv->master); + g_clear_object (&priv->ip4_config); + g_clear_object (&priv->dhcp4_config); + g_clear_object (&priv->ip6_config); + g_clear_object (&priv->dhcp6_config); + + G_OBJECT_CLASS (nm_active_connection_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object); + + g_free (priv->id); + g_free (priv->uuid); + g_free (priv->type); + g_free (priv->specific_object_path); + + G_OBJECT_CLASS (nm_active_connection_parent_class)->finalize (object); +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMActiveConnection *self = NM_ACTIVE_CONNECTION (object); + + switch (prop_id) { + case PROP_CONNECTION: + g_value_set_object (value, nm_active_connection_get_connection (self)); + break; + case PROP_ID: + g_value_set_string (value, nm_active_connection_get_id (self)); + break; + case PROP_UUID: + g_value_set_string (value, nm_active_connection_get_uuid (self)); + break; + case PROP_TYPE: + g_value_set_string (value, nm_active_connection_get_connection_type (self)); + break; + case PROP_SPECIFIC_OBJECT_PATH: + g_value_set_string (value, nm_active_connection_get_specific_object_path (self)); + break; + case PROP_DEVICES: + g_value_take_boxed (value, _nm_utils_copy_object_array (nm_active_connection_get_devices (self))); + break; + case PROP_STATE: + g_value_set_enum (value, nm_active_connection_get_state (self)); + break; + case PROP_DEFAULT: + g_value_set_boolean (value, nm_active_connection_get_default (self)); + break; + case PROP_IP4_CONFIG: + g_value_set_object (value, nm_active_connection_get_ip4_config (self)); + break; + case PROP_DHCP4_CONFIG: + g_value_set_object (value, nm_active_connection_get_dhcp4_config (self)); + break; + case PROP_DEFAULT6: + g_value_set_boolean (value, nm_active_connection_get_default6 (self)); + break; + case PROP_IP6_CONFIG: + g_value_set_object (value, nm_active_connection_get_ip6_config (self)); + break; + case PROP_DHCP6_CONFIG: + g_value_set_object (value, nm_active_connection_get_dhcp6_config (self)); + break; + case PROP_VPN: + g_value_set_boolean (value, nm_active_connection_get_vpn (self)); + break; + case PROP_MASTER: + g_value_set_object (value, nm_active_connection_get_master (self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +demarshal_specific_object_path (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field) +{ + char **param = (char **) field; + + /* We have to demarshal this manually, because the D-Bus property name + * ("SpecificObject"), doesn't match the object property name + * ("specific-object-path"). (The name "specific-object" is reserved for + * future use as an NMObject-valued property.) + */ + if (!g_variant_is_of_type (value, G_VARIANT_TYPE_OBJECT_PATH)) + return FALSE; + + g_free (*param); + *param = g_variant_dup_string (value, NULL); + return TRUE; +} + +static void +init_dbus (NMObject *object) +{ + NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object); + const NMPropertiesInfo property_info[] = { + { NM_ACTIVE_CONNECTION_CONNECTION, &priv->connection, NULL, NM_TYPE_REMOTE_CONNECTION }, + { NM_ACTIVE_CONNECTION_ID, &priv->id }, + { NM_ACTIVE_CONNECTION_UUID, &priv->uuid }, + { NM_ACTIVE_CONNECTION_TYPE, &priv->type }, + { "specific-object", &priv->specific_object_path, demarshal_specific_object_path }, + { NM_ACTIVE_CONNECTION_DEVICES, &priv->devices, NULL, NM_TYPE_DEVICE }, + { NM_ACTIVE_CONNECTION_STATE, &priv->state }, + { NM_ACTIVE_CONNECTION_DEFAULT, &priv->is_default }, + { NM_ACTIVE_CONNECTION_IP4_CONFIG, &priv->ip4_config, NULL, NM_TYPE_IP4_CONFIG }, + { NM_ACTIVE_CONNECTION_DHCP4_CONFIG, &priv->dhcp4_config, NULL, NM_TYPE_DHCP4_CONFIG }, + { NM_ACTIVE_CONNECTION_DEFAULT6, &priv->is_default6 }, + { NM_ACTIVE_CONNECTION_IP6_CONFIG, &priv->ip6_config, NULL, NM_TYPE_IP6_CONFIG }, + { NM_ACTIVE_CONNECTION_DHCP6_CONFIG, &priv->dhcp6_config, NULL, NM_TYPE_DHCP6_CONFIG }, + { NM_ACTIVE_CONNECTION_VPN, &priv->is_vpn }, + { NM_ACTIVE_CONNECTION_MASTER, &priv->master, NULL, NM_TYPE_DEVICE }, + + { NULL }, + }; + + NM_OBJECT_CLASS (nm_active_connection_parent_class)->init_dbus (object); + + _nm_object_register_properties (object, + NM_DBUS_INTERFACE_ACTIVE_CONNECTION, + property_info); +} + + +static void +nm_active_connection_class_init (NMActiveConnectionClass *ap_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (ap_class); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (ap_class); + + g_type_class_add_private (ap_class, sizeof (NMActiveConnectionPrivate)); + + _nm_object_class_add_interface (nm_object_class, NM_DBUS_INTERFACE_ACTIVE_CONNECTION); + + /* virtual methods */ + object_class->get_property = get_property; + object_class->dispose = dispose; + object_class->finalize = finalize; + + nm_object_class->init_dbus = init_dbus; + + /* properties */ + + /** + * NMActiveConnection:connection: + * + * The connection that this is an active instance of. + **/ + g_object_class_install_property + (object_class, PROP_CONNECTION, + g_param_spec_object (NM_ACTIVE_CONNECTION_CONNECTION, "", "", + NM_TYPE_REMOTE_CONNECTION, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMActiveConnection:id: + * + * The active connection's ID + **/ + g_object_class_install_property + (object_class, PROP_ID, + g_param_spec_string (NM_ACTIVE_CONNECTION_ID, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMActiveConnection:uuid: + * + * The active connection's UUID + **/ + g_object_class_install_property + (object_class, PROP_UUID, + g_param_spec_string (NM_ACTIVE_CONNECTION_UUID, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMActiveConnection:type: + * + * The active connection's type + **/ + g_object_class_install_property + (object_class, PROP_TYPE, + g_param_spec_string (NM_ACTIVE_CONNECTION_TYPE, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMActiveConnection:specific-object-path: + * + * The path to the "specific object" of the active connection; see + * nm_active_connection_get_specific_object_path() for more details. + **/ + g_object_class_install_property + (object_class, PROP_SPECIFIC_OBJECT_PATH, + g_param_spec_string (NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT_PATH, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMActiveConnection:devices: + * + * The devices of the active connection. + * + * Element-type: NMDevice + **/ + g_object_class_install_property + (object_class, PROP_DEVICES, + g_param_spec_boxed (NM_ACTIVE_CONNECTION_DEVICES, "", "", + G_TYPE_PTR_ARRAY, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMActiveConnection:state: + * + * The state of the active connection. + **/ + g_object_class_install_property + (object_class, PROP_STATE, + g_param_spec_enum (NM_ACTIVE_CONNECTION_STATE, "", "", + NM_TYPE_ACTIVE_CONNECTION_STATE, + NM_ACTIVE_CONNECTION_STATE_UNKNOWN, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMActiveConnection:default: + * + * Whether the active connection is the default IPv4 one. + **/ + g_object_class_install_property + (object_class, PROP_DEFAULT, + g_param_spec_boolean (NM_ACTIVE_CONNECTION_DEFAULT, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMActiveConnection:ip4-config: + * + * The IPv4 #NMIPConfig of the connection. + **/ + g_object_class_install_property + (object_class, PROP_IP4_CONFIG, + g_param_spec_object (NM_ACTIVE_CONNECTION_IP4_CONFIG, "", "", + NM_TYPE_IP_CONFIG, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMActiveConnection:dhcp4-config: + * + * The IPv4 #NMDhcpConfig of the connection. + **/ + g_object_class_install_property + (object_class, PROP_DHCP4_CONFIG, + g_param_spec_object (NM_ACTIVE_CONNECTION_DHCP4_CONFIG, "", "", + NM_TYPE_DHCP_CONFIG, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMActiveConnection:default6: + * + * Whether the active connection is the default IPv6 one. + **/ + g_object_class_install_property + (object_class, PROP_DEFAULT6, + g_param_spec_boolean (NM_ACTIVE_CONNECTION_DEFAULT6, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMActiveConnection:ip6-config: + * + * The IPv6 #NMIPConfig of the connection. + **/ + g_object_class_install_property + (object_class, PROP_IP6_CONFIG, + g_param_spec_object (NM_ACTIVE_CONNECTION_IP6_CONFIG, "", "", + NM_TYPE_IP_CONFIG, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMActiveConnection:dhcp6-config: + * + * The IPv6 #NMDhcpConfig of the connection. + **/ + g_object_class_install_property + (object_class, PROP_DHCP6_CONFIG, + g_param_spec_object (NM_ACTIVE_CONNECTION_DHCP6_CONFIG, "", "", + NM_TYPE_DHCP_CONFIG, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMActiveConnection:vpn: + * + * Whether the active connection is a VPN connection. + **/ + g_object_class_install_property + (object_class, PROP_VPN, + g_param_spec_boolean (NM_ACTIVE_CONNECTION_VPN, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMActiveConnection:master: + * + * The master device if one exists. + **/ + g_object_class_install_property + (object_class, PROP_MASTER, + g_param_spec_object (NM_ACTIVE_CONNECTION_MASTER, "", "", + NM_TYPE_DEVICE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); +} diff --git a/libnm/nm-active-connection.h b/libnm/nm-active-connection.h new file mode 100644 index 00000000..4bc84148 --- /dev/null +++ b/libnm/nm-active-connection.h @@ -0,0 +1,87 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2007 - 2014 Red Hat, Inc. + * Copyright 2008 Novell, Inc. + */ + +#ifndef __NM_ACTIVE_CONNECTION_H__ +#define __NM_ACTIVE_CONNECTION_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include <nm-object.h> + +G_BEGIN_DECLS + +#define NM_TYPE_ACTIVE_CONNECTION (nm_active_connection_get_type ()) +#define NM_ACTIVE_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_ACTIVE_CONNECTION, NMActiveConnection)) +#define NM_ACTIVE_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_ACTIVE_CONNECTION, NMActiveConnectionClass)) +#define NM_IS_ACTIVE_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_ACTIVE_CONNECTION)) +#define NM_IS_ACTIVE_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_ACTIVE_CONNECTION)) +#define NM_ACTIVE_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_ACTIVE_CONNECTION, NMActiveConnectionClass)) + +#define NM_ACTIVE_CONNECTION_CONNECTION "connection" +#define NM_ACTIVE_CONNECTION_ID "id" +#define NM_ACTIVE_CONNECTION_UUID "uuid" +#define NM_ACTIVE_CONNECTION_TYPE "type" +#define NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT_PATH "specific-object-path" +#define NM_ACTIVE_CONNECTION_DEVICES "devices" +#define NM_ACTIVE_CONNECTION_STATE "state" +#define NM_ACTIVE_CONNECTION_DEFAULT "default" +#define NM_ACTIVE_CONNECTION_IP4_CONFIG "ip4-config" +#define NM_ACTIVE_CONNECTION_DHCP4_CONFIG "dhcp4-config" +#define NM_ACTIVE_CONNECTION_DEFAULT6 "default6" +#define NM_ACTIVE_CONNECTION_IP6_CONFIG "ip6-config" +#define NM_ACTIVE_CONNECTION_DHCP6_CONFIG "dhcp6-config" +#define NM_ACTIVE_CONNECTION_VPN "vpn" +#define NM_ACTIVE_CONNECTION_MASTER "master" + +struct _NMActiveConnection { + NMObject parent; +}; + +typedef struct { + NMObjectClass parent; + + /*< private >*/ + gpointer padding[8]; +} NMActiveConnectionClass; + +GType nm_active_connection_get_type (void); + +NMRemoteConnection *nm_active_connection_get_connection (NMActiveConnection *connection); +const char *nm_active_connection_get_id (NMActiveConnection *connection); +const char *nm_active_connection_get_uuid (NMActiveConnection *connection); +const char *nm_active_connection_get_connection_type (NMActiveConnection *connection); +const char *nm_active_connection_get_specific_object_path (NMActiveConnection *connection); +const GPtrArray *nm_active_connection_get_devices (NMActiveConnection *connection); +NMActiveConnectionState nm_active_connection_get_state (NMActiveConnection *connection); +NMDevice *nm_active_connection_get_master (NMActiveConnection *connection); +gboolean nm_active_connection_get_default (NMActiveConnection *connection); +NMIPConfig *nm_active_connection_get_ip4_config (NMActiveConnection *connection); +NMDhcpConfig *nm_active_connection_get_dhcp4_config (NMActiveConnection *connection); +gboolean nm_active_connection_get_default6 (NMActiveConnection *connection); +NMIPConfig *nm_active_connection_get_ip6_config (NMActiveConnection *connection); +NMDhcpConfig *nm_active_connection_get_dhcp6_config (NMActiveConnection *connection); +gboolean nm_active_connection_get_vpn (NMActiveConnection *connection); + +G_END_DECLS + +#endif /* __NM_ACTIVE_CONNECTION_H__ */ diff --git a/libnm/nm-client.c b/libnm/nm-client.c new file mode 100644 index 00000000..ef73e329 --- /dev/null +++ b/libnm/nm-client.c @@ -0,0 +1,2238 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2007 - 2008 Novell, Inc. + * Copyright 2007 - 2014 Red Hat, Inc. + */ + +#include "config.h" + +#include <string.h> +#include <nm-utils.h> + +#include "nm-client.h" +#include "nm-manager.h" +#include "nm-remote-settings.h" +#include "nm-device-ethernet.h" +#include "nm-device-wifi.h" +#include "nm-device-private.h" +#include "nm-core-internal.h" +#include "nm-active-connection.h" +#include "nm-vpn-connection.h" +#include "nm-remote-connection.h" +#include "nm-object-cache.h" +#include "nm-glib-compat.h" +#include "nm-dbus-helpers.h" + +void _nm_device_wifi_set_wireless_enabled (NMDeviceWifi *device, gboolean enabled); + +static void nm_client_initable_iface_init (GInitableIface *iface); +static void nm_client_async_initable_iface_init (GAsyncInitableIface *iface); + +G_DEFINE_TYPE_WITH_CODE (NMClient, nm_client, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_client_initable_iface_init); + G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_client_async_initable_iface_init); + ) + +#define NM_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_CLIENT, NMClientPrivate)) + +typedef struct { + NMManager *manager; + NMRemoteSettings *settings; +} NMClientPrivate; + +enum { + PROP_0, + PROP_VERSION, + PROP_STATE, + PROP_STARTUP, + PROP_NM_RUNNING, + PROP_NETWORKING_ENABLED, + PROP_WIRELESS_ENABLED, + PROP_WIRELESS_HARDWARE_ENABLED, + PROP_WWAN_ENABLED, + PROP_WWAN_HARDWARE_ENABLED, + PROP_WIMAX_ENABLED, + PROP_WIMAX_HARDWARE_ENABLED, + PROP_ACTIVE_CONNECTIONS, + PROP_CONNECTIVITY, + PROP_PRIMARY_CONNECTION, + PROP_ACTIVATING_CONNECTION, + PROP_DEVICES, + PROP_CONNECTIONS, + PROP_HOSTNAME, + PROP_CAN_MODIFY, + + LAST_PROP +}; + +enum { + DEVICE_ADDED, + DEVICE_REMOVED, + PERMISSION_CHANGED, + CONNECTION_ADDED, + CONNECTION_REMOVED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +/**********************************************************************/ + +/** + * nm_client_error_quark: + * + * Registers an error quark for #NMClient if necessary. + * + * Returns: the error quark used for #NMClient errors. + **/ +GQuark +nm_client_error_quark (void) +{ + static GQuark quark; + + if (G_UNLIKELY (!quark)) + quark = g_quark_from_static_string ("nm-client-error-quark"); + return quark; +} + +/**********************************************************************/ + +static void +nm_client_init (NMClient *client) +{ +} + +static gboolean +_nm_client_check_nm_running (NMClient *client, GError **error) +{ + if (nm_client_get_nm_running (client)) + return TRUE; + else { + g_set_error_literal (error, + NM_CLIENT_ERROR, + NM_CLIENT_ERROR_MANAGER_NOT_RUNNING, + "NetworkManager is not running"); + return FALSE; + } +} + +/** + * nm_client_get_version: + * @client: a #NMClient + * + * Gets NetworkManager version. + * + * Returns: string with the version (or %NULL if NetworkManager is not running) + **/ +const char * +nm_client_get_version (NMClient *client) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), NULL); + + return nm_manager_get_version (NM_CLIENT_GET_PRIVATE (client)->manager); +} + +/** + * nm_client_get_state: + * @client: a #NMClient + * + * Gets the current daemon state. + * + * Returns: the current %NMState + **/ +NMState +nm_client_get_state (NMClient *client) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), NM_STATE_UNKNOWN); + + return nm_manager_get_state (NM_CLIENT_GET_PRIVATE (client)->manager); +} + +/** + * nm_client_get_startup: + * @client: a #NMClient + * + * Tests whether the daemon is still in the process of activating + * connections at startup. + * + * Returns: whether the daemon is still starting up + **/ +gboolean +nm_client_get_startup (NMClient *client) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), NM_STATE_UNKNOWN); + + return nm_manager_get_startup (NM_CLIENT_GET_PRIVATE (client)->manager); +} + +/** + * nm_client_get_nm_running: + * @client: a #NMClient + * + * Determines whether the daemon is running. + * + * Returns: %TRUE if the daemon is running + **/ +gboolean +nm_client_get_nm_running (NMClient *client) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); + + return nm_manager_get_nm_running (NM_CLIENT_GET_PRIVATE (client)->manager); +} + +/** + * nm_client_networking_get_enabled: + * @client: a #NMClient + * + * Whether networking is enabled or disabled. + * + * Returns: %TRUE if networking is enabled, %FALSE if networking is disabled + **/ +gboolean +nm_client_networking_get_enabled (NMClient *client) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); + + return nm_manager_networking_get_enabled (NM_CLIENT_GET_PRIVATE (client)->manager); +} + +/** + * nm_client_networking_set_enabled: + * @client: a #NMClient + * @enabled: %TRUE to set networking enabled, %FALSE to set networking disabled + * @error: (allow-none): return location for a #GError, or %NULL + * + * Enables or disables networking. When networking is disabled, all controlled + * interfaces are disconnected and deactivated. When networking is enabled, + * all controlled interfaces are available for activation. + * + * Returns: %TRUE on success, %FALSE otherwise + **/ +gboolean +nm_client_networking_set_enabled (NMClient *client, gboolean enable, GError **error) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); + + if (!_nm_client_check_nm_running (client, error)) + return FALSE; + + return nm_manager_networking_set_enabled (NM_CLIENT_GET_PRIVATE (client)->manager, + enable, error); +} + +/** + * nm_client_wireless_get_enabled: + * @client: a #NMClient + * + * Determines whether the wireless is enabled. + * + * Returns: %TRUE if wireless is enabled + **/ +gboolean +nm_client_wireless_get_enabled (NMClient *client) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); + + return nm_manager_wireless_get_enabled (NM_CLIENT_GET_PRIVATE (client)->manager); +} + +/** + * nm_client_wireless_set_enabled: + * @client: a #NMClient + * @enabled: %TRUE to enable wireless + * + * Enables or disables wireless devices. + **/ +void +nm_client_wireless_set_enabled (NMClient *client, gboolean enabled) +{ + g_return_if_fail (NM_IS_CLIENT (client)); + + if (!_nm_client_check_nm_running (client, NULL)) + return; + + nm_manager_wireless_set_enabled (NM_CLIENT_GET_PRIVATE (client)->manager, enabled); +} + +/** + * nm_client_wireless_hardware_get_enabled: + * @client: a #NMClient + * + * Determines whether the wireless hardware is enabled. + * + * Returns: %TRUE if the wireless hardware is enabled + **/ +gboolean +nm_client_wireless_hardware_get_enabled (NMClient *client) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); + + return nm_manager_wireless_hardware_get_enabled (NM_CLIENT_GET_PRIVATE (client)->manager); +} + +/** + * nm_client_wwan_get_enabled: + * @client: a #NMClient + * + * Determines whether WWAN is enabled. + * + * Returns: %TRUE if WWAN is enabled + **/ +gboolean +nm_client_wwan_get_enabled (NMClient *client) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); + + return nm_manager_wwan_get_enabled (NM_CLIENT_GET_PRIVATE (client)->manager); +} + +/** + * nm_client_wwan_set_enabled: + * @client: a #NMClient + * @enabled: %TRUE to enable WWAN + * + * Enables or disables WWAN devices. + **/ +void +nm_client_wwan_set_enabled (NMClient *client, gboolean enabled) +{ + g_return_if_fail (NM_IS_CLIENT (client)); + + if (!_nm_client_check_nm_running (client, NULL)) + return; + + nm_manager_wwan_set_enabled (NM_CLIENT_GET_PRIVATE (client)->manager, enabled); +} + +/** + * nm_client_wwan_hardware_get_enabled: + * @client: a #NMClient + * + * Determines whether the WWAN hardware is enabled. + * + * Returns: %TRUE if the WWAN hardware is enabled + **/ +gboolean +nm_client_wwan_hardware_get_enabled (NMClient *client) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); + + return nm_manager_wwan_hardware_get_enabled (NM_CLIENT_GET_PRIVATE (client)->manager); +} + +/** + * nm_client_wimax_get_enabled: + * @client: a #NMClient + * + * Determines whether WiMAX is enabled. + * + * Returns: %TRUE if WiMAX is enabled + **/ +gboolean +nm_client_wimax_get_enabled (NMClient *client) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); + + return nm_manager_wimax_get_enabled (NM_CLIENT_GET_PRIVATE (client)->manager); +} + +/** + * nm_client_wimax_set_enabled: + * @client: a #NMClient + * @enabled: %TRUE to enable WiMAX + * + * Enables or disables WiMAX devices. + **/ +void +nm_client_wimax_set_enabled (NMClient *client, gboolean enabled) +{ + g_return_if_fail (NM_IS_CLIENT (client)); + + if (!_nm_client_check_nm_running (client, NULL)) + return; + + nm_manager_wimax_set_enabled (NM_CLIENT_GET_PRIVATE (client)->manager, enabled); +} + +/** + * nm_client_wimax_hardware_get_enabled: + * @client: a #NMClient + * + * Determines whether the WiMAX hardware is enabled. + * + * Returns: %TRUE if the WiMAX hardware is enabled + **/ +gboolean +nm_client_wimax_hardware_get_enabled (NMClient *client) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); + + return nm_manager_wimax_hardware_get_enabled (NM_CLIENT_GET_PRIVATE (client)->manager); +} + +/** + * nm_client_get_logging: + * @client: a #NMClient + * @level: (allow-none): return location for logging level string + * @domains: (allow-none): return location for log domains string. The string is + * a list of domains separated by "," + * @error: (allow-none): return location for a #GError, or %NULL + * + * Gets NetworkManager current logging level and domains. + * + * Returns: %TRUE on success, %FALSE otherwise + **/ +gboolean +nm_client_get_logging (NMClient *client, char **level, char **domains, GError **error) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); + g_return_val_if_fail (level == NULL || *level == NULL, FALSE); + g_return_val_if_fail (domains == NULL || *domains == NULL, FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (!_nm_client_check_nm_running (client, error)) + return FALSE; + + return nm_manager_get_logging (NM_CLIENT_GET_PRIVATE (client)->manager, + level, domains, error); +} + +/** + * nm_client_set_logging: + * @client: a #NMClient + * @level: (allow-none): logging level to set (%NULL or an empty string for no change) + * @domains: (allow-none): logging domains to set. The string should be a list of log + * domains separated by ",". (%NULL or an empty string for no change) + * @error: (allow-none): return location for a #GError, or %NULL + * + * Sets NetworkManager logging level and/or domains. + * + * Returns: %TRUE on success, %FALSE otherwise + **/ +gboolean +nm_client_set_logging (NMClient *client, const char *level, const char *domains, GError **error) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (!_nm_client_check_nm_running (client, error)) + return FALSE; + + return nm_manager_set_logging (NM_CLIENT_GET_PRIVATE (client)->manager, + level, domains, error); +} + +/** + * nm_client_get_permission_result: + * @client: a #NMClient + * @permission: the permission for which to return the result, one of #NMClientPermission + * + * Requests the result of a specific permission, which indicates whether the + * client can or cannot perform the action the permission represents + * + * Returns: the permission's result, one of #NMClientPermissionResult + **/ +NMClientPermissionResult +nm_client_get_permission_result (NMClient *client, NMClientPermission permission) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), NM_CLIENT_PERMISSION_RESULT_UNKNOWN); + + return nm_manager_get_permission_result (NM_CLIENT_GET_PRIVATE (client)->manager, permission); +} + +/** + * nm_client_get_connectivity: + * @client: an #NMClient + * + * Gets the current network connectivity state. Contrast + * nm_client_check_connectivity() and + * nm_client_check_connectivity_async(), which re-check the + * connectivity state first before returning any information. + * + * Returns: the current connectivity state + */ +NMConnectivityState +nm_client_get_connectivity (NMClient *client) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), NM_STATE_UNKNOWN); + + return nm_manager_get_connectivity (NM_CLIENT_GET_PRIVATE (client)->manager); +} + +/** + * nm_client_check_connectivity: + * @client: an #NMClient + * @cancellable: a #GCancellable + * @error: return location for a #GError + * + * Updates the network connectivity state and returns the (new) + * current state. Contrast nm_client_get_connectivity(), which returns + * the most recent known state without re-checking. + * + * This is a blocking call; use nm_client_check_connectivity_async() + * if you do not want to block. + * + * Returns: the (new) current connectivity state + */ +NMConnectivityState +nm_client_check_connectivity (NMClient *client, + GCancellable *cancellable, + GError **error) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), NM_CONNECTIVITY_UNKNOWN); + + if (!_nm_client_check_nm_running (client, error)) + return NM_CONNECTIVITY_UNKNOWN; + + return nm_manager_check_connectivity (NM_CLIENT_GET_PRIVATE (client)->manager, + cancellable, error); +} + +static void +check_connectivity_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + GSimpleAsyncResult *simple = user_data; + NMConnectivityState connectivity; + GError *error = NULL; + + connectivity = nm_manager_check_connectivity_finish (NM_MANAGER (object), + result, &error); + if (!error) + g_simple_async_result_set_op_res_gssize (simple, connectivity); + else + g_simple_async_result_take_error (simple, error); + + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +/** + * nm_client_check_connectivity_async: + * @client: an #NMClient + * @cancellable: a #GCancellable + * @callback: callback to call with the result + * @user_data: data for @callback. + * + * Asynchronously updates the network connectivity state and invokes + * @callback when complete. Contrast nm_client_get_connectivity(), + * which (immediately) returns the most recent known state without + * re-checking, and nm_client_check_connectivity(), which blocks. + */ +void +nm_client_check_connectivity_async (NMClient *client, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *simple; + GError *error = NULL; + + g_return_if_fail (NM_IS_CLIENT (client)); + + if (!_nm_client_check_nm_running (client, &error)) { + g_simple_async_report_take_gerror_in_idle (G_OBJECT (client), callback, user_data, error); + return; + } + + simple = g_simple_async_result_new (G_OBJECT (client), callback, user_data, + nm_client_check_connectivity_async); + nm_manager_check_connectivity_async (NM_CLIENT_GET_PRIVATE (client)->manager, + cancellable, check_connectivity_cb, simple); +} + +/** + * nm_client_check_connectivity_finish: + * @client: an #NMClient + * @result: the #GAsyncResult + * @error: return location for a #GError + * + * Retrieves the result of an nm_client_check_connectivity_async() + * call. + * + * Returns: the (new) current connectivity state + */ +NMConnectivityState +nm_client_check_connectivity_finish (NMClient *client, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail (NM_IS_CLIENT (client), NM_CONNECTIVITY_UNKNOWN); + g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), NM_CONNECTIVITY_UNKNOWN); + + simple = G_SIMPLE_ASYNC_RESULT (result); + + if (g_simple_async_result_propagate_error (simple, error)) + return NM_CONNECTIVITY_UNKNOWN; + return (NMConnectivityState) g_simple_async_result_get_op_res_gssize (simple); +} + + +/** + * nm_client_save_hostname: + * @client: the %NMClient + * @hostname: (allow-none): the new persistent hostname to set, or %NULL to + * clear any existing persistent hostname + * @cancellable: a #GCancellable, or %NULL + * @error: return location for #GError + * + * Requests that the machine's persistent hostname be set to the specified value + * or cleared. + * + * Returns: %TRUE if the request was successful, %FALSE if it failed + **/ +gboolean +nm_client_save_hostname (NMClient *client, + const char *hostname, + GCancellable *cancellable, + GError **error) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); + + return nm_remote_settings_save_hostname (NM_CLIENT_GET_PRIVATE (client)->settings, + hostname, cancellable, error); +} + +static void +save_hostname_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + GSimpleAsyncResult *simple = user_data; + GError *error = NULL; + + if (nm_remote_settings_save_hostname_finish (NM_REMOTE_SETTINGS (object), result, &error)) + g_simple_async_result_set_op_res_gboolean (simple, TRUE); + else + g_simple_async_result_take_error (simple, error); + + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +/** + * nm_client_save_hostname_async: + * @client: the %NMClient + * @hostname: (allow-none): the new persistent hostname to set, or %NULL to + * clear any existing persistent hostname + * @cancellable: a #GCancellable, or %NULL + * @callback: (scope async): callback to be called when the operation completes + * @user_data: (closure): caller-specific data passed to @callback + * + * Requests that the machine's persistent hostname be set to the specified value + * or cleared. + **/ +void +nm_client_save_hostname_async (NMClient *client, + const char *hostname, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *simple; + GError *error = NULL; + + g_return_if_fail (NM_IS_CLIENT (client)); + + if (!_nm_client_check_nm_running (client, &error)) { + g_simple_async_report_take_gerror_in_idle (G_OBJECT (client), callback, user_data, error); + return; + } + + simple = g_simple_async_result_new (G_OBJECT (client), callback, user_data, + nm_client_save_hostname_async); + nm_remote_settings_save_hostname_async (NM_CLIENT_GET_PRIVATE (client)->settings, + hostname, + cancellable, save_hostname_cb, simple); +} + +/** + * nm_client_save_hostname_finish: + * @client: the %NMClient + * @result: the result passed to the #GAsyncReadyCallback + * @error: return location for #GError + * + * Gets the result of an nm_client_save_hostname_async() call. + * + * Returns: %TRUE if the request was successful, %FALSE if it failed + **/ +gboolean +nm_client_save_hostname_finish (NMClient *client, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); + g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), FALSE); + + simple = G_SIMPLE_ASYNC_RESULT (result); + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + else + return g_simple_async_result_get_op_res_gboolean (simple); +} + +/****************************************************************/ +/* Devices */ +/****************************************************************/ + +/** + * nm_client_get_devices: + * @client: a #NMClient + * + * Gets all the known network devices. Use nm_device_get_type() or the + * <literal>NM_IS_DEVICE_XXXX</literal> functions to determine what kind of + * device member of the returned array is, and then you may use device-specific + * methods such as nm_device_ethernet_get_hw_address(). + * + * Returns: (transfer none) (element-type NMDevice): a #GPtrArray + * containing all the #NMDevices. The returned array is owned by the + * #NMClient object and should not be modified. + **/ +const GPtrArray * +nm_client_get_devices (NMClient *client) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), NULL); + + return nm_manager_get_devices (NM_CLIENT_GET_PRIVATE (client)->manager); +} + +/** + * nm_client_get_device_by_path: + * @client: a #NMClient + * @object_path: the object path to search for + * + * Gets a #NMDevice from a #NMClient. + * + * Returns: (transfer none): the #NMDevice for the given @object_path or %NULL if none is found. + **/ +NMDevice * +nm_client_get_device_by_path (NMClient *client, const char *object_path) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), NULL); + g_return_val_if_fail (object_path, NULL); + + return nm_manager_get_device_by_path (NM_CLIENT_GET_PRIVATE (client)->manager, object_path); +} + +/** + * nm_client_get_device_by_iface: + * @client: a #NMClient + * @iface: the interface name to search for + * + * Gets a #NMDevice from a #NMClient. + * + * Returns: (transfer none): the #NMDevice for the given @iface or %NULL if none is found. + **/ +NMDevice * +nm_client_get_device_by_iface (NMClient *client, const char *iface) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), NULL); + g_return_val_if_fail (iface, NULL); + + return nm_manager_get_device_by_iface (NM_CLIENT_GET_PRIVATE (client)->manager, iface); +} + +/****************************************************************/ +/* Active Connections */ +/****************************************************************/ + +/** + * nm_client_get_active_connections: + * @client: a #NMClient + * + * Gets the active connections. + * + * Returns: (transfer none) (element-type NMActiveConnection): a #GPtrArray + * containing all the active #NMActiveConnections. + * The returned array is owned by the client and should not be modified. + **/ +const GPtrArray * +nm_client_get_active_connections (NMClient *client) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), NULL); + + return nm_manager_get_active_connections (NM_CLIENT_GET_PRIVATE (client)->manager); +} + +/** + * nm_client_get_primary_connection: + * @client: an #NMClient + * + * Gets the #NMActiveConnection corresponding to the primary active + * network device. + * + * In particular, when there is no VPN active, or the VPN does not + * have the default route, this returns the active connection that has + * the default route. If there is a VPN active with the default route, + * then this function returns the active connection that contains the + * route to the VPN endpoint. + * + * If there is no default route, or the default route is over a + * non-NetworkManager-recognized device, this will return %NULL. + * + * Returns: (transfer none): the appropriate #NMActiveConnection, if + * any + */ +NMActiveConnection * +nm_client_get_primary_connection (NMClient *client) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), NULL); + + return nm_manager_get_primary_connection (NM_CLIENT_GET_PRIVATE (client)->manager); +} + +/** + * nm_client_get_activating_connection: + * @client: an #NMClient + * + * Gets the #NMActiveConnection corresponding to a + * currently-activating connection that is expected to become the new + * #NMClient:primary-connection upon successful activation. + * + * Returns: (transfer none): the appropriate #NMActiveConnection, if + * any. + */ +NMActiveConnection * +nm_client_get_activating_connection (NMClient *client) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), NULL); + + return nm_manager_get_activating_connection (NM_CLIENT_GET_PRIVATE (client)->manager); +} + +static void +activate_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + GSimpleAsyncResult *simple = user_data; + NMActiveConnection *ac; + GError *error = NULL; + + ac = nm_manager_activate_connection_finish (NM_MANAGER (object), result, &error); + if (ac) + g_simple_async_result_set_op_res_gpointer (simple, ac, g_object_unref); + else + g_simple_async_result_take_error (simple, error); + + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +/** + * nm_client_activate_connection_async: + * @client: a #NMClient + * @connection: (allow-none): an #NMConnection + * @device: (allow-none): the #NMDevice + * @specific_object: (allow-none): the object path of a connection-type-specific + * object this activation should use. This parameter is currently ignored for + * wired and mobile broadband connections, and the value of %NULL should be used + * (ie, no specific object). For Wi-Fi or WiMAX connections, pass the object + * path of a #NMAccessPoint or #NMWimaxNsp owned by @device, which you can + * get using nm_object_get_path(), and which will be used to complete the + * details of the newly added connection. + * @cancellable: a #GCancellable, or %NULL + * @callback: callback to be called when the activation has started + * @user_data: caller-specific data passed to @callback + * + * Asynchronously starts a connection to a particular network using the + * configuration settings from @connection and the network device @device. + * Certain connection types also take a "specific object" which is the object + * path of a connection- specific object, like an #NMAccessPoint for Wi-Fi + * connections, or an #NMWimaxNsp for WiMAX connections, to which you wish to + * connect. If the specific object is not given, NetworkManager can, in some + * cases, automatically determine which network to connect to given the settings + * in @connection. + * + * If @connection is not given for a device-based activation, NetworkManager + * picks the best available connection for the device and activates it. + * + * Note that the callback is invoked when NetworkManager has started activating + * the new connection, not when it finishes. You can used the returned + * #NMActiveConnection object (in particular, #NMActiveConnection:state) to + * track the activation to its completion. + **/ +void +nm_client_activate_connection_async (NMClient *client, + NMConnection *connection, + NMDevice *device, + const char *specific_object, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *simple; + GError *error = NULL; + + g_return_if_fail (NM_IS_CLIENT (client)); + if (device) + g_return_if_fail (NM_IS_DEVICE (device)); + if (connection) + g_return_if_fail (NM_IS_CONNECTION (connection)); + + if (!_nm_client_check_nm_running (client, &error)) { + g_simple_async_report_take_gerror_in_idle (G_OBJECT (client), callback, user_data, error); + return; + } + + simple = g_simple_async_result_new (G_OBJECT (client), callback, user_data, + nm_client_activate_connection_async); + nm_manager_activate_connection_async (NM_CLIENT_GET_PRIVATE (client)->manager, + connection, device, specific_object, + cancellable, activate_cb, simple); +} + +/** + * nm_client_activate_connection_finish: + * @client: an #NMClient + * @result: the result passed to the #GAsyncReadyCallback + * @error: location for a #GError, or %NULL + * + * Gets the result of a call to nm_client_activate_connection_async(). + * + * Returns: (transfer full): the new #NMActiveConnection on success, %NULL on + * failure, in which case @error will be set. + **/ +NMActiveConnection * +nm_client_activate_connection_finish (NMClient *client, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail (NM_IS_CLIENT (client), NULL); + g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), NULL); + + simple = G_SIMPLE_ASYNC_RESULT (result); + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + else + return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple)); +} + +static void +add_activate_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + GSimpleAsyncResult *simple = user_data; + NMActiveConnection *ac; + GError *error = NULL; + + ac = nm_manager_add_and_activate_connection_finish (NM_MANAGER (object), result, &error); + if (ac) + g_simple_async_result_set_op_res_gpointer (simple, ac, g_object_unref); + else + g_simple_async_result_take_error (simple, error); + + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +/** + * nm_client_add_and_activate_connection_async: + * @client: a #NMClient + * @partial: (allow-none): an #NMConnection to add; the connection may be + * partially filled (or even %NULL) and will be completed by NetworkManager + * using the given @device and @specific_object before being added + * @device: the #NMDevice + * @specific_object: (allow-none): the object path of a connection-type-specific + * object this activation should use. This parameter is currently ignored for + * wired and mobile broadband connections, and the value of %NULL should be used + * (ie, no specific object). For Wi-Fi or WiMAX connections, pass the object + * path of a #NMAccessPoint or #NMWimaxNsp owned by @device, which you can + * get using nm_object_get_path(), and which will be used to complete the + * details of the newly added connection. + * @cancellable: a #GCancellable, or %NULL + * @callback: callback to be called when the activation has started + * @user_data: caller-specific data passed to @callback + * + * Adds a new connection using the given details (if any) as a template, + * automatically filling in missing settings with the capabilities of the given + * device and specific object. The new connection is then asynchronously + * activated as with nm_client_activate_connection_async(). Cannot be used for + * VPN connections at this time. + * + * Note that the callback is invoked when NetworkManager has started activating + * the new connection, not when it finishes. You can used the returned + * #NMActiveConnection object (in particular, #NMActiveConnection:state) to + * track the activation to its completion. + **/ +void +nm_client_add_and_activate_connection_async (NMClient *client, + NMConnection *partial, + NMDevice *device, + const char *specific_object, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *simple; + GError *error = NULL; + + g_return_if_fail (NM_IS_CLIENT (client)); + g_return_if_fail (NM_IS_DEVICE (device)); + if (partial) + g_return_if_fail (NM_IS_CONNECTION (partial)); + + if (!_nm_client_check_nm_running (client, &error)) { + g_simple_async_report_take_gerror_in_idle (G_OBJECT (client), callback, user_data, error); + return; + } + + simple = g_simple_async_result_new (G_OBJECT (client), callback, user_data, + nm_client_add_and_activate_connection_async); + nm_manager_add_and_activate_connection_async (NM_CLIENT_GET_PRIVATE (client)->manager, + partial, device, specific_object, + cancellable, add_activate_cb, simple); +} + +/** + * nm_client_add_and_activate_connection_finish: + * @client: an #NMClient + * @result: the result passed to the #GAsyncReadyCallback + * @error: location for a #GError, or %NULL + * + * Gets the result of a call to nm_client_add_and_activate_connection_async(). + * + * You can call nm_active_connection_get_connection() on the returned + * #NMActiveConnection to find the path of the created #NMConnection. + * + * Returns: (transfer full): the new #NMActiveConnection on success, %NULL on + * failure, in which case @error will be set. + **/ +NMActiveConnection * +nm_client_add_and_activate_connection_finish (NMClient *client, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail (NM_IS_CLIENT (client), NULL); + g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), NULL); + + simple = G_SIMPLE_ASYNC_RESULT (result); + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + else + return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple)); +} + +/** + * nm_client_deactivate_connection: + * @client: a #NMClient + * @active: the #NMActiveConnection to deactivate + * @cancellable: a #GCancellable, or %NULL + * @error: location for a #GError, or %NULL + * + * Deactivates an active #NMActiveConnection. + * + * Returns: success or failure + **/ +gboolean +nm_client_deactivate_connection (NMClient *client, + NMActiveConnection *active, + GCancellable *cancellable, + GError **error) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); + g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (active), FALSE); + + if (!_nm_client_check_nm_running (client, NULL)) + return TRUE; + + return nm_manager_deactivate_connection (NM_CLIENT_GET_PRIVATE (client)->manager, + active, cancellable, error); +} + +static void +deactivated_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + GSimpleAsyncResult *simple = user_data; + GError *error = NULL; + + if (nm_manager_deactivate_connection_finish (NM_MANAGER (object), result, &error)) + g_simple_async_result_set_op_res_gboolean (simple, TRUE); + else + g_simple_async_result_take_error (simple, error); + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +/** + * nm_client_deactivate_connection_async: + * @client: a #NMClient + * @active: the #NMActiveConnection to deactivate + * @cancellable: a #GCancellable, or %NULL + * @callback: callback to be called when the deactivation has completed + * @user_data: caller-specific data passed to @callback + * + * Asynchronously deactivates an active #NMActiveConnection. + **/ +void +nm_client_deactivate_connection_async (NMClient *client, + NMActiveConnection *active, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *simple; + + g_return_if_fail (NM_IS_CLIENT (client)); + g_return_if_fail (NM_IS_ACTIVE_CONNECTION (active)); + + simple = g_simple_async_result_new (G_OBJECT (client), callback, user_data, + nm_client_deactivate_connection_async); + + if (!_nm_client_check_nm_running (client, NULL)) { + g_simple_async_result_set_op_res_gboolean (simple, TRUE); + g_simple_async_result_complete_in_idle (simple); + g_object_unref (simple); + return; + } + + nm_manager_deactivate_connection_async (NM_CLIENT_GET_PRIVATE (client)->manager, + active, + cancellable, deactivated_cb, simple); +} + +/** + * nm_client_deactivate_connection_finish: + * @client: a #NMClient + * @result: the result passed to the #GAsyncReadyCallback + * @error: location for a #GError, or %NULL + * + * Gets the result of a call to nm_client_deactivate_connection_async(). + * + * Returns: success or failure + **/ +gboolean +nm_client_deactivate_connection_finish (NMClient *client, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); + g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), FALSE); + + simple = G_SIMPLE_ASYNC_RESULT (result); + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + else + return g_simple_async_result_get_op_res_gboolean (simple); +} + +/****************************************************************/ +/* Connections */ +/****************************************************************/ + +/** + * nm_client_get_connections: + * @client: the %NMClient + * + * Returns: (transfer none) (element-type NMRemoteConnection): an array + * containing all connections provided by the remote settings service. The + * returned array is owned by the #NMClient object and should not be modified. + **/ +const GPtrArray * +nm_client_get_connections (NMClient *client) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), NULL); + + return nm_remote_settings_get_connections (NM_CLIENT_GET_PRIVATE (client)->settings); +} + +/** + * nm_client_get_connection_by_id: + * @client: the %NMClient + * @id: the id of the remote connection + * + * Returns the first matching %NMRemoteConnection matching a given @id. + * + * Returns: (transfer none): the remote connection object on success, or %NULL if no + * matching object was found. + **/ +NMRemoteConnection * +nm_client_get_connection_by_id (NMClient *client, const char *id) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), NULL); + g_return_val_if_fail (id != NULL, NULL); + + return nm_remote_settings_get_connection_by_id (NM_CLIENT_GET_PRIVATE (client)->settings, id); +} + +/** + * nm_client_get_connection_by_path: + * @client: the %NMClient + * @path: the D-Bus object path of the remote connection + * + * Returns the %NMRemoteConnection representing the connection at @path. + * + * Returns: (transfer none): the remote connection object on success, or %NULL if the object was + * not known + **/ +NMRemoteConnection * +nm_client_get_connection_by_path (NMClient *client, const char *path) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), NULL); + g_return_val_if_fail (path != NULL, NULL); + + return nm_remote_settings_get_connection_by_path (NM_CLIENT_GET_PRIVATE (client)->settings, path); +} + +/** + * nm_client_get_connection_by_uuid: + * @client: the %NMClient + * @uuid: the UUID of the remote connection + * + * Returns the %NMRemoteConnection identified by @uuid. + * + * Returns: (transfer none): the remote connection object on success, or %NULL if the object was + * not known + **/ +NMRemoteConnection * +nm_client_get_connection_by_uuid (NMClient *client, const char *uuid) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), NULL); + g_return_val_if_fail (uuid != NULL, NULL); + + return nm_remote_settings_get_connection_by_uuid (NM_CLIENT_GET_PRIVATE (client)->settings, uuid); +} + +static void +add_connection_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + GSimpleAsyncResult *simple = user_data; + NMRemoteConnection *conn; + GError *error = NULL; + + conn = nm_remote_settings_add_connection_finish (NM_REMOTE_SETTINGS (object), result, &error); + if (conn) + g_simple_async_result_set_op_res_gpointer (simple, conn, g_object_unref); + else + g_simple_async_result_take_error (simple, error); + + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +/** + * nm_client_add_connection_async: + * @client: the %NMClient + * @connection: the connection to add. Note that this object's settings will be + * added, not the object itself + * @save_to_disk: whether to immediately save the connection to disk + * @cancellable: a #GCancellable, or %NULL + * @callback: (scope async): callback to be called when the add operation completes + * @user_data: (closure): caller-specific data passed to @callback + * + * Requests that the remote settings service add the given settings to a new + * connection. If @save_to_disk is %TRUE, the connection is immediately written + * to disk; otherwise it is initially only stored in memory, but may be saved + * later by calling the connection's nm_remote_connection_commit_changes() + * method. + * + * @connection is untouched by this function and only serves as a template of + * the settings to add. The #NMRemoteConnection object that represents what + * NetworkManager actually added is returned to @callback when the addition + * operation is complete. + * + * Note that the #NMRemoteConnection returned in @callback may not contain + * identical settings to @connection as NetworkManager may perform automatic + * completion and/or normalization of connection properties. + **/ +void +nm_client_add_connection_async (NMClient *client, + NMConnection *connection, + gboolean save_to_disk, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *simple; + GError *error = NULL; + + g_return_if_fail (NM_IS_CLIENT (client)); + g_return_if_fail (NM_IS_CONNECTION (connection)); + + if (!_nm_client_check_nm_running (client, &error)) { + g_simple_async_report_take_gerror_in_idle (G_OBJECT (client), callback, user_data, error); + return; + } + + simple = g_simple_async_result_new (G_OBJECT (client), callback, user_data, + nm_client_deactivate_connection_async); + nm_remote_settings_add_connection_async (NM_CLIENT_GET_PRIVATE (client)->settings, + connection, save_to_disk, + cancellable, add_connection_cb, simple); +} + +/** + * nm_client_add_connection_finish: + * @client: an #NMClient + * @result: the result passed to the #GAsyncReadyCallback + * @error: location for a #GError, or %NULL + * + * Gets the result of a call to nm_client_add_connection_async(). + * + * Returns: (transfer full): the new #NMRemoteConnection on success, %NULL on + * failure, in which case @error will be set. + **/ +NMRemoteConnection * +nm_client_add_connection_finish (NMClient *client, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail (NM_IS_CLIENT (client), NULL); + g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), NULL); + + simple = G_SIMPLE_ASYNC_RESULT (result); + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + else + return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple)); +} + +/** + * nm_client_load_connections: + * @client: the %NMClient + * @filenames: %NULL-terminated array of filenames to load + * @failures: (out) (transfer full): on return, a %NULL-terminated array of + * filenames that failed to load + * @cancellable: a #GCancellable, or %NULL + * @error: return location for #GError + * + * Requests that the remote settings service load or reload the given files, + * adding or updating the connections described within. + * + * The changes to the indicated files will not yet be reflected in + * @client's connections array when the function returns. + * + * If all of the indicated files were successfully loaded, the + * function will return %TRUE, and @failures will be set to %NULL. If + * NetworkManager tried to load the files, but some (or all) failed, + * then @failures will be set to a %NULL-terminated array of the + * filenames that failed to load. + * + * Returns: %TRUE if NetworkManager at least tried to load @filenames, + * %FALSE if an error occurred (eg, permission denied). + **/ +gboolean +nm_client_load_connections (NMClient *client, + char **filenames, + char ***failures, + GCancellable *cancellable, + GError **error) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); + g_return_val_if_fail (filenames != NULL, FALSE); + + if (!_nm_client_check_nm_running (client, error)) + return FALSE; + + return nm_remote_settings_load_connections (NM_CLIENT_GET_PRIVATE (client)->settings, + filenames, failures, + cancellable, error); +} + +static void +load_connections_cb (GObject *object, GAsyncResult *result, gpointer user_data) +{ + GSimpleAsyncResult *simple = user_data; + GError *error = NULL; + char **failures = NULL; + + if (nm_remote_settings_load_connections_finish (NM_REMOTE_SETTINGS (object), + &failures, result, &error)) + g_simple_async_result_set_op_res_gpointer (simple, failures, (GDestroyNotify) g_strfreev); + else + g_simple_async_result_take_error (simple, error); + + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +/** + * nm_client_load_connections_async: + * @client: the %NMClient + * @filenames: %NULL-terminated array of filenames to load + * @cancellable: a #GCancellable, or %NULL + * @callback: (scope async): callback to be called when the operation completes + * @user_data: (closure): caller-specific data passed to @callback + * + * Requests that the remote settings service asynchronously load or reload the + * given files, adding or updating the connections described within. + * + * See nm_client_load_connections() for more details. + **/ +void +nm_client_load_connections_async (NMClient *client, + char **filenames, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *simple; + GError *error = NULL; + + g_return_if_fail (NM_IS_CLIENT (client)); + g_return_if_fail (filenames != NULL); + + if (!_nm_client_check_nm_running (client, &error)) { + g_simple_async_report_take_gerror_in_idle (G_OBJECT (client), callback, user_data, error); + return; + } + + simple = g_simple_async_result_new (G_OBJECT (client), callback, user_data, + nm_client_load_connections_async); + nm_remote_settings_load_connections_async (NM_CLIENT_GET_PRIVATE (client)->settings, + filenames, + cancellable, load_connections_cb, simple); +} + +/** + * nm_client_load_connections_finish: + * @client: the %NMClient + * @failures: (out) (transfer full): on return, a %NULL-terminated array of + * filenames that failed to load + * @result: the result passed to the #GAsyncReadyCallback + * @error: location for a #GError, or %NULL + * + * Gets the result of an nm_client_load_connections_async() call. + + * See nm_client_load_connections() for more details. + * + * Returns: %TRUE if NetworkManager at least tried to load @filenames, + * %FALSE if an error occurred (eg, permission denied). + **/ +gboolean +nm_client_load_connections_finish (NMClient *client, + char ***failures, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); + g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), FALSE); + + simple = G_SIMPLE_ASYNC_RESULT (result); + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + else { + if (failures) + *failures = g_strdupv (g_simple_async_result_get_op_res_gpointer (simple)); + return TRUE; + } +} + +/** + * nm_client_reload_connections: + * @client: the #NMClient + * @cancellable: a #GCancellable, or %NULL + * @error: return location for #GError + * + * Requests that the remote settings service reload all connection + * files from disk, adding, updating, and removing connections until + * the in-memory state matches the on-disk state. + * + * Return value: %TRUE on success, %FALSE on failure + **/ +gboolean +nm_client_reload_connections (NMClient *client, + GCancellable *cancellable, + GError **error) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); + + if (!_nm_client_check_nm_running (client, error)) + return FALSE; + + return nm_remote_settings_reload_connections (NM_CLIENT_GET_PRIVATE (client)->settings, + cancellable, error); +} + +static void +reload_connections_cb (GObject *object, GAsyncResult *result, gpointer user_data) +{ + GSimpleAsyncResult *simple = user_data; + GError *error = NULL; + + if (nm_remote_settings_reload_connections_finish (NM_REMOTE_SETTINGS (object), + result, &error)) + g_simple_async_result_set_op_res_gboolean (simple, TRUE); + else + g_simple_async_result_take_error (simple, error); + + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +/** + * nm_client_reload_connections_async: + * @client: the #NMClient + * @cancellable: a #GCancellable, or %NULL + * @callback: (scope async): callback to be called when the reload operation completes + * @user_data: (closure): caller-specific data passed to @callback + * + * Requests that the remote settings service begin reloading all connection + * files from disk, adding, updating, and removing connections until the + * in-memory state matches the on-disk state. + **/ +void +nm_client_reload_connections_async (NMClient *client, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *simple; + GError *error = NULL; + + g_return_if_fail (NM_IS_CLIENT (client)); + + if (!_nm_client_check_nm_running (client, &error)) { + g_simple_async_report_take_gerror_in_idle (G_OBJECT (client), callback, user_data, error); + return; + } + + simple = g_simple_async_result_new (G_OBJECT (client), callback, user_data, + nm_client_reload_connections_async); + nm_remote_settings_reload_connections_async (NM_CLIENT_GET_PRIVATE (client)->settings, + cancellable, reload_connections_cb, simple); +} + +/** + * nm_client_reload_connections_finish: + * @client: the #NMClient + * @result: the result passed to the #GAsyncReadyCallback + * @error: return location for #GError + * + * Gets the result of an nm_client_reload_connections_async() call. + * + * Return value: %TRUE on success, %FALSE on failure + **/ +gboolean +nm_client_reload_connections_finish (NMClient *client, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); + g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), FALSE); + + simple = G_SIMPLE_ASYNC_RESULT (result); + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + else + return g_simple_async_result_get_op_res_gboolean (simple); +} + +/****************************************************************/ + +/** + * nm_client_new: + * @cancellable: a #GCancellable, or %NULL + * @error: location for a #GError, or %NULL + * + * Creates a new #NMClient. + * + * Note that this will do blocking D-Bus calls to initialize the + * client. You can use nm_client_new_async() if you want to avoid + * that. + * + * Returns: a new #NMClient or NULL on an error + **/ +NMClient * +nm_client_new (GCancellable *cancellable, + GError **error) +{ + return g_initable_new (NM_TYPE_CLIENT, cancellable, error, + NULL); +} + +static void +client_inited (GObject *source, GAsyncResult *result, gpointer user_data) +{ + GSimpleAsyncResult *simple = user_data; + GError *error = NULL; + + if (!g_async_initable_new_finish (G_ASYNC_INITABLE (source), result, &error)) + g_simple_async_result_take_error (simple, error); + else + g_simple_async_result_set_op_res_gpointer (simple, source, g_object_unref); + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +/** + * nm_client_new_async: + * @cancellable: a #GCancellable, or %NULL + * @callback: callback to call when the client is created + * @user_data: data for @callback + * + * Creates a new #NMClient and begins asynchronously initializing it. + * @callback will be called when it is done; use + * nm_client_new_finish() to get the result. Note that on an error, + * the callback can be invoked with two first parameters as NULL. + **/ +void +nm_client_new_async (GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *simple; + + simple = g_simple_async_result_new (NULL, callback, user_data, nm_client_new_async); + + g_async_initable_new_async (NM_TYPE_CLIENT, G_PRIORITY_DEFAULT, + cancellable, client_inited, simple, + NULL); +} + +/** + * nm_client_new_finish: + * @result: a #GAsyncResult + * @error: location for a #GError, or %NULL + * + * Gets the result of an nm_client_new_async() call. + * + * Returns: a new #NMClient, or %NULL on error + **/ +NMClient * +nm_client_new_finish (GAsyncResult *result, GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL, nm_client_new_async), NULL); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + simple = G_SIMPLE_ASYNC_RESULT (result); + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + else + return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple)); +} + +static void +subobject_notify (GObject *object, + GParamSpec *pspec, + gpointer client) +{ + if (!g_str_has_suffix (pspec->name, "-internal")) + g_object_notify (client, pspec->name); +} + +static void +manager_device_added (NMManager *manager, + NMDevice *device, + gpointer client) +{ + g_signal_emit (client, signals[DEVICE_ADDED], 0, device); +} +static void +manager_device_removed (NMManager *manager, + NMDevice *device, + gpointer client) +{ + g_signal_emit (client, signals[DEVICE_REMOVED], 0, device); +} + +static void +manager_permission_changed (NMManager *manager, + NMClientPermission permission, + NMClientPermissionResult result, + gpointer client) +{ + g_signal_emit (client, signals[PERMISSION_CHANGED], 0, permission, result); +} + +static void +settings_connection_added (NMRemoteSettings *manager, + NMRemoteConnection *connection, + gpointer client) +{ + g_signal_emit (client, signals[CONNECTION_ADDED], 0, connection); +} +static void +settings_connection_removed (NMRemoteSettings *manager, + NMRemoteConnection *connection, + gpointer client) +{ + g_signal_emit (client, signals[CONNECTION_REMOVED], 0, connection); +} + +static void +constructed (GObject *object) +{ + NMClient *client = NM_CLIENT (object); + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client); + + priv->manager = g_object_new (NM_TYPE_MANAGER, + NM_OBJECT_PATH, NM_DBUS_PATH, + NULL); + g_signal_connect (priv->manager, "notify", + G_CALLBACK (subobject_notify), client); + g_signal_connect (priv->manager, "device-added", + G_CALLBACK (manager_device_added), client); + g_signal_connect (priv->manager, "device-removed", + G_CALLBACK (manager_device_removed), client); + g_signal_connect (priv->manager, "permission-changed", + G_CALLBACK (manager_permission_changed), client); + + priv->settings = g_object_new (NM_TYPE_REMOTE_SETTINGS, + NM_OBJECT_PATH, NM_DBUS_PATH_SETTINGS, + NULL); + g_signal_connect (priv->settings, "notify", + G_CALLBACK (subobject_notify), client); + g_signal_connect (priv->settings, "connection-added", + G_CALLBACK (settings_connection_added), client); + g_signal_connect (priv->settings, "connection-removed", + G_CALLBACK (settings_connection_removed), client); + + G_OBJECT_CLASS (nm_client_parent_class)->constructed (object); +} + +static gboolean +init_sync (GInitable *initable, GCancellable *cancellable, GError **error) +{ + NMClient *client = NM_CLIENT (initable); + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client); + + if (!g_initable_init (G_INITABLE (priv->manager), cancellable, error)) + return FALSE; + if (!g_initable_init (G_INITABLE (priv->settings), cancellable, error)) + return FALSE; + + return TRUE; +} + +typedef struct { + NMClient *client; + GCancellable *cancellable; + GSimpleAsyncResult *result; + gboolean manager_inited; + gboolean settings_inited; +} NMClientInitData; + +static void +init_async_complete (NMClientInitData *init_data) +{ + g_simple_async_result_complete (init_data->result); + g_object_unref (init_data->result); + g_clear_object (&init_data->cancellable); + g_slice_free (NMClientInitData, init_data); +} + +static void +init_async_inited_manager (GObject *object, GAsyncResult *result, gpointer user_data) +{ + NMClientInitData *init_data = user_data; + GError *error = NULL; + + if (!g_async_initable_init_finish (G_ASYNC_INITABLE (object), result, &error)) + g_simple_async_result_take_error (init_data->result, error); + + init_data->manager_inited = TRUE; + if (init_data->settings_inited) + init_async_complete (init_data); +} + +static void +init_async_inited_settings (GObject *object, GAsyncResult *result, gpointer user_data) +{ + NMClientInitData *init_data = user_data; + GError *error = NULL; + + if (!g_async_initable_init_finish (G_ASYNC_INITABLE (object), result, &error)) + g_simple_async_result_take_error (init_data->result, error); + + init_data->settings_inited = TRUE; + if (init_data->manager_inited) + init_async_complete (init_data); +} + +static void +init_async (GAsyncInitable *initable, int io_priority, + GCancellable *cancellable, GAsyncReadyCallback callback, + gpointer user_data) +{ + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (initable); + NMClientInitData *init_data; + + init_data = g_slice_new0 (NMClientInitData); + init_data->client = NM_CLIENT (initable); + init_data->cancellable = cancellable ? g_object_ref (cancellable) : NULL; + init_data->result = g_simple_async_result_new (G_OBJECT (initable), callback, + user_data, init_async); + g_simple_async_result_set_op_res_gboolean (init_data->result, TRUE); + + g_async_initable_init_async (G_ASYNC_INITABLE (priv->manager), + G_PRIORITY_DEFAULT, init_data->cancellable, + init_async_inited_manager, init_data); + g_async_initable_init_async (G_ASYNC_INITABLE (priv->settings), + G_PRIORITY_DEFAULT, init_data->cancellable, + init_async_inited_settings, init_data); +} + +static gboolean +init_finish (GAsyncInitable *initable, GAsyncResult *result, GError **error) +{ + GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); + + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + else + return TRUE; +} + +static void +dispose (GObject *object) +{ + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (object); + + if (priv->manager) { + g_signal_handlers_disconnect_by_data (priv->manager, object); + g_clear_object (&priv->manager); + } + if (priv->settings) { + g_signal_handlers_disconnect_by_data (priv->settings, object); + g_clear_object (&priv->settings); + } + + G_OBJECT_CLASS (nm_client_parent_class)->dispose (object); +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + switch (prop_id) { + case PROP_NETWORKING_ENABLED: + case PROP_WIRELESS_ENABLED: + case PROP_WWAN_ENABLED: + case PROP_WIMAX_ENABLED: + g_object_set_property (G_OBJECT (NM_CLIENT_GET_PRIVATE (object)->manager), + pspec->name, value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + switch (prop_id) { + case PROP_VERSION: + case PROP_STATE: + case PROP_STARTUP: + case PROP_NM_RUNNING: + case PROP_NETWORKING_ENABLED: + case PROP_WIRELESS_ENABLED: + case PROP_WIRELESS_HARDWARE_ENABLED: + case PROP_WWAN_ENABLED: + case PROP_WWAN_HARDWARE_ENABLED: + case PROP_WIMAX_ENABLED: + case PROP_WIMAX_HARDWARE_ENABLED: + case PROP_ACTIVE_CONNECTIONS: + case PROP_CONNECTIVITY: + case PROP_PRIMARY_CONNECTION: + case PROP_ACTIVATING_CONNECTION: + case PROP_DEVICES: + g_object_get_property (G_OBJECT (NM_CLIENT_GET_PRIVATE (object)->manager), + pspec->name, value); + break; + case PROP_CONNECTIONS: + case PROP_HOSTNAME: + case PROP_CAN_MODIFY: + g_object_get_property (G_OBJECT (NM_CLIENT_GET_PRIVATE (object)->settings), + pspec->name, value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_client_class_init (NMClientClass *client_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (client_class); + + g_type_class_add_private (client_class, sizeof (NMClientPrivate)); + + /* virtual methods */ + object_class->constructed = constructed; + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->dispose = dispose; + + /* properties */ + + /** + * NMClient:version: + * + * The NetworkManager version. + **/ + g_object_class_install_property + (object_class, PROP_VERSION, + g_param_spec_string (NM_CLIENT_VERSION, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMClient:state: + * + * The current daemon state. + **/ + g_object_class_install_property + (object_class, PROP_STATE, + g_param_spec_enum (NM_CLIENT_STATE, "", "", + NM_TYPE_STATE, + NM_STATE_UNKNOWN, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMClient:startup: + * + * Whether the daemon is still starting up. + **/ + g_object_class_install_property + (object_class, PROP_STARTUP, + g_param_spec_boolean (NM_CLIENT_STARTUP, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMClient:nm-running: + * + * Whether the daemon is running. + **/ + g_object_class_install_property + (object_class, PROP_NM_RUNNING, + g_param_spec_boolean (NM_CLIENT_NM_RUNNING, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMClient:networking-enabled: + * + * Whether networking is enabled. + **/ + g_object_class_install_property + (object_class, PROP_NETWORKING_ENABLED, + g_param_spec_boolean (NM_CLIENT_NETWORKING_ENABLED, "", "", + TRUE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMClient:wireless-enabled: + * + * Whether wireless is enabled. + **/ + g_object_class_install_property + (object_class, PROP_WIRELESS_ENABLED, + g_param_spec_boolean (NM_CLIENT_WIRELESS_ENABLED, "", "", + FALSE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMClient:wireless-hardware-enabled: + * + * Whether the wireless hardware is enabled. + **/ + g_object_class_install_property + (object_class, PROP_WIRELESS_HARDWARE_ENABLED, + g_param_spec_boolean (NM_CLIENT_WIRELESS_HARDWARE_ENABLED, "", "", + TRUE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMClient:wwan-enabled: + * + * Whether WWAN functionality is enabled. + **/ + g_object_class_install_property + (object_class, PROP_WWAN_ENABLED, + g_param_spec_boolean (NM_CLIENT_WWAN_ENABLED, "", "", + FALSE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMClient:wwan-hardware-enabled: + * + * Whether the WWAN hardware is enabled. + **/ + g_object_class_install_property + (object_class, PROP_WWAN_HARDWARE_ENABLED, + g_param_spec_boolean (NM_CLIENT_WWAN_HARDWARE_ENABLED, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMClient:wimax-enabled: + * + * Whether WiMAX functionality is enabled. + **/ + g_object_class_install_property + (object_class, PROP_WIMAX_ENABLED, + g_param_spec_boolean (NM_CLIENT_WIMAX_ENABLED, "", "", + FALSE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMClient:wimax-hardware-enabled: + * + * Whether the WiMAX hardware is enabled. + **/ + g_object_class_install_property + (object_class, PROP_WIMAX_HARDWARE_ENABLED, + g_param_spec_boolean (NM_CLIENT_WIMAX_HARDWARE_ENABLED, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMClient:active-connections: + * + * The active connections. + * + * Element-type: NMActiveConnection + **/ + g_object_class_install_property + (object_class, PROP_ACTIVE_CONNECTIONS, + g_param_spec_boxed (NM_CLIENT_ACTIVE_CONNECTIONS, "", "", + G_TYPE_PTR_ARRAY, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMClient:connectivity: + * + * The network connectivity state. + */ + g_object_class_install_property + (object_class, PROP_CONNECTIVITY, + g_param_spec_enum (NM_CLIENT_CONNECTIVITY, "", "", + NM_TYPE_CONNECTIVITY_STATE, + NM_CONNECTIVITY_UNKNOWN, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMClient:primary-connection: + * + * The #NMActiveConnection of the device with the default route; + * see nm_client_get_primary_connection() for more details. + **/ + g_object_class_install_property + (object_class, PROP_PRIMARY_CONNECTION, + g_param_spec_object (NM_CLIENT_PRIMARY_CONNECTION, "", "", + NM_TYPE_ACTIVE_CONNECTION, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMClient:activating-connection: + * + * The #NMActiveConnection of the activating connection that is + * likely to become the new #NMClient:primary-connection. + **/ + g_object_class_install_property + (object_class, PROP_ACTIVATING_CONNECTION, + g_param_spec_object (NM_CLIENT_ACTIVATING_CONNECTION, "", "", + NM_TYPE_ACTIVE_CONNECTION, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMClient:devices: + * + * List of known network devices. + * + * Element-type: NMDevice + **/ + g_object_class_install_property + (object_class, PROP_DEVICES, + g_param_spec_boxed (NM_CLIENT_DEVICES, "", "", + G_TYPE_PTR_ARRAY, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMClient:connections: + * + * The list of configured connections that are available to the user. (Note + * that this differs from the underlying D-Bus property, which may also + * contain the object paths of connections that the user does not have + * permission to read the details of.) + * + * Element-type: NMRemoteConnection + */ + g_object_class_install_property + (object_class, PROP_CONNECTIONS, + g_param_spec_boxed (NM_CLIENT_CONNECTIONS, "", "", + G_TYPE_PTR_ARRAY, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMClient:hostname: + * + * The machine hostname stored in persistent configuration. This can be + * modified by calling nm_client_save_hostname(). + */ + g_object_class_install_property + (object_class, PROP_HOSTNAME, + g_param_spec_string (NM_CLIENT_HOSTNAME, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMClient:can-modify: + * + * If %TRUE, adding and modifying connections is supported. + */ + g_object_class_install_property + (object_class, PROP_CAN_MODIFY, + g_param_spec_boolean (NM_CLIENT_CAN_MODIFY, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /* signals */ + + /** + * NMClient::device-added: + * @client: the client that received the signal + * @device: (type NMDevice): the new device + * + * Notifies that a #NMDevice is added. + **/ + signals[DEVICE_ADDED] = + g_signal_new (NM_CLIENT_DEVICE_ADDED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMClientClass, device_added), + NULL, NULL, NULL, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); + + /** + * NMClient::device-removed: + * @client: the client that received the signal + * @device: (type NMDevice): the removed device + * + * Notifies that a #NMDevice is removed. + **/ + signals[DEVICE_REMOVED] = + g_signal_new (NM_CLIENT_DEVICE_REMOVED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMClientClass, device_removed), + NULL, NULL, NULL, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); + + /** + * NMClient::permission-changed: + * @client: the client that received the signal + * @permission: a permission from #NMClientPermission + * @result: the permission's result, one of #NMClientPermissionResult + * + * Notifies that a permission has changed + **/ + signals[PERMISSION_CHANGED] = + g_signal_new (NM_CLIENT_PERMISSION_CHANGED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); + /** + * NMClient::connection-added: + * @client: the settings object that received the signal + * @connection: the new connection + * + * Notifies that a #NMConnection has been added. + **/ + signals[CONNECTION_ADDED] = + g_signal_new (NM_CLIENT_CONNECTION_ADDED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMClientClass, connection_added), + NULL, NULL, NULL, + G_TYPE_NONE, 1, + NM_TYPE_REMOTE_CONNECTION); + + /** + * NMClient::connection-removed: + * @client: the settings object that received the signal + * @connection: the removed connection + * + * Notifies that a #NMConnection has been removed. + **/ + signals[CONNECTION_REMOVED] = + g_signal_new (NM_CLIENT_CONNECTION_REMOVED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMClientClass, connection_removed), + NULL, NULL, NULL, + G_TYPE_NONE, 1, + NM_TYPE_REMOTE_CONNECTION); +} + +static void +nm_client_initable_iface_init (GInitableIface *iface) +{ + iface->init = init_sync; +} + +static void +nm_client_async_initable_iface_init (GAsyncInitableIface *iface) +{ + iface->init_async = init_async; + iface->init_finish = init_finish; +} diff --git a/libnm/nm-client.h b/libnm/nm-client.h new file mode 100644 index 00000000..619ad858 --- /dev/null +++ b/libnm/nm-client.h @@ -0,0 +1,341 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2007 - 2008 Novell, Inc. + * Copyright 2007 - 2014 Red Hat, Inc. + */ + +#ifndef __NM_CLIENT_H__ +#define __NM_CLIENT_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include <nm-types.h> + +G_BEGIN_DECLS + +#define NM_TYPE_CLIENT (nm_client_get_type ()) +#define NM_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_CLIENT, NMClient)) +#define NM_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_CLIENT, NMClientClass)) +#define NM_IS_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_CLIENT)) +#define NM_IS_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_CLIENT)) +#define NM_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_CLIENT, NMClientClass)) + +#define NM_CLIENT_VERSION "version" +#define NM_CLIENT_STATE "state" +#define NM_CLIENT_STARTUP "startup" +#define NM_CLIENT_NM_RUNNING "nm-running" +#define NM_CLIENT_NETWORKING_ENABLED "networking-enabled" +#define NM_CLIENT_WIRELESS_ENABLED "wireless-enabled" +#define NM_CLIENT_WIRELESS_HARDWARE_ENABLED "wireless-hardware-enabled" +#define NM_CLIENT_WWAN_ENABLED "wwan-enabled" +#define NM_CLIENT_WWAN_HARDWARE_ENABLED "wwan-hardware-enabled" +#define NM_CLIENT_WIMAX_ENABLED "wimax-enabled" +#define NM_CLIENT_WIMAX_HARDWARE_ENABLED "wimax-hardware-enabled" +#define NM_CLIENT_ACTIVE_CONNECTIONS "active-connections" +#define NM_CLIENT_CONNECTIVITY "connectivity" +#define NM_CLIENT_PRIMARY_CONNECTION "primary-connection" +#define NM_CLIENT_ACTIVATING_CONNECTION "activating-connection" +#define NM_CLIENT_DEVICES "devices" +#define NM_CLIENT_CONNECTIONS "connections" +#define NM_CLIENT_HOSTNAME "hostname" +#define NM_CLIENT_CAN_MODIFY "can-modify" + +#define NM_CLIENT_DEVICE_ADDED "device-added" +#define NM_CLIENT_DEVICE_REMOVED "device-removed" +#define NM_CLIENT_PERMISSION_CHANGED "permission-changed" +#define NM_CLIENT_CONNECTION_ADDED "connection-added" +#define NM_CLIENT_CONNECTION_REMOVED "connection-removed" + +/** + * NMClientPermission: + * @NM_CLIENT_PERMISSION_NONE: unknown or no permission + * @NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK: controls whether networking + * can be globally enabled or disabled + * @NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI: controls whether Wi-Fi can be + * globally enabled or disabled + * @NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN: controls whether WWAN (3G) can be + * globally enabled or disabled + * @NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX: controls whether WiMAX can be + * globally enabled or disabled + * @NM_CLIENT_PERMISSION_SLEEP_WAKE: controls whether the client can ask + * NetworkManager to sleep and wake + * @NM_CLIENT_PERMISSION_NETWORK_CONTROL: controls whether networking connections + * can be started, stopped, and changed + * @NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED: controls whether a password + * protected Wi-Fi hotspot can be created + * @NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN: controls whether an open Wi-Fi hotspot + * can be created + * @NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM: controls whether connections + * that are available to all users can be modified + * @NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN: controls whether connections + * owned by the current user can be modified + * @NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME: controls whether the + * persistent hostname can be changed + * @NM_CLIENT_PERMISSION_LAST: a reserved boundary value + * + * #NMClientPermission values indicate various permissions that NetworkManager + * clients can obtain to perform certain tasks on behalf of the current user. + **/ +typedef enum { + NM_CLIENT_PERMISSION_NONE = 0, + NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK = 1, + NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI = 2, + NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN = 3, + NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX = 4, + NM_CLIENT_PERMISSION_SLEEP_WAKE = 5, + NM_CLIENT_PERMISSION_NETWORK_CONTROL = 6, + NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED = 7, + NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN = 8, + NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM = 9, + NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN = 10, + NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME = 11, + + NM_CLIENT_PERMISSION_LAST = NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME +} NMClientPermission; + +/** + * NMClientPermissionResult: + * @NM_CLIENT_PERMISSION_RESULT_UNKNOWN: unknown or no authorization + * @NM_CLIENT_PERMISSION_RESULT_YES: the permission is available + * @NM_CLIENT_PERMISSION_RESULT_AUTH: authorization is necessary before the + * permission is available + * @NM_CLIENT_PERMISSION_RESULT_NO: permission to perform the operation is + * denied by system policy + * + * #NMClientPermissionResult values indicate what authorizations and permissions + * the user requires to obtain a given #NMClientPermission + **/ +typedef enum { + NM_CLIENT_PERMISSION_RESULT_UNKNOWN = 0, + NM_CLIENT_PERMISSION_RESULT_YES, + NM_CLIENT_PERMISSION_RESULT_AUTH, + NM_CLIENT_PERMISSION_RESULT_NO +} NMClientPermissionResult; + +/** + * NMClientError: + * @NM_CLIENT_ERROR_FAILED: unknown or unclassified error + * @NM_CLIENT_ERROR_MANAGER_NOT_RUNNING: an operation that requires NetworkManager + * failed because NetworkManager is not running + * @NM_CLIENT_ERROR_OBJECT_CREATION_FAILED: NetworkManager claimed that an + * operation succeeded, but the object that was allegedly created (eg, + * #NMRemoteConnection, #NMActiveConnection) was apparently destroyed before + * #NMClient could create a representation of it. + * + * Describes errors that may result from operations involving a #NMClient. + * + * D-Bus operations may also return errors from other domains, including + * #NMManagerError, #NMSettingsError, #NMAgentManagerError, and #NMConnectionError. + **/ +typedef enum { + NM_CLIENT_ERROR_FAILED = 0, + NM_CLIENT_ERROR_MANAGER_NOT_RUNNING, + NM_CLIENT_ERROR_OBJECT_CREATION_FAILED, +} NMClientError; + +#define NM_CLIENT_ERROR nm_client_error_quark () +GQuark nm_client_error_quark (void); + +struct _NMClient { + GObject parent; +}; + +typedef struct { + GObjectClass parent; + + /* Signals */ + void (*device_added) (NMClient *client, NMDevice *device); + void (*device_removed) (NMClient *client, NMDevice *device); + void (*permission_changed) (NMClient *client, + NMClientPermission permission, + NMClientPermissionResult result); + void (*connection_added) (NMClient *client, NMRemoteConnection *connection); + void (*connection_removed) (NMClient *client, NMRemoteConnection *connection); + + /*< private >*/ + gpointer padding[8]; +} NMClientClass; + +GType nm_client_get_type (void); + +NMClient *nm_client_new (GCancellable *cancellable, + GError **error); + +void nm_client_new_async (GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +NMClient *nm_client_new_finish (GAsyncResult *result, + GError **error); + +const char *nm_client_get_version (NMClient *client); +NMState nm_client_get_state (NMClient *client); +gboolean nm_client_get_startup (NMClient *client); +gboolean nm_client_get_nm_running (NMClient *client); + +gboolean nm_client_networking_get_enabled (NMClient *client); +gboolean nm_client_networking_set_enabled (NMClient *client, + gboolean enabled, + GError **error); + +gboolean nm_client_wireless_get_enabled (NMClient *client); +void nm_client_wireless_set_enabled (NMClient *client, gboolean enabled); +gboolean nm_client_wireless_hardware_get_enabled (NMClient *client); + +gboolean nm_client_wwan_get_enabled (NMClient *client); +void nm_client_wwan_set_enabled (NMClient *client, gboolean enabled); +gboolean nm_client_wwan_hardware_get_enabled (NMClient *client); + +gboolean nm_client_wimax_get_enabled (NMClient *client); +void nm_client_wimax_set_enabled (NMClient *client, gboolean enabled); +gboolean nm_client_wimax_hardware_get_enabled (NMClient *client); + +gboolean nm_client_get_logging (NMClient *client, + char **level, + char **domains, + GError **error); +gboolean nm_client_set_logging (NMClient *client, + const char *level, + const char *domains, + GError **error); + +NMClientPermissionResult nm_client_get_permission_result (NMClient *client, + NMClientPermission permission); + +NMConnectivityState nm_client_get_connectivity (NMClient *client); + +NMConnectivityState nm_client_check_connectivity (NMClient *client, + GCancellable *cancellable, + GError **error); +void nm_client_check_connectivity_async (NMClient *client, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +NMConnectivityState nm_client_check_connectivity_finish (NMClient *client, + GAsyncResult *result, + GError **error); + +gboolean nm_client_save_hostname (NMClient *client, + const char *hostname, + GCancellable *cancellable, + GError **error); +void nm_client_save_hostname_async (NMClient *client, + const char *hostname, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean nm_client_save_hostname_finish (NMClient *client, + GAsyncResult *result, + GError **error); + +/* Devices */ + +const GPtrArray *nm_client_get_devices (NMClient *client); +NMDevice *nm_client_get_device_by_path (NMClient *client, const char *object_path); +NMDevice *nm_client_get_device_by_iface (NMClient *client, const char *iface); + +/* Active Connections */ + +const GPtrArray *nm_client_get_active_connections (NMClient *client); + +NMActiveConnection *nm_client_get_primary_connection (NMClient *client); +NMActiveConnection *nm_client_get_activating_connection (NMClient *client); + +void nm_client_activate_connection_async (NMClient *client, + NMConnection *connection, + NMDevice *device, + const char *specific_object, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +NMActiveConnection *nm_client_activate_connection_finish (NMClient *client, + GAsyncResult *result, + GError **error); + +void nm_client_add_and_activate_connection_async (NMClient *client, + NMConnection *partial, + NMDevice *device, + const char *specific_object, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +NMActiveConnection *nm_client_add_and_activate_connection_finish (NMClient *client, + GAsyncResult *result, + GError **error); + +gboolean nm_client_deactivate_connection (NMClient *client, + NMActiveConnection *active, + GCancellable *cancellable, + GError **error); +void nm_client_deactivate_connection_async (NMClient *client, + NMActiveConnection *active, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean nm_client_deactivate_connection_finish (NMClient *client, + GAsyncResult *result, + GError **error); + +/* Connections */ + +const GPtrArray *nm_client_get_connections (NMClient *client); + +NMRemoteConnection *nm_client_get_connection_by_id (NMClient *client, const char *id); +NMRemoteConnection *nm_client_get_connection_by_path (NMClient *client, const char *path); +NMRemoteConnection *nm_client_get_connection_by_uuid (NMClient *client, const char *uuid); + +void nm_client_add_connection_async (NMClient *client, + NMConnection *connection, + gboolean save_to_disk, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +NMRemoteConnection *nm_client_add_connection_finish (NMClient *client, + GAsyncResult *result, + GError **error); + +gboolean nm_client_load_connections (NMClient *client, + char **filenames, + char ***failures, + GCancellable *cancellable, + GError **error); +void nm_client_load_connections_async (NMClient *client, + char **filenames, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean nm_client_load_connections_finish (NMClient *client, + char ***failures, + GAsyncResult *result, + GError **error); + +gboolean nm_client_reload_connections (NMClient *client, + GCancellable *cancellable, + GError **error); +void nm_client_reload_connections_async (NMClient *client, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean nm_client_reload_connections_finish (NMClient *client, + GAsyncResult *result, + GError **error); + +G_END_DECLS + +#endif /* __NM_CLIENT_H__ */ diff --git a/libnm/nm-dbus-helpers.c b/libnm/nm-dbus-helpers.c new file mode 100644 index 00000000..7a99e70d --- /dev/null +++ b/libnm/nm-dbus-helpers.c @@ -0,0 +1,405 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2013 Red Hat, Inc. + */ + +#include "config.h" + +#include <string.h> +#include <gio/gio.h> +#include "nm-dbus-helpers.h" +#include "nm-dbus-interface.h" + +static GBusType nm_bus = G_BUS_TYPE_SYSTEM; + +GBusType +_nm_dbus_bus_type (void) +{ + static gsize init_value = 0; + + if (g_once_init_enter (&init_value)) { + if (g_getenv ("LIBNM_USE_SESSION_BUS")) + nm_bus = G_BUS_TYPE_SESSION; + + g_once_init_leave (&init_value, 1); + } + + return nm_bus; +} + +static struct { + GMutex mutex; + GWeakRef weak_ref; +} private_connection; + +static void +_private_dbus_connection_closed_cb (GDBusConnection *connection, + gboolean remote_peer_vanished, + GError *error, + gpointer user_data) +{ + GDBusConnection *p; + + g_mutex_lock (&private_connection.mutex); + p = g_weak_ref_get (&private_connection.weak_ref); + if (connection == p) { + g_signal_handlers_disconnect_by_func (G_OBJECT (connection), G_CALLBACK (_private_dbus_connection_closed_cb), NULL); + g_weak_ref_set (&private_connection.weak_ref, NULL); + } + if (p) + g_object_unref (p); + g_mutex_unlock (&private_connection.mutex); +} + +static GDBusConnection * +_private_dbus_connection_internalize (GDBusConnection *connection) +{ + GDBusConnection *p; + + g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL); + g_return_val_if_fail (!g_dbus_connection_is_closed (connection), NULL); + + g_mutex_lock (&private_connection.mutex); + p = g_weak_ref_get (&private_connection.weak_ref); + if (p) { + g_object_unref (connection); + connection = p; + } else { + g_weak_ref_set (&private_connection.weak_ref, connection); + g_signal_connect (connection, "closed", G_CALLBACK (_private_dbus_connection_closed_cb), NULL); + } + g_mutex_unlock (&private_connection.mutex); + return connection; +} + +GDBusConnection * +_nm_dbus_new_connection (GCancellable *cancellable, GError **error) +{ + GDBusConnection *connection = NULL; + + /* If running as root try the private bus first */ + if (0 == geteuid ()) { + GError *local = NULL; + GDBusConnection *p; + + p = g_weak_ref_get (&private_connection.weak_ref); + if (p) + return p; + + connection = g_dbus_connection_new_for_address_sync ("unix:path=" NMRUNDIR "/private", + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, + NULL, cancellable, &local); + if (connection) + return _private_dbus_connection_internalize (connection); + + if (g_error_matches (local, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + g_propagate_error (error, local); + return NULL; + } + g_error_free (local); + } + + return g_bus_get_sync (_nm_dbus_bus_type (), cancellable, error); +} + +static void +new_connection_async_got_system (GObject *source, GAsyncResult *result, gpointer user_data) +{ + GSimpleAsyncResult *simple = user_data; + GDBusConnection *connection; + GError *error = NULL; + + connection = g_bus_get_finish (result, &error); + if (connection) + g_simple_async_result_set_op_res_gpointer (simple, connection, g_object_unref); + else + g_simple_async_result_take_error (simple, error); + + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +static void +new_connection_async_got_private (GObject *source, GAsyncResult *result, gpointer user_data) +{ + GSimpleAsyncResult *simple = user_data; + GDBusConnection *connection; + GError *error = NULL; + + connection = g_dbus_connection_new_for_address_finish (result, &error); + if (connection) { + connection = _private_dbus_connection_internalize (connection); + g_simple_async_result_set_op_res_gpointer (simple, connection, g_object_unref); + g_simple_async_result_complete (simple); + g_object_unref (simple); + return; + } + + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + g_simple_async_result_take_error (simple, error); + g_simple_async_result_complete (simple); + g_object_unref (simple); + return; + } + + g_clear_error (&error); + g_bus_get (_nm_dbus_bus_type (), + g_object_get_data (G_OBJECT (simple), "cancellable"), + new_connection_async_got_system, simple); +} + +static void +_nm_dbus_new_connection_async_do (GSimpleAsyncResult *simple, GCancellable *cancellable) +{ + g_dbus_connection_new_for_address ("unix:path=" NMRUNDIR "/private", + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, + NULL, + cancellable, + new_connection_async_got_private, simple); +} + +static gboolean +_nm_dbus_new_connection_async_get_private (gpointer user_data) +{ + GSimpleAsyncResult *simple = user_data; + GDBusConnection *p; + + p = g_weak_ref_get (&private_connection.weak_ref); + if (!p) { + /* The connection is gone. Create a new one async... */ + _nm_dbus_new_connection_async_do (simple, + g_object_get_data (G_OBJECT (simple), "cancellable")); + } else { + g_simple_async_result_set_op_res_gpointer (simple, p, g_object_unref); + g_simple_async_result_complete (simple); + g_object_unref (simple); + } + + return G_SOURCE_REMOVE; +} + +void +_nm_dbus_new_connection_async (GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *simple; + + simple = g_simple_async_result_new (NULL, callback, user_data, _nm_dbus_new_connection_async); + + /* If running as root try the private bus first */ + if (0 == geteuid ()) { + GDBusConnection *p; + + if (cancellable) { + g_object_set_data_full (G_OBJECT (simple), "cancellable", + g_object_ref (cancellable), g_object_unref); + } + p = g_weak_ref_get (&private_connection.weak_ref); + if (p) { + g_object_unref (p); + g_idle_add (_nm_dbus_new_connection_async_get_private, simple); + } else + _nm_dbus_new_connection_async_do (simple, cancellable); + } else { + g_bus_get (_nm_dbus_bus_type (), + cancellable, + new_connection_async_got_system, simple); + } +} + +GDBusConnection * +_nm_dbus_new_connection_finish (GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); + + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + + return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple)); +} + +gboolean +_nm_dbus_is_connection_private (GDBusConnection *connection) +{ + return g_dbus_connection_get_unique_name (connection) == NULL; +} + +static GHashTable *proxy_types; + +#undef _nm_dbus_register_proxy_type +void +_nm_dbus_register_proxy_type (const char *interface, + GType proxy_type) +{ + if (!proxy_types) + proxy_types = g_hash_table_new (g_str_hash, g_str_equal); + + g_assert (g_hash_table_lookup (proxy_types, interface) == NULL); + g_hash_table_insert (proxy_types, (char *) interface, GSIZE_TO_POINTER (proxy_type)); +} + +/* We don't (currently) use GDBus's property-handling code */ +#define NM_DBUS_PROXY_FLAGS (G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | \ + G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START) + +GDBusProxy * +_nm_dbus_new_proxy_for_connection (GDBusConnection *connection, + const char *path, + const char *interface, + GCancellable *cancellable, + GError **error) +{ + GType proxy_type; + const char *name; + + proxy_type = GPOINTER_TO_SIZE (g_hash_table_lookup (proxy_types, interface)); + if (!proxy_type) + proxy_type = G_TYPE_DBUS_PROXY; + + if (_nm_dbus_is_connection_private (connection)) + name = NULL; + else + name = NM_DBUS_SERVICE; + + return g_initable_new (proxy_type, cancellable, error, + "g-connection", connection, + "g-flags", NM_DBUS_PROXY_FLAGS, + "g-name", name, + "g-object-path", path, + "g-interface-name", interface, + NULL); +} + +void +_nm_dbus_new_proxy_for_connection_async (GDBusConnection *connection, + const char *path, + const char *interface, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GType proxy_type; + const char *name; + + proxy_type = GPOINTER_TO_SIZE (g_hash_table_lookup (proxy_types, interface)); + if (!proxy_type) + proxy_type = G_TYPE_DBUS_PROXY; + + if (_nm_dbus_is_connection_private (connection)) + name = NULL; + else + name = NM_DBUS_SERVICE; + + g_async_initable_new_async (proxy_type, G_PRIORITY_DEFAULT, + cancellable, callback, user_data, + "g-connection", connection, + "g-flags", NM_DBUS_PROXY_FLAGS, + "g-name", name, + "g-object-path", path, + "g-interface-name", interface, + NULL); +} + +GDBusProxy * +_nm_dbus_new_proxy_for_connection_finish (GAsyncResult *result, + GError **error) +{ + GObject *source, *proxy; + + source = g_async_result_get_source_object (result); + proxy = g_async_initable_new_finish (G_ASYNC_INITABLE (source), result, error); + g_object_unref (source); + + return G_DBUS_PROXY (proxy); +} + +/* Binds the properties on a generated server-side GDBus object to the + * corresponding properties on the public object. + */ +void +_nm_dbus_bind_properties (gpointer object, gpointer skeleton) +{ + GParamSpec **properties; + guint n_properties; + int i; + + properties = g_object_class_list_properties (G_OBJECT_GET_CLASS (skeleton), &n_properties); + for (i = 0; i < n_properties; i++) { + if (g_str_has_prefix (properties[i]->name, "g-")) + continue; + + g_object_bind_property (object, properties[i]->name, + skeleton, properties[i]->name, + G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); + } +} + +static char * +signal_name_from_method_name (const char *method_name) +{ + GString *signal_name; + const char *p; + + signal_name = g_string_new ("handle"); + for (p = method_name; *p; p++) { + if (g_ascii_isupper (*p)) + g_string_append_c (signal_name, '-'); + g_string_append_c (signal_name, g_ascii_tolower (*p)); + } + + return g_string_free (signal_name, FALSE); +} + +static void +_nm_dbus_method_meta_marshal (GClosure *closure, GValue *return_value, + guint n_param_values, const GValue *param_values, + gpointer invocation_hint, gpointer marshal_data) +{ + closure->marshal (closure, return_value, n_param_values, + param_values, invocation_hint, + ((GCClosure *)closure)->callback); + + g_value_set_boolean (return_value, TRUE); +} + +/* Takes (method_name, handler_func) pairs and connects the handlers to the + * signals on skeleton, with object as the user_data, but swapped so it comes + * first in the argument list, and handling the return value automatically. + */ +void +_nm_dbus_bind_methods (gpointer object, gpointer skeleton, ...) +{ + va_list ap; + const char *method_name; + char *signal_name; + GCallback handler; + GClosure *closure; + + va_start (ap, skeleton); + while ( (method_name = va_arg (ap, const char *)) + && (handler = va_arg (ap, GCallback))) { + signal_name = signal_name_from_method_name (method_name); + closure = g_cclosure_new_swap (handler, object, NULL); + g_closure_set_meta_marshal (closure, NULL, _nm_dbus_method_meta_marshal); + g_signal_connect_closure (skeleton, signal_name, closure, FALSE); + g_free (signal_name); + } + va_end (ap); +} diff --git a/libnm/nm-dbus-helpers.h b/libnm/nm-dbus-helpers.h new file mode 100644 index 00000000..ca779d3a --- /dev/null +++ b/libnm/nm-dbus-helpers.h @@ -0,0 +1,78 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2013 Red Hat, Inc. + */ + +#ifndef __NM_DBUS_HELPERS_PRIVATE_H__ +#define __NM_DBUS_HELPERS_PRIVATE_H__ + +#include <gio/gio.h> + +/* Copied from dbus/dbus-shared.h */ +#define DBUS_SERVICE_DBUS "org.freedesktop.DBus" +#define DBUS_PATH_DBUS "/org/freedesktop/DBus" +#define DBUS_PATH_LOCAL "/org/freedesktop/DBus/Local" + +#define DBUS_INTERFACE_DBUS "org.freedesktop.DBus" +#define DBUS_INTERFACE_INTROSPECTABLE "org.freedesktop.DBus.Introspectable" +#define DBUS_INTERFACE_PROPERTIES "org.freedesktop.DBus.Properties" +#define DBUS_INTERFACE_PEER "org.freedesktop.DBus.Peer" + + +GBusType _nm_dbus_bus_type (void); + +GDBusConnection *_nm_dbus_new_connection (GCancellable *cancellable, + GError **error); + +void _nm_dbus_new_connection_async (GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +GDBusConnection *_nm_dbus_new_connection_finish (GAsyncResult *result, + GError **error); + +gboolean _nm_dbus_is_connection_private (GDBusConnection *connection); + +void _nm_dbus_register_proxy_type (const char *interface, + GType proxy_type); +/* Guarantee that @interface is a static string */ +#define _nm_dbus_register_proxy_type(interface, proxy_type) \ + _nm_dbus_register_proxy_type (interface "", proxy_type) \ + +GDBusProxy *_nm_dbus_new_proxy_for_connection (GDBusConnection *connection, + const char *path, + const char *interface, + GCancellable *cancellable, + GError **error); + +void _nm_dbus_new_proxy_for_connection_async (GDBusConnection *connection, + const char *path, + const char *interface, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +GDBusProxy *_nm_dbus_new_proxy_for_connection_finish (GAsyncResult *result, + GError **error); + +void _nm_dbus_bind_properties (gpointer object, + gpointer skeleton); + +void _nm_dbus_bind_methods (gpointer object, + gpointer skeleton, + ...) G_GNUC_NULL_TERMINATED; + +#endif /* __NM_DBUS_HELPERS_PRIVATE_H__ */ diff --git a/libnm/nm-device-adsl.c b/libnm/nm-device-adsl.c new file mode 100644 index 00000000..99771548 --- /dev/null +++ b/libnm/nm-device-adsl.c @@ -0,0 +1,159 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * author: Pantelis Koukousoulas <pktoss@gmail.com> + * Copyright 2009 - 2011 Red Hat, Inc. + */ + +#include "config.h" + +#include "nm-device-adsl.h" +#include "nm-device-private.h" +#include "nm-object-private.h" + +#include "nm-setting-adsl.h" +#include "nm-setting-connection.h" + +#include <string.h> +#include <glib/gi18n-lib.h> + +G_DEFINE_TYPE (NMDeviceAdsl, nm_device_adsl, NM_TYPE_DEVICE) + +#define NM_DEVICE_ADSL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_ADSL, NMDeviceAdslPrivate)) + +typedef struct { + gboolean carrier; + +} NMDeviceAdslPrivate; + +enum { + PROP_0, + PROP_CARRIER, + LAST_PROP +}; + +/** + * nm_device_adsl_get_carrier: + * @device: a #NMDeviceAdsl + * + * Whether the device has carrier. + * + * Returns: %TRUE if the device has carrier + **/ +gboolean +nm_device_adsl_get_carrier (NMDeviceAdsl *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_ADSL (device), FALSE); + + return NM_DEVICE_ADSL_GET_PRIVATE (device)->carrier; +} + +static gboolean +connection_compatible (NMDevice *device, NMConnection *connection, GError **error) +{ + if (!NM_DEVICE_CLASS (nm_device_adsl_parent_class)->connection_compatible (device, connection, error)) + return FALSE; + + if (!nm_connection_is_type (connection, NM_SETTING_ADSL_SETTING_NAME)) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + _("The connection was not an ADSL connection.")); + return FALSE; + } + + return TRUE; +} + +static GType +get_setting_type (NMDevice *device) +{ + return NM_TYPE_SETTING_ADSL; +} + +/******************************************************************/ + +static void +nm_device_adsl_init (NMDeviceAdsl *device) +{ + _nm_device_set_device_type (NM_DEVICE (device), NM_DEVICE_TYPE_ADSL); +} + +static void +init_dbus (NMObject *object) +{ + NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (object); + const NMPropertiesInfo property_info[] = { + { NM_DEVICE_ADSL_CARRIER, &priv->carrier }, + { NULL }, + }; + + NM_OBJECT_CLASS (nm_device_adsl_parent_class)->init_dbus (object); + + _nm_object_register_properties (object, + NM_DBUS_INTERFACE_DEVICE_ADSL, + property_info); +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMDeviceAdsl *device = NM_DEVICE_ADSL (object); + + switch (prop_id) { + case PROP_CARRIER: + g_value_set_boolean (value, nm_device_adsl_get_carrier (device)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_device_adsl_class_init (NMDeviceAdslClass *adsl_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (adsl_class); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (adsl_class); + NMDeviceClass *device_class = NM_DEVICE_CLASS (adsl_class); + + g_type_class_add_private (object_class, sizeof (NMDeviceAdslPrivate)); + + _nm_object_class_add_interface (nm_object_class, NM_DBUS_INTERFACE_DEVICE_ADSL); + + /* virtual methods */ + object_class->get_property = get_property; + + nm_object_class->init_dbus = init_dbus; + + device_class->connection_compatible = connection_compatible; + device_class->get_setting_type = get_setting_type; + + /* properties */ + /** + * NMDeviceAdsl:carrier: + * + * Whether the device has carrier. + **/ + g_object_class_install_property + (object_class, PROP_CARRIER, + g_param_spec_boolean (NM_DEVICE_ADSL_CARRIER, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); +} diff --git a/libnm/nm-device-adsl.h b/libnm/nm-device-adsl.h new file mode 100644 index 00000000..d0174514 --- /dev/null +++ b/libnm/nm-device-adsl.h @@ -0,0 +1,58 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2011 Pantelis Koukousoulas <pktoss@gmail.com> + */ + +#ifndef __NM_DEVICE_ADSL_H__ +#define __NM_DEVICE_ADSL_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include <nm-device.h> + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_ADSL (nm_device_adsl_get_type ()) +#define NM_DEVICE_ADSL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_ADSL, NMDeviceAdsl)) +#define NM_DEVICE_ADSL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_ADSL, NMDeviceAdslClass)) +#define NM_IS_DEVICE_ADSL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_ADSL)) +#define NM_IS_DEVICE_ADSL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_ADSL)) +#define NM_DEVICE_ADSL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_ADSL, NMDeviceAdslClass)) + +#define NM_DEVICE_ADSL_CARRIER "carrier" + +struct _NMDeviceAdsl { + NMDevice parent; +}; + +typedef struct { + NMDeviceClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMDeviceAdslClass; + +GType nm_device_adsl_get_type (void); + +gboolean nm_device_adsl_get_carrier (NMDeviceAdsl *device); + +G_END_DECLS + +#endif /* __NM_DEVICE_ADSL_H__ */ diff --git a/libnm/nm-device-bond.c b/libnm/nm-device-bond.c new file mode 100644 index 00000000..6bb67323 --- /dev/null +++ b/libnm/nm-device-bond.c @@ -0,0 +1,271 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2012 Red Hat, Inc. + */ + +#include "config.h" + +#include <string.h> +#include <glib/gi18n-lib.h> + +#include "nm-glib-compat.h" + +#include <nm-setting-connection.h> +#include <nm-setting-bond.h> +#include <nm-utils.h> + +#include "nm-device-bond.h" +#include "nm-device-private.h" +#include "nm-object-private.h" +#include "nm-core-internal.h" + +G_DEFINE_TYPE (NMDeviceBond, nm_device_bond, NM_TYPE_DEVICE) + +#define NM_DEVICE_BOND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_BOND, NMDeviceBondPrivate)) + +typedef struct { + char *hw_address; + gboolean carrier; + GPtrArray *slaves; +} NMDeviceBondPrivate; + +enum { + PROP_0, + PROP_HW_ADDRESS, + PROP_CARRIER, + PROP_SLAVES, + + LAST_PROP +}; + +/** + * nm_device_bond_get_hw_address: + * @device: a #NMDeviceBond + * + * Gets the hardware (MAC) address of the #NMDeviceBond + * + * Returns: the hardware address. This is the internal string used by the + * device, and must not be modified. + **/ +const char * +nm_device_bond_get_hw_address (NMDeviceBond *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_BOND (device), NULL); + + return NM_DEVICE_BOND_GET_PRIVATE (device)->hw_address; +} + +/** + * nm_device_bond_get_carrier: + * @device: a #NMDeviceBond + * + * Whether the device has carrier. + * + * Returns: %TRUE if the device has carrier + **/ +gboolean +nm_device_bond_get_carrier (NMDeviceBond *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_BOND (device), FALSE); + + return NM_DEVICE_BOND_GET_PRIVATE (device)->carrier; +} + +/** + * nm_device_bond_get_slaves: + * @device: a #NMDeviceBond + * + * Gets the devices currently slaved to @device. + * + * Returns: (element-type NMDevice): the #GPtrArray containing + * #NMDevices that are slaves of @device. This is the internal + * copy used by the device, and must not be modified. + **/ +const GPtrArray * +nm_device_bond_get_slaves (NMDeviceBond *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_BOND (device), FALSE); + + return NM_DEVICE_BOND_GET_PRIVATE (device)->slaves; +} + +static gboolean +connection_compatible (NMDevice *device, NMConnection *connection, GError **error) +{ + if (!NM_DEVICE_CLASS (nm_device_bond_parent_class)->connection_compatible (device, connection, error)) + return FALSE; + + if (!nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME)) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + _("The connection was not a bond connection.")); + return FALSE; + } + + /* FIXME: check slaves? */ + + return TRUE; +} + +static GType +get_setting_type (NMDevice *device) +{ + return NM_TYPE_SETTING_BOND; +} + +static const char * +get_hw_address (NMDevice *device) +{ + return nm_device_bond_get_hw_address (NM_DEVICE_BOND (device)); +} + +/***********************************************************/ + +static void +nm_device_bond_init (NMDeviceBond *device) +{ + NMDeviceBondPrivate *priv = NM_DEVICE_BOND_GET_PRIVATE (device); + + _nm_device_set_device_type (NM_DEVICE (device), NM_DEVICE_TYPE_BOND); + + priv->slaves = g_ptr_array_new (); +} + +static void +init_dbus (NMObject *object) +{ + NMDeviceBondPrivate *priv = NM_DEVICE_BOND_GET_PRIVATE (object); + const NMPropertiesInfo property_info[] = { + { NM_DEVICE_BOND_HW_ADDRESS, &priv->hw_address }, + { NM_DEVICE_BOND_CARRIER, &priv->carrier }, + { NM_DEVICE_BOND_SLAVES, &priv->slaves, NULL, NM_TYPE_DEVICE }, + { NULL }, + }; + + NM_OBJECT_CLASS (nm_device_bond_parent_class)->init_dbus (object); + + _nm_object_register_properties (object, + NM_DBUS_INTERFACE_DEVICE_BOND, + property_info); +} + +static void +dispose (GObject *object) +{ + NMDeviceBondPrivate *priv = NM_DEVICE_BOND_GET_PRIVATE (object); + + g_clear_pointer (&priv->slaves, g_ptr_array_unref); + + G_OBJECT_CLASS (nm_device_bond_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + NMDeviceBondPrivate *priv = NM_DEVICE_BOND_GET_PRIVATE (object); + + g_free (priv->hw_address); + + G_OBJECT_CLASS (nm_device_bond_parent_class)->finalize (object); +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMDeviceBond *device = NM_DEVICE_BOND (object); + + switch (prop_id) { + case PROP_HW_ADDRESS: + g_value_set_string (value, nm_device_bond_get_hw_address (device)); + break; + case PROP_CARRIER: + g_value_set_boolean (value, nm_device_bond_get_carrier (device)); + break; + case PROP_SLAVES: + g_value_take_boxed (value, _nm_utils_copy_object_array (nm_device_bond_get_slaves (device))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_device_bond_class_init (NMDeviceBondClass *bond_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (bond_class); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (bond_class); + NMDeviceClass *device_class = NM_DEVICE_CLASS (bond_class); + + g_type_class_add_private (bond_class, sizeof (NMDeviceBondPrivate)); + + _nm_object_class_add_interface (nm_object_class, NM_DBUS_INTERFACE_DEVICE_BOND); + + /* virtual methods */ + object_class->dispose = dispose; + object_class->finalize = finalize; + object_class->get_property = get_property; + + nm_object_class->init_dbus = init_dbus; + + device_class->connection_compatible = connection_compatible; + device_class->get_setting_type = get_setting_type; + device_class->get_hw_address = get_hw_address; + + /* properties */ + + /** + * NMDeviceBond:hw-address: + * + * The hardware (MAC) address of the device. + **/ + g_object_class_install_property + (object_class, PROP_HW_ADDRESS, + g_param_spec_string (NM_DEVICE_BOND_HW_ADDRESS, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceBond:carrier: + * + * Whether the device has carrier. + **/ + g_object_class_install_property + (object_class, PROP_CARRIER, + g_param_spec_boolean (NM_DEVICE_BOND_CARRIER, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceBond:slaves: + * + * The devices slaved to the bond device. + * + * Element-type: NMDevice + **/ + g_object_class_install_property + (object_class, PROP_SLAVES, + g_param_spec_boxed (NM_DEVICE_BOND_SLAVES, "", "", + G_TYPE_PTR_ARRAY, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); +} diff --git a/libnm/nm-device-bond.h b/libnm/nm-device-bond.h new file mode 100644 index 00000000..b7a0b113 --- /dev/null +++ b/libnm/nm-device-bond.h @@ -0,0 +1,62 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2012 Red Hat, Inc. + */ + +#ifndef __NM_DEVICE_BOND_H__ +#define __NM_DEVICE_BOND_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include <nm-device.h> + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_BOND (nm_device_bond_get_type ()) +#define NM_DEVICE_BOND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_BOND, NMDeviceBond)) +#define NM_DEVICE_BOND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_BOND, NMDeviceBondClass)) +#define NM_IS_DEVICE_BOND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_BOND)) +#define NM_IS_DEVICE_BOND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_BOND)) +#define NM_DEVICE_BOND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_BOND, NMDeviceBondClass)) + +#define NM_DEVICE_BOND_HW_ADDRESS "hw-address" +#define NM_DEVICE_BOND_CARRIER "carrier" +#define NM_DEVICE_BOND_SLAVES "slaves" + +struct _NMDeviceBond { + NMDevice parent; +}; + +typedef struct { + NMDeviceClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMDeviceBondClass; + +GType nm_device_bond_get_type (void); + +const char *nm_device_bond_get_hw_address (NMDeviceBond *device); +gboolean nm_device_bond_get_carrier (NMDeviceBond *device); +const GPtrArray *nm_device_bond_get_slaves (NMDeviceBond *device); + +G_END_DECLS + +#endif /* __NM_DEVICE_BOND_H__ */ diff --git a/libnm/nm-device-bridge.c b/libnm/nm-device-bridge.c new file mode 100644 index 00000000..ce28f2c2 --- /dev/null +++ b/libnm/nm-device-bridge.c @@ -0,0 +1,271 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2012 Red Hat, Inc. + */ + +#include "config.h" + +#include <string.h> +#include <glib/gi18n-lib.h> + +#include "nm-glib-compat.h" + +#include <nm-setting-connection.h> +#include <nm-setting-bridge.h> +#include <nm-utils.h> + +#include "nm-device-bridge.h" +#include "nm-device-private.h" +#include "nm-object-private.h" +#include "nm-core-internal.h" + +G_DEFINE_TYPE (NMDeviceBridge, nm_device_bridge, NM_TYPE_DEVICE) + +#define NM_DEVICE_BRIDGE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_BRIDGE, NMDeviceBridgePrivate)) + +typedef struct { + char *hw_address; + gboolean carrier; + GPtrArray *slaves; +} NMDeviceBridgePrivate; + +enum { + PROP_0, + PROP_HW_ADDRESS, + PROP_CARRIER, + PROP_SLAVES, + + LAST_PROP +}; + +/** + * nm_device_bridge_get_hw_address: + * @device: a #NMDeviceBridge + * + * Gets the hardware (MAC) address of the #NMDeviceBridge + * + * Returns: the hardware address. This is the internal string used by the + * device, and must not be modified. + **/ +const char * +nm_device_bridge_get_hw_address (NMDeviceBridge *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_BRIDGE (device), NULL); + + return NM_DEVICE_BRIDGE_GET_PRIVATE (device)->hw_address; +} + +/** + * nm_device_bridge_get_carrier: + * @device: a #NMDeviceBridge + * + * Whether the device has carrier. + * + * Returns: %TRUE if the device has carrier + **/ +gboolean +nm_device_bridge_get_carrier (NMDeviceBridge *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_BRIDGE (device), FALSE); + + return NM_DEVICE_BRIDGE_GET_PRIVATE (device)->carrier; +} + +/** + * nm_device_bridge_get_slaves: + * @device: a #NMDeviceBridge + * + * Gets the devices currently slaved to @device. + * + * Returns: (element-type NMDevice): the #GPtrArray containing + * #NMDevices that are slaves of @device. This is the internal + * copy used by the device, and must not be modified. + **/ +const GPtrArray * +nm_device_bridge_get_slaves (NMDeviceBridge *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_BRIDGE (device), FALSE); + + return NM_DEVICE_BRIDGE_GET_PRIVATE (device)->slaves; +} + +static gboolean +connection_compatible (NMDevice *device, NMConnection *connection, GError **error) +{ + if (!NM_DEVICE_CLASS (nm_device_bridge_parent_class)->connection_compatible (device, connection, error)) + return FALSE; + + if (!nm_connection_is_type (connection, NM_SETTING_BRIDGE_SETTING_NAME)) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + _("The connection was not a bridge connection.")); + return FALSE; + } + + /* FIXME: check ports? */ + + return TRUE; +} + +static GType +get_setting_type (NMDevice *device) +{ + return NM_TYPE_SETTING_BRIDGE; +} + +static const char * +get_hw_address (NMDevice *device) +{ + return nm_device_bridge_get_hw_address (NM_DEVICE_BRIDGE (device)); +} + +/***********************************************************/ + +static void +nm_device_bridge_init (NMDeviceBridge *device) +{ + NMDeviceBridgePrivate *priv = NM_DEVICE_BRIDGE_GET_PRIVATE (device); + + _nm_device_set_device_type (NM_DEVICE (device), NM_DEVICE_TYPE_BRIDGE); + + priv->slaves = g_ptr_array_new (); +} + +static void +init_dbus (NMObject *object) +{ + NMDeviceBridgePrivate *priv = NM_DEVICE_BRIDGE_GET_PRIVATE (object); + const NMPropertiesInfo property_info[] = { + { NM_DEVICE_BRIDGE_HW_ADDRESS, &priv->hw_address }, + { NM_DEVICE_BRIDGE_CARRIER, &priv->carrier }, + { NM_DEVICE_BRIDGE_SLAVES, &priv->slaves, NULL, NM_TYPE_DEVICE }, + { NULL }, + }; + + NM_OBJECT_CLASS (nm_device_bridge_parent_class)->init_dbus (object); + + _nm_object_register_properties (object, + NM_DBUS_INTERFACE_DEVICE_BRIDGE, + property_info); +} + +static void +dispose (GObject *object) +{ + NMDeviceBridgePrivate *priv = NM_DEVICE_BRIDGE_GET_PRIVATE (object); + + g_clear_pointer (&priv->slaves, g_ptr_array_unref); + + G_OBJECT_CLASS (nm_device_bridge_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + NMDeviceBridgePrivate *priv = NM_DEVICE_BRIDGE_GET_PRIVATE (object); + + g_free (priv->hw_address); + + G_OBJECT_CLASS (nm_device_bridge_parent_class)->finalize (object); +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMDeviceBridge *device = NM_DEVICE_BRIDGE (object); + + switch (prop_id) { + case PROP_HW_ADDRESS: + g_value_set_string (value, nm_device_bridge_get_hw_address (device)); + break; + case PROP_CARRIER: + g_value_set_boolean (value, nm_device_bridge_get_carrier (device)); + break; + case PROP_SLAVES: + g_value_take_boxed (value, _nm_utils_copy_object_array (nm_device_bridge_get_slaves (device))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_device_bridge_class_init (NMDeviceBridgeClass *bridge_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (bridge_class); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (bridge_class); + NMDeviceClass *device_class = NM_DEVICE_CLASS (bridge_class); + + g_type_class_add_private (bridge_class, sizeof (NMDeviceBridgePrivate)); + + _nm_object_class_add_interface (nm_object_class, NM_DBUS_INTERFACE_DEVICE_BRIDGE); + + /* virtual methods */ + object_class->dispose = dispose; + object_class->finalize = finalize; + object_class->get_property = get_property; + + nm_object_class->init_dbus = init_dbus; + + device_class->connection_compatible = connection_compatible; + device_class->get_setting_type = get_setting_type; + device_class->get_hw_address = get_hw_address; + + /* properties */ + + /** + * NMDeviceBridge:hw-address: + * + * The hardware (MAC) address of the device. + **/ + g_object_class_install_property + (object_class, PROP_HW_ADDRESS, + g_param_spec_string (NM_DEVICE_BRIDGE_HW_ADDRESS, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceBridge:carrier: + * + * Whether the device has carrier. + **/ + g_object_class_install_property + (object_class, PROP_CARRIER, + g_param_spec_boolean (NM_DEVICE_BRIDGE_CARRIER, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceBridge:slaves: + * + * The devices slaved to the bridge device. + * + * Element-type: NMDevice + **/ + g_object_class_install_property + (object_class, PROP_SLAVES, + g_param_spec_boxed (NM_DEVICE_BRIDGE_SLAVES, "", "", + G_TYPE_PTR_ARRAY, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); +} diff --git a/libnm/nm-device-bridge.h b/libnm/nm-device-bridge.h new file mode 100644 index 00000000..42a0b3a5 --- /dev/null +++ b/libnm/nm-device-bridge.h @@ -0,0 +1,62 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2012 Red Hat, Inc. + */ + +#ifndef __NM_DEVICE_BRIDGE_H__ +#define __NM_DEVICE_BRIDGE_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include <nm-device.h> + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_BRIDGE (nm_device_bridge_get_type ()) +#define NM_DEVICE_BRIDGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_BRIDGE, NMDeviceBridge)) +#define NM_DEVICE_BRIDGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_BRIDGE, NMDeviceBridgeClass)) +#define NM_IS_DEVICE_BRIDGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_BRIDGE)) +#define NM_IS_DEVICE_BRIDGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_BRIDGE)) +#define NM_DEVICE_BRIDGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_BRIDGE, NMDeviceBridgeClass)) + +#define NM_DEVICE_BRIDGE_HW_ADDRESS "hw-address" +#define NM_DEVICE_BRIDGE_CARRIER "carrier" +#define NM_DEVICE_BRIDGE_SLAVES "slaves" + +struct _NMDeviceBridge { + NMDevice parent; +}; + +typedef struct { + NMDeviceClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMDeviceBridgeClass; + +GType nm_device_bridge_get_type (void); + +const char *nm_device_bridge_get_hw_address (NMDeviceBridge *device); +gboolean nm_device_bridge_get_carrier (NMDeviceBridge *device); +const GPtrArray *nm_device_bridge_get_slaves (NMDeviceBridge *device); + +G_END_DECLS + +#endif /* __NM_DEVICE_BRIDGE_H__ */ diff --git a/libnm/nm-device-bt.c b/libnm/nm-device-bt.c new file mode 100644 index 00000000..77526464 --- /dev/null +++ b/libnm/nm-device-bt.c @@ -0,0 +1,305 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2007 - 2008 Novell, Inc. + * Copyright 2007 - 2012 Red Hat, Inc. + */ + +#include "config.h" + +#include <string.h> +#include <glib/gi18n-lib.h> + +#include "nm-glib-compat.h" + +#include <nm-setting-connection.h> +#include <nm-setting-bluetooth.h> +#include <nm-utils.h> + +#include "nm-device-bt.h" +#include "nm-device-private.h" +#include "nm-object-private.h" +#include "nm-enum-types.h" + +G_DEFINE_TYPE (NMDeviceBt, nm_device_bt, NM_TYPE_DEVICE) + +#define NM_DEVICE_BT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_BT, NMDeviceBtPrivate)) + +typedef struct { + char *hw_address; + char *name; + guint32 bt_capabilities; +} NMDeviceBtPrivate; + +enum { + PROP_0, + PROP_HW_ADDRESS, + PROP_NAME, + PROP_BT_CAPABILITIES, + + LAST_PROP +}; + +/** + * nm_device_bt_get_hw_address: + * @device: a #NMDeviceBt + * + * Gets the hardware (MAC) address of the #NMDeviceBt + * + * Returns: the hardware address. This is the internal string used by the + * device, and must not be modified. + **/ +const char * +nm_device_bt_get_hw_address (NMDeviceBt *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_BT (device), NULL); + + return NM_DEVICE_BT_GET_PRIVATE (device)->hw_address; +} + +/** + * nm_device_bt_get_name: + * @device: a #NMDeviceBt + * + * Gets the name of the #NMDeviceBt. + * + * Returns: the name of the device + **/ +const char * +nm_device_bt_get_name (NMDeviceBt *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_BT (device), NULL); + + return NM_DEVICE_BT_GET_PRIVATE (device)->name; +} + +/** + * nm_device_bt_get_capabilities: + * @device: a #NMDeviceBt + * + * Returns the Bluetooth device's usable capabilities. + * + * Returns: a combination of #NMBluetoothCapabilities + **/ +NMBluetoothCapabilities +nm_device_bt_get_capabilities (NMDeviceBt *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_BT (device), NM_BT_CAPABILITY_NONE); + + return NM_DEVICE_BT_GET_PRIVATE (device)->bt_capabilities; +} + +static NMBluetoothCapabilities +get_connection_bt_type (NMConnection *connection) +{ + NMSettingBluetooth *s_bt; + const char *bt_type; + + s_bt = nm_connection_get_setting_bluetooth (connection); + if (!s_bt) + return NM_BT_CAPABILITY_NONE; + + bt_type = nm_setting_bluetooth_get_connection_type (s_bt); + g_assert (bt_type); + + if (!strcmp (bt_type, NM_SETTING_BLUETOOTH_TYPE_DUN)) + return NM_BT_CAPABILITY_DUN; + else if (!strcmp (bt_type, NM_SETTING_BLUETOOTH_TYPE_PANU)) + return NM_BT_CAPABILITY_NAP; + + return NM_BT_CAPABILITY_NONE; +} + +static gboolean +connection_compatible (NMDevice *device, NMConnection *connection, GError **error) +{ + NMSettingBluetooth *s_bt; + const char *hw_addr, *setting_addr; + NMBluetoothCapabilities dev_caps; + NMBluetoothCapabilities bt_type; + + if (!NM_DEVICE_CLASS (nm_device_bt_parent_class)->connection_compatible (device, connection, error)) + return FALSE; + + if (!nm_connection_is_type (connection, NM_SETTING_BLUETOOTH_SETTING_NAME)) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + _("The connection was not a Bluetooth connection.")); + return FALSE; + } + + /* Check BT address */ + hw_addr = nm_device_bt_get_hw_address (NM_DEVICE_BT (device)); + if (hw_addr) { + if (!nm_utils_hwaddr_valid (hw_addr, ETH_ALEN)) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, + _("Invalid device Bluetooth address.")); + return FALSE; + } + s_bt = nm_connection_get_setting_bluetooth (connection); + setting_addr = nm_setting_bluetooth_get_bdaddr (s_bt); + if (setting_addr && !nm_utils_hwaddr_matches (setting_addr, -1, hw_addr, -1)) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + _("The Bluetooth addresses of the device and the connection didn't match.")); + return FALSE; + } + } + + dev_caps = nm_device_bt_get_capabilities (NM_DEVICE_BT (device)); + bt_type = get_connection_bt_type (connection); + if (!(bt_type & dev_caps)) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + _("The device is lacking Bluetooth capabilities required by the connection.")); + return FALSE; + } + + return TRUE; +} + +static GType +get_setting_type (NMDevice *device) +{ + return NM_TYPE_SETTING_BLUETOOTH; +} + +static const char * +get_hw_address (NMDevice *device) +{ + return nm_device_bt_get_hw_address (NM_DEVICE_BT (device)); +} + +/************************************************************/ + +static void +nm_device_bt_init (NMDeviceBt *device) +{ + _nm_device_set_device_type (NM_DEVICE (device), NM_DEVICE_TYPE_BT); +} + +static void +init_dbus (NMObject *object) +{ + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (object); + const NMPropertiesInfo property_info[] = { + { NM_DEVICE_BT_HW_ADDRESS, &priv->hw_address }, + { NM_DEVICE_BT_NAME, &priv->name }, + { NM_DEVICE_BT_CAPABILITIES, &priv->bt_capabilities }, + { NULL }, + }; + + NM_OBJECT_CLASS (nm_device_bt_parent_class)->init_dbus (object); + + _nm_object_register_properties (object, + NM_DBUS_INTERFACE_DEVICE_BLUETOOTH, + property_info); +} + +static void +finalize (GObject *object) +{ + NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (object); + + g_free (priv->hw_address); + g_free (priv->name); + + G_OBJECT_CLASS (nm_device_bt_parent_class)->finalize (object); +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMDeviceBt *device = NM_DEVICE_BT (object); + + switch (prop_id) { + case PROP_HW_ADDRESS: + g_value_set_string (value, nm_device_bt_get_hw_address (device)); + break; + case PROP_NAME: + g_value_set_string (value, nm_device_bt_get_name (device)); + break; + case PROP_BT_CAPABILITIES: + g_value_set_flags (value, nm_device_bt_get_capabilities (device)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_device_bt_class_init (NMDeviceBtClass *bt_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (bt_class); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (bt_class); + NMDeviceClass *device_class = NM_DEVICE_CLASS (bt_class); + + g_type_class_add_private (bt_class, sizeof (NMDeviceBtPrivate)); + + _nm_object_class_add_interface (nm_object_class, NM_DBUS_INTERFACE_DEVICE_BLUETOOTH); + + /* virtual methods */ + object_class->finalize = finalize; + object_class->get_property = get_property; + + nm_object_class->init_dbus = init_dbus; + + device_class->connection_compatible = connection_compatible; + device_class->get_setting_type = get_setting_type; + device_class->get_hw_address = get_hw_address; + + /* properties */ + + /** + * NMDeviceBt:hw-address: + * + * The hardware (MAC) address of the device. + **/ + g_object_class_install_property + (object_class, PROP_HW_ADDRESS, + g_param_spec_string (NM_DEVICE_BT_HW_ADDRESS, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceBt:name: + * + * The name of the bluetooth device. + **/ + g_object_class_install_property + (object_class, PROP_NAME, + g_param_spec_string (NM_DEVICE_BT_NAME, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceBt:bt-capabilities: + * + * The device's bluetooth capabilities, a combination of #NMBluetoothCapabilities. + **/ + g_object_class_install_property + (object_class, PROP_BT_CAPABILITIES, + g_param_spec_flags (NM_DEVICE_BT_CAPABILITIES, "", "", + NM_TYPE_BLUETOOTH_CAPABILITIES, + NM_BT_CAPABILITY_NONE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + +} diff --git a/libnm/nm-device-bt.h b/libnm/nm-device-bt.h new file mode 100644 index 00000000..e066cbcd --- /dev/null +++ b/libnm/nm-device-bt.h @@ -0,0 +1,65 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2008 - 2012 Red Hat, Inc. + * Copyright 2008 Novell, Inc. + */ + +#ifndef __NM_DEVICE_BT_H__ +#define __NM_DEVICE_BT_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include <nm-device.h> + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_BT (nm_device_bt_get_type ()) +#define NM_DEVICE_BT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_BT, NMDeviceBt)) +#define NM_DEVICE_BT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_BT, NMDeviceBtClass)) +#define NM_IS_DEVICE_BT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_BT)) +#define NM_IS_DEVICE_BT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_BT)) +#define NM_DEVICE_BT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_BT, NMDeviceBtClass)) + +#define NM_DEVICE_BT_HW_ADDRESS "hw-address" +#define NM_DEVICE_BT_NAME "name" +#define NM_DEVICE_BT_CAPABILITIES "bt-capabilities" + +struct _NMDeviceBt { + NMDevice parent; +}; + +typedef struct { + NMDeviceClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMDeviceBtClass; + +GType nm_device_bt_get_type (void); + +const char *nm_device_bt_get_hw_address (NMDeviceBt *device); + +const char *nm_device_bt_get_name (NMDeviceBt *device); + +NMBluetoothCapabilities nm_device_bt_get_capabilities (NMDeviceBt *device); + +G_END_DECLS + +#endif /* __NM_DEVICE_BT_H__ */ diff --git a/libnm/nm-device-ethernet.c b/libnm/nm-device-ethernet.c new file mode 100644 index 00000000..be2cb4dc --- /dev/null +++ b/libnm/nm-device-ethernet.c @@ -0,0 +1,317 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2007 - 2008 Novell, Inc. + * Copyright 2007 - 2012 Red Hat, Inc. + */ + +#include "config.h" + +#include <string.h> +#include <glib/gi18n-lib.h> + +#include "nm-glib-compat.h" + +#include <nm-setting-connection.h> +#include <nm-setting-wired.h> +#include <nm-setting-pppoe.h> +#include <nm-utils.h> + +#include "nm-device-ethernet.h" +#include "nm-device-private.h" +#include "nm-object-private.h" + +G_DEFINE_TYPE (NMDeviceEthernet, nm_device_ethernet, NM_TYPE_DEVICE) + +#define NM_DEVICE_ETHERNET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_ETHERNET, NMDeviceEthernetPrivate)) + +typedef struct { + char *hw_address; + char *perm_hw_address; + guint32 speed; + gboolean carrier; +} NMDeviceEthernetPrivate; + +enum { + PROP_0, + PROP_HW_ADDRESS, + PROP_PERM_HW_ADDRESS, + PROP_SPEED, + PROP_CARRIER, + + LAST_PROP +}; + +/** + * nm_device_ethernet_get_hw_address: + * @device: a #NMDeviceEthernet + * + * Gets the active hardware (MAC) address of the #NMDeviceEthernet + * + * Returns: the active hardware address. This is the internal string used by the + * device, and must not be modified. + **/ +const char * +nm_device_ethernet_get_hw_address (NMDeviceEthernet *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_ETHERNET (device), NULL); + + return NM_DEVICE_ETHERNET_GET_PRIVATE (device)->hw_address; +} + +/** + * nm_device_ethernet_get_permanent_hw_address: + * @device: a #NMDeviceEthernet + * + * Gets the permanent hardware (MAC) address of the #NMDeviceEthernet + * + * Returns: the permanent hardware address. This is the internal string used by the + * device, and must not be modified. + **/ +const char * +nm_device_ethernet_get_permanent_hw_address (NMDeviceEthernet *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_ETHERNET (device), NULL); + + return NM_DEVICE_ETHERNET_GET_PRIVATE (device)->perm_hw_address; +} + +/** + * nm_device_ethernet_get_speed: + * @device: a #NMDeviceEthernet + * + * Gets the speed of the #NMDeviceEthernet. + * + * Returns: the speed of the device + **/ +guint32 +nm_device_ethernet_get_speed (NMDeviceEthernet *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_ETHERNET (device), 0); + + return NM_DEVICE_ETHERNET_GET_PRIVATE (device)->speed; +} + +/** + * nm_device_ethernet_get_carrier: + * @device: a #NMDeviceEthernet + * + * Whether the device has carrier. + * + * Returns: %TRUE if the device has carrier + **/ +gboolean +nm_device_ethernet_get_carrier (NMDeviceEthernet *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_ETHERNET (device), FALSE); + + return NM_DEVICE_ETHERNET_GET_PRIVATE (device)->carrier; +} + +static gboolean +connection_compatible (NMDevice *device, NMConnection *connection, GError **error) +{ + NMSettingWired *s_wired; + gboolean is_pppoe = FALSE; + + if (!NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->connection_compatible (device, connection, error)) + return FALSE; + + if (nm_connection_is_type (connection, NM_SETTING_PPPOE_SETTING_NAME)) + is_pppoe = TRUE; + else if (!nm_connection_is_type (connection, NM_SETTING_WIRED_SETTING_NAME)) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + _("The connection was not an Ethernet or PPPoE connection.")); + return FALSE; + } + + s_wired = nm_connection_get_setting_wired (connection); + /* Wired setting optional for PPPoE */ + if (s_wired) { + const char *perm_addr, *setting_addr; + + /* FIXME: filter using s390 subchannels when they are exported over the bus */ + + /* Check MAC address */ + perm_addr = nm_device_ethernet_get_permanent_hw_address (NM_DEVICE_ETHERNET (device)); + if (perm_addr) { + if (!nm_utils_hwaddr_valid (perm_addr, ETH_ALEN)) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, + _("Invalid device MAC address.")); + return FALSE; + } + setting_addr = nm_setting_wired_get_mac_address (s_wired); + if (setting_addr && !nm_utils_hwaddr_matches (setting_addr, -1, perm_addr, -1)) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + _("The MACs of the device and the connection didn't match.")); + return FALSE; + } + } + } + + return TRUE; +} + +static GType +get_setting_type (NMDevice *device) +{ + return NM_TYPE_SETTING_WIRED; +} + +static const char * +get_hw_address (NMDevice *device) +{ + return nm_device_ethernet_get_hw_address (NM_DEVICE_ETHERNET (device)); +} + +/***********************************************************/ + +static void +nm_device_ethernet_init (NMDeviceEthernet *device) +{ + _nm_device_set_device_type (NM_DEVICE (device), NM_DEVICE_TYPE_ETHERNET); +} + +static void +init_dbus (NMObject *object) +{ + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (object); + const NMPropertiesInfo property_info[] = { + { NM_DEVICE_ETHERNET_HW_ADDRESS, &priv->hw_address }, + { NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS, &priv->perm_hw_address }, + { NM_DEVICE_ETHERNET_SPEED, &priv->speed }, + { NM_DEVICE_ETHERNET_CARRIER, &priv->carrier }, + { NULL }, + }; + + NM_OBJECT_CLASS (nm_device_ethernet_parent_class)->init_dbus (object); + + _nm_object_register_properties (object, + NM_DBUS_INTERFACE_DEVICE_WIRED, + property_info); +} + +static void +finalize (GObject *object) +{ + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (object); + + g_free (priv->hw_address); + g_free (priv->perm_hw_address); + + G_OBJECT_CLASS (nm_device_ethernet_parent_class)->finalize (object); +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMDeviceEthernet *device = NM_DEVICE_ETHERNET (object); + + switch (prop_id) { + case PROP_HW_ADDRESS: + g_value_set_string (value, nm_device_ethernet_get_hw_address (device)); + break; + case PROP_PERM_HW_ADDRESS: + g_value_set_string (value, nm_device_ethernet_get_permanent_hw_address (device)); + break; + case PROP_SPEED: + g_value_set_uint (value, nm_device_ethernet_get_speed (device)); + break; + case PROP_CARRIER: + g_value_set_boolean (value, nm_device_ethernet_get_carrier (device)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_device_ethernet_class_init (NMDeviceEthernetClass *eth_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (eth_class); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (eth_class); + NMDeviceClass *device_class = NM_DEVICE_CLASS (eth_class); + + g_type_class_add_private (eth_class, sizeof (NMDeviceEthernetPrivate)); + + _nm_object_class_add_interface (nm_object_class, NM_DBUS_INTERFACE_DEVICE_WIRED); + + /* virtual methods */ + object_class->finalize = finalize; + object_class->get_property = get_property; + + nm_object_class->init_dbus = init_dbus; + + device_class->connection_compatible = connection_compatible; + device_class->get_setting_type = get_setting_type; + device_class->get_hw_address = get_hw_address; + + /* properties */ + + /** + * NMDeviceEthernet:hw-address: + * + * The active hardware (MAC) address of the device. + **/ + g_object_class_install_property + (object_class, PROP_HW_ADDRESS, + g_param_spec_string (NM_DEVICE_ETHERNET_HW_ADDRESS, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceEthernet:perm-hw-address: + * + * The permanent hardware (MAC) address of the device. + **/ + g_object_class_install_property + (object_class, PROP_PERM_HW_ADDRESS, + g_param_spec_string (NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceEthernet:speed: + * + * The speed of the device. + **/ + g_object_class_install_property + (object_class, PROP_SPEED, + g_param_spec_uint (NM_DEVICE_ETHERNET_SPEED, "", "", + 0, G_MAXUINT32, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceEthernet:carrier: + * + * Whether the device has carrier. + **/ + g_object_class_install_property + (object_class, PROP_CARRIER, + g_param_spec_boolean (NM_DEVICE_ETHERNET_CARRIER, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + +} diff --git a/libnm/nm-device-ethernet.h b/libnm/nm-device-ethernet.h new file mode 100644 index 00000000..09286e73 --- /dev/null +++ b/libnm/nm-device-ethernet.h @@ -0,0 +1,65 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2007 - 2008 Novell, Inc. + * Copyright 2007 - 2012 Red Hat, Inc. + */ + +#ifndef __NM_DEVICE_ETHERNET_H__ +#define __NM_DEVICE_ETHERNET_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include <nm-device.h> + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_ETHERNET (nm_device_ethernet_get_type ()) +#define NM_DEVICE_ETHERNET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_ETHERNET, NMDeviceEthernet)) +#define NM_DEVICE_ETHERNET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_ETHERNET, NMDeviceEthernetClass)) +#define NM_IS_DEVICE_ETHERNET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_ETHERNET)) +#define NM_IS_DEVICE_ETHERNET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_ETHERNET)) +#define NM_DEVICE_ETHERNET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_ETHERNET, NMDeviceEthernetClass)) + +#define NM_DEVICE_ETHERNET_HW_ADDRESS "hw-address" +#define NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS "perm-hw-address" +#define NM_DEVICE_ETHERNET_SPEED "speed" +#define NM_DEVICE_ETHERNET_CARRIER "carrier" + +struct _NMDeviceEthernet { + NMDevice parent; +}; + +typedef struct { + NMDeviceClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMDeviceEthernetClass; + +GType nm_device_ethernet_get_type (void); + +const char * nm_device_ethernet_get_hw_address (NMDeviceEthernet *device); +const char * nm_device_ethernet_get_permanent_hw_address (NMDeviceEthernet *device); +guint32 nm_device_ethernet_get_speed (NMDeviceEthernet *device); +gboolean nm_device_ethernet_get_carrier (NMDeviceEthernet *device); + +G_END_DECLS + +#endif /* __NM_DEVICE_ETHERNET_H__ */ diff --git a/libnm/nm-device-generic.c b/libnm/nm-device-generic.c new file mode 100644 index 00000000..3ed0fa7e --- /dev/null +++ b/libnm/nm-device-generic.c @@ -0,0 +1,214 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2013 Red Hat, Inc. + */ + +#include "config.h" + +#include <string.h> +#include <glib/gi18n-lib.h> + +#include "nm-device-generic.h" +#include "nm-device-private.h" +#include "nm-object-private.h" +#include "nm-setting-generic.h" +#include "nm-setting-connection.h" + +G_DEFINE_TYPE (NMDeviceGeneric, nm_device_generic, NM_TYPE_DEVICE) + +#define NM_DEVICE_GENERIC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_GENERIC, NMDeviceGenericPrivate)) + +typedef struct { + char *hw_address; + char *type_description; +} NMDeviceGenericPrivate; + +enum { + PROP_0, + PROP_HW_ADDRESS, + PROP_TYPE_DESCRIPTION, + + LAST_PROP +}; + +/** + * nm_device_generic_get_hw_address: + * @device: a #NMDeviceGeneric + * + * Gets the hardware address of the #NMDeviceGeneric + * + * Returns: the hardware address. This is the internal string used by the + * device, and must not be modified. + **/ +const char * +nm_device_generic_get_hw_address (NMDeviceGeneric *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_GENERIC (device), NULL); + + return NM_DEVICE_GENERIC_GET_PRIVATE (device)->hw_address; +} + +/***********************************************************/ + +static const char * +get_type_description (NMDevice *device) +{ + NMDeviceGenericPrivate *priv = NM_DEVICE_GENERIC_GET_PRIVATE (device); + + return priv->type_description; +} + +static const char * +get_hw_address (NMDevice *device) +{ + return nm_device_generic_get_hw_address (NM_DEVICE_GENERIC (device)); +} + +static gboolean +connection_compatible (NMDevice *device, NMConnection *connection, GError **error) +{ + const char *iface_name; + + if (!NM_DEVICE_CLASS (nm_device_generic_parent_class)->connection_compatible (device, connection, error)) + return FALSE; + + if (!nm_connection_is_type (connection, NM_SETTING_GENERIC_SETTING_NAME)) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + _("The connection was not a generic connection.")); + return FALSE; + } + + iface_name = nm_connection_get_interface_name (connection); + if (!iface_name) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION, + _("The connection did not specify an interface name.")); + return FALSE; + } + + return TRUE; +} + +static GType +get_setting_type (NMDevice *device) +{ + return NM_TYPE_SETTING_GENERIC; +} + +/***********************************************************/ + +static void +nm_device_generic_init (NMDeviceGeneric *device) +{ + _nm_device_set_device_type (NM_DEVICE (device), NM_DEVICE_TYPE_GENERIC); +} + +static void +init_dbus (NMObject *object) +{ + NMDeviceGenericPrivate *priv = NM_DEVICE_GENERIC_GET_PRIVATE (object); + const NMPropertiesInfo property_info[] = { + { NM_DEVICE_GENERIC_HW_ADDRESS, &priv->hw_address }, + { NM_DEVICE_GENERIC_TYPE_DESCRIPTION, &priv->type_description }, + { NULL }, + }; + + NM_OBJECT_CLASS (nm_device_generic_parent_class)->init_dbus (object); + + _nm_object_register_properties (object, + NM_DBUS_INTERFACE_DEVICE_GENERIC, + property_info); +} + +static void +finalize (GObject *object) +{ + NMDeviceGenericPrivate *priv = NM_DEVICE_GENERIC_GET_PRIVATE (object); + + g_free (priv->hw_address); + g_free (priv->type_description); + + G_OBJECT_CLASS (nm_device_generic_parent_class)->finalize (object); +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMDeviceGenericPrivate *priv = NM_DEVICE_GENERIC_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_HW_ADDRESS: + g_value_set_string (value, priv->hw_address); + break; + case PROP_TYPE_DESCRIPTION: + g_value_set_string (value, priv->type_description); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_device_generic_class_init (NMDeviceGenericClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); + + g_type_class_add_private (klass, sizeof (NMDeviceGenericPrivate)); + + _nm_object_class_add_interface (nm_object_class, NM_DBUS_INTERFACE_DEVICE_GENERIC); + + object_class->finalize = finalize; + object_class->get_property = get_property; + + nm_object_class->init_dbus = init_dbus; + + device_class->get_type_description = get_type_description; + device_class->get_hw_address = get_hw_address; + device_class->connection_compatible = connection_compatible; + device_class->get_setting_type = get_setting_type; + + /** + * NMDeviceGeneric:hw-address: + * + * The hardware address of the device. + **/ + g_object_class_install_property + (object_class, PROP_HW_ADDRESS, + g_param_spec_string (NM_DEVICE_GENERIC_HW_ADDRESS, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceGeneric:type-description: + * + * A description of the specific type of device this is, or %NULL + * if not known. + **/ + g_object_class_install_property + (object_class, PROP_TYPE_DESCRIPTION, + g_param_spec_string (NM_DEVICE_GENERIC_TYPE_DESCRIPTION, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); +} diff --git a/libnm/nm-device-generic.h b/libnm/nm-device-generic.h new file mode 100644 index 00000000..457a8840 --- /dev/null +++ b/libnm/nm-device-generic.h @@ -0,0 +1,59 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2013 Red Hat, Inc. + */ + +#ifndef __NM_DEVICE_GENERIC_H__ +#define __NM_DEVICE_GENERIC_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include <nm-device.h> + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_GENERIC (nm_device_generic_get_type ()) +#define NM_DEVICE_GENERIC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_GENERIC, NMDeviceGeneric)) +#define NM_DEVICE_GENERIC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_GENERIC, NMDeviceGenericClass)) +#define NM_IS_DEVICE_GENERIC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_GENERIC)) +#define NM_IS_DEVICE_GENERIC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_GENERIC)) +#define NM_DEVICE_GENERIC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_GENERIC, NMDeviceGenericClass)) + +#define NM_DEVICE_GENERIC_HW_ADDRESS "hw-address" +#define NM_DEVICE_GENERIC_TYPE_DESCRIPTION "type-description" + +struct _NMDeviceGeneric { + NMDevice parent; +}; + +typedef struct { + NMDeviceClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMDeviceGenericClass; + +GType nm_device_generic_get_type (void); + +const char *nm_device_generic_get_hw_address (NMDeviceGeneric *device); + +G_END_DECLS + +#endif /* __NM_DEVICE_GENERIC_H__ */ diff --git a/libnm/nm-device-infiniband.c b/libnm/nm-device-infiniband.c new file mode 100644 index 00000000..bce8a87a --- /dev/null +++ b/libnm/nm-device-infiniband.c @@ -0,0 +1,236 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2011 - 2012 Red Hat, Inc. + */ + +#include "config.h" + +#include <string.h> +#include <glib/gi18n-lib.h> + +#include "nm-glib-compat.h" + +#include <nm-setting-connection.h> +#include <nm-setting-infiniband.h> +#include <nm-utils.h> + +#include "nm-device-infiniband.h" +#include "nm-device-private.h" +#include "nm-object-private.h" + +G_DEFINE_TYPE (NMDeviceInfiniband, nm_device_infiniband, NM_TYPE_DEVICE) + +#define NM_DEVICE_INFINIBAND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_INFINIBAND, NMDeviceInfinibandPrivate)) + +typedef struct { + char *hw_address; + gboolean carrier; +} NMDeviceInfinibandPrivate; + +enum { + PROP_0, + PROP_HW_ADDRESS, + PROP_CARRIER, + + LAST_PROP +}; + +/** + * nm_device_infiniband_get_hw_address: + * @device: a #NMDeviceInfiniband + * + * Gets the hardware (MAC) address of the #NMDeviceInfiniband + * + * Returns: the hardware address. This is the internal string used by the + * device, and must not be modified. + **/ +const char * +nm_device_infiniband_get_hw_address (NMDeviceInfiniband *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_INFINIBAND (device), NULL); + + return NM_DEVICE_INFINIBAND_GET_PRIVATE (device)->hw_address; +} + +/** + * nm_device_infiniband_get_carrier: + * @device: a #NMDeviceInfiniband + * + * Whether the device has carrier. + * + * Returns: %TRUE if the device has carrier + **/ +gboolean +nm_device_infiniband_get_carrier (NMDeviceInfiniband *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_INFINIBAND (device), FALSE); + + return NM_DEVICE_INFINIBAND_GET_PRIVATE (device)->carrier; +} + +static gboolean +connection_compatible (NMDevice *device, NMConnection *connection, GError **error) +{ + NMSettingInfiniband *s_infiniband; + const char *hwaddr, *setting_hwaddr; + + if (!NM_DEVICE_CLASS (nm_device_infiniband_parent_class)->connection_compatible (device, connection, error)) + return FALSE; + + if (!nm_connection_is_type (connection, NM_SETTING_INFINIBAND_SETTING_NAME)) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + _("The connection was not an InfiniBand connection.")); + return FALSE; + } + + hwaddr = nm_device_infiniband_get_hw_address (NM_DEVICE_INFINIBAND (device)); + if (hwaddr) { + if (!nm_utils_hwaddr_valid (hwaddr, INFINIBAND_ALEN)) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, + _("Invalid device MAC address.")); + return FALSE; + } + + s_infiniband = nm_connection_get_setting_infiniband (connection); + setting_hwaddr = nm_setting_infiniband_get_mac_address (s_infiniband); + if (setting_hwaddr && !nm_utils_hwaddr_matches (setting_hwaddr, -1, hwaddr, -1)) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + _("The MACs of the device and the connection didn't match.")); + return FALSE; + } + } + + return TRUE; +} + +static GType +get_setting_type (NMDevice *device) +{ + return NM_TYPE_SETTING_INFINIBAND; +} + +static const char * +get_hw_address (NMDevice *device) +{ + return nm_device_infiniband_get_hw_address (NM_DEVICE_INFINIBAND (device)); +} + +/***********************************************************/ + +static void +nm_device_infiniband_init (NMDeviceInfiniband *device) +{ + _nm_device_set_device_type (NM_DEVICE (device), NM_DEVICE_TYPE_INFINIBAND); +} + +static void +init_dbus (NMObject *object) +{ + NMDeviceInfinibandPrivate *priv = NM_DEVICE_INFINIBAND_GET_PRIVATE (object); + const NMPropertiesInfo property_info[] = { + { NM_DEVICE_INFINIBAND_HW_ADDRESS, &priv->hw_address }, + { NM_DEVICE_INFINIBAND_CARRIER, &priv->carrier }, + { NULL }, + }; + + NM_OBJECT_CLASS (nm_device_infiniband_parent_class)->init_dbus (object); + + _nm_object_register_properties (object, + NM_DBUS_INTERFACE_DEVICE_INFINIBAND, + property_info); +} + +static void +finalize (GObject *object) +{ + NMDeviceInfinibandPrivate *priv = NM_DEVICE_INFINIBAND_GET_PRIVATE (object); + + g_free (priv->hw_address); + + G_OBJECT_CLASS (nm_device_infiniband_parent_class)->finalize (object); +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMDeviceInfiniband *device = NM_DEVICE_INFINIBAND (object); + + switch (prop_id) { + case PROP_HW_ADDRESS: + g_value_set_string (value, nm_device_infiniband_get_hw_address (device)); + break; + case PROP_CARRIER: + g_value_set_boolean (value, nm_device_infiniband_get_carrier (device)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_device_infiniband_class_init (NMDeviceInfinibandClass *ib_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (ib_class); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (ib_class); + NMDeviceClass *device_class = NM_DEVICE_CLASS (ib_class); + + g_type_class_add_private (ib_class, sizeof (NMDeviceInfinibandPrivate)); + + _nm_object_class_add_interface (nm_object_class, NM_DBUS_INTERFACE_DEVICE_INFINIBAND); + + /* virtual methods */ + object_class->finalize = finalize; + object_class->get_property = get_property; + + nm_object_class->init_dbus = init_dbus; + + device_class->connection_compatible = connection_compatible; + device_class->get_setting_type = get_setting_type; + device_class->get_hw_address = get_hw_address; + + /* properties */ + + /** + * NMDeviceInfiniband:hw-address: + * + * The hardware (MAC) address of the device. + **/ + g_object_class_install_property + (object_class, PROP_HW_ADDRESS, + g_param_spec_string (NM_DEVICE_INFINIBAND_HW_ADDRESS, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceInfiniband:carrier: + * + * Whether the device has carrier. + **/ + g_object_class_install_property + (object_class, PROP_CARRIER, + g_param_spec_boolean (NM_DEVICE_INFINIBAND_CARRIER, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + +} diff --git a/libnm/nm-device-infiniband.h b/libnm/nm-device-infiniband.h new file mode 100644 index 00000000..c1f9be07 --- /dev/null +++ b/libnm/nm-device-infiniband.h @@ -0,0 +1,60 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2011 - 2012 Red Hat, Inc. + */ + +#ifndef __NM_DEVICE_INFINIBAND_H__ +#define __NM_DEVICE_INFINIBAND_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include <nm-device.h> + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_INFINIBAND (nm_device_infiniband_get_type ()) +#define NM_DEVICE_INFINIBAND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_INFINIBAND, NMDeviceInfiniband)) +#define NM_DEVICE_INFINIBAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_INFINIBAND, NMDeviceInfinibandClass)) +#define NM_IS_DEVICE_INFINIBAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_INFINIBAND)) +#define NM_IS_DEVICE_INFINIBAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_INFINIBAND)) +#define NM_DEVICE_INFINIBAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_INFINIBAND, NMDeviceInfinibandClass)) + +#define NM_DEVICE_INFINIBAND_HW_ADDRESS "hw-address" +#define NM_DEVICE_INFINIBAND_CARRIER "carrier" + +struct _NMDeviceInfiniband { + NMDevice parent; +}; + +typedef struct { + NMDeviceClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMDeviceInfinibandClass; + +GType nm_device_infiniband_get_type (void); + +const char * nm_device_infiniband_get_hw_address (NMDeviceInfiniband *device); +gboolean nm_device_infiniband_get_carrier (NMDeviceInfiniband *device); + +G_END_DECLS + +#endif /* __NM_DEVICE_INFINIBAND_H__ */ diff --git a/libnm/nm-device-modem.c b/libnm/nm-device-modem.c new file mode 100644 index 00000000..dcbb447a --- /dev/null +++ b/libnm/nm-device-modem.c @@ -0,0 +1,254 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2011 - 2012 Red Hat, Inc. + * Copyright 2008 Novell, Inc. + */ + +#include "config.h" + +#include <string.h> +#include <glib/gi18n-lib.h> + +#include "nm-glib-compat.h" + +#include <nm-setting-connection.h> +#include <nm-setting-gsm.h> +#include <nm-setting-cdma.h> + +#include "nm-device-modem.h" +#include "nm-device-private.h" +#include "nm-object-private.h" +#include "nm-enum-types.h" + +G_DEFINE_TYPE (NMDeviceModem, nm_device_modem, NM_TYPE_DEVICE) + +#define NM_DEVICE_MODEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_MODEM, NMDeviceModemPrivate)) + +typedef struct { + NMDeviceModemCapabilities caps; + NMDeviceModemCapabilities current_caps; +} NMDeviceModemPrivate; + +enum { + PROP_0, + PROP_MODEM_CAPS, + PROP_CURRENT_CAPS, + LAST_PROP +}; + +/** + * nm_device_modem_get_modem_capabilities: + * @self: a #NMDeviceModem + * + * Returns a bitfield of the generic access technology families the modem + * supports. Not all capabilities are available concurrently however; some + * may require a firmware reload or reinitialization. + * + * Returns: the generic access technology families the modem supports + **/ +NMDeviceModemCapabilities +nm_device_modem_get_modem_capabilities (NMDeviceModem *self) +{ + g_return_val_if_fail (NM_IS_DEVICE_MODEM (self), NM_DEVICE_MODEM_CAPABILITY_NONE); + + return NM_DEVICE_MODEM_GET_PRIVATE (self)->caps; +} + +/** + * nm_device_modem_get_current_capabilities: + * @self: a #NMDeviceModem + * + * Returns a bitfield of the generic access technology families the modem + * supports without a firmware reload or reinitialization. This value + * represents the network types the modem can immediately connect to. + * + * Returns: the generic access technology families the modem supports without + * a firmware reload or other reinitialization + **/ +NMDeviceModemCapabilities +nm_device_modem_get_current_capabilities (NMDeviceModem *self) +{ + g_return_val_if_fail (NM_IS_DEVICE_MODEM (self), NM_DEVICE_MODEM_CAPABILITY_NONE); + + return NM_DEVICE_MODEM_GET_PRIVATE (self)->current_caps; +} + +static const char * +get_type_description (NMDevice *device) +{ + NMDeviceModemCapabilities caps; + + caps = nm_device_modem_get_current_capabilities (NM_DEVICE_MODEM (device)); + if (caps & NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS) + return "gsm"; + else if (caps & NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO) + return "cdma"; + else + return NULL; +} + +#define MODEM_CAPS_3GPP(caps) (caps & (NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS | \ + NM_DEVICE_MODEM_CAPABILITY_LTE)) + +#define MODEM_CAPS_3GPP2(caps) (caps & (NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO)) + +static gboolean +connection_compatible (NMDevice *device, NMConnection *connection, GError **error) +{ + NMSettingGsm *s_gsm; + NMSettingCdma *s_cdma; + NMDeviceModemCapabilities current_caps; + + if (!NM_DEVICE_CLASS (nm_device_modem_parent_class)->connection_compatible (device, connection, error)) + return FALSE; + + if ( !nm_connection_is_type (connection, NM_SETTING_GSM_SETTING_NAME) + && !nm_connection_is_type (connection, NM_SETTING_CDMA_SETTING_NAME)) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + _("The connection was not a modem connection.")); + return FALSE; + } + + s_gsm = nm_connection_get_setting_gsm (connection); + s_cdma = nm_connection_get_setting_cdma (connection); + if (!s_cdma && !s_gsm) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION, + _("The connection was not a valid modem connection.")); + return FALSE; + } + + current_caps = nm_device_modem_get_current_capabilities (NM_DEVICE_MODEM (device)); + if (!(s_gsm && MODEM_CAPS_3GPP (current_caps)) && !(s_cdma && MODEM_CAPS_3GPP2 (current_caps))) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + _("The device is lacking capabilities required by the connection.")); + return FALSE; + } + + return TRUE; +} + +static GType +get_setting_type (NMDevice *device) +{ + NMDeviceModemCapabilities caps; + + caps = nm_device_modem_get_current_capabilities (NM_DEVICE_MODEM (device)); + if (caps & (NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS | NM_DEVICE_MODEM_CAPABILITY_LTE)) + return NM_TYPE_SETTING_GSM; + else if (caps & NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO) + return NM_TYPE_SETTING_CDMA; + else + return G_TYPE_INVALID; +} + +/*******************************************************************/ + +static void +nm_device_modem_init (NMDeviceModem *device) +{ + _nm_device_set_device_type (NM_DEVICE (device), NM_DEVICE_TYPE_MODEM); +} + +static void +init_dbus (NMObject *object) +{ + NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (object); + const NMPropertiesInfo property_info[] = { + { NM_DEVICE_MODEM_MODEM_CAPABILITIES, &priv->caps }, + { NM_DEVICE_MODEM_CURRENT_CAPABILITIES, &priv->current_caps }, + { NULL }, + }; + + NM_OBJECT_CLASS (nm_device_modem_parent_class)->init_dbus (object); + + _nm_object_register_properties (object, + NM_DBUS_INTERFACE_DEVICE_MODEM, + property_info); +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMDeviceModem *self = NM_DEVICE_MODEM (object); + + switch (prop_id) { + case PROP_MODEM_CAPS: + g_value_set_flags (value, nm_device_modem_get_modem_capabilities (self)); + break; + case PROP_CURRENT_CAPS: + g_value_set_flags (value, nm_device_modem_get_current_capabilities (self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_device_modem_class_init (NMDeviceModemClass *modem_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (modem_class); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (modem_class); + NMDeviceClass *device_class = NM_DEVICE_CLASS (modem_class); + + g_type_class_add_private (modem_class, sizeof (NMDeviceModemPrivate)); + + _nm_object_class_add_interface (nm_object_class, NM_DBUS_INTERFACE_DEVICE_MODEM); + + /* virtual methods */ + object_class->get_property = get_property; + + nm_object_class->init_dbus = init_dbus; + + device_class->get_type_description = get_type_description; + device_class->connection_compatible = connection_compatible; + device_class->get_setting_type = get_setting_type; + + /** + * NMDeviceModem:modem-capabilities: + * + * The generic family of access technologies the modem supports. Not all + * capabilities are available at the same time however; some modems require + * a firmware reload or other reinitialization to switch between eg + * CDMA/EVDO and GSM/UMTS. + **/ + g_object_class_install_property + (object_class, PROP_MODEM_CAPS, + g_param_spec_flags (NM_DEVICE_MODEM_MODEM_CAPABILITIES, "", "", + NM_TYPE_DEVICE_MODEM_CAPABILITIES, + NM_DEVICE_MODEM_CAPABILITY_NONE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceModem:current-capabilities: + * + * The generic family of access technologies the modem currently supports + * without a firmware reload or reinitialization. + **/ + g_object_class_install_property + (object_class, PROP_CURRENT_CAPS, + g_param_spec_flags (NM_DEVICE_MODEM_CURRENT_CAPABILITIES, "", "", + NM_TYPE_DEVICE_MODEM_CAPABILITIES, + NM_DEVICE_MODEM_CAPABILITY_NONE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); +} diff --git a/libnm/nm-device-modem.h b/libnm/nm-device-modem.h new file mode 100644 index 00000000..38a4ddbb --- /dev/null +++ b/libnm/nm-device-modem.h @@ -0,0 +1,61 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2011 - 2012 Red Hat, Inc. + * Copyright 2008 Novell, Inc. + */ + +#ifndef __NM_DEVICE_MODEM_H__ +#define __NM_DEVICE_MODEM_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include <nm-device.h> + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_MODEM (nm_device_modem_get_type ()) +#define NM_DEVICE_MODEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_MODEM, NMDeviceModem)) +#define NM_DEVICE_MODEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_MODEM, NMDeviceModemClass)) +#define NM_IS_DEVICE_MODEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_MODEM)) +#define NM_IS_DEVICE_MODEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_MODEM)) +#define NM_DEVICE_MODEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_MODEM, NMDeviceModemClass)) + +#define NM_DEVICE_MODEM_MODEM_CAPABILITIES "modem-capabilities" +#define NM_DEVICE_MODEM_CURRENT_CAPABILITIES "current-capabilities" + +struct _NMDeviceModem { + NMDevice parent; +}; + +typedef struct { + NMDeviceClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMDeviceModemClass; + +GType nm_device_modem_get_type (void); + +NMDeviceModemCapabilities nm_device_modem_get_modem_capabilities (NMDeviceModem *self); +NMDeviceModemCapabilities nm_device_modem_get_current_capabilities (NMDeviceModem *self); + +G_END_DECLS + +#endif /* __NM_DEVICE_MODEM_H__ */ diff --git a/libnm/nm-device-olpc-mesh.c b/libnm/nm-device-olpc-mesh.c new file mode 100644 index 00000000..108e5339 --- /dev/null +++ b/libnm/nm-device-olpc-mesh.c @@ -0,0 +1,261 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2012 Red Hat, Inc. + */ + +#include "config.h" + +#include <string.h> +#include <glib/gi18n-lib.h> + +#include "nm-glib-compat.h" + +#include <nm-setting-connection.h> +#include <nm-setting-olpc-mesh.h> + +#include "nm-device-olpc-mesh.h" +#include "nm-device-private.h" +#include "nm-object-private.h" +#include "nm-device-wifi.h" + +G_DEFINE_TYPE (NMDeviceOlpcMesh, nm_device_olpc_mesh, NM_TYPE_DEVICE) + +#define NM_DEVICE_OLPC_MESH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_OLPC_MESH, NMDeviceOlpcMeshPrivate)) + +typedef struct { + char *hw_address; + NMDeviceWifi *companion; + guint32 active_channel; +} NMDeviceOlpcMeshPrivate; + +enum { + PROP_0, + PROP_HW_ADDRESS, + PROP_COMPANION, + PROP_ACTIVE_CHANNEL, + + LAST_PROP +}; + +/** + * nm_device_olpc_mesh_get_hw_address: + * @device: a #NMDeviceOlpcMesh + * + * Gets the hardware (MAC) address of the #NMDeviceOlpcMesh + * + * Returns: the hardware address. This is the internal string used by the + * device, and must not be modified. + **/ +const char * +nm_device_olpc_mesh_get_hw_address (NMDeviceOlpcMesh *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_OLPC_MESH (device), NULL); + + return NM_DEVICE_OLPC_MESH_GET_PRIVATE (device)->hw_address; +} + +/** + * nm_device_olpc_mesh_get_companion: + * @device: a #NMDeviceOlpcMesh + * + * Gets the companion device of the #NMDeviceOlpcMesh. + * + * Returns: (transfer none): the companion of the device of %NULL + **/ +NMDeviceWifi * +nm_device_olpc_mesh_get_companion (NMDeviceOlpcMesh *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_OLPC_MESH (device), NULL); + + return NM_DEVICE_OLPC_MESH_GET_PRIVATE (device)->companion; +} + +/** + * nm_device_olpc_mesh_get_active_channel: + * @device: a #NMDeviceOlpcMesh + * + * Returns the active channel of the #NMDeviceOlpcMesh device. + * + * Returns: active channel of the device + **/ +guint32 +nm_device_olpc_mesh_get_active_channel (NMDeviceOlpcMesh *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_OLPC_MESH (device), 0); + + return NM_DEVICE_OLPC_MESH_GET_PRIVATE (device)->active_channel; +} + +static const char * +get_hw_address (NMDevice *device) +{ + return nm_device_olpc_mesh_get_hw_address (NM_DEVICE_OLPC_MESH (device)); +} + +static gboolean +connection_compatible (NMDevice *device, NMConnection *connection, GError **error) +{ + if (!NM_DEVICE_CLASS (nm_device_olpc_mesh_parent_class)->connection_compatible (device, connection, error)) + return FALSE; + + if (!nm_connection_is_type (connection, NM_SETTING_OLPC_MESH_SETTING_NAME)) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + _("The connection was not an OLPC Mesh connection.")); + return FALSE; + } + + return TRUE; +} + +static GType +get_setting_type (NMDevice *device) +{ + return NM_TYPE_SETTING_OLPC_MESH; +} + +/**************************************************************/ + +static void +nm_device_olpc_mesh_init (NMDeviceOlpcMesh *device) +{ + _nm_device_set_device_type (NM_DEVICE (device), NM_DEVICE_TYPE_OLPC_MESH); +} + +static void +init_dbus (NMObject *object) +{ + NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (object); + const NMPropertiesInfo property_info[] = { + { NM_DEVICE_OLPC_MESH_HW_ADDRESS, &priv->hw_address }, + { NM_DEVICE_OLPC_MESH_COMPANION, &priv->companion, NULL, NM_TYPE_DEVICE_WIFI }, + { NM_DEVICE_OLPC_MESH_ACTIVE_CHANNEL, &priv->active_channel }, + { NULL }, + }; + + NM_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->init_dbus (object); + + _nm_object_register_properties (object, + NM_DBUS_INTERFACE_DEVICE_OLPC_MESH, + property_info); +} + +static void +dispose (GObject *object) +{ + NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (object); + + g_clear_object (&priv->companion); + + G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (object); + + g_free (priv->hw_address); + + G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->finalize (object); +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMDeviceOlpcMesh *device = NM_DEVICE_OLPC_MESH (object); + + switch (prop_id) { + case PROP_HW_ADDRESS: + g_value_set_string (value, nm_device_olpc_mesh_get_hw_address (device)); + break; + case PROP_COMPANION: + g_value_set_object (value, nm_device_olpc_mesh_get_companion (device)); + break; + case PROP_ACTIVE_CHANNEL: + g_value_set_uint (value, nm_device_olpc_mesh_get_active_channel (device)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_device_olpc_mesh_class_init (NMDeviceOlpcMeshClass *olpc_mesh_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (olpc_mesh_class); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (olpc_mesh_class); + NMDeviceClass *device_class = NM_DEVICE_CLASS (olpc_mesh_class); + + g_type_class_add_private (olpc_mesh_class, sizeof (NMDeviceOlpcMeshPrivate)); + + _nm_object_class_add_interface (nm_object_class, NM_DBUS_INTERFACE_DEVICE_OLPC_MESH); + + /* virtual methods */ + object_class->dispose = dispose; + object_class->finalize = finalize; + object_class->get_property = get_property; + + nm_object_class->init_dbus = init_dbus; + + device_class->connection_compatible = connection_compatible; + device_class->get_setting_type = get_setting_type; + device_class->get_hw_address = get_hw_address; + + /* properties */ + + /** + * NMDeviceOlpcMesh:hw-address: + * + * The hardware (MAC) address of the device. + **/ + g_object_class_install_property + (object_class, PROP_HW_ADDRESS, + g_param_spec_string (NM_DEVICE_OLPC_MESH_HW_ADDRESS, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceOlpcMesh:companion: + * + * The companion device. + **/ + g_object_class_install_property + (object_class, PROP_COMPANION, + g_param_spec_object (NM_DEVICE_OLPC_MESH_COMPANION, "", "", + NM_TYPE_DEVICE_WIFI, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceOlpcMesh:active-channel: + * + * The device's active channel. + **/ + g_object_class_install_property + (object_class, PROP_ACTIVE_CHANNEL, + g_param_spec_uint (NM_DEVICE_OLPC_MESH_ACTIVE_CHANNEL, "", "", + 0, G_MAXUINT32, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + +} diff --git a/libnm/nm-device-olpc-mesh.h b/libnm/nm-device-olpc-mesh.h new file mode 100644 index 00000000..b5899445 --- /dev/null +++ b/libnm/nm-device-olpc-mesh.h @@ -0,0 +1,62 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2012 Red Hat, Inc. + */ + +#ifndef __NM_DEVICE_OLPC_MESH_H__ +#define __NM_DEVICE_OLPC_MESH_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include <nm-device.h> + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_OLPC_MESH (nm_device_olpc_mesh_get_type ()) +#define NM_DEVICE_OLPC_MESH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_OLPC_MESH, NMDeviceOlpcMesh)) +#define NM_DEVICE_OLPC_MESH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_OLPC_MESH, NMDeviceOlpcMeshClass)) +#define NM_IS_DEVICE_OLPC_MESH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_OLPC_MESH)) +#define NM_IS_DEVICE_OLPC_MESH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_OLPC_MESH)) +#define NM_DEVICE_OLPC_MESH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_OLPC_MESH, NMDeviceOlpcMeshClass)) + +#define NM_DEVICE_OLPC_MESH_HW_ADDRESS "hw-address" +#define NM_DEVICE_OLPC_MESH_COMPANION "companion" +#define NM_DEVICE_OLPC_MESH_ACTIVE_CHANNEL "active-channel" + +struct _NMDeviceOlpcMesh { + NMDevice parent; +}; + +typedef struct { + NMDeviceClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMDeviceOlpcMeshClass; + +GType nm_device_olpc_mesh_get_type (void); + +const char *nm_device_olpc_mesh_get_hw_address (NMDeviceOlpcMesh *device); +NMDeviceWifi *nm_device_olpc_mesh_get_companion (NMDeviceOlpcMesh *device); +guint32 nm_device_olpc_mesh_get_active_channel (NMDeviceOlpcMesh *device); + +G_END_DECLS + +#endif /* __NM_DEVICE_OLPC_MESH_H__ */ diff --git a/libnm/nm-device-private.h b/libnm/nm-device-private.h new file mode 100644 index 00000000..66fc6b6b --- /dev/null +++ b/libnm/nm-device-private.h @@ -0,0 +1,26 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2007 - 2012 Red Hat, Inc. + */ + +#ifndef __NM_DEVICE_PRIVATE_H__ +#define __NM_DEVICE_PRIVATE_H__ + +void _nm_device_set_device_type (NMDevice *device, NMDeviceType dtype); + +#endif /* __NM_DEVICE_PRIVATE_H__ */ diff --git a/libnm/nm-device-team.c b/libnm/nm-device-team.c new file mode 100644 index 00000000..cff1d718 --- /dev/null +++ b/libnm/nm-device-team.c @@ -0,0 +1,271 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2013 Jiri Pirko <jiri@resnulli.us> + */ + +#include "config.h" + +#include <string.h> +#include <glib/gi18n-lib.h> + +#include "nm-glib-compat.h" + +#include <nm-setting-connection.h> +#include <nm-setting-team.h> +#include <nm-utils.h> + +#include "nm-device-team.h" +#include "nm-device-private.h" +#include "nm-object-private.h" +#include "nm-core-internal.h" + +G_DEFINE_TYPE (NMDeviceTeam, nm_device_team, NM_TYPE_DEVICE) + +#define NM_DEVICE_TEAM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_TEAM, NMDeviceTeamPrivate)) + +typedef struct { + char *hw_address; + gboolean carrier; + GPtrArray *slaves; +} NMDeviceTeamPrivate; + +enum { + PROP_0, + PROP_HW_ADDRESS, + PROP_CARRIER, + PROP_SLAVES, + + LAST_PROP +}; + +/** + * nm_device_team_get_hw_address: + * @device: a #NMDeviceTeam + * + * Gets the hardware (MAC) address of the #NMDeviceTeam + * + * Returns: the hardware address. This is the internal string used by the + * device, and must not be modified. + **/ +const char * +nm_device_team_get_hw_address (NMDeviceTeam *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_TEAM (device), NULL); + + return NM_DEVICE_TEAM_GET_PRIVATE (device)->hw_address; +} + +/** + * nm_device_team_get_carrier: + * @device: a #NMDeviceTeam + * + * Whether the device has carrier. + * + * Returns: %TRUE if the device has carrier + **/ +gboolean +nm_device_team_get_carrier (NMDeviceTeam *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_TEAM (device), FALSE); + + return NM_DEVICE_TEAM_GET_PRIVATE (device)->carrier; +} + +/** + * nm_device_team_get_slaves: + * @device: a #NMDeviceTeam + * + * Gets the devices currently enslaved to @device. + * + * Returns: (element-type NMDevice): the #GPtrArray containing + * #NMDevices that are slaves of @device. This is the internal + * copy used by the device, and must not be modified. + **/ +const GPtrArray * +nm_device_team_get_slaves (NMDeviceTeam *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_TEAM (device), FALSE); + + return NM_DEVICE_TEAM_GET_PRIVATE (device)->slaves; +} + +static const char * +get_hw_address (NMDevice *device) +{ + return nm_device_team_get_hw_address (NM_DEVICE_TEAM (device)); +} + +static gboolean +connection_compatible (NMDevice *device, NMConnection *connection, GError **error) +{ + if (!NM_DEVICE_CLASS (nm_device_team_parent_class)->connection_compatible (device, connection, error)) + return FALSE; + + if (!nm_connection_is_type (connection, NM_SETTING_TEAM_SETTING_NAME)) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION, + _("The connection was not a team connection.")); + return FALSE; + } + + /* FIXME: check slaves? */ + + return TRUE; +} + +static GType +get_setting_type (NMDevice *device) +{ + return NM_TYPE_SETTING_TEAM; +} + +/***********************************************************/ + +static void +nm_device_team_init (NMDeviceTeam *device) +{ + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (device); + + _nm_device_set_device_type (NM_DEVICE (device), NM_DEVICE_TYPE_TEAM); + + priv->slaves = g_ptr_array_new (); +} + +static void +init_dbus (NMObject *object) +{ + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (object); + const NMPropertiesInfo property_info[] = { + { NM_DEVICE_TEAM_HW_ADDRESS, &priv->hw_address }, + { NM_DEVICE_TEAM_CARRIER, &priv->carrier }, + { NM_DEVICE_TEAM_SLAVES, &priv->slaves, NULL, NM_TYPE_DEVICE }, + { NULL }, + }; + + NM_OBJECT_CLASS (nm_device_team_parent_class)->init_dbus (object); + + _nm_object_register_properties (object, + NM_DBUS_INTERFACE_DEVICE_TEAM, + property_info); +} + +static void +dispose (GObject *object) +{ + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (object); + + g_clear_pointer (&priv->slaves, g_ptr_array_unref); + + G_OBJECT_CLASS (nm_device_team_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (object); + + g_free (priv->hw_address); + + G_OBJECT_CLASS (nm_device_team_parent_class)->finalize (object); +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMDeviceTeam *device = NM_DEVICE_TEAM (object); + + switch (prop_id) { + case PROP_HW_ADDRESS: + g_value_set_string (value, nm_device_team_get_hw_address (device)); + break; + case PROP_CARRIER: + g_value_set_boolean (value, nm_device_team_get_carrier (device)); + break; + case PROP_SLAVES: + g_value_take_boxed (value, _nm_utils_copy_object_array (nm_device_team_get_slaves (device))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_device_team_class_init (NMDeviceTeamClass *team_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (team_class); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (team_class); + NMDeviceClass *device_class = NM_DEVICE_CLASS (team_class); + + g_type_class_add_private (team_class, sizeof (NMDeviceTeamPrivate)); + + _nm_object_class_add_interface (nm_object_class, NM_DBUS_INTERFACE_DEVICE_TEAM); + + /* virtual methods */ + object_class->dispose = dispose; + object_class->finalize = finalize; + object_class->get_property = get_property; + + nm_object_class->init_dbus = init_dbus; + + device_class->connection_compatible = connection_compatible; + device_class->get_setting_type = get_setting_type; + device_class->get_hw_address = get_hw_address; + + /* properties */ + + /** + * NMDeviceTeam:hw-address: + * + * The hardware (MAC) address of the device. + **/ + g_object_class_install_property + (object_class, PROP_HW_ADDRESS, + g_param_spec_string (NM_DEVICE_TEAM_HW_ADDRESS, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceTeam:carrier: + * + * Whether the device has carrier. + **/ + g_object_class_install_property + (object_class, PROP_CARRIER, + g_param_spec_boolean (NM_DEVICE_TEAM_CARRIER, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceTeam:slaves: + * + * The devices enslaved to the team device. + * + * Element-type: NMDevice + **/ + g_object_class_install_property + (object_class, PROP_SLAVES, + g_param_spec_boxed (NM_DEVICE_TEAM_SLAVES, "", "", + G_TYPE_PTR_ARRAY, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); +} diff --git a/libnm/nm-device-team.h b/libnm/nm-device-team.h new file mode 100644 index 00000000..a7185795 --- /dev/null +++ b/libnm/nm-device-team.h @@ -0,0 +1,62 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2013 Jiri Pirko <jiri@resnulli.us> + */ + +#ifndef __NM_DEVICE_TEAM_H__ +#define __NM_DEVICE_TEAM_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include <nm-device.h> + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_TEAM (nm_device_team_get_type ()) +#define NM_DEVICE_TEAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_TEAM, NMDeviceTeam)) +#define NM_DEVICE_TEAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_TEAM, NMDeviceTeamClass)) +#define NM_IS_DEVICE_TEAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_TEAM)) +#define NM_IS_DEVICE_TEAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_TEAM)) +#define NM_DEVICE_TEAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_TEAM, NMDeviceTeamClass)) + +#define NM_DEVICE_TEAM_HW_ADDRESS "hw-address" +#define NM_DEVICE_TEAM_CARRIER "carrier" +#define NM_DEVICE_TEAM_SLAVES "slaves" + +struct _NMDeviceTeam { + NMDevice parent; +}; + +typedef struct { + NMDeviceClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMDeviceTeamClass; + +GType nm_device_team_get_type (void); + +const char *nm_device_team_get_hw_address (NMDeviceTeam *device); +gboolean nm_device_team_get_carrier (NMDeviceTeam *device); +const GPtrArray *nm_device_team_get_slaves (NMDeviceTeam *device); + +G_END_DECLS + +#endif /* __NM_DEVICE_TEAM_H__ */ diff --git a/libnm/nm-device-vlan.c b/libnm/nm-device-vlan.c new file mode 100644 index 00000000..fb6e3bd7 --- /dev/null +++ b/libnm/nm-device-vlan.c @@ -0,0 +1,305 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2012 Red Hat, Inc. + */ + +#include "config.h" + +#include <string.h> +#include <glib/gi18n-lib.h> + +#include "nm-glib-compat.h" + +#include <nm-setting-connection.h> +#include <nm-setting-vlan.h> +#include <nm-setting-wired.h> +#include <nm-utils.h> + +#include "nm-device-vlan.h" +#include "nm-device-private.h" +#include "nm-object-private.h" + +G_DEFINE_TYPE (NMDeviceVlan, nm_device_vlan, NM_TYPE_DEVICE) + +#define NM_DEVICE_VLAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_VLAN, NMDeviceVlanPrivate)) + +typedef struct { + char *hw_address; + gboolean carrier; + NMDevice *parent; + guint vlan_id; +} NMDeviceVlanPrivate; + +enum { + PROP_0, + PROP_HW_ADDRESS, + PROP_CARRIER, + PROP_PARENT, + PROP_VLAN_ID, + + LAST_PROP +}; + +/** + * nm_device_vlan_get_hw_address: + * @device: a #NMDeviceVlan + * + * Gets the hardware (MAC) address of the #NMDeviceVlan + * + * Returns: the hardware address. This is the internal string used by the + * device, and must not be modified. + **/ +const char * +nm_device_vlan_get_hw_address (NMDeviceVlan *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_VLAN (device), NULL); + + return NM_DEVICE_VLAN_GET_PRIVATE (device)->hw_address; +} + +/** + * nm_device_vlan_get_carrier: + * @device: a #NMDeviceVlan + * + * Whether the device has carrier. + * + * Returns: %TRUE if the device has carrier + **/ +gboolean +nm_device_vlan_get_carrier (NMDeviceVlan *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_VLAN (device), FALSE); + + return NM_DEVICE_VLAN_GET_PRIVATE (device)->carrier; +} + +/** + * nm_device_vlan_get_parent: + * @device: a #NMDeviceVlan + * + * Returns: (transfer none): the device's parent device + **/ +NMDevice * +nm_device_vlan_get_parent (NMDeviceVlan *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_VLAN (device), FALSE); + + return NM_DEVICE_VLAN_GET_PRIVATE (device)->parent; +} + +/** + * nm_device_vlan_get_vlan_id: + * @device: a #NMDeviceVlan + * + * Returns: the device's VLAN ID + **/ +guint +nm_device_vlan_get_vlan_id (NMDeviceVlan *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_VLAN (device), FALSE); + + return NM_DEVICE_VLAN_GET_PRIVATE (device)->vlan_id; +} + +static gboolean +connection_compatible (NMDevice *device, NMConnection *connection, GError **error) +{ + NMSettingVlan *s_vlan; + NMSettingWired *s_wired; + const char *setting_hwaddr; + + if (!NM_DEVICE_CLASS (nm_device_vlan_parent_class)->connection_compatible (device, connection, error)) + return FALSE; + + if (!nm_connection_is_type (connection, NM_SETTING_VLAN_SETTING_NAME)) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + _("The connection was not a VLAN connection.")); + return FALSE; + } + + s_vlan = nm_connection_get_setting_vlan (connection); + if (nm_setting_vlan_get_id (s_vlan) != nm_device_vlan_get_vlan_id (NM_DEVICE_VLAN (device))) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + _("The VLAN identifiers of the device and the connection didn't match.")); + return FALSE; + } + + s_wired = nm_connection_get_setting_wired (connection); + if (s_wired) + setting_hwaddr = nm_setting_wired_get_mac_address (s_wired); + else + setting_hwaddr = NULL; + if (setting_hwaddr) { + if (!nm_utils_hwaddr_matches (setting_hwaddr, -1, + NM_DEVICE_VLAN_GET_PRIVATE (device)->hw_address, -1)) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + _("The hardware address of the device and the connection didn't match.")); + } + } + + return TRUE; +} + +static GType +get_setting_type (NMDevice *device) +{ + return NM_TYPE_SETTING_VLAN; +} + +static const char * +get_hw_address (NMDevice *device) +{ + return nm_device_vlan_get_hw_address (NM_DEVICE_VLAN (device)); +} + +/***********************************************************/ + +static void +nm_device_vlan_init (NMDeviceVlan *device) +{ + _nm_device_set_device_type (NM_DEVICE (device), NM_DEVICE_TYPE_VLAN); +} + +static void +init_dbus (NMObject *object) +{ + NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (object); + const NMPropertiesInfo property_info[] = { + { NM_DEVICE_VLAN_HW_ADDRESS, &priv->hw_address }, + { NM_DEVICE_VLAN_CARRIER, &priv->carrier }, + { NM_DEVICE_VLAN_PARENT, &priv->parent, NULL, NM_TYPE_DEVICE }, + { NM_DEVICE_VLAN_VLAN_ID, &priv->vlan_id }, + { NULL }, + }; + + NM_OBJECT_CLASS (nm_device_vlan_parent_class)->init_dbus (object); + + _nm_object_register_properties (object, + NM_DBUS_INTERFACE_DEVICE_VLAN, + property_info); +} + +static void +finalize (GObject *object) +{ + NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (object); + + g_free (priv->hw_address); + g_clear_object (&priv->parent); + + G_OBJECT_CLASS (nm_device_vlan_parent_class)->finalize (object); +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMDeviceVlan *device = NM_DEVICE_VLAN (object); + + switch (prop_id) { + case PROP_HW_ADDRESS: + g_value_set_string (value, nm_device_vlan_get_hw_address (device)); + break; + case PROP_CARRIER: + g_value_set_boolean (value, nm_device_vlan_get_carrier (device)); + break; + case PROP_PARENT: + g_value_set_object (value, nm_device_vlan_get_parent (device)); + break; + case PROP_VLAN_ID: + g_value_set_uint (value, nm_device_vlan_get_vlan_id (device)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_device_vlan_class_init (NMDeviceVlanClass *vlan_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (vlan_class); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (vlan_class); + NMDeviceClass *device_class = NM_DEVICE_CLASS (vlan_class); + + g_type_class_add_private (vlan_class, sizeof (NMDeviceVlanPrivate)); + + _nm_object_class_add_interface (nm_object_class, NM_DBUS_INTERFACE_DEVICE_VLAN); + + /* virtual methods */ + object_class->finalize = finalize; + object_class->get_property = get_property; + + nm_object_class->init_dbus = init_dbus; + + device_class->connection_compatible = connection_compatible; + device_class->get_setting_type = get_setting_type; + device_class->get_hw_address = get_hw_address; + + /* properties */ + + /** + * NMDeviceVlan:hw-address: + * + * The hardware (MAC) address of the device. + **/ + g_object_class_install_property + (object_class, PROP_HW_ADDRESS, + g_param_spec_string (NM_DEVICE_VLAN_HW_ADDRESS, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceVlan:carrier: + * + * Whether the device has carrier. + **/ + g_object_class_install_property + (object_class, PROP_CARRIER, + g_param_spec_boolean (NM_DEVICE_VLAN_CARRIER, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceVlan:parent: + * + * The devices's parent device. + **/ + g_object_class_install_property + (object_class, PROP_PARENT, + g_param_spec_object (NM_DEVICE_VLAN_PARENT, "", "", + NM_TYPE_DEVICE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceVlan:vlan-id: + * + * The device's VLAN ID. + **/ + g_object_class_install_property + (object_class, PROP_VLAN_ID, + g_param_spec_uint (NM_DEVICE_VLAN_VLAN_ID, "", "", + 0, 4095, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); +} diff --git a/libnm/nm-device-vlan.h b/libnm/nm-device-vlan.h new file mode 100644 index 00000000..6ab24202 --- /dev/null +++ b/libnm/nm-device-vlan.h @@ -0,0 +1,64 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2012 - 2014 Red Hat, Inc. + */ + +#ifndef __NM_DEVICE_VLAN_H__ +#define __NM_DEVICE_VLAN_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include <nm-device.h> + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_VLAN (nm_device_vlan_get_type ()) +#define NM_DEVICE_VLAN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_VLAN, NMDeviceVlan)) +#define NM_DEVICE_VLAN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_VLAN, NMDeviceVlanClass)) +#define NM_IS_DEVICE_VLAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_VLAN)) +#define NM_IS_DEVICE_VLAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_VLAN)) +#define NM_DEVICE_VLAN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_VLAN, NMDeviceVlanClass)) + +#define NM_DEVICE_VLAN_HW_ADDRESS "hw-address" +#define NM_DEVICE_VLAN_CARRIER "carrier" +#define NM_DEVICE_VLAN_PARENT "parent" +#define NM_DEVICE_VLAN_VLAN_ID "vlan-id" + +struct _NMDeviceVlan { + NMDevice parent; +}; + +typedef struct { + NMDeviceClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMDeviceVlanClass; + +GType nm_device_vlan_get_type (void); + +const char * nm_device_vlan_get_hw_address (NMDeviceVlan *device); +gboolean nm_device_vlan_get_carrier (NMDeviceVlan *device); +NMDevice * nm_device_vlan_get_parent (NMDeviceVlan *device); +guint nm_device_vlan_get_vlan_id (NMDeviceVlan *device); + +G_END_DECLS + +#endif /* __NM_DEVICE_VLAN_H__ */ diff --git a/libnm/nm-device-wifi.c b/libnm/nm-device-wifi.c new file mode 100644 index 00000000..4a19f2e5 --- /dev/null +++ b/libnm/nm-device-wifi.c @@ -0,0 +1,837 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2007 - 2008 Novell, Inc. + * Copyright 2007 - 2014 Red Hat, Inc. + */ + +#include "config.h" + +#include <string.h> +#include <glib/gi18n-lib.h> + +#include "nm-glib-compat.h" + +#include <nm-setting-connection.h> +#include <nm-setting-wireless.h> +#include <nm-setting-wireless-security.h> +#include <nm-utils.h> + +#include "nm-device-wifi.h" +#include "nm-access-point.h" +#include "nm-device-private.h" +#include "nm-object-private.h" +#include "nm-object-cache.h" +#include "nm-core-internal.h" +#include "nm-dbus-helpers.h" + +#include "nmdbus-device-wifi.h" + +G_DEFINE_TYPE (NMDeviceWifi, nm_device_wifi, NM_TYPE_DEVICE) + +#define NM_DEVICE_WIFI_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_WIFI, NMDeviceWifiPrivate)) + +void _nm_device_wifi_set_wireless_enabled (NMDeviceWifi *device, gboolean enabled); +static void state_changed_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data); + +typedef struct { + NMDeviceWifi *device; + GSimpleAsyncResult *simple; +} RequestScanInfo; + +typedef struct { + NMDBusDeviceWifi *proxy; + + char *hw_address; + char *perm_hw_address; + NM80211Mode mode; + guint32 rate; + NMAccessPoint *active_ap; + NMDeviceWifiCapabilities wireless_caps; + GPtrArray *aps; + + RequestScanInfo *scan_info; +} NMDeviceWifiPrivate; + +enum { + PROP_0, + PROP_HW_ADDRESS, + PROP_PERM_HW_ADDRESS, + PROP_MODE, + PROP_BITRATE, + PROP_ACTIVE_ACCESS_POINT, + PROP_WIRELESS_CAPABILITIES, + PROP_ACCESS_POINTS, + + LAST_PROP +}; + +enum { + ACCESS_POINT_ADDED, + ACCESS_POINT_REMOVED, + + LAST_SIGNAL +}; +static guint signals[LAST_SIGNAL] = { 0 }; + +/** + * nm_device_wifi_get_hw_address: + * @device: a #NMDeviceWifi + * + * Gets the actual hardware (MAC) address of the #NMDeviceWifi + * + * Returns: the actual hardware address. This is the internal string used by the + * device, and must not be modified. + **/ +const char * +nm_device_wifi_get_hw_address (NMDeviceWifi *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), NULL); + + return NM_DEVICE_WIFI_GET_PRIVATE (device)->hw_address; +} + +/** + * nm_device_wifi_get_permanent_hw_address: + * @device: a #NMDeviceWifi + * + * Gets the permanent hardware (MAC) address of the #NMDeviceWifi + * + * Returns: the permanent hardware address. This is the internal string used by the + * device, and must not be modified. + **/ +const char * +nm_device_wifi_get_permanent_hw_address (NMDeviceWifi *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), NULL); + + return NM_DEVICE_WIFI_GET_PRIVATE (device)->perm_hw_address; +} + +/** + * nm_device_wifi_get_mode: + * @device: a #NMDeviceWifi + * + * Gets the #NMDeviceWifi mode. + * + * Returns: the mode + **/ +NM80211Mode +nm_device_wifi_get_mode (NMDeviceWifi *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), 0); + + return NM_DEVICE_WIFI_GET_PRIVATE (device)->mode; +} + +/** + * nm_device_wifi_get_bitrate: + * @device: a #NMDeviceWifi + * + * Gets the bit rate of the #NMDeviceWifi in kbit/s. + * + * Returns: the bit rate (kbit/s) + **/ +guint32 +nm_device_wifi_get_bitrate (NMDeviceWifi *device) +{ + NMDeviceState state; + + g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), 0); + + state = nm_device_get_state (NM_DEVICE (device)); + switch (state) { + case NM_DEVICE_STATE_IP_CONFIG: + case NM_DEVICE_STATE_IP_CHECK: + case NM_DEVICE_STATE_SECONDARIES: + case NM_DEVICE_STATE_ACTIVATED: + case NM_DEVICE_STATE_DEACTIVATING: + break; + default: + return 0; + } + + return NM_DEVICE_WIFI_GET_PRIVATE (device)->rate; +} + +/** + * nm_device_wifi_get_capabilities: + * @device: a #NMDeviceWifi + * + * Gets the Wi-Fi capabilities of the #NMDeviceWifi. + * + * Returns: the capabilities + **/ +NMDeviceWifiCapabilities +nm_device_wifi_get_capabilities (NMDeviceWifi *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), 0); + + return NM_DEVICE_WIFI_GET_PRIVATE (device)->wireless_caps; +} + +/** + * nm_device_wifi_get_active_access_point: + * @device: a #NMDeviceWifi + * + * Gets the active #NMAccessPoint. + * + * Returns: (transfer none): the access point or %NULL if none is active + **/ +NMAccessPoint * +nm_device_wifi_get_active_access_point (NMDeviceWifi *device) +{ + NMDeviceState state; + + g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), NULL); + + state = nm_device_get_state (NM_DEVICE (device)); + switch (state) { + case NM_DEVICE_STATE_PREPARE: + case NM_DEVICE_STATE_CONFIG: + case NM_DEVICE_STATE_NEED_AUTH: + case NM_DEVICE_STATE_IP_CONFIG: + case NM_DEVICE_STATE_IP_CHECK: + case NM_DEVICE_STATE_SECONDARIES: + case NM_DEVICE_STATE_ACTIVATED: + case NM_DEVICE_STATE_DEACTIVATING: + break; + default: + return NULL; + break; + } + + return NM_DEVICE_WIFI_GET_PRIVATE (device)->active_ap; +} + +/** + * nm_device_wifi_get_access_points: + * @device: a #NMDeviceWifi + * + * Gets all the scanned access points of the #NMDeviceWifi. + * + * Returns: (element-type NMAccessPoint): a #GPtrArray containing all the + * scanned #NMAccessPoints. + * The returned array is owned by the client and should not be modified. + **/ +const GPtrArray * +nm_device_wifi_get_access_points (NMDeviceWifi *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), NULL); + + return NM_DEVICE_WIFI_GET_PRIVATE (device)->aps; +} + +/** + * nm_device_wifi_get_access_point_by_path: + * @device: a #NMDeviceWifi + * @path: the object path of the access point + * + * Gets a #NMAccessPoint by path. + * + * Returns: (transfer none): the access point or %NULL if none is found. + **/ +NMAccessPoint * +nm_device_wifi_get_access_point_by_path (NMDeviceWifi *device, + const char *path) +{ + const GPtrArray *aps; + int i; + NMAccessPoint *ap = NULL; + + g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), NULL); + g_return_val_if_fail (path != NULL, NULL); + + aps = nm_device_wifi_get_access_points (device); + if (!aps) + return NULL; + + for (i = 0; i < aps->len; i++) { + NMAccessPoint *candidate = g_ptr_array_index (aps, i); + if (!strcmp (nm_object_get_path (NM_OBJECT (candidate)), path)) { + ap = candidate; + break; + } + } + + return ap; +} + +/** + * nm_device_wifi_request_scan: + * @device: a #NMDeviceWifi + * @cancellable: a #GCancellable, or %NULL + * @error: location for a #GError, or %NULL + * + * Request NM to scan for access points on @device. Note that the function + * returns immediately after requesting the scan, and it may take some time + * after that for the scan to complete. + * + * Returns: %TRUE on success, %FALSE on error, in which case @error will be + * set. + **/ +gboolean +nm_device_wifi_request_scan (NMDeviceWifi *device, + GCancellable *cancellable, + GError **error) +{ + gboolean ret; + + g_return_val_if_fail (NM_IS_DEVICE_WIFI (device), FALSE); + + ret = nmdbus_device_wifi_call_request_scan_sync (NM_DEVICE_WIFI_GET_PRIVATE (device)->proxy, + g_variant_new_array (G_VARIANT_TYPE ("{sv}"), + NULL, 0), + cancellable, error); + if (error && *error) + g_dbus_error_strip_remote_error (*error); + return ret; +} + +static void +request_scan_cb (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + RequestScanInfo *info = user_data; + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (info->device); + GError *error = NULL; + + priv->scan_info = NULL; + + if (nmdbus_device_wifi_call_request_scan_finish (NMDBUS_DEVICE_WIFI (source), + result, &error)) + g_simple_async_result_set_op_res_gboolean (info->simple, TRUE); + else { + g_dbus_error_strip_remote_error (error); + g_simple_async_result_take_error (info->simple, error); + } + + g_simple_async_result_complete (info->simple); + g_object_unref (info->simple); + g_slice_free (RequestScanInfo, info); +} + +/** + * nm_device_wifi_request_scan_async: + * @device: a #NMDeviceWifi + * @cancellable: a #GCancellable, or %NULL + * @callback: callback to be called when the scan has been requested + * @user_data: caller-specific data passed to @callback + * + * Request NM to scan for access points on @device. Note that @callback will be + * called immediately after requesting the scan, and it may take some time after + * that for the scan to complete. + **/ +void +nm_device_wifi_request_scan_async (NMDeviceWifi *device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device); + RequestScanInfo *info; + GSimpleAsyncResult *simple; + + g_return_if_fail (NM_IS_DEVICE_WIFI (device)); + + simple = g_simple_async_result_new (G_OBJECT (device), callback, user_data, + nm_device_wifi_request_scan_async); + + /* If a scan is in progress, just return */ + if (priv->scan_info) { + g_simple_async_result_set_op_res_gboolean (simple, TRUE); + g_simple_async_result_complete_in_idle (simple); + g_object_unref (simple); + return; + } + + info = g_slice_new0 (RequestScanInfo); + info->device = device; + info->simple = simple; + + priv->scan_info = info; + nmdbus_device_wifi_call_request_scan (NM_DEVICE_WIFI_GET_PRIVATE (device)->proxy, + g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0), + cancellable, request_scan_cb, info); +} + +/** + * nm_device_wifi_request_scan_finish: + * @device: a #NMDeviceWifi + * @result: the result passed to the #GAsyncReadyCallback + * @error: location for a #GError, or %NULL + * + * Gets the result of a call to nm_device_wifi_request_scan_async(). + * + * Returns: %TRUE on success, %FALSE on error, in which case @error will be + * set. + **/ +gboolean +nm_device_wifi_request_scan_finish (NMDeviceWifi *device, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (device), nm_device_wifi_request_scan_async), FALSE); + + simple = G_SIMPLE_ASYNC_RESULT (result); + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + else + return g_simple_async_result_get_op_res_gboolean (simple); +} + +static void +clean_up_aps (NMDeviceWifi *self, gboolean in_dispose) +{ + NMDeviceWifiPrivate *priv; + GPtrArray *aps; + int i; + + g_return_if_fail (NM_IS_DEVICE_WIFI (self)); + + priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + + if (priv->active_ap) { + g_object_unref (priv->active_ap); + priv->active_ap = NULL; + } + + aps = priv->aps; + + if (in_dispose) + priv->aps = NULL; + else { + priv->aps = g_ptr_array_new (); + + for (i = 0; i < aps->len; i++) { + NMAccessPoint *ap = NM_ACCESS_POINT (g_ptr_array_index (aps, i)); + + g_signal_emit (self, signals[ACCESS_POINT_REMOVED], 0, ap); + } + } + + g_ptr_array_unref (aps); +} + +/** + * _nm_device_wifi_set_wireless_enabled: + * @device: a #NMDeviceWifi + * @enabled: %TRUE to enable the device + * + * Enables or disables the wireless device. + **/ +void +_nm_device_wifi_set_wireless_enabled (NMDeviceWifi *device, + gboolean enabled) +{ + g_return_if_fail (NM_IS_DEVICE_WIFI (device)); + + if (!enabled) + clean_up_aps (device, FALSE); +} + +#define WPA_CAPS (NM_WIFI_DEVICE_CAP_CIPHER_TKIP | \ + NM_WIFI_DEVICE_CAP_CIPHER_CCMP | \ + NM_WIFI_DEVICE_CAP_WPA | \ + NM_WIFI_DEVICE_CAP_RSN) + +#define RSN_CAPS (NM_WIFI_DEVICE_CAP_CIPHER_CCMP | NM_WIFI_DEVICE_CAP_RSN) + +static gboolean +has_proto (NMSettingWirelessSecurity *s_wsec, const char *proto) +{ + int i; + + for (i = 0; i < nm_setting_wireless_security_get_num_protos (s_wsec); i++) { + if (g_strcmp0 (proto, nm_setting_wireless_security_get_proto (s_wsec, i)) == 0) + return TRUE; + } + return FALSE; +} + +static gboolean +connection_compatible (NMDevice *device, NMConnection *connection, GError **error) +{ + NMSettingWireless *s_wifi; + NMSettingWirelessSecurity *s_wsec; + const char *hwaddr, *setting_hwaddr; + NMDeviceWifiCapabilities wifi_caps; + const char *key_mgmt; + + if (!NM_DEVICE_CLASS (nm_device_wifi_parent_class)->connection_compatible (device, connection, error)) + return FALSE; + + if (!nm_connection_is_type (connection, NM_SETTING_WIRELESS_SETTING_NAME)) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + _("The connection was not a Wi-Fi connection.")); + return FALSE; + } + + /* Check MAC address */ + hwaddr = nm_device_wifi_get_permanent_hw_address (NM_DEVICE_WIFI (device)); + if (hwaddr) { + if (!nm_utils_hwaddr_valid (hwaddr, ETH_ALEN)) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, + _("Invalid device MAC address.")); + return FALSE; + } + s_wifi = nm_connection_get_setting_wireless (connection); + setting_hwaddr = nm_setting_wireless_get_mac_address (s_wifi); + if (setting_hwaddr && !nm_utils_hwaddr_matches (setting_hwaddr, -1, hwaddr, -1)) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + _("The MACs of the device and the connection didn't match.")); + return FALSE; + } + } + + /* Check device capabilities; we assume all devices can do WEP at least */ + + s_wsec = nm_connection_get_setting_wireless_security (connection); + if (s_wsec) { + /* Connection has security, verify it against the device's capabilities */ + key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec); + if ( !g_strcmp0 (key_mgmt, "wpa-none") + || !g_strcmp0 (key_mgmt, "wpa-psk") + || !g_strcmp0 (key_mgmt, "wpa-eap")) { + + wifi_caps = nm_device_wifi_get_capabilities (NM_DEVICE_WIFI (device)); + + /* Is device only WEP capable? */ + if (!(wifi_caps & WPA_CAPS)) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + _("The device is lacking WPA capabilities required by the connection.")); + return FALSE; + } + + /* Make sure WPA2/RSN-only connections don't get chosen for WPA-only cards */ + if (has_proto (s_wsec, "rsn") && !has_proto (s_wsec, "wpa") && !(wifi_caps & RSN_CAPS)) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + _("The device is lacking WPA2/RSN capabilities required by the connection.")); + return FALSE; + } + } + } + + return TRUE; +} + +static GType +get_setting_type (NMDevice *device) +{ + return NM_TYPE_SETTING_WIRELESS; +} + +static const char * +get_hw_address (NMDevice *device) +{ + return nm_device_wifi_get_hw_address (NM_DEVICE_WIFI (device)); +} + +/**************************************************************/ + +static void +nm_device_wifi_init (NMDeviceWifi *device) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device); + + _nm_device_set_device_type (NM_DEVICE (device), NM_DEVICE_TYPE_WIFI); + + g_signal_connect (device, + "notify::" NM_DEVICE_STATE, + G_CALLBACK (state_changed_cb), + NULL); + + priv->aps = g_ptr_array_new (); +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMDeviceWifi *self = NM_DEVICE_WIFI (object); + + switch (prop_id) { + case PROP_HW_ADDRESS: + g_value_set_string (value, nm_device_wifi_get_hw_address (self)); + break; + case PROP_PERM_HW_ADDRESS: + g_value_set_string (value, nm_device_wifi_get_permanent_hw_address (self)); + break; + case PROP_MODE: + g_value_set_enum (value, nm_device_wifi_get_mode (self)); + break; + case PROP_BITRATE: + g_value_set_uint (value, nm_device_wifi_get_bitrate (self)); + break; + case PROP_ACTIVE_ACCESS_POINT: + g_value_set_object (value, nm_device_wifi_get_active_access_point (self)); + break; + case PROP_WIRELESS_CAPABILITIES: + g_value_set_flags (value, nm_device_wifi_get_capabilities (self)); + break; + case PROP_ACCESS_POINTS: + g_value_take_boxed (value, _nm_utils_copy_object_array (nm_device_wifi_get_access_points (self))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +state_changed_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data) +{ + NMDeviceWifi *self = NM_DEVICE_WIFI (device); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + + switch (nm_device_get_state (device)) { + case NM_DEVICE_STATE_UNKNOWN: + case NM_DEVICE_STATE_UNMANAGED: + case NM_DEVICE_STATE_UNAVAILABLE: + case NM_DEVICE_STATE_DISCONNECTED: + case NM_DEVICE_STATE_FAILED: + /* Just clear active AP; don't clear the AP list unless wireless is disabled completely */ + if (priv->active_ap) { + g_object_unref (priv->active_ap); + priv->active_ap = NULL; + } + _nm_object_queue_notify (NM_OBJECT (device), NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT); + priv->rate = 0; + _nm_object_queue_notify (NM_OBJECT (device), NM_DEVICE_WIFI_BITRATE); + break; + default: + break; + } +} + +static void +init_dbus (NMObject *object) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (object); + const NMPropertiesInfo property_info[] = { + { NM_DEVICE_WIFI_HW_ADDRESS, &priv->hw_address }, + { NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS, &priv->perm_hw_address }, + { NM_DEVICE_WIFI_MODE, &priv->mode }, + { NM_DEVICE_WIFI_BITRATE, &priv->rate }, + { NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT, &priv->active_ap, NULL, NM_TYPE_ACCESS_POINT }, + { NM_DEVICE_WIFI_CAPABILITIES, &priv->wireless_caps }, + { NM_DEVICE_WIFI_ACCESS_POINTS, &priv->aps, NULL, NM_TYPE_ACCESS_POINT, "access-point" }, + { NULL }, + }; + + NM_OBJECT_CLASS (nm_device_wifi_parent_class)->init_dbus (object); + + priv->proxy = NMDBUS_DEVICE_WIFI (_nm_object_get_proxy (object, NM_DBUS_INTERFACE_DEVICE_WIRELESS)); + _nm_object_register_properties (object, + NM_DBUS_INTERFACE_DEVICE_WIRELESS, + property_info); +} + +static void +access_point_removed (NMDeviceWifi *self, NMAccessPoint *ap) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + + if (ap == priv->active_ap) { + g_object_unref (priv->active_ap); + priv->active_ap = NULL; + _nm_object_queue_notify (NM_OBJECT (self), NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT); + + priv->rate = 0; + _nm_object_queue_notify (NM_OBJECT (self), NM_DEVICE_WIFI_BITRATE); + } +} + +static void +dispose (GObject *object) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (object); + + if (priv->aps) + clean_up_aps (NM_DEVICE_WIFI (object), TRUE); + + G_OBJECT_CLASS (nm_device_wifi_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (object); + + g_free (priv->hw_address); + g_free (priv->perm_hw_address); + + G_OBJECT_CLASS (nm_device_wifi_parent_class)->finalize (object); +} + +static void +nm_device_wifi_class_init (NMDeviceWifiClass *wifi_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (wifi_class); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (wifi_class); + NMDeviceClass *device_class = NM_DEVICE_CLASS (wifi_class); + + g_type_class_add_private (wifi_class, sizeof (NMDeviceWifiPrivate)); + + _nm_object_class_add_interface (nm_object_class, NM_DBUS_INTERFACE_DEVICE_WIRELESS); + _nm_dbus_register_proxy_type (NM_DBUS_INTERFACE_DEVICE_WIRELESS, + NMDBUS_TYPE_DEVICE_WIFI_PROXY); + + /* virtual methods */ + object_class->get_property = get_property; + object_class->dispose = dispose; + object_class->finalize = finalize; + + nm_object_class->init_dbus = init_dbus; + + device_class->connection_compatible = connection_compatible; + device_class->get_setting_type = get_setting_type; + device_class->get_hw_address = get_hw_address; + + wifi_class->access_point_removed = access_point_removed; + + /* properties */ + + /** + * NMDeviceWifi:hw-address: + * + * The hardware (MAC) address of the device. + **/ + g_object_class_install_property + (object_class, PROP_HW_ADDRESS, + g_param_spec_string (NM_DEVICE_WIFI_HW_ADDRESS, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceWifi:perm-hw-address: + * + * The hardware (MAC) address of the device. + **/ + g_object_class_install_property + (object_class, PROP_PERM_HW_ADDRESS, + g_param_spec_string (NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceWifi:mode: + * + * The mode of the device. + **/ + g_object_class_install_property + (object_class, PROP_MODE, + g_param_spec_enum (NM_DEVICE_WIFI_MODE, "", "", + NM_TYPE_802_11_MODE, + NM_802_11_MODE_UNKNOWN, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceWifi:bitrate: + * + * The bit rate of the device in kbit/s. + **/ + g_object_class_install_property + (object_class, PROP_BITRATE, + g_param_spec_uint (NM_DEVICE_WIFI_BITRATE, "", "", + 0, G_MAXUINT32, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceWifi:active-access-point: + * + * The active #NMAccessPoint of the device. + **/ + g_object_class_install_property + (object_class, PROP_ACTIVE_ACCESS_POINT, + g_param_spec_object (NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT, "", "", + NM_TYPE_ACCESS_POINT, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceWifi:wireless-capabilities: + * + * The wireless capabilities of the device. + **/ + g_object_class_install_property + (object_class, PROP_WIRELESS_CAPABILITIES, + g_param_spec_flags (NM_DEVICE_WIFI_CAPABILITIES, "", "", + NM_TYPE_DEVICE_WIFI_CAPABILITIES, + NM_WIFI_DEVICE_CAP_NONE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceWifi:access-points: + * + * List of all Wi-Fi access points the device can see. + * + * Element-type: NMAccessPoint + **/ + g_object_class_install_property + (object_class, PROP_ACCESS_POINTS, + g_param_spec_boxed (NM_DEVICE_WIFI_ACCESS_POINTS, "", "", + G_TYPE_PTR_ARRAY, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /* signals */ + + /** + * NMDeviceWifi::access-point-added: + * @device: the Wi-Fi device that received the signal + * @ap: the new access point + * + * Notifies that a #NMAccessPoint is added to the Wi-Fi device. + **/ + signals[ACCESS_POINT_ADDED] = + g_signal_new ("access-point-added", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMDeviceWifiClass, access_point_added), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); + + /** + * NMDeviceWifi::access-point-removed: + * @device: the Wi-Fi device that received the signal + * @ap: the removed access point + * + * Notifies that a #NMAccessPoint is removed from the Wi-Fi device. + **/ + signals[ACCESS_POINT_REMOVED] = + g_signal_new ("access-point-removed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMDeviceWifiClass, access_point_removed), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); +} diff --git a/libnm/nm-device-wifi.h b/libnm/nm-device-wifi.h new file mode 100644 index 00000000..24339fd3 --- /dev/null +++ b/libnm/nm-device-wifi.h @@ -0,0 +1,91 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2007 - 2008 Novell, Inc. + * Copyright 2007 - 2012 Red Hat, Inc. + */ + +#ifndef __NM_DEVICE_WIFI_H__ +#define __NM_DEVICE_WIFI_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include <nm-device.h> + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_WIFI (nm_device_wifi_get_type ()) +#define NM_DEVICE_WIFI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_WIFI, NMDeviceWifi)) +#define NM_DEVICE_WIFI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_WIFI, NMDeviceWifiClass)) +#define NM_IS_DEVICE_WIFI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_WIFI)) +#define NM_IS_DEVICE_WIFI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_WIFI)) +#define NM_DEVICE_WIFI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_WIFI, NMDeviceWifiClass)) + +#define NM_DEVICE_WIFI_HW_ADDRESS "hw-address" +#define NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS "perm-hw-address" +#define NM_DEVICE_WIFI_MODE "mode" +#define NM_DEVICE_WIFI_BITRATE "bitrate" +#define NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT "active-access-point" +#define NM_DEVICE_WIFI_CAPABILITIES "wireless-capabilities" +#define NM_DEVICE_WIFI_ACCESS_POINTS "access-points" + +struct _NMDeviceWifi { + NMDevice parent; +}; + +typedef struct { + NMDeviceClass parent; + + /* Signals */ + void (*access_point_added) (NMDeviceWifi *device, NMAccessPoint *ap); + void (*access_point_removed) (NMDeviceWifi *device, NMAccessPoint *ap); + + /*< private >*/ + gpointer padding[4]; +} NMDeviceWifiClass; + +GType nm_device_wifi_get_type (void); + +const char * nm_device_wifi_get_hw_address (NMDeviceWifi *device); +const char * nm_device_wifi_get_permanent_hw_address (NMDeviceWifi *device); +NM80211Mode nm_device_wifi_get_mode (NMDeviceWifi *device); +guint32 nm_device_wifi_get_bitrate (NMDeviceWifi *device); +NMDeviceWifiCapabilities nm_device_wifi_get_capabilities (NMDeviceWifi *device); +NMAccessPoint * nm_device_wifi_get_active_access_point (NMDeviceWifi *device); + +NMAccessPoint * nm_device_wifi_get_access_point_by_path (NMDeviceWifi *device, + const char *path); + +const GPtrArray * nm_device_wifi_get_access_points (NMDeviceWifi *device); + +gboolean nm_device_wifi_request_scan (NMDeviceWifi *device, + GCancellable *cancellable, + GError **error); + +void nm_device_wifi_request_scan_async (NMDeviceWifi *device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean nm_device_wifi_request_scan_finish (NMDeviceWifi *device, + GAsyncResult *result, + GError **error); + +G_END_DECLS + +#endif /* __NM_DEVICE_WIFI_H__ */ diff --git a/libnm/nm-device-wimax.c b/libnm/nm-device-wimax.c new file mode 100644 index 00000000..f199b669 --- /dev/null +++ b/libnm/nm-device-wimax.c @@ -0,0 +1,678 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2011 - 2012 Red Hat, Inc. + * Copyright 2009 Novell, Inc. + */ + +#include "config.h" + +#include <string.h> +#include <glib/gi18n-lib.h> + +#include "nm-glib-compat.h" + +#include <nm-setting-connection.h> +#include <nm-setting-wimax.h> +#include <nm-utils.h> + +#include "nm-device-wimax.h" +#include "nm-wimax-nsp.h" +#include "nm-object-private.h" +#include "nm-object-cache.h" +#include "nm-core-internal.h" +#include "nm-device-private.h" + +G_DEFINE_TYPE (NMDeviceWimax, nm_device_wimax, NM_TYPE_DEVICE) + +#define NM_DEVICE_WIMAX_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_WIMAX, NMDeviceWimaxPrivate)) + +void _nm_device_wimax_set_wireless_enabled (NMDeviceWimax *wimax, gboolean enabled); +static void state_changed_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data); + +typedef struct { + char *hw_address; + NMWimaxNsp *active_nsp; + GPtrArray *nsps; + + guint center_freq; + gint rssi; + gint cinr; + gint tx_power; + char *bsid; +} NMDeviceWimaxPrivate; + +enum { + PROP_0, + PROP_HW_ADDRESS, + PROP_ACTIVE_NSP, + PROP_CENTER_FREQ, + PROP_RSSI, + PROP_CINR, + PROP_TX_POWER, + PROP_BSID, + PROP_NSPS, + + LAST_PROP +}; + +enum { + NSP_ADDED, + NSP_REMOVED, + + LAST_SIGNAL +}; +static guint signals[LAST_SIGNAL] = { 0 }; + +/** + * nm_device_wimax_get_hw_address: + * @wimax: a #NMDeviceWimax + * + * Gets the hardware (MAC) address of the #NMDeviceWimax + * + * Returns: the hardware address. This is the internal string used by the + * device, and must not be modified. + **/ +const char * +nm_device_wimax_get_hw_address (NMDeviceWimax *wimax) +{ + g_return_val_if_fail (NM_IS_DEVICE_WIMAX (wimax), NULL); + + return NM_DEVICE_WIMAX_GET_PRIVATE (wimax)->hw_address; +} + +/** + * nm_device_wimax_get_active_nsp: + * @wimax: a #NMDeviceWimax + * + * Gets the active #NMWimaxNsp. + * + * Returns: (transfer full): the access point or %NULL if none is active + **/ +NMWimaxNsp * +nm_device_wimax_get_active_nsp (NMDeviceWimax *wimax) +{ + NMDeviceState state; + + g_return_val_if_fail (NM_IS_DEVICE_WIMAX (wimax), NULL); + + state = nm_device_get_state (NM_DEVICE (wimax)); + switch (state) { + case NM_DEVICE_STATE_PREPARE: + case NM_DEVICE_STATE_CONFIG: + case NM_DEVICE_STATE_NEED_AUTH: + case NM_DEVICE_STATE_IP_CONFIG: + case NM_DEVICE_STATE_IP_CHECK: + case NM_DEVICE_STATE_SECONDARIES: + case NM_DEVICE_STATE_ACTIVATED: + case NM_DEVICE_STATE_DEACTIVATING: + break; + default: + return NULL; + break; + } + + return NM_DEVICE_WIMAX_GET_PRIVATE (wimax)->active_nsp; +} + +/** + * nm_device_wimax_get_nsps: + * @wimax: a #NMDeviceWimax + * + * Gets all the scanned NSPs of the #NMDeviceWimax. + * + * Returns: (element-type NMWimaxNsp): a #GPtrArray containing + * all the scanned #NMWimaxNsps. + * The returned array is owned by the client and should not be modified. + **/ +const GPtrArray * +nm_device_wimax_get_nsps (NMDeviceWimax *wimax) +{ + g_return_val_if_fail (NM_IS_DEVICE_WIMAX (wimax), NULL); + + return NM_DEVICE_WIMAX_GET_PRIVATE (wimax)->nsps; +} + +/** + * nm_device_wimax_get_nsp_by_path: + * @wimax: a #NMDeviceWimax + * @path: the object path of the NSP + * + * Gets a #NMWimaxNsp by path. + * + * Returns: (transfer none): the access point or %NULL if none is found. + **/ +NMWimaxNsp * +nm_device_wimax_get_nsp_by_path (NMDeviceWimax *wimax, + const char *path) +{ + const GPtrArray *nsps; + int i; + NMWimaxNsp *nsp = NULL; + + g_return_val_if_fail (NM_IS_DEVICE_WIMAX (wimax), NULL); + g_return_val_if_fail (path != NULL, NULL); + + nsps = nm_device_wimax_get_nsps (wimax); + if (!nsps) + return NULL; + + for (i = 0; i < nsps->len; i++) { + NMWimaxNsp *candidate = g_ptr_array_index (nsps, i); + if (!strcmp (nm_object_get_path (NM_OBJECT (candidate)), path)) { + nsp = candidate; + break; + } + } + + return nsp; +} + +static void +clean_up_nsps (NMDeviceWimax *self) +{ + NMDeviceWimaxPrivate *priv; + + g_return_if_fail (NM_IS_DEVICE_WIMAX (self)); + + priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + if (priv->active_nsp) { + g_object_unref (priv->active_nsp); + priv->active_nsp = NULL; + } + + g_clear_pointer (&priv->nsps, g_ptr_array_unref); +} + +/** + * nm_device_wimax_get_center_frequency: + * @self: a #NMDeviceWimax + * + * Gets the center frequency (in KHz) of the radio channel the device is using + * to communicate with the network when connected. Has no meaning when the + * device is not connected. + * + * Returns: the center frequency in KHz, or 0 + **/ +guint +nm_device_wimax_get_center_frequency (NMDeviceWimax *self) +{ + g_return_val_if_fail (NM_IS_DEVICE_WIMAX (self), 0); + + return NM_DEVICE_WIMAX_GET_PRIVATE (self)->center_freq; +} + +/** + * nm_device_wimax_get_rssi: + * @self: a #NMDeviceWimax + * + * Gets the RSSI of the current radio link in dBm. This value indicates how + * strong the raw received RF signal from the base station is, but does not + * indicate the overall quality of the radio link. Has no meaning when the + * device is not connected. + * + * Returns: the RSSI in dBm, or 0 + **/ +gint +nm_device_wimax_get_rssi (NMDeviceWimax *self) +{ + g_return_val_if_fail (NM_IS_DEVICE_WIMAX (self), 0); + + return NM_DEVICE_WIMAX_GET_PRIVATE (self)->rssi; +} + +/** + * nm_device_wimax_get_cinr: + * @self: a #NMDeviceWimax + * + * Gets the CINR (Carrier to Interference + Noise Ratio) of the current radio + * link in dB. CINR is a more accurate measure of radio link quality. Has no + * meaning when the device is not connected. + * + * Returns: the CINR in dB, or 0 + **/ +gint +nm_device_wimax_get_cinr (NMDeviceWimax *self) +{ + g_return_val_if_fail (NM_IS_DEVICE_WIMAX (self), 0); + + return NM_DEVICE_WIMAX_GET_PRIVATE (self)->cinr; +} + +/** + * nm_device_wimax_get_tx_power: + * @self: a #NMDeviceWimax + * + * Average power of the last burst transmitted by the device, in units of + * 0.5 dBm. i.e. a TxPower of -11 represents an actual device TX power of + * -5.5 dBm. Has no meaning when the device is not connected. + * + * Returns: the TX power in dBm, or 0 + **/ +gint +nm_device_wimax_get_tx_power (NMDeviceWimax *self) +{ + g_return_val_if_fail (NM_IS_DEVICE_WIMAX (self), 0); + + return NM_DEVICE_WIMAX_GET_PRIVATE (self)->tx_power; +} + +/** + * nm_device_wimax_get_bsid: + * @self: a #NMDeviceWimax + * + * Gets the ID of the serving Base Station when the device is connected. + * + * Returns: the ID of the serving Base Station, or %NULL + **/ +const char * +nm_device_wimax_get_bsid (NMDeviceWimax *self) +{ + g_return_val_if_fail (NM_IS_DEVICE_WIMAX (self), NULL); + + return NM_DEVICE_WIMAX_GET_PRIVATE (self)->bsid; +} + +static gboolean +connection_compatible (NMDevice *device, NMConnection *connection, GError **error) +{ + NMSettingWimax *s_wimax; + const char *hwaddr, *setting_hwaddr; + + if (!NM_DEVICE_CLASS (nm_device_wimax_parent_class)->connection_compatible (device, connection, error)) + return FALSE; + + if (!nm_connection_is_type (connection, NM_SETTING_WIMAX_SETTING_NAME)) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + _("The connection was not a WiMAX connection.")); + return FALSE; + } + + /* Check MAC address */ + hwaddr = nm_device_wimax_get_hw_address (NM_DEVICE_WIMAX (device)); + if (hwaddr) { + if (!nm_utils_hwaddr_valid (hwaddr, ETH_ALEN)) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, + _("Invalid device MAC address.")); + return FALSE; + } + s_wimax = nm_connection_get_setting_wimax (connection); + setting_hwaddr = nm_setting_wimax_get_mac_address (s_wimax); + if (setting_hwaddr && !nm_utils_hwaddr_matches (setting_hwaddr, -1, hwaddr, -1)) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + _("The MACs of the device and the connection didn't match.")); + return FALSE; + } + } + + return TRUE; +} + +static GType +get_setting_type (NMDevice *device) +{ + return NM_TYPE_SETTING_WIMAX; +} + +static const char * +get_hw_address (NMDevice *device) +{ + return nm_device_wimax_get_hw_address (NM_DEVICE_WIMAX (device)); +} + +/**************************************************************/ + +static void +nm_device_wimax_init (NMDeviceWimax *device) +{ + _nm_device_set_device_type (NM_DEVICE (device), NM_DEVICE_TYPE_WIMAX); + + g_signal_connect (device, + "notify::" NM_DEVICE_STATE, + G_CALLBACK (state_changed_cb), + NULL); +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (object); + + switch (prop_id) { + case PROP_HW_ADDRESS: + g_value_set_string (value, nm_device_wimax_get_hw_address (self)); + break; + case PROP_ACTIVE_NSP: + g_value_set_object (value, nm_device_wimax_get_active_nsp (self)); + break; + case PROP_CENTER_FREQ: + g_value_set_uint (value, nm_device_wimax_get_center_frequency (self)); + break; + case PROP_RSSI: + g_value_set_int (value, nm_device_wimax_get_rssi (self)); + break; + case PROP_CINR: + g_value_set_int (value, nm_device_wimax_get_cinr (self)); + break; + case PROP_TX_POWER: + g_value_set_int (value, nm_device_wimax_get_tx_power (self)); + break; + case PROP_BSID: + g_value_set_string (value, nm_device_wimax_get_bsid (self)); + break; + case PROP_NSPS: + g_value_take_boxed (value, _nm_utils_copy_object_array (nm_device_wimax_get_nsps (self))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clear_link_status (NMDeviceWimax *self) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + if (priv->center_freq) { + priv->center_freq = 0; + _nm_object_queue_notify (NM_OBJECT (self), NM_DEVICE_WIMAX_CENTER_FREQUENCY); + } + + if (priv->rssi) { + priv->rssi = 0; + _nm_object_queue_notify (NM_OBJECT (self), NM_DEVICE_WIMAX_RSSI); + } + + if (priv->cinr) { + priv->cinr = 0; + _nm_object_queue_notify (NM_OBJECT (self), NM_DEVICE_WIMAX_CINR); + } + + if (priv->tx_power) { + priv->tx_power = 0; + _nm_object_queue_notify (NM_OBJECT (self), NM_DEVICE_WIMAX_TX_POWER); + } + + if (priv->bsid) { + g_free (priv->bsid); + priv->bsid = NULL; + _nm_object_queue_notify (NM_OBJECT (self), NM_DEVICE_WIMAX_BSID); + } +} + +static void +state_changed_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data) +{ + NMDeviceWimax *self = NM_DEVICE_WIMAX (device); + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + NMDeviceState state; + + state = nm_device_get_state (device); + switch (state) { + case NM_DEVICE_STATE_UNKNOWN: + case NM_DEVICE_STATE_UNMANAGED: + case NM_DEVICE_STATE_UNAVAILABLE: + case NM_DEVICE_STATE_DISCONNECTED: + case NM_DEVICE_STATE_FAILED: + if (priv->active_nsp) { + g_object_unref (priv->active_nsp); + priv->active_nsp = NULL; + } + _nm_object_queue_notify (NM_OBJECT (device), NM_DEVICE_WIMAX_ACTIVE_NSP); + clear_link_status (self); + break; + case NM_DEVICE_STATE_PREPARE: + case NM_DEVICE_STATE_CONFIG: + case NM_DEVICE_STATE_NEED_AUTH: + case NM_DEVICE_STATE_IP_CONFIG: + clear_link_status (self); + break; + default: + break; + } +} + +static void +init_dbus (NMObject *object) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (object); + const NMPropertiesInfo property_info[] = { + { NM_DEVICE_WIMAX_HW_ADDRESS, &priv->hw_address }, + { NM_DEVICE_WIMAX_ACTIVE_NSP, &priv->active_nsp, NULL, NM_TYPE_WIMAX_NSP }, + { NM_DEVICE_WIMAX_CENTER_FREQUENCY, &priv->center_freq }, + { NM_DEVICE_WIMAX_RSSI, &priv->rssi }, + { NM_DEVICE_WIMAX_CINR, &priv->cinr }, + { NM_DEVICE_WIMAX_TX_POWER, &priv->tx_power }, + { NM_DEVICE_WIMAX_BSID, &priv->bsid }, + { NM_DEVICE_WIMAX_NSPS, &priv->nsps, NULL, NM_TYPE_WIMAX_NSP, "nsp" }, + { NULL }, + }; + + NM_OBJECT_CLASS (nm_device_wimax_parent_class)->init_dbus (object); + + _nm_object_register_properties (object, + NM_DBUS_INTERFACE_DEVICE_WIMAX, + property_info); +} + +static void +nsp_removed (NMDeviceWimax *self, NMWimaxNsp *nsp) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); + + if (nsp == priv->active_nsp) { + g_object_unref (priv->active_nsp); + priv->active_nsp = NULL; + _nm_object_queue_notify (NM_OBJECT (self), NM_DEVICE_WIMAX_ACTIVE_NSP); + } +} + +static void +dispose (GObject *object) +{ + NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (object); + + if (priv->hw_address) { + g_free (priv->hw_address); + priv->hw_address = NULL; + } + + if (priv->bsid) { + g_free (priv->bsid); + priv->bsid = NULL; + } + + if (priv->nsps) + clean_up_nsps (NM_DEVICE_WIMAX (object)); + + G_OBJECT_CLASS (nm_device_wimax_parent_class)->dispose (object); +} + +static void +nm_device_wimax_class_init (NMDeviceWimaxClass *wimax_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (wimax_class); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (wimax_class); + NMDeviceClass *device_class = NM_DEVICE_CLASS (wimax_class); + + g_type_class_add_private (wimax_class, sizeof (NMDeviceWimaxPrivate)); + + _nm_object_class_add_interface (nm_object_class, NM_DBUS_INTERFACE_DEVICE_WIMAX); + + /* virtual methods */ + object_class->get_property = get_property; + object_class->dispose = dispose; + + nm_object_class->init_dbus = init_dbus; + + device_class->connection_compatible = connection_compatible; + device_class->get_setting_type = get_setting_type; + device_class->get_hw_address = get_hw_address; + + wimax_class->nsp_removed = nsp_removed; + + /* properties */ + + /** + * NMDeviceWimax:hw-address: + * + * The hardware (MAC) address of the device. + **/ + g_object_class_install_property + (object_class, PROP_HW_ADDRESS, + g_param_spec_string (NM_DEVICE_WIMAX_HW_ADDRESS, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceWimax:active-nsp: + * + * The active #NMWimaxNsp of the device. + **/ + g_object_class_install_property + (object_class, PROP_ACTIVE_NSP, + g_param_spec_object (NM_DEVICE_WIMAX_ACTIVE_NSP, "", "", + NM_TYPE_WIMAX_NSP, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceWimax:center-frequency: + * + * The center frequency (in KHz) of the radio channel the device is using to + * communicate with the network when connected. Has no meaning when the + * device is not connected. + **/ + g_object_class_install_property + (object_class, PROP_CENTER_FREQ, + g_param_spec_uint (NM_DEVICE_WIMAX_CENTER_FREQUENCY, "", "", + 0, G_MAXUINT, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceWimax:rssi: + * + * RSSI of the current radio link in dBm. This value indicates how strong + * the raw received RF signal from the base station is, but does not + * indicate the overall quality of the radio link. Has no meaning when the + * device is not connected. + **/ + g_object_class_install_property + (object_class, PROP_RSSI, + g_param_spec_int (NM_DEVICE_WIMAX_RSSI, "", "", + G_MININT, G_MAXINT, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceWimax:cinr: + * + * CINR (Carrier to Interference + Noise Ratio) of the current radio link + * in dB. CINR is a more accurate measure of radio link quality. Has no + * meaning when the device is not connected. + **/ + g_object_class_install_property + (object_class, PROP_CINR, + g_param_spec_int (NM_DEVICE_WIMAX_CINR, "", "", + G_MININT, G_MAXINT, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceWimax:tx-power: + * + * Average power of the last burst transmitted by the device, in units of + * 0.5 dBm. i.e. a TxPower of -11 represents an actual device TX power of + * -5.5 dBm. Has no meaning when the device is not connected. + **/ + g_object_class_install_property + (object_class, PROP_TX_POWER, + g_param_spec_int (NM_DEVICE_WIMAX_TX_POWER, "", "", + G_MININT, G_MAXINT, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceWimax:bsid: + * + * The ID of the serving base station as received from the network. Has + * no meaning when the device is not connected. + **/ + g_object_class_install_property + (object_class, PROP_BSID, + g_param_spec_string (NM_DEVICE_WIMAX_BSID, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceWimax:nsps: + * + * List of all WiMAX Network Service Providers the device can see. + * + * Element-type: NMWimaxNsp + **/ + g_object_class_install_property + (object_class, PROP_NSPS, + g_param_spec_boxed (NM_DEVICE_WIMAX_NSPS, "", "", + G_TYPE_PTR_ARRAY, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /* signals */ + + /** + * NMDeviceWimax::nsp-added: + * @self: the wimax device that received the signal + * @nsp: the new NSP + * + * Notifies that a #NMWimaxNsp is added to the wimax device. + **/ + signals[NSP_ADDED] = + g_signal_new ("nsp-added", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMDeviceWimaxClass, nsp_added), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); + + /** + * NMDeviceWimax::nsp-removed: + * @self: the wimax device that received the signal + * @nsp: the removed NSP + * + * Notifies that a #NMWimaxNsp is removed from the wimax device. + **/ + signals[NSP_REMOVED] = + g_signal_new ("nsp-removed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMDeviceWimaxClass, nsp_removed), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); +} diff --git a/libnm/nm-device-wimax.h b/libnm/nm-device-wimax.h new file mode 100644 index 00000000..60910984 --- /dev/null +++ b/libnm/nm-device-wimax.h @@ -0,0 +1,81 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2011 - 2012 Red Hat, Inc. + * Copyright 2009 Novell, Inc. + */ + +#ifndef __NM_DEVICE_WIMAX_H__ +#define __NM_DEVICE_WIMAX_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include <nm-device.h> + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_WIMAX (nm_device_wimax_get_type ()) +#define NM_DEVICE_WIMAX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_WIMAX, NMDeviceWimax)) +#define NM_DEVICE_WIMAX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_WIMAX, NMDeviceWimaxClass)) +#define NM_IS_DEVICE_WIMAX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_WIMAX)) +#define NM_IS_DEVICE_WIMAX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_WIMAX)) +#define NM_DEVICE_WIMAX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_WIMAX, NMDeviceWimaxClass)) + +#define NM_DEVICE_WIMAX_HW_ADDRESS "hw-address" +#define NM_DEVICE_WIMAX_ACTIVE_NSP "active-nsp" +#define NM_DEVICE_WIMAX_CENTER_FREQUENCY "center-frequency" +#define NM_DEVICE_WIMAX_RSSI "rssi" +#define NM_DEVICE_WIMAX_CINR "cinr" +#define NM_DEVICE_WIMAX_TX_POWER "tx-power" +#define NM_DEVICE_WIMAX_BSID "bsid" +#define NM_DEVICE_WIMAX_NSPS "nsps" + +struct _NMDeviceWimax { + NMDevice parent; +}; + +typedef struct { + NMDeviceClass parent; + + /* Signals */ + void (*nsp_added) (NMDeviceWimax *self, NMWimaxNsp *nsp); + void (*nsp_removed) (NMDeviceWimax *self, NMWimaxNsp *nsp); + + /*< private >*/ + gpointer padding[4]; +} NMDeviceWimaxClass; + +GType nm_device_wimax_get_type (void); + +const char *nm_device_wimax_get_hw_address (NMDeviceWimax *wimax); +NMWimaxNsp *nm_device_wimax_get_active_nsp (NMDeviceWimax *wimax); +NMWimaxNsp *nm_device_wimax_get_nsp_by_path (NMDeviceWimax *wimax, + const char *path); + +const GPtrArray *nm_device_wimax_get_nsps (NMDeviceWimax *wimax); + +guint nm_device_wimax_get_center_frequency (NMDeviceWimax *self); +gint nm_device_wimax_get_rssi (NMDeviceWimax *self); +gint nm_device_wimax_get_cinr (NMDeviceWimax *self); +gint nm_device_wimax_get_tx_power (NMDeviceWimax *self); +const char * nm_device_wimax_get_bsid (NMDeviceWimax *self); + +G_END_DECLS + +#endif /* __NM_DEVICE_WIMAX_H__ */ diff --git a/libnm/nm-device.c b/libnm/nm-device.c new file mode 100644 index 00000000..e80ac707 --- /dev/null +++ b/libnm/nm-device.c @@ -0,0 +1,2232 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2007 - 2008 Novell, Inc. + * Copyright 2007 - 2012 Red Hat, Inc. + */ + +#include "config.h" + +#include <string.h> + +#include <glib/gi18n-lib.h> +#include <gudev/gudev.h> + +#include "nm-dbus-interface.h" +#include "nm-active-connection.h" +#include "nm-device-ethernet.h" +#include "nm-device-adsl.h" +#include "nm-device-wifi.h" +#include "nm-device-modem.h" +#include "nm-device-bt.h" +#include "nm-device-olpc-mesh.h" +#include "nm-device-wimax.h" +#include "nm-device-infiniband.h" +#include "nm-device-bond.h" +#include "nm-device-team.h" +#include "nm-device-bridge.h" +#include "nm-device-vlan.h" +#include "nm-device-generic.h" +#include "nm-device.h" +#include "nm-device-private.h" +#include "nm-dhcp4-config.h" +#include "nm-dhcp6-config.h" +#include "nm-ip4-config.h" +#include "nm-ip6-config.h" +#include "nm-object-private.h" +#include "nm-object-cache.h" +#include "nm-remote-connection.h" +#include "nm-core-internal.h" +#include "nm-glib-compat.h" +#include "nm-utils.h" +#include "nm-dbus-helpers.h" +#include "nm-setting-connection.h" + +#include "nmdbus-device.h" + +static GType _nm_device_decide_type (GVariant *value); +gboolean connection_compatible (NMDevice *device, NMConnection *connection, GError **error); + +G_DEFINE_TYPE_WITH_CODE (NMDevice, nm_device, NM_TYPE_OBJECT, + _nm_object_register_type_func (g_define_type_id, + _nm_device_decide_type, + NM_DBUS_INTERFACE_DEVICE, + "DeviceType"); + ) + +#define NM_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE, NMDevicePrivate)) + +typedef struct { + NMDBusDevice *proxy; + + char *iface; + char *ip_iface; + NMDeviceType device_type; + char *udi; + char *driver; + char *driver_version; + char *firmware_version; + char *type_description; + NMDeviceCapabilities capabilities; + gboolean managed; + gboolean firmware_missing; + gboolean autoconnect; + NMIPConfig *ip4_config; + NMDhcpConfig *dhcp4_config; + NMIPConfig *ip6_config; + NMDhcpConfig *dhcp6_config; + NMDeviceState state; + NMDeviceState last_seen_state; + NMDeviceStateReason reason; + + NMActiveConnection *active_connection; + GPtrArray *available_connections; + + GUdevClient *client; + char *product, *short_product; + char *vendor, *short_vendor; + char *description, *bus_name; + + char *physical_port_id; + guint32 mtu; +} NMDevicePrivate; + +enum { + PROP_0, + PROP_INTERFACE, + PROP_UDI, + PROP_DRIVER, + PROP_DRIVER_VERSION, + PROP_FIRMWARE_VERSION, + PROP_CAPABILITIES, + PROP_MANAGED, + PROP_AUTOCONNECT, + PROP_FIRMWARE_MISSING, + PROP_IP4_CONFIG, + PROP_DHCP4_CONFIG, + PROP_IP6_CONFIG, + PROP_STATE, + PROP_STATE_REASON, + PROP_PRODUCT, + PROP_VENDOR, + PROP_DHCP6_CONFIG, + PROP_IP_INTERFACE, + PROP_DEVICE_TYPE, + PROP_ACTIVE_CONNECTION, + PROP_AVAILABLE_CONNECTIONS, + PROP_PHYSICAL_PORT_ID, + PROP_MTU, + + LAST_PROP +}; + +enum { + STATE_CHANGED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +static void +nm_device_init (NMDevice *device) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + + priv->state = NM_DEVICE_STATE_UNKNOWN; + priv->reason = NM_DEVICE_STATE_REASON_NONE; +} + +static gboolean +demarshal_state_reason (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field) +{ + guint32 *reason_field = field; + + g_variant_get (value, "(uu)", NULL, reason_field); + _nm_object_queue_notify (object, NM_DEVICE_STATE_REASON); + return TRUE; +} + +static void +device_state_changed (NMDBusDevice *proxy, + guint new_state, + guint old_state, + guint reason, + gpointer user_data); + +static void +init_dbus (NMObject *object) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object); + const NMPropertiesInfo property_info[] = { + { NM_DEVICE_UDI, &priv->udi }, + { NM_DEVICE_INTERFACE, &priv->iface }, + { NM_DEVICE_IP_INTERFACE, &priv->ip_iface }, + { NM_DEVICE_DRIVER, &priv->driver }, + { NM_DEVICE_DRIVER_VERSION, &priv->driver_version }, + { NM_DEVICE_FIRMWARE_VERSION, &priv->firmware_version }, + { NM_DEVICE_CAPABILITIES, &priv->capabilities }, + { NM_DEVICE_MANAGED, &priv->managed }, + { NM_DEVICE_AUTOCONNECT, &priv->autoconnect }, + { NM_DEVICE_FIRMWARE_MISSING, &priv->firmware_missing }, + { NM_DEVICE_IP4_CONFIG, &priv->ip4_config, NULL, NM_TYPE_IP4_CONFIG }, + { NM_DEVICE_DHCP4_CONFIG, &priv->dhcp4_config, NULL, NM_TYPE_DHCP4_CONFIG }, + { NM_DEVICE_IP6_CONFIG, &priv->ip6_config, NULL, NM_TYPE_IP6_CONFIG }, + { NM_DEVICE_DHCP6_CONFIG, &priv->dhcp6_config, NULL, NM_TYPE_DHCP6_CONFIG }, + { NM_DEVICE_STATE, &priv->state }, + { NM_DEVICE_STATE_REASON, &priv->reason, demarshal_state_reason }, + { NM_DEVICE_ACTIVE_CONNECTION, &priv->active_connection, NULL, NM_TYPE_ACTIVE_CONNECTION }, + { NM_DEVICE_AVAILABLE_CONNECTIONS, &priv->available_connections, NULL, NM_TYPE_REMOTE_CONNECTION }, + { NM_DEVICE_PHYSICAL_PORT_ID, &priv->physical_port_id }, + { NM_DEVICE_MTU, &priv->mtu }, + + /* Properties that exist in D-Bus but that we don't track */ + { "ip4-address", NULL }, + { "device-type", NULL }, + + { NULL }, + }; + + NM_OBJECT_CLASS (nm_device_parent_class)->init_dbus (object); + + priv->proxy = NMDBUS_DEVICE (_nm_object_get_proxy (object, NM_DBUS_INTERFACE_DEVICE)); + _nm_object_register_properties (object, + NM_DBUS_INTERFACE_DEVICE, + property_info); + + g_signal_connect (priv->proxy, "state-changed", + G_CALLBACK (device_state_changed), object); +} + +typedef struct { + NMDeviceState old_state; + NMDeviceState new_state; + NMDeviceStateReason reason; +} StateChangeData; + +static void +device_state_change_reloaded (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + NMDevice *self = NM_DEVICE (object); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + StateChangeData *data = user_data; + NMDeviceState old_state = data->old_state; + NMDeviceState new_state = data->new_state; + NMDeviceStateReason reason = data->reason; + + g_slice_free (StateChangeData, data); + + _nm_object_reload_properties_finish (NM_OBJECT (object), result, NULL); + + /* If the device changes state several times in rapid succession, then we'll + * queue several reload_properties() calls, and there's no guarantee that + * they'll finish in the right order. In that case, only emit the signal + * for the last one. + */ + if (priv->last_seen_state != new_state) + return; + + /* Ensure that nm_device_get_state() will return the right value even if + * we haven't processed the corresponding PropertiesChanged yet. + */ + priv->state = new_state; + + g_signal_emit (self, signals[STATE_CHANGED], 0, + new_state, old_state, reason); +} + +static void +device_state_changed (NMDBusDevice *proxy, + guint new_state, + guint old_state, + guint reason, + gpointer user_data) +{ + NMDevice *self = NM_DEVICE (user_data); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + StateChangeData *data; + + if (old_state == new_state) + return; + + /* Our object-valued properties (eg, ip4_config) will still + * have their old values at this point, because NMObject is + * in the process of asynchronously reading the new values. + * Wait for that to finish before emitting the signal. + */ + priv->last_seen_state = new_state; + + data = g_slice_new (StateChangeData); + data->old_state = old_state; + data->new_state = new_state; + data->reason = reason; + _nm_object_reload_properties_async (NM_OBJECT (user_data), + NULL, + device_state_change_reloaded, + data); +} + +static GType +_nm_device_gtype_from_dtype (NMDeviceType dtype) +{ + switch (dtype) { + case NM_DEVICE_TYPE_ETHERNET: + return NM_TYPE_DEVICE_ETHERNET; + case NM_DEVICE_TYPE_WIFI: + return NM_TYPE_DEVICE_WIFI; + case NM_DEVICE_TYPE_MODEM: + return NM_TYPE_DEVICE_MODEM; + case NM_DEVICE_TYPE_BT: + return NM_TYPE_DEVICE_BT; + case NM_DEVICE_TYPE_ADSL: + return NM_TYPE_DEVICE_ADSL; + case NM_DEVICE_TYPE_OLPC_MESH: + return NM_TYPE_DEVICE_OLPC_MESH; + case NM_DEVICE_TYPE_WIMAX: + return NM_TYPE_DEVICE_WIMAX; + case NM_DEVICE_TYPE_INFINIBAND: + return NM_TYPE_DEVICE_INFINIBAND; + case NM_DEVICE_TYPE_BOND: + return NM_TYPE_DEVICE_BOND; + case NM_DEVICE_TYPE_TEAM: + return NM_TYPE_DEVICE_TEAM; + case NM_DEVICE_TYPE_BRIDGE: + return NM_TYPE_DEVICE_BRIDGE; + case NM_DEVICE_TYPE_VLAN: + return NM_TYPE_DEVICE_VLAN; + case NM_DEVICE_TYPE_GENERIC: + return NM_TYPE_DEVICE_GENERIC; + default: + g_warning ("Unknown device type %d", dtype); + return G_TYPE_INVALID; + } +} + +static void +constructed (GObject *object) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object); + + G_OBJECT_CLASS (nm_device_parent_class)->constructed (object); + + /* Catch failure of subclasses to call _nm_device_set_device_type() */ + g_warn_if_fail (priv->device_type != NM_DEVICE_TYPE_UNKNOWN); + /* Catch a subclass setting the wrong type */ + g_warn_if_fail (G_OBJECT_TYPE (object) == _nm_device_gtype_from_dtype (priv->device_type)); +} + +static void +dispose (GObject *object) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object); + + g_clear_object (&priv->ip4_config); + g_clear_object (&priv->dhcp4_config); + g_clear_object (&priv->ip6_config); + g_clear_object (&priv->dhcp6_config); + g_clear_object (&priv->client); + g_clear_object (&priv->active_connection); + + g_clear_pointer (&priv->available_connections, g_ptr_array_unref); + + G_OBJECT_CLASS (nm_device_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object); + + g_free (priv->iface); + g_free (priv->ip_iface); + g_free (priv->udi); + g_free (priv->driver); + g_free (priv->driver_version); + g_free (priv->firmware_version); + g_free (priv->product); + g_free (priv->short_product); + g_free (priv->vendor); + g_free (priv->short_vendor); + g_free (priv->description); + g_free (priv->bus_name); + g_free (priv->type_description); + g_free (priv->physical_port_id); + + G_OBJECT_CLASS (nm_device_parent_class)->finalize (object); +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMDevice *device = NM_DEVICE (object); + + switch (prop_id) { + case PROP_DEVICE_TYPE: + g_value_set_enum (value, nm_device_get_device_type (device)); + break; + case PROP_UDI: + g_value_set_string (value, nm_device_get_udi (device)); + break; + case PROP_INTERFACE: + g_value_set_string (value, nm_device_get_iface (device)); + break; + case PROP_IP_INTERFACE: + g_value_set_string (value, nm_device_get_ip_iface (device)); + break; + case PROP_DRIVER: + g_value_set_string (value, nm_device_get_driver (device)); + break; + case PROP_DRIVER_VERSION: + g_value_set_string (value, nm_device_get_driver_version (device)); + break; + case PROP_FIRMWARE_VERSION: + g_value_set_string (value, nm_device_get_firmware_version (device)); + break; + case PROP_CAPABILITIES: + g_value_set_flags (value, nm_device_get_capabilities (device)); + break; + case PROP_MANAGED: + g_value_set_boolean (value, nm_device_get_managed (device)); + break; + case PROP_AUTOCONNECT: + g_value_set_boolean (value, nm_device_get_autoconnect (device)); + break; + case PROP_FIRMWARE_MISSING: + g_value_set_boolean (value, nm_device_get_firmware_missing (device)); + break; + case PROP_IP4_CONFIG: + g_value_set_object (value, nm_device_get_ip4_config (device)); + break; + case PROP_DHCP4_CONFIG: + g_value_set_object (value, nm_device_get_dhcp4_config (device)); + break; + case PROP_IP6_CONFIG: + g_value_set_object (value, nm_device_get_ip6_config (device)); + break; + case PROP_DHCP6_CONFIG: + g_value_set_object (value, nm_device_get_dhcp6_config (device)); + break; + case PROP_STATE: + g_value_set_enum (value, nm_device_get_state (device)); + break; + case PROP_STATE_REASON: + g_value_set_uint (value, nm_device_get_state_reason (device)); + break; + case PROP_ACTIVE_CONNECTION: + g_value_set_object (value, nm_device_get_active_connection (device)); + break; + case PROP_AVAILABLE_CONNECTIONS: + g_value_take_boxed (value, _nm_utils_copy_object_array (nm_device_get_available_connections (device))); + break; + case PROP_PRODUCT: + g_value_set_string (value, nm_device_get_product (device)); + break; + case PROP_VENDOR: + g_value_set_string (value, nm_device_get_vendor (device)); + break; + case PROP_PHYSICAL_PORT_ID: + g_value_set_string (value, nm_device_get_physical_port_id (device)); + break; + case PROP_MTU: + g_value_set_uint (value, nm_device_get_mtu (device)); + 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) +{ + NMDevice *self = NM_DEVICE (object); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + gboolean b; + + switch (prop_id) { + case PROP_DEVICE_TYPE: + /* Construct only */ + priv->device_type = g_value_get_enum (value); + break; + case PROP_AUTOCONNECT: + b = g_value_get_boolean (value); + if (priv->autoconnect != b) + nm_device_set_autoconnect (NM_DEVICE (object), b); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_device_class_init (NMDeviceClass *device_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (device_class); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (device_class); + + g_type_class_add_private (device_class, sizeof (NMDevicePrivate)); + + _nm_object_class_add_interface (nm_object_class, NM_DBUS_INTERFACE_DEVICE); + _nm_dbus_register_proxy_type (NM_DBUS_INTERFACE_DEVICE, NMDBUS_TYPE_DEVICE_PROXY); + + /* virtual methods */ + object_class->constructed = constructed; + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->dispose = dispose; + object_class->finalize = finalize; + + nm_object_class->init_dbus = init_dbus; + + device_class->connection_compatible = connection_compatible; + + /* properties */ + + /** + * NMDevice:interface: + * + * The interface of the device. + **/ + g_object_class_install_property + (object_class, PROP_INTERFACE, + g_param_spec_string (NM_DEVICE_INTERFACE, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDevice:ip-interface: + * + * The IP interface of the device which should be used for all IP-related + * operations like addressing and routing. + **/ + g_object_class_install_property + (object_class, PROP_IP_INTERFACE, + g_param_spec_string (NM_DEVICE_IP_INTERFACE, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDevice:device-type: + * + * The numeric type of the device. + **/ + g_object_class_install_property + (object_class, PROP_DEVICE_TYPE, + g_param_spec_enum (NM_DEVICE_DEVICE_TYPE, "", "", + NM_TYPE_DEVICE_TYPE, + NM_DEVICE_TYPE_UNKNOWN, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + /** + * NMDevice:udi: + * + * An operating-system specific device hardware identifier; this is not + * unique to a specific hardware device across reboots or hotplugs. It + * is an opaque string which for some device types (Bluetooth, Modem) + * contains an identifier provided by the underlying hardware service daemon + * such as Bluez or ModemManager, and clients can use this property to + * request more information about the device from those services. + **/ + g_object_class_install_property + (object_class, PROP_UDI, + g_param_spec_string (NM_DEVICE_UDI, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDevice:driver: + * + * The driver of the device. + **/ + g_object_class_install_property + (object_class, PROP_DRIVER, + g_param_spec_string (NM_DEVICE_DRIVER, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDevice:driver-version: + * + * The version of the device driver. + **/ + g_object_class_install_property + (object_class, PROP_DRIVER_VERSION, + g_param_spec_string (NM_DEVICE_DRIVER_VERSION, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDevice:firmware-version: + * + * The firmware version of the device. + **/ + g_object_class_install_property + (object_class, PROP_FIRMWARE_VERSION, + g_param_spec_string (NM_DEVICE_FIRMWARE_VERSION, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDevice:capabilities: + * + * The capabilities of the device. + **/ + g_object_class_install_property + (object_class, PROP_CAPABILITIES, + g_param_spec_flags (NM_DEVICE_CAPABILITIES, "", "", + NM_TYPE_DEVICE_CAPABILITIES, + NM_DEVICE_CAP_NONE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDevice:managed: + * + * Whether the device is managed by NetworkManager. + **/ + g_object_class_install_property + (object_class, PROP_MANAGED, + g_param_spec_boolean (NM_DEVICE_MANAGED, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDevice:autoconnect: + * + * Whether the device can auto-activate a connection. + **/ + g_object_class_install_property + (object_class, PROP_AUTOCONNECT, + g_param_spec_boolean (NM_DEVICE_AUTOCONNECT, "", "", + TRUE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDevice:firmware-missing: + * + * When %TRUE indicates the device is likely missing firmware required + * for its operation. + **/ + g_object_class_install_property + (object_class, PROP_FIRMWARE_MISSING, + g_param_spec_boolean (NM_DEVICE_FIRMWARE_MISSING, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDevice:ip4-config: + * + * The #NMIP4Config of the device. + **/ + g_object_class_install_property + (object_class, PROP_IP4_CONFIG, + g_param_spec_object (NM_DEVICE_IP4_CONFIG, "", "", + NM_TYPE_IP_CONFIG, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDevice:dhcp4-config: + * + * The IPv4 #NMDhcpConfig of the device. + **/ + g_object_class_install_property + (object_class, PROP_DHCP4_CONFIG, + g_param_spec_object (NM_DEVICE_DHCP4_CONFIG, "", "", + NM_TYPE_DHCP_CONFIG, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDevice:ip6-config: + * + * The IPv6 #NMIPConfig of the device. + **/ + g_object_class_install_property + (object_class, PROP_IP6_CONFIG, + g_param_spec_object (NM_DEVICE_IP6_CONFIG, "", "", + NM_TYPE_IP_CONFIG, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDevice:dhcp6-config: + * + * The IPv6 #NMDhcpConfig of the device. + **/ + g_object_class_install_property + (object_class, PROP_DHCP6_CONFIG, + g_param_spec_object (NM_DEVICE_DHCP6_CONFIG, "", "", + NM_TYPE_DHCP_CONFIG, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDevice:state: + * + * The state of the device. + **/ + g_object_class_install_property + (object_class, PROP_STATE, + g_param_spec_enum (NM_DEVICE_STATE, "", "", + NM_TYPE_DEVICE_STATE, + NM_DEVICE_STATE_UNKNOWN, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDevice:state-reason: + * + * The reason for the device state. + **/ + g_object_class_install_property + (object_class, PROP_STATE_REASON, + g_param_spec_uint (NM_DEVICE_STATE_REASON, "", "", + 0, G_MAXUINT32, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDevice:active-connection: + * + * The #NMActiveConnection object that "owns" this device during activation. + **/ + g_object_class_install_property + (object_class, PROP_ACTIVE_CONNECTION, + g_param_spec_object (NM_DEVICE_ACTIVE_CONNECTION, "", "", + NM_TYPE_ACTIVE_CONNECTION, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDevice:available-connections: + * + * The available connections of the device + * + * Element-type: NMRemoteConnection + **/ + g_object_class_install_property + (object_class, PROP_AVAILABLE_CONNECTIONS, + g_param_spec_boxed (NM_DEVICE_AVAILABLE_CONNECTIONS, "", "", + G_TYPE_PTR_ARRAY, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDevice:vendor: + * + * The vendor string of the device. + **/ + g_object_class_install_property + (object_class, PROP_VENDOR, + g_param_spec_string (NM_DEVICE_VENDOR, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDevice:product: + * + * The product string of the device. + **/ + g_object_class_install_property + (object_class, PROP_PRODUCT, + g_param_spec_string (NM_DEVICE_PRODUCT, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDevice:physical-port-id: + * + * The physical port ID of the device. (See + * nm_device_get_physical_port_id().) + **/ + g_object_class_install_property + (object_class, PROP_PHYSICAL_PORT_ID, + g_param_spec_string (NM_DEVICE_PHYSICAL_PORT_ID, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDevice:mtu: + * + * The MTU of the device. + **/ + g_object_class_install_property + (object_class, PROP_MTU, + g_param_spec_uint (NM_DEVICE_MTU, "", "", + 0, G_MAXUINT32, 1500, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /* signals */ + + /** + * NMDevice::state-changed: + * @device: the device object that received the signal + * @new_state: the new state of the device + * @old_state: the previous state of the device + * @reason: the reason describing the state change + * + * Notifies the state change of a #NMDevice. + **/ + signals[STATE_CHANGED] = + g_signal_new ("state-changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMDeviceClass, state_changed), + NULL, NULL, NULL, + G_TYPE_NONE, 3, + G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT); +} + +/** + * _nm_device_set_device_type: + * @device: the device + * @dtype: the NM device type + * + * Sets the NM device type if it wasn't set during construction. INTERNAL + * ONLY METHOD. + **/ +void +_nm_device_set_device_type (NMDevice *device, NMDeviceType dtype) +{ + NMDevicePrivate *priv; + + g_return_if_fail (device != NULL); + g_return_if_fail (dtype != NM_DEVICE_TYPE_UNKNOWN); + + priv = NM_DEVICE_GET_PRIVATE (device); + if (priv->device_type == NM_DEVICE_TYPE_UNKNOWN) + priv->device_type = dtype; + else + g_warn_if_fail (dtype == priv->device_type); +} + +static GType +_nm_device_decide_type (GVariant *value) +{ + return _nm_device_gtype_from_dtype (g_variant_get_uint32 (value)); +} + +/** + * nm_device_get_iface: + * @device: a #NMDevice + * + * Gets the interface name of the #NMDevice. + * + * Returns: the interface of the device. This is the internal string used by the + * device, and must not be modified. + **/ +const char * +nm_device_get_iface (NMDevice *device) +{ + g_return_val_if_fail (NM_IS_DEVICE (device), NULL); + + return NM_DEVICE_GET_PRIVATE (device)->iface; +} + +/** + * nm_device_get_ip_iface: + * @device: a #NMDevice + * + * Gets the IP interface name of the #NMDevice over which IP traffic flows + * when the device is in the ACTIVATED state. + * + * Returns: the IP traffic interface of the device. This is the internal string + * used by the device, and must not be modified. + **/ +const char * +nm_device_get_ip_iface (NMDevice *device) +{ + g_return_val_if_fail (NM_IS_DEVICE (device), NULL); + + return NM_DEVICE_GET_PRIVATE (device)->ip_iface; +} + +/** + * nm_device_get_device_type: + * @device: a #NMDevice + * + * Returns the numeric type of the #NMDevice, ie Ethernet, Wi-Fi, etc. + * + * Returns: the device type + **/ +NMDeviceType +nm_device_get_device_type (NMDevice *self) +{ + g_return_val_if_fail (NM_IS_DEVICE (self), NM_DEVICE_TYPE_UNKNOWN); + + return NM_DEVICE_GET_PRIVATE (self)->device_type; +} + +/** + * nm_device_get_udi: + * @device: a #NMDevice + * + * Gets the Unique Device Identifier of the #NMDevice. + * + * Returns: the Unique Device Identifier of the device. This identifier may be + * used to gather more information about the device from various operating + * system services like udev or sysfs. + **/ +const char * +nm_device_get_udi (NMDevice *device) +{ + g_return_val_if_fail (NM_IS_DEVICE (device), NULL); + + return NM_DEVICE_GET_PRIVATE (device)->udi; +} + +/** + * nm_device_get_driver: + * @device: a #NMDevice + * + * Gets the driver of the #NMDevice. + * + * Returns: the driver of the device. This is the internal string used by the + * device, and must not be modified. + **/ +const char * +nm_device_get_driver (NMDevice *device) +{ + g_return_val_if_fail (NM_IS_DEVICE (device), NULL); + + return NM_DEVICE_GET_PRIVATE (device)->driver; +} + +/** + * nm_device_get_driver_version: + * @device: a #NMDevice + * + * Gets the driver version of the #NMDevice. + * + * Returns: the version of the device driver. This is the internal string used by the + * device, and must not be modified. + **/ +const char * +nm_device_get_driver_version (NMDevice *device) +{ + g_return_val_if_fail (NM_IS_DEVICE (device), NULL); + + return NM_DEVICE_GET_PRIVATE (device)->driver_version; +} + +/** + * nm_device_get_firmware_version: + * @device: a #NMDevice + * + * Gets the firmware version of the #NMDevice. + * + * Returns: the firmware version of the device. This is the internal string used by the + * device, and must not be modified. + **/ +const char * +nm_device_get_firmware_version (NMDevice *device) +{ + g_return_val_if_fail (NM_IS_DEVICE (device), NULL); + + return NM_DEVICE_GET_PRIVATE (device)->firmware_version; +} + +/** + * nm_device_get_type_description: + * @device: a #NMDevice + * + * Gets a (non-localized) description of the type of device that + * @device is. + * + * Returns: the type description of the device. This is the internal + * string used by the device, and must not be modified. + **/ +const char * +nm_device_get_type_description (NMDevice *device) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + const char *desc, *typename; + + g_return_val_if_fail (NM_IS_DEVICE (device), NULL); + + if (priv->type_description) + return priv->type_description; + + if (NM_DEVICE_GET_CLASS (device)->get_type_description) { + desc = NM_DEVICE_GET_CLASS (device)->get_type_description (device); + if (desc) + return desc; + } + + typename = G_OBJECT_TYPE_NAME (device); + if (g_str_has_prefix (typename, "NMDevice")) + typename += 8; + priv->type_description = g_ascii_strdown (typename, -1); + + return priv->type_description; +} + +/** + * nm_device_get_hw_address: + * @device: a #NMDevice + * + * Gets the current a hardware address (MAC) for the @device. + * + * Returns: the current MAC of the device, or %NULL. + * This is the internal string used by the device, and must not be modified. + **/ +const char * +nm_device_get_hw_address (NMDevice *device) +{ + g_return_val_if_fail (NM_IS_DEVICE (device), NULL); + + if (NM_DEVICE_GET_CLASS (device)->get_hw_address) + return NM_DEVICE_GET_CLASS (device)->get_hw_address (device); + + return NULL; +} + +/** + * nm_device_get_capabilities: + * @device: a #NMDevice + * + * Gets the device' capabilities. + * + * Returns: the capabilities + **/ +NMDeviceCapabilities +nm_device_get_capabilities (NMDevice *device) +{ + g_return_val_if_fail (NM_IS_DEVICE (device), 0); + + return NM_DEVICE_GET_PRIVATE (device)->capabilities; +} + +/** + * nm_device_get_managed: + * @device: a #NMDevice + * + * Whether the #NMDevice is managed by NetworkManager. + * + * Returns: %TRUE if the device is managed by NetworkManager + **/ +gboolean +nm_device_get_managed (NMDevice *device) +{ + g_return_val_if_fail (NM_IS_DEVICE (device), 0); + + return NM_DEVICE_GET_PRIVATE (device)->managed; +} + +/** + * nm_device_get_autoconnect: + * @device: a #NMDevice + * + * Whether the #NMDevice can be autoconnected. + * + * Returns: %TRUE if the device is allowed to be autoconnected + **/ +gboolean +nm_device_get_autoconnect (NMDevice *device) +{ + g_return_val_if_fail (NM_IS_DEVICE (device), FALSE); + + return NM_DEVICE_GET_PRIVATE (device)->autoconnect; +} + +/** + * nm_device_set_autoconnect: + * @device: a #NMDevice + * @autoconnect: %TRUE to enable autoconnecting + * + * Enables or disables automatic activation of the #NMDevice. + **/ +void +nm_device_set_autoconnect (NMDevice *device, gboolean autoconnect) +{ + g_return_if_fail (NM_IS_DEVICE (device)); + + NM_DEVICE_GET_PRIVATE (device)->autoconnect = autoconnect; + + _nm_object_set_property (NM_OBJECT (device), + NM_DBUS_INTERFACE_DEVICE, + "Autoconnect", + "b", autoconnect); +} + +/** + * nm_device_get_firmware_missing: + * @device: a #NMDevice + * + * Indicates that firmware required for the device's operation is likely + * to be missing. + * + * Returns: %TRUE if firmware required for the device's operation is likely + * to be missing. + **/ +gboolean +nm_device_get_firmware_missing (NMDevice *device) +{ + g_return_val_if_fail (NM_IS_DEVICE (device), 0); + + return NM_DEVICE_GET_PRIVATE (device)->firmware_missing; +} + +/** + * nm_device_get_ip4_config: + * @device: a #NMDevice + * + * Gets the current IPv4 #NMIPConfig associated with the #NMDevice. + * + * You can alternatively use nm_active_connection_get_ip4_config(), which also + * works with VPN connections. + * + * Returns: (transfer none): the IPv4 #NMIPConfig, or %NULL if the device is not + * activated. + **/ +NMIPConfig * +nm_device_get_ip4_config (NMDevice *device) +{ + g_return_val_if_fail (NM_IS_DEVICE (device), NULL); + + return NM_DEVICE_GET_PRIVATE (device)->ip4_config; +} + +/** + * nm_device_get_dhcp4_config: + * @device: a #NMDevice + * + * Gets the current IPv4 #NMDhcpConfig associated with the #NMDevice. + * + * You can alternatively use nm_active_connection_get_dhcp4_config(), which also + * works with VPN connections. + * + * Returns: (transfer none): the IPv4 #NMDhcpConfig, or %NULL if the device is + * not activated or not using DHCP. + **/ +NMDhcpConfig * +nm_device_get_dhcp4_config (NMDevice *device) +{ + g_return_val_if_fail (NM_IS_DEVICE (device), NULL); + + return NM_DEVICE_GET_PRIVATE (device)->dhcp4_config; +} + +/** + * nm_device_get_ip6_config: + * @device: a #NMDevice + * + * Gets the current IPv6 #NMIPConfig associated with the #NMDevice. + * + * You can alternatively use nm_active_connection_get_ip6_config(), which also + * works with VPN connections. + * + * Returns: (transfer none): the IPv6 #NMIPConfig or %NULL if the device is not activated. + **/ +NMIPConfig * +nm_device_get_ip6_config (NMDevice *device) +{ + g_return_val_if_fail (NM_IS_DEVICE (device), NULL); + + return NM_DEVICE_GET_PRIVATE (device)->ip6_config; +} + +/** + * nm_device_get_dhcp6_config: + * @device: a #NMDevice + * + * Gets the current IPv6 #NMDhcpConfig associated with the #NMDevice. + * + * You can alternatively use nm_active_connection_get_dhcp6_config(), which also + * works with VPN connections. + * + * Returns: (transfer none): the IPv6 #NMDhcpConfig, or %NULL if the device is + * not activated or not using DHCPv6. + **/ +NMDhcpConfig * +nm_device_get_dhcp6_config (NMDevice *device) +{ + g_return_val_if_fail (NM_IS_DEVICE (device), NULL); + + return NM_DEVICE_GET_PRIVATE (device)->dhcp6_config; +} + +/** + * nm_device_get_state: + * @device: a #NMDevice + * + * Gets the current #NMDevice state. + * + * Returns: the current device state + **/ +NMDeviceState +nm_device_get_state (NMDevice *device) +{ + g_return_val_if_fail (NM_IS_DEVICE (device), NM_DEVICE_STATE_UNKNOWN); + + return NM_DEVICE_GET_PRIVATE (device)->state; +} + +/** + * nm_device_get_state_reason: + * @device: a #NMDevice + * + * Gets the reason for entering the current #NMDevice state. + * + * Returns: the reason for entering the current device state + **/ +NMDeviceStateReason +nm_device_get_state_reason (NMDevice *device) +{ + g_return_val_if_fail (NM_IS_DEVICE (device), NM_DEVICE_STATE_REASON_UNKNOWN); + + return NM_DEVICE_GET_PRIVATE (device)->reason; +} + +/** + * nm_device_get_active_connection: + * @device: a #NMDevice + * + * Gets the #NMActiveConnection object which owns this device during activation. + * + * Returns: (transfer none): the #NMActiveConnection or %NULL if the device is + * not part of an active connection + **/ +NMActiveConnection * +nm_device_get_active_connection (NMDevice *device) +{ + g_return_val_if_fail (NM_IS_DEVICE (device), NULL); + + return NM_DEVICE_GET_PRIVATE (device)->active_connection; +} + +/** + * nm_device_get_available_connections: + * @device: a #NMDevice + * + * Gets the #NMRemoteConnections currently known to the daemon that could + * be activated on @device. + * + * Returns: (element-type NMRemoteConnection): the #GPtrArray + * containing #NMRemoteConnections. This is the internal copy used by + * the connection, and must not be modified. + **/ +const GPtrArray * +nm_device_get_available_connections (NMDevice *device) +{ + g_return_val_if_fail (NM_IS_DEVICE (device), NULL); + + return NM_DEVICE_GET_PRIVATE (device)->available_connections; +} + +static inline guint8 +hex2byte (const char *hex) +{ + int a, b; + a = g_ascii_xdigit_value (*hex++); + if (a < 0) + return -1; + b = g_ascii_xdigit_value (*hex++); + if (b < 0) + return -1; + return (a << 4) | b; +} + +static char * +get_decoded_property (GUdevDevice *device, const char *property) +{ + const char *orig, *p; + char *unescaped, *n; + guint len; + + p = orig = g_udev_device_get_property (device, property); + if (!orig) + return NULL; + + len = strlen (orig); + n = unescaped = g_malloc0 (len + 1); + while (*p) { + if ((len >= 4) && (*p == '\\') && (*(p+1) == 'x')) { + *n++ = (char) hex2byte (p + 2); + p += 4; + len -= 4; + } else { + *n++ = *p++; + len--; + } + } + + return unescaped; +} + +static gboolean +ensure_udev_client (NMDevice *device) +{ + static const char *const subsys[3] = { "net", "tty", NULL }; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + + if (!priv->client) + priv->client = g_udev_client_new (subsys); + + return priv->client != NULL; +} + +static char * +_get_udev_property (NMDevice *device, + const char *enc_prop, /* ID_XXX_ENC */ + const char *db_prop) /* ID_XXX_FROM_DATABASE */ +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + GUdevDevice *udev_device = NULL, *tmpdev, *olddev; + const char *ifname; + guint32 count = 0; + char *enc_value = NULL, *db_value = NULL; + + if (!ensure_udev_client (device)) + return NULL; + + ifname = nm_device_get_iface (device); + if (!ifname) + return NULL; + + udev_device = g_udev_client_query_by_subsystem_and_name (priv->client, "net", ifname); + if (!udev_device) + udev_device = g_udev_client_query_by_subsystem_and_name (priv->client, "tty", ifname); + if (!udev_device) + return NULL; + + /* Walk up the chain of the device and its parents a few steps to grab + * vendor and device ID information off it. + */ + + /* Ref the device again because we have to unref it each iteration, + * as g_udev_device_get_parent() returns a ref-ed object. + */ + tmpdev = g_object_ref (udev_device); + while ((count++ < 3) && tmpdev && !enc_value) { + if (!enc_value) + enc_value = get_decoded_property (tmpdev, enc_prop); + if (!db_value) + db_value = g_strdup (g_udev_device_get_property (tmpdev, db_prop)); + + olddev = tmpdev; + tmpdev = g_udev_device_get_parent (tmpdev); + g_object_unref (olddev); + } + + /* Unref the last device if we found what we needed before running out + * of parents. + */ + if (tmpdev) + g_object_unref (tmpdev); + + /* Balance the initial g_udev_client_query_by_subsystem_and_name() */ + g_object_unref (udev_device); + + /* Prefer the encoded value which comes directly from the device + * over the hwdata database value. + */ + if (enc_value) { + g_free (db_value); + return enc_value; + } + + return db_value; +} + +/** + * nm_device_get_product: + * @device: a #NMDevice + * + * Gets the product string of the #NMDevice. + * + * Returns: the product name of the device. This is the internal string used by the + * device, and must not be modified. + **/ +const char * +nm_device_get_product (NMDevice *device) +{ + NMDevicePrivate *priv; + + g_return_val_if_fail (NM_IS_DEVICE (device), NULL); + + priv = NM_DEVICE_GET_PRIVATE (device); + if (!priv->product) { + priv->product = _get_udev_property (device, "ID_MODEL_ENC", "ID_MODEL_FROM_DATABASE"); + if (!priv->product) { + /* Sometimes ID_PRODUCT_FROM_DATABASE is used? */ + priv->product = _get_udev_property (device, "ID_MODEL_ENC", "ID_PRODUCT_FROM_DATABASE"); + } + _nm_object_queue_notify (NM_OBJECT (device), NM_DEVICE_PRODUCT); + } + return priv->product; +} + +/** + * nm_device_get_vendor: + * @device: a #NMDevice + * + * Gets the vendor string of the #NMDevice. + * + * Returns: the vendor name of the device. This is the internal string used by the + * device, and must not be modified. + **/ +const char * +nm_device_get_vendor (NMDevice *device) +{ + NMDevicePrivate *priv; + + g_return_val_if_fail (NM_IS_DEVICE (device), NULL); + + priv = NM_DEVICE_GET_PRIVATE (device); + if (!priv->vendor) { + priv->vendor = _get_udev_property (device, "ID_VENDOR_ENC", "ID_VENDOR_FROM_DATABASE"); + _nm_object_queue_notify (NM_OBJECT (device), NM_DEVICE_VENDOR); + } + return priv->vendor; +} + +static const char * const ignored_words[] = { + "Semiconductor", + "Components", + "Corporation", + "Communications", + "Company", + "Corp.", + "Corp", + "Co.", + "Inc.", + "Inc", + "Incorporated", + "Ltd.", + "Limited.", + "Intel?", + "chipset", + "adapter", + "[hex]", + "NDIS", + "Module", + NULL +}; + +static const char * const ignored_phrases[] = { + "Multiprotocol MAC/baseband processor", + "Wireless LAN Controller", + "Wireless LAN Adapter", + "Wireless Adapter", + "Network Connection", + "Wireless Cardbus Adapter", + "Wireless CardBus Adapter", + "54 Mbps Wireless PC Card", + "Wireless PC Card", + "Wireless PC", + "PC Card with XJACK(r) Antenna", + "Wireless cardbus", + "Wireless LAN PC Card", + "Technology Group Ltd.", + "Communication S.p.A.", + "Business Mobile Networks BV", + "Mobile Broadband Minicard Composite Device", + "Mobile Communications AB", + "(PC-Suite Mode)", + NULL +}; + +static char * +fixup_desc_string (const char *desc) +{ + char *p, *temp; + char **words, **item; + GString *str; + int i; + + if (!desc) + return NULL; + + p = temp = g_strdup (desc); + while (*p) { + if (*p == '_' || *p == ',') + *p = ' '; + p++; + } + + /* Attempt to shorten ID by ignoring certain phrases */ + for (i = 0; ignored_phrases[i]; i++) { + p = strstr (temp, ignored_phrases[i]); + if (p) { + guint32 ignored_len = strlen (ignored_phrases[i]); + + memmove (p, p + ignored_len, strlen (p + ignored_len) + 1); /* +1 for the \0 */ + } + } + + /* Attempt to shorten ID by ignoring certain individual words */ + words = g_strsplit (temp, " ", 0); + str = g_string_new_len (NULL, strlen (temp)); + g_free (temp); + + for (item = words; *item; item++) { + gboolean ignore = FALSE; + + if (**item == '\0') + continue; + + for (i = 0; ignored_words[i]; i++) { + if (!strcmp (*item, ignored_words[i])) { + ignore = TRUE; + break; + } + } + + if (!ignore) { + if (str->len) + g_string_append_c (str, ' '); + g_string_append (str, *item); + } + } + g_strfreev (words); + + temp = str->str; + g_string_free (str, FALSE); + + return temp; +} + +static void +get_description (NMDevice *device) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + const char *dev_product; + const char *dev_vendor; + char *pdown; + char *vdown; + GString *str; + + dev_product = nm_device_get_product (device); + priv->short_product = fixup_desc_string (dev_product); + + dev_vendor = nm_device_get_vendor (device); + priv->short_vendor = fixup_desc_string (dev_vendor); + + if (!dev_product || !dev_vendor) { + priv->description = g_strdup (nm_device_get_iface (device)); + return; + } + + str = g_string_new_len (NULL, strlen (priv->short_vendor) + strlen (priv->short_product) + 1); + + /* Another quick hack; if all of the fixed up vendor string + * is found in product, ignore the vendor. + */ + pdown = g_ascii_strdown (priv->short_product, -1); + vdown = g_ascii_strdown (priv->short_vendor, -1); + if (!strstr (pdown, vdown)) { + g_string_append (str, priv->short_vendor); + g_string_append_c (str, ' '); + } + g_free (pdown); + g_free (vdown); + + g_string_append (str, priv->short_product); + + priv->description = g_string_free (str, FALSE); +} + +static const char * +get_short_vendor (NMDevice *device) +{ + NMDevicePrivate *priv; + + g_return_val_if_fail (NM_IS_DEVICE (device), NULL); + + priv = NM_DEVICE_GET_PRIVATE (device); + + if (!priv->description) + get_description (device); + + return priv->short_vendor; +} + +/** + * nm_device_get_description: + * @device: an #NMDevice + * + * Gets a description of @device, based on its vendor and product names. + * + * Returns: a description of @device. If either the vendor or the + * product name is unknown, this returns the interface name. + */ +const char * +nm_device_get_description (NMDevice *device) +{ + NMDevicePrivate *priv; + + g_return_val_if_fail (NM_IS_DEVICE (device), NULL); + + priv = NM_DEVICE_GET_PRIVATE (device); + + if (!priv->description) + get_description (device); + + return priv->description; +} + +static const char * +get_type_name (NMDevice *device) +{ + switch (nm_device_get_device_type (device)) { + case NM_DEVICE_TYPE_ETHERNET: + return _("Ethernet"); + case NM_DEVICE_TYPE_WIFI: + return _("Wi-Fi"); + case NM_DEVICE_TYPE_BT: + return _("Bluetooth"); + case NM_DEVICE_TYPE_OLPC_MESH: + return _("OLPC Mesh"); + case NM_DEVICE_TYPE_WIMAX: + return _("WiMAX"); + case NM_DEVICE_TYPE_MODEM: + return _("Mobile Broadband"); + case NM_DEVICE_TYPE_INFINIBAND: + return _("InfiniBand"); + case NM_DEVICE_TYPE_BOND: + return _("Bond"); + case NM_DEVICE_TYPE_TEAM: + return _("Team"); + case NM_DEVICE_TYPE_BRIDGE: + return _("Bridge"); + case NM_DEVICE_TYPE_VLAN: + return _("VLAN"); + case NM_DEVICE_TYPE_ADSL: + return _("ADSL"); + default: + return _("Unknown"); + } +} + +static char * +get_device_type_name_with_iface (NMDevice *device) +{ + const char *type_name = get_type_name (device); + + switch (nm_device_get_device_type (device)) { + case NM_DEVICE_TYPE_BOND: + case NM_DEVICE_TYPE_TEAM: + case NM_DEVICE_TYPE_BRIDGE: + case NM_DEVICE_TYPE_VLAN: + return g_strdup_printf ("%s (%s)", type_name, nm_device_get_iface (device)); + default: + return g_strdup (type_name); + } +} + +static char * +get_device_generic_type_name_with_iface (NMDevice *device) +{ + switch (nm_device_get_device_type (device)) { + case NM_DEVICE_TYPE_ETHERNET: + case NM_DEVICE_TYPE_INFINIBAND: + return g_strdup (_("Wired")); + default: + return get_device_type_name_with_iface (device); + } +} + +static const char * +get_bus_name (NMDevice *device) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + GUdevDevice *udevice; + const char *ifname, *bus; + + if (priv->bus_name) + goto out; + + if (!ensure_udev_client (device)) + return NULL; + + ifname = nm_device_get_iface (device); + if (!ifname) + return NULL; + + udevice = g_udev_client_query_by_subsystem_and_name (priv->client, "net", ifname); + if (!udevice) + udevice = g_udev_client_query_by_subsystem_and_name (priv->client, "tty", ifname); + if (!udevice) + return NULL; + + bus = g_udev_device_get_property (udevice, "ID_BUS"); + if (!g_strcmp0 (bus, "pci")) + priv->bus_name = g_strdup (_("PCI")); + else if (!g_strcmp0 (bus, "usb")) + priv->bus_name = g_strdup (_("USB")); + else { + /* Use "" instead of NULL so we can tell later that we've + * already tried. + */ + priv->bus_name = g_strdup (""); + } + +out: + if (*priv->bus_name) + return priv->bus_name; + else + return NULL; +} + +static gboolean +find_duplicates (char **names, + gboolean *duplicates, + int num_devices) +{ + int i, j; + gboolean found_any = FALSE; + + memset (duplicates, 0, num_devices * sizeof (gboolean)); + for (i = 0; i < num_devices; i++) { + if (duplicates[i]) + continue; + for (j = i + 1; j < num_devices; j++) { + if (duplicates[j]) + continue; + if (!strcmp (names[i], names[j])) + duplicates[i] = duplicates[j] = found_any = TRUE; + } + } + + return found_any; +} + +/** + * nm_device_disambiguate_names: + * @devices: (array length=num_devices): an array of #NMDevice + * @num_devices: length of @devices + * + * Generates a list of short-ish unique presentation names for the + * devices in @devices. + * + * Returns: (transfer full) (array zero-terminated=1): the device names + */ +char ** +nm_device_disambiguate_names (NMDevice **devices, + int num_devices) +{ + char **names; + gboolean *duplicates; + int i; + + names = g_new (char *, num_devices + 1); + duplicates = g_new (gboolean, num_devices); + + /* Generic device name */ + for (i = 0; i < num_devices; i++) + names[i] = get_device_generic_type_name_with_iface (devices[i]); + if (!find_duplicates (names, duplicates, num_devices)) + goto done; + + /* Try specific names (eg, "Ethernet" and "InfiniBand" rather + * than "Wired") + */ + for (i = 0; i < num_devices; i++) { + if (duplicates[i]) { + g_free (names[i]); + names[i] = get_device_type_name_with_iface (devices[i]); + } + } + if (!find_duplicates (names, duplicates, num_devices)) + goto done; + + /* Try prefixing bus name (eg, "PCI Ethernet" vs "USB Ethernet") */ + for (i = 0; i < num_devices; i++) { + if (duplicates[i]) { + const char *bus = get_bus_name (devices[i]); + char *name; + + if (!bus) + continue; + + g_free (names[i]); + name = get_device_type_name_with_iface (devices[i]); + /* Translators: the first %s is a bus name (eg, "USB") or + * product name, the second is a device type (eg, + * "Ethernet"). You can change this to something like + * "%2$s (%1$s)" if there's no grammatical way to combine + * the strings otherwise. + */ + names[i] = g_strdup_printf (C_("long device name", "%s %s"), + bus, name); + g_free (name); + } + } + if (!find_duplicates (names, duplicates, num_devices)) + goto done; + + /* Try prefixing vendor name */ + for (i = 0; i < num_devices; i++) { + if (duplicates[i]) { + const char *vendor = get_short_vendor (devices[i]); + char *name; + + if (!vendor) + continue; + + g_free (names[i]); + name = get_device_type_name_with_iface (devices[i]); + names[i] = g_strdup_printf (C_("long device name", "%s %s"), + vendor, + get_type_name (devices[i])); + g_free (name); + } + } + if (!find_duplicates (names, duplicates, num_devices)) + goto done; + + /* We have multiple identical network cards, so we have to differentiate + * them by interface name. + */ + for (i = 0; i < num_devices; i++) { + if (duplicates[i]) { + const char *interface = nm_device_get_iface (devices[i]); + + if (!interface) + continue; + + g_free (names[i]); + names[i] = g_strdup_printf ("%s (%s)", + get_type_name (devices[i]), + interface); + } + } + +done: + g_free (duplicates); + names[num_devices] = NULL; + return names; +} + +/** + * nm_device_get_physical_port_id: + * @device: a #NMDevice + * + * Gets the physical port ID of the #NMDevice. If non-%NULL, this is + * an opaque string that can be used to recognize when + * seemingly-unrelated #NMDevices are actually just different virtual + * ports on a single physical port. (Eg, NPAR / SR-IOV.) + * + * Returns: the physical port ID of the device, or %NULL if the port + * ID is unknown. This is the internal string used by the device and + * must not be modified. + **/ +const char * +nm_device_get_physical_port_id (NMDevice *device) +{ + NMDevicePrivate *priv; + + g_return_val_if_fail (NM_IS_DEVICE (device), NULL); + + priv = NM_DEVICE_GET_PRIVATE (device); + + if (priv->physical_port_id && *priv->physical_port_id) + return priv->physical_port_id; + else + return NULL; +} + +/** + * nm_device_get_mtu: + * @device: a #NMDevice + * + * Gets the MTU of the #NMDevice. + * + * Returns: the MTU of the device. + **/ +guint32 +nm_device_get_mtu (NMDevice *device) +{ + g_return_val_if_fail (NM_IS_DEVICE (device), 0); + + return NM_DEVICE_GET_PRIVATE (device)->mtu; +} + +/** + * nm_device_is_software: + * @device: a #NMDevice + * + * Whether the device is a software device. + * + * Returns: %TRUE if @device is a software device, %FALSE if it is a hardware device. + **/ +gboolean +nm_device_is_software (NMDevice *device) +{ + g_return_val_if_fail (NM_IS_DEVICE (device), FALSE); + + return !!(NM_DEVICE_GET_PRIVATE (device)->capabilities & NM_DEVICE_CAP_IS_SOFTWARE); +} + +/** + * nm_device_disconnect: + * @device: a #NMDevice + * @cancellable: a #GCancellable, or %NULL + * @error: location for a #GError, or %NULL + * + * Disconnects the device if currently connected, and prevents the device from + * automatically connecting to networks until the next manual network connection + * request. + * + * Returns: %TRUE on success, %FALSE on error, in which case @error will be set. + **/ +gboolean +nm_device_disconnect (NMDevice *device, + GCancellable *cancellable, + GError **error) +{ + gboolean ret; + + g_return_val_if_fail (NM_IS_DEVICE (device), FALSE); + + ret = nmdbus_device_call_disconnect_sync (NM_DEVICE_GET_PRIVATE (device)->proxy, + cancellable, error); + if (error && *error) + g_dbus_error_strip_remote_error (*error); + return ret; +} + +static void +device_disconnect_cb (GObject *proxy, + GAsyncResult *result, + gpointer user_data) +{ + GSimpleAsyncResult *simple = user_data; + GError *error = NULL; + + if (nmdbus_device_call_disconnect_finish (NMDBUS_DEVICE (proxy), result, &error)) + g_simple_async_result_set_op_res_gboolean (simple, TRUE); + else { + g_dbus_error_strip_remote_error (error); + g_simple_async_result_take_error (simple, error); + } + + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +/** + * nm_device_disconnect_async: + * @device: a #NMDevice + * @cancellable: a #GCancellable, or %NULL + * @callback: callback to be called when the disconnect operation completes + * @user_data: caller-specific data passed to @callback + * + * Asynchronously begins disconnecting the device if currently connected, and + * prevents the device from automatically connecting to networks until the next + * manual network connection request. + **/ +void +nm_device_disconnect_async (NMDevice *device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *simple; + + g_return_if_fail (NM_IS_DEVICE (device)); + + simple = g_simple_async_result_new (G_OBJECT (device), callback, user_data, + nm_device_disconnect_async); + + nmdbus_device_call_disconnect (NM_DEVICE_GET_PRIVATE (device)->proxy, + cancellable, + device_disconnect_cb, simple); +} + +/** + * nm_device_disconnect_finish: + * @device: a #NMDevice + * @result: the result passed to the #GAsyncReadyCallback + * @error: location for a #GError, or %NULL + * + * Gets the result of a call to nm_device_disconnect_async(). + * + * Returns: %TRUE on success, %FALSE on error, in which case @error + * will be set. + **/ +gboolean +nm_device_disconnect_finish (NMDevice *device, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (device), nm_device_disconnect_async), FALSE); + + simple = G_SIMPLE_ASYNC_RESULT (result); + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + else + return g_simple_async_result_get_op_res_gboolean (simple); +} + +/** + * nm_device_delete: + * @device: a #NMDevice + * @cancellable: a #GCancellable, or %NULL + * @error: location for a #GError, or %NULL + * + * Deletes the software device. Hardware devices can't be deleted. + * + * Returns: %TRUE on success, %FALSE on error, in which case @error + * will be set. + **/ +gboolean +nm_device_delete (NMDevice *device, + GCancellable *cancellable, + GError **error) +{ + gboolean ret; + + g_return_val_if_fail (NM_IS_DEVICE (device), FALSE); + + ret = nmdbus_device_call_delete_sync (NM_DEVICE_GET_PRIVATE (device)->proxy, + cancellable, error); + if (error && *error) + g_dbus_error_strip_remote_error (*error); + return ret; +} + +static void +device_delete_cb (GObject *proxy, + GAsyncResult *result, + gpointer user_data) +{ + GSimpleAsyncResult *simple = user_data; + GError *error = NULL; + + if (nmdbus_device_call_delete_finish (NMDBUS_DEVICE (proxy), result, &error)) + g_simple_async_result_set_op_res_gboolean (simple, TRUE); + else { + g_dbus_error_strip_remote_error (error); + g_simple_async_result_take_error (simple, error); + } + + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +/** + * nm_device_delete_async: + * @device: a #NMDevice + * @cancellable: a #GCancellable, or %NULL + * @callback: callback to be called when delete operation completes + * @user_data: caller-specific data passed to @callback + * + * Asynchronously begins deleteing the software device. Hardware devices can't + * be deleted. + **/ +void +nm_device_delete_async (NMDevice *device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *simple; + + g_return_if_fail (NM_IS_DEVICE (device)); + + simple = g_simple_async_result_new (G_OBJECT (device), callback, user_data, + nm_device_delete_async); + + nmdbus_device_call_delete (NM_DEVICE_GET_PRIVATE (device)->proxy, + cancellable, + device_delete_cb, simple); +} + +/** + * nm_device_delete_finish: + * @device: a #NMDevice + * @result: the result passed to the #GAsyncReadyCallback + * @error: location for a #GError, or %NULL + * + * Gets the result of a call to nm_device_delete_async(). + * + * Returns: %TRUE on success, %FALSE on error, in which case @error + * will be set. + **/ +gboolean +nm_device_delete_finish (NMDevice *device, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (device), nm_device_delete_async), FALSE); + + simple = G_SIMPLE_ASYNC_RESULT (result); + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + else + return g_simple_async_result_get_op_res_gboolean (simple); +} + +/** + * nm_device_connection_valid: + * @device: an #NMDevice to validate @connection against + * @connection: an #NMConnection to validate against @device + * + * Validates a given connection for a given #NMDevice object and returns + * whether the connection may be activated with the device. For example if + * @device is a Wi-Fi device that supports only WEP encryption, the connection + * will only be valid if it is a Wi-Fi connection which describes a WEP or open + * network, and will not be valid if it describes a WPA network, or if it is + * an Ethernet, Bluetooth, WWAN, etc connection that is incompatible with the + * device. + * + * Returns: %TRUE if the connection may be activated with this device, %FALSE + * if is incompatible with the device's capabilities and characteristics. + **/ +gboolean +nm_device_connection_valid (NMDevice *device, NMConnection *connection) +{ + return nm_device_connection_compatible (device, connection, NULL); +} + +gboolean +connection_compatible (NMDevice *device, NMConnection *connection, GError **error) +{ + const char *config_iface, *device_iface; + GError *local = NULL; + + if (!nm_connection_verify (connection, &local)) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION, + _("The connection was not valid: %s"), local->message); + g_error_free (local); + return FALSE; + } + + config_iface = nm_connection_get_interface_name (connection); + device_iface = nm_device_get_iface (device); + if (config_iface && g_strcmp0 (config_iface, device_iface) != 0) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + _("The interface names of the device and the connection didn't match.")); + return FALSE; + } + + return TRUE; +} + +/** + * nm_device_connection_compatible: + * @device: an #NMDevice to validate @connection against + * @connection: an #NMConnection to validate against @device + * @error: return location for a #GError, or %NULL + * + * Validates a given connection for a given #NMDevice object and returns + * whether the connection may be activated with the device. For example if + * @device is a Wi-Fi device that supports only WEP encryption, the connection + * will only be valid if it is a Wi-Fi connection which describes a WEP or open + * network, and will not be valid if it describes a WPA network, or if it is + * an Ethernet, Bluetooth, WWAN, etc connection that is incompatible with the + * device. + * + * This function does the same as nm_device_connection_valid(), i.e. checking + * compatibility of the given device and connection. But, in addition, it sets + * GError when FALSE is returned. + * + * Returns: %TRUE if the connection may be activated with this device, %FALSE + * if is incompatible with the device's capabilities and characteristics. + **/ +gboolean +nm_device_connection_compatible (NMDevice *device, NMConnection *connection, GError **error) +{ + g_return_val_if_fail (NM_IS_DEVICE (device), FALSE); + g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + return NM_DEVICE_GET_CLASS (device)->connection_compatible (device, connection, error); +} + +/** + * nm_device_filter_connections: + * @device: an #NMDevice to filter connections for + * @connections: (element-type NMConnection): an array of #NMConnections to filter + * + * Filters a given array of connections for a given #NMDevice object and returns + * connections which may be activated with the device. For example if @device + * is a Wi-Fi device that supports only WEP encryption, the returned array will + * contain any Wi-Fi connections in @connections that allow connection to + * unencrypted or WEP-enabled SSIDs. The returned array will not contain + * Ethernet, Bluetooth, Wi-Fi WPA connections, or any other connection that is + * incompatible with the device. To get the full list of connections see + * nm_client_get_connections(). + * + * Returns: (transfer container) (element-type NMConnection): an array of + * #NMConnections that could be activated with the given @device. The array + * should be freed with g_ptr_array_unref() when it is no longer required. + **/ +GPtrArray * +nm_device_filter_connections (NMDevice *device, const GPtrArray *connections) +{ + GPtrArray *filtered; + int i; + + filtered = g_ptr_array_new_with_free_func (g_object_unref); + for (i = 0; i < connections->len; i++) { + NMConnection *candidate = connections->pdata[i]; + + /* Connection applies to this device */ + if (nm_device_connection_valid (device, candidate)) + g_ptr_array_add (filtered, g_object_ref (candidate)); + } + + return filtered; +} + +/** + * nm_device_get_setting_type: + * @device: an #NMDevice + * + * Gets the (primary) #NMSetting subtype associated with connections + * that can be used on @device. + * + * Returns: @device's associated #NMSetting type + */ +GType +nm_device_get_setting_type (NMDevice *device) +{ + g_return_val_if_fail (NM_IS_DEVICE (device), G_TYPE_INVALID); + g_return_val_if_fail (NM_DEVICE_GET_CLASS (device)->get_setting_type != NULL, G_TYPE_INVALID); + + return NM_DEVICE_GET_CLASS (device)->get_setting_type (device); +} diff --git a/libnm/nm-device.h b/libnm/nm-device.h new file mode 100644 index 00000000..5cc37356 --- /dev/null +++ b/libnm/nm-device.h @@ -0,0 +1,161 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2007 - 2008 Novell, Inc. + * Copyright 2007 - 2013 Red Hat, Inc. + */ + +#ifndef __NM_DEVICE_H__ +#define __NM_DEVICE_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include <nm-object.h> + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE (nm_device_get_type ()) +#define NM_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE, NMDevice)) +#define NM_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE, NMDeviceClass)) +#define NM_IS_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE)) +#define NM_IS_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE)) +#define NM_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE, NMDeviceClass)) + +#define NM_DEVICE_DEVICE_TYPE "device-type" +#define NM_DEVICE_UDI "udi" +#define NM_DEVICE_INTERFACE "interface" +#define NM_DEVICE_IP_INTERFACE "ip-interface" +#define NM_DEVICE_DRIVER "driver" +#define NM_DEVICE_DRIVER_VERSION "driver-version" +#define NM_DEVICE_FIRMWARE_VERSION "firmware-version" +#define NM_DEVICE_CAPABILITIES "capabilities" +#define NM_DEVICE_MANAGED "managed" +#define NM_DEVICE_AUTOCONNECT "autoconnect" +#define NM_DEVICE_FIRMWARE_MISSING "firmware-missing" +#define NM_DEVICE_IP4_CONFIG "ip4-config" +#define NM_DEVICE_DHCP4_CONFIG "dhcp4-config" +#define NM_DEVICE_IP6_CONFIG "ip6-config" +#define NM_DEVICE_DHCP6_CONFIG "dhcp6-config" +#define NM_DEVICE_STATE "state" +#define NM_DEVICE_STATE_REASON "state-reason" +#define NM_DEVICE_ACTIVE_CONNECTION "active-connection" +#define NM_DEVICE_AVAILABLE_CONNECTIONS "available-connections" +#define NM_DEVICE_VENDOR "vendor" +#define NM_DEVICE_PRODUCT "product" +#define NM_DEVICE_PHYSICAL_PORT_ID "physical-port-id" +#define NM_DEVICE_MTU "mtu" + +struct _NMDevice { + NMObject parent; +}; + +typedef struct { + NMObjectClass parent; + + /* Signals */ + void (*state_changed) (NMDevice *device, + NMDeviceState new_state, + NMDeviceState old_state, + NMDeviceStateReason reason); + + /* Methods */ + gboolean (*connection_compatible) (NMDevice *device, + NMConnection *connection, + GError **error); + + const char * (*get_type_description) (NMDevice *device); + const char * (*get_hw_address) (NMDevice *device); + + GType (*get_setting_type) (NMDevice *device); + + /*< private >*/ + gpointer padding[8]; +} NMDeviceClass; + +GType nm_device_get_type (void); + +const char * nm_device_get_iface (NMDevice *device); +const char * nm_device_get_ip_iface (NMDevice *device); +NMDeviceType nm_device_get_device_type (NMDevice *device); +const char * nm_device_get_udi (NMDevice *device); +const char * nm_device_get_driver (NMDevice *device); +const char * nm_device_get_driver_version (NMDevice *device); +const char * nm_device_get_firmware_version (NMDevice *device); +const char * nm_device_get_type_description (NMDevice *device); +const char * nm_device_get_hw_address (NMDevice *device); +NMDeviceCapabilities nm_device_get_capabilities (NMDevice *device); +gboolean nm_device_get_managed (NMDevice *device); +gboolean nm_device_get_autoconnect (NMDevice *device); +void nm_device_set_autoconnect (NMDevice *device, gboolean autoconnect); +gboolean nm_device_get_firmware_missing (NMDevice *device); +NMIPConfig * nm_device_get_ip4_config (NMDevice *device); +NMDhcpConfig * nm_device_get_dhcp4_config (NMDevice *device); +NMIPConfig * nm_device_get_ip6_config (NMDevice *device); +NMDhcpConfig * nm_device_get_dhcp6_config (NMDevice *device); +NMDeviceState nm_device_get_state (NMDevice *device); +NMDeviceStateReason nm_device_get_state_reason (NMDevice *device); +NMActiveConnection * nm_device_get_active_connection(NMDevice *device); +const GPtrArray * nm_device_get_available_connections(NMDevice *device); +const char * nm_device_get_physical_port_id (NMDevice *device); +guint32 nm_device_get_mtu (NMDevice *device); +gboolean nm_device_is_software (NMDevice *device); + +const char * nm_device_get_product (NMDevice *device); +const char * nm_device_get_vendor (NMDevice *device); +const char * nm_device_get_description (NMDevice *device); +char ** nm_device_disambiguate_names (NMDevice **devices, + int num_devices); + +gboolean nm_device_disconnect (NMDevice *device, + GCancellable *cancellable, + GError **error); +void nm_device_disconnect_async (NMDevice *device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean nm_device_disconnect_finish (NMDevice *device, + GAsyncResult *result, + GError **error); + +gboolean nm_device_delete (NMDevice *device, + GCancellable *cancellable, + GError **error); +void nm_device_delete_async (NMDevice *device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean nm_device_delete_finish (NMDevice *device, + GAsyncResult *result, + GError **error); + +GPtrArray * nm_device_filter_connections (NMDevice *device, + const GPtrArray *connections); + +gboolean nm_device_connection_valid (NMDevice *device, + NMConnection *connection); + +gboolean nm_device_connection_compatible (NMDevice *device, + NMConnection *connection, + GError **error); + +GType nm_device_get_setting_type (NMDevice *device); + +G_END_DECLS + +#endif /* __NM_DEVICE_H__ */ diff --git a/libnm/nm-dhcp-config.c b/libnm/nm-dhcp-config.c new file mode 100644 index 00000000..7227abac --- /dev/null +++ b/libnm/nm-dhcp-config.c @@ -0,0 +1,222 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2008 - 2014 Red Hat, Inc. + * Copyright 2008 Novell, Inc. + */ + +#include "config.h" + +#include <string.h> + +#include "nm-dhcp-config.h" +#include "nm-dhcp4-config.h" +#include "nm-dhcp6-config.h" +#include "nm-dbus-interface.h" +#include "nm-object-private.h" +#include "nm-utils.h" + +G_DEFINE_ABSTRACT_TYPE (NMDhcpConfig, nm_dhcp_config, NM_TYPE_OBJECT) + +#define NM_DHCP_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DHCP_CONFIG, NMDhcpConfigPrivate)) + +typedef struct { + GHashTable *options; +} NMDhcpConfigPrivate; + +enum { + PROP_0, + PROP_FAMILY, + PROP_OPTIONS, + + LAST_PROP +}; + +static void +nm_dhcp_config_init (NMDhcpConfig *config) +{ + NMDhcpConfigPrivate *priv = NM_DHCP_CONFIG_GET_PRIVATE (config); + + priv->options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); +} + +static gboolean +demarshal_dhcp_options (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field) +{ + NMDhcpConfigPrivate *priv = NM_DHCP_CONFIG_GET_PRIVATE (object); + GVariantIter iter; + const char *key; + GVariant *opt; + + g_hash_table_remove_all (priv->options); + + g_variant_iter_init (&iter, value); + while (g_variant_iter_next (&iter, "{&sv}", &key, &opt)) { + g_hash_table_insert (priv->options, g_strdup (key), g_variant_dup_string (opt, NULL)); + g_variant_unref (opt); + } + + _nm_object_queue_notify (object, NM_DHCP_CONFIG_OPTIONS); + return TRUE; +} + +static void +init_dbus (NMObject *object) +{ + NMDhcpConfigPrivate *priv = NM_DHCP_CONFIG_GET_PRIVATE (object); + const NMPropertiesInfo property_info[] = { + { NM_DHCP_CONFIG_OPTIONS, &priv->options, demarshal_dhcp_options }, + { NULL }, + }; + + NM_OBJECT_CLASS (nm_dhcp_config_parent_class)->init_dbus (object); + + _nm_object_register_properties (object, + (NM_IS_DHCP4_CONFIG (object) ? + NM_DBUS_INTERFACE_DHCP4_CONFIG : + NM_DBUS_INTERFACE_DHCP6_CONFIG), + property_info); +} + +static void +finalize (GObject *object) +{ + NMDhcpConfigPrivate *priv = NM_DHCP_CONFIG_GET_PRIVATE (object); + + if (priv->options) + g_hash_table_destroy (priv->options); + + G_OBJECT_CLASS (nm_dhcp_config_parent_class)->finalize (object); +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMDhcpConfig *self = NM_DHCP_CONFIG (object); + + switch (prop_id) { + case PROP_FAMILY: + g_value_set_int (value, nm_dhcp_config_get_family (self)); + break; + case PROP_OPTIONS: + g_value_set_boxed (value, nm_dhcp_config_get_options (self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_dhcp_config_class_init (NMDhcpConfigClass *config_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (config_class); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (config_class); + + g_type_class_add_private (config_class, sizeof (NMDhcpConfigPrivate)); + + /* virtual methods */ + object_class->get_property = get_property; + object_class->finalize = finalize; + + nm_object_class->init_dbus = init_dbus; + + /* properties */ + + /** + * NMDhcpConfig:family: + * + * The IP address family of the configuration; either + * <literal>AF_INET</literal> or <literal>AF_INET6</literal>. + **/ + g_object_class_install_property + (object_class, PROP_FAMILY, + g_param_spec_int (NM_DHCP_CONFIG_FAMILY, "", "", + 0, 255, AF_UNSPEC, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDhcpConfig:options: + * + * The #GHashTable containing options of the configuration. + * + * Type: GLib.HashTable(utf8,utf8) + **/ + g_object_class_install_property + (object_class, PROP_OPTIONS, + g_param_spec_boxed (NM_DHCP_CONFIG_OPTIONS, "", "", + G_TYPE_HASH_TABLE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); +} + +/** + * nm_dhcp_config_get_family: + * @config: a #NMDhcpConfig + * + * Gets the IP address family of the configuration + * + * Returns: the IP address family; either <literal>AF_INET</literal> or + * <literal>AF_INET6</literal> + **/ +int +nm_dhcp_config_get_family (NMDhcpConfig *config) +{ + g_return_val_if_fail (NM_IS_DHCP_CONFIG (config), AF_UNSPEC); + + return NM_IS_DHCP4_CONFIG (config) ? AF_INET : AF_INET6; +} + +/** + * nm_dhcp_config_get_options: + * @config: a #NMDhcpConfig + * + * Gets all the options contained in the configuration. + * + * Returns: (transfer none) (element-type utf8 utf8): the #GHashTable containing + * strings for keys and values. This is the internal copy used by the + * configuration, and must not be modified. + **/ +GHashTable * +nm_dhcp_config_get_options (NMDhcpConfig *config) +{ + g_return_val_if_fail (NM_IS_DHCP_CONFIG (config), NULL); + + return NM_DHCP_CONFIG_GET_PRIVATE (config)->options; +} + +/** + * nm_dhcp_config_get_one_option: + * @config: a #NMDhcpConfig + * @option: the option to retrieve + * + * Gets one option by option name. + * + * Returns: the configuration option's value. This is the internal string used by the + * configuration, and must not be modified. + **/ +const char * +nm_dhcp_config_get_one_option (NMDhcpConfig *config, const char *option) +{ + g_return_val_if_fail (NM_IS_DHCP_CONFIG (config), NULL); + + return g_hash_table_lookup (nm_dhcp_config_get_options (config), option); +} diff --git a/libnm/nm-dhcp-config.h b/libnm/nm-dhcp-config.h new file mode 100644 index 00000000..85aa3bd2 --- /dev/null +++ b/libnm/nm-dhcp-config.h @@ -0,0 +1,62 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2008 Red Hat, Inc. + * Copyright 2008 Novell, Inc. + */ + +#ifndef __NM_DHCP_CONFIG_H__ +#define __NM_DHCP_CONFIG_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include <nm-object.h> + +G_BEGIN_DECLS + +#define NM_TYPE_DHCP_CONFIG (nm_dhcp_config_get_type ()) +#define NM_DHCP_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DHCP_CONFIG, NMDhcpConfig)) +#define NM_DHCP_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DHCP_CONFIG, NMDhcpConfigClass)) +#define NM_IS_DHCP_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DHCP_CONFIG)) +#define NM_IS_DHCP_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DHCP_CONFIG)) + +struct _NMDhcpConfig { + NMObject parent; +}; + +typedef struct { + NMObjectClass parent; + + /*< private >*/ + gpointer padding[8]; +} NMDhcpConfigClass; + +#define NM_DHCP_CONFIG_FAMILY "family" +#define NM_DHCP_CONFIG_OPTIONS "options" + +GType nm_dhcp_config_get_type (void); + +int nm_dhcp_config_get_family (NMDhcpConfig *config); + +GHashTable *nm_dhcp_config_get_options (NMDhcpConfig *config); +const char *nm_dhcp_config_get_one_option (NMDhcpConfig *config, const char *option); + +G_END_DECLS + +#endif /* __NM_DHCP_CONFIG_H__ */ diff --git a/libnm/nm-dhcp4-config.c b/libnm/nm-dhcp4-config.c new file mode 100644 index 00000000..808edaa6 --- /dev/null +++ b/libnm/nm-dhcp4-config.c @@ -0,0 +1,39 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2014 Red Hat, Inc. + */ + +#include "config.h" + +#include "nm-dhcp4-config.h" +#include "nm-object-private.h" + +G_DEFINE_TYPE (NMDhcp4Config, nm_dhcp4_config, NM_TYPE_DHCP_CONFIG) + +static void +nm_dhcp4_config_init (NMDhcp4Config *config) +{ +} + +static void +nm_dhcp4_config_class_init (NMDhcp4ConfigClass *config_class) +{ + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (config_class); + + _nm_object_class_add_interface (nm_object_class, NM_DBUS_INTERFACE_DHCP4_CONFIG); +} diff --git a/libnm/nm-dhcp4-config.h b/libnm/nm-dhcp4-config.h new file mode 100644 index 00000000..3423740d --- /dev/null +++ b/libnm/nm-dhcp4-config.h @@ -0,0 +1,49 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2014 Red Hat, Inc. + */ + +#ifndef __NM_DHCP4_CONFIG_H__ +#define __NM_DHCP4_CONFIG_H__ + +#include <nm-dhcp-config.h> + +G_BEGIN_DECLS + +#define NM_TYPE_DHCP4_CONFIG (nm_dhcp4_config_get_type ()) +#define NM_DHCP4_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DHCP4_CONFIG, NMDhcp4Config)) +#define NM_DHCP4_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DHCP4_CONFIG, NMDhcp4ConfigClass)) +#define NM_IS_DHCP4_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DHCP4_CONFIG)) +#define NM_IS_DHCP4_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DHCP4_CONFIG)) + +typedef struct { + NMDhcpConfig parent; +} NMDhcp4Config; + +typedef struct { + NMDhcpConfigClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMDhcp4ConfigClass; + +GType nm_dhcp4_config_get_type (void); + +G_END_DECLS + +#endif /* __NM_DHCP4_CONFIG_H__ */ diff --git a/libnm/nm-dhcp6-config.c b/libnm/nm-dhcp6-config.c new file mode 100644 index 00000000..0bd924c4 --- /dev/null +++ b/libnm/nm-dhcp6-config.c @@ -0,0 +1,39 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2014 Red Hat, Inc. + */ + +#include "config.h" + +#include "nm-dhcp6-config.h" +#include "nm-object-private.h" + +G_DEFINE_TYPE (NMDhcp6Config, nm_dhcp6_config, NM_TYPE_OBJECT) + +static void +nm_dhcp6_config_init (NMDhcp6Config *config) +{ +} + +static void +nm_dhcp6_config_class_init (NMDhcp6ConfigClass *config_class) +{ + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (config_class); + + _nm_object_class_add_interface (nm_object_class, NM_DBUS_INTERFACE_DHCP6_CONFIG); +} diff --git a/libnm/nm-dhcp6-config.h b/libnm/nm-dhcp6-config.h new file mode 100644 index 00000000..abb24adf --- /dev/null +++ b/libnm/nm-dhcp6-config.h @@ -0,0 +1,49 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2014 Red Hat, Inc. + */ + +#ifndef __NM_DHCP6_CONFIG_H__ +#define __NM_DHCP6_CONFIG_H__ + +#include <nm-dhcp-config.h> + +G_BEGIN_DECLS + +#define NM_TYPE_DHCP6_CONFIG (nm_dhcp6_config_get_type ()) +#define NM_DHCP6_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DHCP6_CONFIG, NMDhcp6Config)) +#define NM_DHCP6_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DHCP6_CONFIG, NMDhcp6ConfigClass)) +#define NM_IS_DHCP6_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DHCP6_CONFIG)) +#define NM_IS_DHCP6_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DHCP6_CONFIG)) + +typedef struct { + NMDhcpConfig parent; +} NMDhcp6Config; + +typedef struct { + NMDhcpConfigClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMDhcp6ConfigClass; + +GType nm_dhcp6_config_get_type (void); + +G_END_DECLS + +#endif /* __NM_DHCP6_CONFIG_H__ */ diff --git a/libnm/nm-enum-types.c b/libnm/nm-enum-types.c new file mode 100644 index 00000000..1e5dcb0d --- /dev/null +++ b/libnm/nm-enum-types.c @@ -0,0 +1,152 @@ + + + +/* Generated by glib-mkenums. Do not edit */ + +#include "nm-enum-types.h" + +#include "NetworkManager.h" +#include "nm-access-point.h" +#include "nm-active-connection.h" +#include "nm-client.h" +#include "nm-device-adsl.h" +#include "nm-device-bond.h" +#include "nm-device-bridge.h" +#include "nm-device-bt.h" +#include "nm-device-ethernet.h" +#include "nm-device-generic.h" +#include "nm-device-infiniband.h" +#include "nm-device-modem.h" +#include "nm-device-olpc-mesh.h" +#include "nm-device-team.h" +#include "nm-device-vlan.h" +#include "nm-device-wifi.h" +#include "nm-device-wimax.h" +#include "nm-device.h" +#include "nm-dhcp-config.h" +#include "nm-ip-config.h" +#include "nm-object.h" +#include "nm-remote-connection.h" +#include "nm-types.h" +#include "nm-vpn-connection.h" +#include "nm-vpn-editor-plugin.h" +#include "nm-wimax-nsp.h" +#include "nm-secret-agent-old.h" +#include "nm-vpn-plugin-old.h" + +GType +nm_client_permission_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_CLIENT_PERMISSION_NONE, "NM_CLIENT_PERMISSION_NONE", "none" }, + { NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK, "NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK", "enable-disable-network" }, + { NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI, "NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI", "enable-disable-wifi" }, + { NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN, "NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN", "enable-disable-wwan" }, + { NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX, "NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX", "enable-disable-wimax" }, + { NM_CLIENT_PERMISSION_SLEEP_WAKE, "NM_CLIENT_PERMISSION_SLEEP_WAKE", "sleep-wake" }, + { NM_CLIENT_PERMISSION_NETWORK_CONTROL, "NM_CLIENT_PERMISSION_NETWORK_CONTROL", "network-control" }, + { NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED, "NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED", "wifi-share-protected" }, + { NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN, "NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN", "wifi-share-open" }, + { NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM, "NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM", "settings-modify-system" }, + { NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN, "NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN", "settings-modify-own" }, + { NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME, "NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME", "settings-modify-hostname" }, + { NM_CLIENT_PERMISSION_LAST, "NM_CLIENT_PERMISSION_LAST", "last" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMClientPermission"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_client_permission_result_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_CLIENT_PERMISSION_RESULT_UNKNOWN, "NM_CLIENT_PERMISSION_RESULT_UNKNOWN", "unknown" }, + { NM_CLIENT_PERMISSION_RESULT_YES, "NM_CLIENT_PERMISSION_RESULT_YES", "yes" }, + { NM_CLIENT_PERMISSION_RESULT_AUTH, "NM_CLIENT_PERMISSION_RESULT_AUTH", "auth" }, + { NM_CLIENT_PERMISSION_RESULT_NO, "NM_CLIENT_PERMISSION_RESULT_NO", "no" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMClientPermissionResult"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_client_error_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_CLIENT_ERROR_FAILED, "NM_CLIENT_ERROR_FAILED", "failed" }, + { NM_CLIENT_ERROR_MANAGER_NOT_RUNNING, "NM_CLIENT_ERROR_MANAGER_NOT_RUNNING", "manager-not-running" }, + { NM_CLIENT_ERROR_OBJECT_CREATION_FAILED, "NM_CLIENT_ERROR_OBJECT_CREATION_FAILED", "object-creation-failed" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMClientError"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_vpn_editor_plugin_capability_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GFlagsValue values[] = { + { NM_VPN_EDITOR_PLUGIN_CAPABILITY_NONE, "NM_VPN_EDITOR_PLUGIN_CAPABILITY_NONE", "none" }, + { NM_VPN_EDITOR_PLUGIN_CAPABILITY_IMPORT, "NM_VPN_EDITOR_PLUGIN_CAPABILITY_IMPORT", "import" }, + { NM_VPN_EDITOR_PLUGIN_CAPABILITY_EXPORT, "NM_VPN_EDITOR_PLUGIN_CAPABILITY_EXPORT", "export" }, + { NM_VPN_EDITOR_PLUGIN_CAPABILITY_IPV6, "NM_VPN_EDITOR_PLUGIN_CAPABILITY_IPV6", "ipv6" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_flags_register_static (g_intern_static_string ("NMVpnEditorPluginCapability"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType +nm_wimax_nsp_network_type_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN, "NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN", "unknown" }, + { NM_WIMAX_NSP_NETWORK_TYPE_HOME, "NM_WIMAX_NSP_NETWORK_TYPE_HOME", "home" }, + { NM_WIMAX_NSP_NETWORK_TYPE_PARTNER, "NM_WIMAX_NSP_NETWORK_TYPE_PARTNER", "partner" }, + { NM_WIMAX_NSP_NETWORK_TYPE_ROAMING_PARTNER, "NM_WIMAX_NSP_NETWORK_TYPE_ROAMING_PARTNER", "roaming-partner" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMWimaxNspNetworkType"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} + + + diff --git a/libnm/nm-enum-types.h b/libnm/nm-enum-types.h new file mode 100644 index 00000000..1db04ab8 --- /dev/null +++ b/libnm/nm-enum-types.h @@ -0,0 +1,28 @@ + + + +/* Generated by glib-mkenums. Do not edit */ + +#ifndef __NM_ENUM_TYPES_H__ +#define __NM_ENUM_TYPES_H__ + +#include <nm-core-enum-types.h> +#include <glib-object.h> + +G_BEGIN_DECLS +GType nm_client_permission_get_type (void) G_GNUC_CONST; +#define NM_TYPE_CLIENT_PERMISSION (nm_client_permission_get_type ()) +GType nm_client_permission_result_get_type (void) G_GNUC_CONST; +#define NM_TYPE_CLIENT_PERMISSION_RESULT (nm_client_permission_result_get_type ()) +GType nm_client_error_get_type (void) G_GNUC_CONST; +#define NM_TYPE_CLIENT_ERROR (nm_client_error_get_type ()) +GType nm_vpn_editor_plugin_capability_get_type (void) G_GNUC_CONST; +#define NM_TYPE_VPN_EDITOR_PLUGIN_CAPABILITY (nm_vpn_editor_plugin_capability_get_type ()) +GType nm_wimax_nsp_network_type_get_type (void) G_GNUC_CONST; +#define NM_TYPE_WIMAX_NSP_NETWORK_TYPE (nm_wimax_nsp_network_type_get_type ()) +G_END_DECLS + +#endif /* __NM_ENUM_TYPES_H__ */ + + + diff --git a/libnm/nm-ifcfg-rh-docs.xml b/libnm/nm-ifcfg-rh-docs.xml new file mode 100644 index 00000000..96ecfde8 --- /dev/null +++ b/libnm/nm-ifcfg-rh-docs.xml @@ -0,0 +1,263 @@ +<?xml version="1.0"?> +<!DOCTYPE nm-ifcfg-rh-docs [ +]> + +<nm-ifcfg-rh-docs> + <setting name="802-1x"> +<property name="eap" variable="IEEE_8021X_EAP_METHODS(+)" format="" values=""LEAP", "PWD", "TLS", "PEAP", "TTLS", "FAST"" default="" example="IEEE_8021X_EAP_METHODS=PEAP" description="EAP method for 802.1X authentication."/> +<property name="identity" variable="IEEE_8021X_IDENTITY(+)" format="" values="" default="" example="IEEE_8021X_IDENTITY=itsme" description="Identity for EAP authentication methods."/> +<property name="anonymous-identity" variable="IEEE_8021X_ANON_IDENTITY(+)" format="" values="" default="" example="" description="Anonymous identity for EAP authentication methods."/> +<property name="pac-file" variable="IEEE_8021X_PAC_FILE(+)" format="" values="" default="" example="IEEE_8021X_PAC_FILE=/home/joe/my-fast.pac" description="File with PAC (Protected Access Credential) for EAP-FAST."/> +<property name="ca-cert" variable="IEEE_8021X_CA_CERT(+)" format="" values="" default="" example="IEEE_8021X_CA_CERT=/home/joe/cacert.crt" description="CA certificate for EAP."/> +<property name="ca-path" variable="(none)" format="" values="" default="" example="" description="The property is not handled by ifcfg-rh plugin."/> +<property name="subject-match" variable="IEEE_8021X_SUBJECT_MATCH(+)" format="" values="" default="" example="IEEE_8021X_SUBJECT_MATCH="Red Hat"" description="Substring to match subject of server certificate against."/> +<property name="altubject-matches" variable="IEEE_8021X_AlTSUBJECT_MATCHES(+)" format="" values="" default="" example="IEEE_8021X_ALTSUBJECT_MATCHES="s1.domain.cc"" description="List of strings to be matched against the altSubjectName."/> +<property name="client-cert" variable="IEEE_8021X_CLIENT_CERT(+)" format="" values="" default="" example="IEEE_8021X_CLIENT_CERT=/home/joe/mycert.crt" description="Client certificate for EAP."/> +<property name="phase1-peapver" variable="IEEE_8021X_PEAP_VERSION(+)" format="" values="0, 1" default="" example="" description="Use to force a specific PEAP version."/> +<property name="phase1-peaplabel" variable="IEEE_8021X_PEAP_FORCE_NEW_LABEL(+)" format="" values="yes, no" default="no" example="" description="Use to force the new PEAP label during key derivation."/> +<property name="phase1-fast-provisioning" variable="IEEE_8021X_FAST_PROVISIONING(+)" format="" values="space-separated list of these values [allow-auth, allow-unauth]" default="" example="IEEE_8021X_FAST_PROVISIONING="allow-auth allow-unauth"" description="Enable in-line provisioning of EAP-FAST credentials."/> +<property name="phase2-auth" variable="IEEE_8021X_INNER_AUTH_METHODS(+)" format="" values=""PAP", "CHAP", "MSCHAP", "MSCHAPV2", "GTC", "OTP", "MD5" and "TLS"" default="" example="IEEE_8021X_INNER_AUTH_METHODS=PAP" description="Inner non-EAP authentication methods. IEEE_8021X_INNER_AUTH_METHODS +can contain values both for 'phase2-auth' and 'phase2-autheap' properties."/> +<property name="phase2-autheap" variable="IEEE_8021X_INNER_AUTH_METHODS(+)" format="" values=""EAP-MD5", "EAP-MSCHAPV2", "EAP-GTC", "EAP-OTP" and "EAP-TLS"" default="" example="IEEE_8021X_INNER_AUTH_METHODS="MSCHAPV2 EAP-TLS"" description="Inner EAP-based authentication methods. Note that +IEEE_8021X_INNER_AUTH_METHODS is also used for 'phase2-auth' values."/> +<property name="phase2-subject-match" variable="IEEE_8021X_PHASE2_SUBJECT_MATCH(+)" format="" values="" default="" example="IEEE_8021X_PHASE2_SUBJECT_MATCH="Red Hat"" description="Substring to match subject of server certificate against."/> +<property name="phase2-altsubject-matches" variable="IEEE_8021X_PHASE2_ALTSUBJECT_MATCHES(+)" format="" values="" default="" example="" description=""/> +<property name="phase2-client-cert" variable="IEEE_8021X_INNER_CLIENT_CERT(+)" format="" values="" default="" example="IEEE_8021X_INNER_CLIENT_CERT=/home/joe/mycert.crt" description="Client certificate for inner EAP method."/> +<property name="password" variable="IEEE_8021X_PASSWORD(+)" format="" values="" default="" example="" description="UTF-8 encoded password used for EAP. It can also go to "key-" +lookaside file, or it can be owned by a secret agent."/> +<property name="password-flags" variable="IEEE_8021X_PASSWORD_FLAGS(+)" format="NMSettingSecretFlags" values="" default="" example="" description="Password flags for IEEE_8021X_PASSWORD password."/> +<property name="password-raw" variable="(none)" format="" values="" default="" example="" description="The property is not handled by ifcfg-rh plugin."/> +<property name="password-raw-flags" variable="(none)" format="" values="" default="" example="" description="The property is not handled by ifcfg-rh plugin."/> +<property name="private-key" variable="IEEE_8021X_PRIVATE_KEY(+)" format="" values="" default="" example="IEEE_8021X_PRIVATE_KEY=/home/joe/mykey.p12" description="Private key for EAP-TLS."/> +<property name="private-key-password" variable="IEEE_8021X_PRIVATE_KEY_PASSWORD(+)" format="" values="" default="" example="" description="Password for IEEE_8021X_PRIVATE_KEY. It can also go to "key-" +lookaside file, or it can be owned by a secret agent."/> +<property name="private-key-password-flags" variable="IEEE_8021X_PRIVATE_KEY_PASSWORD_FLAGS(+)" format="NMSettingSecretFlags" values="" default="" example="" description="Password flags for IEEE_8021X_PRIVATE_KEY_PASSWORD password."/> +<property name="phase2-private-key" variable="IEEE_8021X_INNER_PRIVATE_KEY(+)" format="" values="" default="" example="" description="Private key for inner authentication method for EAP-TLS."/> +<property name="phase2-private-key-password" variable="IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD(+)" format="" values="" default="" example="" description="Password for IEEE_8021X_INNER_PRIVATE_KEY. It can also go to "key-" +lookaside file, or it can be owned by a secret agent."/> +<property name="phase2-private-key-password-flags" variable="IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD_FLAGS(+)" format="NMSettingSecretFlags" values="" default="" example="" description="Password flags for IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD password."/> +<property name="pin" variable="(none)" format="" values="" default="" example="" description="The property is not handled by ifcfg-rh plugin."/> +<property name="pin-flags" variable="(none)" format="" values="" default="" example="" description="The property is not handled by ifcfg-rh plugin."/> +<property name="system-ca-certs" variable="(none)" format="" values="" default="" example="" description="The property is not handled by ifcfg-rh plugin."/> +</setting> +<setting name="adsl"> +</setting> +<setting name="bluetooth"> +</setting> +<setting name="bond"> +<property name="options" variable="BONDING_OPTS" format="" values="" default="" example="BONDING_OPTS="miimon=100 mode=broadcast"" description="Bonding options."/> +</setting> +<setting name="bridge-port"> +<property name="priority" variable="BRIDGING_OPTS: priority=" format="" values="0 - 63" default="32" example="" description="STP priority."/> +<property name="path-cost" variable="BRIDGING_OPTS: path_cost=" format="" values="1 - 65535" default="100" example="" description="STP cost."/> +<property name="hairpin-mode" variable="BRIDGING_OPTS: hairpin_mode=" format="" values="" default="yes" example="" description="Hairpin mode of the bridge port."/> +</setting> +<setting name="bridge"> +<property name="mac-address" variable="MACADDR(+)" format="" values="" default="" example="" description="MAC address of the bridge. Note that this requires a recent +kernel support, originally introduced in 3.15 upstream kernel) +MACADDR for bridges is an NM extension."/> +<property name="stp" variable="STP" format="" values="" default="no" example="" description="Span tree protocol participation."/> +<property name="priority" variable="BRIDGING_OPTS: priority=" format="" values="0 - 32768" default="32768" example="" description="STP priority."/> +<property name="forward-delay" variable="DELAY" format="" values="2 - 30" default="15" example="" description="STP forwarding delay."/> +<property name="hello-time" variable="BRIDGING_OPTS: hello_time=" format="" values="1 - 10" default="2" example="" description="STP hello time."/> +<property name="max-age" variable="BRIDGING_OPTS: max_age=" format="" values="6 - 40" default="20" example="" description="STP maximum message age."/> +<property name="ageing-time" variable="BRIDGING_OPTS: ageing_time=" format="" values="0 - 1000000" default="300" example="" description="Ethernet MAC ageing time."/> +</setting> +<setting name="cdma"> +</setting> +<setting name="connection"> +<property name="id" variable="NAME(+)" format="" values="" default="" example="" description="User friendly name for the connection profile."/> +<property name="uuid" variable="UUID(+)" format="" values="" default="" example="" description="UUID for the connection profile. When missing, NetworkManager +creates the UUID itself (by hashing the file)."/> +<property name="interface-name" variable="DEVICE" format="" values="" default="" example="" description="Interface name of the device this profile is bound to. The variable +can be left out when the profile should apply for more devices. Note that DEVICE +can be required for some connection types."/> +<property name="type" variable="TYPE (DEVICETYPE, DEVICE)" format="" values="Ethernet, Wireless, InfiniBand, Bridge, Bond, Vlan, Team, TeamPort" default="" example="TYPE=Ethernet; TYPE=Bond; TYPE=Bridge; DEVICETYPE=TeamPort" description="Base type of the connection. DEVICETYPE is used for teaming +connections."/> +<property name="permissions" variable="USERS(+)" format="" values="" default="" example="USERS="joe bob"" description="USERS restrict the access for this conenction to certain +users only."/> +<property name="autoconnect" variable="ONBOOT" format="" values="" default="yes" example="" description="Whether the connection should be autoconnected (not only while booting)."/> +<property name="autoconnect-priority" variable="AUTOCONNECT_PRIORITY(+)" format="" values="-999 to 999" default="0" example="AUTOCONNECT_PRIORITY=20" description="Connection priority for automatic activation. Connections with +higher numbers are preferred when selecting profiles for automatic activation."/> +<property name="zone" variable="ZONE(+)" format="" values="" default="" example="ZONE=Work" description="Trust level of this connection. The string is usually used +for a firewall."/> +<property name="master" variable="MASTER, TEAM_MASTER, BRIDGE" format="" values="" default="" example="" description="Reference to master connection. The variable used depends on +the connection type."/> +<property name="slave-type" variable="MASTER, TEAM_MASTER, DEVICETYPE, BRIDGE" format="" values="" default="" example="" description="Slave type doesn't map directly to a variable, but it is +recognized using different variables. MASTER for bonding, +TEAM_MASTER and DEVICETYPE for teaming, BRIDGE for bridging."/> +<property name="secondaries" variable="SECONDARY_UUIDS(+)" format="" values="" default="" example="" description="UUID of VPN connections that should be activated +together with this connection."/> +<property name="gateway-ping-timeout" variable="GATEWAY_PING_TIMEOUT(+)" format="" values="" default="0" example="GATEWAY_PING_TIMEOUT=5" description="If greater than zero, the IP connectivity will be checked by +pinging the gateway and waiting for the specified timeout (in seconds)."/> +</setting> +<setting name="dcb"> +<property name="app-fcoe-flags" variable="DCB_APP_FCOE_ENABLE, DCB_APP_FCOE_ADVERTISE, DCB_APP_FCOE_WILLING" format="" values="" default="no" example="DCB_APP_FCOE_ENABLE=yes DCB_APP_FCOE_ADVERTISE=yes" description="FCOE flags."/> +<property name="app-fcoe-priority" variable="DCB_APP_FCOE_PRIORITY" format="" values="0 - 7" default="" example="" description="Priority of FCoE frames."/> +<property name="app-fcoe-mode" variable="DCB_APP_FCOE_MODE" format="" values="fabric, vn2vn" default="fabric" example="" description="FCoE controller mode."/> +<property name="app-iscsi-flags" variable="DCB_APP_ISCSI_ENABLE, DCB_APP_ISCSI_ADVERTISE, DCB_APP_ISCSI_WILLING" format="" values="" default="no" example="" description="iSCSI flags."/> +<property name="app-iscsi-priority" variable="DCB_APP_ISCSI_PRIORITY" format="" values="0 - 7" default="" example="" description="Priority of iSCSI frames."/> +<property name="app-fip-flags" variable="DCB_APP_FIP_ENABLE, DCB_APP_FIP_ADVERTISE, DCB_APP_FIP_WILLING" format="" values="" default="no" example="" description="FIP flags."/> +<property name="app-fip-priority" variable="DCB_APP_FIP_PRIORITY" format="" values="0 - 7" default="" example="" description="Priority of FIP frames."/> +<property name="priority-flow-control-flags" variable="DCB_PFC_ENABLE, DCB_PFC_ADVERTISE, DCB_PFC_WILLING" format="" values="" default="no" example="" description="Priority flow control flags."/> +<property name="priority-flow-control" variable="DCB_PFC_UP" format="" values="" default="" example="DCB_PFC_UP=01101110" description="Priority flow control values. String of 8 "0" and "1", where "0". +means "do not transmit priority pause", "1" means "transmit pause"."/> +<property name="priority-group-flags" variable="DCB_PG_ENABLE, DCB_PG_ADVERTISE, DCB_PG_WILLING" format="" values="" default="no" example="" description="Priority groups flags."/> +<property name="priority-group-id" variable="DCB_PG_ID" format="" values="" default="" example="DCB_PG_ID=1205f173" description="Priority groups values. String of eight priorities (0 - 7) or "f" +(unrestricted)."/> +<property name="priority-group-bandwidth" variable="DCB_PG_PCT" format="" values="" default="" example="DCB_PG_PCT=10,5,10,15,10,10,10,30" description="Priority groups values. Eight bandwidths (in percent), separated with commas."/> +<property name="priority-bandwidth" variable="DCB_PG_UPPCT" format="" values="" default="" example="DCB_PG_UPPCT=7,13,10,10,15,15,10,20" description="Priority values. Eight bandwidths (in percent), separated with commas. +The sum of the numbers must be 100."/> +<property name="priority-strict-bandwidth" variable="DCB_PG_STRICT" format="" values="" default="" example="DCB_PG_STRICT=01101110" description="Priority values. String of eight "0" or "1", where "0" means +"may not utilize all bandwidth", "1" means "may utilize all bandwidth"."/> +<property name="priority-traffic-class" variable="DCB_PG_UP2TC" format="" values="" default="" example="DCB_PG_UP2TC=01623701" description="Priority values. String of eight trafic class values (0 - 7)."/> +</setting> +<setting name="generic"> +</setting> +<setting name="gsm"> +</setting> +<setting name="infiniband"> +<property name="mac-address" variable="HWADDR" format="" values="" default="" example="HWADDR=01:02:03:04:05:06:07:08:09:0A:01:02:03:04:05:06:07:08:09:11" description="IBoIP 20-byte hardware address of the device (in traditional +hex-digits-and-colons notation)."/> +<property name="mtu" variable="MTU" format="" values="" default="" example="" description="MTU of the interface."/> +<property name="transport-mode" variable="CONNECTED_MODE" format="" values="" default="CONNECTED_MODE=no" example="" description="CONNECTED_MODE=yes for "connected" mode, CONNECTED_MODE=no for +"datagram" mode"/> +<property name="p-key" variable="PKEY_ID (and PKEY=yes)" format="" values="" default="PKEY=no" example="PKEY=yes PKEY_ID=2 PHYSDEV=mlx4_ib0 DEVICE=mlx4_ib0.8002" description="InfiniBand P_Key. The value can be a hex number prefixed with "0x" +or a decimal number. +When PKEY_ID is specified, PHYSDEV and DEVICE also must be specified."/> +<property name="parent" variable="PHYSDEV (PKEY=yes)" format="" values="" default="PKEY=no" example="PHYSDEV=ib0" description="InfiniBand parent device."/> +</setting> +<setting name=""> +</setting> +<setting name="ipv4"> +<property name="method" variable="BOOTPROTO" format="string" values="none, dhcp (bootp), static, ibft, autoip, shared" default="none" example="" description="Method used for IPv4 protocol configuration."/> +<property name="dns" variable="DNS1, DNS2, ..." format="string" values="" default="" example="DNS1=1.2.3.4 DNS2=10.0.0.254 DNS3=8.8.8.8" description="List of DNS servers. Even if NetworkManager supports many DNS +servers, initscripts and resolver only care about the first three, usually."/> +<property name="dns-search" variable="DOMAIN" format="string (space-separated domains)" values="" default="" example="" description="List of DNS search domains."/> +<property name="addresses" variable="IPADDR, PREFIX, IPADDR1, PREFIX1, ..." format="" values="" default="" example="IPADDR=10.5.5.23 PREFIX=24 IPADDR1=1.1.1.2 PREFIX1=16" description="List of static IP addresses."/> +<property name="gateway" variable="GATEWAY" format="" values="" default="" example="GATEWAY=10.5.5.1" description="Gateway IP address."/> +<property name="routes" variable="ADDRESS1, NETMASK1, GATEWAY1, METRIC1, ..." format="" values="" default="" example="" description="List of static routes. They are not stored in ifcfg-* file, +but in route-* file instead."/> +<property name="ignore-auto-routes" variable="PEERROUTES(+)" format="" values="" default="yes" example="" description="PEERROUTES has the opposite meaning as 'ignore-auto-routes' property."/> +<property name="ignore-auto-dns" variable="PEERDNS" format="" values="" default="yes" example="" description="PEERDNS has the opposite meaning as 'ignore-auto-dns' property."/> +<property name="dhcp-send-hostname" variable="DHCP_SEND_HOSTNAME(+)" format="" values="" default="yes" example="" description="Whether DHCP_HOSTNAME should be sent to the DHCP server."/> +<property name="dhcp-hostname" variable="DHCP_HOSTNAME" format="" values="" default="" example="" description="Hostname to send to the DHCP server."/> +<property name="never-default" variable="DEFROUTE (GATEWAYDEV in /etc/sysconfig/network)" format="" values="" default="yes" example="" description="DEFROUTE=no tells NetworkManager that this connection +should not be assigned the default route. DEFROUTE has the opposite +meaning as 'never-default' property."/> +<property name="may-fail" variable="IPV4_FAILURE_FATAL(+)" format="" values="" default="no" example="" description="IPV4_FAILURE_FATAL has the opposite meaning as 'may-fail' property."/> +<property name="dhcp-client-id" variable="DHCP_CLIENT_ID(+)" format="" values="" default="" example="DHCP_CLIENT_ID=ax-srv-1" description="A string sent to the DHCP server to identify the local machine."/> +</setting> +<setting name="ipv6"> +<property name="method" variable="IPV6INIT, IPV6FORWARDING, IPV6_AUTOCONF, DHCPV6C" format="" values="" default="IPV6INIT=yes; IPV6FORWARDING=no; IPV6_AUTOCONF=!IPV6FORWARDING, DHCPV6=no" example="" description="Method used for IPv6 protocol configuration. +ignore ~ IPV6INIT=no; auto ~ IPV6_AUTOCONF=yes; dhcp ~ IPV6_AUTOCONF=no and DHCPV6C=yes"/> +<property name="dns" variable="DNS1, DNS2, ..." format="string" values="" default="" example="" description="List of DNS servers. NetworkManager uses the variables both +for IPv4 and IPv6."/> +<property name="dns-search" variable="DOMAIN" format="string (space-separated domains)" values="" default="" example="" description="List of DNS search domains."/> +<property name="addresses" variable="IPV6ADDR, IPV6ADDR_SECONDARIES" format="" values="" default="" example="IPV6ADDR=ab12:9876::1 +IPV6ADDR_SECONDARIES="ab12:9876::2 ab12:9876::3"" description="List of static IP addresses."/> +<property name="gateway" variable="IPV6_DEFAULTGW" format="" values="" default="" example="IPV6_DEFAULTGW=abbe::1" description="Gateway IP address."/> +<property name="routes" variable="(none)" format="" values="" default="" example="" description="List of static routes. They are not stored in ifcfg-* file, +but in route6-* file instead in the form of command line for 'ip route add'."/> +<property name="ignore-auto-routes" variable="IPV6_PEERROUTES(+)" format="" values="" default="yes" example="" description="IPV6_PEERROUTES has the opposite meaning as 'ignore-auto-routes' property."/> +<property name="ignore-auto-dns" variable="IPV6_PEERDNS(+)" format="" values="" default="yes" example="" description="IPV6_PEERDNS has the opposite meaning as 'ignore-auto-dns' property."/> +<property name="dhcp-hostname" variable="DHCP_HOSTNAME" format="" values="" default="" example="" description="Hostname to send the DHCP server."/> +<property name="never-default" variable="IPV6_DEFROUTE(+), (and IPV6_DEFAULTGW, IPV6_DEFAULTDEV in /etc/sysconfig/network)" format="" values="" default="IPV6_DEFROUTE=yes (when no variable specified)" example="" description="IPV6_DEFROUTE=no tells NetworkManager that this connection +should not be assigned the default IPv6 route. IPV6_DEFROUTE has the opposite +meaning as 'never-default' property."/> +<property name="may-fail" variable="IPV6_FAILURE_FATAL(+)" format="" values="" default="no" example="" description="IPV6_FAILURE_FATAL has the opposite meaning as 'may-fail' property."/> +<property name="ip6-privacy" variable="IPV6_PRIVACY, IPV6_PRIVACY_PREFER_PUBLIC_IP(+)" format="" values="IPV6_PRIVACY: no, yes (rfc3041 or rfc4941); +IPV6_PRIVACY_PREFER_PUBLIC_IP: yes, no" default="no" example="IPV6_PRIVACY=rfc3041 IPV6_PRIVACY_PREFER_PUBLIC_IP=yes" description="Configure IPv6 Privacy Extensions for SLAAC (RFC4941)."/> +</setting> +<setting name="802-11-olpc-mesh"> +</setting> +<setting name="ppp"> +</setting> +<setting name="pppoe"> +</setting> +<setting name="serial"> +</setting> +<setting name="team-port"> +<property name="config" variable="TEAM_PORT_CONFIG" format="" values="" default="" example="" description="Team port configuration in JSON. See man teamd.conf for details."/> +</setting> +<setting name="team"> +<property name="config" variable="TEAM_CONFIG" format="" values="" default="" example="" description="Team configuration in JSON. See man teamd.conf for details."/> +</setting> +<setting name="vlan"> +<property name="parent" variable="DEVICE or PHYSDEV" format="" values="" default="" example="" description="Parent interface of the VLAN."/> +<property name="id" variable="VLAN_ID or DEVICE" format="" values="" default="" example="" description="VLAN identifier."/> +<property name="flags" variable="VLAN_FLAGS, REORDER_HDR" format="" values=""GVRP", "LOOSE_BINDING" for VLAN_FLAGS; 0 or 1 for REORDER_HDR" default="" example="" description="Parent interface of the VLAN."/> +<property name="ingress-property-map" variable="VLAN_INGRESS_PRIORITY_MAP" format="" values="" default="" example="VLAN_INGRESS_PRIORITY_MAP=4:2,3:5" description="Ingress priority mapping."/> +<property name="egress-property-map" variable="VLAN_EGRESS_PRIORITY_MAP" format="" values="" default="" example="VLAN_EGRESS_PRIORITY_MAP=5:4,4:1,3:7" description="Egress priority mapping."/> +<property name="interface-name" variable="PHYSDEV and VLAN_ID, or DEVICE" format="" values="" default="" example="PHYSDEV=eth0, VLAN_ID=12; or DEVICE=eth0.12" description="VLAN interface name. +If all variables are set, parent device from PHYSDEV takes precedence over DEVICE, +but VLAN id from DEVICE takes precedence over VLAN_ID."/> +</setting> +<setting name="vpn"> +</setting> +<setting name="wimax"> +</setting> +<setting name="802-3-ethernet"> +<property name="port" variable="(none)" format="" values="" default="" example="" description="The property is not saved by the plugin."/> +<property name="speed" variable="(none)" format="" values="" default="" example="" description="The property is not saved by the plugin."/> +<property name="duplex" variable="(none)" format="" values="" default="" example="" description="The property is not saved by the plugin."/> +<property name="auto-negotiate" variable="(none)" format="" values="" default="" example="" description="The property is not saved by the plugin."/> +<property name="mac-address" variable="HWADDR" format="" values="" default="" example="" description="Hardware address of the device in traditional hex-digits-and-colons +notation (e.g. 00:22:68:14:5A:05)."/> +<property name="cloned-mac-address" variable="MACADDR" format="" values="" default="" example="" description="Cloned (spoofed) MAC address in traditional hex-digits-and-colons +notation (e.g. 00:22:68:14:5A:99)."/> +<property name="mac-address-blacklist" variable="HWADDR_BLACKLIST(+)" format="" values="" default="" example="HWADDR_BLACKLIST="00:22:68:11:69:08 00:11:22:11:44:55"" description="It denies usage of the connection for any device whose address +is listed."/> +<property name="mtu" variable="MTU" format="" values="" default="" example="" description="MTU of the interface."/> +<property name="s390-subchannels" variable="SUBCHANNELS" format="" values="" default="" example="SUBCHANNELS=0.0.b00a,0.0.b00b,0.0.b00c" description="Subchannels for IBM S390 hosts."/> +<property name="s390-nettype" variable="NETTYPE" format="" values=""qeth", "lcs" or "ctc"" default="" example="NETTYPE=qeth" description="Network type of the S390 host."/> +<property name="s390-options" variable="OPTIONS and PORTNAME, CTCPROTO," format="" values="" default="" example="" description="S390 device options. All options go to OPTIONS, except for +"portname" and "ctcprot" that have their own variables."/> +</setting> +<setting name="802-11-wireless-security"> +<property name="key-mgmt" variable="KEY_MGMT(+)" format="" values="IEEE8021X, WPA-PSK, WPA-EAP" default="" example="" description="Key management menthod."/> +<property name="wep-tx-keyidx" variable="DEFAULTKEY" format="" values="1, 2, 3, 4" default="1" example="" description="Index of active WEP key."/> +<property name="auth-alg" variable="SECURITYMODE(+)" format="" values="restricted, open, leap" default="" example="" description="Authentication algorithm for WEP."/> +<property name="proto" variable="WPA_ALLOW_WPA(+), WPA_ALLOW_WPA2(+)" format="" values="yes, no" default="no" example="" description="Allowed WPA protocols, WPA and WPA2 (RSN)."/> +<property name="pairwise" variable="CIPHER_PAIRWISE(+)" format="" values="CCMP, TKIP" default="" example="" description="Restrict pairwise encryption algorithms, specified as a space +separated list."/> +<property name="group" variable="CIPHER_GROUP(+)" format="" values="CCMP, TKIP, WEP40, WEP104" default="" example="" description="Restrict group/broadcast encryption algorithms, specified as a space +separated list."/> +<property name="leap-username" variable="IEEE_8021X_IDENTITY(+)" format="" values="" default="" example="" description="Login name for LEAP."/> +<property name="wep-key0" variable="KEY1, KEY_PASSPHRASE1(+)" format="" values="" default="" example="" description="The first WEP key (used in most networks). See also DEFAULTKEY for key index."/> +<property name="wep-key1" variable="KEY2, KEY_PASSPHRASE2(+)" format="" values="" default="" example="" description="WEP key with index 1. See also DEFAULTKEY for key index."/> +<property name="wep-key2" variable="KEY3, KEY_PASSPHRASE3(+)" format="" values="" default="" example="" description="WEP key with index 2. See also DEFAULTKEY for key index."/> +<property name="wep-key3" variable="KEY4, KEY_PASSPHRASE4(+)" format="" values="" default="" example="" description="WEP key with index 3. See also DEFAULTKEY for key index."/> +<property name="wep-key-flags" variable="WEP_KEY_FLAGS(+)" format="NMSettingSecretFlags" values="" default="" example="" description="Password flags for KEY<i>, KEY_PASSPHRASE<i> password."/> +<property name="psk" variable="WPA_PSK" format="" values="" default="" example="" description="Pre-Shared-Key for WPA networks."/> +<property name="psk-flags" variable="WPA_PSK_FLAGS(+)" format="NMSettingSecretFlags" values="" default="" example="WPA_PSK_FLAGS=user" description="Password flags for WPA_PSK_FLAGS."/> +<property name="leap-password" variable="IEEE_8021X_PASSWORD(+)" format="" values="" default="" example="" description="Password for LEAP. It can also go to "key-" +lookaside file, or it can be owned by a secret agent."/> +<property name="leap-password-flags" variable="IEEE_8021X_PASSWORD_FLAGS(+)" format="NMSettingSecretFlags" values="" default="" example="" description="Password flags for IEEE_8021X_PASSWORD_FLAGS."/> +<property name="wep-key-type" variable="KEY<i> or KEY_PASSPHRASE<i>(+)" format="" values="" default="" example="KEY1=s:ahoj, KEY1=0a1c45bc02, KEY_PASSPHRASE1=mysupersecretkey" description="KEY is used for "key" type (10 or 26 hexadecimal characters, +or 5 or 13 character string prefixed with "s:"). KEY_PASSPHRASE is used +for WEP passphrases."/> +</setting> +<setting name="802-11-wireless"> +<property name="ssid" variable="ESSID" format="" values="" default="" example="ESSID="Quick Net"" description="SSID of Wi-Fi network."/> +<property name="mode" variable="MODE" format="" values="Ad-Hoc, Managed (Auto) [case insensitive]" default="" example="" description="Wi-Fi network mode."/> +<property name="band" variable="BAND(+)" format="" values="a, bg" default="" example="BAND=bg" description="BAND alone is honored, but CHANNEL overrides BAND since it +implies a band."/> +<property name="channel" variable="CHANNEL" format="" values="" default="" example="CHANNEL=6" description="Channel used for the Wi-Fi communication. +Channels greater than 14 mean "a" band, otherwise the +band is "bg"."/> +<property name="bssid" variable="BSSID(+)" format="" values="" default="" example="BSSID=00:1E:BD:64:83:21" description="Restricts association only to a single AP."/> +<property name="rate" variable="(none)" format="" values="" default="" example="" description="This property is not handled by ifcfg-rh plugin."/> +<property name="tx-power" variable="(none)" format="" values="" default="" example="" description="This property is not handled by ifcfg-rh plugin."/> +<property name="mac-address" variable="HWADDR" format="" values="" default="" example="" description="Hardware address of the device in traditional hex-digits-and-colons +notation (e.g. 00:22:68:14:5A:05)."/> +<property name="cloned-mac-address" variable="MACADDR" format="" values="" default="" example="" description="Cloned (spoofed) MAC address in traditional hex-digits-and-colons +notation (e.g. 00:22:68:14:5A:99)."/> +<property name="mac-address-blacklist" variable="HWADDR_BLACKLIST(+)" format="" values="" default="" example="" description="It denies usage of the connection for any device whose address +is listed."/> +<property name="seen-bssids" variable="(none)" format="" values="" default="" example="" description="This property is not handled by ifcfg-rh plugin."/> +<property name="mtu" variable="MTU" format="" values="" default="" example="" description="MTU of the wireless interface."/> +<property name="hidden" variable="SSID_HIDDEN(+)" format="" values="" default="" example="" description="Whether the network hides the SSID."/> +<property name="security" variable="(none)" format="" values="" default="" example="" description="This property is deprecated and not handled by ifcfg-rh-plugin."/> +</setting> +</nm-ifcfg-rh-docs> \ No newline at end of file diff --git a/libnm/nm-ip-config.c b/libnm/nm-ip-config.c new file mode 100644 index 00000000..d057903e --- /dev/null +++ b/libnm/nm-ip-config.c @@ -0,0 +1,502 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2007 - 2011 Novell, Inc. + * Copyright 2008 - 2014 Red Hat, Inc. + */ + +#include "config.h" + +#include <string.h> + +#include "nm-ip-config.h" +#include "nm-ip4-config.h" +#include "nm-ip6-config.h" +#include "nm-setting-ip-config.h" +#include "nm-dbus-interface.h" +#include "nm-object-private.h" +#include "nm-utils.h" +#include "nm-core-internal.h" + +G_DEFINE_ABSTRACT_TYPE (NMIPConfig, nm_ip_config, NM_TYPE_OBJECT) + +#define NM_IP_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_IP_CONFIG, NMIPConfigPrivate)) + +typedef struct { + char *gateway; + GPtrArray *addresses; + GPtrArray *routes; + char **nameservers; + char **domains; + char **searches; + char **wins; + + gboolean new_style_data; +} NMIPConfigPrivate; + +enum { + PROP_0, + PROP_FAMILY, + PROP_GATEWAY, + PROP_ADDRESSES, + PROP_ROUTES, + PROP_NAMESERVERS, + PROP_DOMAINS, + PROP_SEARCHES, + PROP_WINS_SERVERS, + + LAST_PROP +}; + +static void +nm_ip_config_init (NMIPConfig *config) +{ + NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE (config); + + priv->addresses = g_ptr_array_new (); + priv->routes = g_ptr_array_new (); + priv->nameservers = g_new0 (char *, 1); + priv->domains = g_new0 (char *, 1); + priv->searches = g_new0 (char *, 1); + priv->wins = g_new0 (char *, 1); +} + +static gboolean +demarshal_ip_addresses (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field) +{ + NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE (object); + + if (priv->new_style_data) + return TRUE; + + g_ptr_array_unref (priv->addresses); + if (NM_IS_IP4_CONFIG (object)) + priv->addresses = nm_utils_ip4_addresses_from_variant (value, NULL); + else + priv->addresses = nm_utils_ip6_addresses_from_variant (value, NULL); + _nm_object_queue_notify (object, NM_IP_CONFIG_ADDRESSES); + + return TRUE; +} + +static gboolean +demarshal_ip_address_data (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field) +{ + NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE (object); + + priv->new_style_data = TRUE; + + g_ptr_array_unref (priv->addresses); + if (NM_IS_IP4_CONFIG (object)) + priv->addresses = nm_utils_ip_addresses_from_variant (value, AF_INET); + else + priv->addresses = nm_utils_ip_addresses_from_variant (value, AF_INET6); + _nm_object_queue_notify (object, NM_IP_CONFIG_ADDRESSES); + + return TRUE; +} + +static gboolean +demarshal_ip_array (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field) +{ + char ***obj_field; + + obj_field = field; + if (*obj_field) + g_strfreev (*obj_field); + + if (NM_IS_IP4_CONFIG (object)) + *obj_field = nm_utils_ip4_dns_from_variant (value); + else + *obj_field = nm_utils_ip6_dns_from_variant (value); + + _nm_object_queue_notify (object, pspec->name); + return TRUE; +} + +static gboolean +demarshal_ip_routes (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field) +{ + NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE (object); + + if (priv->new_style_data) + return TRUE; + + g_ptr_array_unref (priv->routes); + if (NM_IS_IP4_CONFIG (object)) + priv->routes = nm_utils_ip4_routes_from_variant (value); + else + priv->routes = nm_utils_ip6_routes_from_variant (value); + _nm_object_queue_notify (object, NM_IP_CONFIG_ROUTES); + + return TRUE; +} + +static gboolean +demarshal_ip_route_data (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field) +{ + NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE (object); + + priv->new_style_data = TRUE; + + g_ptr_array_unref (priv->routes); + if (NM_IS_IP4_CONFIG (object)) + priv->routes = nm_utils_ip_routes_from_variant (value, AF_INET); + else + priv->routes = nm_utils_ip_routes_from_variant (value, AF_INET6); + _nm_object_queue_notify (object, NM_IP_CONFIG_ROUTES); + + return TRUE; +} + +static void +init_dbus (NMObject *object) +{ + NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE (object); + const NMPropertiesInfo property_info[] = { + { NM_IP_CONFIG_GATEWAY, &priv->gateway, }, + { NM_IP_CONFIG_ADDRESSES, &priv->addresses, demarshal_ip_addresses }, + { "address-data", &priv->addresses, demarshal_ip_address_data }, + { NM_IP_CONFIG_ROUTES, &priv->routes, demarshal_ip_routes }, + { "route-data", &priv->routes, demarshal_ip_route_data }, + { NM_IP_CONFIG_NAMESERVERS, &priv->nameservers, demarshal_ip_array }, + { NM_IP_CONFIG_DOMAINS, &priv->domains, }, + { NM_IP_CONFIG_SEARCHES, &priv->searches, }, + { NM_IP_CONFIG_WINS_SERVERS, &priv->wins, demarshal_ip_array }, + { NULL }, + }; + + NM_OBJECT_CLASS (nm_ip_config_parent_class)->init_dbus (object); + + _nm_object_register_properties (object, + (NM_IS_IP4_CONFIG (object) ? + NM_DBUS_INTERFACE_IP4_CONFIG : + NM_DBUS_INTERFACE_IP6_CONFIG), + property_info); +} + +static void +finalize (GObject *object) +{ + NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE (object); + + g_free (priv->gateway); + + g_ptr_array_unref (priv->addresses); + g_ptr_array_unref (priv->routes); + + g_strfreev (priv->nameservers); + g_strfreev (priv->domains); + g_strfreev (priv->searches); + g_strfreev (priv->wins); + + G_OBJECT_CLASS (nm_ip_config_parent_class)->finalize (object); +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMIPConfig *self = NM_IP_CONFIG (object); + + switch (prop_id) { + case PROP_FAMILY: + g_value_set_int (value, nm_ip_config_get_family (self)); + break; + case PROP_GATEWAY: + g_value_set_string (value, nm_ip_config_get_gateway (self)); + break; + case PROP_ADDRESSES: + g_value_take_boxed (value, _nm_utils_copy_array (nm_ip_config_get_addresses (self), + (NMUtilsCopyFunc) nm_ip_address_dup, + (GDestroyNotify) nm_ip_address_unref)); + break; + case PROP_ROUTES: + g_value_take_boxed (value, _nm_utils_copy_array (nm_ip_config_get_routes (self), + (NMUtilsCopyFunc) nm_ip_route_dup, + (GDestroyNotify) nm_ip_route_unref)); + break; + case PROP_NAMESERVERS: + g_value_set_boxed (value, (char **) nm_ip_config_get_nameservers (self)); + break; + case PROP_DOMAINS: + g_value_set_boxed (value, (char **) nm_ip_config_get_domains (self)); + break; + case PROP_SEARCHES: + g_value_set_boxed (value, (char **) nm_ip_config_get_searches (self)); + break; + case PROP_WINS_SERVERS: + g_value_set_boxed (value, (char **) nm_ip_config_get_wins_servers (self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_ip_config_class_init (NMIPConfigClass *config_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (config_class); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (config_class); + + g_type_class_add_private (config_class, sizeof (NMIPConfigPrivate)); + + /* virtual methods */ + object_class->get_property = get_property; + object_class->finalize = finalize; + + nm_object_class->init_dbus = init_dbus; + + /* properties */ + + /** + * NMIPConfig:family: + * + * The IP address family of the configuration; either + * <literal>AF_INET</literal> or <literal>AF_INET6</literal>. + **/ + g_object_class_install_property + (object_class, PROP_FAMILY, + g_param_spec_int (NM_IP_CONFIG_FAMILY, "", "", + 0, 255, AF_UNSPEC, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMIPConfig:gateway: + * + * The IP gateway address of the configuration as string. + **/ + g_object_class_install_property + (object_class, PROP_GATEWAY, + g_param_spec_string (NM_IP_CONFIG_GATEWAY, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMIPConfig:addresses: + * + * A #GPtrArray containing the addresses (#NMIPAddress) of the configuration. + **/ + g_object_class_install_property + (object_class, PROP_ADDRESSES, + g_param_spec_boxed (NM_IP_CONFIG_ADDRESSES, "", "", + G_TYPE_PTR_ARRAY, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMIPConfig:routes: + * + * A #GPtrArray containing the routes (#NMIPRoute) of the configuration. + **/ + g_object_class_install_property + (object_class, PROP_ROUTES, + g_param_spec_boxed (NM_IP_CONFIG_ROUTES, "", "", + G_TYPE_PTR_ARRAY, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMIPConfig:nameservers: + * + * The array containing name server IP addresses of the configuration. + **/ + g_object_class_install_property + (object_class, PROP_NAMESERVERS, + g_param_spec_boxed (NM_IP_CONFIG_NAMESERVERS, "", "", + G_TYPE_STRV, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMIPConfig:domains: + * + * The array containing domain strings of the configuration. + **/ + g_object_class_install_property + (object_class, PROP_DOMAINS, + g_param_spec_boxed (NM_IP_CONFIG_DOMAINS, "", "", + G_TYPE_STRV, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMIPConfig:searches: + * + * The array containing DNS search strings of the configuration. + **/ + g_object_class_install_property + (object_class, PROP_SEARCHES, + g_param_spec_boxed (NM_IP_CONFIG_SEARCHES, "", "", + G_TYPE_STRV, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMIPConfig:wins-servers: + * + * The array containing WINS server IP addresses of the configuration. + * (This will always be empty for IPv6 configurations.) + **/ + g_object_class_install_property + (object_class, PROP_WINS_SERVERS, + g_param_spec_boxed (NM_IP_CONFIG_WINS_SERVERS, "", "", + G_TYPE_STRV, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); +} + +/** + * nm_ip_config_get_family: + * @config: a #NMIPConfig + * + * Gets the IP address family + * + * Returns: the IP address family; either <literal>AF_INET</literal> or + * <literal>AF_INET6</literal> + **/ +int +nm_ip_config_get_family (NMIPConfig *config) +{ + g_return_val_if_fail (NM_IS_IP_CONFIG (config), AF_UNSPEC); + + return NM_IS_IP4_CONFIG (config) ? AF_INET : AF_INET6; +} + +/** + * nm_ip_config_get_gateway: + * @config: a #NMIPConfig + * + * Gets the IP gateway address. + * + * Returns: (transfer none): the IP address of the gateway. + **/ +const char * +nm_ip_config_get_gateway (NMIPConfig *config) +{ + g_return_val_if_fail (NM_IS_IP_CONFIG (config), NULL); + + return NM_IP_CONFIG_GET_PRIVATE (config)->gateway; +} + +/** + * nm_ip_config_get_addresses: + * @config: a #NMIPConfig + * + * Gets the IP addresses (containing the address, prefix, and gateway). + * + * Returns: (element-type NMIPAddress) (transfer none): the #GPtrArray + * containing #NMIPAddress<!-- -->es. This is the internal copy used by the + * configuration and must not be modified. + **/ +GPtrArray * +nm_ip_config_get_addresses (NMIPConfig *config) +{ + g_return_val_if_fail (NM_IS_IP_CONFIG (config), NULL); + + return NM_IP_CONFIG_GET_PRIVATE (config)->addresses; +} + +/** + * nm_ip_config_get_nameservers: + * @config: a #NMIPConfig + * + * Gets the domain name servers (DNS). + * + * Returns: (transfer none): the array of nameserver IP addresses + **/ +const char * const * +nm_ip_config_get_nameservers (NMIPConfig *config) +{ + g_return_val_if_fail (NM_IS_IP_CONFIG (config), NULL); + + return (const char * const *) NM_IP_CONFIG_GET_PRIVATE (config)->nameservers; +} + +/** + * nm_ip_config_get_domains: + * @config: a #NMIPConfig + * + * Gets the domain names. + * + * Returns: (transfer none): the array of domains. + * (This is never %NULL, though it may be 0-length). + **/ +const char * const * +nm_ip_config_get_domains (NMIPConfig *config) +{ + g_return_val_if_fail (NM_IS_IP_CONFIG (config), NULL); + + return (const char * const *) NM_IP_CONFIG_GET_PRIVATE (config)->domains; +} + +/** + * nm_ip_config_get_searches: + * @config: a #NMIPConfig + * + * Gets the DNS searches. + * + * Returns: (transfer none): the array of DNS search strings. + * (This is never %NULL, though it may be 0-length). + **/ +const char * const * +nm_ip_config_get_searches (NMIPConfig *config) +{ + g_return_val_if_fail (NM_IS_IP_CONFIG (config), NULL); + + return (const char * const *) NM_IP_CONFIG_GET_PRIVATE (config)->searches; +} + +/** + * nm_ip_config_get_wins_servers: + * @config: a #NMIPConfig + * + * Gets the Windows Internet Name Service servers (WINS). + * + * Returns: (transfer none): the arry of WINS server IP address strings. + * (This is never %NULL, though it may be 0-length.) + **/ +const char * const * +nm_ip_config_get_wins_servers (NMIPConfig *config) +{ + g_return_val_if_fail (NM_IS_IP_CONFIG (config), NULL); + + return (const char * const *) NM_IP_CONFIG_GET_PRIVATE (config)->wins; +} + +/** + * nm_ip_config_get_routes: + * @config: a #NMIPConfig + * + * Gets the routes. + * + * Returns: (element-type NMIPRoute) (transfer none): the #GPtrArray containing + * #NMIPRoutes. This is the internal copy used by the configuration, and must + * not be modified. + **/ +GPtrArray * +nm_ip_config_get_routes (NMIPConfig *config) +{ + g_return_val_if_fail (NM_IS_IP_CONFIG (config), NULL); + + return NM_IP_CONFIG_GET_PRIVATE (config)->routes; +} diff --git a/libnm/nm-ip-config.h b/libnm/nm-ip-config.h new file mode 100644 index 00000000..815135a0 --- /dev/null +++ b/libnm/nm-ip-config.h @@ -0,0 +1,73 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2007 - 2008 Novell, Inc. + * Copyright 2008 - 2014 Red Hat, Inc. + */ + +#ifndef __NM_IP_CONFIG_H__ +#define __NM_IP_CONFIG_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include <nm-object.h> + +G_BEGIN_DECLS + +#define NM_TYPE_IP_CONFIG (nm_ip_config_get_type ()) +#define NM_IP_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_IP_CONFIG, NMIPConfig)) +#define NM_IP_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_IP_CONFIG, NMIPConfigClass)) +#define NM_IS_IP_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_IP_CONFIG)) +#define NM_IS_IP_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_IP_CONFIG)) +#define NM_IP_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_IP_CONFIG, NMIPConfigClass)) + +struct _NMIPConfig { + NMObject parent; +}; + +typedef struct { + NMObjectClass parent; + + /*< private >*/ + gpointer padding[8]; +} NMIPConfigClass; + +#define NM_IP_CONFIG_FAMILY "family" +#define NM_IP_CONFIG_GATEWAY "gateway" +#define NM_IP_CONFIG_ADDRESSES "addresses" +#define NM_IP_CONFIG_ROUTES "routes" +#define NM_IP_CONFIG_NAMESERVERS "nameservers" +#define NM_IP_CONFIG_DOMAINS "domains" +#define NM_IP_CONFIG_SEARCHES "searches" +#define NM_IP_CONFIG_WINS_SERVERS "wins-servers" + +GType nm_ip_config_get_type (void); + +int nm_ip_config_get_family (NMIPConfig *config); +const char * nm_ip_config_get_gateway (NMIPConfig *config); +GPtrArray * nm_ip_config_get_addresses (NMIPConfig *config); +GPtrArray * nm_ip_config_get_routes (NMIPConfig *config); +const char * const *nm_ip_config_get_nameservers (NMIPConfig *config); +const char * const *nm_ip_config_get_domains (NMIPConfig *config); +const char * const *nm_ip_config_get_searches (NMIPConfig *config); +const char * const *nm_ip_config_get_wins_servers (NMIPConfig *config); + +G_END_DECLS + +#endif /* __NM_IP_CONFIG_H__ */ diff --git a/libnm/nm-ip4-config.c b/libnm/nm-ip4-config.c new file mode 100644 index 00000000..26797dd7 --- /dev/null +++ b/libnm/nm-ip4-config.c @@ -0,0 +1,39 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2014 Red Hat, Inc. + */ + +#include "config.h" + +#include "nm-ip4-config.h" +#include "nm-object-private.h" + +G_DEFINE_TYPE (NMIP4Config, nm_ip4_config, NM_TYPE_IP_CONFIG) + +static void +nm_ip4_config_init (NMIP4Config *config) +{ +} + +static void +nm_ip4_config_class_init (NMIP4ConfigClass *config_class) +{ + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (config_class); + + _nm_object_class_add_interface (nm_object_class, NM_DBUS_INTERFACE_IP4_CONFIG); +} diff --git a/libnm/nm-ip4-config.h b/libnm/nm-ip4-config.h new file mode 100644 index 00000000..e2a18e0f --- /dev/null +++ b/libnm/nm-ip4-config.h @@ -0,0 +1,51 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2007 - 2008 Novell, Inc. + * Copyright 2008 Red Hat, Inc. + */ + +#ifndef __NM_IP4_CONFIG_H__ +#define __NM_IP4_CONFIG_H__ + +#include <nm-ip-config.h> + +G_BEGIN_DECLS + +#define NM_TYPE_IP4_CONFIG (nm_ip4_config_get_type ()) +#define NM_IP4_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_IP4_CONFIG, NMIP4Config)) +#define NM_IP4_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_IP4_CONFIG, NMIP4ConfigClass)) +#define NM_IS_IP4_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_IP4_CONFIG)) +#define NM_IS_IP4_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_IP4_CONFIG)) +#define NM_IP4_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_IP4_CONFIG, NMIP4ConfigClass)) + +typedef struct { + NMIPConfig parent; +} NMIP4Config; + +typedef struct { + NMIPConfigClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMIP4ConfigClass; + +GType nm_ip4_config_get_type (void); + +G_END_DECLS + +#endif /* __NM_IP4_CONFIG_H__ */ diff --git a/libnm/nm-ip6-config.c b/libnm/nm-ip6-config.c new file mode 100644 index 00000000..8a6c966c --- /dev/null +++ b/libnm/nm-ip6-config.c @@ -0,0 +1,39 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2014 Red Hat, Inc. + */ + +#include "config.h" + +#include "nm-ip6-config.h" +#include "nm-object-private.h" + +G_DEFINE_TYPE (NMIP6Config, nm_ip6_config, NM_TYPE_IP_CONFIG) + +static void +nm_ip6_config_init (NMIP6Config *config) +{ +} + +static void +nm_ip6_config_class_init (NMIP6ConfigClass *config_class) +{ + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (config_class); + + _nm_object_class_add_interface (nm_object_class, NM_DBUS_INTERFACE_IP6_CONFIG); +} diff --git a/libnm/nm-ip6-config.h b/libnm/nm-ip6-config.h new file mode 100644 index 00000000..1953476d --- /dev/null +++ b/libnm/nm-ip6-config.h @@ -0,0 +1,51 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2007 - 2008 Novell, Inc. + * Copyright 2008 - 2014 Red Hat, Inc. + */ + +#ifndef __NM_IP6_CONFIG_H__ +#define __NM_IP6_CONFIG_H__ + +#include <nm-ip-config.h> + +G_BEGIN_DECLS + +#define NM_TYPE_IP6_CONFIG (nm_ip6_config_get_type ()) +#define NM_IP6_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_IP6_CONFIG, NMIP6Config)) +#define NM_IP6_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_IP6_CONFIG, NMIP6ConfigClass)) +#define NM_IS_IP6_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_IP6_CONFIG)) +#define NM_IS_IP6_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_IP6_CONFIG)) +#define NM_IP6_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_IP6_CONFIG, NMIP6ConfigClass)) + +typedef struct { + NMIPConfig parent; +} NMIP6Config; + +typedef struct { + NMIPConfigClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMIP6ConfigClass; + +GType nm_ip6_config_get_type (void); + +G_END_DECLS + +#endif /* __NM_IP6_CONFIG_H__ */ diff --git a/libnm/nm-keyfile-docs.xml b/libnm/nm-keyfile-docs.xml new file mode 100644 index 00000000..d080a427 --- /dev/null +++ b/libnm/nm-keyfile-docs.xml @@ -0,0 +1,96 @@ +<?xml version="1.0"?> +<!DOCTYPE nm-keyfile-docs [ +]> + +<nm-keyfile-docs> + <setting name="802-1x"> +</setting> +<setting name="adsl"> +</setting> +<setting name="bluetooth"> +</setting> +<setting name="bond"> +</setting> +<setting name="bridge-port"> +</setting> +<setting name="bridge"> +<property name="mac-address" variable="mac-address" format="ususal hex-digits-and-colons notation" values="" default="" example="mac-address=00:22:68:12:79:A2 +mac-address=0;34;104;18;121;162;" description="MAC address in traditional hex-digits-and-colons notation, +or semicolon separated list of 6 decimal bytes (obsolete)"/> +</setting> +<setting name="cdma"> +</setting> +<setting name="connection"> +</setting> +<setting name="dcb"> +</setting> +<setting name="generic"> +</setting> +<setting name="gsm"> +</setting> +<setting name="infiniband"> +<property name="mac-address" variable="mac-address" format="ususal hex-digits-and-colons notation" values="" default="" example="mac-address= 80:00:00:6d:fe:80:00:00:00:00:00:00:00:02:55:00:70:33:cf:01" description="MAC address in traditional hex-digits-and-colons notation, or +or semicolon separated list of 20 decimal bytes (obsolete)"/> +</setting> +<setting name=""> +</setting> +<setting name="ipv4"> +<property name="dns" variable="dns" format="list of DNS IP addresses" values="" default="" example="dns=1.2.3.4;8.8.8.8;8.8.4.4;" description="List of DNS servers."/> +<property name="addresses" variable="address1, address2, ..." format="address/plen" values="" default="" example="address1=192.168.100.100/24 address2=10.1.1.5/24" description="List of static IP addresses."/> +<property name="gateway" variable="gateway" format="string" values="" default="" example="gateway=192.168.100.1" description="Gateway IP addresses as a string."/> +<property name="routes" variable="route1, route2, ..." format="route/plen[,gateway,metric]" values="" default="" example="route1=8.8.8.0/24,10.1.1.1,77 +route2=7.7.0.0/16" description="List of IP routes."/> +</setting> +<setting name="ipv6"> +<property name="dns" variable="dns" format="list of DNS IP addresses" values="" default="" example="dns=2001:4860:4860::8888;2001:4860:4860::8844;" description="List of DNS servers."/> +<property name="addresses" variable="address1, address2, ..." format="address/plen" values="" default="" example="address1=abbe::cafe/96 address2=2001::1234" description="List of static IP addresses."/> +<property name="gateway" variable="gateway" format="string" values="" default="" example="gateway=abbe::1" description="Gateway IP addresses as a string."/> +<property name="routes" variable="route1, route2, ..." format="route/plen[,gateway,metric]" values="" default="" example="route1=2001:4860:4860::/64,2620:52:0:2219:222:68ff:fe11:5403" description="List of IP routes."/> +</setting> +<setting name="802-11-olpc-mesh"> +</setting> +<setting name="ppp"> +</setting> +<setting name="pppoe"> +</setting> +<setting name="serial"> +<property name="parity" variable="parity" format="'e', 'o', or 'n'" values="" default="" example="parity=n" description="The connection parity; even, odd, or none. Note that older +versions of NetworkManager stored this as an integer: 69 ('E') for even, +111 ('o') for odd, or 110 ('n') for none."/> +</setting> +<setting name="team-port"> +</setting> +<setting name="team"> +</setting> +<setting name="vlan"> +</setting> +<setting name="vpn"> +<property name="data" variable="separate variables named after keys of the dictionary" format="" values="" default="" example="remote=ovpn.corp.com cipher=AES-256-CBC username=joe" description="The keys of the data dictionary are used as variable names directly +under [vpn] section."/> +<property name="secrets" variable="separate variables named after keys of the dictionary" format="" values="" default="" example="password=Popocatepetl" description="The keys of the secrets dictionary are used as variable names directly +under [vpn-secrets] section."/> +</setting> +<setting name="wimax"> +</setting> +<setting name="802-3-ethernet"> +<property name="mac-address" variable="mac-address" format="ususal hex-digits-and-colons notation" values="" default="" example="" description="MAC address in traditional hex-digits-and-colons notation +(e.g. 00:22:68:12:79:A2), or semicolon separated list of 6 bytes (obsolete) +(e.g. 0;34;104;18;121;162)"/> +<property name="cloned-mac-address" variable="cloned-mac-address" format="ususal hex-digits-and-colons notation" values="" default="" example="" description="Cloned MAC address in traditional hex-digits-and-colons notation +(e.g. 00:22:68:12:79:B2), or semicolon separated list of 6 bytes (obsolete) +(e.g. 0;34;104;18;121;178)."/> +<property name="mac-address-blacklist" variable="mac-address-blacklist" format="list of MACs (separated with semicolons)" values="" default="" example="mac-address-blacklist= 00:22:68:12:79:A6;00:22:68:12:79:78" description="MAC address blacklist."/> +</setting> +<setting name="802-11-wireless-security"> +</setting> +<setting name="802-11-wireless"> +<property name="ssid" variable="ssid" format="string (or decimal-byte list - obsolete)" values="" default="" example="ssid=Quick Net" description="SSID of Wi-Fi network."/> +<property name="mac-address" variable="mac-address" format="ususal hex-digits-and-colons notation" values="" default="" example="" description="MAC address in traditional hex-digits-and-colons notation +(e.g. 00:22:68:12:79:A2), or semicolon separated list of 6 bytes (obsolete) +(e.g. 0;34;104;18;121;162)."/> +<property name="cloned-mac-address" variable="cloned-mac-address" format="ususal hex-digits-and-colons notation" values="" default="" example="" description="Cloned MAC address in traditional hex-digits-and-colons notation +(e.g. 00:22:68:12:79:B2), or semicolon separated list of 6 bytes (obsolete) +(e.g. 0;34;104;18;121;178)."/> +<property name="mac-address-blacklist" variable="mac-address-blacklist" format="list of MACs (separated with semicolons)" values="" default="" example="mac-address-blacklist= 00:22:68:12:79:A6;00:22:68:12:79:78" description="MAC address blacklist."/> +</setting> +</nm-keyfile-docs> \ No newline at end of file diff --git a/libnm/nm-manager.c b/libnm/nm-manager.c new file mode 100644 index 00000000..1abb5130 --- /dev/null +++ b/libnm/nm-manager.c @@ -0,0 +1,1730 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2007 - 2008 Novell, Inc. + * Copyright 2007 - 2014 Red Hat, Inc. + */ + +#include "config.h" + +#include <string.h> +#include <glib/gi18n-lib.h> +#include <nm-utils.h> + +#include "nm-manager.h" +#include "nm-device-ethernet.h" +#include "nm-device-wifi.h" +#include "nm-device-private.h" +#include "nm-core-internal.h" +#include "nm-object-private.h" +#include "nm-active-connection.h" +#include "nm-vpn-connection.h" +#include "nm-object-cache.h" +#include "nm-glib-compat.h" +#include "nm-dbus-helpers.h" + +#include "nmdbus-manager.h" + +void _nm_device_wifi_set_wireless_enabled (NMDeviceWifi *device, gboolean enabled); + +static void nm_manager_initable_iface_init (GInitableIface *iface); +static void nm_manager_async_initable_iface_init (GAsyncInitableIface *iface); +static GInitableIface *nm_manager_parent_initable_iface; +static GAsyncInitableIface *nm_manager_parent_async_initable_iface; + +G_DEFINE_TYPE_WITH_CODE (NMManager, nm_manager, NM_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_manager_initable_iface_init); + G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_manager_async_initable_iface_init); + ) + +#define NM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_MANAGER, NMManagerPrivate)) + +typedef struct { + NMDBusManager *manager_proxy; + GCancellable *props_cancellable; + char *version; + NMState state; + gboolean startup; + GPtrArray *devices; + GPtrArray *active_connections; + NMConnectivityState connectivity; + NMActiveConnection *primary_connection; + NMActiveConnection *activating_connection; + + GCancellable *perm_call_cancellable; + GHashTable *permissions; + + /* Activations waiting for their NMActiveConnection + * to appear and then their callback to be called. + */ + GSList *pending_activations; + + gboolean networking_enabled; + gboolean wireless_enabled; + gboolean wireless_hw_enabled; + + gboolean wwan_enabled; + gboolean wwan_hw_enabled; + + gboolean wimax_enabled; + gboolean wimax_hw_enabled; +} NMManagerPrivate; + +enum { + PROP_0, + PROP_VERSION, + PROP_STATE, + PROP_STARTUP, + PROP_NM_RUNNING, + PROP_NETWORKING_ENABLED, + PROP_WIRELESS_ENABLED, + PROP_WIRELESS_HARDWARE_ENABLED, + PROP_WWAN_ENABLED, + PROP_WWAN_HARDWARE_ENABLED, + PROP_WIMAX_ENABLED, + PROP_WIMAX_HARDWARE_ENABLED, + PROP_ACTIVE_CONNECTIONS, + PROP_CONNECTIVITY, + PROP_PRIMARY_CONNECTION, + PROP_ACTIVATING_CONNECTION, + PROP_DEVICES, + + LAST_PROP +}; + +enum { + DEVICE_ADDED, + DEVICE_REMOVED, + ACTIVE_CONNECTION_ADDED, + ACTIVE_CONNECTION_REMOVED, + PERMISSION_CHANGED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +static void nm_running_changed_cb (GObject *object, + GParamSpec *pspec, + gpointer user_data); + +/**********************************************************************/ + +static void +nm_manager_init (NMManager *manager) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); + + priv->state = NM_STATE_UNKNOWN; + priv->connectivity = NM_CONNECTIVITY_UNKNOWN; + + priv->permissions = g_hash_table_new (g_direct_hash, g_direct_equal); + priv->devices = g_ptr_array_new (); + priv->active_connections = g_ptr_array_new (); +} + +static void +poke_wireless_devices_with_rf_status (NMManager *manager) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); + int i; + + for (i = 0; i < priv->devices->len; i++) { + NMDevice *device = g_ptr_array_index (priv->devices, i); + + if (NM_IS_DEVICE_WIFI (device)) + _nm_device_wifi_set_wireless_enabled (NM_DEVICE_WIFI (device), priv->wireless_enabled); + } +} + +static void +wireless_enabled_cb (GObject *object, GParamSpec *pspec, gpointer user_data) +{ + poke_wireless_devices_with_rf_status (NM_MANAGER (object)); +} + +static void manager_recheck_permissions (NMDBusManager *proxy, gpointer user_data); + +static void +init_dbus (NMObject *object) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (object); + const NMPropertiesInfo property_info[] = { + { NM_MANAGER_VERSION, &priv->version }, + { NM_MANAGER_STATE, &priv->state }, + { NM_MANAGER_STARTUP, &priv->startup }, + { NM_MANAGER_NETWORKING_ENABLED, &priv->networking_enabled }, + { NM_MANAGER_WIRELESS_ENABLED, &priv->wireless_enabled }, + { NM_MANAGER_WIRELESS_HARDWARE_ENABLED, &priv->wireless_hw_enabled }, + { NM_MANAGER_WWAN_ENABLED, &priv->wwan_enabled }, + { NM_MANAGER_WWAN_HARDWARE_ENABLED, &priv->wwan_hw_enabled }, + { NM_MANAGER_WIMAX_ENABLED, &priv->wimax_enabled }, + { NM_MANAGER_WIMAX_HARDWARE_ENABLED, &priv->wimax_hw_enabled }, + { NM_MANAGER_ACTIVE_CONNECTIONS, &priv->active_connections, NULL, NM_TYPE_ACTIVE_CONNECTION, "active-connection" }, + { NM_MANAGER_CONNECTIVITY, &priv->connectivity }, + { NM_MANAGER_PRIMARY_CONNECTION, &priv->primary_connection, NULL, NM_TYPE_ACTIVE_CONNECTION }, + { NM_MANAGER_ACTIVATING_CONNECTION, &priv->activating_connection, NULL, NM_TYPE_ACTIVE_CONNECTION }, + { NM_MANAGER_DEVICES, &priv->devices, NULL, NM_TYPE_DEVICE, "device" }, + { NULL }, + }; + + NM_OBJECT_CLASS (nm_manager_parent_class)->init_dbus (object); + + priv->manager_proxy = NMDBUS_MANAGER (_nm_object_get_proxy (object, NM_DBUS_INTERFACE)); + _nm_object_register_properties (object, + NM_DBUS_INTERFACE, + property_info); + + /* Permissions */ + g_signal_connect (priv->manager_proxy, "check-permissions", + G_CALLBACK (manager_recheck_permissions), object); +} + +#define NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK "org.freedesktop.NetworkManager.enable-disable-network" +#define NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI "org.freedesktop.NetworkManager.enable-disable-wifi" +#define NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN "org.freedesktop.NetworkManager.enable-disable-wwan" +#define NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX "org.freedesktop.NetworkManager.enable-disable-wimax" +#define NM_AUTH_PERMISSION_SLEEP_WAKE "org.freedesktop.NetworkManager.sleep-wake" +#define NM_AUTH_PERMISSION_NETWORK_CONTROL "org.freedesktop.NetworkManager.network-control" +#define NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED "org.freedesktop.NetworkManager.wifi.share.protected" +#define NM_AUTH_PERMISSION_WIFI_SHARE_OPEN "org.freedesktop.NetworkManager.wifi.share.open" +#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM "org.freedesktop.NetworkManager.settings.modify.system" +#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN "org.freedesktop.NetworkManager.settings.modify.own" +#define NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME "org.freedesktop.NetworkManager.settings.modify.hostname" + +static NMClientPermission +nm_permission_to_client (const char *nm) +{ + if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK)) + return NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK; + else if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI)) + return NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI; + else if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN)) + return NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN; + else if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX)) + return NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX; + else if (!strcmp (nm, NM_AUTH_PERMISSION_SLEEP_WAKE)) + return NM_CLIENT_PERMISSION_SLEEP_WAKE; + else if (!strcmp (nm, NM_AUTH_PERMISSION_NETWORK_CONTROL)) + return NM_CLIENT_PERMISSION_NETWORK_CONTROL; + else if (!strcmp (nm, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED)) + return NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED; + else if (!strcmp (nm, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN)) + return NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN; + else if (!strcmp (nm, NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM)) + return NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM; + else if (!strcmp (nm, NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN)) + return NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN; + else if (!strcmp (nm, NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME)) + return NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME; + + return NM_CLIENT_PERMISSION_NONE; +} + +static NMClientPermissionResult +nm_permission_result_to_client (const char *nm) +{ + if (!strcmp (nm, "yes")) + return NM_CLIENT_PERMISSION_RESULT_YES; + else if (!strcmp (nm, "no")) + return NM_CLIENT_PERMISSION_RESULT_NO; + else if (!strcmp (nm, "auth")) + return NM_CLIENT_PERMISSION_RESULT_AUTH; + return NM_CLIENT_PERMISSION_RESULT_UNKNOWN; +} + +static void +update_permissions (NMManager *self, GVariant *permissions) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + GHashTableIter iter; + gpointer key, value; + NMClientPermission perm; + NMClientPermissionResult perm_result; + GList *keys, *keys_iter; + + /* get list of old permissions for change notification */ + keys = g_hash_table_get_keys (priv->permissions); + g_hash_table_remove_all (priv->permissions); + + if (permissions) { + GVariantIter viter; + const char *pkey, *pvalue; + + /* Process new permissions */ + g_variant_iter_init (&viter, permissions); + while (g_variant_iter_next (&viter, "{&s&s}", &pkey, &pvalue)) { + perm = nm_permission_to_client (pkey); + perm_result = nm_permission_result_to_client (pvalue); + if (perm) { + g_hash_table_insert (priv->permissions, + GUINT_TO_POINTER (perm), + GUINT_TO_POINTER (perm_result)); + + /* Remove this permission from the list of previous permissions + * we'll be sending NM_CLIENT_PERMISSION_RESULT_UNKNOWN for + * in the change signal since it is still a known permission. + */ + keys = g_list_remove (keys, GUINT_TO_POINTER (perm)); + } + } + } + + /* Signal changes in all updated permissions */ + g_hash_table_iter_init (&iter, priv->permissions); + while (g_hash_table_iter_next (&iter, &key, &value)) { + g_signal_emit (self, signals[PERMISSION_CHANGED], 0, + GPOINTER_TO_UINT (key), + GPOINTER_TO_UINT (value)); + } + + /* And signal changes in all permissions that used to be valid but for + * some reason weren't received in the last request (if any). + */ + for (keys_iter = keys; keys_iter; keys_iter = g_list_next (keys_iter)) { + g_signal_emit (self, signals[PERMISSION_CHANGED], 0, + GPOINTER_TO_UINT (keys_iter->data), + NM_CLIENT_PERMISSION_RESULT_UNKNOWN); + } + g_list_free (keys); +} + +static gboolean +get_permissions_sync (NMManager *self, GError **error) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + GVariant *permissions; + + if (nmdbus_manager_call_get_permissions_sync (priv->manager_proxy, + &permissions, + NULL, error)) { + update_permissions (self, permissions); + g_variant_unref (permissions); + return TRUE; + } else { + if (error && *error) + g_dbus_error_strip_remote_error (*error); + update_permissions (self, NULL); + return FALSE; + } +} + +static void +get_permissions_reply (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + NMManager *self; + NMManagerPrivate *priv; + GVariant *permissions = NULL; + GError *error = NULL; + + /* WARNING: this may be called after the manager is disposed, so we can't + * look at self/priv until after we've determined that that isn't the case. + */ + + nmdbus_manager_call_get_permissions_finish (NMDBUS_MANAGER (object), + &permissions, + result, &error); + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + /* @self has been disposed. */ + g_error_free (error); + return; + } + + self = user_data; + priv = NM_MANAGER_GET_PRIVATE (self); + + update_permissions (self, permissions); + + g_clear_pointer (&permissions, g_variant_unref); + g_clear_error (&error); + g_clear_object (&priv->perm_call_cancellable); +} + +static void +manager_recheck_permissions (NMDBusManager *proxy, gpointer user_data) +{ + NMManager *self = NM_MANAGER (user_data); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + + if (priv->perm_call_cancellable) + return; + + priv->perm_call_cancellable = g_cancellable_new (); + nmdbus_manager_call_get_permissions (priv->manager_proxy, + priv->perm_call_cancellable, + get_permissions_reply, + self); +} + +const char * +nm_manager_get_version (NMManager *manager) +{ + g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); + + return NM_MANAGER_GET_PRIVATE (manager)->version; +} + +NMState +nm_manager_get_state (NMManager *manager) +{ + g_return_val_if_fail (NM_IS_MANAGER (manager), NM_STATE_UNKNOWN); + + return NM_MANAGER_GET_PRIVATE (manager)->state; +} + +gboolean +nm_manager_get_startup (NMManager *manager) +{ + g_return_val_if_fail (NM_IS_MANAGER (manager), NM_STATE_UNKNOWN); + + return NM_MANAGER_GET_PRIVATE (manager)->startup; +} + +gboolean +nm_manager_get_nm_running (NMManager *manager) +{ + g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE); + + return _nm_object_get_nm_running (NM_OBJECT (manager)); +} + +gboolean +nm_manager_networking_get_enabled (NMManager *manager) +{ + g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE); + + return NM_MANAGER_GET_PRIVATE (manager)->networking_enabled; +} + +gboolean +nm_manager_networking_set_enabled (NMManager *manager, gboolean enable, GError **error) +{ + gboolean ret; + + g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE); + + ret = nmdbus_manager_call_enable_sync (NM_MANAGER_GET_PRIVATE (manager)->manager_proxy, + enable, + NULL, error); + if (error && *error) + g_dbus_error_strip_remote_error (*error); + return ret; +} + +gboolean +nm_manager_wireless_get_enabled (NMManager *manager) +{ + g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE); + + return NM_MANAGER_GET_PRIVATE (manager)->wireless_enabled; +} + +void +nm_manager_wireless_set_enabled (NMManager *manager, gboolean enabled) +{ + g_return_if_fail (NM_IS_MANAGER (manager)); + + _nm_object_set_property (NM_OBJECT (manager), + NM_DBUS_INTERFACE, + "WirelessEnabled", + "b", enabled); +} + +gboolean +nm_manager_wireless_hardware_get_enabled (NMManager *manager) +{ + g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE); + + return NM_MANAGER_GET_PRIVATE (manager)->wireless_hw_enabled; +} + +gboolean +nm_manager_wwan_get_enabled (NMManager *manager) +{ + g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE); + + return NM_MANAGER_GET_PRIVATE (manager)->wwan_enabled; +} + +void +nm_manager_wwan_set_enabled (NMManager *manager, gboolean enabled) +{ + g_return_if_fail (NM_IS_MANAGER (manager)); + + _nm_object_set_property (NM_OBJECT (manager), + NM_DBUS_INTERFACE, + "WwanEnabled", + "b", enabled); +} + +gboolean +nm_manager_wwan_hardware_get_enabled (NMManager *manager) +{ + g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE); + + return NM_MANAGER_GET_PRIVATE (manager)->wwan_hw_enabled; +} + +gboolean +nm_manager_wimax_get_enabled (NMManager *manager) +{ + g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE); + + return NM_MANAGER_GET_PRIVATE (manager)->wimax_enabled; +} + +void +nm_manager_wimax_set_enabled (NMManager *manager, gboolean enabled) +{ + g_return_if_fail (NM_IS_MANAGER (manager)); + + _nm_object_set_property (NM_OBJECT (manager), + NM_DBUS_INTERFACE, + "WimaxEnabled", + "b", enabled); +} + +gboolean +nm_manager_wimax_hardware_get_enabled (NMManager *manager) +{ + g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE); + + return NM_MANAGER_GET_PRIVATE (manager)->wimax_hw_enabled; +} + +gboolean +nm_manager_get_logging (NMManager *manager, char **level, char **domains, GError **error) +{ + gboolean ret; + + g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE); + g_return_val_if_fail (level == NULL || *level == NULL, FALSE); + g_return_val_if_fail (domains == NULL || *domains == NULL, FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (!level && !domains) + return TRUE; + + ret = nmdbus_manager_call_get_logging_sync (NM_MANAGER_GET_PRIVATE (manager)->manager_proxy, + level, domains, + NULL, error); + if (error && *error) + g_dbus_error_strip_remote_error (*error); + return ret; +} + +gboolean +nm_manager_set_logging (NMManager *manager, const char *level, const char *domains, GError **error) +{ + gboolean ret; + + g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (!level && !domains) + return TRUE; + + if (!level) + level = ""; + if (!domains) + domains = ""; + + ret = nmdbus_manager_call_set_logging_sync (NM_MANAGER_GET_PRIVATE (manager)->manager_proxy, + level, domains, + NULL, error); + if (error && *error) + g_dbus_error_strip_remote_error (*error); + return ret; +} + +NMClientPermissionResult +nm_manager_get_permission_result (NMManager *manager, NMClientPermission permission) +{ + gpointer result; + + g_return_val_if_fail (NM_IS_MANAGER (manager), NM_CLIENT_PERMISSION_RESULT_UNKNOWN); + + result = g_hash_table_lookup (NM_MANAGER_GET_PRIVATE (manager)->permissions, + GUINT_TO_POINTER (permission)); + return GPOINTER_TO_UINT (result); +} + +NMConnectivityState +nm_manager_get_connectivity (NMManager *manager) +{ + g_return_val_if_fail (NM_IS_MANAGER (manager), NM_STATE_UNKNOWN); + + return NM_MANAGER_GET_PRIVATE (manager)->connectivity; +} + +NMConnectivityState +nm_manager_check_connectivity (NMManager *manager, + GCancellable *cancellable, + GError **error) +{ + NMManagerPrivate *priv; + guint32 connectivity; + + g_return_val_if_fail (NM_IS_MANAGER (manager), NM_CONNECTIVITY_UNKNOWN); + priv = NM_MANAGER_GET_PRIVATE (manager); + + if (nmdbus_manager_call_check_connectivity_sync (priv->manager_proxy, + &connectivity, + cancellable, error)) + return connectivity; + else { + if (error && *error) + g_dbus_error_strip_remote_error (*error); + return NM_CONNECTIVITY_UNKNOWN; + } +} + +static void +check_connectivity_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + GSimpleAsyncResult *simple = user_data; + guint32 connectivity; + GError *error = NULL; + + if (nmdbus_manager_call_check_connectivity_finish (NMDBUS_MANAGER (object), + &connectivity, + result, &error)) + g_simple_async_result_set_op_res_gssize (simple, connectivity); + else { + g_dbus_error_strip_remote_error (error); + g_simple_async_result_take_error (simple, error); + } + + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +void +nm_manager_check_connectivity_async (NMManager *manager, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + NMManagerPrivate *priv; + GSimpleAsyncResult *simple; + + g_return_if_fail (NM_IS_MANAGER (manager)); + priv = NM_MANAGER_GET_PRIVATE (manager); + + simple = g_simple_async_result_new (G_OBJECT (manager), callback, user_data, + nm_manager_check_connectivity_async); + nmdbus_manager_call_check_connectivity (priv->manager_proxy, + cancellable, + check_connectivity_cb, simple); +} + +NMConnectivityState +nm_manager_check_connectivity_finish (NMManager *manager, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (manager), nm_manager_check_connectivity_async), NM_CONNECTIVITY_UNKNOWN); + + simple = G_SIMPLE_ASYNC_RESULT (result); + + if (g_simple_async_result_propagate_error (simple, error)) + return NM_CONNECTIVITY_UNKNOWN; + return (NMConnectivityState) g_simple_async_result_get_op_res_gssize (simple); +} + +/****************************************************************/ +/* Devices */ +/****************************************************************/ + +const GPtrArray * +nm_manager_get_devices (NMManager *manager) +{ + g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); + + return NM_MANAGER_GET_PRIVATE (manager)->devices; +} + +NMDevice * +nm_manager_get_device_by_path (NMManager *manager, const char *object_path) +{ + const GPtrArray *devices; + int i; + NMDevice *device = NULL; + + g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); + g_return_val_if_fail (object_path, NULL); + + devices = nm_manager_get_devices (manager); + for (i = 0; i < devices->len; i++) { + NMDevice *candidate = g_ptr_array_index (devices, i); + if (!strcmp (nm_object_get_path (NM_OBJECT (candidate)), object_path)) { + device = candidate; + break; + } + } + + return device; +} + +NMDevice * +nm_manager_get_device_by_iface (NMManager *manager, const char *iface) +{ + const GPtrArray *devices; + int i; + NMDevice *device = NULL; + + g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); + g_return_val_if_fail (iface, NULL); + + devices = nm_manager_get_devices (manager); + for (i = 0; i < devices->len; i++) { + NMDevice *candidate = g_ptr_array_index (devices, i); + if (!strcmp (nm_device_get_iface (candidate), iface)) { + device = candidate; + break; + } + } + + return device; +} + +/****************************************************************/ +/* Active Connections */ +/****************************************************************/ + +const GPtrArray * +nm_manager_get_active_connections (NMManager *manager) +{ + g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); + + return NM_MANAGER_GET_PRIVATE (manager)->active_connections; +} + +NMActiveConnection * +nm_manager_get_primary_connection (NMManager *manager) +{ + g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); + + return NM_MANAGER_GET_PRIVATE (manager)->primary_connection; +} + +NMActiveConnection * +nm_manager_get_activating_connection (NMManager *manager) +{ + g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); + + return NM_MANAGER_GET_PRIVATE (manager)->activating_connection; +} + +typedef struct { + NMManager *manager; + GSimpleAsyncResult *simple; + GCancellable *cancellable; + gulong cancelled_id; + char *active_path; + char *new_connection_path; +} ActivateInfo; + +static void active_removed (NMObject *object, NMActiveConnection *active, gpointer user_data); + +static void +activate_info_complete (ActivateInfo *info, + NMActiveConnection *active, + GError *error) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (info->manager); + + g_signal_handlers_disconnect_by_func (info->manager, G_CALLBACK (active_removed), info); + if (active) + g_simple_async_result_set_op_res_gpointer (info->simple, g_object_ref (active), g_object_unref); + else + g_simple_async_result_set_from_error (info->simple, error); + g_simple_async_result_complete (info->simple); + + priv->pending_activations = g_slist_remove (priv->pending_activations, info); + + g_free (info->active_path); + g_free (info->new_connection_path); + g_object_unref (info->simple); + if (info->cancellable) { + if (info->cancelled_id) + g_signal_handler_disconnect (info->cancellable, info->cancelled_id); + g_object_unref (info->cancellable); + } + g_slice_free (ActivateInfo, info); +} + +static NMActiveConnection * +find_active_connection_by_path (NMManager *self, const char *ac_path) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + int i; + + for (i = 0; i < priv->active_connections->len; i++) { + NMActiveConnection *candidate = g_ptr_array_index (priv->active_connections, i); + const char *candidate_path = nm_object_get_path (NM_OBJECT (candidate)); + + if (g_strcmp0 (ac_path, candidate_path) == 0) + return candidate; + } + + return NULL; +} + +static void +recheck_pending_activations (NMManager *self) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + GSList *iter, *next; + NMActiveConnection *candidate; + const GPtrArray *devices; + NMDevice *device; + + /* For each pending activation, look for an active connection that has the + * pending activation's object path, where the active connection and its + * device have both updated their properties to point to each other, and + * call the pending connection's callback. + */ + for (iter = priv->pending_activations; iter; iter = next) { + ActivateInfo *info = iter->data; + + next = g_slist_next (iter); + + candidate = find_active_connection_by_path (self, info->active_path); + if (!candidate) + continue; + + /* Check that the AC and device are both ready */ + devices = nm_active_connection_get_devices (candidate); + if (devices->len == 0) + continue; + + if (!NM_IS_VPN_CONNECTION (candidate)) { + device = devices->pdata[0]; + if (nm_device_get_active_connection (device) != candidate) + continue; + } + + activate_info_complete (info, candidate, NULL); + break; + } +} + +static void +activation_cancelled (GCancellable *cancellable, + gpointer user_data) +{ + ActivateInfo *info = user_data; + GError *error = NULL; + + if (!g_cancellable_set_error_if_cancelled (cancellable, &error)) + return; + + activate_info_complete (info, NULL, error); + g_clear_error (&error); +} + +static void +active_removed (NMObject *object, NMActiveConnection *active, gpointer user_data) +{ + ActivateInfo *info = user_data; + GError *error = NULL; + + if (strcmp (info->active_path, nm_object_get_path (NM_OBJECT (active)))) + return; + + error = g_error_new_literal (NM_CLIENT_ERROR, + NM_CLIENT_ERROR_FAILED, + _("Active connection could not be attached to the device")); + activate_info_complete (info, NULL, error); + g_clear_error (&error); +} + +static void +activate_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + ActivateInfo *info = user_data; + GError *error = NULL; + + if (nmdbus_manager_call_activate_connection_finish (NMDBUS_MANAGER (object), + &info->active_path, + result, &error)) { + if (info->cancellable) { + info->cancelled_id = g_signal_connect (info->cancellable, "cancelled", + G_CALLBACK (activation_cancelled), info); + } + + g_signal_connect (info->manager, "active-connection-removed", + G_CALLBACK (active_removed), info); + + recheck_pending_activations (info->manager); + } else { + g_dbus_error_strip_remote_error (error); + activate_info_complete (info, NULL, error); + g_clear_error (&error); + } +} + +void +nm_manager_activate_connection_async (NMManager *manager, + NMConnection *connection, + NMDevice *device, + const char *specific_object, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + NMManagerPrivate *priv; + ActivateInfo *info; + + g_return_if_fail (NM_IS_MANAGER (manager)); + if (device) + g_return_if_fail (NM_IS_DEVICE (device)); + if (connection) + g_return_if_fail (NM_IS_CONNECTION (connection)); + + info = g_slice_new0 (ActivateInfo); + info->manager = manager; + info->simple = g_simple_async_result_new (G_OBJECT (manager), callback, user_data, + nm_manager_activate_connection_async); + info->cancellable = cancellable ? g_object_ref (cancellable) : NULL; + + priv = NM_MANAGER_GET_PRIVATE (manager); + priv->pending_activations = g_slist_prepend (priv->pending_activations, info); + + nmdbus_manager_call_activate_connection (priv->manager_proxy, + connection ? nm_connection_get_path (connection) : "/", + device ? nm_object_get_path (NM_OBJECT (device)) : "/", + specific_object ? specific_object : "/", + cancellable, + activate_cb, info); +} + +NMActiveConnection * +nm_manager_activate_connection_finish (NMManager *manager, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (manager), nm_manager_activate_connection_async), NULL); + + simple = G_SIMPLE_ASYNC_RESULT (result); + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + else + return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple)); +} + +static void +add_activate_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + ActivateInfo *info = user_data; + GError *error = NULL; + + if (nmdbus_manager_call_add_and_activate_connection_finish (NMDBUS_MANAGER (object), + NULL, + &info->active_path, + result, &error)) { + if (info->cancellable) { + info->cancelled_id = g_signal_connect (info->cancellable, "cancelled", + G_CALLBACK (activation_cancelled), info); + } + + g_signal_connect (info->manager, "active-connection-removed", + G_CALLBACK (active_removed), info); + + recheck_pending_activations (info->manager); + } else { + g_dbus_error_strip_remote_error (error); + activate_info_complete (info, NULL, error); + g_clear_error (&error); + } +} + +void +nm_manager_add_and_activate_connection_async (NMManager *manager, + NMConnection *partial, + NMDevice *device, + const char *specific_object, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + NMManagerPrivate *priv; + GVariant *dict = NULL; + ActivateInfo *info; + + g_return_if_fail (NM_IS_MANAGER (manager)); + g_return_if_fail (NM_IS_DEVICE (device)); + if (partial) + g_return_if_fail (NM_IS_CONNECTION (partial)); + + info = g_slice_new0 (ActivateInfo); + info->manager = manager; + info->simple = g_simple_async_result_new (G_OBJECT (manager), callback, user_data, + nm_manager_add_and_activate_connection_async); + info->cancellable = cancellable ? g_object_ref (cancellable) : NULL; + + priv = NM_MANAGER_GET_PRIVATE (manager); + priv->pending_activations = g_slist_prepend (priv->pending_activations, info); + + if (partial) + dict = nm_connection_to_dbus (partial, NM_CONNECTION_SERIALIZE_ALL); + if (!dict) + dict = g_variant_new_array (G_VARIANT_TYPE ("{sa{sv}}"), NULL, 0); + + nmdbus_manager_call_add_and_activate_connection (priv->manager_proxy, + dict, + nm_object_get_path (NM_OBJECT (device)), + specific_object ? specific_object : "/", + cancellable, + add_activate_cb, info); +} + +NMActiveConnection * +nm_manager_add_and_activate_connection_finish (NMManager *manager, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (manager), nm_manager_add_and_activate_connection_async), NULL); + + simple = G_SIMPLE_ASYNC_RESULT (result); + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + else + return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple)); +} + +static void +device_ac_changed (GObject *object, GParamSpec *pspec, gpointer user_data) +{ + NMManager *self = user_data; + + recheck_pending_activations (self); +} + +static void +device_added (NMManager *self, NMDevice *device) +{ + g_signal_connect (device, "notify::" NM_DEVICE_ACTIVE_CONNECTION, + G_CALLBACK (device_ac_changed), self); +} + +static void +device_removed (NMManager *self, NMDevice *device) +{ + g_signal_handlers_disconnect_by_func (device, G_CALLBACK (device_ac_changed), self); +} + +static void +ac_devices_changed (GObject *object, GParamSpec *pspec, gpointer user_data) +{ + NMManager *self = user_data; + + recheck_pending_activations (self); +} + +static void +active_connection_added (NMManager *self, NMActiveConnection *ac) +{ + g_signal_connect (ac, "notify::" NM_ACTIVE_CONNECTION_DEVICES, + G_CALLBACK (ac_devices_changed), self); + recheck_pending_activations (self); +} + +static void +active_connection_removed (NMManager *self, NMActiveConnection *ac) +{ + g_signal_handlers_disconnect_by_func (ac, G_CALLBACK (ac_devices_changed), self); +} + +static void +object_creation_failed (NMObject *object, const char *failed_path) +{ + NMManager *self = NM_MANAGER (object); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + GError *error; + GSList *iter; + + /* A newly activated connection failed due to some immediate error + * and disappeared from active connection list. Make sure the + * callback gets called. + */ + error = g_error_new_literal (NM_CLIENT_ERROR, + NM_CLIENT_ERROR_OBJECT_CREATION_FAILED, + _("Active connection removed before it was initialized")); + + for (iter = priv->pending_activations; iter; iter = iter->next) { + ActivateInfo *info = iter->data; + + if (g_strcmp0 (failed_path, info->active_path) == 0) { + activate_info_complete (info, NULL, error); + g_error_free (error); + return; + } + } +} + +gboolean +nm_manager_deactivate_connection (NMManager *manager, + NMActiveConnection *active, + GCancellable *cancellable, + GError **error) +{ + const char *path; + gboolean ret; + + g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE); + g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (active), FALSE); + + path = nm_object_get_path (NM_OBJECT (active)); + ret = nmdbus_manager_call_deactivate_connection_sync (NM_MANAGER_GET_PRIVATE (manager)->manager_proxy, + path, + cancellable, error); + if (error && *error) + g_dbus_error_strip_remote_error (*error); + return ret; +} + +static void +deactivated_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + GSimpleAsyncResult *simple = user_data; + GError *error = NULL; + + if (nmdbus_manager_call_deactivate_connection_finish (NMDBUS_MANAGER (object), + result, &error)) + g_simple_async_result_set_op_res_gboolean (simple, TRUE); + else { + g_dbus_error_strip_remote_error (error); + g_simple_async_result_take_error (simple, error); + } + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +void +nm_manager_deactivate_connection_async (NMManager *manager, + NMActiveConnection *active, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + const char *path; + GSimpleAsyncResult *simple; + + g_return_if_fail (NM_IS_MANAGER (manager)); + g_return_if_fail (NM_IS_ACTIVE_CONNECTION (active)); + + simple = g_simple_async_result_new (G_OBJECT (manager), callback, user_data, + nm_manager_deactivate_connection_async); + + path = nm_object_get_path (NM_OBJECT (active)); + nmdbus_manager_call_deactivate_connection (NM_MANAGER_GET_PRIVATE (manager)->manager_proxy, + path, + cancellable, + deactivated_cb, simple); +} + +gboolean +nm_manager_deactivate_connection_finish (NMManager *manager, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (manager), nm_manager_deactivate_connection_async), FALSE); + + simple = G_SIMPLE_ASYNC_RESULT (result); + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + else + return g_simple_async_result_get_op_res_gboolean (simple); +} + +/****************************************************************/ + +static void +free_devices (NMManager *manager, gboolean in_dispose) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); + GPtrArray *devices; + NMDevice *device; + int i; + + if (!priv->devices) + return; + + devices = priv->devices; + + if (in_dispose) + priv->devices = NULL; + else { + priv->devices = g_ptr_array_new (); + + for (i = 0; i < devices->len; i++) { + device = devices->pdata[i]; + g_signal_emit (manager, signals[DEVICE_REMOVED], 0, device); + } + } + + g_ptr_array_unref (devices); +} + +static void +free_active_connections (NMManager *manager, gboolean in_dispose) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); + GPtrArray *active_connections; + NMActiveConnection *active_connection; + int i; + + if (!priv->active_connections) + return; + + active_connections = priv->active_connections; + if (in_dispose) + priv->active_connections = NULL; + else + priv->active_connections = g_ptr_array_new (); + + for (i = 0; i < active_connections->len; i++) { + active_connection = active_connections->pdata[i]; + g_signal_emit (manager, signals[ACTIVE_CONNECTION_REMOVED], 0, active_connection); + /* Break circular refs */ + g_object_run_dispose (G_OBJECT (active_connection)); + } + g_ptr_array_unref (active_connections); + + if (!in_dispose) + g_object_notify (G_OBJECT (manager), NM_MANAGER_ACTIVE_CONNECTIONS); +} + +static void +updated_properties (GObject *object, GAsyncResult *result, gpointer user_data) +{ + NMManager *manager = NM_MANAGER (user_data); + GError *error = NULL; + + if (!_nm_object_reload_properties_finish (NM_OBJECT (object), result, &error)) { + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + g_warning ("%s: error reading NMManager properties: %s", __func__, error->message); + g_error_free (error); + } + + _nm_object_queue_notify (NM_OBJECT (manager), NM_MANAGER_NM_RUNNING); +} + +static void +nm_running_changed_cb (GObject *object, + GParamSpec *pspec, + gpointer user_data) +{ + NMManager *manager = NM_MANAGER (object); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); + + if (!nm_manager_get_nm_running (manager)) { + NM_UTILS_CLEAR_CANCELLABLE (priv->props_cancellable); + + priv->state = NM_STATE_UNKNOWN; + priv->startup = FALSE; + _nm_object_queue_notify (NM_OBJECT (manager), NM_MANAGER_NM_RUNNING); + _nm_object_suppress_property_updates (NM_OBJECT (manager), TRUE); + poke_wireless_devices_with_rf_status (manager); + free_devices (manager, FALSE); + free_active_connections (manager, FALSE); + update_permissions (manager, NULL); + priv->wireless_enabled = FALSE; + priv->wireless_hw_enabled = FALSE; + priv->wwan_enabled = FALSE; + priv->wwan_hw_enabled = FALSE; + priv->wimax_enabled = FALSE; + priv->wimax_hw_enabled = FALSE; + g_free (priv->version); + priv->version = NULL; + + /* Clear object cache to ensure bad refcounting by managers doesn't + * keep objects in the cache. + */ + _nm_object_cache_clear (); + } else { + _nm_object_suppress_property_updates (NM_OBJECT (manager), FALSE); + + NM_UTILS_CLEAR_CANCELLABLE (priv->props_cancellable); + priv->props_cancellable = g_cancellable_new (); + _nm_object_reload_properties_async (NM_OBJECT (manager), priv->props_cancellable, updated_properties, manager); + + manager_recheck_permissions (priv->manager_proxy, manager); + } +} + +/****************************************************************/ + +static void +constructed (GObject *object) +{ + G_OBJECT_CLASS (nm_manager_parent_class)->constructed (object); + + g_signal_connect (object, "notify::" NM_OBJECT_NM_RUNNING, + G_CALLBACK (nm_running_changed_cb), NULL); + + g_signal_connect (object, "notify::" NM_MANAGER_WIRELESS_ENABLED, + G_CALLBACK (wireless_enabled_cb), NULL); +} + +static gboolean +init_sync (GInitable *initable, GCancellable *cancellable, GError **error) +{ + NMManager *manager = NM_MANAGER (initable); + + if (!nm_manager_parent_initable_iface->init (initable, cancellable, error)) + return FALSE; + + if ( nm_manager_get_nm_running (manager) + && !get_permissions_sync (manager, error)) + return FALSE; + + return TRUE; +} + +typedef struct { + NMManager *manager; + GCancellable *cancellable; + GSimpleAsyncResult *result; +} NMManagerInitData; + +static void +init_async_complete (NMManagerInitData *init_data) +{ + g_simple_async_result_complete (init_data->result); + g_object_unref (init_data->result); + g_clear_object (&init_data->cancellable); + g_slice_free (NMManagerInitData, init_data); +} + +static void +init_async_got_permissions (GObject *object, GAsyncResult *result, gpointer user_data) +{ + NMManagerInitData *init_data = user_data; + GVariant *permissions; + + if (nmdbus_manager_call_get_permissions_finish (NMDBUS_MANAGER (object), + &permissions, + result, NULL)) { + update_permissions (init_data->manager, permissions); + g_variant_unref (permissions); + } else + update_permissions (init_data->manager, NULL); + + init_async_complete (init_data); +} + +static void +init_async_parent_inited (GObject *source, GAsyncResult *result, gpointer user_data) +{ + NMManagerInitData *init_data = user_data; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (init_data->manager); + GError *error = NULL; + + if (!nm_manager_parent_async_initable_iface->init_finish (G_ASYNC_INITABLE (source), result, &error)) { + g_simple_async_result_take_error (init_data->result, error); + init_async_complete (init_data); + return; + } + + if (!nm_manager_get_nm_running (init_data->manager)) { + init_async_complete (init_data); + return; + } + + nmdbus_manager_call_get_permissions (priv->manager_proxy, + init_data->cancellable, + init_async_got_permissions, init_data); +} + +static void +init_async (GAsyncInitable *initable, int io_priority, + GCancellable *cancellable, GAsyncReadyCallback callback, + gpointer user_data) +{ + NMManagerInitData *init_data; + + init_data = g_slice_new0 (NMManagerInitData); + init_data->manager = NM_MANAGER (initable); + init_data->cancellable = cancellable ? g_object_ref (cancellable) : NULL; + init_data->result = g_simple_async_result_new (G_OBJECT (initable), callback, + user_data, init_async); + g_simple_async_result_set_op_res_gboolean (init_data->result, TRUE); + + nm_manager_parent_async_initable_iface->init_async (initable, io_priority, cancellable, + init_async_parent_inited, init_data); +} + +static gboolean +init_finish (GAsyncInitable *initable, GAsyncResult *result, GError **error) +{ + GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); + + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + else + return TRUE; +} + +static void +dispose (GObject *object) +{ + NMManager *manager = NM_MANAGER (object); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (object); + + if (priv->perm_call_cancellable) { + g_cancellable_cancel (priv->perm_call_cancellable); + g_clear_object (&priv->perm_call_cancellable); + } + + free_devices (manager, TRUE); + free_active_connections (manager, TRUE); + g_clear_object (&priv->primary_connection); + g_clear_object (&priv->activating_connection); + + /* Each activation should hold a ref on @manager, so if we're being disposed, + * there shouldn't be any pending. + */ + g_warn_if_fail (priv->pending_activations == NULL); + + g_hash_table_destroy (priv->permissions); + priv->permissions = NULL; + + G_OBJECT_CLASS (nm_manager_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (object); + + g_free (priv->version); + + G_OBJECT_CLASS (nm_manager_parent_class)->finalize (object); +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (object); + gboolean b; + + switch (prop_id) { + case PROP_NETWORKING_ENABLED: + b = g_value_get_boolean (value); + if (priv->networking_enabled != b) { + nm_manager_networking_set_enabled (NM_MANAGER (object), b, NULL); + /* Let the property value flip when we get the change signal from NM */ + } + break; + case PROP_WIRELESS_ENABLED: + b = g_value_get_boolean (value); + if (priv->wireless_enabled != b) { + nm_manager_wireless_set_enabled (NM_MANAGER (object), b); + /* Let the property value flip when we get the change signal from NM */ + } + break; + case PROP_WWAN_ENABLED: + b = g_value_get_boolean (value); + if (priv->wwan_enabled != b) { + nm_manager_wwan_set_enabled (NM_MANAGER (object), b); + /* Let the property value flip when we get the change signal from NM */ + } + break; + case PROP_WIMAX_ENABLED: + b = g_value_get_boolean (value); + if (priv->wimax_enabled != b) { + nm_manager_wimax_set_enabled (NM_MANAGER (object), b); + /* Let the property value flip when we get the change signal from NM */ + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMManager *self = NM_MANAGER (object); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + + switch (prop_id) { + case PROP_VERSION: + g_value_set_string (value, nm_manager_get_version (self)); + break; + case PROP_STATE: + g_value_set_enum (value, nm_manager_get_state (self)); + break; + case PROP_STARTUP: + g_value_set_boolean (value, nm_manager_get_startup (self)); + break; + case PROP_NM_RUNNING: + g_value_set_boolean (value, nm_manager_get_nm_running (self)); + break; + case PROP_NETWORKING_ENABLED: + g_value_set_boolean (value, nm_manager_networking_get_enabled (self)); + break; + case PROP_WIRELESS_ENABLED: + g_value_set_boolean (value, priv->wireless_enabled); + break; + case PROP_WIRELESS_HARDWARE_ENABLED: + g_value_set_boolean (value, priv->wireless_hw_enabled); + break; + case PROP_WWAN_ENABLED: + g_value_set_boolean (value, priv->wwan_enabled); + break; + case PROP_WWAN_HARDWARE_ENABLED: + g_value_set_boolean (value, priv->wwan_hw_enabled); + break; + case PROP_WIMAX_ENABLED: + g_value_set_boolean (value, priv->wimax_enabled); + break; + case PROP_WIMAX_HARDWARE_ENABLED: + g_value_set_boolean (value, priv->wimax_hw_enabled); + break; + case PROP_ACTIVE_CONNECTIONS: + g_value_take_boxed (value, _nm_utils_copy_object_array (nm_manager_get_active_connections (self))); + break; + case PROP_CONNECTIVITY: + g_value_set_enum (value, priv->connectivity); + break; + case PROP_PRIMARY_CONNECTION: + g_value_set_object (value, priv->primary_connection); + break; + case PROP_ACTIVATING_CONNECTION: + g_value_set_object (value, priv->activating_connection); + break; + case PROP_DEVICES: + g_value_take_boxed (value, _nm_utils_copy_object_array (nm_manager_get_devices (self))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_manager_class_init (NMManagerClass *manager_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (manager_class); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (manager_class); + + g_type_class_add_private (manager_class, sizeof (NMManagerPrivate)); + + _nm_object_class_add_interface (nm_object_class, NM_DBUS_INTERFACE); + _nm_dbus_register_proxy_type (NM_DBUS_INTERFACE, NMDBUS_TYPE_MANAGER_PROXY); + + /* virtual methods */ + object_class->constructed = constructed; + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->dispose = dispose; + object_class->finalize = finalize; + + nm_object_class->init_dbus = init_dbus; + nm_object_class->object_creation_failed = object_creation_failed; + + manager_class->device_added = device_added; + manager_class->device_removed = device_removed; + manager_class->active_connection_added = active_connection_added; + manager_class->active_connection_removed = active_connection_removed; + + /* properties */ + + g_object_class_install_property + (object_class, PROP_VERSION, + g_param_spec_string (NM_MANAGER_VERSION, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property + (object_class, PROP_STATE, + g_param_spec_enum (NM_CLIENT_STATE, "", "", + NM_TYPE_STATE, + NM_STATE_UNKNOWN, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property + (object_class, PROP_STARTUP, + g_param_spec_boolean (NM_MANAGER_STARTUP, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property + (object_class, PROP_NM_RUNNING, + g_param_spec_boolean (NM_MANAGER_NM_RUNNING, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property + (object_class, PROP_NETWORKING_ENABLED, + g_param_spec_boolean (NM_MANAGER_NETWORKING_ENABLED, "", "", + TRUE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property + (object_class, PROP_WIRELESS_ENABLED, + g_param_spec_boolean (NM_MANAGER_WIRELESS_ENABLED, "", "", + FALSE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property + (object_class, PROP_WIRELESS_HARDWARE_ENABLED, + g_param_spec_boolean (NM_MANAGER_WIRELESS_HARDWARE_ENABLED, "", "", + TRUE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property + (object_class, PROP_WWAN_ENABLED, + g_param_spec_boolean (NM_MANAGER_WWAN_ENABLED, "", "", + FALSE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property + (object_class, PROP_WWAN_HARDWARE_ENABLED, + g_param_spec_boolean (NM_MANAGER_WWAN_HARDWARE_ENABLED, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property + (object_class, PROP_WIMAX_ENABLED, + g_param_spec_boolean (NM_MANAGER_WIMAX_ENABLED, "", "", + FALSE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property + (object_class, PROP_WIMAX_HARDWARE_ENABLED, + g_param_spec_boolean (NM_MANAGER_WIMAX_HARDWARE_ENABLED, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property + (object_class, PROP_ACTIVE_CONNECTIONS, + g_param_spec_boxed (NM_MANAGER_ACTIVE_CONNECTIONS, "", "", + G_TYPE_PTR_ARRAY, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property + (object_class, PROP_CONNECTIVITY, + g_param_spec_enum (NM_CLIENT_CONNECTIVITY, "", "", + NM_TYPE_CONNECTIVITY_STATE, + NM_CONNECTIVITY_UNKNOWN, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property + (object_class, PROP_PRIMARY_CONNECTION, + g_param_spec_object (NM_MANAGER_PRIMARY_CONNECTION, "", "", + NM_TYPE_ACTIVE_CONNECTION, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property + (object_class, PROP_ACTIVATING_CONNECTION, + g_param_spec_object (NM_MANAGER_ACTIVATING_CONNECTION, "", "", + NM_TYPE_ACTIVE_CONNECTION, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property + (object_class, PROP_DEVICES, + g_param_spec_boxed (NM_MANAGER_DEVICES, "", "", + G_TYPE_PTR_ARRAY, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /* signals */ + + signals[DEVICE_ADDED] = + g_signal_new ("device-added", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMManagerClass, device_added), + NULL, NULL, NULL, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); + signals[DEVICE_REMOVED] = + g_signal_new ("device-removed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMManagerClass, device_removed), + NULL, NULL, NULL, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); + signals[ACTIVE_CONNECTION_ADDED] = + g_signal_new ("active-connection-added", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMManagerClass, active_connection_added), + NULL, NULL, NULL, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); + signals[ACTIVE_CONNECTION_REMOVED] = + g_signal_new ("active-connection-removed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMManagerClass, active_connection_removed), + NULL, NULL, NULL, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); + signals[PERMISSION_CHANGED] = + g_signal_new ("permission-changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); +} + +static void +nm_manager_initable_iface_init (GInitableIface *iface) +{ + nm_manager_parent_initable_iface = g_type_interface_peek_parent (iface); + + iface->init = init_sync; +} + +static void +nm_manager_async_initable_iface_init (GAsyncInitableIface *iface) +{ + nm_manager_parent_async_initable_iface = g_type_interface_peek_parent (iface); + + iface->init_async = init_async; + iface->init_finish = init_finish; +} diff --git a/libnm/nm-manager.h b/libnm/nm-manager.h new file mode 100644 index 00000000..ca9f7dd6 --- /dev/null +++ b/libnm/nm-manager.h @@ -0,0 +1,170 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2007 - 2008 Novell, Inc. + * Copyright 2007 - 2014 Red Hat, Inc. + */ + +#ifndef __NM_MANAGER_H__ +#define __NM_MANAGER_H__ + +#include <nm-object.h> +#include <nm-client.h> + +G_BEGIN_DECLS + +#define NM_TYPE_MANAGER (nm_manager_get_type ()) +#define NM_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_MANAGER, NMManager)) +#define NM_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_MANAGER, NMManagerClass)) +#define NM_IS_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_MANAGER)) +#define NM_IS_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_MANAGER)) +#define NM_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_MANAGER, NMManagerClass)) + +#define NM_MANAGER_VERSION "version" +#define NM_MANAGER_STATE "state" +#define NM_MANAGER_STARTUP "startup" +#define NM_MANAGER_NM_RUNNING "nm-running" +#define NM_MANAGER_NETWORKING_ENABLED "networking-enabled" +#define NM_MANAGER_WIRELESS_ENABLED "wireless-enabled" +#define NM_MANAGER_WIRELESS_HARDWARE_ENABLED "wireless-hardware-enabled" +#define NM_MANAGER_WWAN_ENABLED "wwan-enabled" +#define NM_MANAGER_WWAN_HARDWARE_ENABLED "wwan-hardware-enabled" +#define NM_MANAGER_WIMAX_ENABLED "wimax-enabled" +#define NM_MANAGER_WIMAX_HARDWARE_ENABLED "wimax-hardware-enabled" +#define NM_MANAGER_ACTIVE_CONNECTIONS "active-connections" +#define NM_MANAGER_CONNECTIVITY "connectivity" +#define NM_MANAGER_PRIMARY_CONNECTION "primary-connection" +#define NM_MANAGER_ACTIVATING_CONNECTION "activating-connection" +#define NM_MANAGER_DEVICES "devices" + +typedef struct { + NMObject parent; +} NMManager; + +typedef struct { + NMObjectClass parent; + + /* Signals */ + void (*device_added) (NMManager *manager, NMDevice *device); + void (*device_removed) (NMManager *manager, NMDevice *device); + void (*active_connection_added) (NMManager *manager, NMActiveConnection *ac); + void (*active_connection_removed) (NMManager *manager, NMActiveConnection *ac); + void (*permission_changed) (NMManager *manager, + NMClientPermission permission, + NMClientPermissionResult result); +} NMManagerClass; + +GType nm_manager_get_type (void); + +const char *nm_manager_get_version (NMManager *manager); +NMState nm_manager_get_state (NMManager *manager); +gboolean nm_manager_get_startup (NMManager *manager); +gboolean nm_manager_get_nm_running (NMManager *manager); + +gboolean nm_manager_networking_get_enabled (NMManager *manager); +gboolean nm_manager_networking_set_enabled (NMManager *manager, + gboolean enabled, + GError **error); + +gboolean nm_manager_wireless_get_enabled (NMManager *manager); +void nm_manager_wireless_set_enabled (NMManager *manager, gboolean enabled); +gboolean nm_manager_wireless_hardware_get_enabled (NMManager *manager); + +gboolean nm_manager_wwan_get_enabled (NMManager *manager); +void nm_manager_wwan_set_enabled (NMManager *manager, gboolean enabled); +gboolean nm_manager_wwan_hardware_get_enabled (NMManager *manager); + +gboolean nm_manager_wimax_get_enabled (NMManager *manager); +void nm_manager_wimax_set_enabled (NMManager *manager, gboolean enabled); +gboolean nm_manager_wimax_hardware_get_enabled (NMManager *manager); + +gboolean nm_manager_get_logging (NMManager *manager, + char **level, + char **domains, + GError **error); +gboolean nm_manager_set_logging (NMManager *manager, + const char *level, + const char *domains, + GError **error); + +NMClientPermissionResult nm_manager_get_permission_result (NMManager *manager, + NMClientPermission permission); + +NMConnectivityState nm_manager_get_connectivity (NMManager *manager); + +NMConnectivityState nm_manager_check_connectivity (NMManager *manager, + GCancellable *cancellable, + GError **error); +void nm_manager_check_connectivity_async (NMManager *manager, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +NMConnectivityState nm_manager_check_connectivity_finish (NMManager *manager, + GAsyncResult *result, + GError **error); + +/* Devices */ + +const GPtrArray *nm_manager_get_devices (NMManager *manager); +NMDevice *nm_manager_get_device_by_path (NMManager *manager, const char *object_path); +NMDevice *nm_manager_get_device_by_iface (NMManager *manager, const char *iface); + +/* Active Connections */ + +const GPtrArray *nm_manager_get_active_connections (NMManager *manager); + +NMActiveConnection *nm_manager_get_primary_connection (NMManager *manager); +NMActiveConnection *nm_manager_get_activating_connection (NMManager *manager); + +void nm_manager_activate_connection_async (NMManager *manager, + NMConnection *connection, + NMDevice *device, + const char *specific_object, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +NMActiveConnection *nm_manager_activate_connection_finish (NMManager *manager, + GAsyncResult *result, + GError **error); + +void nm_manager_add_and_activate_connection_async (NMManager *manager, + NMConnection *partial, + NMDevice *device, + const char *specific_object, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +NMActiveConnection *nm_manager_add_and_activate_connection_finish (NMManager *manager, + GAsyncResult *result, + GError **error); + +gboolean nm_manager_deactivate_connection (NMManager *manager, + NMActiveConnection *active, + GCancellable *cancellable, + GError **error); +void nm_manager_deactivate_connection_async (NMManager *manager, + NMActiveConnection *active, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean nm_manager_deactivate_connection_finish (NMManager *manager, + GAsyncResult *result, + GError **error); + +G_END_DECLS + +#endif /* __NM_MANAGER_H__ */ diff --git a/libnm/nm-object-cache.c b/libnm/nm-object-cache.c new file mode 100644 index 00000000..752c606a --- /dev/null +++ b/libnm/nm-object-cache.c @@ -0,0 +1,90 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2008 Red Hat, Inc. + */ + +#include "config.h" + +#include <string.h> +#include <glib.h> +#include "nm-object-cache.h" +#include "nm-object.h" + +static GHashTable *cache = NULL; + +static void +_init_cache (void) +{ + if (G_UNLIKELY (cache == NULL)) + cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); +} + +static void +_nm_object_cache_remove_by_path (char *path) +{ + _init_cache (); + g_hash_table_remove (cache, path); + g_free (path); +} + +void +_nm_object_cache_add (NMObject *object) +{ + char *path; + + _init_cache (); + path = g_strdup (nm_object_get_path (object)); + g_hash_table_insert (cache, path, object); + g_object_set_data_full (G_OBJECT (object), "nm-object-cache-tag", + g_strdup (path), (GDestroyNotify) _nm_object_cache_remove_by_path); +} + +NMObject * +_nm_object_cache_get (const char *path) +{ + NMObject *object; + + _init_cache (); + object = g_hash_table_lookup (cache, path); + return object ? g_object_ref (object) : NULL; +} + +void +_nm_object_cache_clear (void) +{ + GHashTableIter iter; + GObject *obj; + const char *path; + char *foo; + + if (!cache) + return; + + g_hash_table_iter_init (&iter, cache); + while (g_hash_table_iter_next (&iter, (gpointer) &path, (gpointer) &obj)) { + /* Remove the callback so that if the object isn't yet released + * by a client, when it does finally get unrefed, it won't trigger + * the cache removal for a new object with the same path as the + * one being released. + */ + foo = g_object_steal_data (obj, "nm-object-cache-tag"); + g_free (foo); + + g_hash_table_iter_remove (&iter); + } +} diff --git a/libnm/nm-object-cache.h b/libnm/nm-object-cache.h new file mode 100644 index 00000000..ebadbaa8 --- /dev/null +++ b/libnm/nm-object-cache.h @@ -0,0 +1,37 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2008 Red Hat, Inc. + */ + +#ifndef __NM_OBJECT_CACHE_H__ +#define __NM_OBJECT_CACHE_H__ + +#include <glib.h> +#include <glib-object.h> +#include "nm-object.h" + +G_BEGIN_DECLS + +/* Returns referenced object from the cache */ +NMObject *_nm_object_cache_get (const char *path); +void _nm_object_cache_add (NMObject *object); +void _nm_object_cache_clear (void); + +G_END_DECLS + +#endif /* __NM_OBJECT_CACHE_H__ */ diff --git a/libnm/nm-object-private.h b/libnm/nm-object-private.h new file mode 100644 index 00000000..0b13cbb6 --- /dev/null +++ b/libnm/nm-object-private.h @@ -0,0 +1,83 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2008 - 2011 Red Hat, Inc. + */ + +#ifndef __NM_OBJECT_PRIVATE_H__ +#define __NM_OBJECT_PRIVATE_H__ + +#include <gio/gio.h> +#include "nm-object.h" + +typedef gboolean (*PropertyMarshalFunc) (NMObject *, GParamSpec *, GVariant *, gpointer); + +typedef GObject * (*NMObjectCreatorFunc) (GDBusConnection *, const char *); + +typedef struct { + const char *name; + gpointer field; + PropertyMarshalFunc func; + GType object_type; + const char *signal_prefix; +} NMPropertiesInfo; + +void _nm_object_register_properties (NMObject *object, + const char *interface, + const NMPropertiesInfo *info); + +void _nm_object_reload_properties_async (NMObject *object, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean _nm_object_reload_properties_finish (NMObject *object, + GAsyncResult *result, + GError **error); + +void _nm_object_queue_notify (NMObject *object, const char *property); + +void _nm_object_suppress_property_updates (NMObject *object, gboolean suppress); + +/* DBus property accessors */ + +void _nm_object_reload_property (NMObject *object, + const char *interface, + const char *prop_name); + +void _nm_object_set_property (NMObject *object, + const char *interface, + const char *prop_name, + const char *format_string, + ...); + +/* object demarshalling support */ +typedef GType (*NMObjectDecideTypeFunc) (GVariant *); + +void _nm_object_register_type_func (GType base_type, + NMObjectDecideTypeFunc type_func, + const char *interface, + const char *property); + +#define NM_OBJECT_NM_RUNNING "nm-running-internal" +gboolean _nm_object_get_nm_running (NMObject *self); + +void _nm_object_class_add_interface (NMObjectClass *object_class, + const char *interface); +GDBusProxy *_nm_object_get_proxy (NMObject *object, + const char *interface); + +#endif /* __NM_OBJECT_PRIVATE_H__ */ diff --git a/libnm/nm-object.c b/libnm/nm-object.c new file mode 100644 index 00000000..391166b2 --- /dev/null +++ b/libnm/nm-object.c @@ -0,0 +1,1761 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2007 - 2008 Novell, Inc. + * Copyright 2007 - 2012 Red Hat, Inc. + */ + +#include "config.h" + +#include <string.h> +#include <gio/gio.h> +#include <glib/gi18n-lib.h> +#include <stdlib.h> +#include <stdio.h> +#include <nm-utils.h> +#include "nm-dbus-interface.h" +#include "nm-object.h" +#include "nm-object-cache.h" +#include "nm-object-private.h" +#include "nm-glib-compat.h" +#include "nm-dbus-helpers.h" +#include "nm-client.h" + +static gboolean debug = FALSE; +#define dbgmsg(f,...) if (G_UNLIKELY (debug)) { g_message (f, ## __VA_ARGS__ ); } + +static void nm_object_initable_iface_init (GInitableIface *iface); +static void nm_object_async_initable_iface_init (GAsyncInitableIface *iface); + +typedef struct { + NMObjectDecideTypeFunc type_func; + char *interface; + char *property; +} NMObjectTypeFuncData; + +static GHashTable *type_funcs; + +typedef struct { + GSList *interfaces; +} NMObjectClassPrivate; + +#define NM_OBJECT_CLASS_GET_PRIVATE(k) (G_TYPE_CLASS_GET_PRIVATE ((k), NM_TYPE_OBJECT, NMObjectClassPrivate)) + +G_DEFINE_ABSTRACT_TYPE_WITH_CODE (NMObject, nm_object, G_TYPE_OBJECT, + type_funcs = g_hash_table_new (NULL, NULL); + g_type_add_class_private (g_define_type_id, sizeof (NMObjectClassPrivate)); + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_object_initable_iface_init); + G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_object_async_initable_iface_init); + ) + +#define NM_OBJECT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_OBJECT, NMObjectPrivate)) + +typedef struct { + PropertyMarshalFunc func; + GType object_type; + gpointer field; + const char *signal_prefix; +} PropertyInfo; + +static void reload_complete (NMObject *object, gboolean emit_now); +static gboolean demarshal_generic (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field); + +typedef struct { + GDBusConnection *connection; + gboolean nm_running; + + char *path; + GHashTable *proxies; + GDBusProxy *properties_proxy; + GSList *property_tables; + NMObject *parent; + gboolean suppress_property_updates; + + GSList *notify_items; + guint32 notify_id; + + GSList *reload_results; + guint reload_remaining; + GError *reload_error; +} NMObjectPrivate; + +enum { + PROP_0, + PROP_PATH, + PROP_DBUS_CONNECTION, + PROP_NM_RUNNING, + + LAST_PROP +}; + +/** + * _nm_object_class_add_interface: + * @object_class: an #NMObjectClass + * @interface: a D-Bus interface name + * + * Registers that @object_class implements @interface. A proxy for that + * interface will automatically be created at construction time, and can + * be retrieved with _nm_object_get_proxy(). + */ +void +_nm_object_class_add_interface (NMObjectClass *object_class, + const char *interface) +{ + NMObjectClassPrivate *cpriv; + + g_return_if_fail (NM_IS_OBJECT_CLASS (object_class)); + g_return_if_fail (interface); + + cpriv = NM_OBJECT_CLASS_GET_PRIVATE (object_class); + + g_return_if_fail (g_slist_find_custom (cpriv->interfaces, interface, (GCompareFunc) g_strcmp0) == NULL); + + cpriv->interfaces = g_slist_prepend (cpriv->interfaces, g_strdup (interface)); +} + +/** + * nm_object_get_path: + * @object: a #NMObject + * + * Gets the DBus path of the #NMObject. + * + * Returns: the object's path. This is the internal string used by the + * device, and must not be modified. + **/ +const char * +nm_object_get_path (NMObject *object) +{ + g_return_val_if_fail (NM_IS_OBJECT (object), NULL); + + return NM_OBJECT_GET_PRIVATE (object)->path; +} + +/** + * _nm_object_get_proxy: + * @object: an #NMObject + * @interface: a D-Bus interface implemented by @object + * + * Gets the D-Bus proxy for @interface on @object. + * + * Returns: (transfer none): a D-Bus proxy + */ +GDBusProxy * +_nm_object_get_proxy (NMObject *object, + const char *interface) +{ + GDBusProxy *proxy; + + g_return_val_if_fail (NM_IS_OBJECT (object), NULL); + + proxy = g_hash_table_lookup (NM_OBJECT_GET_PRIVATE (object)->proxies, interface); + g_return_val_if_fail (proxy != NULL, NULL); + return proxy; +} + +typedef enum { + NOTIFY_SIGNAL_PENDING_NONE, + NOTIFY_SIGNAL_PENDING_ADDED, + NOTIFY_SIGNAL_PENDING_REMOVED, + NOTIFY_SIGNAL_PENDING_ADDED_REMOVED, +} NotifySignalPending; + +typedef struct { + const char *property; + const char *signal_prefix; + NotifySignalPending pending; + NMObject *changed; +} NotifyItem; + +static void +notify_item_free (NotifyItem *item) +{ + g_clear_object (&item->changed); + g_slice_free (NotifyItem, item); +} + +static gboolean +deferred_notify_cb (gpointer data) +{ + NMObject *object = NM_OBJECT (data); + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); + NMObjectClass *object_class = NM_OBJECT_GET_CLASS (object); + GSList *props, *iter; + + priv->notify_id = 0; + + /* Wait until all reloads are done before notifying */ + if (priv->reload_remaining) + return G_SOURCE_REMOVE; + + /* Clear priv->notify_items early so that an NMObject subclass that + * listens to property changes can queue up other property changes + * during the g_object_notify() call separately from the property + * list we're iterating. + */ + props = g_slist_reverse (priv->notify_items); + priv->notify_items = NULL; + + g_object_ref (object); + + /* Emit added/removed signals first since some of our internal objects + * use the added/removed signals for new object processing. + */ + for (iter = props; iter; iter = g_slist_next (iter)) { + NotifyItem *item = iter->data; + char buf[50]; + gint ret = 0; + + switch (item->pending) { + case NOTIFY_SIGNAL_PENDING_ADDED: + ret = g_snprintf (buf, sizeof (buf), "%s-added", item->signal_prefix); + break; + case NOTIFY_SIGNAL_PENDING_REMOVED: + ret = g_snprintf (buf, sizeof (buf), "%s-removed", item->signal_prefix); + break; + case NOTIFY_SIGNAL_PENDING_ADDED_REMOVED: + if (object_class->object_creation_failed) + object_class->object_creation_failed (object, nm_object_get_path (item->changed)); + break; + case NOTIFY_SIGNAL_PENDING_NONE: + default: + break; + } + if (ret > 0) { + g_assert (ret < sizeof (buf)); + g_signal_emit_by_name (object, buf, item->changed); + } + } + + /* Emit property change notifications second */ + for (iter = props; iter; iter = g_slist_next (iter)) { + NotifyItem *item = iter->data; + + if (item->property) + g_object_notify (G_OBJECT (object), item->property); + } + + g_object_unref (object); + + g_slist_free_full (props, (GDestroyNotify) notify_item_free); + return G_SOURCE_REMOVE; +} + +static void +_nm_object_defer_notify (NMObject *object) +{ + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); + + if (!priv->notify_id) + priv->notify_id = g_idle_add_full (G_PRIORITY_LOW, deferred_notify_cb, object, NULL); +} + +static void +_nm_object_queue_notify_full (NMObject *object, + const char *property, + const char *signal_prefix, + gboolean added, + NMObject *changed) +{ + NMObjectPrivate *priv; + NotifyItem *item; + GSList *iter; + + g_return_if_fail (NM_IS_OBJECT (object)); + g_return_if_fail (!signal_prefix != !property); + g_return_if_fail (!signal_prefix == !changed); + + priv = NM_OBJECT_GET_PRIVATE (object); + _nm_object_defer_notify (object); + + property = g_intern_string (property); + signal_prefix = g_intern_string (signal_prefix); + for (iter = priv->notify_items; iter; iter = g_slist_next (iter)) { + item = iter->data; + + if (property && (property == item->property)) + return; + + /* Collapse signals for the same object (such as "added->removed") to + * ensure we don't emit signals when their sum should have no effect. + * The "added->removed->removed" sequence requires special handling, + * hence the addition of the ADDED_REMOVED state to ensure that no + * signal is emitted in this case: + * + * Without the ADDED_REMOVED state: + * NONE + added -> ADDED + * ADDED + removed -> NONE + * NONE + removed -> REMOVED (would emit 'removed' signal) + * + * With the ADDED_REMOVED state: + * NONE | ADDED_REMOVED + added -> ADDED + * ADDED + removed -> ADDED_REMOVED + * ADDED_REMOVED + removed -> ADDED_REMOVED (emits no signal) + */ + if (signal_prefix && (changed == item->changed) && (item->signal_prefix == signal_prefix)) { + switch (item->pending) { + case NOTIFY_SIGNAL_PENDING_ADDED: + if (!added) + item->pending = NOTIFY_SIGNAL_PENDING_ADDED_REMOVED; + break; + case NOTIFY_SIGNAL_PENDING_REMOVED: + if (added) + item->pending = NOTIFY_SIGNAL_PENDING_NONE; + break; + case NOTIFY_SIGNAL_PENDING_ADDED_REMOVED: + if (added) + item->pending = NOTIFY_SIGNAL_PENDING_ADDED; + break; + case NOTIFY_SIGNAL_PENDING_NONE: + item->pending = added ? NOTIFY_SIGNAL_PENDING_ADDED : NOTIFY_SIGNAL_PENDING_REMOVED; + break; + default: + g_assert_not_reached (); + } + return; + } + } + + item = g_slice_new0 (NotifyItem); + item->property = property; + if (signal_prefix) { + item->signal_prefix = signal_prefix; + item->pending = added ? NOTIFY_SIGNAL_PENDING_ADDED : NOTIFY_SIGNAL_PENDING_REMOVED; + item->changed = changed ? g_object_ref (changed) : NULL; + } + priv->notify_items = g_slist_prepend (priv->notify_items, item); +} + +void +_nm_object_queue_notify (NMObject *object, const char *property) +{ + _nm_object_queue_notify_full (object, property, NULL, FALSE, NULL); +} + +void +_nm_object_register_type_func (GType base_type, + NMObjectDecideTypeFunc type_func, + const char *interface, + const char *property) +{ + NMObjectTypeFuncData *type_data; + + g_return_if_fail (type_func != NULL); + g_return_if_fail (interface != NULL); + g_return_if_fail (property != NULL); + + type_data = g_slice_new (NMObjectTypeFuncData); + type_data->type_func = type_func; + type_data->interface = g_strdup (interface); + type_data->property = g_strdup (property); + + g_hash_table_insert (type_funcs, + GSIZE_TO_POINTER (base_type), + type_data); +} + +static GObject * +_nm_object_create (GType type, GDBusConnection *connection, const char *path) +{ + NMObjectTypeFuncData *type_data; + GObject *object; + GError *error = NULL; + + type_data = g_hash_table_lookup (type_funcs, GSIZE_TO_POINTER (type)); + if (type_data) { + GDBusProxy *proxy; + GVariant *ret, *value; + + proxy = _nm_dbus_new_proxy_for_connection (connection, path, + DBUS_INTERFACE_PROPERTIES, + NULL, &error); + if (!proxy) { + g_warning ("Could not create proxy for %s: %s.", path, error->message); + g_error_free (error); + return NULL; + } + + ret = g_dbus_proxy_call_sync (proxy, + "Get", + g_variant_new ("(ss)", + type_data->interface, + type_data->property), + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, &error); + g_object_unref (proxy); + if (!ret) { + dbgmsg ("Could not fetch property '%s' of interface '%s' on %s: %s\n", + type_data->property, type_data->interface, path, error->message); + g_error_free (error); + return NULL; + } + + g_variant_get (ret, "(v)", &value); + type = type_data->type_func (value); + g_variant_unref (value); + g_variant_unref (ret); + } + + if (type == G_TYPE_INVALID) { + dbgmsg ("Could not create object for %s: unknown object type", path); + return NULL; + } + + object = g_object_new (type, + NM_OBJECT_PATH, path, + NM_OBJECT_DBUS_CONNECTION, connection, + NULL); + /* Cache the object before initializing it (and in particular, loading its + * property values); this is necessary to make circular references work (eg, + * when creating an NMActiveConnection, it will create an NMDevice which + * will in turn try to create the parent NMActiveConnection). Since we don't + * support multi-threaded use, we know that we will have inited the object + * before any external code sees it. + */ + _nm_object_cache_add (NM_OBJECT (object)); + if (!g_initable_init (G_INITABLE (object), NULL, &error)) { + dbgmsg ("Could not create object for %s: %s", path, error->message); + g_error_free (error); + g_clear_object (&object); + } + + return object; +} + +typedef void (*NMObjectCreateCallbackFunc) (GObject *, const char *, gpointer); +typedef struct { + char *path; + NMObjectCreateCallbackFunc callback; + gpointer user_data; + NMObjectTypeFuncData *type_data; + GDBusConnection *connection; +} NMObjectTypeAsyncData; + +static void +create_async_complete (GObject *object, NMObjectTypeAsyncData *async_data) +{ + async_data->callback (object, async_data->path, async_data->user_data); + + g_free (async_data->path); + g_object_unref (async_data->connection); + g_slice_free (NMObjectTypeAsyncData, async_data); +} + +static void +create_async_inited (GObject *object, GAsyncResult *result, gpointer user_data) +{ + NMObjectTypeAsyncData *async_data = user_data; + GError *error = NULL; + + if (!g_async_initable_init_finish (G_ASYNC_INITABLE (object), result, &error)) { + dbgmsg ("Could not create object for %s: %s", + nm_object_get_path (NM_OBJECT (object)), + error->message); + g_error_free (error); + g_clear_object (&object); + } + + create_async_complete (object, async_data); +} + +static void +create_async_got_type (NMObjectTypeAsyncData *async_data, GType type) +{ + GObject *object; + + /* Ensure we don't have the object already; we may get multiple type + * requests for the same object if there are multiple properties on + * other objects that refer to the object at this path. One of those + * other requests may have already completed. + */ + object = (GObject *) _nm_object_cache_get (async_data->path); + if (object) { + create_async_complete (object, async_data); + return; + } + + if (type == G_TYPE_INVALID) { + /* Don't know how to create this object */ + create_async_complete (NULL, async_data); + return; + } + + object = g_object_new (type, + NM_OBJECT_PATH, async_data->path, + NM_OBJECT_DBUS_CONNECTION, async_data->connection, + NULL); + _nm_object_cache_add (NM_OBJECT (object)); + g_async_initable_init_async (G_ASYNC_INITABLE (object), G_PRIORITY_DEFAULT, + NULL, create_async_inited, async_data); +} + +static void +create_async_got_property (GObject *proxy, GAsyncResult *result, gpointer user_data) +{ + NMObjectTypeAsyncData *async_data = user_data; + NMObjectTypeFuncData *type_data = async_data->type_data; + GVariant *ret, *value; + GError *error = NULL; + GType type; + + ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, &error); + if (ret) { + g_variant_get (ret, "(v)", &value); + type = type_data->type_func (value); + g_variant_unref (value); + g_variant_unref (ret); + } else { + dbgmsg ("Could not fetch property '%s' of interface '%s' on %s: %s\n", + type_data->property, type_data->interface, async_data->path, + error->message); + g_clear_error (&error); + type = G_TYPE_INVALID; + } + + create_async_got_type (async_data, type); +} + +static void +create_async_got_proxy (GObject *object, GAsyncResult *result, gpointer user_data) +{ + NMObjectTypeAsyncData *async_data = user_data; + GDBusProxy *proxy; + GError *error = NULL; + + proxy = _nm_dbus_new_proxy_for_connection_finish (result, &error); + if (!proxy) { + g_warning ("Could not create proxy for %s: %s.", async_data->path, error->message); + g_error_free (error); + create_async_complete (NULL, async_data); + return; + } + + g_dbus_proxy_call (proxy, + "Get", + g_variant_new ("(ss)", + async_data->type_data->interface, + async_data->type_data->property), + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, + create_async_got_property, async_data); +} + +static void +_nm_object_create_async (GType type, GDBusConnection *connection, const char *path, + NMObjectCreateCallbackFunc callback, gpointer user_data) +{ + NMObjectTypeAsyncData *async_data; + + async_data = g_slice_new (NMObjectTypeAsyncData); + async_data->path = g_strdup (path); + async_data->callback = callback; + async_data->user_data = user_data; + async_data->connection = g_object_ref (connection); + + async_data->type_data = g_hash_table_lookup (type_funcs, GSIZE_TO_POINTER (type)); + if (async_data->type_data) { + _nm_dbus_new_proxy_for_connection_async (connection, path, + DBUS_INTERFACE_PROPERTIES, + NULL, + create_async_got_proxy, async_data); + return; + } + + create_async_got_type (async_data, type); +} + +/* Stolen from dbus-glib */ +static char* +wincaps_to_dash (const char *caps) +{ + const char *p; + GString *str; + + str = g_string_new (NULL); + p = caps; + while (*p) { + if (g_ascii_isupper (*p)) { + if (str->len > 0 && (str->len < 2 || str->str[str->len-2] != '-')) + g_string_append_c (str, '-'); + g_string_append_c (str, g_ascii_tolower (*p)); + } else + g_string_append_c (str, *p); + ++p; + } + + return g_string_free (str, FALSE); +} + +/* Adds object to array if it's not already there */ +static void +add_to_object_array_unique (GPtrArray *array, GObject *obj) +{ + guint i; + + g_return_if_fail (array != NULL); + + if (obj != NULL) { + for (i = 0; i < array->len; i++) { + if (g_ptr_array_index (array, i) == obj) { + g_object_unref (obj); + return; + } + } + g_ptr_array_add (array, obj); + } +} + +typedef struct { + NMObject *self; + PropertyInfo *pi; + + GObject **objects; + int length, remaining; + + gboolean array; + const char *property_name; +} ObjectCreatedData; + +/* Places items from 'needles' that are not in 'haystack' into 'diff' */ +static void +array_diff (GPtrArray *needles, GPtrArray *haystack, GPtrArray *diff) +{ + guint i, j; + GObject *obj; + + g_assert (needles); + g_assert (haystack); + g_assert (diff); + + for (i = 0; i < needles->len; i++) { + obj = g_ptr_array_index (needles, i); + + for (j = 0; j < haystack->len; j++) { + if (g_ptr_array_index (haystack, j) == obj) + break; + } + + if (j == haystack->len) + g_ptr_array_add (diff, obj); + } +} + +static void +queue_added_removed_signal (NMObject *self, + const char *signal_prefix, + NMObject *changed, + gboolean added) +{ + _nm_object_queue_notify_full (self, NULL, signal_prefix, added, changed); +} + +static void +object_property_complete (ObjectCreatedData *odata) +{ + NMObject *self = odata->self; + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self); + PropertyInfo *pi = odata->pi; + gboolean different = TRUE; + + if (odata->array) { + GPtrArray *old = *((GPtrArray **) pi->field); + GPtrArray *new; + int i; + + /* Build up new array */ + new = g_ptr_array_new_full (odata->length, g_object_unref); + for (i = 0; i < odata->length; i++) + add_to_object_array_unique (new, odata->objects[i]); + + if (pi->signal_prefix) { + GPtrArray *added = g_ptr_array_sized_new (3); + GPtrArray *removed = g_ptr_array_sized_new (3); + + if (old) { + /* Find objects in 'old' that do not exist in 'new' */ + array_diff (old, new, removed); + + /* Find objects in 'new' that do not exist in old */ + array_diff (new, old, added); + } else { + for (i = 0; i < new->len; i++) + g_ptr_array_add (added, g_ptr_array_index (new, i)); + } + + *((GPtrArray **) pi->field) = new; + + /* Emit added & removed */ + for (i = 0; i < removed->len; i++) { + queue_added_removed_signal (self, + pi->signal_prefix, + g_ptr_array_index (removed, i), + FALSE); + } + + for (i = 0; i < added->len; i++) { + queue_added_removed_signal (self, + pi->signal_prefix, + g_ptr_array_index (added, i), + TRUE); + } + + different = removed->len || added->len; + g_ptr_array_unref (added); + g_ptr_array_unref (removed); + } else { + /* No added/removed signals to send, just replace the property with + * the new values. + */ + *((GPtrArray **) pi->field) = new; + different = TRUE; + } + + /* Free old array last since it will release references, thus freeing + * any objects in the 'removed' array. + */ + if (old) + g_ptr_array_unref (old); + } else { + GObject **obj_p = pi->field; + + different = (*obj_p != odata->objects[0]); + if (*obj_p) + g_object_unref (*obj_p); + *obj_p = odata->objects[0]; + } + + if (different && odata->property_name) + _nm_object_queue_notify (self, odata->property_name); + + if (--priv->reload_remaining == 0) + reload_complete (self, FALSE); + + g_object_unref (self); + g_free (odata->objects); + g_slice_free (ObjectCreatedData, odata); +} + +static void +object_created (GObject *obj, const char *path, gpointer user_data) +{ + ObjectCreatedData *odata = user_data; + + /* We assume that on error, the creator_func printed something */ + + if (obj == NULL && g_strcmp0 (path, "/") != 0 ) { + NMObjectClass *object_class = NM_OBJECT_GET_CLASS (odata->self); + + if (object_class->object_creation_failed) + object_class->object_creation_failed (odata->self, path); + } + + odata->objects[--odata->remaining] = obj; + if (!odata->remaining) + object_property_complete (odata); +} + +static gboolean +handle_object_property (NMObject *self, const char *property_name, GVariant *value, + PropertyInfo *pi, gboolean synchronously) +{ + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self); + GObject *obj; + const char *path; + ObjectCreatedData *odata; + + odata = g_slice_new (ObjectCreatedData); + odata->self = g_object_ref (self); + odata->pi = pi; + odata->objects = g_new (GObject *, 1); + odata->length = odata->remaining = 1; + odata->array = FALSE; + odata->property_name = property_name; + + priv->reload_remaining++; + + path = g_variant_get_string (value, NULL); + + if (!strcmp (path, "/")) { + object_created (NULL, path, odata); + return TRUE; + } + + obj = G_OBJECT (_nm_object_cache_get (path)); + if (obj) { + object_created (obj, path, odata); + return TRUE; + } else if (synchronously) { + obj = _nm_object_create (pi->object_type, priv->connection, path); + object_created (obj, path, odata); + return obj != NULL; + } else { + _nm_object_create_async (pi->object_type, priv->connection, path, + object_created, odata); + /* Assume success */ + return TRUE; + } +} + +static gboolean +handle_object_array_property (NMObject *self, const char *property_name, GVariant *value, + PropertyInfo *pi, gboolean synchronously) +{ + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self); + GObject *obj; + GVariantIter iter; + gsize npaths; + GPtrArray **array = pi->field; + const char *path; + ObjectCreatedData *odata; + + npaths = g_variant_n_children (value); + + odata = g_slice_new (ObjectCreatedData); + odata->self = g_object_ref (self); + odata->pi = pi; + odata->objects = g_new0 (GObject *, npaths); + odata->length = odata->remaining = npaths; + odata->array = TRUE; + odata->property_name = property_name; + + priv->reload_remaining++; + + if (npaths == 0) { + object_property_complete (odata); + return TRUE; + } + + g_variant_iter_init (&iter, value); + while (g_variant_iter_next (&iter, "&o", &path)) { + if (!strcmp (path, "/")) { + /* FIXME: can't happen? */ + continue; + } + + obj = G_OBJECT (_nm_object_cache_get (path)); + if (obj) { + object_created (obj, path, odata); + } else if (synchronously) { + obj = _nm_object_create (pi->object_type, priv->connection, path); + object_created (obj, path, odata); + } else { + _nm_object_create_async (pi->object_type, priv->connection, path, + object_created, odata); + } + } + + if (!synchronously) { + /* Assume success */ + return TRUE; + } + + return *array && ((*array)->len == npaths); +} + +static void +handle_property_changed (NMObject *self, const char *dbus_name, + GVariant *value, gboolean synchronously) +{ + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self); + char *prop_name; + PropertyInfo *pi; + GParamSpec *pspec; + gboolean success = FALSE, found = FALSE; + GSList *iter; + + prop_name = wincaps_to_dash (dbus_name); + + /* Iterate through the object and its parents to find the property */ + for (iter = priv->property_tables; iter; iter = g_slist_next (iter)) { + pi = g_hash_table_lookup ((GHashTable *) iter->data, prop_name); + if (pi) { + if (!pi->field) { + /* We know about this property but aren't tracking changes on it. */ + goto out; + } + + found = TRUE; + break; + } + } + + if (!found) { + dbgmsg ("Property '%s' unhandled.", prop_name); + goto out; + } + + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (self)), prop_name); + if (!pspec && pi->func == demarshal_generic) { + dbgmsg ("%s: property '%s' changed but wasn't defined by object type %s.", + __func__, + prop_name, + G_OBJECT_TYPE_NAME (self)); + goto out; + } + + if (G_UNLIKELY (debug)) { + char *s; + s = g_variant_print (value, FALSE); + dbgmsg ("PC: (%p) %s:%s => '%s' (%s%s%s)", + self, G_OBJECT_TYPE_NAME (self), + prop_name, + s, + g_variant_get_type_string (value), + pi->object_type ? " / " : "", + pi->object_type ? g_type_name (pi->object_type) : ""); + g_free (s); + } + + if (pspec && pi->object_type) { + if (g_variant_is_of_type (value, G_VARIANT_TYPE_OBJECT_PATH)) + success = handle_object_property (self, pspec->name, value, pi, synchronously); + else if (g_variant_is_of_type (value, G_VARIANT_TYPE ("ao"))) + success = handle_object_array_property (self, pspec->name, value, pi, synchronously); + else { + g_warn_if_reached (); + goto out; + } + } else + success = (*(pi->func)) (self, pspec, value, pi->field); + + if (!success) { + dbgmsg ("%s: failed to update property '%s' of object type %s.", + __func__, + prop_name, + G_OBJECT_TYPE_NAME (self)); + } + +out: + g_free (prop_name); +} + +static void +process_properties_changed (NMObject *self, GVariant *properties, gboolean synchronously) +{ + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self); + GVariantIter iter; + const char *name; + GVariant *value; + + if (priv->suppress_property_updates) + return; + + g_variant_iter_init (&iter, properties); + while (g_variant_iter_next (&iter, "{&sv}", &name, &value)) + handle_property_changed (self, name, value, synchronously); +} + +static void +property_proxy_signal (GDBusProxy *proxy, + const char *sender_name, + const char *signal_name, + GVariant *parameters, + gpointer user_data) +{ + GVariant *properties; + + if (strcmp (signal_name, "PropertiesChanged") != 0) + return; + + g_variant_get (parameters, "(@a{sv})", &properties); + process_properties_changed (NM_OBJECT (user_data), properties, FALSE); + g_variant_unref (properties); +} + +#define HANDLE_TYPE(vtype, ctype, getter) \ + G_STMT_START { \ + if (g_variant_is_of_type (value, vtype)) { \ + ctype *param = (ctype *) field; \ + *param = getter (value); \ + } else { \ + success = FALSE; \ + goto done; \ + } \ + } G_STMT_END + +static gboolean +demarshal_generic (NMObject *object, + GParamSpec *pspec, + GVariant *value, + gpointer field) +{ + gboolean success = TRUE; + + if (pspec->value_type == G_TYPE_STRING) { + if (g_variant_is_of_type (value, G_VARIANT_TYPE_STRING)) { + char **param = (char **) field; + g_free (*param); + *param = g_variant_dup_string (value, NULL); + } else if (g_variant_is_of_type (value, G_VARIANT_TYPE_OBJECT_PATH)) { + char **param = (char **) field; + g_free (*param); + *param = g_variant_dup_string (value, NULL); + /* Handle "NULL" object paths */ + if (g_strcmp0 (*param, "/") == 0) { + g_free (*param); + *param = NULL; + } + } else { + success = FALSE; + goto done; + } + } else if (pspec->value_type == G_TYPE_STRV) { + char ***param = (char ***)field; + if (*param) + g_strfreev (*param); + *param = g_variant_dup_strv (value, NULL); + } else if (pspec->value_type == G_TYPE_BYTES) { + GBytes **param = (GBytes **)field; + gconstpointer val; + gsize length; + + if (*param) + g_bytes_unref (*param); + val = g_variant_get_fixed_array (value, &length, 1); + if (length) + *param = g_bytes_new (val, length); + else + *param = NULL; + } else if (G_IS_PARAM_SPEC_ENUM (pspec)) { + int *param = (int *) field; + + if (g_variant_is_of_type (value, G_VARIANT_TYPE_INT32)) + *param = g_variant_get_int32 (value); + else if (g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32)) + *param = g_variant_get_uint32 (value); + else { + success = FALSE; + goto done; + } + } else if (G_IS_PARAM_SPEC_FLAGS (pspec)) { + guint *param = (guint *) field; + + if (g_variant_is_of_type (value, G_VARIANT_TYPE_INT32)) + *param = g_variant_get_int32 (value); + else if (g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32)) + *param = g_variant_get_uint32 (value); + else { + success = FALSE; + goto done; + } + } else if (pspec->value_type == G_TYPE_BOOLEAN) + HANDLE_TYPE (G_VARIANT_TYPE_BOOLEAN, gboolean, g_variant_get_boolean); + else if (pspec->value_type == G_TYPE_UCHAR) + HANDLE_TYPE (G_VARIANT_TYPE_BYTE, guchar, g_variant_get_byte); + else if (pspec->value_type == G_TYPE_DOUBLE) + HANDLE_TYPE (G_VARIANT_TYPE_DOUBLE, gdouble, g_variant_get_double); + else if (pspec->value_type == G_TYPE_INT) + HANDLE_TYPE (G_VARIANT_TYPE_INT32, gint, g_variant_get_int32); + else if (pspec->value_type == G_TYPE_UINT) + HANDLE_TYPE (G_VARIANT_TYPE_UINT32, guint, g_variant_get_uint32); + else if (pspec->value_type == G_TYPE_INT64) + HANDLE_TYPE (G_VARIANT_TYPE_INT64, gint, g_variant_get_int64); + else if (pspec->value_type == G_TYPE_UINT64) + HANDLE_TYPE (G_VARIANT_TYPE_UINT64, guint, g_variant_get_uint64); + else if (pspec->value_type == G_TYPE_LONG) + HANDLE_TYPE (G_VARIANT_TYPE_INT64, glong, g_variant_get_int64); + else if (pspec->value_type == G_TYPE_ULONG) + HANDLE_TYPE (G_VARIANT_TYPE_UINT64, gulong, g_variant_get_uint64); + else { + g_warning ("%s: %s:%s unhandled type %s.", + __func__, + G_OBJECT_TYPE_NAME (object), + pspec->name, + g_type_name (pspec->value_type)); + success = FALSE; + } + +done: + if (success) { + _nm_object_queue_notify (object, pspec->name); + } else { + dbgmsg ("%s: %s:%s (type %s) couldn't be set from D-Bus type %s.", + __func__, G_OBJECT_TYPE_NAME (object), pspec->name, + g_type_name (pspec->value_type), g_variant_get_type_string (value)); + } + return success; +} + +void +_nm_object_register_properties (NMObject *object, + const char *interface, + const NMPropertiesInfo *info) +{ + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); + GDBusProxy *proxy; + static gsize dval = 0; + const char *debugstr; + NMPropertiesInfo *tmp; + GHashTable *instance; + + g_return_if_fail (NM_IS_OBJECT (object)); + g_return_if_fail (interface != NULL); + g_return_if_fail (info != NULL); + + if (g_once_init_enter (&dval)) { + debugstr = getenv ("LIBNM_GLIB_DEBUG"); + if (debugstr && strstr (debugstr, "properties-changed")) + debug = TRUE; + g_once_init_leave (&dval, 1); + } + + proxy = _nm_object_get_proxy (object, interface); + g_return_if_fail (proxy != NULL); + + g_signal_connect (proxy, "g-signal", + G_CALLBACK (property_proxy_signal), object); + + instance = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + priv->property_tables = g_slist_prepend (priv->property_tables, instance); + + for (tmp = (NMPropertiesInfo *) info; tmp->name; tmp++) { + PropertyInfo *pi; + + if (!tmp->name || (tmp->func && !tmp->field)) { + g_warning ("%s: missing field in NMPropertiesInfo", __func__); + continue; + } + + pi = g_malloc0 (sizeof (PropertyInfo)); + pi->func = tmp->func ? tmp->func : demarshal_generic; + pi->object_type = tmp->object_type; + pi->field = tmp->field; + pi->signal_prefix = tmp->signal_prefix; + g_hash_table_insert (instance, g_strdup (tmp->name), pi); + } +} + +static gboolean +_nm_object_reload_properties (NMObject *object, GError **error) +{ + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); + GVariant *ret, *props; + GHashTableIter iter; + const char *interface; + GDBusProxy *proxy; + + if (!g_hash_table_size (priv->proxies) || !priv->nm_running) + return TRUE; + + priv->reload_remaining++; + + g_hash_table_iter_init (&iter, priv->proxies); + while (g_hash_table_iter_next (&iter, (gpointer *) &interface, (gpointer *) &proxy)) { + ret = g_dbus_proxy_call_sync (priv->properties_proxy, + "GetAll", + g_variant_new ("(s)", interface), + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, error); + if (!ret) { + if (error && *error) + g_dbus_error_strip_remote_error (*error); + return FALSE; + } + + g_variant_get (ret, "(@a{sv})", &props); + process_properties_changed (object, props, TRUE); + g_variant_unref (props); + g_variant_unref (ret); + } + + if (--priv->reload_remaining == 0) + reload_complete (object, TRUE); + + return TRUE; +} + +void +_nm_object_suppress_property_updates (NMObject *object, gboolean suppress) +{ + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); + + priv->suppress_property_updates = suppress; +} + + +void +_nm_object_reload_property (NMObject *object, + const char *interface, + const char *prop_name) +{ + GVariant *ret, *value; + GError *err = NULL; + + g_return_if_fail (NM_IS_OBJECT (object)); + g_return_if_fail (interface != NULL); + g_return_if_fail (prop_name != NULL); + + if (!NM_OBJECT_GET_PRIVATE (object)->nm_running) + return; + + ret = g_dbus_proxy_call_sync (NM_OBJECT_GET_PRIVATE (object)->properties_proxy, + "Get", + g_variant_new ("(ss)", interface, prop_name), + G_DBUS_CALL_FLAGS_NONE, 15000, + NULL, &err); + if (!ret) { + dbgmsg ("%s: Error getting '%s' for %s: (%d) %s\n", + __func__, + prop_name, + nm_object_get_path (object), + err->code, + err->message); + g_clear_error (&err); + return; + } + + g_variant_get (ret, "(v)", &value); + handle_property_changed (object, prop_name, value, TRUE); + g_variant_unref (value); + g_variant_unref (ret); +} + +void +_nm_object_set_property (NMObject *object, + const char *interface, + const char *prop_name, + const char *format_string, + ...) +{ + GVariant *val, *ret; + va_list ap; + + g_return_if_fail (NM_IS_OBJECT (object)); + g_return_if_fail (interface != NULL); + g_return_if_fail (prop_name != NULL); + g_return_if_fail (format_string != NULL); + + if (!NM_OBJECT_GET_PRIVATE (object)->nm_running) + return; + + va_start (ap, format_string); + val = g_variant_new_va (format_string, NULL, &ap); + va_end (ap); + g_return_if_fail (val != NULL); + + ret = g_dbus_proxy_call_sync (NM_OBJECT_GET_PRIVATE (object)->properties_proxy, + "Set", + g_variant_new ("(ssv)", interface, prop_name, val), + G_DBUS_CALL_FLAGS_NONE, 2000, + NULL, NULL); + /* Ignore errors. */ + if (ret) + g_variant_unref (ret); +} + +static void +reload_complete (NMObject *object, gboolean emit_now) +{ + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); + GSimpleAsyncResult *simple; + GSList *results, *iter; + GError *error; + + if (emit_now) { + if (priv->notify_id) { + g_source_remove (priv->notify_id); + priv->notify_id = 0; + } + deferred_notify_cb (object); + } else + _nm_object_defer_notify (object); + + results = priv->reload_results; + priv->reload_results = NULL; + error = priv->reload_error; + priv->reload_error = NULL; + + for (iter = results; iter; iter = iter->next) { + simple = iter->data; + + if (error) + g_simple_async_result_set_from_error (simple, error); + else + g_simple_async_result_set_op_res_gboolean (simple, TRUE); + + g_simple_async_result_complete (simple); + g_object_unref (simple); + } + g_slist_free (results); + g_clear_error (&error); +} + +static void +reload_got_properties (GObject *proxy, + GAsyncResult *result, + gpointer user_data) +{ + NMObject *object = user_data; + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); + GVariant *ret, *props; + GError *error = NULL; + + ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, &error); + if (ret) { + g_variant_get (ret, "(@a{sv})", &props); + process_properties_changed (object, props, FALSE); + g_variant_unref (props); + g_variant_unref (ret); + } else { + g_dbus_error_strip_remote_error (error); + if (priv->reload_error) + g_error_free (error); + else + priv->reload_error = error; + } + + if (--priv->reload_remaining == 0) + reload_complete (object, FALSE); +} + +void +_nm_object_reload_properties_async (NMObject *object, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); + GSimpleAsyncResult *simple; + GHashTableIter iter; + const char *interface; + GDBusProxy *proxy; + + simple = g_simple_async_result_new (G_OBJECT (object), callback, + user_data, _nm_object_reload_properties_async); + + if (!g_hash_table_size (priv->proxies) || !priv->nm_running) { + g_simple_async_result_complete_in_idle (simple); + g_object_unref (simple); + return; + } + + priv->reload_results = g_slist_prepend (priv->reload_results, simple); + + /* If there was already a reload happening, we don't need to + * re-read the properties again, we just need to wait for the + * existing reload to finish. + */ + if (priv->reload_results->next) + return; + + g_hash_table_iter_init (&iter, priv->proxies); + while (g_hash_table_iter_next (&iter, (gpointer *) &interface, (gpointer *) &proxy)) { + priv->reload_remaining++; + g_dbus_proxy_call (priv->properties_proxy, + "GetAll", + g_variant_new ("(s)", interface), + G_DBUS_CALL_FLAGS_NONE, -1, + cancellable, + reload_got_properties, object); + } +} + +gboolean +_nm_object_reload_properties_finish (NMObject *object, GAsyncResult *result, GError **error) +{ + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); + GSimpleAsyncResult *simple; + + g_return_val_if_fail (NM_IS_OBJECT (object), FALSE); + g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (object), _nm_object_reload_properties_async), FALSE); + + /* NM might have disappeared meanwhile. That would cause a NoReply error to be emitted, + * but we don't care if property updates were disabled. */ + if (priv->suppress_property_updates) + return TRUE; + + simple = G_SIMPLE_ASYNC_RESULT (result); + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + + return g_simple_async_result_get_op_res_gboolean (simple); +} + +gboolean +_nm_object_get_nm_running (NMObject *self) +{ + return NM_OBJECT_GET_PRIVATE (self)->nm_running; +} + +/**************************************************************/ + +static void +on_name_owner_changed (GObject *proxy, + GParamSpec *pspec, + gpointer user_data) +{ + NMObject *self = NM_OBJECT (user_data); + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self); + gboolean now_running; + char *owner; + + now_running = ((owner = g_dbus_proxy_get_name_owner (priv->properties_proxy)) != NULL); + g_free (owner); + if (now_running != priv->nm_running) { + priv->nm_running = now_running; + g_object_notify (G_OBJECT (self), NM_OBJECT_NM_RUNNING); + } +} + +static void +init_dbus (NMObject *object) +{ + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); + char *owner; + + if (_nm_dbus_is_connection_private (priv->connection)) + priv->nm_running = TRUE; + else { + priv->nm_running = ((owner = g_dbus_proxy_get_name_owner (priv->properties_proxy)) != NULL); + g_free (owner); + g_signal_connect (priv->properties_proxy, "notify::g-name-owner", + G_CALLBACK (on_name_owner_changed), object); + } +} + +static gboolean +init_sync (GInitable *initable, GCancellable *cancellable, GError **error) +{ + NMObject *self = NM_OBJECT (initable); + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self); + NMObjectClassPrivate *cpriv = NM_OBJECT_CLASS_GET_PRIVATE (NM_OBJECT_GET_CLASS (self)); + GSList *iter; + + if (!priv->path) { + g_set_error_literal (error, NM_CLIENT_ERROR, NM_CLIENT_ERROR_OBJECT_CREATION_FAILED, + _("Caller did not specify D-Bus path for object")); + return FALSE; + } + + if (!priv->connection) + priv->connection = _nm_dbus_new_connection (cancellable, error); + if (!priv->connection) + return FALSE; + + /* Create proxies */ + for (iter = cpriv->interfaces; iter; iter = iter->next) { + const char *interface = iter->data; + GDBusProxy *proxy; + + proxy = _nm_dbus_new_proxy_for_connection (priv->connection, priv->path, interface, + cancellable, error); + if (!proxy) + return FALSE; + g_hash_table_insert (priv->proxies, (char *) interface, proxy); + } + + priv->properties_proxy = _nm_dbus_new_proxy_for_connection (priv->connection, + priv->path, + DBUS_INTERFACE_PROPERTIES, + cancellable, error); + if (!priv->properties_proxy) + return FALSE; + + NM_OBJECT_GET_CLASS (self)->init_dbus (self); + + return _nm_object_reload_properties (self, error); +} + +/**************************************************************/ + +typedef struct { + NMObject *object; + GSimpleAsyncResult *simple; + GCancellable *cancellable; + int proxies_pending; + GError *error; +} NMObjectInitData; + +static void +init_async_complete (NMObjectInitData *init_data) +{ + if (init_data->error) + g_simple_async_result_take_error (init_data->simple, init_data->error); + else + g_simple_async_result_set_op_res_gboolean (init_data->simple, TRUE); + g_simple_async_result_complete (init_data->simple); + g_object_unref (init_data->simple); + g_clear_object (&init_data->cancellable); + g_slice_free (NMObjectInitData, init_data); +} + +static void +init_async_got_properties (GObject *object, GAsyncResult *result, gpointer user_data) +{ + NMObjectInitData *init_data = user_data; + + _nm_object_reload_properties_finish (NM_OBJECT (object), result, &init_data->error); + init_async_complete (init_data); +} + +static void +init_async_got_proxy (GObject *object, GAsyncResult *result, gpointer user_data) +{ + NMObjectInitData *init_data = user_data; + NMObject *self = init_data->object; + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self); + GDBusProxy *proxy; + + if (!init_data->error) { + proxy = _nm_dbus_new_proxy_for_connection_finish (result, &init_data->error); + if (proxy) { + const char *interface = g_dbus_proxy_get_interface_name (proxy); + + if (!strcmp (interface, DBUS_INTERFACE_PROPERTIES)) + priv->properties_proxy = proxy; + else + g_hash_table_insert (priv->proxies, (char *) interface, proxy); + } + } + + init_data->proxies_pending--; + if (init_data->proxies_pending) + return; + + if (init_data->error) { + init_async_complete (init_data); + return; + } + + NM_OBJECT_GET_CLASS (self)->init_dbus (self); + + _nm_object_reload_properties_async (init_data->object, init_data->cancellable, init_async_got_properties, init_data); +} + +static void +init_async_got_bus (GObject *object, GAsyncResult *result, gpointer user_data) +{ + NMObjectInitData *init_data = user_data; + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (init_data->object); + NMObjectClassPrivate *cpriv = NM_OBJECT_CLASS_GET_PRIVATE (NM_OBJECT_GET_CLASS (init_data->object)); + GSList *iter; + + priv->connection = _nm_dbus_new_connection_finish (result, &init_data->error); + if (!priv->connection) { + init_async_complete (init_data); + return; + } + + for (iter = cpriv->interfaces; iter; iter = iter->next) { + const char *interface = iter->data; + + _nm_dbus_new_proxy_for_connection_async (priv->connection, + priv->path, interface, + init_data->cancellable, + init_async_got_proxy, init_data); + init_data->proxies_pending++; + } + + _nm_dbus_new_proxy_for_connection_async (priv->connection, + priv->path, + DBUS_INTERFACE_PROPERTIES, + init_data->cancellable, + init_async_got_proxy, init_data); + init_data->proxies_pending++; +} + +static void +init_async (GAsyncInitable *initable, int io_priority, + GCancellable *cancellable, GAsyncReadyCallback callback, + gpointer user_data) +{ + NMObject *self = NM_OBJECT (initable); + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self); + NMObjectInitData *init_data; + + if (!priv->path) { + g_simple_async_report_error_in_idle (G_OBJECT (initable), + callback, user_data, + NM_CLIENT_ERROR, + NM_CLIENT_ERROR_OBJECT_CREATION_FAILED, + "%s", + _("Caller did not specify D-Bus path for object")); + return; + } + + init_data = g_slice_new0 (NMObjectInitData); + init_data->object = self; + init_data->simple = g_simple_async_result_new (G_OBJECT (initable), callback, user_data, init_async); + init_data->cancellable = cancellable ? g_object_ref (cancellable) : NULL; + + _nm_dbus_new_connection_async (cancellable, init_async_got_bus, init_data); +} + +static gboolean +init_finish (GAsyncInitable *initable, GAsyncResult *result, GError **error) +{ + GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); + + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + else + return TRUE; +} + +/**************************************************************/ + +static void +nm_object_initable_iface_init (GInitableIface *iface) +{ + iface->init = init_sync; +} + +static void +nm_object_async_initable_iface_init (GAsyncInitableIface *iface) +{ + iface->init_async = init_async; + iface->init_finish = init_finish; +} + +static void +nm_object_init (NMObject *object) +{ + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); + + priv->proxies = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref); +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_PATH: + /* Construct only */ + priv->path = g_value_dup_string (value); + break; + case PROP_DBUS_CONNECTION: + /* Construct only */ + priv->connection = g_value_dup_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_PATH: + g_value_set_string (value, priv->path); + break; + case PROP_DBUS_CONNECTION: + g_value_set_object (value, priv->connection); + break; + case PROP_NM_RUNNING: + g_value_set_boolean (value, priv->nm_running); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +dispose (GObject *object) +{ + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); + + if (priv->notify_id) { + g_source_remove (priv->notify_id); + priv->notify_id = 0; + } + + g_slist_free_full (priv->notify_items, (GDestroyNotify) notify_item_free); + priv->notify_items = NULL; + + g_clear_pointer (&priv->proxies, g_hash_table_unref); + g_clear_object (&priv->properties_proxy); + + g_clear_object (&priv->connection); + + G_OBJECT_CLASS (nm_object_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); + + g_slist_free_full (priv->property_tables, (GDestroyNotify) g_hash_table_destroy); + g_free (priv->path); + + G_OBJECT_CLASS (nm_object_parent_class)->finalize (object); +} + +static void +nm_object_class_init (NMObjectClass *nm_object_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (nm_object_class); + + g_type_class_add_private (nm_object_class, sizeof (NMObjectPrivate)); + + /* virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->dispose = dispose; + object_class->finalize = finalize; + + nm_object_class->init_dbus = init_dbus; + + /* Properties */ + + /** + * NMObject:path: + * + * The D-Bus object path. + **/ + g_object_class_install_property + (object_class, PROP_PATH, + g_param_spec_string (NM_OBJECT_PATH, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + /** + * NMObject:dbus-connection: (skip) + * + * The #GDBusConnection of the object. + **/ + g_object_class_install_property + (object_class, PROP_DBUS_CONNECTION, + g_param_spec_object (NM_OBJECT_DBUS_CONNECTION, "", "", + G_TYPE_DBUS_CONNECTION, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + /** + * NMObject:manager-running: (skip) + * + * Internal use only. + */ + g_object_class_install_property + (object_class, PROP_NM_RUNNING, + g_param_spec_boolean (NM_OBJECT_NM_RUNNING, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); +} + diff --git a/libnm/nm-object.h b/libnm/nm-object.h new file mode 100644 index 00000000..b42f160d --- /dev/null +++ b/libnm/nm-object.h @@ -0,0 +1,70 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2007 - 2008 Novell, Inc. + * Copyright 2007 - 2012 Red Hat, Inc. + */ + +#ifndef __NM_OBJECT_H__ +#define __NM_OBJECT_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include <nm-types.h> + +G_BEGIN_DECLS + +#define NM_TYPE_OBJECT (nm_object_get_type ()) +#define NM_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_OBJECT, NMObject)) +#define NM_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_OBJECT, NMObjectClass)) +#define NM_IS_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_OBJECT)) +#define NM_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_OBJECT)) +#define NM_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_OBJECT, NMObjectClass)) + +#define NM_OBJECT_PATH "path" +#define NM_OBJECT_DBUS_CONNECTION "dbus-connection" + +struct _NMObject { + GObject parent; +}; + +typedef struct { + GObjectClass parent; + + /* Methods */ + void (*init_dbus) (NMObject *object); + + /* The "object-creation-failed" method is PRIVATE for libnm and + * is not meant for any external usage. It indicates that an error + * occured during creation of an object. + */ + void (*object_creation_failed) (NMObject *master_object, + const char *failed_path); + + /*< private >*/ + gpointer padding[8]; +} NMObjectClass; + +GType nm_object_get_type (void); + +const char *nm_object_get_path (NMObject *object); + +G_END_DECLS + +#endif /* __NM_OBJECT_H__ */ diff --git a/libnm/nm-property-docs.xml b/libnm/nm-property-docs.xml new file mode 100644 index 00000000..1520e0f9 --- /dev/null +++ b/libnm/nm-property-docs.xml @@ -0,0 +1,296 @@ +<?xml version="1.0"?> +<!DOCTYPE nm-setting-docs [ +<!ENTITY quot """> +]> +<nm-setting-docs> + <setting name="802-1x"> + <property name="altsubject-matches" type="array of string" default="[]" description="List of strings to be matched against the altSubjectName of the certificate presented by the authentication server. If the list is empty, no verification of the server certificate's altSubjectName is performed." /> + <property name="anonymous-identity" type="string" description="Anonymous identity string for EAP authentication methods. Used as the unencrypted identity with EAP types that support different tunneled identity like EAP-TTLS." /> + <property name="ca-cert" type="byte array" description="Contains the CA certificate if used by the EAP method specified in the "eap" property. Certificate data is specified using a "scheme"; two are currently supported: blob and path. When using the blob scheme (which is backwards compatible with NM 0.7.x) this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string "file://" and ending with a terminating NUL byte. This property can be unset even if the EAP method supports CA certificates, but this allows man-in-the-middle attacks and is NOT recommended." /> + <property name="ca-path" type="string" description="UTF-8 encoded path to a directory containing PEM or DER formatted certificates to be added to the verification chain in addition to the certificate specified in the "ca-cert" property." /> + <property name="client-cert" type="byte array" description="Contains the client certificate if used by the EAP method specified in the "eap" property. Certificate data is specified using a "scheme"; two are currently supported: blob and path. When using the blob scheme (which is backwards compatible with NM 0.7.x) this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string "file://" and ending with a terminating NUL byte." /> + <property name="eap" type="array of string" default="[]" description="The allowed EAP method to be used when authenticating to the network with 802.1x. Valid methods are: "leap", "md5", "tls", "peap", "ttls", "pwd", and "fast". Each method requires different configuration using the properties of this setting; refer to wpa_supplicant documentation for the allowed combinations." /> + <property name="identity" type="string" description="Identity string for EAP authentication methods. Often the user's user or login name." /> + <property name="name" type="string" default="802-1x" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="pac-file" type="string" description="UTF-8 encoded file path containing PAC for EAP-FAST." /> + <property name="password" type="string" description="UTF-8 encoded password used for EAP authentication methods. If both the "password" property and the "password-raw" property are specified, "password" is preferred." /> + <property name="password-flags" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "password" property." /> + <property name="password-raw" type="byte array" description="Password used for EAP authentication methods, given as a byte array to allow passwords in other encodings than UTF-8 to be used. If both the "password" property and the "password-raw" property are specified, "password" is preferred." /> + <property name="password-raw-flags" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "password-raw" property." /> + <property name="phase1-fast-provisioning" type="string" description="Enables or disables in-line provisioning of EAP-FAST credentials when FAST is specified as the EAP method in the "eap" property. Recognized values are "0" (disabled), "1" (allow unauthenticated provisioning), "2" (allow authenticated provisioning), and "3" (allow both authenticated and unauthenticated provisioning). See the wpa_supplicant documentation for more details." /> + <property name="phase1-peaplabel" type="string" description="Forces use of the new PEAP label during key derivation. Some RADIUS servers may require forcing the new PEAP label to interoperate with PEAPv1. Set to "1" to force use of the new PEAP label. See the wpa_supplicant documentation for more details." /> + <property name="phase1-peapver" type="string" description="Forces which PEAP version is used when PEAP is set as the EAP method in the "eap" property. When unset, the version reported by the server will be used. Sometimes when using older RADIUS servers, it is necessary to force the client to use a particular PEAP version. To do so, this property may be set to "0" or "1" to force that specific PEAP version." /> + <property name="phase2-altsubject-matches" type="array of string" default="[]" description="List of strings to be matched against the altSubjectName of the certificate presented by the authentication server during the inner "phase 2" authentication. If the list is empty, no verification of the server certificate's altSubjectName is performed." /> + <property name="phase2-auth" type="string" description="Specifies the allowed "phase 2" inner non-EAP authentication methods when an EAP method that uses an inner TLS tunnel is specified in the "eap" property. Recognized non-EAP "phase 2" methods are "pap", "chap", "mschap", "mschapv2", "gtc", "otp", "md5", and "tls". Each "phase 2" inner method requires specific parameters for successful authentication; see the wpa_supplicant documentation for more details." /> + <property name="phase2-autheap" type="string" description="Specifies the allowed "phase 2" inner EAP-based authentication methods when an EAP method that uses an inner TLS tunnel is specified in the "eap" property. Recognized EAP-based "phase 2" methods are "md5", "mschapv2", "otp", "gtc", and "tls". Each "phase 2" inner method requires specific parameters for successful authentication; see the wpa_supplicant documentation for more details." /> + <property name="phase2-ca-cert" type="byte array" description="Contains the "phase 2" CA certificate if used by the EAP method specified in the "phase2-auth" or "phase2-autheap" properties. Certificate data is specified using a "scheme"; two are currently supported: blob and path. When using the blob scheme (which is backwards compatible with NM 0.7.x) this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string "file://" and ending with a terminating NUL byte. This property can be unset even if the EAP method supports CA certificates, but this allows man-in-the-middle attacks and is NOT recommended." /> + <property name="phase2-ca-path" type="string" description="UTF-8 encoded path to a directory containing PEM or DER formatted certificates to be added to the verification chain in addition to the certificate specified in the "phase2-ca-cert" property." /> + <property name="phase2-client-cert" type="byte array" description="Contains the "phase 2" client certificate if used by the EAP method specified in the "phase2-auth" or "phase2-autheap" properties. Certificate data is specified using a "scheme"; two are currently supported: blob and path. When using the blob scheme (which is backwards compatible with NM 0.7.x) this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string "file://" and ending with a terminating NUL byte. This property can be unset even if the EAP method supports CA certificates, but this allows man-in-the-middle attacks and is NOT recommended." /> + <property name="phase2-private-key" type="byte array" description="Contains the "phase 2" inner private key when the "phase2-auth" or "phase2-autheap" property is set to "tls". Key data is specified using a "scheme"; two are currently supported: blob and path. When using the blob scheme and private keys, this property should be set to the key's encrypted PEM encoded data. When using private keys with the path scheme, this property should be set to the full UTF-8 encoded path of the key, prefixed with the string "file://" and ending with a terminating NUL byte. When using PKCS#12 format private keys and the blob scheme, this property should be set to the PKCS#12 data and the "phase2-private-key-password" property must be set to password used to decrypt the PKCS#12 certificate and key. When using PKCS#12 files and the path scheme, this property should be set to the full UTF-8 encoded path of the key, prefixed with the string "file://" and and ending with a terminating NUL byte, and as with the blob scheme the "phase2-private-key-password" property must be set to the password used to decode the PKCS#12 private key and certificate." /> + <property name="phase2-private-key-password" type="string" description="The password used to decrypt the "phase 2" private key specified in the "phase2-private-key" property when the private key either uses the path scheme, or is a PKCS#12 format key." /> + <property name="phase2-private-key-password-flags" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "phase2-private-key-password" property." /> + <property name="phase2-subject-match" type="string" description="Substring to be matched against the subject of the certificate presented by the authentication server during the inner "phase 2" authentication. When unset, no verification of the authentication server certificate's subject is performed." /> + <property name="pin" type="string" description="PIN used for EAP authentication methods." /> + <property name="pin-flags" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "pin" property." /> + <property name="private-key" type="byte array" description="Contains the private key when the "eap" property is set to "tls". Key data is specified using a "scheme"; two are currently supported: blob and path. When using the blob scheme and private keys, this property should be set to the key's encrypted PEM encoded data. When using private keys with the path scheme, this property should be set to the full UTF-8 encoded path of the key, prefixed with the string "file://" and ending with a terminating NUL byte. When using PKCS#12 format private keys and the blob scheme, this property should be set to the PKCS#12 data and the "private-key-password" property must be set to password used to decrypt the PKCS#12 certificate and key. When using PKCS#12 files and the path scheme, this property should be set to the full UTF-8 encoded path of the key, prefixed with the string "file://" and and ending with a terminating NUL byte, and as with the blob scheme the "private-key-password" property must be set to the password used to decode the PKCS#12 private key and certificate. WARNING: "private-key" is not a "secret" property, and thus unencrypted private key data using the BLOB scheme may be readable by unprivileged users. Private keys should always be encrypted with a private key password to prevent unauthorized access to unencrypted private key data." /> + <property name="private-key-password" type="string" description="The password used to decrypt the private key specified in the "private-key" property when the private key either uses the path scheme, or if the private key is a PKCS#12 format key." /> + <property name="private-key-password-flags" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "private-key-password" property." /> + <property name="subject-match" type="string" description="Substring to be matched against the subject of the certificate presented by the authentication server. When unset, no verification of the authentication server certificate's subject is performed." /> + <property name="system-ca-certs" type="boolean" default="FALSE" description="When TRUE, overrides the "ca-path" and "phase2-ca-path" properties using the system CA directory specified at configure time with the --system-ca-path switch. The certificates in this directory are added to the verification chain in addition to any certificates specified by the "ca-cert" and "phase2-ca-cert" properties." /> + </setting> + <setting name="adsl"> + <property name="encapsulation" type="string" description="Encapsulation of ADSL connection. Can be "vcmux" or "llc"." /> + <property name="name" type="string" default="adsl" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="password" type="string" description="Password used to authenticate with the ADSL service." /> + <property name="password-flags" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "password" property." /> + <property name="protocol" type="string" description="ADSL connection protocol. Can be "pppoa", "pppoe" or "ipoatm"." /> + <property name="username" type="string" description="Username used to authenticate with the ADSL service." /> + <property name="vci" type="uint32" default="0" description="VCI of ADSL connection" /> + <property name="vpi" type="uint32" default="0" description="VPI of ADSL connection" /> + </setting> + <setting name="bluetooth"> + <property name="bdaddr" type="byte array" description="The Bluetooth address of the device." /> + <property name="name" type="string" default="bluetooth" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="type" type="string" description="Either "dun" for Dial-Up Networking connections or "panu" for Personal Area Networking connections to devices supporting the NAP profile." /> + </setting> + <setting name="bond"> + <property name="name" type="string" default="bond" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="options" type="dict of string to string" description="Dictionary of key/value pairs of bonding options. Both keys and values must be strings. Option names must contain only alphanumeric characters (ie, [a-zA-Z0-9])." /> + </setting> + <setting name="bridge"> + <property name="ageing-time" type="uint32" default="300" description="The Ethernet MAC address aging time, in seconds." /> + <property name="forward-delay" type="uint32" default="15" description="The Spanning Tree Protocol (STP) forwarding delay, in seconds." /> + <property name="hello-time" type="uint32" default="2" description="The Spanning Tree Protocol (STP) hello time, in seconds." /> + <property name="mac-address" type="byte array" description="If specified, the MAC address of bridge. When creating a new bridge, this MAC address will be set. When matching an existing (outside NetworkManager created) bridge, this MAC address must match." /> + <property name="max-age" type="uint32" default="20" description="The Spanning Tree Protocol (STP) maximum message age, in seconds." /> + <property name="name" type="string" default="bridge" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="priority" type="uint32" default="32768" description="Sets the Spanning Tree Protocol (STP) priority for this bridge. Lower values are "better"; the lowest priority bridge will be elected the root bridge." /> + <property name="stp" type="boolean" default="TRUE" description="Controls whether Spanning Tree Protocol (STP) is enabled for this bridge." /> + </setting> + <setting name="bridge-port"> + <property name="hairpin-mode" type="boolean" default="FALSE" description="Enables or disabled "hairpin mode" for the port, which allows frames to be sent back out through the port the frame was received on." /> + <property name="name" type="string" default="bridge-port" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="path-cost" type="uint32" default="100" description="The Spanning Tree Protocol (STP) port cost for destinations via this port." /> + <property name="priority" type="uint32" default="32" description="The Spanning Tree Protocol (STP) priority of this bridge port." /> + </setting> + <setting name="cdma"> + <property name="name" type="string" default="cdma" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="number" type="string" description="The number to dial to establish the connection to the CDMA-based mobile broadband network, if any. If not specified, the default number (#777) is used when required." /> + <property name="password" type="string" description="The password used to authenticate with the network, if required. Many providers do not require a password, or accept any password. But if a password is required, it is specified here." /> + <property name="password-flags" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "password" property." /> + <property name="username" type="string" description="The username used to authenticate with the network, if required. Many providers do not require a username, or accept any username. But if a username is required, it is specified here." /> + </setting> + <setting name="connection"> + <property name="autoconnect" type="boolean" default="TRUE" description="Whether or not the connection should be automatically connected by NetworkManager when the resources for the connection are available. TRUE to automatically activate the connection, FALSE to require manual intervention to activate the connection." /> + <property name="autoconnect-priority" type="int32" default="0" description="The autoconnect priority. If the connection is set to autoconnect, connections with higher priority will be preferred. Defaults to 0. The higher number means higher priority." /> + <property name="gateway-ping-timeout" type="uint32" default="0" description="If greater than zero, delay success of IP addressing until either the timeout is reached, or an IP gateway replies to a ping." /> + <property name="id" type="string" description="A human readable unique identifier for the connection, like "Work Wi-Fi" or "T-Mobile 3G"." /> + <property name="interface-name" type="string" description="The name of the network interface this connection is bound to. If not set, then the connection can be attached to any interface of the appropriate type (subject to restrictions imposed by other settings). For software devices this specifies the name of the created device. For connection types where interface names cannot easily be made persistent (e.g. mobile broadband or USB Ethernet), this property should not be used. Setting this property restricts the interfaces a connection can be used with, and if interface names change or are reordered the connection may be applied to the wrong interface." /> + <property name="master" type="string" description="Interface name of the master device or UUID of the master connection." /> + <property name="name" type="string" default="connection" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="permissions" type="array of string" default="[]" description="An array of strings defining what access a given user has to this connection. If this is NULL or empty, all users are allowed to access this connection. Otherwise a user is allowed to access this connection if and only if they are in this list. Each entry is of the form "[type]:[id]:[reserved]"; for example, "user:dcbw:blah". At this time only the "user" [type] is allowed. Any other values are ignored and reserved for future use. [id] is the username that this permission refers to, which may not contain the ":" character. Any [reserved] information present must be ignored and is reserved for future use. All of [type], [id], and [reserved] must be valid UTF-8." /> + <property name="read-only" type="boolean" default="FALSE" description="FALSE if the connection can be modified using the provided settings service's D-Bus interface with the right privileges, or TRUE if the connection is read-only and cannot be modified." /> + <property name="secondaries" type="array of string" default="[]" description="List of connection UUIDs that should be activated when the base connection itself is activated. Currently only VPN connections are supported." /> + <property name="slave-type" type="string" description="Setting name of the device type of this slave's master connection (eg, "bond"), or NULL if this connection is not a slave." /> + <property name="timestamp" type="uint64" default="0" description="The time, in seconds since the Unix Epoch, that the connection was last _successfully_ fully activated. NetworkManager updates the connection timestamp periodically when the connection is active to ensure that an active connection has the latest timestamp. The property is only meant for reading (changes to this property will not be preserved)." /> + <property name="type" type="string" description="Base type of the connection. For hardware-dependent connections, should contain the setting name of the hardware-type specific setting (ie, "802-3-ethernet" or "802-11-wireless" or "bluetooth", etc), and for non-hardware dependent connections like VPN or otherwise, should contain the setting name of that setting type (ie, "vpn" or "bridge", etc)." /> + <property name="uuid" type="string" description="A universally unique identifier for the connection, for example generated with libuuid. It should be assigned when the connection is created, and never changed as long as the connection still applies to the same network. For example, it should not be changed when the "id" property or NMSettingIP4Config changes, but might need to be re-created when the Wi-Fi SSID, mobile broadband network provider, or "type" property changes. The UUID must be in the format "2815492f-7e56-435e-b2e9-246bd7cdc664" (ie, contains only hexadecimal characters and "-")." /> + <property name="zone" type="string" description="The trust level of a the connection. Free form case-insensitive string (for example "Home", "Work", "Public"). NULL or unspecified zone means the connection will be placed in the default zone as defined by the firewall." /> + </setting> + <setting name="dcb"> + <property name="app-fcoe-flags" type="NMSettingDcbFlags (uint32)" description="Specifies the NMSettingDcbFlags for the DCB FCoE application. Flags may be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4)." /> + <property name="app-fcoe-mode" type="string" default=""fabric"" description="The FCoE controller mode; either "fabric" (default) or "vn2vn"." /> + <property name="app-fcoe-priority" type="int32" default="-1" description="The highest User Priority (0 - 7) which FCoE frames should use, or -1 for default priority. Only used when the "app-fcoe-flags" property includes the NM_SETTING_DCB_FLAG_ENABLE (0x1) flag." /> + <property name="app-fip-flags" type="NMSettingDcbFlags (uint32)" description="Specifies the NMSettingDcbFlags for the DCB FIP application. Flags may be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4)." /> + <property name="app-fip-priority" type="int32" default="-1" description="The highest User Priority (0 - 7) which FIP frames should use, or -1 for default priority. Only used when the "app-fip-flags" property includes the NM_SETTING_DCB_FLAG_ENABLE (0x1) flag." /> + <property name="app-iscsi-flags" type="NMSettingDcbFlags (uint32)" description="Specifies the NMSettingDcbFlags for the DCB iSCSI application. Flags may be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4)." /> + <property name="app-iscsi-priority" type="int32" default="-1" description="The highest User Priority (0 - 7) which iSCSI frames should use, or -1 for default priority. Only used when the "app-iscsi-flags" property includes the NM_SETTING_DCB_FLAG_ENABLE (0x1) flag." /> + <property name="name" type="string" default="dcb" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="priority-bandwidth" type="array of uint32" description="An array of 8 uint values, where the array index corresponds to the User Priority (0 - 7) and the value indicates the percentage of bandwidth of the priority's assigned group that the priority may use. The sum of all percentages for priorities which belong to the same group must total 100 percent." /> + <property name="priority-flow-control" type="array of uint32" description="An array of 8 boolean values, where the array index corresponds to the User Priority (0 - 7) and the value indicates whether or not the corresponding priority should transmit priority pause." /> + <property name="priority-flow-control-flags" type="NMSettingDcbFlags (uint32)" description="Specifies the NMSettingDcbFlags for DCB Priority Flow Control (PFC). Flags may be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4)." /> + <property name="priority-group-bandwidth" type="array of uint32" description="An array of 8 uint values, where the array index corresponds to the Priority Group ID (0 - 7) and the value indicates the percentage of link bandwidth allocated to that group. Allowed values are 0 - 100, and the sum of all values must total 100 percent." /> + <property name="priority-group-flags" type="NMSettingDcbFlags (uint32)" description="Specifies the NMSettingDcbFlags for DCB Priority Groups. Flags may be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4)." /> + <property name="priority-group-id" type="array of uint32" description="An array of 8 uint values, where the array index corresponds to the User Priority (0 - 7) and the value indicates the Priority Group ID. Allowed Priority Group ID values are 0 - 7 or 15 for the unrestricted group." /> + <property name="priority-strict-bandwidth" type="array of uint32" description="An array of 8 boolean values, where the array index corresponds to the User Priority (0 - 7) and the value indicates whether or not the priority may use all of the bandwidth allocated to its assigned group." /> + <property name="priority-traffic-class" type="array of uint32" description="An array of 8 uint values, where the array index corresponds to the User Priority (0 - 7) and the value indicates the traffic class (0 - 7) to which the priority is mapped." /> + </setting> + <setting name="generic"> + <property name="name" type="string" default="generic" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + </setting> + <setting name="gsm"> + <property name="apn" type="string" description="The GPRS Access Point Name specifying the APN used when establishing a data session with the GSM-based network. The APN often determines how the user will be billed for their network usage and whether the user has access to the Internet or just a provider-specific walled-garden, so it is important to use the correct APN for the user's mobile broadband plan. The APN may only be composed of the characters a-z, 0-9, ., and - per GSM 03.60 Section 14.9." /> + <property name="home-only" type="boolean" default="FALSE" description="When TRUE, only connections to the home network will be allowed. Connections to roaming networks will not be made." /> + <property name="name" type="string" default="gsm" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="network-id" type="string" description="The Network ID (GSM LAI format, ie MCC-MNC) to force specific network registration. If the Network ID is specified, NetworkManager will attempt to force the device to register only on the specified network. This can be used to ensure that the device does not roam when direct roaming control of the device is not otherwise possible." /> + <property name="number" type="string" description="Number to dial when establishing a PPP data session with the GSM-based mobile broadband network. Many modems do not require PPP for connections to the mobile network and thus this property should be left blank, which allows NetworkManager to select the appropriate settings automatically." /> + <property name="password" type="string" description="The password used to authenticate with the network, if required. Many providers do not require a password, or accept any password. But if a password is required, it is specified here." /> + <property name="password-flags" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "password" property." /> + <property name="pin" type="string" description="If the SIM is locked with a PIN it must be unlocked before any other operations are requested. Specify the PIN here to allow operation of the device." /> + <property name="pin-flags" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "pin" property." /> + <property name="username" type="string" description="The username used to authenticate with the network, if required. Many providers do not require a username, or accept any username. But if a username is required, it is specified here." /> + </setting> + <setting name="infiniband"> + <property name="mac-address" type="byte array" description="If specified, this connection will only apply to the IPoIB device whose permanent MAC address matches. This property does not change the MAC address of the device (i.e. MAC spoofing)." /> + <property name="mtu" type="uint32" default="0" description="If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple frames." /> + <property name="name" type="string" default="infiniband" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="p-key" type="int32" default="-1" description="The InfiniBand P_Key to use for this device. A value of -1 means to use the default P_Key (aka "the P_Key at index 0"). Otherwise it is a 16-bit unsigned integer, whose high bit is set if it is a "full membership" P_Key." /> + <property name="parent" type="string" description="The interface name of the parent device of this device. Normally NULL, but if the "p_key" property is set, then you must specify the base device by setting either this property or "mac-address"." /> + <property name="transport-mode" type="string" description="The IP-over-InfiniBand transport mode. Either "datagram" or "connected"." /> + </setting> + <setting name="ipv4"> + <property name="addresses" type="array of array of uint32" description="Array of IP addresses." /> + <property name="dhcp-client-id" type="string" description="A string sent to the DHCP server to identify the local machine which the DHCP server may use to customize the DHCP lease and options." /> + <property name="dhcp-hostname" type="string" description="If the "dhcp-send-hostname" property is TRUE, then the specified name will be sent to the DHCP server when acquiring a lease." /> + <property name="dhcp-send-hostname" type="boolean" default="TRUE" description="If TRUE, a hostname is sent to the DHCP server when acquiring a lease. Some DHCP servers use this hostname to update DNS databases, essentially providing a static hostname for the computer. If the "dhcp-hostname" property is NULL and this property is TRUE, the current persistent hostname of the computer is sent." /> + <property name="dns" type="array of uint32" default="[]" description="Array of IP addresses of DNS servers." /> + <property name="dns-search" type="array of string" default="[]" description="Array of DNS search domains." /> + <property name="gateway" type="string" description="The gateway associated with this configuration. This is only meaningful if "addresses" is also set." /> + <property name="ignore-auto-dns" type="boolean" default="FALSE" description="When "method" is set to "auto" and this property to TRUE, automatically configured nameservers and search domains are ignored and only nameservers and search domains specified in the "dns" and "dns-search" properties, if any, are used." /> + <property name="ignore-auto-routes" type="boolean" default="FALSE" description="When "method" is set to "auto" and this property to TRUE, automatically configured routes are ignored and only routes specified in the "routes" property, if any, are used." /> + <property name="may-fail" type="boolean" default="TRUE" description="If TRUE, allow overall network configuration to proceed even if the configuration specified by this property times out. Note that at least one IP configuration must succeed or overall network configuration will still fail. For example, in IPv6-only networks, setting this property to TRUE on the NMSettingIP4Config allows the overall network configuration to succeed if IPv4 configuration fails but IPv6 configuration completes successfully." /> + <property name="method" type="string" description="IP configuration method. NMSettingIP4Config and NMSettingIP6Config both support "auto", "manual", and "link-local". See the subclass-specific documentation for other values. In general, for the "auto" method, properties such as "dns" and "routes" specify information that is added on to the information returned from automatic configuration. The "ignore-auto-routes" and "ignore-auto-dns" properties modify this behavior. For methods that imply no upstream network, such as "shared" or "link-local", these properties must be empty." /> + <property name="name" type="string" default="ipv4" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="never-default" type="boolean" default="FALSE" description="If TRUE, this connection will never be the default connection for this IP type, meaning it will never be assigned the default route by NetworkManager." /> + <property name="route-metric" type="int64" default="-1" description="The default metric for routes that don't explicitly specify a metric. The default value -1 means that the metric is choosen automatically based on the device type. The metric applies to dynamic routes, manual (static) routes that don't have an explicit metric setting, address prefix routes, and the default route. Note that for IPv6, the kernel accepts zero (0) but coerces it to 1024 (user default). Hence, setting this property to zero effectively mean setting it to 1024. For IPv4, zero is a regular value for the metric." /> + <property name="routes" type="array of array of uint32" description="Array of IP routes." /> + </setting> + <setting name="ipv6"> + <property name="addresses" type="array of legacy IPv6 address struct" description="Array of IP addresses." /> + <property name="dhcp-hostname" type="string" description="If the "dhcp-send-hostname" property is TRUE, then the specified name will be sent to the DHCP server when acquiring a lease." /> + <property name="dhcp-send-hostname" type="boolean" default="TRUE" description="If TRUE, a hostname is sent to the DHCP server when acquiring a lease. Some DHCP servers use this hostname to update DNS databases, essentially providing a static hostname for the computer. If the "dhcp-hostname" property is NULL and this property is TRUE, the current persistent hostname of the computer is sent." /> + <property name="dns" type="array of byte array" default="[]" description="Array of IP addresses of DNS servers." /> + <property name="dns-search" type="array of string" default="[]" description="Array of DNS search domains." /> + <property name="gateway" type="string" description="The gateway associated with this configuration. This is only meaningful if "addresses" is also set." /> + <property name="ignore-auto-dns" type="boolean" default="FALSE" description="When "method" is set to "auto" and this property to TRUE, automatically configured nameservers and search domains are ignored and only nameservers and search domains specified in the "dns" and "dns-search" properties, if any, are used." /> + <property name="ignore-auto-routes" type="boolean" default="FALSE" description="When "method" is set to "auto" and this property to TRUE, automatically configured routes are ignored and only routes specified in the "routes" property, if any, are used." /> + <property name="ip6-privacy" type="NMSettingIP6ConfigPrivacy (int32)" description="Configure IPv6 Privacy Extensions for SLAAC, described in RFC4941. If enabled, it makes the kernel generate a temporary IPv6 address in addition to the public one generated from MAC address via modified EUI-64. This enhances privacy, but could cause problems in some applications, on the other hand. The permitted values are: 0: disabled, 1: enabled (prefer public address), 2: enabled (prefer temporary addresses)." /> + <property name="may-fail" type="boolean" default="TRUE" description="If TRUE, allow overall network configuration to proceed even if the configuration specified by this property times out. Note that at least one IP configuration must succeed or overall network configuration will still fail. For example, in IPv6-only networks, setting this property to TRUE on the NMSettingIP4Config allows the overall network configuration to succeed if IPv4 configuration fails but IPv6 configuration completes successfully." /> + <property name="method" type="string" description="IP configuration method. NMSettingIP4Config and NMSettingIP6Config both support "auto", "manual", and "link-local". See the subclass-specific documentation for other values. In general, for the "auto" method, properties such as "dns" and "routes" specify information that is added on to the information returned from automatic configuration. The "ignore-auto-routes" and "ignore-auto-dns" properties modify this behavior. For methods that imply no upstream network, such as "shared" or "link-local", these properties must be empty." /> + <property name="name" type="string" default="ipv6" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="never-default" type="boolean" default="FALSE" description="If TRUE, this connection will never be the default connection for this IP type, meaning it will never be assigned the default route by NetworkManager." /> + <property name="route-metric" type="int64" default="-1" description="The default metric for routes that don't explicitly specify a metric. The default value -1 means that the metric is choosen automatically based on the device type. The metric applies to dynamic routes, manual (static) routes that don't have an explicit metric setting, address prefix routes, and the default route. Note that for IPv6, the kernel accepts zero (0) but coerces it to 1024 (user default). Hence, setting this property to zero effectively mean setting it to 1024. For IPv4, zero is a regular value for the metric." /> + <property name="routes" type="array of legacy IPv6 route struct" description="Array of IP routes." /> + </setting> + <setting name="802-11-olpc-mesh"> + <property name="channel" type="uint32" default="0" description="Channel on which the mesh network to join is located." /> + <property name="dhcp-anycast-address" type="byte array" description="Anycast DHCP MAC address used when requesting an IP address via DHCP. The specific anycast address used determines which DHCP server class answers the request." /> + <property name="name" type="string" default="802-11-olpc-mesh" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="ssid" type="byte array" description="SSID of the mesh network to join." /> + </setting> + <setting name="ppp"> + <property name="baud" type="uint32" default="0" description="If non-zero, instruct pppd to set the serial port to the specified baudrate. This value should normally be left as 0 to automatically choose the speed." /> + <property name="crtscts" type="boolean" default="FALSE" description="If TRUE, specify that pppd should set the serial port to use hardware flow control with RTS and CTS signals. This value should normally be set to FALSE." /> + <property name="lcp-echo-failure" type="uint32" default="0" description="If non-zero, instruct pppd to presume the connection to the peer has failed if the specified number of LCP echo-requests go unanswered by the peer. The "lcp-echo-interval" property must also be set to a non-zero value if this property is used." /> + <property name="lcp-echo-interval" type="uint32" default="0" description="If non-zero, instruct pppd to send an LCP echo-request frame to the peer every n seconds (where n is the specified value). Note that some PPP peers will respond to echo requests and some will not, and it is not possible to autodetect this." /> + <property name="mppe-stateful" type="boolean" default="FALSE" description="If TRUE, stateful MPPE is used. See pppd documentation for more information on stateful MPPE." /> + <property name="mru" type="uint32" default="0" description="If non-zero, instruct pppd to request that the peer send packets no larger than the specified size. If non-zero, the MRU should be between 128 and 16384." /> + <property name="mtu" type="uint32" default="0" description="If non-zero, instruct pppd to send packets no larger than the specified size." /> + <property name="name" type="string" default="ppp" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="no-vj-comp" type="boolean" default="FALSE" description="If TRUE, Van Jacobsen TCP header compression will not be requested." /> + <property name="noauth" type="boolean" default="TRUE" description="If TRUE, do not require the other side (usually the PPP server) to authenticate itself to the client. If FALSE, require authentication from the remote side. In almost all cases, this should be TRUE." /> + <property name="nobsdcomp" type="boolean" default="FALSE" description="If TRUE, BSD compression will not be requested." /> + <property name="nodeflate" type="boolean" default="FALSE" description="If TRUE, "deflate" compression will not be requested." /> + <property name="refuse-chap" type="boolean" default="FALSE" description="If TRUE, the CHAP authentication method will not be used." /> + <property name="refuse-eap" type="boolean" default="FALSE" description="If TRUE, the EAP authentication method will not be used." /> + <property name="refuse-mschap" type="boolean" default="FALSE" description="If TRUE, the MSCHAP authentication method will not be used." /> + <property name="refuse-mschapv2" type="boolean" default="FALSE" description="If TRUE, the MSCHAPv2 authentication method will not be used." /> + <property name="refuse-pap" type="boolean" default="FALSE" description="If TRUE, the PAP authentication method will not be used." /> + <property name="require-mppe" type="boolean" default="FALSE" description="If TRUE, MPPE (Microsoft Point-to-Point Encrpytion) will be required for the PPP session. If either 64-bit or 128-bit MPPE is not available the session will fail. Note that MPPE is not used on mobile broadband connections." /> + <property name="require-mppe-128" type="boolean" default="FALSE" description="If TRUE, 128-bit MPPE (Microsoft Point-to-Point Encrpytion) will be required for the PPP session, and the "require-mppe" property must also be set to TRUE. If 128-bit MPPE is not available the session will fail." /> + </setting> + <setting name="pppoe"> + <property name="name" type="string" default="pppoe" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="password" type="string" description="Password used to authenticate with the PPPoE service." /> + <property name="password-flags" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "password" property." /> + <property name="service" type="string" description="If specified, instruct PPPoE to only initiate sessions with access concentrators that provide the specified service. For most providers, this should be left blank. It is only required if there are multiple access concentrators or a specific service is known to be required." /> + <property name="username" type="string" description="Username used to authenticate with the PPPoE service." /> + </setting> + <setting name="serial"> + <property name="baud" type="uint32" default="57600" description="Speed to use for communication over the serial port. Note that this value usually has no effect for mobile broadband modems as they generally ignore speed settings and use the highest available speed." /> + <property name="bits" type="uint32" default="8" description="Byte-width of the serial communication. The 8 in "8n1" for example." /> + <property name="name" type="string" default="serial" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="parity" type="NMSettingSerialParity (byte)" description="Parity setting of the serial port." /> + <property name="send-delay" type="uint64" default="0" description="Time to delay between each byte sent to the modem, in microseconds." /> + <property name="stopbits" type="uint32" default="1" description="Number of stop bits for communication on the serial port. Either 1 or 2. The 1 in "8n1" for example." /> + </setting> + <setting name="team"> + <property name="config" type="string" description="The JSON configuration for the team network interface. The property should contain raw JSON configuration data suitable for teamd, because the value is passed directly to teamd. If not specified, the default configuration is used. See man teamd.conf for the format details." /> + <property name="name" type="string" default="team" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + </setting> + <setting name="team-port"> + <property name="config" type="string" description="The JSON configuration for the team port. The property should contain raw JSON configuration data suitable for teamd, because the value is passed directly to teamd. If not specified, the default configuration is used. See man teamd.conf for the format details." /> + <property name="name" type="string" default="team-port" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + </setting> + <setting name="vlan"> + <property name="egress-priority-map" type="array of string" default="[]" description="For outgoing packets, a list of mappings from Linux SKB priorities to 802.1p priorities. The mapping is given in the format "from:to" where both "from" and "to" are unsigned integers, ie "7:3"." /> + <property name="flags" type="NMVlanFlags (uint32)" description="One or more flags which control the behavior and features of the VLAN interface. Flags include NM_VLAN_FLAG_REORDER_HEADERS (0x1) (reordering of output packet headers), NM_VLAN_FLAG_GVRP (0x2) (use of the GVRP protocol), and NM_VLAN_FLAG_LOOSE_BINDING (0x4) (loose binding of the interface to its master device's operating state)." /> + <property name="id" type="uint32" default="0" description="The VLAN identifier that the interface created by this connection should be assigned." /> + <property name="ingress-priority-map" type="array of string" default="[]" description="For incoming packets, a list of mappings from 802.1p priorities to Linux SKB priorities. The mapping is given in the format "from:to" where both "from" and "to" are unsigned integers, ie "7:3"." /> + <property name="name" type="string" default="vlan" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="parent" type="string" description="If given, specifies the parent interface name or parent connection UUID from which this VLAN interface should be created. If this property is not specified, the connection must contain an "802-3-ethernet" setting with a "mac-address" property." /> + </setting> + <setting name="vpn"> + <property name="data" type="dict of string to string" description="Dictionary of key/value pairs of VPN plugin specific data. Both keys and values must be strings." /> + <property name="name" type="string" default="vpn" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="persistent" type="boolean" default="FALSE" description="If the VPN service supports persistence, and this property is TRUE, the VPN will attempt to stay connected across link changes and outages, until explicitly disconnected." /> + <property name="secrets" type="dict of string to string" description="Dictionary of key/value pairs of VPN plugin specific secrets like passwords or private keys. Both keys and values must be strings." /> + <property name="service-type" type="string" description="D-Bus service name of the VPN plugin that this setting uses to connect to its network. i.e. org.freedesktop.NetworkManager.vpnc for the vpnc plugin." /> + <property name="user-name" type="string" description="If the VPN connection requires a user name for authentication, that name should be provided here. If the connection is available to more than one user, and the VPN requires each user to supply a different name, then leave this property empty. If this property is empty, NetworkManager will automatically supply the username of the user which requested the VPN connection." /> + </setting> + <setting name="wimax"> + <property name="mac-address" type="byte array" description="If specified, this connection will only apply to the WiMAX device whose MAC address matches. This property does not change the MAC address of the device (known as MAC spoofing)." /> + <property name="name" type="string" default="wimax" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="network-name" type="string" description="Network Service Provider (NSP) name of the WiMAX network this connection should use." /> + </setting> + <setting name="802-3-ethernet"> + <property name="auto-negotiate" type="boolean" default="TRUE" description="If TRUE, allow auto-negotiation of port speed and duplex mode. If FALSE, do not allow auto-negotiation, in which case the "speed" and "duplex" properties should be set." /> + <property name="cloned-mac-address" type="byte array" description="If specified, request that the device use this MAC address instead of its permanent MAC address. This is known as MAC cloning or spoofing." /> + <property name="duplex" type="string" description="If specified, request that the device only use the specified duplex mode. Either "half" or "full"." /> + <property name="mac-address" type="byte array" description="If specified, this connection will only apply to the Ethernet device whose permanent MAC address matches. This property does not change the MAC address of the device (i.e. MAC spoofing)." /> + <property name="mac-address-blacklist" type="array of string" default="[]" description="If specified, this connection will never apply to the Ethernet device whose permanent MAC address matches an address in the list. Each MAC address is in the standard hex-digits-and-colons notation (00:11:22:33:44:55)." /> + <property name="mtu" type="uint32" default="0" description="If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple Ethernet frames." /> + <property name="name" type="string" default="802-3-ethernet" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="port" type="string" description="Specific port type to use if multiple the device supports multiple attachment methods. One of "tp" (Twisted Pair), "aui" (Attachment Unit Interface), "bnc" (Thin Ethernet) or "mii" (Media Independent Interface. If the device supports only one port type, this setting is ignored." /> + <property name="s390-nettype" type="string" description="s390 network device type; one of "qeth", "lcs", or "ctc", representing the different types of virtual network devices available on s390 systems." /> + <property name="s390-options" type="dict of string to string" description="Dictionary of key/value pairs of s390-specific device options. Both keys and values must be strings. Allowed keys include "portno", "layer2", "portname", "protocol", among others. Key names must contain only alphanumeric characters (ie, [a-zA-Z0-9])." /> + <property name="s390-subchannels" type="array of string" default="[]" description="Identifies specific subchannels that this network device uses for communication with z/VM or s390 host. Like the "mac-address" property for non-z/VM devices, this property can be used to ensure this connection only applies to the network device that uses these subchannels. The list should contain exactly 3 strings, and each string may only be composed of hexadecimal characters and the period (.) character." /> + <property name="speed" type="uint32" default="0" description="If non-zero, request that the device use only the specified speed. In Mbit/s, ie 100 == 100Mbit/s." /> + </setting> + <setting name="802-11-wireless"> + <property name="band" type="string" description="802.11 frequency band of the network. One of "a" for 5GHz 802.11a or "bg" for 2.4GHz 802.11. This will lock associations to the Wi-Fi network to the specific band, i.e. if "a" is specified, the device will not associate with the same network in the 2.4GHz band even if the network's settings are compatible. This setting depends on specific driver capability and may not work with all drivers." /> + <property name="bssid" type="byte array" description="If specified, directs the device to only associate with the given access point. This capability is highly driver dependent and not supported by all devices. Note: this property does not control the BSSID used when creating an Ad-Hoc network and is unlikely to in the future." /> + <property name="channel" type="uint32" default="0" description="Wireless channel to use for the Wi-Fi connection. The device will only join (or create for Ad-Hoc networks) a Wi-Fi network on the specified channel. Because channel numbers overlap between bands, this property also requires the "band" property to be set." /> + <property name="cloned-mac-address" type="byte array" description="If specified, request that the Wi-Fi device use this MAC address instead of its permanent MAC address. This is known as MAC cloning or spoofing." /> + <property name="hidden" type="boolean" default="FALSE" description="If TRUE, indicates this network is a non-broadcasting network that hides its SSID. In this case various workarounds may take place, such as probe-scanning the SSID for more reliable network discovery. However, these workarounds expose inherent insecurities with hidden SSID networks, and thus hidden SSID networks should be used with caution." /> + <property name="mac-address" type="byte array" description="If specified, this connection will only apply to the Wi-Fi device whose permanent MAC address matches. This property does not change the MAC address of the device (i.e. MAC spoofing)." /> + <property name="mac-address-blacklist" type="array of string" default="[]" description="A list of permanent MAC addresses of Wi-Fi devices to which this connection should never apply. Each MAC address should be given in the standard hex-digits-and-colons notation (eg "00:11:22:33:44:55")." /> + <property name="mode" type="string" description="Wi-Fi network mode; one of "infrastructure", "adhoc" or "ap". If blank, infrastructure is assumed." /> + <property name="mtu" type="uint32" default="0" description="If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple Ethernet frames." /> + <property name="name" type="string" default="802-11-wireless" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="rate" type="uint32" default="0" description="If non-zero, directs the device to only use the specified bitrate for communication with the access point. Units are in Kb/s, ie 5500 = 5.5 Mbit/s. This property is highly driver dependent and not all devices support setting a static bitrate." /> + <property name="seen-bssids" type="array of string" default="[]" description="A list of BSSIDs (each BSSID formatted as a MAC address like "00:11:22:33:44:55") that have been detected as part of the Wi-Fi network. NetworkManager internally tracks previously seen BSSIDs. The property is only meant for reading and reflects the BSSID list of NetworkManager. The changes you make to this property will not be preserved." /> + <property name="ssid" type="byte array" description="SSID of the Wi-Fi network. Must be specified." /> + <property name="tx-power" type="uint32" default="0" description="If non-zero, directs the device to use the specified transmit power. Units are dBm. This property is highly driver dependent and not all devices support setting a static transmit power." /> + </setting> + <setting name="802-11-wireless-security"> + <property name="auth-alg" type="string" description="When WEP is used (ie, key-mgmt = "none" or "ieee8021x") indicate the 802.11 authentication algorithm required by the AP here. One of "open" for Open System, "shared" for Shared Key, or "leap" for Cisco LEAP. When using Cisco LEAP (ie, key-mgmt = "ieee8021x" and auth-alg = "leap") the "leap-username" and "leap-password" properties must be specified." /> + <property name="group" type="array of string" default="[]" description="A list of group/broadcast encryption algorithms which prevents connections to Wi-Fi networks that do not utilize one of the algorithms in the list. For maximum compatibility leave this property empty. Each list element may be one of "wep40", "wep104", "tkip", or "ccmp"." /> + <property name="key-mgmt" type="string" description="Key management used for the connection. One of "none" (WEP), "ieee8021x" (Dynamic WEP), "wpa-none" (Ad-Hoc WPA-PSK), "wpa-psk" (infrastructure WPA-PSK), or "wpa-eap" (WPA-Enterprise). This property must be set for any Wi-Fi connection that uses security." /> + <property name="leap-password" type="string" description="The login password for legacy LEAP connections (ie, key-mgmt = "ieee8021x" and auth-alg = "leap")." /> + <property name="leap-password-flags" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "leap-password" property." /> + <property name="leap-username" type="string" description="The login username for legacy LEAP connections (ie, key-mgmt = "ieee8021x" and auth-alg = "leap")." /> + <property name="name" type="string" default="802-11-wireless-security" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="pairwise" type="array of string" default="[]" description="A list of pairwise encryption algorithms which prevents connections to Wi-Fi networks that do not utilize one of the algorithms in the list. For maximum compatibility leave this property empty. Each list element may be one of "tkip" or "ccmp"." /> + <property name="proto" type="array of string" default="[]" description="List of strings specifying the allowed WPA protocol versions to use. Each element may be one "wpa" (allow WPA) or "rsn" (allow WPA2/RSN). If not specified, both WPA and RSN connections are allowed." /> + <property name="psk" type="string" description="Pre-Shared-Key for WPA networks. If the key is 64-characters long, it must contain only hexadecimal characters and is interpreted as a hexadecimal WPA key. Otherwise, the key must be between 8 and 63 ASCII characters (as specified in the 802.11i standard) and is interpreted as a WPA passphrase, and is hashed to derive the actual WPA-PSK used when connecting to the Wi-Fi network." /> + <property name="psk-flags" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "psk" property." /> + <property name="wep-key-flags" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "wep-key0", "wep-key1", "wep-key2", and "wep-key3" properties." /> + <property name="wep-key-type" type="NMWepKeyType (uint32)" description="Controls the interpretation of WEP keys. Allowed values are NM_WEP_KEY_TYPE_KEY (1), in which case the key is either a 10- or 26-character hexadecimal string, or a 5- or 13-character ASCII password; or NM_WEP_KEY_TYPE_PASSPHRASE (2), in which case the passphrase is provided as a string and will be hashed using the de-facto MD5 method to derive the actual WEP key." /> + <property name="wep-key0" type="string" description="Index 0 WEP key. This is the WEP key used in most networks. See the "wep-key-type" property for a description of how this key is interpreted." /> + <property name="wep-key1" type="string" description="Index 1 WEP key. This WEP index is not used by most networks. See the "wep-key-type" property for a description of how this key is interpreted." /> + <property name="wep-key2" type="string" description="Index 2 WEP key. This WEP index is not used by most networks. See the "wep-key-type" property for a description of how this key is interpreted." /> + <property name="wep-key3" type="string" description="Index 3 WEP key. This WEP index is not used by most networks. See the "wep-key-type" property for a description of how this key is interpreted." /> + <property name="wep-tx-keyidx" type="uint32" default="0" description="When static WEP is used (ie, key-mgmt = "none") and a non-default WEP key index is used by the AP, put that WEP key index here. Valid values are 0 (default key) through 3. Note that some consumer access points (like the Linksys WRT54G) number the keys 1 - 4." /> + </setting> +</nm-setting-docs> diff --git a/libnm/nm-remote-connection-private.h b/libnm/nm-remote-connection-private.h new file mode 100644 index 00000000..e3f35428 --- /dev/null +++ b/libnm/nm-remote-connection-private.h @@ -0,0 +1,33 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2009 Red Hat, Inc. + */ + +#ifndef __NM_REMOTE_CONNECTION_PRIVATE_H__ +#define __NM_REMOTE_CONNECTION_PRIVATE_H__ + +#define NM_REMOTE_CONNECTION_INIT_RESULT "init-result" + +typedef enum { + NM_REMOTE_CONNECTION_INIT_RESULT_UNKNOWN = 0, + NM_REMOTE_CONNECTION_INIT_RESULT_SUCCESS, + NM_REMOTE_CONNECTION_INIT_RESULT_ERROR, + NM_REMOTE_CONNECTION_INIT_RESULT_INVISIBLE, +} NMRemoteConnectionInitResult; + +#endif /* __NM_REMOTE_CONNECTION_PRIVATE__ */ diff --git a/libnm/nm-remote-connection.c b/libnm/nm-remote-connection.c new file mode 100644 index 00000000..3afe7f8e --- /dev/null +++ b/libnm/nm-remote-connection.c @@ -0,0 +1,857 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2007 - 2008 Novell, Inc. + * Copyright 2007 - 2011 Red Hat, Inc. + */ + +#include "config.h" + +#include <string.h> +#include <gio/gio.h> +#include <glib/gi18n-lib.h> + +#include <nm-dbus-interface.h> +#include <nm-utils.h> +#include <nm-setting-connection.h> +#include "nm-remote-connection.h" +#include "nm-remote-connection-private.h" +#include "nm-object-private.h" +#include "nm-glib-compat.h" +#include "nm-dbus-helpers.h" + +#include "nmdbus-settings-connection.h" + +static void nm_remote_connection_connection_iface_init (NMConnectionInterface *iface); +static void nm_remote_connection_initable_iface_init (GInitableIface *iface); +static void nm_remote_connection_async_initable_iface_init (GAsyncInitableIface *iface); +static GInitableIface *nm_remote_connection_parent_initable_iface; +static GAsyncInitableIface *nm_remote_connection_parent_async_initable_iface; + +G_DEFINE_TYPE_WITH_CODE (NMRemoteConnection, nm_remote_connection, NM_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (NM_TYPE_CONNECTION, nm_remote_connection_connection_iface_init); + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_remote_connection_initable_iface_init); + G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_remote_connection_async_initable_iface_init); + ) + +enum { + PROP_0, + PROP_UNSAVED, + PROP_VISIBLE, + + LAST_PROP +}; + +typedef struct { + NMDBusSettingsConnection *proxy; + + gboolean unsaved; + + gboolean visible; +} NMRemoteConnectionPrivate; + +#define NM_REMOTE_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_REMOTE_CONNECTION, NMRemoteConnectionPrivate)) + +/****************************************************************/ + +/** + * nm_remote_connection_commit_changes: + * @connection: the #NMRemoteConnection + * @save_to_disk: whether to persist the changes to disk + * @cancellable: a #GCancellable, or %NULL + * @error: location for a #GError, or %NULL + * + * Send any local changes to the settings and properties of @connection to + * NetworkManager. If @save_to_disk is %TRUE, the updated connection will be saved to + * disk; if %FALSE, then only the in-memory representation will be changed. + * + * Returns: %TRUE on success, %FALSE on error, in which case @error will be set. + **/ +gboolean +nm_remote_connection_commit_changes (NMRemoteConnection *connection, + gboolean save_to_disk, + GCancellable *cancellable, + GError **error) +{ + NMRemoteConnectionPrivate *priv; + GVariant *settings; + gboolean ret; + + g_return_val_if_fail (NM_IS_REMOTE_CONNECTION (connection), FALSE); + + priv = NM_REMOTE_CONNECTION_GET_PRIVATE (connection); + + settings = nm_connection_to_dbus (NM_CONNECTION (connection), NM_CONNECTION_SERIALIZE_ALL); + if (save_to_disk) { + ret = nmdbus_settings_connection_call_update_sync (priv->proxy, + settings, + cancellable, error); + } else { + ret = nmdbus_settings_connection_call_update_unsaved_sync (priv->proxy, + settings, + cancellable, error); + } + if (error && *error) + g_dbus_error_strip_remote_error (*error); + return ret; +} + +static void +update_cb (GObject *proxy, GAsyncResult *result, gpointer user_data) +{ + GSimpleAsyncResult *simple = user_data; + gboolean (*finish_func) (NMDBusSettingsConnection *, GAsyncResult *, GError **); + GError *error = NULL; + + finish_func = g_object_get_data (G_OBJECT (simple), "finish_func"); + if (finish_func (NMDBUS_SETTINGS_CONNECTION (proxy), result, &error)) + g_simple_async_result_set_op_res_gboolean (simple, TRUE); + else { + g_dbus_error_strip_remote_error (error); + g_simple_async_result_take_error (simple, error); + } + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +/** + * nm_remote_connection_commit_changes_async: + * @connection: the #NMRemoteConnection + * @save_to_disk: whether to save the changes to persistent storage + * @cancellable: a #GCancellable, or %NULL + * @callback: callback to be called when the commit operation completes + * @user_data: caller-specific data passed to @callback + * + * Asynchronously sends any local changes to the settings and properties of + * @connection to NetworkManager. If @save is %TRUE, the updated connection will + * be saved to disk; if %FALSE, then only the in-memory representation will be + * changed. + **/ +void +nm_remote_connection_commit_changes_async (NMRemoteConnection *connection, + gboolean save_to_disk, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + NMRemoteConnectionPrivate *priv; + GSimpleAsyncResult *simple; + GVariant *settings; + + g_return_if_fail (NM_IS_REMOTE_CONNECTION (connection)); + + priv = NM_REMOTE_CONNECTION_GET_PRIVATE (connection); + + simple = g_simple_async_result_new (G_OBJECT (connection), callback, user_data, + nm_remote_connection_commit_changes_async); + + settings = nm_connection_to_dbus (NM_CONNECTION (connection), NM_CONNECTION_SERIALIZE_ALL); + if (save_to_disk) { + g_object_set_data (G_OBJECT (simple), "finish_func", + nmdbus_settings_connection_call_update_finish); + nmdbus_settings_connection_call_update (priv->proxy, + settings, + cancellable, + update_cb, simple); + } else { + g_object_set_data (G_OBJECT (simple), "finish_func", + nmdbus_settings_connection_call_update_unsaved_finish); + nmdbus_settings_connection_call_update_unsaved (priv->proxy, + settings, + cancellable, + update_cb, simple); + } +} + +/** + * nm_remote_connection_commit_changes_finish: + * @connection: the #NMRemoteConnection + * @result: the result passed to the #GAsyncReadyCallback + * @error: location for a #GError, or %NULL + * + * Gets the result of a call to nm_remote_connection_commit_changes_async(). + * + * Returns: %TRUE on success, %FALSE on error, in which case @error will be set. + **/ +gboolean +nm_remote_connection_commit_changes_finish (NMRemoteConnection *connection, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (connection), nm_remote_connection_commit_changes_async), FALSE); + + simple = G_SIMPLE_ASYNC_RESULT (result); + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + else + return g_simple_async_result_get_op_res_gboolean (simple); +} + +/** + * nm_remote_connection_save: + * @connection: the #NMRemoteConnection + * @cancellable: a #GCancellable, or %NULL + * @error: location for a #GError, or %NULL + * + * Saves the connection to disk if the connection has changes that have not yet + * been written to disk, or if the connection has never been saved. + * + * Returns: %TRUE on success, %FALSE on error, in which case @error will be set. + **/ +gboolean +nm_remote_connection_save (NMRemoteConnection *connection, + GCancellable *cancellable, + GError **error) +{ + NMRemoteConnectionPrivate *priv; + gboolean ret; + + g_return_val_if_fail (NM_IS_REMOTE_CONNECTION (connection), FALSE); + + priv = NM_REMOTE_CONNECTION_GET_PRIVATE (connection); + + ret = nmdbus_settings_connection_call_save_sync (priv->proxy, cancellable, error); + if (error && *error) + g_dbus_error_strip_remote_error (*error); + return ret; +} + +static void +save_cb (GObject *proxy, GAsyncResult *result, gpointer user_data) +{ + GSimpleAsyncResult *simple = user_data; + GError *error = NULL; + + if (nmdbus_settings_connection_call_save_finish (NMDBUS_SETTINGS_CONNECTION (proxy), + result, &error)) + g_simple_async_result_set_op_res_gboolean (simple, TRUE); + else { + g_dbus_error_strip_remote_error (error); + g_simple_async_result_take_error (simple, error); + } + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +/** + * nm_remote_connection_save_async: + * @connection: the #NMRemoteConnection + * @cancellable: a #GCancellable, or %NULL + * @callback: callback to be called when the save operation completes + * @user_data: caller-specific data passed to @callback + * + * Saves the connection to disk if the connection has changes that have not yet + * been written to disk, or if the connection has never been saved. + **/ +void +nm_remote_connection_save_async (NMRemoteConnection *connection, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + NMRemoteConnectionPrivate *priv; + GSimpleAsyncResult *simple; + + g_return_if_fail (NM_IS_REMOTE_CONNECTION (connection)); + + priv = NM_REMOTE_CONNECTION_GET_PRIVATE (connection); + + simple = g_simple_async_result_new (G_OBJECT (connection), callback, user_data, + nm_remote_connection_save_async); + nmdbus_settings_connection_call_save (priv->proxy, cancellable, save_cb, simple); +} + +/** + * nm_remote_connection_save_finish: + * @connection: the #NMRemoteConnection + * @result: the result passed to the #GAsyncReadyCallback + * @error: location for a #GError, or %NULL + * + * Gets the result of a call to nm_remote_connection_save_async(). + * + * Returns: %TRUE on success, %FALSE on error, in which case @error will be set. + **/ +gboolean +nm_remote_connection_save_finish (NMRemoteConnection *connection, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (connection), nm_remote_connection_save_async), FALSE); + + simple = G_SIMPLE_ASYNC_RESULT (result); + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + else + return g_simple_async_result_get_op_res_gboolean (simple); +} + +/** + * nm_remote_connection_delete: + * @connection: the #NMRemoteConnection + * @cancellable: a #GCancellable, or %NULL + * @error: location for a #GError, or %NULL + * + * Deletes the connection. + * + * Returns: %TRUE on success, %FALSE on error, in which case @error will be set. + **/ +gboolean +nm_remote_connection_delete (NMRemoteConnection *connection, + GCancellable *cancellable, + GError **error) +{ + NMRemoteConnectionPrivate *priv; + gboolean ret; + + g_return_val_if_fail (NM_IS_REMOTE_CONNECTION (connection), FALSE); + + priv = NM_REMOTE_CONNECTION_GET_PRIVATE (connection); + + ret = nmdbus_settings_connection_call_delete_sync (priv->proxy, cancellable, error); + if (error && *error) + g_dbus_error_strip_remote_error (*error); + return ret; +} + +static void +delete_cb (GObject *proxy, GAsyncResult *result, gpointer user_data) +{ + GSimpleAsyncResult *simple = user_data; + GError *error = NULL; + + if (nmdbus_settings_connection_call_delete_finish (NMDBUS_SETTINGS_CONNECTION (proxy), + result, &error)) + g_simple_async_result_set_op_res_gboolean (simple, TRUE); + else { + g_dbus_error_strip_remote_error (error); + g_simple_async_result_take_error (simple, error); + } + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +/** + * nm_remote_connection_delete_async: + * @connection: the #NMRemoteConnection + * @cancellable: a #GCancellable, or %NULL + * @callback: callback to be called when the delete operation completes + * @user_data: caller-specific data passed to @callback + * + * Asynchronously deletes the connection. + **/ +void +nm_remote_connection_delete_async (NMRemoteConnection *connection, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + NMRemoteConnectionPrivate *priv; + GSimpleAsyncResult *simple; + + g_return_if_fail (NM_IS_REMOTE_CONNECTION (connection)); + + priv = NM_REMOTE_CONNECTION_GET_PRIVATE (connection); + + simple = g_simple_async_result_new (G_OBJECT (connection), callback, user_data, + nm_remote_connection_delete_async); + nmdbus_settings_connection_call_delete (priv->proxy, cancellable, delete_cb, simple); +} + +/** + * nm_remote_connection_delete_finish: + * @connection: the #NMRemoteConnection + * @result: the result passed to the #GAsyncReadyCallback + * @error: location for a #GError, or %NULL + * + * Gets the result of a call to nm_remote_connection_delete_async(). + * + * Returns: %TRUE on success, %FALSE on error, in which case @error will be set. + **/ +gboolean +nm_remote_connection_delete_finish (NMRemoteConnection *connection, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (connection), nm_remote_connection_delete_async), FALSE); + + simple = G_SIMPLE_ASYNC_RESULT (result); + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + else + return g_simple_async_result_get_op_res_gboolean (simple); +} + +/** + * nm_remote_connection_get_secrets: + * @connection: the #NMRemoteConnection + * @setting_name: the #NMSetting object name to get secrets for + * @cancellable: a #GCancellable, or %NULL + * @error: location for a #GError, or %NULL + * + * Request the connection's secrets. Note that this is a blocking D-Bus call, + * not a simple property accessor. + * + * Returns: a #GVariant of type %NM_VARIANT_TYPE_CONNECTION containing + * @connection's secrets, or %NULL on error. + **/ +GVariant * +nm_remote_connection_get_secrets (NMRemoteConnection *connection, + const char *setting_name, + GCancellable *cancellable, + GError **error) +{ + NMRemoteConnectionPrivate *priv; + GVariant *secrets; + + g_return_val_if_fail (NM_IS_REMOTE_CONNECTION (connection), NULL); + + priv = NM_REMOTE_CONNECTION_GET_PRIVATE (connection); + + if (nmdbus_settings_connection_call_get_secrets_sync (priv->proxy, + setting_name, + &secrets, + cancellable, error)) + return secrets; + else { + if (error && *error) + g_dbus_error_strip_remote_error (*error); + return NULL; + } +} + +static void +get_secrets_cb (GObject *proxy, GAsyncResult *result, gpointer user_data) +{ + GSimpleAsyncResult *simple = user_data; + GVariant *secrets = NULL; + GError *error = NULL; + + if (nmdbus_settings_connection_call_get_secrets_finish (NMDBUS_SETTINGS_CONNECTION (proxy), + &secrets, result, &error)) + g_simple_async_result_set_op_res_gpointer (simple, secrets, (GDestroyNotify) g_variant_unref); + else { + g_dbus_error_strip_remote_error (error); + g_simple_async_result_take_error (simple, error); + } + + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +/** + * nm_remote_connection_get_secrets_async: + * @connection: the #NMRemoteConnection + * @setting_name: the #NMSetting object name to get secrets for + * @cancellable: a #GCancellable, or %NULL + * @callback: callback to be called when the secret request completes + * @user_data: caller-specific data passed to @callback + * + * Asynchronously requests the connection's secrets. + **/ +void +nm_remote_connection_get_secrets_async (NMRemoteConnection *connection, + const char *setting_name, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + NMRemoteConnectionPrivate *priv; + GSimpleAsyncResult *simple; + + g_return_if_fail (NM_IS_REMOTE_CONNECTION (connection)); + + priv = NM_REMOTE_CONNECTION_GET_PRIVATE (connection); + + simple = g_simple_async_result_new (G_OBJECT (connection), callback, user_data, + nm_remote_connection_get_secrets_async); + + nmdbus_settings_connection_call_get_secrets (priv->proxy, + setting_name, + cancellable, + get_secrets_cb, simple); +} + +/** + * nm_remote_connection_get_secrets_finish: + * @connection: the #NMRemoteConnection + * @result: the result passed to the #GAsyncReadyCallback + * @error: location for a #GError, or %NULL + * + * Gets the result of a call to nm_remote_connection_get_secrets_async(). + * + * Returns: (transfer full): a #GVariant of type %NM_VARIANT_TYPE_CONNECTION + * containing @connection's secrets, or %NULL on error. + **/ +GVariant * +nm_remote_connection_get_secrets_finish (NMRemoteConnection *connection, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (connection), nm_remote_connection_get_secrets_async), FALSE); + + simple = G_SIMPLE_ASYNC_RESULT (result); + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + else + return g_variant_ref (g_simple_async_result_get_op_res_gpointer (simple)); +} + +/** + * nm_remote_connection_get_unsaved: + * @connection: the #NMRemoteConnection + * + * Returns: %TRUE if the remote connection contains changes that have not + * been saved to disk, %FALSE if the connection is the same as its on-disk + * representation. + **/ +gboolean +nm_remote_connection_get_unsaved (NMRemoteConnection *connection) +{ + g_return_val_if_fail (NM_IS_REMOTE_CONNECTION (connection), FALSE); + + return NM_REMOTE_CONNECTION_GET_PRIVATE (connection)->unsaved; +} + +/** + * nm_remote_connection_get_visible: + * @connection: the #NMRemoteConnection + * + * Checks if the connection is visible to the current user. If the + * connection is not visible then it is essentially useless; it will + * not contain any settings, and operations such as + * nm_remote_connection_save() and nm_remote_connection_delete() will + * always fail. (#NMRemoteSettings will not normally return + * non-visible connections to callers, but it is possible for a + * connection's visibility to change after you already have a + * reference to it.) + * + * Returns: %TRUE if the remote connection is visible to the current + * user, %FALSE if not. + **/ +gboolean +nm_remote_connection_get_visible (NMRemoteConnection *connection) +{ + g_return_val_if_fail (NM_IS_REMOTE_CONNECTION (connection), FALSE); + + return NM_REMOTE_CONNECTION_GET_PRIVATE (connection)->visible; +} + +/****************************************************************/ + +static void +replace_settings (NMRemoteConnection *self, GVariant *new_settings) +{ + GError *error = NULL; + + if (!nm_connection_replace_settings (NM_CONNECTION (self), new_settings, &error)) { + g_warning ("%s: error updating connection %s settings: (%d) %s", + __func__, + nm_connection_get_path (NM_CONNECTION (self)), + error ? error->code : -1, + (error && error->message) ? error->message : "(unknown)"); + g_clear_error (&error); + } +} + +static void +updated_get_settings_cb (GObject *proxy, + GAsyncResult *result, + gpointer user_data) +{ + NMRemoteConnection *self = user_data; + NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self); + GVariant *new_settings; + gboolean visible; + + if (!nmdbus_settings_connection_call_get_settings_finish (priv->proxy, &new_settings, + result, NULL)) { + /* Connection is no longer visible to this user. */ + nm_connection_clear_settings (NM_CONNECTION (self)); + + visible = FALSE; + } else { + replace_settings (self, new_settings); + g_variant_unref (new_settings); + + visible = TRUE; + } + + if (visible != priv->visible) { + priv->visible = visible; + g_object_notify (G_OBJECT (self), NM_REMOTE_CONNECTION_VISIBLE); + } +} + +static void +updated_cb (NMDBusSettingsConnection *proxy, gpointer user_data) +{ + NMRemoteConnection *self = NM_REMOTE_CONNECTION (user_data); + NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self); + + /* The connection got updated; request the replacement settings */ + nmdbus_settings_connection_call_get_settings (priv->proxy, + NULL, + updated_get_settings_cb, self); +} + +/****************************************************************/ + +static void +init_dbus (NMObject *object) +{ + NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (object); + const NMPropertiesInfo property_info[] = { + { NM_REMOTE_CONNECTION_UNSAVED, &priv->unsaved }, + { NULL }, + }; + + NM_OBJECT_CLASS (nm_remote_connection_parent_class)->init_dbus (object); + + priv->proxy = NMDBUS_SETTINGS_CONNECTION (_nm_object_get_proxy (object, NM_DBUS_INTERFACE_SETTINGS_CONNECTION)); + g_assert (priv->proxy); + + _nm_object_register_properties (object, + NM_DBUS_INTERFACE_SETTINGS_CONNECTION, + property_info); + + g_signal_connect (priv->proxy, "updated", + G_CALLBACK (updated_cb), object); +} + +static gboolean +init_sync (GInitable *initable, GCancellable *cancellable, GError **error) +{ + NMRemoteConnection *self = NM_REMOTE_CONNECTION (initable); + NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (initable); + GVariant *settings; + + if (!nm_remote_connection_parent_initable_iface->init (initable, cancellable, error)) + return FALSE; + + if (!nmdbus_settings_connection_call_get_settings_sync (priv->proxy, + &settings, + cancellable, error)) { + if (error && *error) + g_dbus_error_strip_remote_error (*error); + return FALSE; + } + + priv->visible = TRUE; + replace_settings (self, settings); + g_variant_unref (settings); + + return TRUE; +} + +typedef struct { + NMRemoteConnection *connection; + GCancellable *cancellable; + GSimpleAsyncResult *result; +} NMRemoteConnectionInitData; + +static void +init_async_complete (NMRemoteConnectionInitData *init_data, GError *error) +{ + if (error) + g_simple_async_result_take_error (init_data->result, error); + else + g_simple_async_result_set_op_res_gboolean (init_data->result, TRUE); + + g_simple_async_result_complete (init_data->result); + g_object_unref (init_data->result); + g_clear_object (&init_data->cancellable); + g_slice_free (NMRemoteConnectionInitData, init_data); +} + +static void +init_get_settings_cb (GObject *proxy, + GAsyncResult *result, + gpointer user_data) +{ + NMRemoteConnectionInitData *init_data = user_data; + NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (init_data->connection); + GVariant *settings; + GError *error = NULL; + + if (!nmdbus_settings_connection_call_get_settings_finish (priv->proxy, &settings, + result, &error)) { + g_dbus_error_strip_remote_error (error); + init_async_complete (init_data, error); + return; + } + + priv->visible = TRUE; + replace_settings (init_data->connection, settings); + g_variant_unref (settings); + + init_async_complete (init_data, NULL); +} + +static void +init_async_parent_inited (GObject *source, GAsyncResult *result, gpointer user_data) +{ + NMRemoteConnectionInitData *init_data = user_data; + NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (init_data->connection); + GError *error = NULL; + + if (!nm_remote_connection_parent_async_initable_iface->init_finish (G_ASYNC_INITABLE (source), result, &error)) { + init_async_complete (init_data, error); + return; + } + + nmdbus_settings_connection_call_get_settings (priv->proxy, + init_data->cancellable, + init_get_settings_cb, init_data); +} + +static void +init_async (GAsyncInitable *initable, int io_priority, + GCancellable *cancellable, GAsyncReadyCallback callback, + gpointer user_data) +{ + NMRemoteConnectionInitData *init_data; + + init_data = g_slice_new0 (NMRemoteConnectionInitData); + init_data->connection = NM_REMOTE_CONNECTION (initable); + init_data->cancellable = cancellable ? g_object_ref (cancellable) : NULL; + init_data->result = g_simple_async_result_new (G_OBJECT (initable), callback, + user_data, init_async); + + nm_remote_connection_parent_async_initable_iface-> + init_async (initable, io_priority, cancellable, init_async_parent_inited, init_data); +} + +static gboolean +init_finish (GAsyncInitable *initable, GAsyncResult *result, GError **error) +{ + GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); + + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + else + return TRUE; +} + +static void +nm_remote_connection_init (NMRemoteConnection *self) +{ +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + switch (prop_id) { + case PROP_UNSAVED: + g_value_set_boolean (value, NM_REMOTE_CONNECTION_GET_PRIVATE (object)->unsaved); + break; + case PROP_VISIBLE: + g_value_set_boolean (value, NM_REMOTE_CONNECTION_GET_PRIVATE (object)->visible); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +constructed (GObject *object) +{ + nm_connection_set_path (NM_CONNECTION (object), + nm_object_get_path (NM_OBJECT (object))); +} + +static void +nm_remote_connection_class_init (NMRemoteConnectionClass *remote_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (remote_class); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (remote_class); + + g_type_class_add_private (object_class, sizeof (NMRemoteConnectionPrivate)); + + _nm_object_class_add_interface (nm_object_class, NM_DBUS_INTERFACE_SETTINGS_CONNECTION); + _nm_dbus_register_proxy_type (NM_DBUS_INTERFACE_SETTINGS_CONNECTION, + NMDBUS_TYPE_SETTINGS_CONNECTION_PROXY); + + /* virtual methods */ + object_class->constructed = constructed; + object_class->get_property = get_property; + + nm_object_class->init_dbus = init_dbus; + + /* Properties */ + /** + * NMRemoteConnection:unsaved: + * + * %TRUE if the remote connection contains changes that have not been saved + * to disk, %FALSE if the connection is the same as its on-disk representation. + **/ + g_object_class_install_property + (object_class, PROP_UNSAVED, + g_param_spec_boolean (NM_REMOTE_CONNECTION_UNSAVED, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMRemoteConnection:visible: + * + * %TRUE if the remote connection is visible to the current user, %FALSE if + * not. If the connection is not visible then it is essentially useless; it + * will not contain any settings, and operations such as + * nm_remote_connection_save() and nm_remote_connection_delete() will always + * fail. (#NMRemoteSettings will not normally return non-visible connections + * to callers, but it is possible for a connection's visibility to change + * after you already have a reference to it.) + **/ + g_object_class_install_property + (object_class, PROP_VISIBLE, + g_param_spec_boolean (NM_REMOTE_CONNECTION_VISIBLE, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); +} + +static void +nm_remote_connection_connection_iface_init (NMConnectionInterface *iface) +{ +} + +static void +nm_remote_connection_initable_iface_init (GInitableIface *iface) +{ + nm_remote_connection_parent_initable_iface = g_type_interface_peek_parent (iface); + + iface->init = init_sync; +} + +static void +nm_remote_connection_async_initable_iface_init (GAsyncInitableIface *iface) +{ + nm_remote_connection_parent_async_initable_iface = g_type_interface_peek_parent (iface); + + iface->init_async = init_async; + iface->init_finish = init_finish; +} diff --git a/libnm/nm-remote-connection.h b/libnm/nm-remote-connection.h new file mode 100644 index 00000000..3ea8037f --- /dev/null +++ b/libnm/nm-remote-connection.h @@ -0,0 +1,114 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2007 - 2008 Novell, Inc. + * Copyright 2007 - 2011 Red Hat, Inc. + */ + +#ifndef __NM_REMOTE_CONNECTION_H__ +#define __NM_REMOTE_CONNECTION_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include <nm-object.h> + +G_BEGIN_DECLS + +#define NM_TYPE_REMOTE_CONNECTION (nm_remote_connection_get_type ()) +#define NM_REMOTE_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_REMOTE_CONNECTION, NMRemoteConnection)) +#define NM_REMOTE_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_REMOTE_CONNECTION, NMRemoteConnectionClass)) +#define NM_IS_REMOTE_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_REMOTE_CONNECTION)) +#define NM_IS_REMOTE_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_REMOTE_CONNECTION)) +#define NM_REMOTE_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_REMOTE_CONNECTION, NMRemoteConnectionClass)) + + +/* Properties */ +#define NM_REMOTE_CONNECTION_DBUS_CONNECTION "dbus-connection" +#define NM_REMOTE_CONNECTION_PATH "path" +#define NM_REMOTE_CONNECTION_UNSAVED "unsaved" +#define NM_REMOTE_CONNECTION_VISIBLE "visible" + +struct _NMRemoteConnection { + NMObject parent; +}; + +typedef struct { + NMObjectClass parent_class; + + /*< private >*/ + gpointer padding[8]; +} NMRemoteConnectionClass; + +GType nm_remote_connection_get_type (void); + +gboolean nm_remote_connection_commit_changes (NMRemoteConnection *connection, + gboolean save_to_disk, + GCancellable *cancellable, + GError **error); +void nm_remote_connection_commit_changes_async (NMRemoteConnection *connection, + gboolean save_to_disk, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean nm_remote_connection_commit_changes_finish (NMRemoteConnection *connection, + GAsyncResult *result, + GError **error); + +gboolean nm_remote_connection_save (NMRemoteConnection *connection, + GCancellable *cancellable, + GError **error); +void nm_remote_connection_save_async (NMRemoteConnection *connection, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean nm_remote_connection_save_finish (NMRemoteConnection *connection, + GAsyncResult *result, + GError **error); + +gboolean nm_remote_connection_delete (NMRemoteConnection *connection, + GCancellable *cancellable, + GError **error); +void nm_remote_connection_delete_async (NMRemoteConnection *connection, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean nm_remote_connection_delete_finish (NMRemoteConnection *connection, + GAsyncResult *result, + GError **error); + +GVariant *nm_remote_connection_get_secrets (NMRemoteConnection *connection, + const char *setting_name, + GCancellable *cancellable, + GError **error); +void nm_remote_connection_get_secrets_async (NMRemoteConnection *connection, + const char *setting_name, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +GVariant *nm_remote_connection_get_secrets_finish (NMRemoteConnection *connection, + GAsyncResult *result, + GError **error); + +gboolean nm_remote_connection_get_unsaved (NMRemoteConnection *connection); + +gboolean nm_remote_connection_get_visible (NMRemoteConnection *connection); + +G_END_DECLS + +#endif /* __NM_REMOTE_CONNECTION__ */ diff --git a/libnm/nm-remote-settings.c b/libnm/nm-remote-settings.c new file mode 100644 index 00000000..d37e3666 --- /dev/null +++ b/libnm/nm-remote-settings.c @@ -0,0 +1,832 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2008 Novell, Inc. + * Copyright 2009 - 2012 Red Hat, Inc. + */ + +#include "config.h" + +#include <string.h> +#include <glib/gi18n-lib.h> +#include <nm-dbus-interface.h> +#include <nm-connection.h> + +#include "nm-remote-settings.h" +#include "nm-client.h" +#include "nm-remote-connection.h" +#include "nm-remote-connection-private.h" +#include "nm-object-private.h" +#include "nm-dbus-helpers.h" +#include "nm-glib-compat.h" +#include "nm-object-private.h" +#include "nm-core-internal.h" + +#include "nmdbus-settings.h" + +G_DEFINE_TYPE (NMRemoteSettings, nm_remote_settings, NM_TYPE_OBJECT) + +#define NM_REMOTE_SETTINGS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_REMOTE_SETTINGS, NMRemoteSettingsPrivate)) + +typedef struct { + NMDBusSettings *proxy; + GPtrArray *all_connections; + GPtrArray *visible_connections; + GCancellable *props_cancellable; + + /* AddConnectionInfo objects that are waiting for the connection to become initialized */ + GSList *add_list; + + char *hostname; + gboolean can_modify; +} NMRemoteSettingsPrivate; + +enum { + PROP_0, + PROP_CONNECTIONS, + PROP_HOSTNAME, + PROP_CAN_MODIFY, + + LAST_PROP +}; + +/* Signals */ +enum { + CONNECTION_ADDED, + CONNECTION_REMOVED, + + LAST_SIGNAL +}; +static guint signals[LAST_SIGNAL] = { 0 }; + +/**********************************************************************/ + +typedef struct { + NMRemoteSettings *self; + GSimpleAsyncResult *simple; + char *path; + gboolean saved; +} AddConnectionInfo; + +static AddConnectionInfo * +add_connection_info_find (NMRemoteSettings *self, const char *path) +{ + NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); + GSList *iter; + + for (iter = priv->add_list; iter; iter = g_slist_next (iter)) { + AddConnectionInfo *info = iter->data; + + if (!g_strcmp0 (info->path, path)) + return info; + } + + return NULL; +} + +static void +add_connection_info_complete (NMRemoteSettings *self, + AddConnectionInfo *info, + NMRemoteConnection *connection, + GError *error) +{ + NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); + + g_return_if_fail (info != NULL); + + if (connection) { + g_simple_async_result_set_op_res_gpointer (info->simple, + g_object_ref (connection), + g_object_unref); + } else + g_simple_async_result_set_from_error (info->simple, error); + g_simple_async_result_complete (info->simple); + + g_object_unref (info->simple); + priv->add_list = g_slist_remove (priv->add_list, info); + + g_free (info->path); + g_slice_free (AddConnectionInfo, info); +} + +typedef const char * (*ConnectionStringGetter) (NMConnection *); + +static NMRemoteConnection * +get_connection_by_string (NMRemoteSettings *settings, + const char *string, + ConnectionStringGetter get_comparison_string) +{ + NMRemoteSettingsPrivate *priv; + NMConnection *candidate; + int i; + + if (!_nm_object_get_nm_running (NM_OBJECT (settings))) + return NULL; + + priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings); + + for (i = 0; i < priv->visible_connections->len; i++) { + candidate = priv->visible_connections->pdata[i]; + if (!g_strcmp0 (string, get_comparison_string (candidate))) + return NM_REMOTE_CONNECTION (candidate); + } + + return NULL; +} + +NMRemoteConnection * +nm_remote_settings_get_connection_by_id (NMRemoteSettings *settings, const char *id) +{ + g_return_val_if_fail (NM_IS_REMOTE_SETTINGS (settings), NULL); + g_return_val_if_fail (id != NULL, NULL); + + return get_connection_by_string (settings, id, nm_connection_get_id); +} + +NMRemoteConnection * +nm_remote_settings_get_connection_by_path (NMRemoteSettings *settings, const char *path) +{ + g_return_val_if_fail (NM_IS_REMOTE_SETTINGS (settings), NULL); + g_return_val_if_fail (path != NULL, NULL); + + return get_connection_by_string (settings, path, nm_connection_get_path); +} + +NMRemoteConnection * +nm_remote_settings_get_connection_by_uuid (NMRemoteSettings *settings, const char *uuid) +{ + g_return_val_if_fail (NM_IS_REMOTE_SETTINGS (settings), NULL); + g_return_val_if_fail (uuid != NULL, NULL); + + return get_connection_by_string (settings, uuid, nm_connection_get_uuid); +} + +static void +connection_visible_changed (GObject *object, + GParamSpec *pspec, + gpointer user_data) +{ + NMRemoteConnection *connection = NM_REMOTE_CONNECTION (object); + NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data); + + if (nm_remote_connection_get_visible (connection)) + g_signal_emit (self, signals[CONNECTION_ADDED], 0, connection); + else + g_signal_emit (self, signals[CONNECTION_REMOVED], 0, connection); +} + +static void +cleanup_connection (NMRemoteSettings *self, + NMRemoteConnection *remote) +{ + g_signal_handlers_disconnect_by_func (remote, G_CALLBACK (connection_visible_changed), self); +} + +static void +connection_removed (NMRemoteSettings *self, + NMRemoteConnection *remote) +{ + NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); + gboolean still_exists = FALSE; + int i; + + /* Check if the connection was actually removed or if it just turned invisible. */ + for (i = 0; i < priv->all_connections->len; i++) { + if (remote == priv->all_connections->pdata[i]) { + still_exists = TRUE; + break; + } + } + + if (!still_exists) + cleanup_connection (self, remote); + + /* Allow the signal to propagate if and only if @remote was in visible_connections */ + if (!g_ptr_array_remove (priv->visible_connections, remote)) + g_signal_stop_emission (self, signals[CONNECTION_REMOVED], 0); +} + +static void +connection_added (NMRemoteSettings *self, + NMRemoteConnection *remote) +{ + NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); + AddConnectionInfo *addinfo; + const char *path; + + if (!g_signal_handler_find (remote, G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, 0, 0, NULL, + G_CALLBACK (connection_visible_changed), self)) { + g_signal_connect (remote, + "notify::" NM_REMOTE_CONNECTION_VISIBLE, + G_CALLBACK (connection_visible_changed), + self); + } + + if (nm_remote_connection_get_visible (remote)) + g_ptr_array_add (priv->visible_connections, remote); + else + g_signal_stop_emission (self, signals[CONNECTION_ADDED], 0); + + path = nm_connection_get_path (NM_CONNECTION (remote)); + addinfo = add_connection_info_find (self, path); + if (addinfo) + add_connection_info_complete (self, addinfo, remote, NULL); +} + +static void +object_creation_failed (NMObject *object, const char *failed_path) +{ + NMRemoteSettings *self = NM_REMOTE_SETTINGS (object); + AddConnectionInfo *addinfo; + GError *add_error; + + addinfo = add_connection_info_find (self, failed_path); + if (addinfo) { + add_error = g_error_new_literal (NM_CLIENT_ERROR, + NM_CLIENT_ERROR_OBJECT_CREATION_FAILED, + _("Connection removed before it was initialized")); + add_connection_info_complete (self, addinfo, NULL, add_error); + g_error_free (add_error); + } +} + +const GPtrArray * +nm_remote_settings_get_connections (NMRemoteSettings *settings) +{ + g_return_val_if_fail (NM_IS_REMOTE_SETTINGS (settings), NULL); + + return NM_REMOTE_SETTINGS_GET_PRIVATE (settings)->visible_connections; +} + +static void +add_connection_done (GObject *proxy, GAsyncResult *result, gpointer user_data) +{ + AddConnectionInfo *info = user_data; + GError *error = NULL; + + if (info->saved) { + nmdbus_settings_call_add_connection_finish (NMDBUS_SETTINGS (proxy), + &info->path, + result, &error); + } else { + nmdbus_settings_call_add_connection_unsaved_finish (NMDBUS_SETTINGS (proxy), + &info->path, + result, &error); + } + + if (error) { + g_dbus_error_strip_remote_error (error); + add_connection_info_complete (info->self, info, NULL, error); + g_clear_error (&error); + } + + /* On success, we still have to wait until the connection is fully + * initialized before calling the callback. + */ +} + +void +nm_remote_settings_add_connection_async (NMRemoteSettings *settings, + NMConnection *connection, + gboolean save_to_disk, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + NMRemoteSettingsPrivate *priv; + AddConnectionInfo *info; + GVariant *new_settings; + + g_return_if_fail (NM_IS_REMOTE_SETTINGS (settings)); + g_return_if_fail (NM_IS_CONNECTION (connection)); + + priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings); + + info = g_slice_new0 (AddConnectionInfo); + info->self = settings; + info->simple = g_simple_async_result_new (G_OBJECT (settings), callback, user_data, + nm_remote_settings_add_connection_async); + info->saved = save_to_disk; + + new_settings = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL); + + if (save_to_disk) { + nmdbus_settings_call_add_connection (priv->proxy, + new_settings, + NULL, + add_connection_done, info); + } else { + nmdbus_settings_call_add_connection_unsaved (priv->proxy, + new_settings, + NULL, + add_connection_done, info); + } + + priv->add_list = g_slist_append (priv->add_list, info); +} + +NMRemoteConnection * +nm_remote_settings_add_connection_finish (NMRemoteSettings *settings, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (settings), nm_remote_settings_add_connection_async), NULL); + + simple = G_SIMPLE_ASYNC_RESULT (result); + if (g_simple_async_result_propagate_error (simple, error)) + return NULL; + else + return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple)); +} + +gboolean +nm_remote_settings_load_connections (NMRemoteSettings *settings, + char **filenames, + char ***failures, + GCancellable *cancellable, + GError **error) +{ + NMRemoteSettingsPrivate *priv; + gboolean success; + + g_return_val_if_fail (NM_IS_REMOTE_SETTINGS (settings), FALSE); + g_return_val_if_fail (filenames != NULL, FALSE); + + priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings); + + if (!nmdbus_settings_call_load_connections_sync (priv->proxy, + (const char * const *) filenames, + &success, + failures, + cancellable, error)) { + if (error && *error) + g_dbus_error_strip_remote_error (*error); + success = FALSE; + } + return success; +} + +static void +load_connections_cb (GObject *proxy, GAsyncResult *result, gpointer user_data) +{ + GSimpleAsyncResult *simple = user_data; + GError *error = NULL; + gboolean success; + char **failures = NULL; + + if (nmdbus_settings_call_load_connections_finish (NMDBUS_SETTINGS (proxy), + &success, &failures, + result, &error)) + g_simple_async_result_set_op_res_gpointer (simple, failures, (GDestroyNotify) g_strfreev); + else { + g_dbus_error_strip_remote_error (error); + g_simple_async_result_take_error (simple, error); + } + + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +void +nm_remote_settings_load_connections_async (NMRemoteSettings *settings, + char **filenames, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + NMRemoteSettingsPrivate *priv; + GSimpleAsyncResult *simple; + + g_return_if_fail (NM_IS_REMOTE_SETTINGS (settings)); + g_return_if_fail (filenames != NULL); + + priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings); + + simple = g_simple_async_result_new (G_OBJECT (settings), callback, user_data, + nm_remote_settings_load_connections_async); + + nmdbus_settings_call_load_connections (priv->proxy, + (const char * const *) filenames, + cancellable, load_connections_cb, simple); +} + +gboolean +nm_remote_settings_load_connections_finish (NMRemoteSettings *settings, + char ***failures, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (settings), nm_remote_settings_load_connections_async), FALSE); + + simple = G_SIMPLE_ASYNC_RESULT (result); + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + else { + *failures = g_strdupv (g_simple_async_result_get_op_res_gpointer (simple)); + return TRUE; + } +} + +gboolean +nm_remote_settings_reload_connections (NMRemoteSettings *settings, + GCancellable *cancellable, + GError **error) +{ + NMRemoteSettingsPrivate *priv; + gboolean success; + + g_return_val_if_fail (NM_IS_REMOTE_SETTINGS (settings), FALSE); + + priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings); + + if (!nmdbus_settings_call_reload_connections_sync (priv->proxy, &success, + cancellable, error)) { + if (error && *error) + g_dbus_error_strip_remote_error (*error); + success = FALSE; + } + + return success; +} + +static void +reload_connections_cb (GObject *proxy, GAsyncResult *result, gpointer user_data) +{ + GSimpleAsyncResult *simple = user_data; + gboolean success; + GError *error = NULL; + + if (nmdbus_settings_call_reload_connections_finish (NMDBUS_SETTINGS (proxy), + &success, + result, &error)) + g_simple_async_result_set_op_res_gboolean (simple, success); + else { + g_dbus_error_strip_remote_error (error); + g_simple_async_result_take_error (simple, error); + } + + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +void +nm_remote_settings_reload_connections_async (NMRemoteSettings *settings, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + NMRemoteSettingsPrivate *priv; + GSimpleAsyncResult *simple; + + g_return_if_fail (NM_IS_REMOTE_SETTINGS (settings)); + + priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings); + + simple = g_simple_async_result_new (G_OBJECT (settings), callback, user_data, + nm_remote_settings_reload_connections_async); + + nmdbus_settings_call_reload_connections (priv->proxy, cancellable, + reload_connections_cb, simple); +} + +gboolean +nm_remote_settings_reload_connections_finish (NMRemoteSettings *settings, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (settings), nm_remote_settings_reload_connections_async), FALSE); + + simple = G_SIMPLE_ASYNC_RESULT (result); + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + else + return g_simple_async_result_get_op_res_gboolean (simple); +} + +gboolean +nm_remote_settings_save_hostname (NMRemoteSettings *settings, + const char *hostname, + GCancellable *cancellable, + GError **error) +{ + NMRemoteSettingsPrivate *priv; + gboolean ret; + + + g_return_val_if_fail (NM_IS_REMOTE_SETTINGS (settings), FALSE); + + priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings); + + ret = nmdbus_settings_call_save_hostname_sync (priv->proxy, + hostname ? hostname : "", + cancellable, error); + if (error && *error) + g_dbus_error_strip_remote_error (*error); + return ret; +} + +static void +save_hostname_cb (GObject *proxy, + GAsyncResult *result, + gpointer user_data) +{ + GSimpleAsyncResult *simple = user_data; + GError *error = NULL; + + if (nmdbus_settings_call_save_hostname_finish (NMDBUS_SETTINGS (proxy), result, &error)) + g_simple_async_result_set_op_res_gboolean (simple, TRUE); + else { + g_dbus_error_strip_remote_error (error); + g_simple_async_result_take_error (simple, error); + } + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +void +nm_remote_settings_save_hostname_async (NMRemoteSettings *settings, + const char *hostname, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + NMRemoteSettingsPrivate *priv; + GSimpleAsyncResult *simple; + + g_return_if_fail (NM_IS_REMOTE_SETTINGS (settings)); + + priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings); + + simple = g_simple_async_result_new (G_OBJECT (settings), callback, user_data, + nm_remote_settings_save_hostname_async); + + nmdbus_settings_call_save_hostname (priv->proxy, + hostname ? hostname : "", + cancellable, save_hostname_cb, simple); +} + +gboolean +nm_remote_settings_save_hostname_finish (NMRemoteSettings *settings, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (settings), nm_remote_settings_save_hostname_async), FALSE); + + simple = G_SIMPLE_ASYNC_RESULT (result); + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + else + return g_simple_async_result_get_op_res_gboolean (simple); +} + +static void +updated_properties (GObject *object, GAsyncResult *result, gpointer user_data) +{ + GError *error = NULL; + + if (!_nm_object_reload_properties_finish (NM_OBJECT (object), result, &error)) { + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + g_warning ("%s: error reading NMRemoteSettings properties: %s", __func__, error->message); + g_error_free (error); + } +} + +static void +nm_running_changed (GObject *object, + GParamSpec *pspec, + gpointer user_data) +{ + NMRemoteSettings *self = NM_REMOTE_SETTINGS (object); + NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); + + g_object_freeze_notify (object); + + if (!_nm_object_get_nm_running (NM_OBJECT (self))) { + GPtrArray *connections; + int i; + + NM_UTILS_CLEAR_CANCELLABLE (priv->props_cancellable); + + /* Clear connections */ + connections = priv->all_connections; + priv->all_connections = g_ptr_array_new (); + for (i = 0; i < connections->len; i++) + g_signal_emit (self, signals[CONNECTION_REMOVED], 0, connections->pdata[i]); + g_ptr_array_unref (connections); + + /* Clear properties */ + if (priv->hostname) { + g_free (priv->hostname); + priv->hostname = NULL; + g_object_notify (G_OBJECT (self), NM_REMOTE_SETTINGS_HOSTNAME); + } + + if (priv->can_modify) { + priv->can_modify = FALSE; + g_object_notify (G_OBJECT (self), NM_REMOTE_SETTINGS_CAN_MODIFY); + } + + _nm_object_suppress_property_updates (NM_OBJECT (self), TRUE); + } else { + _nm_object_suppress_property_updates (NM_OBJECT (self), FALSE); + + NM_UTILS_CLEAR_CANCELLABLE (priv->props_cancellable); + priv->props_cancellable = g_cancellable_new (); + _nm_object_reload_properties_async (NM_OBJECT (self), priv->props_cancellable, updated_properties, self); + } + + g_object_thaw_notify (object); +} + +/****************************************************************/ + +static void +nm_remote_settings_init (NMRemoteSettings *self) +{ + NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); + + priv->all_connections = g_ptr_array_new (); + priv->visible_connections = g_ptr_array_new (); +} + +static void +init_dbus (NMObject *object) +{ + NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (object); + const NMPropertiesInfo property_info[] = { + { NM_REMOTE_SETTINGS_CONNECTIONS, &priv->all_connections, NULL, NM_TYPE_REMOTE_CONNECTION, "connection" }, + { NM_REMOTE_SETTINGS_HOSTNAME, &priv->hostname }, + { NM_REMOTE_SETTINGS_CAN_MODIFY, &priv->can_modify }, + { NULL }, + }; + + NM_OBJECT_CLASS (nm_remote_settings_parent_class)->init_dbus (object); + + priv->proxy = NMDBUS_SETTINGS (_nm_object_get_proxy (object, NM_DBUS_INTERFACE_SETTINGS)); + _nm_object_register_properties (object, + NM_DBUS_INTERFACE_SETTINGS, + property_info); + + g_signal_connect (object, "notify::" NM_OBJECT_NM_RUNNING, + G_CALLBACK (nm_running_changed), object); +} + +static GObject * +constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) +{ + guint i; + const char *dbus_path; + + /* Fill in the right D-Bus path if none was specified */ + for (i = 0; i < n_construct_params; i++) { + if (strcmp (construct_params[i].pspec->name, NM_OBJECT_PATH) == 0) { + dbus_path = g_value_get_string (construct_params[i].value); + if (dbus_path == NULL) { + g_value_set_static_string (construct_params[i].value, NM_DBUS_PATH_SETTINGS); + } else { + if (!g_variant_is_object_path (dbus_path)) { + g_warning ("Passed D-Bus object path '%s' is invalid; using default '%s' instead", + dbus_path, NM_DBUS_PATH); + g_value_set_static_string (construct_params[i].value, NM_DBUS_PATH_SETTINGS); + } + } + break; + } + } + + return G_OBJECT_CLASS (nm_remote_settings_parent_class)->constructor (type, + n_construct_params, + construct_params); +} + +static void +dispose (GObject *object) +{ + NMRemoteSettings *self = NM_REMOTE_SETTINGS (object); + NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); + int i; + + if (priv->all_connections) { + for (i = 0; i < priv->all_connections->len; i++) + cleanup_connection (self, priv->all_connections->pdata[i]); + g_clear_pointer (&priv->all_connections, g_ptr_array_unref); + } + + g_signal_handlers_disconnect_by_func (object, G_CALLBACK (nm_running_changed), self); + + g_clear_pointer (&priv->visible_connections, g_ptr_array_unref); + g_clear_pointer (&priv->hostname, g_free); + + G_OBJECT_CLASS (nm_remote_settings_parent_class)->dispose (object); +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_CONNECTIONS: + g_value_take_boxed (value, _nm_utils_copy_object_array (priv->visible_connections)); + break; + case PROP_HOSTNAME: + g_value_set_string (value, priv->hostname); + break; + case PROP_CAN_MODIFY: + g_value_set_boolean (value, priv->can_modify); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_remote_settings_class_init (NMRemoteSettingsClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (class); + + g_type_class_add_private (class, sizeof (NMRemoteSettingsPrivate)); + + _nm_object_class_add_interface (nm_object_class, NM_DBUS_INTERFACE_SETTINGS); + _nm_dbus_register_proxy_type (NM_DBUS_INTERFACE_SETTINGS, NMDBUS_TYPE_SETTINGS_PROXY); + + /* Virtual methods */ + object_class->constructor = constructor; + object_class->get_property = get_property; + object_class->dispose = dispose; + + nm_object_class->init_dbus = init_dbus; + nm_object_class->object_creation_failed = object_creation_failed; + + class->connection_added = connection_added; + class->connection_removed = connection_removed; + + /* Properties */ + + g_object_class_install_property + (object_class, PROP_CONNECTIONS, + g_param_spec_boxed (NM_REMOTE_SETTINGS_CONNECTIONS, "", "", + G_TYPE_PTR_ARRAY, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_HOSTNAME, + g_param_spec_string (NM_REMOTE_SETTINGS_HOSTNAME, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_CAN_MODIFY, + g_param_spec_boolean (NM_REMOTE_SETTINGS_CAN_MODIFY, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /* Signals */ + signals[CONNECTION_ADDED] = + g_signal_new (NM_REMOTE_SETTINGS_CONNECTION_ADDED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMRemoteSettingsClass, connection_added), + NULL, NULL, NULL, + G_TYPE_NONE, 1, + NM_TYPE_REMOTE_CONNECTION); + + signals[CONNECTION_REMOVED] = + g_signal_new (NM_REMOTE_SETTINGS_CONNECTION_REMOVED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMRemoteSettingsClass, connection_removed), + NULL, NULL, NULL, + G_TYPE_NONE, 1, + NM_TYPE_REMOTE_CONNECTION); +} diff --git a/libnm/nm-remote-settings.h b/libnm/nm-remote-settings.h new file mode 100644 index 00000000..1ffc0bf2 --- /dev/null +++ b/libnm/nm-remote-settings.h @@ -0,0 +1,127 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2008 Novell, Inc. + * Copyright 2009 - 2011 Red Hat, Inc. + */ + +#ifndef __NM_REMOTE_SETTINGS_H__ +#define __NM_REMOTE_SETTINGS_H__ + +#include <nm-object.h> + +G_BEGIN_DECLS + +#define NM_TYPE_REMOTE_SETTINGS (nm_remote_settings_get_type ()) +#define NM_REMOTE_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_REMOTE_SETTINGS, NMRemoteSettings)) +#define NM_REMOTE_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_REMOTE_SETTINGS, NMRemoteSettingsClass)) +#define NM_IS_REMOTE_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_REMOTE_SETTINGS)) +#define NM_IS_REMOTE_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_REMOTE_SETTINGS)) +#define NM_REMOTE_SETTINGS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_REMOTE_SETTINGS, NMRemoteSettingsClass)) + +#define NM_REMOTE_SETTINGS_CONNECTIONS "connections" +#define NM_REMOTE_SETTINGS_HOSTNAME "hostname" +#define NM_REMOTE_SETTINGS_CAN_MODIFY "can-modify" + +#define NM_REMOTE_SETTINGS_CONNECTION_ADDED "connection-added" +#define NM_REMOTE_SETTINGS_CONNECTION_REMOVED "connection-removed" + +typedef struct _NMRemoteSettings NMRemoteSettings; +typedef struct _NMRemoteSettingsClass NMRemoteSettingsClass; + +struct _NMRemoteSettings { + NMObject parent; +}; + +struct _NMRemoteSettingsClass { + NMObjectClass parent; + + /* Signals */ + void (*connection_added) (NMRemoteSettings *settings, + NMRemoteConnection *connection); + void (*connection_removed) (NMRemoteSettings *settings, + NMRemoteConnection *connection); + + /*< private >*/ + gpointer padding[8]; +}; + +GType nm_remote_settings_get_type (void); + +const GPtrArray *nm_remote_settings_get_connections (NMRemoteSettings *settings); + +NMRemoteConnection *nm_remote_settings_get_connection_by_id (NMRemoteSettings *settings, + const char *id); + +NMRemoteConnection *nm_remote_settings_get_connection_by_path (NMRemoteSettings *settings, + const char *path); + +NMRemoteConnection *nm_remote_settings_get_connection_by_uuid (NMRemoteSettings *settings, + const char *uuid); + +void nm_remote_settings_add_connection_async (NMRemoteSettings *settings, + NMConnection *connection, + gboolean save_to_disk, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +NMRemoteConnection *nm_remote_settings_add_connection_finish (NMRemoteSettings *settings, + GAsyncResult *result, + GError **error); + +gboolean nm_remote_settings_load_connections (NMRemoteSettings *settings, + char **filenames, + char ***failures, + GCancellable *cancellable, + GError **error); +void nm_remote_settings_load_connections_async (NMRemoteSettings *settings, + char **filenames, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean nm_remote_settings_load_connections_finish (NMRemoteSettings *settings, + char ***failures, + GAsyncResult *result, + GError **error); + +gboolean nm_remote_settings_reload_connections (NMRemoteSettings *settings, + GCancellable *cancellable, + GError **error); +void nm_remote_settings_reload_connections_async (NMRemoteSettings *settings, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean nm_remote_settings_reload_connections_finish (NMRemoteSettings *settings, + GAsyncResult *result, + GError **error); + +gboolean nm_remote_settings_save_hostname (NMRemoteSettings *settings, + const char *hostname, + GCancellable *cancellable, + GError **error); +void nm_remote_settings_save_hostname_async (NMRemoteSettings *settings, + const char *hostname, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean nm_remote_settings_save_hostname_finish (NMRemoteSettings *settings, + GAsyncResult *result, + GError **error); + +G_END_DECLS + +#endif /* __NM_REMOTE_SETTINGS_H__ */ diff --git a/libnm/nm-secret-agent-old.c b/libnm/nm-secret-agent-old.c new file mode 100644 index 00000000..606c4099 --- /dev/null +++ b/libnm/nm-secret-agent-old.c @@ -0,0 +1,1366 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2010 - 2011 Red Hat, Inc. + */ + +#include "config.h" + +#include <string.h> + +#include "nm-glib-compat.h" +#include "nm-dbus-interface.h" +#include "nm-secret-agent-old.h" +#include "nm-enum-types.h" +#include "nm-dbus-helpers.h" +#include "nm-simple-connection.h" + +#include "nmdbus-secret-agent.h" +#include "nmdbus-agent-manager.h" + +static void nm_secret_agent_old_initable_iface_init (GInitableIface *iface); +static void nm_secret_agent_old_async_initable_iface_init (GAsyncInitableIface *iface); +G_DEFINE_ABSTRACT_TYPE_WITH_CODE (NMSecretAgentOld, nm_secret_agent_old, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_secret_agent_old_initable_iface_init); + G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_secret_agent_old_async_initable_iface_init); + ) + +#define NM_SECRET_AGENT_OLD_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SECRET_AGENT_OLD, NMSecretAgentOldPrivate)) + +typedef struct { + gboolean registered; + gboolean registering; + NMSecretAgentCapabilities capabilities; + + GDBusConnection *bus; + gboolean private_bus; + gboolean session_bus; + NMDBusAgentManager *manager_proxy; + NMDBusSecretAgent *dbus_secret_agent; + + /* GetSecretsInfo structs of in-flight GetSecrets requests */ + GSList *pending_gets; + + char *identifier; + gboolean auto_register; + gboolean suppress_auto; +} NMSecretAgentOldPrivate; + +enum { + PROP_0, + PROP_IDENTIFIER, + PROP_AUTO_REGISTER, + PROP_REGISTERED, + PROP_CAPABILITIES, + + LAST_PROP +}; + +/*************************************************************/ + +static void +_internal_unregister (NMSecretAgentOld *self) +{ + NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); + + if (priv->registered) { + g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (priv->dbus_secret_agent)); + priv->registered = FALSE; + priv->registering = FALSE; + g_object_notify (G_OBJECT (self), NM_SECRET_AGENT_OLD_REGISTERED); + } +} + +typedef struct { + char *path; + char *setting_name; + GDBusMethodInvocation *context; +} GetSecretsInfo; + +static void +get_secrets_info_finalize (NMSecretAgentOld *self, GetSecretsInfo *info) +{ + NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); + + g_return_if_fail (info != NULL); + + priv->pending_gets = g_slist_remove (priv->pending_gets, info); + + g_free (info->path); + g_free (info->setting_name); + memset (info, 0, sizeof (*info)); + g_free (info); +} + +static inline gboolean +should_auto_register (NMSecretAgentOld *self) +{ + NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); + + return ( priv->auto_register + && !priv->suppress_auto + && !priv->registered + && !priv->registering); +} + +static void +name_owner_changed (GObject *proxy, + GParamSpec *pspec, + gpointer user_data) +{ + NMSecretAgentOld *self = NM_SECRET_AGENT_OLD (user_data); + NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); + GSList *iter; + char *owner; + + owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (proxy)); + if (owner != NULL) { + if (should_auto_register (self)) + nm_secret_agent_old_register_async (self, NULL, NULL, NULL); + g_free (owner); + } else { + /* Cancel any pending secrets requests */ + for (iter = priv->pending_gets; iter; iter = g_slist_next (iter)) { + GetSecretsInfo *info = iter->data; + + NM_SECRET_AGENT_OLD_GET_CLASS (self)->cancel_get_secrets (self, + info->path, + info->setting_name); + } + g_slist_free (priv->pending_gets); + priv->pending_gets = NULL; + + _internal_unregister (self); + } +} + +static gboolean +verify_sender (NMSecretAgentOld *self, + GDBusMethodInvocation *context, + GError **error) +{ + NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); + char *nm_owner; + const char *sender; + guint32 sender_uid; + GVariant *ret; + GError *local = NULL; + + g_return_val_if_fail (context != NULL, FALSE); + + /* Private bus connection is always to NetworkManager, which is always + * UID 0. + */ + if (priv->private_bus) + return TRUE; + + /* Verify that the sender is the same as NetworkManager's bus name owner. */ + + nm_owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (priv->manager_proxy)); + if (!nm_owner) { + g_set_error_literal (error, + NM_SECRET_AGENT_ERROR, + NM_SECRET_AGENT_ERROR_PERMISSION_DENIED, + "NetworkManager bus name owner unknown."); + return FALSE; + } + + sender = g_dbus_method_invocation_get_sender (context); + if (!sender) { + g_set_error_literal (error, + NM_SECRET_AGENT_ERROR, + NM_SECRET_AGENT_ERROR_PERMISSION_DENIED, + "Failed to get request sender."); + g_free (nm_owner); + return FALSE; + } + + /* Check that the sender matches the current NM bus name owner */ + if (strcmp (sender, nm_owner) != 0) { + g_set_error_literal (error, + NM_SECRET_AGENT_ERROR, + NM_SECRET_AGENT_ERROR_PERMISSION_DENIED, + "Request sender does not match NetworkManager bus name owner."); + g_free (nm_owner); + return FALSE; + } + g_free (nm_owner); + + /* If we're connected to the session bus, then this must be a test program, + * so skip the UID check. + */ + if (priv->session_bus) + return TRUE; + + /* Check the UID of the sender */ + ret = g_dbus_connection_call_sync (priv->bus, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "GetConnectionUnixUser", + g_variant_new ("(s)", sender), + G_VARIANT_TYPE ("(u)"), + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, &local); + if (!ret) { + char *remote_error = g_dbus_error_get_remote_error (local); + + g_dbus_error_strip_remote_error (local); + g_set_error (error, + NM_SECRET_AGENT_ERROR, + NM_SECRET_AGENT_ERROR_PERMISSION_DENIED, + "Failed to request unix user: (%s) %s.", + remote_error ? remote_error : "", + local->message); + g_free (remote_error); + g_error_free (local); + return FALSE; + } + g_variant_get (ret, "(u)", &sender_uid); + g_variant_unref (ret); + + /* We only accept requests from NM, which always runs as root */ + if (0 != sender_uid) { + g_set_error_literal (error, + NM_SECRET_AGENT_ERROR, + NM_SECRET_AGENT_ERROR_PERMISSION_DENIED, + "Request sender is not root."); + return FALSE; + } + + return TRUE; +} + +static gboolean +verify_request (NMSecretAgentOld *self, + GDBusMethodInvocation *context, + GVariant *connection_dict, + const char *connection_path, + NMConnection **out_connection, + GError **error) +{ + NMConnection *connection = NULL; + GError *local = NULL; + + if (!verify_sender (self, context, error)) + return FALSE; + + /* No connection? If the sender verified, then we allow the request */ + if (connection_dict == NULL) + return TRUE; + + /* If we have a connection dictionary, we require a path too */ + if (connection_path == NULL) { + g_set_error_literal (error, + NM_SECRET_AGENT_ERROR, + NM_SECRET_AGENT_ERROR_INVALID_CONNECTION, + "Invalid connection: no connection path given."); + return FALSE; + } + + /* Make sure the given connection is valid */ + g_assert (out_connection); + connection = nm_simple_connection_new_from_dbus (connection_dict, &local); + if (connection) { + nm_connection_set_path (connection, connection_path); + *out_connection = connection; + } else { + g_set_error (error, + NM_SECRET_AGENT_ERROR, + NM_SECRET_AGENT_ERROR_INVALID_CONNECTION, + "Invalid connection: %s", local->message); + g_clear_error (&local); + } + + return !!connection; +} + +static void +get_secrets_cb (NMSecretAgentOld *self, + NMConnection *connection, + GVariant *secrets, + GError *error, + gpointer user_data) +{ + GetSecretsInfo *info = user_data; + + if (error) + g_dbus_method_invocation_return_gerror (info->context, error); + else { + g_dbus_method_invocation_return_value (info->context, + g_variant_new ("(@a{sa{sv}})", secrets)); + } + + /* Remove the request from internal tracking */ + get_secrets_info_finalize (self, info); +} + +static void +impl_secret_agent_old_get_secrets (NMSecretAgentOld *self, + GDBusMethodInvocation *context, + GVariant *connection_dict, + const char *connection_path, + const char *setting_name, + const char * const *hints, + guint flags, + gpointer user_data) +{ + NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); + GError *error = NULL; + NMConnection *connection = NULL; + GetSecretsInfo *info; + + /* Make sure the request comes from NetworkManager and is valid */ + if (!verify_request (self, context, connection_dict, connection_path, &connection, &error)) { + g_dbus_method_invocation_take_error (context, error); + return; + } + + info = g_malloc0 (sizeof (GetSecretsInfo)); + info->path = g_strdup (connection_path); + info->setting_name = g_strdup (setting_name); + info->context = context; + priv->pending_gets = g_slist_append (priv->pending_gets, info); + + NM_SECRET_AGENT_OLD_GET_CLASS (self)->get_secrets (self, + connection, + connection_path, + setting_name, + (const char **) hints, + flags, + get_secrets_cb, + info); + g_object_unref (connection); +} + +static GetSecretsInfo * +find_get_secrets_info (GSList *list, const char *path, const char *setting_name) +{ + GSList *iter; + + for (iter = list; iter; iter = g_slist_next (iter)) { + GetSecretsInfo *candidate = iter->data; + + if ( g_strcmp0 (path, candidate->path) == 0 + && g_strcmp0 (setting_name, candidate->setting_name) == 0) + return candidate; + } + return NULL; +} + +static void +impl_secret_agent_old_cancel_get_secrets (NMSecretAgentOld *self, + GDBusMethodInvocation *context, + const char *connection_path, + const char *setting_name, + gpointer user_data) +{ + NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); + GError *error = NULL; + GetSecretsInfo *info; + + /* Make sure the request comes from NetworkManager and is valid */ + if (!verify_request (self, context, NULL, NULL, NULL, &error)) { + g_dbus_method_invocation_take_error (context, error); + return; + } + + info = find_get_secrets_info (priv->pending_gets, connection_path, setting_name); + if (!info) { + g_dbus_method_invocation_return_error (context, + NM_SECRET_AGENT_ERROR, + NM_SECRET_AGENT_ERROR_FAILED, + "No secrets request in progress for this connection."); + return; + } + + /* Send the cancel request up to the subclass and finalize it */ + NM_SECRET_AGENT_OLD_GET_CLASS (self)->cancel_get_secrets (self, + info->path, + info->setting_name); + g_dbus_method_invocation_return_value (context, NULL); +} + +static void +save_secrets_cb (NMSecretAgentOld *self, + NMConnection *connection, + GError *error, + gpointer user_data) +{ + GDBusMethodInvocation *context = user_data; + + if (error) + g_dbus_method_invocation_return_gerror (context, error); + else + g_dbus_method_invocation_return_value (context, NULL); +} + +static void +impl_secret_agent_old_save_secrets (NMSecretAgentOld *self, + GDBusMethodInvocation *context, + GVariant *connection_dict, + const char *connection_path, + gpointer user_data) +{ + GError *error = NULL; + NMConnection *connection = NULL; + + /* Make sure the request comes from NetworkManager and is valid */ + if (!verify_request (self, context, connection_dict, connection_path, &connection, &error)) { + g_dbus_method_invocation_take_error (context, error); + return; + } + + NM_SECRET_AGENT_OLD_GET_CLASS (self)->save_secrets (self, + connection, + connection_path, + save_secrets_cb, + context); + g_object_unref (connection); +} + +static void +delete_secrets_cb (NMSecretAgentOld *self, + NMConnection *connection, + GError *error, + gpointer user_data) +{ + GDBusMethodInvocation *context = user_data; + + if (error) + g_dbus_method_invocation_return_gerror (context, error); + else + g_dbus_method_invocation_return_value (context, NULL); +} + +static void +impl_secret_agent_old_delete_secrets (NMSecretAgentOld *self, + GDBusMethodInvocation *context, + GVariant *connection_dict, + const char *connection_path, + gpointer user_data) +{ + GError *error = NULL; + NMConnection *connection = NULL; + + /* Make sure the request comes from NetworkManager and is valid */ + if (!verify_request (self, context, connection_dict, connection_path, &connection, &error)) { + g_dbus_method_invocation_take_error (context, error); + return; + } + + NM_SECRET_AGENT_OLD_GET_CLASS (self)->delete_secrets (self, + connection, + connection_path, + delete_secrets_cb, + context); + g_object_unref (connection); +} + +/**************************************************************/ + +static gboolean +check_nm_running (NMSecretAgentOld *self, GError **error) +{ + NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); + char *owner; + + if (priv->private_bus) + return TRUE; + owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (priv->manager_proxy)); + if (owner) { + g_free (owner); + return TRUE; + } + + g_set_error (error, NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_FAILED, + "NetworkManager is not running"); + return FALSE; +} + +/**************************************************************/ + +/** + * nm_secret_agent_old_register: + * @self: a #NMSecretAgentOld + * @cancellable: a #GCancellable, or %NULL + * @error: return location for a #GError, or %NULL + * + * Registers the #NMSecretAgentOld with the NetworkManager secret manager, + * indicating to NetworkManager that the agent is able to provide and save + * secrets for connections on behalf of its user. + * + * It is a programmer error to attempt to register an agent that is already + * registered, or in the process of registering. + * + * Returns: %TRUE if registration was successful, %FALSE on error. + **/ +gboolean +nm_secret_agent_old_register (NMSecretAgentOld *self, + GCancellable *cancellable, + GError **error) +{ + NMSecretAgentOldPrivate *priv; + NMSecretAgentOldClass *class; + + g_return_val_if_fail (NM_IS_SECRET_AGENT_OLD (self), FALSE); + + priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); + + g_return_val_if_fail (priv->registered == FALSE, FALSE); + g_return_val_if_fail (priv->registering == FALSE, FALSE); + g_return_val_if_fail (priv->bus != NULL, FALSE); + g_return_val_if_fail (priv->manager_proxy != NULL, FALSE); + + /* Also make sure the subclass can actually respond to secrets requests */ + class = NM_SECRET_AGENT_OLD_GET_CLASS (self); + g_return_val_if_fail (class->get_secrets != NULL, FALSE); + g_return_val_if_fail (class->save_secrets != NULL, FALSE); + g_return_val_if_fail (class->delete_secrets != NULL, FALSE); + + if (!check_nm_running (self, error)) + return FALSE; + + priv->suppress_auto = FALSE; + + /* Export our secret agent interface before registering with the manager */ + if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (priv->dbus_secret_agent), + priv->bus, + NM_DBUS_PATH_SECRET_AGENT, + error)) + return FALSE; + + priv->registering = TRUE; + if (nmdbus_agent_manager_call_register_with_capabilities_sync (priv->manager_proxy, + priv->identifier, + priv->capabilities, + cancellable, NULL)) + goto success; + + /* Might be an old NetworkManager that doesn't support capabilities; + * fall back to old Register() method instead. + */ + if (nmdbus_agent_manager_call_register_sync (priv->manager_proxy, + priv->identifier, + cancellable, NULL)) + goto success; + + /* Failure */ + priv->registering = FALSE; + _internal_unregister (self); + return FALSE; + +success: + priv->registering = FALSE; + priv->registered = TRUE; + g_object_notify (G_OBJECT (self), NM_SECRET_AGENT_OLD_REGISTERED); + return TRUE; +} + +static void +reg_result (NMSecretAgentOld *self, GSimpleAsyncResult *simple, GError *error) +{ + NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); + + priv->registering = FALSE; + + if (error) { + g_simple_async_result_take_error (simple, error); + g_simple_async_result_complete (simple); + + /* If registration failed we shouldn't expose ourselves on the bus */ + _internal_unregister (self); + } else { + priv->registered = TRUE; + g_object_notify (G_OBJECT (self), NM_SECRET_AGENT_OLD_REGISTERED); + + g_simple_async_result_set_op_res_gboolean (simple, TRUE); + g_simple_async_result_complete (simple); + } + + g_object_unref (simple); +} + +static void +reg_request_cb (GObject *proxy, + GAsyncResult *result, + gpointer user_data) +{ + GSimpleAsyncResult *simple = user_data; + NMSecretAgentOld *self; + NMSecretAgentOldPrivate *priv; + GError *error = NULL; + + self = NM_SECRET_AGENT_OLD (g_async_result_get_source_object (G_ASYNC_RESULT (simple))); + g_object_unref (self); /* drop extra ref added by get_source_object() */ + priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); + + if (!nmdbus_agent_manager_call_register_finish (NMDBUS_AGENT_MANAGER (proxy), result, &error)) + g_dbus_error_strip_remote_error (error); + reg_result (self, simple, error); + g_clear_error (&error); +} + +static void +reg_with_caps_cb (GObject *proxy, + GAsyncResult *result, + gpointer user_data) +{ + GSimpleAsyncResult *simple = user_data; + NMSecretAgentOld *self; + NMSecretAgentOldPrivate *priv; + + self = NM_SECRET_AGENT_OLD (g_async_result_get_source_object (G_ASYNC_RESULT (simple))); + g_object_unref (self); /* drop extra ref added by get_source_object() */ + priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); + + if (nmdbus_agent_manager_call_register_with_capabilities_finish (NMDBUS_AGENT_MANAGER (proxy), result, NULL)) { + reg_result (self, simple, NULL); + return; + } + + /* Might be an old NetworkManager that doesn't support capabilities; + * fall back to old Register() method instead. + */ + nmdbus_agent_manager_call_register (priv->manager_proxy, + priv->identifier, + NULL, reg_request_cb, simple); +} + +/** + * nm_secret_agent_old_register_async: + * @self: a #NMSecretAgentOld + * @cancellable: a #GCancellable, or %NULL + * @callback: callback to call when the agent is registered + * @user_data: data for @callback + * + * Asynchronously registers the #NMSecretAgentOld with the NetworkManager secret + * manager, indicating to NetworkManager that the agent is able to provide and + * save secrets for connections on behalf of its user. + * + * It is a programmer error to attempt to register an agent that is already + * registered, or in the process of registering. + **/ +void +nm_secret_agent_old_register_async (NMSecretAgentOld *self, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + NMSecretAgentOldPrivate *priv; + NMSecretAgentOldClass *class; + GSimpleAsyncResult *simple; + GError *error = NULL; + + g_return_if_fail (NM_IS_SECRET_AGENT_OLD (self)); + + priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); + + g_return_if_fail (priv->registered == FALSE); + g_return_if_fail (priv->registering == FALSE); + g_return_if_fail (priv->bus != NULL); + g_return_if_fail (priv->manager_proxy != NULL); + + /* Also make sure the subclass can actually respond to secrets requests */ + class = NM_SECRET_AGENT_OLD_GET_CLASS (self); + g_return_if_fail (class->get_secrets != NULL); + g_return_if_fail (class->save_secrets != NULL); + g_return_if_fail (class->delete_secrets != NULL); + + simple = g_simple_async_result_new (G_OBJECT (self), callback, user_data, + nm_secret_agent_old_register_async); + + if (!check_nm_running (self, &error)) { + g_simple_async_result_take_error (simple, error); + g_simple_async_result_complete_in_idle (simple); + g_object_unref (simple); + return; + } + + /* Export our secret agent interface before registering with the manager */ + if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (priv->dbus_secret_agent), + priv->bus, + NM_DBUS_PATH_SECRET_AGENT, + &error)) { + g_simple_async_result_take_error (simple, error); + g_simple_async_result_complete_in_idle (simple); + g_object_unref (simple); + return; + } + + priv->suppress_auto = FALSE; + priv->registering = TRUE; + + nmdbus_agent_manager_call_register_with_capabilities (priv->manager_proxy, + priv->identifier, + priv->capabilities, + NULL, + reg_with_caps_cb, simple); +} + +/** + * nm_secret_agent_old_register_finish: + * @self: a #NMSecretAgentOld + * @result: the result passed to the #GAsyncReadyCallback + * @error: return location for a #GError, or %NULL + * + * Gets the result of a call to nm_secret_agent_old_register_async(). + * + * Returns: %TRUE if registration was successful, %FALSE on error. + **/ +gboolean +nm_secret_agent_old_register_finish (NMSecretAgentOld *self, + GAsyncResult *result, + GError **error) +{ + g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self), nm_secret_agent_old_register_async), FALSE); + + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error)) + return FALSE; + else + return TRUE; +} + +/** + * nm_secret_agent_old_unregister: + * @self: a #NMSecretAgentOld + * @cancellable: a #GCancellable, or %NULL + * @error: return location for a #GError, or %NULL + * + * Unregisters the #NMSecretAgentOld with the NetworkManager secret manager, + * indicating to NetworkManager that the agent will no longer provide or + * store secrets on behalf of this user. + * + * It is a programmer error to attempt to unregister an agent that is not + * registered. + * + * Returns: %TRUE if unregistration was successful, %FALSE on error + **/ +gboolean +nm_secret_agent_old_unregister (NMSecretAgentOld *self, + GCancellable *cancellable, + GError **error) +{ + NMSecretAgentOldPrivate *priv; + gboolean success; + + g_return_val_if_fail (NM_IS_SECRET_AGENT_OLD (self), FALSE); + + priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); + + g_return_val_if_fail (priv->registered == TRUE, FALSE); + g_return_val_if_fail (priv->bus != NULL, FALSE); + g_return_val_if_fail (priv->manager_proxy != NULL, FALSE); + + priv->suppress_auto = TRUE; + + success = nmdbus_agent_manager_call_unregister_sync (priv->manager_proxy, cancellable, error); + if (error && *error) + g_dbus_error_strip_remote_error (*error); + _internal_unregister (self); + + return success; +} + +static void +unregister_cb (GObject *proxy, GAsyncResult *result, gpointer user_data) +{ + GSimpleAsyncResult *simple = user_data; + NMSecretAgentOld *self; + GError *error = NULL; + + self = NM_SECRET_AGENT_OLD (g_async_result_get_source_object (G_ASYNC_RESULT (simple))); + g_object_unref (self); /* drop extra ref added by get_source_object() */ + + _internal_unregister (self); + + if (nmdbus_agent_manager_call_unregister_finish (NMDBUS_AGENT_MANAGER (proxy), + result, &error)) + g_simple_async_result_set_op_res_gboolean (simple, TRUE); + else { + g_dbus_error_strip_remote_error (error); + g_simple_async_result_take_error (simple, error); + } + + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +/** + * nm_secret_agent_old_unregister_async: + * @self: a #NMSecretAgentOld + * @cancellable: a #GCancellable, or %NULL + * @callback: callback to call when the agent is unregistered + * @user_data: data for @callback + * + * Asynchronously unregisters the #NMSecretAgentOld with the NetworkManager secret + * manager, indicating to NetworkManager that the agent will no longer provide + * or store secrets on behalf of this user. + * + * It is a programmer error to attempt to unregister an agent that is not + * registered. + **/ +void +nm_secret_agent_old_unregister_async (NMSecretAgentOld *self, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + NMSecretAgentOldPrivate *priv; + GSimpleAsyncResult *simple; + GError *error = NULL; + + g_return_if_fail (NM_IS_SECRET_AGENT_OLD (self)); + + priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); + + g_return_if_fail (priv->registered == TRUE); + g_return_if_fail (priv->bus != NULL); + g_return_if_fail (priv->manager_proxy != NULL); + + simple = g_simple_async_result_new (G_OBJECT (self), callback, user_data, + nm_secret_agent_old_unregister_async); + + if (!check_nm_running (self, &error)) { + g_simple_async_result_take_error (simple, error); + g_simple_async_result_complete_in_idle (simple); + g_object_unref (simple); + return; + } + + priv->suppress_auto = TRUE; + + nmdbus_agent_manager_call_unregister (priv->manager_proxy, cancellable, + unregister_cb, simple); +} + +/** + * nm_secret_agent_old_unregister_finish: + * @self: a #NMSecretAgentOld + * @result: the result passed to the #GAsyncReadyCallback + * @error: return location for a #GError, or %NULL + * + * Gets the result of a call to nm_secret_agent_old_unregister_async(). + * + * Returns: %TRUE if unregistration was successful, %FALSE on error. + **/ +gboolean +nm_secret_agent_old_unregister_finish (NMSecretAgentOld *self, + GAsyncResult *result, + GError **error) +{ + g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self), nm_secret_agent_old_unregister_async), FALSE); + + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error)) + return FALSE; + else + return TRUE; +} + +/** + * nm_secret_agent_old_get_registered: + * @self: a #NMSecretAgentOld + * + * Returns: a %TRUE if the agent is registered, %FALSE if it is not. + **/ +gboolean +nm_secret_agent_old_get_registered (NMSecretAgentOld *self) +{ + g_return_val_if_fail (NM_IS_SECRET_AGENT_OLD (self), FALSE); + + return NM_SECRET_AGENT_OLD_GET_PRIVATE (self)->registered; +} + +/**************************************************************/ + +/** + * nm_secret_agent_old_get_secrets: + * @self: a #NMSecretAgentOld + * @connection: the #NMConnection for which we're asked secrets + * @setting_name: the name of the secret setting + * @hints: (array zero-terminated=1): hints to the agent + * @flags: flags that modify the behavior of the request + * @callback: (scope async): a callback, to be invoked when the operation is done + * @user_data: (closure): caller-specific data to be passed to @callback + * + * Asynchronously retrieves secrets belonging to @connection for the + * setting @setting_name. @flags indicate specific behavior that the secret + * agent should use when performing the request, for example returning only + * existing secrets without user interaction, or requesting entirely new + * secrets from the user. + * + * Virtual: get_secrets + */ +void +nm_secret_agent_old_get_secrets (NMSecretAgentOld *self, + NMConnection *connection, + const char *setting_name, + const char **hints, + NMSecretAgentGetSecretsFlags flags, + NMSecretAgentOldGetSecretsFunc callback, + gpointer user_data) +{ + g_return_if_fail (NM_IS_SECRET_AGENT_OLD (self)); + g_return_if_fail (NM_IS_CONNECTION (connection)); + g_return_if_fail (nm_connection_get_path (connection)); + g_return_if_fail (setting_name != NULL); + g_return_if_fail (strlen (setting_name) > 0); + g_return_if_fail (!(flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_ONLY_SYSTEM)); + g_return_if_fail (!(flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_NO_ERRORS)); + g_return_if_fail (callback != NULL); + + NM_SECRET_AGENT_OLD_GET_CLASS (self)->get_secrets (self, + connection, + nm_connection_get_path (connection), + setting_name, + hints, + flags, + callback, + user_data); +} + +/** + * nm_secret_agent_old_save_secrets: + * @self: a #NMSecretAgentOld + * @connection: a #NMConnection + * @callback: (scope async): a callback, to be invoked when the operation is done + * @user_data: (closure): caller-specific data to be passed to @callback + * + * Asynchronously ensures that all secrets inside @connection are stored to + * disk. + * + * Virtual: save_secrets + */ +void +nm_secret_agent_old_save_secrets (NMSecretAgentOld *self, + NMConnection *connection, + NMSecretAgentOldSaveSecretsFunc callback, + gpointer user_data) +{ + g_return_if_fail (NM_IS_SECRET_AGENT_OLD (self)); + g_return_if_fail (NM_IS_CONNECTION (connection)); + g_return_if_fail (nm_connection_get_path (connection)); + + NM_SECRET_AGENT_OLD_GET_CLASS (self)->save_secrets (self, + connection, + nm_connection_get_path (connection), + callback, + user_data); +} + +/** + * nm_secret_agent_old_delete_secrets: + * @self: a #NMSecretAgentOld + * @connection: a #NMConnection + * @callback: (scope async): a callback, to be invoked when the operation is done + * @user_data: (closure): caller-specific data to be passed to @callback + * + * Asynchronously asks the agent to delete all saved secrets belonging to + * @connection. + * + * Virtual: delete_secrets + */ +void +nm_secret_agent_old_delete_secrets (NMSecretAgentOld *self, + NMConnection *connection, + NMSecretAgentOldDeleteSecretsFunc callback, + gpointer user_data) +{ + g_return_if_fail (NM_IS_SECRET_AGENT_OLD (self)); + g_return_if_fail (NM_IS_CONNECTION (connection)); + g_return_if_fail (nm_connection_get_path (connection)); + + NM_SECRET_AGENT_OLD_GET_CLASS (self)->delete_secrets (self, + connection, + nm_connection_get_path (connection), + callback, + user_data); +} + +/**************************************************************/ + +static gboolean +validate_identifier (const char *identifier) +{ + const char *p = identifier; + size_t id_len; + + /* Length between 3 and 255 characters inclusive */ + id_len = strlen (identifier); + if (id_len < 3 || id_len > 255) + return FALSE; + + if ((identifier[0] == '.') || (identifier[id_len - 1] == '.')) + return FALSE; + + /* FIXME: do complete validation here */ + while (p && *p) { + if (!g_ascii_isalnum (*p) && (*p != '_') && (*p != '-') && (*p != '.')) + return FALSE; + if ((*p == '.') && (*(p + 1) == '.')) + return FALSE; + p++; + } + + return TRUE; +} + +static void +nm_secret_agent_old_init (NMSecretAgentOld *self) +{ + NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); + + priv->dbus_secret_agent = nmdbus_secret_agent_skeleton_new (); + _nm_dbus_bind_properties (self, priv->dbus_secret_agent); + _nm_dbus_bind_methods (self, priv->dbus_secret_agent, + "GetSecrets", impl_secret_agent_old_get_secrets, + "CancelGetSecrets", impl_secret_agent_old_cancel_get_secrets, + "DeleteSecrets", impl_secret_agent_old_delete_secrets, + "SaveSecrets", impl_secret_agent_old_save_secrets, + NULL); +} + +static void +init_common (NMSecretAgentOld *self) +{ + NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); + + priv->private_bus = _nm_dbus_is_connection_private (priv->bus); + + if (priv->private_bus == FALSE) { + priv->session_bus = _nm_dbus_bus_type () == G_BUS_TYPE_SESSION; + + g_signal_connect (priv->manager_proxy, "notify::g-name-owner", + G_CALLBACK (name_owner_changed), self); + } +} + +static gboolean +init_sync (GInitable *initable, GCancellable *cancellable, GError **error) +{ + NMSecretAgentOld *self = NM_SECRET_AGENT_OLD (initable); + NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); + GDBusProxy *proxy; + + priv->bus = _nm_dbus_new_connection (cancellable, error); + if (!priv->bus) + return FALSE; + + proxy = _nm_dbus_new_proxy_for_connection (priv->bus, + NM_DBUS_PATH_AGENT_MANAGER, + NM_DBUS_INTERFACE_AGENT_MANAGER, + cancellable, error); + if (!proxy) + return FALSE; + priv->manager_proxy = NMDBUS_AGENT_MANAGER (proxy); + + init_common (self); + + if (priv->auto_register) + return nm_secret_agent_old_register (self, cancellable, error); + else + return TRUE; +} + +typedef struct { + NMSecretAgentOld *self; + GCancellable *cancellable; + GSimpleAsyncResult *simple; +} NMSecretAgentOldInitData; + +static void +init_async_complete (NMSecretAgentOldInitData *init_data, GError *error) +{ + if (!error) + g_simple_async_result_set_op_res_gboolean (init_data->simple, TRUE); + else + g_simple_async_result_take_error (init_data->simple, error); + + g_simple_async_result_complete_in_idle (init_data->simple); + + g_object_unref (init_data->simple); + g_clear_object (&init_data->cancellable); + g_slice_free (NMSecretAgentOldInitData, init_data); +} + +static void +init_async_registered (GObject *object, GAsyncResult *result, gpointer user_data) +{ + NMSecretAgentOld *self = NM_SECRET_AGENT_OLD (object); + NMSecretAgentOldInitData *init_data = user_data; + GError *error = NULL; + + nm_secret_agent_old_register_finish (self, result, &error); + init_async_complete (init_data, error); +} + +static void +init_async_got_proxy (GObject *object, GAsyncResult *result, gpointer user_data) +{ + NMSecretAgentOldInitData *init_data = user_data; + NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (init_data->self); + GDBusProxy *proxy; + GError *error = NULL; + + proxy = _nm_dbus_new_proxy_for_connection_finish (result, &error); + if (!proxy) { + init_async_complete (init_data, error); + return; + } + priv->manager_proxy = NMDBUS_AGENT_MANAGER (proxy); + + init_common (init_data->self); + + if (priv->auto_register) { + nm_secret_agent_old_register_async (init_data->self, init_data->cancellable, + init_async_registered, init_data); + } else + init_async_complete (init_data, NULL); +} + +static void +init_async_got_bus (GObject *initable, GAsyncResult *result, gpointer user_data) +{ + NMSecretAgentOldInitData *init_data = user_data; + NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (init_data->self); + GError *error = NULL; + + priv->bus = _nm_dbus_new_connection_finish (result, &error); + if (!priv->bus) { + init_async_complete (init_data, error); + return; + } + + _nm_dbus_new_proxy_for_connection_async (priv->bus, + NM_DBUS_PATH_AGENT_MANAGER, + NM_DBUS_INTERFACE_AGENT_MANAGER, + init_data->cancellable, + init_async_got_proxy, init_data); +} + +static void +init_async (GAsyncInitable *initable, int io_priority, + GCancellable *cancellable, GAsyncReadyCallback callback, + gpointer user_data) +{ + NMSecretAgentOld *self = NM_SECRET_AGENT_OLD (initable); + NMSecretAgentOldInitData *init_data; + + init_data = g_slice_new (NMSecretAgentOldInitData); + init_data->self = self; + init_data->cancellable = cancellable ? g_object_ref (cancellable) : NULL; + + init_data->simple = g_simple_async_result_new (G_OBJECT (initable), callback, + user_data, init_async); + + _nm_dbus_new_connection_async (cancellable, init_async_got_bus, init_data); +} + +static gboolean +init_finish (GAsyncInitable *initable, GAsyncResult *result, GError **error) +{ + GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); + + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + else + return TRUE; +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_IDENTIFIER: + g_value_set_string (value, priv->identifier); + break; + case PROP_AUTO_REGISTER: + g_value_set_boolean (value, priv->auto_register); + break; + case PROP_REGISTERED: + g_value_set_boolean (value, priv->registered); + break; + case PROP_CAPABILITIES: + g_value_set_flags (value, priv->capabilities); + 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) +{ + NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (object); + const char *identifier; + + switch (prop_id) { + case PROP_IDENTIFIER: + identifier = g_value_get_string (value); + + g_return_if_fail (validate_identifier (identifier)); + + g_free (priv->identifier); + priv->identifier = g_strdup (identifier); + break; + case PROP_AUTO_REGISTER: + priv->auto_register = g_value_get_boolean (value); + break; + case PROP_CAPABILITIES: + priv->capabilities = g_value_get_flags (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +dispose (GObject *object) +{ + NMSecretAgentOld *self = NM_SECRET_AGENT_OLD (object); + NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self); + + if (priv->registered) + nm_secret_agent_old_unregister_async (self, NULL, NULL, NULL); + + g_clear_pointer (&priv->identifier, g_free); + + while (priv->pending_gets) + get_secrets_info_finalize (self, priv->pending_gets->data); + + g_signal_handlers_disconnect_matched (priv->dbus_secret_agent, G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, self); + g_object_unref (priv->dbus_secret_agent); + + g_clear_object (&priv->manager_proxy); + g_clear_object (&priv->bus); + + G_OBJECT_CLASS (nm_secret_agent_old_parent_class)->dispose (object); +} + +static void +nm_secret_agent_old_class_init (NMSecretAgentOldClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + g_type_class_add_private (class, sizeof (NMSecretAgentOldPrivate)); + + /* Virtual methods */ + object_class->dispose = dispose; + object_class->get_property = get_property; + object_class->set_property = set_property; + + /** + * NMSecretAgentOld:identifier: + * + * Identifies this agent; only one agent in each user session may use the + * same identifier. Identifier formatting follows the same rules as + * D-Bus bus names with the exception that the ':' character is not + * allowed. The valid set of characters is "[A-Z][a-z][0-9]_-." and the + * identifier is limited in length to 255 characters with a minimum + * of 3 characters. An example valid identifier is 'org.gnome.nm-applet' + * (without quotes). + **/ + g_object_class_install_property + (object_class, PROP_IDENTIFIER, + g_param_spec_string (NM_SECRET_AGENT_OLD_IDENTIFIER, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSecretAgentOld:auto-register: + * + * If %TRUE (the default), the agent will always be registered when + * NetworkManager is running; if NetworkManager exits and restarts, the + * agent will re-register itself automatically. + * + * In particular, if this property is %TRUE at construct time, then the + * agent will register itself with NetworkManager during + * construction/initialization, and initialization will fail with an error + * if the agent is unable to register itself. + * + * If the property is %FALSE, the agent will not automatically register with + * NetworkManager, and nm_secret_agent_old_register() or + * nm_secret_agent_old_register_async() must be called to register it. + * + * Calling nm_secret_agent_old_unregister() will suppress auto-registration + * until nm_secret_agent_old_register() is called, which re-enables + * auto-registration. This ensures that the agent remains un-registered when + * you expect it to be unregistered. + **/ + g_object_class_install_property + (object_class, PROP_AUTO_REGISTER, + g_param_spec_boolean (NM_SECRET_AGENT_OLD_AUTO_REGISTER, "", "", + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSecretAgentOld:registered: + * + * %TRUE if the agent is registered with NetworkManager, %FALSE if not. + **/ + g_object_class_install_property + (object_class, PROP_REGISTERED, + g_param_spec_boolean (NM_SECRET_AGENT_OLD_REGISTERED, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMSecretAgentOld:capabilities: + * + * A bitfield of %NMSecretAgentCapabilities. + **/ + g_object_class_install_property + (object_class, PROP_CAPABILITIES, + g_param_spec_flags (NM_SECRET_AGENT_OLD_CAPABILITIES, "", "", + NM_TYPE_SECRET_AGENT_CAPABILITIES, + NM_SECRET_AGENT_CAPABILITY_NONE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + _nm_dbus_register_proxy_type (NM_DBUS_INTERFACE_AGENT_MANAGER, + NMDBUS_TYPE_AGENT_MANAGER_PROXY); +} + +static void +nm_secret_agent_old_initable_iface_init (GInitableIface *iface) +{ + iface->init = init_sync; +} + +static void +nm_secret_agent_old_async_initable_iface_init (GAsyncInitableIface *iface) +{ + iface->init_async = init_async; + iface->init_finish = init_finish; +} diff --git a/libnm/nm-secret-agent-old.h b/libnm/nm-secret-agent-old.h new file mode 100644 index 00000000..6198e2c0 --- /dev/null +++ b/libnm/nm-secret-agent-old.h @@ -0,0 +1,238 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2010 - 2011 Red Hat, Inc. + */ + +#ifndef __NM_SECRET_AGENT_OLD_H__ +#define __NM_SECRET_AGENT_OLD_H__ + +#include <nm-types.h> + +G_BEGIN_DECLS + +#define NM_TYPE_SECRET_AGENT_OLD (nm_secret_agent_old_get_type ()) +#define NM_SECRET_AGENT_OLD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SECRET_AGENT_OLD, NMSecretAgentOld)) +#define NM_SECRET_AGENT_OLD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SECRET_AGENT_OLD, NMSecretAgentOldClass)) +#define NM_IS_SECRET_AGENT_OLD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SECRET_AGENT_OLD)) +#define NM_IS_SECRET_AGENT_OLD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SECRET_AGENT_OLD)) +#define NM_SECRET_AGENT_OLD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SECRET_AGENT_OLD, NMSecretAgentOldClass)) + +#define NM_SECRET_AGENT_OLD_IDENTIFIER "identifier" +#define NM_SECRET_AGENT_OLD_AUTO_REGISTER "auto-register" +#define NM_SECRET_AGENT_OLD_REGISTERED "registered" +#define NM_SECRET_AGENT_OLD_CAPABILITIES "capabilities" + +typedef struct { + GObject parent; +} NMSecretAgentOld; + +/** + * NMSecretAgentOldGetSecretsFunc: + * @agent: the secret agent object + * @connection: (transfer none): the connection for which secrets were requested, + * note that this object will be unrefed after the callback has returned, use + * g_object_ref()/g_object_unref() if you want to use this object after the callback + * has returned + * @secrets: the #GVariant of type %NM_VARIANT_TYPE_CONNECTION containing the requested + * secrets (as created by nm_connection_to_dbus() for example). Each key in @secrets + * should be the name of a #NMSetting object (like "802-11-wireless-security") + * and each value should be an %NM_VARIANT_TYPE_SETTING variant. The sub-dicts + * map string:value, where the string is the setting property name (like "psk") + * and the value is the secret + * @error: if the secrets request failed, give a descriptive error here + * @user_data: caller-specific data to be passed to the function + * + * Called as a result of a request by NM to retrieve secrets. When the + * #NMSecretAgentOld subclass has finished retrieving secrets and is ready to + * return them, or to return an error, this function should be called with + * those secrets or the error. + * + * To easily create the dictionary to return the Wi-Fi PSK, you could do + * something like this: + * <example> + * <title>Creating a secrets dictionary</title> + * <programlisting> + * NMConnection *secrets; + * NMSettingWirelessSecurity *s_wsec; + * GVariant *secrets_dict; + * + * secrets = nm_simple_connection_new (); + * s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new (); + * g_object_set (G_OBJECT (s_wsec), + * NM_SETTING_WIRELESS_SECURITY_PSK, "my really cool PSK", + * NULL); + * nm_connection_add_setting (secrets, NM_SETTING (s_wsec)); + * secrets_dict = nm_connection_to_dbus (secrets, NM_CONNECTION_SERIALIZE_ALL); + * + * (call the NMSecretAgentOldGetSecretsFunc with secrets_dict) + * + * g_object_unref (secrets); + * g_variant_unref (secrets_dict); + * </programlisting> + * </example> + */ +typedef void (*NMSecretAgentOldGetSecretsFunc) (NMSecretAgentOld *agent, + NMConnection *connection, + GVariant *secrets, + GError *error, + gpointer user_data); + +/** + * NMSecretAgentOldSaveSecretsFunc: + * @agent: the secret agent object + * @connection: (transfer none): the connection for which secrets were to be saved, + * note that this object will be unrefed after the callback has returned, use + * g_object_ref()/g_object_unref() if you want to use this object after the callback + * has returned + * @error: if the saving secrets failed, give a descriptive error here + * @user_data: caller-specific data to be passed to the function + * + * Called as a result of a request by NM to save secrets. When the + * #NMSecretAgentOld subclass has finished saving the secrets, this function + * should be called. + */ +typedef void (*NMSecretAgentOldSaveSecretsFunc) (NMSecretAgentOld *agent, + NMConnection *connection, + GError *error, + gpointer user_data); + +/** + * NMSecretAgentOldDeleteSecretsFunc: + * @agent: the secret agent object + * @connection: (transfer none): the connection for which secrets were to be deleted, + * note that this object will be unrefed after the callback has returned, use + * g_object_ref()/g_object_unref() if you want to use this object after the callback + * has returned + * @error: if the deleting secrets failed, give a descriptive error here + * @user_data: caller-specific data to be passed to the function + * + * Called as a result of a request by NM to delete secrets. When the + * #NMSecretAgentOld subclass has finished deleting the secrets, this function + * should be called. + */ +typedef void (*NMSecretAgentOldDeleteSecretsFunc) (NMSecretAgentOld *agent, + NMConnection *connection, + GError *error, + gpointer user_data); + +typedef struct { + GObjectClass parent; + + /* Virtual methods for subclasses */ + + /* Called when the subclass should retrieve and return secrets. Subclass + * must copy or reference any arguments it may require after returning from + * this method, as the arguments will freed (except for 'self', 'callback', + * and 'user_data' of course). If the request is canceled, the callback + * should still be called, but with the + * NM_SECRET_AGENT_OLD_ERROR_AGENT_CANCELED error. + */ + void (*get_secrets) (NMSecretAgentOld *self, + NMConnection *connection, + const char *connection_path, + const char *setting_name, + const char **hints, + NMSecretAgentGetSecretsFlags flags, + NMSecretAgentOldGetSecretsFunc callback, + gpointer user_data); + + /* Called when the subclass should cancel an outstanding request to + * get secrets for a given connection. Canceling the request MUST + * call the callback that was passed along with the initial get_secrets + * call, sending the NM_SECRET_AGENT_OLD_ERROR/ + * NM_SECRET_AGENT_OLD_ERROR_AGENT_CANCELED error to that callback. + */ + void (*cancel_get_secrets) (NMSecretAgentOld *self, + const char *connection_path, + const char *setting_name); + + /* Called when the subclass should save the secrets contained in the + * connection to backing storage. Subclass must copy or reference any + * arguments it may require after returning from this method, as the + * arguments will freed (except for 'self', 'callback', and 'user_data' + * of course). + */ + void (*save_secrets) (NMSecretAgentOld *self, + NMConnection *connection, + const char *connection_path, + NMSecretAgentOldSaveSecretsFunc callback, + gpointer user_data); + + /* Called when the subclass should delete the secrets contained in the + * connection from backing storage. Subclass must copy or reference any + * arguments it may require after returning from this method, as the + * arguments will freed (except for 'self', 'callback', and 'user_data' + * of course). + */ + void (*delete_secrets) (NMSecretAgentOld *self, + NMConnection *connection, + const char *connection_path, + NMSecretAgentOldDeleteSecretsFunc callback, + gpointer user_data); + + /*< private >*/ + gpointer padding[8]; +} NMSecretAgentOldClass; + +GType nm_secret_agent_old_get_type (void); + +gboolean nm_secret_agent_old_register (NMSecretAgentOld *self, + GCancellable *cancellable, + GError **error); +void nm_secret_agent_old_register_async (NMSecretAgentOld *self, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean nm_secret_agent_old_register_finish (NMSecretAgentOld *self, + GAsyncResult *result, + GError **error); + +gboolean nm_secret_agent_old_unregister (NMSecretAgentOld *self, + GCancellable *cancellable, + GError **error); +void nm_secret_agent_old_unregister_async (NMSecretAgentOld *self, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean nm_secret_agent_old_unregister_finish (NMSecretAgentOld *self, + GAsyncResult *result, + GError **error); + +gboolean nm_secret_agent_old_get_registered (NMSecretAgentOld *self); + +void nm_secret_agent_old_get_secrets (NMSecretAgentOld *self, + NMConnection *connection, + const char *setting_name, + const char **hints, + NMSecretAgentGetSecretsFlags flags, + NMSecretAgentOldGetSecretsFunc callback, + gpointer user_data); + +void nm_secret_agent_old_save_secrets (NMSecretAgentOld *self, + NMConnection *connection, + NMSecretAgentOldSaveSecretsFunc callback, + gpointer user_data); + +void nm_secret_agent_old_delete_secrets (NMSecretAgentOld *self, + NMConnection *connection, + NMSecretAgentOldDeleteSecretsFunc callback, + gpointer user_data); + +G_END_DECLS + +#endif /* __NM_SECRET_AGENT_OLD_H__ */ diff --git a/libnm/nm-setting-docs-overrides.xml b/libnm/nm-setting-docs-overrides.xml new file mode 100644 index 00000000..3a52fd7c --- /dev/null +++ b/libnm/nm-setting-docs-overrides.xml @@ -0,0 +1,141 @@ +<?xml version="1.0"?> +<!DOCTYPE nm-dbus-docs [ +]> + +<nm-dbus-docs> + <setting name="802-1x"> +</setting> +<setting name="adsl"> +</setting> +<setting name="bluetooth"> +</setting> +<setting name="bond"> +<property name="interface-name" variable="interface-name" format="string" values="" default="" example="" description="Deprecated in favor of connection.interface-name, but can +be used for backward-compatibility with older daemons, to set the +bond's interface name."/> +</setting> +<setting name="bridge-port"> +</setting> +<setting name="bridge"> +<property name="interface-name" variable="interface-name" format="string" values="" default="" example="" description="Deprecated in favor of connection.interface-name, but can +be used for backward-compatibility with older daemons, to set the +bridge's interface name."/> +</setting> +<setting name="cdma"> +</setting> +<setting name="connection"> +</setting> +<setting name="dcb"> +</setting> +<setting name="generic"> +</setting> +<setting name="gsm"> +</setting> +<setting name="infiniband"> +</setting> +<setting name=""> +</setting> +<setting name="ipv4"> +<property name="dns" variable="dns" format="array of uint32" values="" default="" example="" description="Array of IP addresses of DNS servers (as network-byte-order +integers)"/> +<property name="addresses" variable="addresses" format="array of array of uint32" values="" default="" example="" description="Deprecated in favor of the 'address-data' and 'gateway' +properties, but this can be used for backward-compatibility with older +daemons. Note that if you send this property the daemon will ignore +'address-data' and 'gateway'. + Array of IPv4 address structures. Each IPv4 address structure is +composed of 3 32-bit values; the first being the IPv4 address (network +byte order), the second the prefix (1 - 32), and last the IPv4 gateway +(network byte order). The gateway may be left as 0 if no gateway exists +for that subnet."/> +<property name="address-data" variable="address-data" format="array of vardict" values="" default="" example="" description="Array of IPv4 addresses. Each address dictionary contains at +least 'address' and 'prefix' entries, containing the IP address as a +string, and the prefix length as a uint32. Additional attributes may +also exist on some addresses."/> +<property name="routes" variable="routes" format="array of array of uint32" values="" default="" example="" description="Deprecated in favor of the 'route-data' property, but this +can be used for backward-compatibility with older daemons. Note that if +you send this property the daemon will ignore 'route-data'. + Array of IPv4 route structures. Each IPv4 route structure is composed +of 4 32-bit values; the first being the destination IPv4 network or +address (network byte order), the second the destination network or +address prefix (1 - 32), the third being the next-hop (network byte +order) if any, and the fourth being the route metric. If the metric is +0, NM will choose an appropriate default metric for the device. (There +is no way to explicitly specify an actual metric of 0 with this +property.)"/> +<property name="route-data" variable="route-data" format="array of vardict" values="" default="" example="" description="Array of IPv4 routes. Each route dictionary contains at +least 'dest' and 'prefix' entries, containing the destination IP +address as a string, and the prefix length as a uint32. Most routes +will also have a 'gateway' entry, containing the gateway IP address as +a string. If the route has a 'metric' entry (containing a uint32), that +will be used as the metric for the route (otherwise NM will pick a +default value appropriate to the device). Additional attributes may +also exist on some routes."/> +</setting> +<setting name="ipv6"> +<property name="dns" variable="dns" format="array of byte array" values="" default="" example="" description="Array of IP addresses of DNS servers (in network byte order)"/> +<property name="addresses" variable="addresses" format="array of legacy IPv6 address struct (a(ayuay))" values="" default="" example="" description="Deprecated in favor of the 'address-data' and 'gateway' +properties, but this can be used for backward-compatibility with older +daemons. Note that if you send this property the daemon will ignore +'address-data' and 'gateway'. + Array of IPv6 address structures. Each IPv6 address structure is +composed of an IPv6 address, a prefix length (1 - 128), and an IPv6 +gateway address. The gateway may be zeroed out if no gateway exists for +that subnet."/> +<property name="address-data" variable="address-data" format="array of vardict" values="" default="" example="" description="Array of IPv6 addresses. Each address dictionary contains at +least 'address' and 'prefix' entries, containing the IP address as a +string, and the prefix length as a uint32. Additional attributes may +also exist on some addresses."/> +<property name="routes" variable="routes" format="array of legacy IPv6 route struct (a(ayuayu))" values="" default="" example="" description="Deprecated in favor of the 'route-data' property, but this +can be used for backward-compatibility with older daemons. Note that if +you send this property the daemon will ignore 'route-data'. + Array of IPv6 route structures. Each IPv6 route structure is +composed of an IPv6 address, a prefix length (1 - 128), an IPv6 +next hop address (which may be zeroed out if there is no next hop), +and a metric. If the metric is 0, NM will choose an appropriate +default metric for the device."/> +<property name="route-data" variable="route-data" format="array of vardict" values="" default="" example="" description="Array of IPv6 routes. Each route dictionary contains at +least 'dest' and 'prefix' entries, containing the destination IP +address as a string, and the prefix length as a uint32. Most routes +will also have a 'next-hop' entry, containing the next hop IP address as +a string. If the route has a 'metric' entry (containing a uint32), that +will be used as the metric for the route (otherwise NM will pick a +default value appropriate to the device). Additional attributes may +also exist on some routes."/> +</setting> +<setting name="802-11-olpc-mesh"> +</setting> +<setting name="ppp"> +</setting> +<setting name="pppoe"> +</setting> +<setting name="serial"> +<property name="parity" variable="parity" format="byte" values="" default="" example="" description="The connection parity: 69 (ASCII 'E') for even parity, +111 (ASCII 'o') for odd, 110 (ASCII 'n') for none."/> +</setting> +<setting name="team-port"> +</setting> +<setting name="team"> +<property name="interface-name" variable="interface-name" format="string" values="" default="" example="" description="Deprecated in favor of connection.interface-name, but can +be used for backward-compatibility with older daemons, to set the +team's interface name."/> +</setting> +<setting name="vlan"> +<property name="interface-name" variable="interface-name" format="string" values="" default="" example="" description="Deprecated in favor of connection.interface-name, but can +be used for backward-compatibility with older daemons, to set the +vlan's interface name."/> +</setting> +<setting name="vpn"> +</setting> +<setting name="wimax"> +</setting> +<setting name="802-3-ethernet"> +</setting> +<setting name="802-11-wireless-security"> +</setting> +<setting name="802-11-wireless"> +<property name="security" variable="security" format="" values="" default="" example="" description="This property is deprecated, but can be set to the value +'802-11-wireless-security' when a wireless security setting is also +present in the connection dictionary, for compatibility with very old +NetworkManager daemons."/> +</setting> +</nm-dbus-docs> \ No newline at end of file diff --git a/libnm/nm-setting-docs.xml b/libnm/nm-setting-docs.xml new file mode 100644 index 00000000..50acecf1 --- /dev/null +++ b/libnm/nm-setting-docs.xml @@ -0,0 +1,305 @@ +<?xml version="1.0"?> +<!DOCTYPE nm-setting-docs [ +<!ENTITY quot """> +]> +<nm-setting-docs> + <setting name="802-1x"> + <property name="altsubject-matches" type="array of string" default="[]" description="List of strings to be matched against the altSubjectName of the certificate presented by the authentication server. If the list is empty, no verification of the server certificate's altSubjectName is performed." /> + <property name="anonymous-identity" type="string" description="Anonymous identity string for EAP authentication methods. Used as the unencrypted identity with EAP types that support different tunneled identity like EAP-TTLS." /> + <property name="ca-cert" type="byte array" description="Contains the CA certificate if used by the EAP method specified in the "eap" property. Certificate data is specified using a "scheme"; two are currently supported: blob and path. When using the blob scheme (which is backwards compatible with NM 0.7.x) this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string "file://" and ending with a terminating NUL byte. This property can be unset even if the EAP method supports CA certificates, but this allows man-in-the-middle attacks and is NOT recommended." /> + <property name="ca-path" type="string" description="UTF-8 encoded path to a directory containing PEM or DER formatted certificates to be added to the verification chain in addition to the certificate specified in the "ca-cert" property." /> + <property name="client-cert" type="byte array" description="Contains the client certificate if used by the EAP method specified in the "eap" property. Certificate data is specified using a "scheme"; two are currently supported: blob and path. When using the blob scheme (which is backwards compatible with NM 0.7.x) this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string "file://" and ending with a terminating NUL byte." /> + <property name="eap" type="array of string" default="[]" description="The allowed EAP method to be used when authenticating to the network with 802.1x. Valid methods are: "leap", "md5", "tls", "peap", "ttls", "pwd", and "fast". Each method requires different configuration using the properties of this setting; refer to wpa_supplicant documentation for the allowed combinations." /> + <property name="identity" type="string" description="Identity string for EAP authentication methods. Often the user's user or login name." /> + <property name="name" type="string" default="802-1x" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="pac-file" type="string" description="UTF-8 encoded file path containing PAC for EAP-FAST." /> + <property name="password" type="string" description="UTF-8 encoded password used for EAP authentication methods. If both the "password" property and the "password-raw" property are specified, "password" is preferred." /> + <property name="password-flags" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "password" property." /> + <property name="password-raw" type="byte array" description="Password used for EAP authentication methods, given as a byte array to allow passwords in other encodings than UTF-8 to be used. If both the "password" property and the "password-raw" property are specified, "password" is preferred." /> + <property name="password-raw-flags" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "password-raw" property." /> + <property name="phase1-fast-provisioning" type="string" description="Enables or disables in-line provisioning of EAP-FAST credentials when FAST is specified as the EAP method in the "eap" property. Recognized values are "0" (disabled), "1" (allow unauthenticated provisioning), "2" (allow authenticated provisioning), and "3" (allow both authenticated and unauthenticated provisioning). See the wpa_supplicant documentation for more details." /> + <property name="phase1-peaplabel" type="string" description="Forces use of the new PEAP label during key derivation. Some RADIUS servers may require forcing the new PEAP label to interoperate with PEAPv1. Set to "1" to force use of the new PEAP label. See the wpa_supplicant documentation for more details." /> + <property name="phase1-peapver" type="string" description="Forces which PEAP version is used when PEAP is set as the EAP method in the "eap" property. When unset, the version reported by the server will be used. Sometimes when using older RADIUS servers, it is necessary to force the client to use a particular PEAP version. To do so, this property may be set to "0" or "1" to force that specific PEAP version." /> + <property name="phase2-altsubject-matches" type="array of string" default="[]" description="List of strings to be matched against the altSubjectName of the certificate presented by the authentication server during the inner "phase 2" authentication. If the list is empty, no verification of the server certificate's altSubjectName is performed." /> + <property name="phase2-auth" type="string" description="Specifies the allowed "phase 2" inner non-EAP authentication methods when an EAP method that uses an inner TLS tunnel is specified in the "eap" property. Recognized non-EAP "phase 2" methods are "pap", "chap", "mschap", "mschapv2", "gtc", "otp", "md5", and "tls". Each "phase 2" inner method requires specific parameters for successful authentication; see the wpa_supplicant documentation for more details." /> + <property name="phase2-autheap" type="string" description="Specifies the allowed "phase 2" inner EAP-based authentication methods when an EAP method that uses an inner TLS tunnel is specified in the "eap" property. Recognized EAP-based "phase 2" methods are "md5", "mschapv2", "otp", "gtc", and "tls". Each "phase 2" inner method requires specific parameters for successful authentication; see the wpa_supplicant documentation for more details." /> + <property name="phase2-ca-cert" type="byte array" description="Contains the "phase 2" CA certificate if used by the EAP method specified in the "phase2-auth" or "phase2-autheap" properties. Certificate data is specified using a "scheme"; two are currently supported: blob and path. When using the blob scheme (which is backwards compatible with NM 0.7.x) this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string "file://" and ending with a terminating NUL byte. This property can be unset even if the EAP method supports CA certificates, but this allows man-in-the-middle attacks and is NOT recommended." /> + <property name="phase2-ca-path" type="string" description="UTF-8 encoded path to a directory containing PEM or DER formatted certificates to be added to the verification chain in addition to the certificate specified in the "phase2-ca-cert" property." /> + <property name="phase2-client-cert" type="byte array" description="Contains the "phase 2" client certificate if used by the EAP method specified in the "phase2-auth" or "phase2-autheap" properties. Certificate data is specified using a "scheme"; two are currently supported: blob and path. When using the blob scheme (which is backwards compatible with NM 0.7.x) this property should be set to the certificate's DER encoded data. When using the path scheme, this property should be set to the full UTF-8 encoded path of the certificate, prefixed with the string "file://" and ending with a terminating NUL byte. This property can be unset even if the EAP method supports CA certificates, but this allows man-in-the-middle attacks and is NOT recommended." /> + <property name="phase2-private-key" type="byte array" description="Contains the "phase 2" inner private key when the "phase2-auth" or "phase2-autheap" property is set to "tls". Key data is specified using a "scheme"; two are currently supported: blob and path. When using the blob scheme and private keys, this property should be set to the key's encrypted PEM encoded data. When using private keys with the path scheme, this property should be set to the full UTF-8 encoded path of the key, prefixed with the string "file://" and ending with a terminating NUL byte. When using PKCS#12 format private keys and the blob scheme, this property should be set to the PKCS#12 data and the "phase2-private-key-password" property must be set to password used to decrypt the PKCS#12 certificate and key. When using PKCS#12 files and the path scheme, this property should be set to the full UTF-8 encoded path of the key, prefixed with the string "file://" and and ending with a terminating NUL byte, and as with the blob scheme the "phase2-private-key-password" property must be set to the password used to decode the PKCS#12 private key and certificate." /> + <property name="phase2-private-key-password" type="string" description="The password used to decrypt the "phase 2" private key specified in the "phase2-private-key" property when the private key either uses the path scheme, or is a PKCS#12 format key." /> + <property name="phase2-private-key-password-flags" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "phase2-private-key-password" property." /> + <property name="phase2-subject-match" type="string" description="Substring to be matched against the subject of the certificate presented by the authentication server during the inner "phase 2" authentication. When unset, no verification of the authentication server certificate's subject is performed." /> + <property name="pin" type="string" description="PIN used for EAP authentication methods." /> + <property name="pin-flags" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "pin" property." /> + <property name="private-key" type="byte array" description="Contains the private key when the "eap" property is set to "tls". Key data is specified using a "scheme"; two are currently supported: blob and path. When using the blob scheme and private keys, this property should be set to the key's encrypted PEM encoded data. When using private keys with the path scheme, this property should be set to the full UTF-8 encoded path of the key, prefixed with the string "file://" and ending with a terminating NUL byte. When using PKCS#12 format private keys and the blob scheme, this property should be set to the PKCS#12 data and the "private-key-password" property must be set to password used to decrypt the PKCS#12 certificate and key. When using PKCS#12 files and the path scheme, this property should be set to the full UTF-8 encoded path of the key, prefixed with the string "file://" and and ending with a terminating NUL byte, and as with the blob scheme the "private-key-password" property must be set to the password used to decode the PKCS#12 private key and certificate. WARNING: "private-key" is not a "secret" property, and thus unencrypted private key data using the BLOB scheme may be readable by unprivileged users. Private keys should always be encrypted with a private key password to prevent unauthorized access to unencrypted private key data." /> + <property name="private-key-password" type="string" description="The password used to decrypt the private key specified in the "private-key" property when the private key either uses the path scheme, or if the private key is a PKCS#12 format key." /> + <property name="private-key-password-flags" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "private-key-password" property." /> + <property name="subject-match" type="string" description="Substring to be matched against the subject of the certificate presented by the authentication server. When unset, no verification of the authentication server certificate's subject is performed." /> + <property name="system-ca-certs" type="boolean" default="FALSE" description="When TRUE, overrides the "ca-path" and "phase2-ca-path" properties using the system CA directory specified at configure time with the --system-ca-path switch. The certificates in this directory are added to the verification chain in addition to any certificates specified by the "ca-cert" and "phase2-ca-cert" properties." /> + </setting> + <setting name="adsl"> + <property name="encapsulation" type="string" description="Encapsulation of ADSL connection. Can be "vcmux" or "llc"." /> + <property name="name" type="string" default="adsl" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="password" type="string" description="Password used to authenticate with the ADSL service." /> + <property name="password-flags" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "password" property." /> + <property name="protocol" type="string" description="ADSL connection protocol. Can be "pppoa", "pppoe" or "ipoatm"." /> + <property name="username" type="string" description="Username used to authenticate with the ADSL service." /> + <property name="vci" type="uint32" default="0" description="VCI of ADSL connection" /> + <property name="vpi" type="uint32" default="0" description="VPI of ADSL connection" /> + </setting> + <setting name="bluetooth"> + <property name="bdaddr" type="byte array" description="The Bluetooth address of the device." /> + <property name="name" type="string" default="bluetooth" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="type" type="string" description="Either "dun" for Dial-Up Networking connections or "panu" for Personal Area Networking connections to devices supporting the NAP profile." /> + </setting> + <setting name="bond"> + <property name="interface-name" type="string" description="Deprecated in favor of connection.interface-name, but can be used for backward-compatibility with older daemons, to set the bond's interface name." /> + <property name="name" type="string" default="bond" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="options" type="dict of string to string" description="Dictionary of key/value pairs of bonding options. Both keys and values must be strings. Option names must contain only alphanumeric characters (ie, [a-zA-Z0-9])." /> + </setting> + <setting name="bridge"> + <property name="ageing-time" type="uint32" default="300" description="The Ethernet MAC address aging time, in seconds." /> + <property name="forward-delay" type="uint32" default="15" description="The Spanning Tree Protocol (STP) forwarding delay, in seconds." /> + <property name="hello-time" type="uint32" default="2" description="The Spanning Tree Protocol (STP) hello time, in seconds." /> + <property name="interface-name" type="string" description="Deprecated in favor of connection.interface-name, but can be used for backward-compatibility with older daemons, to set the bridge's interface name." /> + <property name="mac-address" type="byte array" description="If specified, the MAC address of bridge. When creating a new bridge, this MAC address will be set. When matching an existing (outside NetworkManager created) bridge, this MAC address must match." /> + <property name="max-age" type="uint32" default="20" description="The Spanning Tree Protocol (STP) maximum message age, in seconds." /> + <property name="name" type="string" default="bridge" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="priority" type="uint32" default="32768" description="Sets the Spanning Tree Protocol (STP) priority for this bridge. Lower values are "better"; the lowest priority bridge will be elected the root bridge." /> + <property name="stp" type="boolean" default="TRUE" description="Controls whether Spanning Tree Protocol (STP) is enabled for this bridge." /> + </setting> + <setting name="bridge-port"> + <property name="hairpin-mode" type="boolean" default="FALSE" description="Enables or disabled "hairpin mode" for the port, which allows frames to be sent back out through the port the frame was received on." /> + <property name="name" type="string" default="bridge-port" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="path-cost" type="uint32" default="100" description="The Spanning Tree Protocol (STP) port cost for destinations via this port." /> + <property name="priority" type="uint32" default="32" description="The Spanning Tree Protocol (STP) priority of this bridge port." /> + </setting> + <setting name="cdma"> + <property name="name" type="string" default="cdma" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="number" type="string" description="The number to dial to establish the connection to the CDMA-based mobile broadband network, if any. If not specified, the default number (#777) is used when required." /> + <property name="password" type="string" description="The password used to authenticate with the network, if required. Many providers do not require a password, or accept any password. But if a password is required, it is specified here." /> + <property name="password-flags" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "password" property." /> + <property name="username" type="string" description="The username used to authenticate with the network, if required. Many providers do not require a username, or accept any username. But if a username is required, it is specified here." /> + </setting> + <setting name="connection"> + <property name="autoconnect" type="boolean" default="TRUE" description="Whether or not the connection should be automatically connected by NetworkManager when the resources for the connection are available. TRUE to automatically activate the connection, FALSE to require manual intervention to activate the connection." /> + <property name="autoconnect-priority" type="int32" default="0" description="The autoconnect priority. If the connection is set to autoconnect, connections with higher priority will be preferred. Defaults to 0. The higher number means higher priority." /> + <property name="gateway-ping-timeout" type="uint32" default="0" description="If greater than zero, delay success of IP addressing until either the timeout is reached, or an IP gateway replies to a ping." /> + <property name="id" type="string" description="A human readable unique identifier for the connection, like "Work Wi-Fi" or "T-Mobile 3G"." /> + <property name="interface-name" type="string" description="The name of the network interface this connection is bound to. If not set, then the connection can be attached to any interface of the appropriate type (subject to restrictions imposed by other settings). For software devices this specifies the name of the created device. For connection types where interface names cannot easily be made persistent (e.g. mobile broadband or USB Ethernet), this property should not be used. Setting this property restricts the interfaces a connection can be used with, and if interface names change or are reordered the connection may be applied to the wrong interface." /> + <property name="master" type="string" description="Interface name of the master device or UUID of the master connection." /> + <property name="name" type="string" default="connection" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="permissions" type="array of string" default="[]" description="An array of strings defining what access a given user has to this connection. If this is NULL or empty, all users are allowed to access this connection. Otherwise a user is allowed to access this connection if and only if they are in this list. Each entry is of the form "[type]:[id]:[reserved]"; for example, "user:dcbw:blah". At this time only the "user" [type] is allowed. Any other values are ignored and reserved for future use. [id] is the username that this permission refers to, which may not contain the ":" character. Any [reserved] information present must be ignored and is reserved for future use. All of [type], [id], and [reserved] must be valid UTF-8." /> + <property name="read-only" type="boolean" default="FALSE" description="FALSE if the connection can be modified using the provided settings service's D-Bus interface with the right privileges, or TRUE if the connection is read-only and cannot be modified." /> + <property name="secondaries" type="array of string" default="[]" description="List of connection UUIDs that should be activated when the base connection itself is activated. Currently only VPN connections are supported." /> + <property name="slave-type" type="string" description="Setting name of the device type of this slave's master connection (eg, "bond"), or NULL if this connection is not a slave." /> + <property name="timestamp" type="uint64" default="0" description="The time, in seconds since the Unix Epoch, that the connection was last _successfully_ fully activated. NetworkManager updates the connection timestamp periodically when the connection is active to ensure that an active connection has the latest timestamp. The property is only meant for reading (changes to this property will not be preserved)." /> + <property name="type" type="string" description="Base type of the connection. For hardware-dependent connections, should contain the setting name of the hardware-type specific setting (ie, "802-3-ethernet" or "802-11-wireless" or "bluetooth", etc), and for non-hardware dependent connections like VPN or otherwise, should contain the setting name of that setting type (ie, "vpn" or "bridge", etc)." /> + <property name="uuid" type="string" description="A universally unique identifier for the connection, for example generated with libuuid. It should be assigned when the connection is created, and never changed as long as the connection still applies to the same network. For example, it should not be changed when the "id" property or NMSettingIP4Config changes, but might need to be re-created when the Wi-Fi SSID, mobile broadband network provider, or "type" property changes. The UUID must be in the format "2815492f-7e56-435e-b2e9-246bd7cdc664" (ie, contains only hexadecimal characters and "-")." /> + <property name="zone" type="string" description="The trust level of a the connection. Free form case-insensitive string (for example "Home", "Work", "Public"). NULL or unspecified zone means the connection will be placed in the default zone as defined by the firewall." /> + </setting> + <setting name="dcb"> + <property name="app-fcoe-flags" type="NMSettingDcbFlags (uint32)" description="Specifies the NMSettingDcbFlags for the DCB FCoE application. Flags may be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4)." /> + <property name="app-fcoe-mode" type="string" default=""fabric"" description="The FCoE controller mode; either "fabric" (default) or "vn2vn"." /> + <property name="app-fcoe-priority" type="int32" default="-1" description="The highest User Priority (0 - 7) which FCoE frames should use, or -1 for default priority. Only used when the "app-fcoe-flags" property includes the NM_SETTING_DCB_FLAG_ENABLE (0x1) flag." /> + <property name="app-fip-flags" type="NMSettingDcbFlags (uint32)" description="Specifies the NMSettingDcbFlags for the DCB FIP application. Flags may be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4)." /> + <property name="app-fip-priority" type="int32" default="-1" description="The highest User Priority (0 - 7) which FIP frames should use, or -1 for default priority. Only used when the "app-fip-flags" property includes the NM_SETTING_DCB_FLAG_ENABLE (0x1) flag." /> + <property name="app-iscsi-flags" type="NMSettingDcbFlags (uint32)" description="Specifies the NMSettingDcbFlags for the DCB iSCSI application. Flags may be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4)." /> + <property name="app-iscsi-priority" type="int32" default="-1" description="The highest User Priority (0 - 7) which iSCSI frames should use, or -1 for default priority. Only used when the "app-iscsi-flags" property includes the NM_SETTING_DCB_FLAG_ENABLE (0x1) flag." /> + <property name="name" type="string" default="dcb" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="priority-bandwidth" type="array of uint32" description="An array of 8 uint values, where the array index corresponds to the User Priority (0 - 7) and the value indicates the percentage of bandwidth of the priority's assigned group that the priority may use. The sum of all percentages for priorities which belong to the same group must total 100 percent." /> + <property name="priority-flow-control" type="array of uint32" description="An array of 8 boolean values, where the array index corresponds to the User Priority (0 - 7) and the value indicates whether or not the corresponding priority should transmit priority pause." /> + <property name="priority-flow-control-flags" type="NMSettingDcbFlags (uint32)" description="Specifies the NMSettingDcbFlags for DCB Priority Flow Control (PFC). Flags may be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4)." /> + <property name="priority-group-bandwidth" type="array of uint32" description="An array of 8 uint values, where the array index corresponds to the Priority Group ID (0 - 7) and the value indicates the percentage of link bandwidth allocated to that group. Allowed values are 0 - 100, and the sum of all values must total 100 percent." /> + <property name="priority-group-flags" type="NMSettingDcbFlags (uint32)" description="Specifies the NMSettingDcbFlags for DCB Priority Groups. Flags may be any combination of NM_SETTING_DCB_FLAG_ENABLE (0x1), NM_SETTING_DCB_FLAG_ADVERTISE (0x2), and NM_SETTING_DCB_FLAG_WILLING (0x4)." /> + <property name="priority-group-id" type="array of uint32" description="An array of 8 uint values, where the array index corresponds to the User Priority (0 - 7) and the value indicates the Priority Group ID. Allowed Priority Group ID values are 0 - 7 or 15 for the unrestricted group." /> + <property name="priority-strict-bandwidth" type="array of uint32" description="An array of 8 boolean values, where the array index corresponds to the User Priority (0 - 7) and the value indicates whether or not the priority may use all of the bandwidth allocated to its assigned group." /> + <property name="priority-traffic-class" type="array of uint32" description="An array of 8 uint values, where the array index corresponds to the User Priority (0 - 7) and the value indicates the traffic class (0 - 7) to which the priority is mapped." /> + </setting> + <setting name="generic"> + <property name="name" type="string" default="generic" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + </setting> + <setting name="gsm"> + <property name="apn" type="string" description="The GPRS Access Point Name specifying the APN used when establishing a data session with the GSM-based network. The APN often determines how the user will be billed for their network usage and whether the user has access to the Internet or just a provider-specific walled-garden, so it is important to use the correct APN for the user's mobile broadband plan. The APN may only be composed of the characters a-z, 0-9, ., and - per GSM 03.60 Section 14.9." /> + <property name="home-only" type="boolean" default="FALSE" description="When TRUE, only connections to the home network will be allowed. Connections to roaming networks will not be made." /> + <property name="name" type="string" default="gsm" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="network-id" type="string" description="The Network ID (GSM LAI format, ie MCC-MNC) to force specific network registration. If the Network ID is specified, NetworkManager will attempt to force the device to register only on the specified network. This can be used to ensure that the device does not roam when direct roaming control of the device is not otherwise possible." /> + <property name="number" type="string" description="Number to dial when establishing a PPP data session with the GSM-based mobile broadband network. Many modems do not require PPP for connections to the mobile network and thus this property should be left blank, which allows NetworkManager to select the appropriate settings automatically." /> + <property name="password" type="string" description="The password used to authenticate with the network, if required. Many providers do not require a password, or accept any password. But if a password is required, it is specified here." /> + <property name="password-flags" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "password" property." /> + <property name="pin" type="string" description="If the SIM is locked with a PIN it must be unlocked before any other operations are requested. Specify the PIN here to allow operation of the device." /> + <property name="pin-flags" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "pin" property." /> + <property name="username" type="string" description="The username used to authenticate with the network, if required. Many providers do not require a username, or accept any username. But if a username is required, it is specified here." /> + </setting> + <setting name="infiniband"> + <property name="mac-address" type="byte array" description="If specified, this connection will only apply to the IPoIB device whose permanent MAC address matches. This property does not change the MAC address of the device (i.e. MAC spoofing)." /> + <property name="mtu" type="uint32" default="0" description="If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple frames." /> + <property name="name" type="string" default="infiniband" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="p-key" type="int32" default="-1" description="The InfiniBand P_Key to use for this device. A value of -1 means to use the default P_Key (aka "the P_Key at index 0"). Otherwise it is a 16-bit unsigned integer, whose high bit is set if it is a "full membership" P_Key." /> + <property name="parent" type="string" description="The interface name of the parent device of this device. Normally NULL, but if the "p_key" property is set, then you must specify the base device by setting either this property or "mac-address"." /> + <property name="transport-mode" type="string" description="The IP-over-InfiniBand transport mode. Either "datagram" or "connected"." /> + </setting> + <setting name="ipv4"> + <property name="address-data" type="array of vardict" description="Array of IPv4 addresses. Each address dictionary contains at least 'address' and 'prefix' entries, containing the IP address as a string, and the prefix length as a uint32. Additional attributes may also exist on some addresses." /> + <property name="addresses" type="array of array of uint32" description="Deprecated in favor of the 'address-data' and 'gateway' properties, but this can be used for backward-compatibility with older daemons. Note that if you send this property the daemon will ignore 'address-data' and 'gateway'. Array of IPv4 address structures. Each IPv4 address structure is composed of 3 32-bit values; the first being the IPv4 address (network byte order), the second the prefix (1 - 32), and last the IPv4 gateway (network byte order). The gateway may be left as 0 if no gateway exists for that subnet." /> + <property name="dhcp-client-id" type="string" description="A string sent to the DHCP server to identify the local machine which the DHCP server may use to customize the DHCP lease and options." /> + <property name="dhcp-hostname" type="string" description="If the "dhcp-send-hostname" property is TRUE, then the specified name will be sent to the DHCP server when acquiring a lease." /> + <property name="dhcp-send-hostname" type="boolean" default="TRUE" description="If TRUE, a hostname is sent to the DHCP server when acquiring a lease. Some DHCP servers use this hostname to update DNS databases, essentially providing a static hostname for the computer. If the "dhcp-hostname" property is NULL and this property is TRUE, the current persistent hostname of the computer is sent." /> + <property name="dns" type="array of uint32" default="[]" description="Array of IP addresses of DNS servers (as network-byte-order integers)" /> + <property name="dns-search" type="array of string" default="[]" description="Array of DNS search domains." /> + <property name="gateway" type="string" description="The gateway associated with this configuration. This is only meaningful if "addresses" is also set." /> + <property name="ignore-auto-dns" type="boolean" default="FALSE" description="When "method" is set to "auto" and this property to TRUE, automatically configured nameservers and search domains are ignored and only nameservers and search domains specified in the "dns" and "dns-search" properties, if any, are used." /> + <property name="ignore-auto-routes" type="boolean" default="FALSE" description="When "method" is set to "auto" and this property to TRUE, automatically configured routes are ignored and only routes specified in the "routes" property, if any, are used." /> + <property name="may-fail" type="boolean" default="TRUE" description="If TRUE, allow overall network configuration to proceed even if the configuration specified by this property times out. Note that at least one IP configuration must succeed or overall network configuration will still fail. For example, in IPv6-only networks, setting this property to TRUE on the NMSettingIP4Config allows the overall network configuration to succeed if IPv4 configuration fails but IPv6 configuration completes successfully." /> + <property name="method" type="string" description="IP configuration method. NMSettingIP4Config and NMSettingIP6Config both support "auto", "manual", and "link-local". See the subclass-specific documentation for other values. In general, for the "auto" method, properties such as "dns" and "routes" specify information that is added on to the information returned from automatic configuration. The "ignore-auto-routes" and "ignore-auto-dns" properties modify this behavior. For methods that imply no upstream network, such as "shared" or "link-local", these properties must be empty." /> + <property name="name" type="string" default="ipv4" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="never-default" type="boolean" default="FALSE" description="If TRUE, this connection will never be the default connection for this IP type, meaning it will never be assigned the default route by NetworkManager." /> + <property name="route-data" type="array of vardict" description="Array of IPv4 routes. Each route dictionary contains at least 'dest' and 'prefix' entries, containing the destination IP address as a string, and the prefix length as a uint32. Most routes will also have a 'gateway' entry, containing the gateway IP address as a string. If the route has a 'metric' entry (containing a uint32), that will be used as the metric for the route (otherwise NM will pick a default value appropriate to the device). Additional attributes may also exist on some routes." /> + <property name="route-metric" type="int64" default="-1" description="The default metric for routes that don't explicitly specify a metric. The default value -1 means that the metric is choosen automatically based on the device type. The metric applies to dynamic routes, manual (static) routes that don't have an explicit metric setting, address prefix routes, and the default route. Note that for IPv6, the kernel accepts zero (0) but coerces it to 1024 (user default). Hence, setting this property to zero effectively mean setting it to 1024. For IPv4, zero is a regular value for the metric." /> + <property name="routes" type="array of array of uint32" description="Deprecated in favor of the 'route-data' property, but this can be used for backward-compatibility with older daemons. Note that if you send this property the daemon will ignore 'route-data'. Array of IPv4 route structures. Each IPv4 route structure is composed of 4 32-bit values; the first being the destination IPv4 network or address (network byte order), the second the destination network or address prefix (1 - 32), the third being the next-hop (network byte order) if any, and the fourth being the route metric. If the metric is 0, NM will choose an appropriate default metric for the device. (There is no way to explicitly specify an actual metric of 0 with this property.)" /> + </setting> + <setting name="ipv6"> + <property name="address-data" type="array of vardict" description="Array of IPv6 addresses. Each address dictionary contains at least 'address' and 'prefix' entries, containing the IP address as a string, and the prefix length as a uint32. Additional attributes may also exist on some addresses." /> + <property name="addresses" type="array of legacy IPv6 address struct (a(ayuay))" description="Deprecated in favor of the 'address-data' and 'gateway' properties, but this can be used for backward-compatibility with older daemons. Note that if you send this property the daemon will ignore 'address-data' and 'gateway'. Array of IPv6 address structures. Each IPv6 address structure is composed of an IPv6 address, a prefix length (1 - 128), and an IPv6 gateway address. The gateway may be zeroed out if no gateway exists for that subnet." /> + <property name="dhcp-hostname" type="string" description="If the "dhcp-send-hostname" property is TRUE, then the specified name will be sent to the DHCP server when acquiring a lease." /> + <property name="dhcp-send-hostname" type="boolean" default="TRUE" description="If TRUE, a hostname is sent to the DHCP server when acquiring a lease. Some DHCP servers use this hostname to update DNS databases, essentially providing a static hostname for the computer. If the "dhcp-hostname" property is NULL and this property is TRUE, the current persistent hostname of the computer is sent." /> + <property name="dns" type="array of byte array" default="[]" description="Array of IP addresses of DNS servers (in network byte order)" /> + <property name="dns-search" type="array of string" default="[]" description="Array of DNS search domains." /> + <property name="gateway" type="string" description="The gateway associated with this configuration. This is only meaningful if "addresses" is also set." /> + <property name="ignore-auto-dns" type="boolean" default="FALSE" description="When "method" is set to "auto" and this property to TRUE, automatically configured nameservers and search domains are ignored and only nameservers and search domains specified in the "dns" and "dns-search" properties, if any, are used." /> + <property name="ignore-auto-routes" type="boolean" default="FALSE" description="When "method" is set to "auto" and this property to TRUE, automatically configured routes are ignored and only routes specified in the "routes" property, if any, are used." /> + <property name="ip6-privacy" type="NMSettingIP6ConfigPrivacy (int32)" description="Configure IPv6 Privacy Extensions for SLAAC, described in RFC4941. If enabled, it makes the kernel generate a temporary IPv6 address in addition to the public one generated from MAC address via modified EUI-64. This enhances privacy, but could cause problems in some applications, on the other hand. The permitted values are: 0: disabled, 1: enabled (prefer public address), 2: enabled (prefer temporary addresses)." /> + <property name="may-fail" type="boolean" default="TRUE" description="If TRUE, allow overall network configuration to proceed even if the configuration specified by this property times out. Note that at least one IP configuration must succeed or overall network configuration will still fail. For example, in IPv6-only networks, setting this property to TRUE on the NMSettingIP4Config allows the overall network configuration to succeed if IPv4 configuration fails but IPv6 configuration completes successfully." /> + <property name="method" type="string" description="IP configuration method. NMSettingIP4Config and NMSettingIP6Config both support "auto", "manual", and "link-local". See the subclass-specific documentation for other values. In general, for the "auto" method, properties such as "dns" and "routes" specify information that is added on to the information returned from automatic configuration. The "ignore-auto-routes" and "ignore-auto-dns" properties modify this behavior. For methods that imply no upstream network, such as "shared" or "link-local", these properties must be empty." /> + <property name="name" type="string" default="ipv6" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="never-default" type="boolean" default="FALSE" description="If TRUE, this connection will never be the default connection for this IP type, meaning it will never be assigned the default route by NetworkManager." /> + <property name="route-data" type="array of vardict" description="Array of IPv6 routes. Each route dictionary contains at least 'dest' and 'prefix' entries, containing the destination IP address as a string, and the prefix length as a uint32. Most routes will also have a 'next-hop' entry, containing the next hop IP address as a string. If the route has a 'metric' entry (containing a uint32), that will be used as the metric for the route (otherwise NM will pick a default value appropriate to the device). Additional attributes may also exist on some routes." /> + <property name="route-metric" type="int64" default="-1" description="The default metric for routes that don't explicitly specify a metric. The default value -1 means that the metric is choosen automatically based on the device type. The metric applies to dynamic routes, manual (static) routes that don't have an explicit metric setting, address prefix routes, and the default route. Note that for IPv6, the kernel accepts zero (0) but coerces it to 1024 (user default). Hence, setting this property to zero effectively mean setting it to 1024. For IPv4, zero is a regular value for the metric." /> + <property name="routes" type="array of legacy IPv6 route struct (a(ayuayu))" description="Deprecated in favor of the 'route-data' property, but this can be used for backward-compatibility with older daemons. Note that if you send this property the daemon will ignore 'route-data'. Array of IPv6 route structures. Each IPv6 route structure is composed of an IPv6 address, a prefix length (1 - 128), an IPv6 next hop address (which may be zeroed out if there is no next hop), and a metric. If the metric is 0, NM will choose an appropriate default metric for the device." /> + </setting> + <setting name="802-11-olpc-mesh"> + <property name="channel" type="uint32" default="0" description="Channel on which the mesh network to join is located." /> + <property name="dhcp-anycast-address" type="byte array" description="Anycast DHCP MAC address used when requesting an IP address via DHCP. The specific anycast address used determines which DHCP server class answers the request." /> + <property name="name" type="string" default="802-11-olpc-mesh" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="ssid" type="byte array" description="SSID of the mesh network to join." /> + </setting> + <setting name="ppp"> + <property name="baud" type="uint32" default="0" description="If non-zero, instruct pppd to set the serial port to the specified baudrate. This value should normally be left as 0 to automatically choose the speed." /> + <property name="crtscts" type="boolean" default="FALSE" description="If TRUE, specify that pppd should set the serial port to use hardware flow control with RTS and CTS signals. This value should normally be set to FALSE." /> + <property name="lcp-echo-failure" type="uint32" default="0" description="If non-zero, instruct pppd to presume the connection to the peer has failed if the specified number of LCP echo-requests go unanswered by the peer. The "lcp-echo-interval" property must also be set to a non-zero value if this property is used." /> + <property name="lcp-echo-interval" type="uint32" default="0" description="If non-zero, instruct pppd to send an LCP echo-request frame to the peer every n seconds (where n is the specified value). Note that some PPP peers will respond to echo requests and some will not, and it is not possible to autodetect this." /> + <property name="mppe-stateful" type="boolean" default="FALSE" description="If TRUE, stateful MPPE is used. See pppd documentation for more information on stateful MPPE." /> + <property name="mru" type="uint32" default="0" description="If non-zero, instruct pppd to request that the peer send packets no larger than the specified size. If non-zero, the MRU should be between 128 and 16384." /> + <property name="mtu" type="uint32" default="0" description="If non-zero, instruct pppd to send packets no larger than the specified size." /> + <property name="name" type="string" default="ppp" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="no-vj-comp" type="boolean" default="FALSE" description="If TRUE, Van Jacobsen TCP header compression will not be requested." /> + <property name="noauth" type="boolean" default="TRUE" description="If TRUE, do not require the other side (usually the PPP server) to authenticate itself to the client. If FALSE, require authentication from the remote side. In almost all cases, this should be TRUE." /> + <property name="nobsdcomp" type="boolean" default="FALSE" description="If TRUE, BSD compression will not be requested." /> + <property name="nodeflate" type="boolean" default="FALSE" description="If TRUE, "deflate" compression will not be requested." /> + <property name="refuse-chap" type="boolean" default="FALSE" description="If TRUE, the CHAP authentication method will not be used." /> + <property name="refuse-eap" type="boolean" default="FALSE" description="If TRUE, the EAP authentication method will not be used." /> + <property name="refuse-mschap" type="boolean" default="FALSE" description="If TRUE, the MSCHAP authentication method will not be used." /> + <property name="refuse-mschapv2" type="boolean" default="FALSE" description="If TRUE, the MSCHAPv2 authentication method will not be used." /> + <property name="refuse-pap" type="boolean" default="FALSE" description="If TRUE, the PAP authentication method will not be used." /> + <property name="require-mppe" type="boolean" default="FALSE" description="If TRUE, MPPE (Microsoft Point-to-Point Encrpytion) will be required for the PPP session. If either 64-bit or 128-bit MPPE is not available the session will fail. Note that MPPE is not used on mobile broadband connections." /> + <property name="require-mppe-128" type="boolean" default="FALSE" description="If TRUE, 128-bit MPPE (Microsoft Point-to-Point Encrpytion) will be required for the PPP session, and the "require-mppe" property must also be set to TRUE. If 128-bit MPPE is not available the session will fail." /> + </setting> + <setting name="pppoe"> + <property name="name" type="string" default="pppoe" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="password" type="string" description="Password used to authenticate with the PPPoE service." /> + <property name="password-flags" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "password" property." /> + <property name="service" type="string" description="If specified, instruct PPPoE to only initiate sessions with access concentrators that provide the specified service. For most providers, this should be left blank. It is only required if there are multiple access concentrators or a specific service is known to be required." /> + <property name="username" type="string" description="Username used to authenticate with the PPPoE service." /> + </setting> + <setting name="serial"> + <property name="baud" type="uint32" default="57600" description="Speed to use for communication over the serial port. Note that this value usually has no effect for mobile broadband modems as they generally ignore speed settings and use the highest available speed." /> + <property name="bits" type="uint32" default="8" description="Byte-width of the serial communication. The 8 in "8n1" for example." /> + <property name="name" type="string" default="serial" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="parity" type="byte" description="The connection parity: 69 (ASCII 'E') for even parity, 111 (ASCII 'o') for odd, 110 (ASCII 'n') for none." /> + <property name="send-delay" type="uint64" default="0" description="Time to delay between each byte sent to the modem, in microseconds." /> + <property name="stopbits" type="uint32" default="1" description="Number of stop bits for communication on the serial port. Either 1 or 2. The 1 in "8n1" for example." /> + </setting> + <setting name="team"> + <property name="config" type="string" description="The JSON configuration for the team network interface. The property should contain raw JSON configuration data suitable for teamd, because the value is passed directly to teamd. If not specified, the default configuration is used. See man teamd.conf for the format details." /> + <property name="interface-name" type="string" description="Deprecated in favor of connection.interface-name, but can be used for backward-compatibility with older daemons, to set the team's interface name." /> + <property name="name" type="string" default="team" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + </setting> + <setting name="team-port"> + <property name="config" type="string" description="The JSON configuration for the team port. The property should contain raw JSON configuration data suitable for teamd, because the value is passed directly to teamd. If not specified, the default configuration is used. See man teamd.conf for the format details." /> + <property name="name" type="string" default="team-port" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + </setting> + <setting name="vlan"> + <property name="egress-priority-map" type="array of string" default="[]" description="For outgoing packets, a list of mappings from Linux SKB priorities to 802.1p priorities. The mapping is given in the format "from:to" where both "from" and "to" are unsigned integers, ie "7:3"." /> + <property name="flags" type="NMVlanFlags (uint32)" description="One or more flags which control the behavior and features of the VLAN interface. Flags include NM_VLAN_FLAG_REORDER_HEADERS (0x1) (reordering of output packet headers), NM_VLAN_FLAG_GVRP (0x2) (use of the GVRP protocol), and NM_VLAN_FLAG_LOOSE_BINDING (0x4) (loose binding of the interface to its master device's operating state)." /> + <property name="id" type="uint32" default="0" description="The VLAN identifier that the interface created by this connection should be assigned." /> + <property name="ingress-priority-map" type="array of string" default="[]" description="For incoming packets, a list of mappings from 802.1p priorities to Linux SKB priorities. The mapping is given in the format "from:to" where both "from" and "to" are unsigned integers, ie "7:3"." /> + <property name="interface-name" type="string" description="Deprecated in favor of connection.interface-name, but can be used for backward-compatibility with older daemons, to set the vlan's interface name." /> + <property name="name" type="string" default="vlan" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="parent" type="string" description="If given, specifies the parent interface name or parent connection UUID from which this VLAN interface should be created. If this property is not specified, the connection must contain an "802-3-ethernet" setting with a "mac-address" property." /> + </setting> + <setting name="vpn"> + <property name="data" type="dict of string to string" description="Dictionary of key/value pairs of VPN plugin specific data. Both keys and values must be strings." /> + <property name="name" type="string" default="vpn" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="persistent" type="boolean" default="FALSE" description="If the VPN service supports persistence, and this property is TRUE, the VPN will attempt to stay connected across link changes and outages, until explicitly disconnected." /> + <property name="secrets" type="dict of string to string" description="Dictionary of key/value pairs of VPN plugin specific secrets like passwords or private keys. Both keys and values must be strings." /> + <property name="service-type" type="string" description="D-Bus service name of the VPN plugin that this setting uses to connect to its network. i.e. org.freedesktop.NetworkManager.vpnc for the vpnc plugin." /> + <property name="user-name" type="string" description="If the VPN connection requires a user name for authentication, that name should be provided here. If the connection is available to more than one user, and the VPN requires each user to supply a different name, then leave this property empty. If this property is empty, NetworkManager will automatically supply the username of the user which requested the VPN connection." /> + </setting> + <setting name="wimax"> + <property name="mac-address" type="byte array" description="If specified, this connection will only apply to the WiMAX device whose MAC address matches. This property does not change the MAC address of the device (known as MAC spoofing)." /> + <property name="name" type="string" default="wimax" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="network-name" type="string" description="Network Service Provider (NSP) name of the WiMAX network this connection should use." /> + </setting> + <setting name="802-3-ethernet"> + <property name="auto-negotiate" type="boolean" default="TRUE" description="If TRUE, allow auto-negotiation of port speed and duplex mode. If FALSE, do not allow auto-negotiation, in which case the "speed" and "duplex" properties should be set." /> + <property name="cloned-mac-address" type="byte array" description="If specified, request that the device use this MAC address instead of its permanent MAC address. This is known as MAC cloning or spoofing." /> + <property name="duplex" type="string" description="If specified, request that the device only use the specified duplex mode. Either "half" or "full"." /> + <property name="mac-address" type="byte array" description="If specified, this connection will only apply to the Ethernet device whose permanent MAC address matches. This property does not change the MAC address of the device (i.e. MAC spoofing)." /> + <property name="mac-address-blacklist" type="array of string" default="[]" description="If specified, this connection will never apply to the Ethernet device whose permanent MAC address matches an address in the list. Each MAC address is in the standard hex-digits-and-colons notation (00:11:22:33:44:55)." /> + <property name="mtu" type="uint32" default="0" description="If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple Ethernet frames." /> + <property name="name" type="string" default="802-3-ethernet" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="port" type="string" description="Specific port type to use if multiple the device supports multiple attachment methods. One of "tp" (Twisted Pair), "aui" (Attachment Unit Interface), "bnc" (Thin Ethernet) or "mii" (Media Independent Interface. If the device supports only one port type, this setting is ignored." /> + <property name="s390-nettype" type="string" description="s390 network device type; one of "qeth", "lcs", or "ctc", representing the different types of virtual network devices available on s390 systems." /> + <property name="s390-options" type="dict of string to string" description="Dictionary of key/value pairs of s390-specific device options. Both keys and values must be strings. Allowed keys include "portno", "layer2", "portname", "protocol", among others. Key names must contain only alphanumeric characters (ie, [a-zA-Z0-9])." /> + <property name="s390-subchannels" type="array of string" default="[]" description="Identifies specific subchannels that this network device uses for communication with z/VM or s390 host. Like the "mac-address" property for non-z/VM devices, this property can be used to ensure this connection only applies to the network device that uses these subchannels. The list should contain exactly 3 strings, and each string may only be composed of hexadecimal characters and the period (.) character." /> + <property name="speed" type="uint32" default="0" description="If non-zero, request that the device use only the specified speed. In Mbit/s, ie 100 == 100Mbit/s." /> + </setting> + <setting name="802-11-wireless"> + <property name="band" type="string" description="802.11 frequency band of the network. One of "a" for 5GHz 802.11a or "bg" for 2.4GHz 802.11. This will lock associations to the Wi-Fi network to the specific band, i.e. if "a" is specified, the device will not associate with the same network in the 2.4GHz band even if the network's settings are compatible. This setting depends on specific driver capability and may not work with all drivers." /> + <property name="bssid" type="byte array" description="If specified, directs the device to only associate with the given access point. This capability is highly driver dependent and not supported by all devices. Note: this property does not control the BSSID used when creating an Ad-Hoc network and is unlikely to in the future." /> + <property name="channel" type="uint32" default="0" description="Wireless channel to use for the Wi-Fi connection. The device will only join (or create for Ad-Hoc networks) a Wi-Fi network on the specified channel. Because channel numbers overlap between bands, this property also requires the "band" property to be set." /> + <property name="cloned-mac-address" type="byte array" description="If specified, request that the Wi-Fi device use this MAC address instead of its permanent MAC address. This is known as MAC cloning or spoofing." /> + <property name="hidden" type="boolean" default="FALSE" description="If TRUE, indicates this network is a non-broadcasting network that hides its SSID. In this case various workarounds may take place, such as probe-scanning the SSID for more reliable network discovery. However, these workarounds expose inherent insecurities with hidden SSID networks, and thus hidden SSID networks should be used with caution." /> + <property name="mac-address" type="byte array" description="If specified, this connection will only apply to the Wi-Fi device whose permanent MAC address matches. This property does not change the MAC address of the device (i.e. MAC spoofing)." /> + <property name="mac-address-blacklist" type="array of string" default="[]" description="A list of permanent MAC addresses of Wi-Fi devices to which this connection should never apply. Each MAC address should be given in the standard hex-digits-and-colons notation (eg "00:11:22:33:44:55")." /> + <property name="mode" type="string" description="Wi-Fi network mode; one of "infrastructure", "adhoc" or "ap". If blank, infrastructure is assumed." /> + <property name="mtu" type="uint32" default="0" description="If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple Ethernet frames." /> + <property name="name" type="string" default="802-11-wireless" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="rate" type="uint32" default="0" description="If non-zero, directs the device to only use the specified bitrate for communication with the access point. Units are in Kb/s, ie 5500 = 5.5 Mbit/s. This property is highly driver dependent and not all devices support setting a static bitrate." /> + <property name="security" type="None" description="This property is deprecated, but can be set to the value '802-11-wireless-security' when a wireless security setting is also present in the connection dictionary, for compatibility with very old NetworkManager daemons." /> + <property name="seen-bssids" type="array of string" default="[]" description="A list of BSSIDs (each BSSID formatted as a MAC address like "00:11:22:33:44:55") that have been detected as part of the Wi-Fi network. NetworkManager internally tracks previously seen BSSIDs. The property is only meant for reading and reflects the BSSID list of NetworkManager. The changes you make to this property will not be preserved." /> + <property name="ssid" type="byte array" description="SSID of the Wi-Fi network. Must be specified." /> + <property name="tx-power" type="uint32" default="0" description="If non-zero, directs the device to use the specified transmit power. Units are dBm. This property is highly driver dependent and not all devices support setting a static transmit power." /> + </setting> + <setting name="802-11-wireless-security"> + <property name="auth-alg" type="string" description="When WEP is used (ie, key-mgmt = "none" or "ieee8021x") indicate the 802.11 authentication algorithm required by the AP here. One of "open" for Open System, "shared" for Shared Key, or "leap" for Cisco LEAP. When using Cisco LEAP (ie, key-mgmt = "ieee8021x" and auth-alg = "leap") the "leap-username" and "leap-password" properties must be specified." /> + <property name="group" type="array of string" default="[]" description="A list of group/broadcast encryption algorithms which prevents connections to Wi-Fi networks that do not utilize one of the algorithms in the list. For maximum compatibility leave this property empty. Each list element may be one of "wep40", "wep104", "tkip", or "ccmp"." /> + <property name="key-mgmt" type="string" description="Key management used for the connection. One of "none" (WEP), "ieee8021x" (Dynamic WEP), "wpa-none" (Ad-Hoc WPA-PSK), "wpa-psk" (infrastructure WPA-PSK), or "wpa-eap" (WPA-Enterprise). This property must be set for any Wi-Fi connection that uses security." /> + <property name="leap-password" type="string" description="The login password for legacy LEAP connections (ie, key-mgmt = "ieee8021x" and auth-alg = "leap")." /> + <property name="leap-password-flags" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "leap-password" property." /> + <property name="leap-username" type="string" description="The login username for legacy LEAP connections (ie, key-mgmt = "ieee8021x" and auth-alg = "leap")." /> + <property name="name" type="string" default="802-11-wireless-security" description="The setting's name, which uniquely identifies the setting within the connection. Each setting type has a name unique to that type, for example "ppp" or "wireless" or "wired"." /> + <property name="pairwise" type="array of string" default="[]" description="A list of pairwise encryption algorithms which prevents connections to Wi-Fi networks that do not utilize one of the algorithms in the list. For maximum compatibility leave this property empty. Each list element may be one of "tkip" or "ccmp"." /> + <property name="proto" type="array of string" default="[]" description="List of strings specifying the allowed WPA protocol versions to use. Each element may be one "wpa" (allow WPA) or "rsn" (allow WPA2/RSN). If not specified, both WPA and RSN connections are allowed." /> + <property name="psk" type="string" description="Pre-Shared-Key for WPA networks. If the key is 64-characters long, it must contain only hexadecimal characters and is interpreted as a hexadecimal WPA key. Otherwise, the key must be between 8 and 63 ASCII characters (as specified in the 802.11i standard) and is interpreted as a WPA passphrase, and is hashed to derive the actual WPA-PSK used when connecting to the Wi-Fi network." /> + <property name="psk-flags" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "psk" property." /> + <property name="wep-key-flags" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the "wep-key0", "wep-key1", "wep-key2", and "wep-key3" properties." /> + <property name="wep-key-type" type="NMWepKeyType (uint32)" description="Controls the interpretation of WEP keys. Allowed values are NM_WEP_KEY_TYPE_KEY (1), in which case the key is either a 10- or 26-character hexadecimal string, or a 5- or 13-character ASCII password; or NM_WEP_KEY_TYPE_PASSPHRASE (2), in which case the passphrase is provided as a string and will be hashed using the de-facto MD5 method to derive the actual WEP key." /> + <property name="wep-key0" type="string" description="Index 0 WEP key. This is the WEP key used in most networks. See the "wep-key-type" property for a description of how this key is interpreted." /> + <property name="wep-key1" type="string" description="Index 1 WEP key. This WEP index is not used by most networks. See the "wep-key-type" property for a description of how this key is interpreted." /> + <property name="wep-key2" type="string" description="Index 2 WEP key. This WEP index is not used by most networks. See the "wep-key-type" property for a description of how this key is interpreted." /> + <property name="wep-key3" type="string" description="Index 3 WEP key. This WEP index is not used by most networks. See the "wep-key-type" property for a description of how this key is interpreted." /> + <property name="wep-tx-keyidx" type="uint32" default="0" description="When static WEP is used (ie, key-mgmt = "none") and a non-default WEP key index is used by the AP, put that WEP key index here. Valid values are 0 (default key) through 3. Note that some consumer access points (like the Linksys WRT54G) number the keys 1 - 4." /> + </setting> +</nm-setting-docs> diff --git a/libnm/nm-types.h b/libnm/nm-types.h new file mode 100644 index 00000000..ee1ed643 --- /dev/null +++ b/libnm/nm-types.h @@ -0,0 +1,53 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * 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 2014 Red Hat, Inc. + */ + +#ifndef __NM_TYPES_H__ +#define __NM_TYPES_H__ + +#include <gio/gio.h> + +#include <nm-dbus-interface.h> +#include <nm-connection.h> + +typedef struct _NMAccessPoint NMAccessPoint; +typedef struct _NMActiveConnection NMActiveConnection; +typedef struct _NMClient NMClient; +typedef struct _NMDevice NMDevice; +typedef struct _NMDeviceAdsl NMDeviceAdsl; +typedef struct _NMDeviceBond NMDeviceBond; +typedef struct _NMDeviceBridge NMDeviceBridge; +typedef struct _NMDeviceBt NMDeviceBt; +typedef struct _NMDeviceEthernet NMDeviceEthernet; +typedef struct _NMDeviceGeneric NMDeviceGeneric; +typedef struct _NMDeviceInfiniband NMDeviceInfiniband; +typedef struct _NMDeviceModem NMDeviceModem; +typedef struct _NMDeviceOlpcMesh NMDeviceOlpcMesh; +typedef struct _NMDeviceTeam NMDeviceTeam; +typedef struct _NMDeviceVlan NMDeviceVlan; +typedef struct _NMDeviceWifi NMDeviceWifi; +typedef struct _NMDeviceWimax NMDeviceWimax; +typedef struct _NMDhcpConfig NMDhcpConfig; +typedef struct _NMIPConfig NMIPConfig; +typedef struct _NMObject NMObject; +typedef struct _NMRemoteConnection NMRemoteConnection; +typedef struct _NMVpnConnection NMVpnConnection; +typedef struct _NMWimaxNsp NMWimaxNsp; + +#endif /* NM_TYPES_H */ diff --git a/libnm/nm-vpn-connection.c b/libnm/nm-vpn-connection.c new file mode 100644 index 00000000..f46dc0ca --- /dev/null +++ b/libnm/nm-vpn-connection.c @@ -0,0 +1,233 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2007 - 2008 Novell, Inc. + * Copyright 2007 - 2012 Red Hat, Inc. + */ + +#include "config.h" + +#include <string.h> +#include "nm-vpn-connection.h" +#include "nm-dbus-interface.h" +#include "nm-utils.h" +#include "nm-object-private.h" +#include "nm-active-connection.h" +#include "nm-dbus-helpers.h" + +#include "nmdbus-vpn-connection.h" + +G_DEFINE_TYPE (NMVpnConnection, nm_vpn_connection, NM_TYPE_ACTIVE_CONNECTION) + +#define NM_VPN_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_VPN_CONNECTION, NMVpnConnectionPrivate)) + +typedef struct { + char *banner; + NMVpnConnectionState vpn_state; +} NMVpnConnectionPrivate; + +enum { + PROP_0, + PROP_VPN_STATE, + PROP_BANNER, + + LAST_PROP +}; + +enum { + VPN_STATE_CHANGED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + + +/** + * nm_vpn_connection_get_banner: + * @vpn: a #NMVpnConnection + * + * Gets the VPN login banner of the active #NMVpnConnection. + * + * Returns: the VPN login banner of the VPN connection. This is the internal + * string used by the connection, and must not be modified. + **/ +const char * +nm_vpn_connection_get_banner (NMVpnConnection *vpn) +{ + NMVpnConnectionPrivate *priv; + + g_return_val_if_fail (NM_IS_VPN_CONNECTION (vpn), NULL); + + priv = NM_VPN_CONNECTION_GET_PRIVATE (vpn); + + if (priv->vpn_state != NM_VPN_CONNECTION_STATE_ACTIVATED) + return NULL; + + return priv->banner; +} + +/** + * nm_vpn_connection_get_vpn_state: + * @vpn: a #NMVpnConnection + * + * Gets the current #NMVpnConnection state. + * + * Returns: the VPN state of the active VPN connection. + **/ +NMVpnConnectionState +nm_vpn_connection_get_vpn_state (NMVpnConnection *vpn) +{ + g_return_val_if_fail (NM_IS_VPN_CONNECTION (vpn), NM_VPN_CONNECTION_STATE_UNKNOWN); + + return NM_VPN_CONNECTION_GET_PRIVATE (vpn)->vpn_state; +} + +static void +vpn_state_changed_proxy (NMDBusVpnConnection *proxy, + guint vpn_state, + guint reason, + gpointer user_data) +{ + NMVpnConnection *connection = NM_VPN_CONNECTION (user_data); + NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); + + if (priv->vpn_state != vpn_state) { + priv->vpn_state = vpn_state; + g_signal_emit (connection, signals[VPN_STATE_CHANGED], 0, vpn_state, reason); + g_object_notify (G_OBJECT (connection), NM_VPN_CONNECTION_VPN_STATE); + } +} + +/*****************************************************************************/ + +static void +nm_vpn_connection_init (NMVpnConnection *connection) +{ + NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); + + priv->vpn_state = NM_VPN_CONNECTION_STATE_UNKNOWN; +} + +static void +init_dbus (NMObject *object) +{ + NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (object); + const NMPropertiesInfo property_info[] = { + { NM_VPN_CONNECTION_BANNER, &priv->banner }, + { NM_VPN_CONNECTION_VPN_STATE, &priv->vpn_state }, + { NULL }, + }; + GDBusProxy *proxy; + + NM_OBJECT_CLASS (nm_vpn_connection_parent_class)->init_dbus (object); + + _nm_object_register_properties (object, + NM_DBUS_INTERFACE_VPN_CONNECTION, + property_info); + + proxy = _nm_object_get_proxy (object, NM_DBUS_INTERFACE_VPN_CONNECTION); + g_signal_connect (proxy, "vpn-state-changed", + G_CALLBACK (vpn_state_changed_proxy), object); +} + +static void +finalize (GObject *object) +{ + NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (object); + + g_free (priv->banner); + + G_OBJECT_CLASS (nm_vpn_connection_parent_class)->finalize (object); +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMVpnConnection *self = NM_VPN_CONNECTION (object); + + switch (prop_id) { + case PROP_VPN_STATE: + g_value_set_enum (value, nm_vpn_connection_get_vpn_state (self)); + break; + case PROP_BANNER: + g_value_set_string (value, nm_vpn_connection_get_banner (self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_vpn_connection_class_init (NMVpnConnectionClass *connection_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (connection_class); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (connection_class); + + g_type_class_add_private (connection_class, sizeof (NMVpnConnectionPrivate)); + + _nm_object_class_add_interface (nm_object_class, NM_DBUS_INTERFACE_VPN_CONNECTION); + _nm_dbus_register_proxy_type (NM_DBUS_INTERFACE_VPN_CONNECTION, + NMDBUS_TYPE_VPN_CONNECTION_PROXY); + + /* virtual methods */ + object_class->get_property = get_property; + object_class->finalize = finalize; + + nm_object_class->init_dbus = init_dbus; + + /* properties */ + + /** + * NMVpnConnection:vpn-state: + * + * The VPN state of the active VPN connection. + **/ + g_object_class_install_property + (object_class, PROP_VPN_STATE, + g_param_spec_enum (NM_VPN_CONNECTION_VPN_STATE, "", "", + NM_TYPE_VPN_CONNECTION_STATE, + NM_VPN_CONNECTION_STATE_UNKNOWN, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMVpnConnection:banner: + * + * The VPN login banner of the active VPN connection. + **/ + g_object_class_install_property + (object_class, PROP_BANNER, + g_param_spec_string (NM_VPN_CONNECTION_BANNER, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /* signals */ + signals[VPN_STATE_CHANGED] = + g_signal_new ("vpn-state-changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMVpnConnectionClass, vpn_state_changed), + NULL, NULL, NULL, + G_TYPE_NONE, 2, + G_TYPE_UINT, G_TYPE_UINT); +} diff --git a/libnm/nm-vpn-connection.h b/libnm/nm-vpn-connection.h new file mode 100644 index 00000000..349de41e --- /dev/null +++ b/libnm/nm-vpn-connection.h @@ -0,0 +1,67 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2007 - 2008 Novell, Inc. + * Copyright 2007 - 2010 Red Hat, Inc. + */ + +#ifndef __NM_VPN_CONNECTION_H__ +#define __NM_VPN_CONNECTION_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include <nm-active-connection.h> +#include <nm-vpn-dbus-interface.h> + +G_BEGIN_DECLS + +#define NM_TYPE_VPN_CONNECTION (nm_vpn_connection_get_type ()) +#define NM_VPN_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_VPN_CONNECTION, NMVpnConnection)) +#define NM_VPN_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_VPN_CONNECTION, NMVpnConnectionClass)) +#define NM_IS_VPN_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_VPN_CONNECTION)) +#define NM_IS_VPN_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_VPN_CONNECTION)) +#define NM_VPN_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_VPN_CONNECTION, NMVpnConnectionClass)) + +#define NM_VPN_CONNECTION_VPN_STATE "vpn-state" +#define NM_VPN_CONNECTION_BANNER "banner" + +struct _NMVpnConnection { + NMActiveConnection parent; +}; + +typedef struct { + NMActiveConnectionClass parent; + + /* Signals */ + void (*vpn_state_changed) (NMVpnConnection *connection, + NMVpnConnectionState state, + NMVpnConnectionStateReason reason); + + /*< private >*/ + gpointer padding[4]; +} NMVpnConnectionClass; + +GType nm_vpn_connection_get_type (void); + +NMVpnConnectionState nm_vpn_connection_get_vpn_state (NMVpnConnection *vpn); +const char * nm_vpn_connection_get_banner (NMVpnConnection *vpn); + +G_END_DECLS + +#endif /* __NM_VPN_CONNECTION_H__ */ diff --git a/libnm/nm-vpn-editor-plugin.c b/libnm/nm-vpn-editor-plugin.c new file mode 100644 index 00000000..904a6be4 --- /dev/null +++ b/libnm/nm-vpn-editor-plugin.c @@ -0,0 +1,181 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2008 - 2010 Red Hat, Inc. + * Copyright 2008 Novell, Inc. + */ + +#include "config.h" + +#include "nm-vpn-editor-plugin.h" + +static void nm_vpn_editor_plugin_default_init (NMVpnEditorPluginInterface *iface); + +G_DEFINE_INTERFACE (NMVpnEditorPlugin, nm_vpn_editor_plugin, G_TYPE_OBJECT) + +static void +nm_vpn_editor_plugin_default_init (NMVpnEditorPluginInterface *iface) +{ + /* Properties */ + + /** + * NMVpnEditorPlugin:name: + * + * Short display name of the VPN plugin. + */ + g_object_interface_install_property (iface, + g_param_spec_string (NM_VPN_EDITOR_PLUGIN_NAME, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMVpnEditorPlugin:description: + * + * Longer description of the VPN plugin. + */ + g_object_interface_install_property (iface, + g_param_spec_string (NM_VPN_EDITOR_PLUGIN_DESCRIPTION, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMVpnEditorPlugin:service: + * + * D-Bus service name of the plugin's VPN service. + */ + g_object_interface_install_property (iface, + g_param_spec_string (NM_VPN_EDITOR_PLUGIN_SERVICE, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); +} + +/** + * nm_vpn_editor_plugin_get_editor: + * + * Returns: (transfer full): + */ +NMVpnEditor * +nm_vpn_editor_plugin_get_editor (NMVpnEditorPlugin *plugin, + NMConnection *connection, + GError **error) +{ + g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), NULL); + + return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->get_editor (plugin, connection, error); +} + +NMVpnEditorPluginCapability +nm_vpn_editor_plugin_get_capabilities (NMVpnEditorPlugin *plugin) +{ + g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), 0); + + return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->get_capabilities (plugin); +} + +/** + * nm_vpn_editor_plugin_import: + * + * Returns: (transfer full): + */ +NMConnection * +nm_vpn_editor_plugin_import (NMVpnEditorPlugin *plugin, + const char *path, + GError **error) +{ + g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), NULL); + + if (nm_vpn_editor_plugin_get_capabilities (plugin) & NM_VPN_EDITOR_PLUGIN_CAPABILITY_IMPORT) { + g_return_val_if_fail (NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->import_from_file != NULL, NULL); + return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->import_from_file (plugin, path, error); + } + return NULL; +} + +gboolean +nm_vpn_editor_plugin_export (NMVpnEditorPlugin *plugin, + const char *path, + NMConnection *connection, + GError **error) +{ + g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), FALSE); + + if (nm_vpn_editor_plugin_get_capabilities (plugin) & NM_VPN_EDITOR_PLUGIN_CAPABILITY_EXPORT) { + g_return_val_if_fail (NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->export_to_file != NULL, FALSE); + return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->export_to_file (plugin, path, connection, error); + } + return FALSE; +} + +char * +nm_vpn_editor_plugin_get_suggested_filename (NMVpnEditorPlugin *plugin, + NMConnection *connection) +{ + g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), NULL); + + if (NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->get_suggested_filename) + return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->get_suggested_filename (plugin, connection); + return NULL; +} + + +static void nm_vpn_editor_default_init (NMVpnEditorInterface *iface); + +G_DEFINE_INTERFACE (NMVpnEditor, nm_vpn_editor, G_TYPE_OBJECT) + +static void +nm_vpn_editor_default_init (NMVpnEditorInterface *iface) +{ + GType iface_type = G_TYPE_FROM_INTERFACE (iface); + + /* Signals */ + g_signal_new ("changed", + iface_type, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMVpnEditorInterface, changed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +/** + * nm_vpn_editor_get_widget: + * + * Returns: (transfer none): + */ +GObject * +nm_vpn_editor_get_widget (NMVpnEditor *editor) +{ + g_return_val_if_fail (NM_IS_VPN_EDITOR (editor), NULL); + + return NM_VPN_EDITOR_GET_INTERFACE (editor)->get_widget (editor); +} + +gboolean +nm_vpn_editor_update_connection (NMVpnEditor *editor, + NMConnection *connection, + GError **error) +{ + g_return_val_if_fail (NM_IS_VPN_EDITOR (editor), FALSE); + + if (error) + g_return_val_if_fail (*error == NULL, FALSE); + + return NM_VPN_EDITOR_GET_INTERFACE (editor)->update_connection (editor, connection, error); +} diff --git a/libnm/nm-vpn-editor-plugin.h b/libnm/nm-vpn-editor-plugin.h new file mode 100644 index 00000000..5910aa36 --- /dev/null +++ b/libnm/nm-vpn-editor-plugin.h @@ -0,0 +1,189 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2008 - 2014 Red Hat, Inc. + * Copyright 2008 Novell, Inc. + */ + +#ifndef __NM_VPN_EDITOR_PLUGIN_H__ +#define __NM_VPN_EDITOR_PLUGIN_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include <glib.h> +#include <glib-object.h> +#include <nm-types.h> + +G_BEGIN_DECLS + +typedef struct _NMVpnEditorPlugin NMVpnEditorPlugin; +typedef struct _NMVpnEditor NMVpnEditor; + +/* Plugin's factory function that returns a GObject that implements + * NMVpnEditorPlugin. + */ +#ifndef __GI_SCANNER__ +typedef NMVpnEditorPlugin * (*NMVpnEditorPluginFactory) (GError **error); +NMVpnEditorPlugin *nm_vpn_editor_plugin_factory (GError **error); +#endif + + +/**************************************************/ +/* Editor plugin interface */ +/**************************************************/ + +#define NM_TYPE_VPN_EDITOR_PLUGIN (nm_vpn_editor_plugin_get_type ()) +#define NM_VPN_EDITOR_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_VPN_EDITOR_PLUGIN, NMVpnEditorPlugin)) +#define NM_IS_VPN_EDITOR_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_VPN_EDITOR_PLUGIN)) +#define NM_VPN_EDITOR_PLUGIN_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NM_TYPE_VPN_EDITOR_PLUGIN, NMVpnEditorPluginInterface)) + +/** + * NMVpnEditorPluginCapability: + * @NM_VPN_EDITOR_PLUGIN_CAPABILITY_NONE: unknown or no capability + * @NM_VPN_EDITOR_PLUGIN_CAPABILITY_IMPORT: the plugin can import new connections + * @NM_VPN_EDITOR_PLUGIN_CAPABILITY_EXPORT: the plugin can export connections + * @NM_VPN_EDITOR_PLUGIN_CAPABILITY_IPV6: the plugin supports IPv6 addressing + * + * Flags that indicate certain capabilities of the plugin to editor programs. + **/ +typedef enum /*< flags >*/ { + NM_VPN_EDITOR_PLUGIN_CAPABILITY_NONE = 0x00, + NM_VPN_EDITOR_PLUGIN_CAPABILITY_IMPORT = 0x01, + NM_VPN_EDITOR_PLUGIN_CAPABILITY_EXPORT = 0x02, + NM_VPN_EDITOR_PLUGIN_CAPABILITY_IPV6 = 0x04 +} NMVpnEditorPluginCapability; + +/* Short display name of the VPN plugin */ +#define NM_VPN_EDITOR_PLUGIN_NAME "name" + +/* Longer description of the VPN plugin */ +#define NM_VPN_EDITOR_PLUGIN_DESCRIPTION "description" + +/* D-Bus service name of the plugin's VPN service */ +#define NM_VPN_EDITOR_PLUGIN_SERVICE "service" + +/** + * NMVpnEditorPluginInterface: + * @g_iface: the parent interface + * @get_editor: returns an #NMVpnEditor, pre-filled with values from @connection + * if non-%NULL. + * @get_capabilities: returns a bitmask of capabilities. + * @import_from_file: Try to import a connection from the specified path. On + * success, return a partial #NMConnection object. On error, return %NULL and + * set @error with additional information. Note that @error can be %NULL, in + * which case no additional error information should be provided. + * @export_to_file: Export the given connection to the specified path. Return + * %TRUE on success. On error, return %FALSE and set @error with additional + * error information. Note that @error can be %NULL, in which case no + * additional error information should be provided. + * @get_suggested_filename: For a given connection, return a suggested file + * name. Returned value will be %NULL or a suggested file name to be freed by + * the caller. + * + * Interface for VPN editor plugins. + */ +typedef struct { + GTypeInterface g_iface; + + NMVpnEditor * (*get_editor) (NMVpnEditorPlugin *plugin, + NMConnection *connection, + GError **error); + + NMVpnEditorPluginCapability (*get_capabilities) (NMVpnEditorPlugin *plugin); + + NMConnection * (*import_from_file) (NMVpnEditorPlugin *plugin, + const char *path, + GError **error); + + gboolean (*export_to_file) (NMVpnEditorPlugin *plugin, + const char *path, + NMConnection *connection, + GError **error); + + char * (*get_suggested_filename) (NMVpnEditorPlugin *plugin, NMConnection *connection); +} NMVpnEditorPluginInterface; + +GType nm_vpn_editor_plugin_get_type (void); + +NMVpnEditor *nm_vpn_editor_plugin_get_editor (NMVpnEditorPlugin *plugin, + NMConnection *connection, + GError **error); + +NMVpnEditorPluginCapability nm_vpn_editor_plugin_get_capabilities (NMVpnEditorPlugin *plugin); + +NMConnection *nm_vpn_editor_plugin_import (NMVpnEditorPlugin *plugin, + const char *path, + GError **error); +gboolean nm_vpn_editor_plugin_export (NMVpnEditorPlugin *plugin, + const char *path, + NMConnection *connection, + GError **error); +char *nm_vpn_editor_plugin_get_suggested_filename (NMVpnEditorPlugin *plugin, + NMConnection *connection); + +/**************************************************/ +/* Editor interface */ +/**************************************************/ + +#define NM_TYPE_VPN_EDITOR (nm_vpn_editor_get_type ()) +#define NM_VPN_EDITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_VPN_EDITOR, NMVpnEditor)) +#define NM_IS_VPN_EDITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_VPN_EDITOR)) +#define NM_VPN_EDITOR_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NM_TYPE_VPN_EDITOR, NMVpnEditorInterface)) + +/** + * NMVpnEditorInterface: + * @g_iface: the parent interface + * @get_widget: return the #GtkWidget for the VPN editor's UI + * @placeholder: not currently used + * @update_connection: called to save the user-entered options to the connection + * object. Should return %FALSE and set @error if the current options are + * invalid. @error should contain enough information for the plugin to + * determine which UI widget is invalid at a later point in time. For + * example, creating unique error codes for what error occurred and populating + * the message field of @error with the name of the invalid property. + * @changed: emitted when the value of a UI widget changes. May trigger a + * validity check via @update_connection to write values to the connection. + * + * Interface for editing a specific #NMConnection + */ +typedef struct { + GTypeInterface g_iface; + + GObject * (*get_widget) (NMVpnEditor *editor); + + void (*placeholder) (void); + + gboolean (*update_connection) (NMVpnEditor *editor, + NMConnection *connection, + GError **error); + + void (*changed) (NMVpnEditor *editor); +} NMVpnEditorInterface; + +GType nm_vpn_editor_get_type (void); + +GObject * nm_vpn_editor_get_widget (NMVpnEditor *editor); + +gboolean nm_vpn_editor_update_connection (NMVpnEditor *editor, + NMConnection *connection, + GError **error); + +G_END_DECLS + +#endif /* NM_VPN_EDITOR_PLUGIN_H */ diff --git a/libnm/nm-vpn-plugin-old.c b/libnm/nm-vpn-plugin-old.c new file mode 100644 index 00000000..e6843f7e --- /dev/null +++ b/libnm/nm-vpn-plugin-old.c @@ -0,0 +1,1206 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2007 - 2008 Novell, Inc. + * Copyright 2007 - 2008 Red Hat, Inc. + */ + +/* This interface is expected to be deprecated in NM 1.2, at which point there + * will be a new "NMVpnPlugin" class to replace it. + */ + +#include "config.h" + +#include <errno.h> +#include <signal.h> +#include <stdlib.h> + +#include <glib/gi18n-lib.h> +#include <gio/gio.h> + +#include "nm-glib-compat.h" +#include "nm-vpn-plugin-old.h" +#include "nm-enum-types.h" +#include "nm-utils.h" +#include "nm-connection.h" +#include "nm-dbus-helpers.h" +#include "nm-core-internal.h" +#include "nm-simple-connection.h" + +#include "nmdbus-vpn-plugin.h" + +#define NM_VPN_PLUGIN_OLD_QUIT_TIMER 20 + +static void nm_vpn_plugin_old_initable_iface_init (GInitableIface *iface); + +G_DEFINE_ABSTRACT_TYPE_WITH_CODE (NMVpnPluginOld, nm_vpn_plugin_old, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_vpn_plugin_old_initable_iface_init); + ) + +typedef struct { + NMVpnServiceState state; + + /* DBUS-y stuff */ + GDBusConnection *connection; + NMDBusVpnPlugin *dbus_vpn_plugin_old; + char *dbus_service_name; + + /* Temporary stuff */ + guint connect_timer; + guint quit_timer; + guint fail_stop_id; + gboolean interactive; + + gboolean got_config; + gboolean has_ip4, got_ip4; + gboolean has_ip6, got_ip6; + + /* Config stuff copied from config to ip4config */ + char *banner, *tundev, *gateway, *mtu; +} NMVpnPluginOldPrivate; + +#define NM_VPN_PLUGIN_OLD_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_VPN_PLUGIN_OLD, NMVpnPluginOldPrivate)) + +enum { + STATE_CHANGED, + CONFIG, + IP4_CONFIG, + IP6_CONFIG, + LOGIN_BANNER, + FAILURE, + QUIT, + SECRETS_REQUIRED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +enum { + PROP_0, + PROP_DBUS_SERVICE_NAME, + PROP_STATE, + + LAST_PROP +}; + +static GSList *active_plugins = NULL; + + +static void +nm_vpn_plugin_old_set_connection (NMVpnPluginOld *plugin, + GDBusConnection *connection) +{ + NMVpnPluginOldPrivate *priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE (plugin); + + g_clear_object (&priv->connection); + + priv->connection = g_object_ref (connection); +} + +/** + * nm_vpn_plugin_old_get_connection: + * + * Returns: (transfer full): + */ +GDBusConnection * +nm_vpn_plugin_old_get_connection (NMVpnPluginOld *plugin) +{ + GDBusConnection *connection; + + g_return_val_if_fail (NM_IS_VPN_PLUGIN_OLD (plugin), NULL); + + connection = NM_VPN_PLUGIN_OLD_GET_PRIVATE (plugin)->connection; + + if (connection) + g_object_ref (connection); + + return connection; +} + +NMVpnServiceState +nm_vpn_plugin_old_get_state (NMVpnPluginOld *plugin) +{ + g_return_val_if_fail (NM_IS_VPN_PLUGIN_OLD (plugin), NM_VPN_SERVICE_STATE_UNKNOWN); + + return NM_VPN_PLUGIN_OLD_GET_PRIVATE (plugin)->state; +} + +void +nm_vpn_plugin_old_set_state (NMVpnPluginOld *plugin, + NMVpnServiceState state) +{ + NMVpnPluginOldPrivate *priv; + + g_return_if_fail (NM_IS_VPN_PLUGIN_OLD (plugin)); + + priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE (plugin); + if (priv->state != state) { + priv->state = state; + g_signal_emit (plugin, signals[STATE_CHANGED], 0, state); + } +} + +void +nm_vpn_plugin_old_set_login_banner (NMVpnPluginOld *plugin, + const char *banner) +{ + g_return_if_fail (NM_IS_VPN_PLUGIN_OLD (plugin)); + g_return_if_fail (banner != NULL); + + g_signal_emit (plugin, signals[LOGIN_BANNER], 0, banner); +} + +void +nm_vpn_plugin_old_failure (NMVpnPluginOld *plugin, + NMVpnPluginFailure reason) +{ + g_return_if_fail (NM_IS_VPN_PLUGIN_OLD (plugin)); + + g_signal_emit (plugin, signals[FAILURE], 0, reason); +} + +gboolean +nm_vpn_plugin_old_disconnect (NMVpnPluginOld *plugin, GError **err) +{ + gboolean ret = FALSE; + NMVpnServiceState state; + + g_return_val_if_fail (NM_IS_VPN_PLUGIN_OLD (plugin), FALSE); + + state = nm_vpn_plugin_old_get_state (plugin); + switch (state) { + case NM_VPN_SERVICE_STATE_STOPPING: + g_set_error (err, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_STOPPING_IN_PROGRESS, + "%s", + "Could not process the request because the VPN connection is already being stopped."); + break; + case NM_VPN_SERVICE_STATE_STOPPED: + g_set_error (err, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_ALREADY_STOPPED, + "%s", + "Could not process the request because no VPN connection was active."); + break; + case NM_VPN_SERVICE_STATE_STARTING: + case NM_VPN_SERVICE_STATE_STARTED: + nm_vpn_plugin_old_set_state (plugin, NM_VPN_SERVICE_STATE_STOPPING); + ret = NM_VPN_PLUGIN_OLD_GET_CLASS (plugin)->disconnect (plugin, err); + nm_vpn_plugin_old_set_state (plugin, NM_VPN_SERVICE_STATE_STOPPED); + break; + case NM_VPN_SERVICE_STATE_INIT: + ret = TRUE; + break; + + default: + g_warning ("Unhandled VPN service state %d", state); + g_assert_not_reached (); + break; + } + + return ret; +} + +static void +nm_vpn_plugin_old_emit_quit (NMVpnPluginOld *plugin) +{ + g_signal_emit (plugin, signals[QUIT], 0); +} + +static gboolean +connect_timer_expired (gpointer data) +{ + NMVpnPluginOld *plugin = NM_VPN_PLUGIN_OLD (data); + GError *err = NULL; + + g_message ("Connect timer expired, disconnecting."); + nm_vpn_plugin_old_disconnect (plugin, &err); + if (err) { + g_warning ("Disconnect failed: %s", err->message); + g_error_free (err); + } + + return FALSE; +} + +static gboolean +quit_timer_expired (gpointer data) +{ + NMVpnPluginOld *plugin = NM_VPN_PLUGIN_OLD (data); + + nm_vpn_plugin_old_emit_quit (plugin); + + return FALSE; +} + +static gboolean +fail_stop (gpointer data) +{ + NMVpnPluginOld *plugin = NM_VPN_PLUGIN_OLD (data); + + nm_vpn_plugin_old_set_state (plugin, NM_VPN_SERVICE_STATE_STOPPED); + return FALSE; +} + +static void +schedule_fail_stop (NMVpnPluginOld *plugin) +{ + NMVpnPluginOldPrivate *priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE (plugin); + + if (priv->fail_stop_id) + g_source_remove (priv->fail_stop_id); + priv->fail_stop_id = g_idle_add (fail_stop, plugin); +} + +void +nm_vpn_plugin_old_set_config (NMVpnPluginOld *plugin, + GVariant *config) +{ + NMVpnPluginOldPrivate *priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE (plugin); + + g_return_if_fail (NM_IS_VPN_PLUGIN_OLD (plugin)); + g_return_if_fail (config != NULL); + + priv->got_config = TRUE; + + g_variant_lookup (config, NM_VPN_PLUGIN_CONFIG_HAS_IP4, "b", &priv->has_ip4); + g_variant_lookup (config, NM_VPN_PLUGIN_CONFIG_HAS_IP6, "b", &priv->has_ip6); + + g_warn_if_fail (priv->has_ip4 || priv->has_ip6); + + /* Record the items that need to also be inserted into the + * ip4config, for compatibility with older daemons. + */ + g_clear_pointer (&priv->banner, g_free); + g_variant_lookup (config, NM_VPN_PLUGIN_CONFIG_BANNER, "&s", &priv->banner); + g_clear_pointer (&priv->tundev, g_free); + g_variant_lookup (config, NM_VPN_PLUGIN_CONFIG_TUNDEV, "&s", &priv->tundev); + g_clear_pointer (&priv->gateway, g_free); + g_variant_lookup (config, NM_VPN_PLUGIN_CONFIG_EXT_GATEWAY, "&s", &priv->gateway); + g_clear_pointer (&priv->mtu, g_free); + g_variant_lookup (config, NM_VPN_PLUGIN_CONFIG_MTU, "&s", &priv->mtu); + + g_signal_emit (plugin, signals[CONFIG], 0, config); +} + +void +nm_vpn_plugin_old_set_ip4_config (NMVpnPluginOld *plugin, + GVariant *ip4_config) +{ + NMVpnPluginOldPrivate *priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE (plugin); + GVariant *combined_config; + GVariantBuilder builder; + GVariantIter iter; + const char *key, *value; + + g_return_if_fail (NM_IS_VPN_PLUGIN_OLD (plugin)); + g_return_if_fail (ip4_config != NULL); + + priv->got_ip4 = TRUE; + + /* Old plugins won't send the "config" signal and thus can't send + * NM_VPN_PLUGIN_OLD_CONFIG_HAS_IP4 either. But since they don't support IPv6, + * we can safely assume that, if we don't receive a "config" signal but do + * receive an "ip4-config" signal, the old plugin supports IPv4. + */ + if (!priv->got_config) + priv->has_ip4 = TRUE; + + /* Older NetworkManager daemons expect all config info to be in + * the ip4 config, so they won't even notice the "config" signal + * being emitted. So just copy all of that data into the ip4 + * config too. + */ + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{ss}")); + g_variant_iter_init (&iter, ip4_config); + while (g_variant_iter_next (&iter, "{&s&s}", &key, &value)) + g_variant_builder_add (&builder, "{ss}", key, value); + + if (priv->banner) + g_variant_builder_add (&builder, "{ss}", NM_VPN_PLUGIN_IP4_CONFIG_BANNER, &priv->banner); + if (priv->tundev) + g_variant_builder_add (&builder, "{ss}", NM_VPN_PLUGIN_IP4_CONFIG_TUNDEV, &priv->tundev); + if (priv->gateway) + g_variant_builder_add (&builder, "{ss}", NM_VPN_PLUGIN_IP4_CONFIG_EXT_GATEWAY, &priv->gateway); + if (priv->mtu) + g_variant_builder_add (&builder, "{ss}", NM_VPN_PLUGIN_IP4_CONFIG_MTU, &priv->mtu); + + combined_config = g_variant_builder_end (&builder); + g_variant_ref_sink (combined_config); + g_signal_emit (plugin, signals[IP4_CONFIG], 0, combined_config); + g_variant_unref (combined_config); + + if ( priv->has_ip4 == priv->got_ip4 + && priv->has_ip6 == priv->got_ip6) + nm_vpn_plugin_old_set_state (plugin, NM_VPN_SERVICE_STATE_STARTED); +} + +void +nm_vpn_plugin_old_set_ip6_config (NMVpnPluginOld *plugin, + GVariant *ip6_config) +{ + NMVpnPluginOldPrivate *priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE (plugin); + + g_return_if_fail (NM_IS_VPN_PLUGIN_OLD (plugin)); + g_return_if_fail (ip6_config != NULL); + + priv->got_ip6 = TRUE; + g_signal_emit (plugin, signals[IP6_CONFIG], 0, ip6_config); + + if ( priv->has_ip4 == priv->got_ip4 + && priv->has_ip6 == priv->got_ip6) + nm_vpn_plugin_old_set_state (plugin, NM_VPN_SERVICE_STATE_STARTED); +} + +static void +connect_timer_removed (gpointer data) +{ + NM_VPN_PLUGIN_OLD_GET_PRIVATE (data)->connect_timer = 0; +} + +static void +connect_timer_start (NMVpnPluginOld *plugin) +{ + NMVpnPluginOldPrivate *priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE (plugin); + + priv->connect_timer = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT, + 60, + connect_timer_expired, + plugin, + connect_timer_removed); +} + +static void +_connect_generic (NMVpnPluginOld *plugin, + GDBusMethodInvocation *context, + GVariant *properties, + GVariant *details) +{ + NMVpnPluginOldPrivate *priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE (plugin); + NMVpnPluginOldClass *vpn_class = NM_VPN_PLUGIN_OLD_GET_CLASS (plugin); + NMConnection *connection; + gboolean success = FALSE; + GError *error = NULL; + + if (priv->state != NM_VPN_SERVICE_STATE_STOPPED && + priv->state != NM_VPN_SERVICE_STATE_INIT) { + g_dbus_method_invocation_return_error (context, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_WRONG_STATE, + "Could not start connection: wrong plugin state %d", + priv->state); + return; + } + + connection = nm_simple_connection_new_from_dbus (properties, &error); + if (!connection) { + g_dbus_method_invocation_return_error (context, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, + "Invalid connection: (%d) %s", + error->code, error->message); + g_clear_error (&error); + } + + priv->interactive = FALSE; + if (details && !vpn_class->connect_interactive) { + g_dbus_method_invocation_return_error (context, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_INTERACTIVE_NOT_SUPPORTED, + "Plugin does not implement ConnectInteractive()"); + return; + } + + nm_vpn_plugin_old_set_state (plugin, NM_VPN_SERVICE_STATE_STARTING); + + if (details) { + priv->interactive = TRUE; + success = vpn_class->connect_interactive (plugin, connection, details, &error); + } else + success = vpn_class->connect (plugin, connection, &error); + + if (success) { + g_dbus_method_invocation_return_value (context, NULL); + + /* Add a timer to make sure we do not wait indefinitely for the successful connect. */ + connect_timer_start (plugin); + } else { + g_dbus_method_invocation_take_error (context, error); + + /* Stop the plugin from an idle handler so that the Connect + * method return gets sent before the STOP StateChanged signal. + */ + schedule_fail_stop (plugin); + } + + g_object_unref (connection); +} + +static void +impl_vpn_plugin_old_connect (NMVpnPluginOld *plugin, + GDBusMethodInvocation *context, + GVariant *connection, + gpointer user_data) +{ + _connect_generic (plugin, context, connection, NULL); +} + +static void +impl_vpn_plugin_old_connect_interactive (NMVpnPluginOld *plugin, + GDBusMethodInvocation *context, + GVariant *connection, + GVariant *details, + gpointer user_data) +{ + _connect_generic (plugin, context, connection, details); +} + +/***************************************************************/ + +static void +impl_vpn_plugin_old_need_secrets (NMVpnPluginOld *plugin, + GDBusMethodInvocation *context, + GVariant *properties, + gpointer user_data) +{ + NMConnection *connection; + char *setting_name; + gboolean needed; + GError *error = NULL; + + connection = nm_simple_connection_new_from_dbus (properties, &error); + if (!connection) { + g_dbus_method_invocation_return_error (context, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_INVALID_CONNECTION, + "The connection was invalid: %s", + error->message); + g_error_free (error); + return; + } + + if (!NM_VPN_PLUGIN_OLD_GET_CLASS (plugin)->need_secrets) { + g_dbus_method_invocation_return_value (context, + g_variant_new ("(s)", "")); + return; + } + + needed = NM_VPN_PLUGIN_OLD_GET_CLASS (plugin)->need_secrets (plugin, connection, &setting_name, &error); + if (error) { + g_dbus_method_invocation_take_error (context, error); + return; + } + + if (needed) { + g_assert (setting_name); + g_dbus_method_invocation_return_value (context, + g_variant_new ("(s)", setting_name)); + g_free (setting_name); + } else { + /* No secrets required */ + g_dbus_method_invocation_return_value (context, + g_variant_new ("(s)", "")); + } +} + +static void +impl_vpn_plugin_old_new_secrets (NMVpnPluginOld *plugin, + GDBusMethodInvocation *context, + GVariant *properties, + gpointer user_data) +{ + NMVpnPluginOldPrivate *priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE (plugin); + NMConnection *connection; + GError *error = NULL; + gboolean success; + + if (priv->state != NM_VPN_SERVICE_STATE_STARTING) { + g_dbus_method_invocation_return_error (context, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_WRONG_STATE, + "Could not accept new secrets: wrong plugin state %d", + priv->state); + return; + } + + connection = nm_simple_connection_new_from_dbus (properties, &error); + if (!connection) { + g_dbus_method_invocation_return_error (context, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, + "Invalid connection: (%d) %s", + error->code, error->message); + g_clear_error (&error); + return; + } + + if (!NM_VPN_PLUGIN_OLD_GET_CLASS (plugin)->new_secrets) { + g_dbus_method_invocation_return_error (context, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_INTERACTIVE_NOT_SUPPORTED, + "Could not accept new secrets: plugin cannot process interactive secrets"); + g_object_unref (connection); + return; + } + + success = NM_VPN_PLUGIN_OLD_GET_CLASS (plugin)->new_secrets (plugin, connection, &error); + if (success) { + g_dbus_method_invocation_return_value (context, NULL); + + /* Add a timer to make sure we do not wait indefinitely for the successful connect. */ + connect_timer_start (plugin); + } else { + g_dbus_method_invocation_take_error (context, error); + + /* Stop the plugin from and idle handler so that the NewSecrets + * method return gets sent before the STOP StateChanged signal. + */ + schedule_fail_stop (plugin); + } + + g_object_unref (connection); +} + +/** + * nm_vpn_plugin_old_secrets_required: + * @plugin: the #NMVpnPluginOld + * @message: an information message about why secrets are required, if any + * @hints: VPN specific secret names for required new secrets + * + * Called by VPN plugin implementations to signal to NetworkManager that secrets + * are required during the connection process. This signal may be used to + * request new secrets when the secrets originally provided by NetworkManager + * are insufficient, or the VPN process indicates that it needs additional + * information to complete the request. + */ +void +nm_vpn_plugin_old_secrets_required (NMVpnPluginOld *plugin, + const char *message, + const char **hints) +{ + NMVpnPluginOldPrivate *priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE (plugin); + + /* Plugin must be able to accept the new secrets if it calls this method */ + g_return_if_fail (NM_VPN_PLUGIN_OLD_GET_CLASS (plugin)->new_secrets); + + /* Plugin cannot call this method if NetworkManager didn't originally call + * ConnectInteractive(). + */ + g_return_if_fail (priv->interactive == TRUE); + + /* Cancel the connect timer since secrets might take a while. It'll + * get restarted when the secrets come back via NewSecrets(). + */ + if (priv->connect_timer) + g_source_remove (priv->connect_timer); + + g_signal_emit (plugin, signals[SECRETS_REQUIRED], 0, message, hints); +} + +/***************************************************************/ + +#define DATA_KEY_TAG "DATA_KEY=" +#define DATA_VAL_TAG "DATA_VAL=" +#define SECRET_KEY_TAG "SECRET_KEY=" +#define SECRET_VAL_TAG "SECRET_VAL=" + +static void +free_secret (gpointer data) +{ + char *secret = data; + + memset (secret, 0, strlen (secret)); + g_free (secret); +} + +/** + * nm_vpn_plugin_old_read_vpn_details: + * @fd: file descriptor to read from, usually stdin (0) + * @out_data: (out) (transfer full): on successful return, a hash table + * (mapping char*:char*) containing the key/value pairs of VPN data items + * @out_secrets: (out) (transfer full): on successful return, a hash table + * (mapping char*:char*) containing the key/value pairsof VPN secrets + * + * Parses key/value pairs from a file descriptor (normally stdin) passed by + * an applet when the applet calls the authentication dialog of the VPN plugin. + * + * Returns: %TRUE if reading values was successful, %FALSE if not + **/ +gboolean +nm_vpn_plugin_old_read_vpn_details (int fd, + GHashTable **out_data, + GHashTable **out_secrets) +{ + GHashTable *data, *secrets; + gboolean success = FALSE; + char *key = NULL, *val = NULL; + GString *line; + gchar c; + + if (out_data) + g_return_val_if_fail (*out_data == NULL, FALSE); + if (out_secrets) + g_return_val_if_fail (*out_secrets == NULL, FALSE); + + data = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + secrets = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, free_secret); + + line = g_string_new (NULL); + + /* Read stdin for data and secret items until we get a DONE */ + while (1) { + ssize_t nr; + GHashTable *hash = NULL; + + errno = 0; + nr = read (fd, &c, 1); + if (nr == -1) { + if (errno == EAGAIN) { + g_usleep (100); + continue; + } + break; + } + + if (c != '\n') { + g_string_append_c (line, c); + continue; + } + + /* Check for the finish marker */ + if (strcmp (line->str, "DONE") == 0) + break; + + /* Otherwise it's a data/secret item */ + if (strncmp (line->str, DATA_KEY_TAG, strlen (DATA_KEY_TAG)) == 0) { + hash = data; + key = g_strdup (line->str + strlen (DATA_KEY_TAG)); + } else if (strncmp (line->str, DATA_VAL_TAG, strlen (DATA_VAL_TAG)) == 0) { + hash = data; + val = g_strdup (line->str + strlen (DATA_VAL_TAG)); + } else if (strncmp (line->str, SECRET_KEY_TAG, strlen (SECRET_KEY_TAG)) == 0) { + hash = secrets; + key = g_strdup (line->str + strlen (SECRET_KEY_TAG)); + } else if (strncmp (line->str, SECRET_VAL_TAG, strlen (SECRET_VAL_TAG)) == 0) { + hash = secrets; + val = g_strdup (line->str + strlen (SECRET_VAL_TAG)); + } + g_string_truncate (line, 0); + + if (key && val && hash) { + g_hash_table_insert (hash, key, val); + key = NULL; + val = NULL; + success = TRUE; /* Got at least one value */ + } + } + + if (success) { + if (out_data) + *out_data = data; + else + g_hash_table_destroy (data); + + if (out_secrets) + *out_secrets = secrets; + else + g_hash_table_destroy (secrets); + } else { + g_hash_table_destroy (data); + g_hash_table_destroy (secrets); + } + + g_string_free (line, TRUE); + return success; +} + +/** + * nm_vpn_plugin_old_get_secret_flags: + * @data: hash table containing VPN key/value pair data items + * @secret_name: VPN secret key name for which to retrieve flags for + * @out_flags: (out): on success, the flags associated with @secret_name + * + * Given a VPN secret key name, attempts to find the corresponding flags data + * item in @data. If found, converts the flags data item to + * #NMSettingSecretFlags and returns it. + * + * Returns: %TRUE if the flag data item was found and successfully converted + * to flags, %FALSE if not + **/ +gboolean +nm_vpn_plugin_old_get_secret_flags (GHashTable *data, + const char *secret_name, + NMSettingSecretFlags *out_flags) +{ + char *flag_name; + const char *val; + unsigned long tmp; + gboolean success = FALSE; + + g_return_val_if_fail (data != NULL, FALSE); + g_return_val_if_fail (secret_name != NULL, FALSE); + g_return_val_if_fail (out_flags != NULL, FALSE); + g_return_val_if_fail (*out_flags == NM_SETTING_SECRET_FLAG_NONE, FALSE); + + flag_name = g_strdup_printf ("%s-flags", secret_name); + + /* Try new flags value first */ + val = g_hash_table_lookup (data, flag_name); + if (val) { + errno = 0; + tmp = strtoul (val, NULL, 10); + if (errno == 0 && tmp <= NM_SETTING_SECRET_FLAGS_ALL) { + *out_flags = (NMSettingSecretFlags) tmp; + success = TRUE; + } + } + + g_free (flag_name); + return success; +} + +/***************************************************************/ + +static void +impl_vpn_plugin_old_disconnect (NMVpnPluginOld *plugin, + GDBusMethodInvocation *context, + gpointer user_data) +{ + GError *error = NULL; + + if (nm_vpn_plugin_old_disconnect (plugin, &error)) + g_dbus_method_invocation_return_value (context, NULL); + else + g_dbus_method_invocation_take_error (context, error); +} + +static void +impl_vpn_plugin_old_set_config (NMVpnPluginOld *plugin, + GDBusMethodInvocation *context, + GVariant *config, + gpointer user_data) +{ + nm_vpn_plugin_old_set_config (plugin, config); + g_dbus_method_invocation_return_value (context, NULL); +} + +static void +impl_vpn_plugin_old_set_ip4_config (NMVpnPluginOld *plugin, + GDBusMethodInvocation *context, + GVariant *config, + gpointer user_data) +{ + nm_vpn_plugin_old_set_ip4_config (plugin, config); + g_dbus_method_invocation_return_value (context, NULL); +} + +static void +impl_vpn_plugin_old_set_ip6_config (NMVpnPluginOld *plugin, + GDBusMethodInvocation *context, + GVariant *config, + gpointer user_data) +{ + nm_vpn_plugin_old_set_ip6_config (plugin, config); + g_dbus_method_invocation_return_value (context, NULL); +} + +static void +impl_vpn_plugin_old_set_failure (NMVpnPluginOld *plugin, + GDBusMethodInvocation *context, + char *reason, + gpointer user_data) +{ + nm_vpn_plugin_old_failure (plugin, NM_VPN_PLUGIN_FAILURE_BAD_IP_CONFIG); + g_dbus_method_invocation_return_value (context, NULL); +} + +/*********************************************************************/ + +static void +sigterm_handler (int signum) +{ + g_slist_foreach (active_plugins, (GFunc) nm_vpn_plugin_old_emit_quit, NULL); +} + +static void +setup_unix_signal_handler (void) +{ + struct sigaction action; + sigset_t block_mask; + + action.sa_handler = sigterm_handler; + sigemptyset (&block_mask); + action.sa_mask = block_mask; + action.sa_flags = 0; + sigaction (SIGINT, &action, NULL); + sigaction (SIGTERM, &action, NULL); +} + +/*********************************************************************/ + +static void +one_plugin_destroyed (gpointer data, + GObject *object) +{ + active_plugins = g_slist_remove (active_plugins, object); +} + +static void +nm_vpn_plugin_old_init (NMVpnPluginOld *plugin) +{ + active_plugins = g_slist_append (active_plugins, plugin); + g_object_weak_ref (G_OBJECT (plugin), + one_plugin_destroyed, + NULL); +} + +static gboolean +init_sync (GInitable *initable, GCancellable *cancellable, GError **error) +{ + NMVpnPluginOld *plugin = NM_VPN_PLUGIN_OLD (initable); + NMVpnPluginOldPrivate *priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE (plugin); + GDBusConnection *connection = NULL; + GDBusProxy *proxy; + GVariant *ret; + gboolean success = FALSE; + + if (!priv->dbus_service_name) { + g_set_error_literal (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, + _("No service name specified")); + return FALSE; + } + + connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error); + if (!connection) + return FALSE; + + proxy = g_dbus_proxy_new_sync (connection, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | + G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, + NULL, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + cancellable, error); + if (!proxy) + goto out; + + ret = g_dbus_proxy_call_sync (proxy, + "RequestName", + g_variant_new ("(s)", priv->dbus_service_name), + G_DBUS_CALL_FLAGS_NONE, 0, + cancellable, error); + g_object_unref (proxy); + if (!ret) { + if (error && *error) + g_dbus_error_strip_remote_error (*error); + goto out; + } + g_variant_unref (ret); + + priv->dbus_vpn_plugin_old = nmdbus_vpn_plugin_skeleton_new (); + if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (priv->dbus_vpn_plugin_old), + connection, + NM_VPN_DBUS_PLUGIN_PATH, + error)) + goto out; + + _nm_dbus_bind_properties (plugin, priv->dbus_vpn_plugin_old); + _nm_dbus_bind_methods (plugin, priv->dbus_vpn_plugin_old, + "Connect", impl_vpn_plugin_old_connect, + "ConnectInteractive", impl_vpn_plugin_old_connect_interactive, + "NeedSecrets", impl_vpn_plugin_old_need_secrets, + "NewSecrets", impl_vpn_plugin_old_new_secrets, + "Disconnect", impl_vpn_plugin_old_disconnect, + "SetConfig", impl_vpn_plugin_old_set_config, + "SetIp4Config", impl_vpn_plugin_old_set_ip4_config, + "SetIp6Config", impl_vpn_plugin_old_set_ip6_config, + "SetFailure", impl_vpn_plugin_old_set_failure, + NULL); + + nm_vpn_plugin_old_set_connection (plugin, connection); + nm_vpn_plugin_old_set_state (plugin, NM_VPN_SERVICE_STATE_INIT); + + success = TRUE; + + out: + g_clear_object (&connection); + + return success; +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMVpnPluginOldPrivate *priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_DBUS_SERVICE_NAME: + /* Construct-only */ + priv->dbus_service_name = g_value_dup_string (value); + break; + case PROP_STATE: + nm_vpn_plugin_old_set_state (NM_VPN_PLUGIN_OLD (object), + (NMVpnServiceState) g_value_get_enum (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMVpnPluginOldPrivate *priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_DBUS_SERVICE_NAME: + g_value_set_string (value, priv->dbus_service_name); + break; + case PROP_STATE: + g_value_set_enum (value, nm_vpn_plugin_old_get_state (NM_VPN_PLUGIN_OLD (object))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +dispose (GObject *object) +{ + NMVpnPluginOld *plugin = NM_VPN_PLUGIN_OLD (object); + NMVpnPluginOldPrivate *priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE (plugin); + NMVpnServiceState state; + GError *err = NULL; + + if (priv->fail_stop_id) { + g_source_remove (priv->fail_stop_id); + priv->fail_stop_id = 0; + } + + state = nm_vpn_plugin_old_get_state (plugin); + + if (state == NM_VPN_SERVICE_STATE_STARTED || + state == NM_VPN_SERVICE_STATE_STARTING) + nm_vpn_plugin_old_disconnect (plugin, &err); + + if (err) { + g_warning ("Error disconnecting VPN connection: %s", err->message); + g_error_free (err); + } + + G_OBJECT_CLASS (nm_vpn_plugin_old_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + NMVpnPluginOld *plugin = NM_VPN_PLUGIN_OLD (object); + NMVpnPluginOldPrivate *priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE (plugin); + + nm_vpn_plugin_old_set_connection (plugin, NULL); + g_free (priv->dbus_service_name); + + g_clear_pointer (&priv->banner, g_free); + g_clear_pointer (&priv->tundev, g_free); + g_clear_pointer (&priv->gateway, g_free); + g_clear_pointer (&priv->mtu, g_free); + + G_OBJECT_CLASS (nm_vpn_plugin_old_parent_class)->finalize (object); +} + +static void +quit_timer_removed (gpointer data) +{ + NM_VPN_PLUGIN_OLD_GET_PRIVATE (data)->quit_timer = 0; +} + +static void +state_changed (NMVpnPluginOld *plugin, NMVpnServiceState state) +{ + NMVpnPluginOldPrivate *priv = NM_VPN_PLUGIN_OLD_GET_PRIVATE (plugin); + + switch (state) { + case NM_VPN_SERVICE_STATE_STARTING: + /* Remove the quit timer. */ + if (priv->quit_timer) + g_source_remove (priv->quit_timer); + + if (priv->fail_stop_id) { + g_source_remove (priv->fail_stop_id); + priv->fail_stop_id = 0; + } + break; + case NM_VPN_SERVICE_STATE_STOPPED: + priv->quit_timer = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT, + NM_VPN_PLUGIN_OLD_QUIT_TIMER, + quit_timer_expired, + plugin, + quit_timer_removed); + break; + default: + /* Clean up all timers we might have set up. */ + if (priv->connect_timer) + g_source_remove (priv->connect_timer); + + if (priv->quit_timer) + g_source_remove (priv->quit_timer); + + if (priv->fail_stop_id) { + g_source_remove (priv->fail_stop_id); + priv->fail_stop_id = 0; + } + break; + } +} + +static void +nm_vpn_plugin_old_class_init (NMVpnPluginOldClass *plugin_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (plugin_class); + + g_type_class_add_private (object_class, sizeof (NMVpnPluginOldPrivate)); + + /* virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->dispose = dispose; + object_class->finalize = finalize; + + plugin_class->state_changed = state_changed; + + /* properties */ + + /** + * NMVpnPluginOld:service-name: + * + * The D-Bus service name of this plugin. + */ + g_object_class_install_property + (object_class, PROP_DBUS_SERVICE_NAME, + g_param_spec_string (NM_VPN_PLUGIN_OLD_DBUS_SERVICE_NAME, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + /** + * NMVpnPluginOld:state: + * + * The state of the plugin. + */ + g_object_class_install_property + (object_class, PROP_STATE, + g_param_spec_enum (NM_VPN_PLUGIN_OLD_STATE, "", "", + NM_TYPE_VPN_SERVICE_STATE, + NM_VPN_SERVICE_STATE_INIT, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /* signals */ + signals[STATE_CHANGED] = + g_signal_new ("state-changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMVpnPluginOldClass, state_changed), + NULL, NULL, + NULL, + G_TYPE_NONE, 1, + G_TYPE_UINT); + + signals[SECRETS_REQUIRED] = + g_signal_new ("secrets-required", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + NULL, + G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRV); + + signals[CONFIG] = + g_signal_new ("config", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMVpnPluginOldClass, config), + NULL, NULL, + NULL, + G_TYPE_NONE, 1, + G_TYPE_VARIANT); + + signals[IP4_CONFIG] = + g_signal_new ("ip4-config", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMVpnPluginOldClass, ip4_config), + NULL, NULL, + NULL, + G_TYPE_NONE, 1, + G_TYPE_VARIANT); + + signals[IP6_CONFIG] = + g_signal_new ("ip6-config", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMVpnPluginOldClass, ip6_config), + NULL, NULL, + NULL, + G_TYPE_NONE, 1, + G_TYPE_VARIANT); + + signals[LOGIN_BANNER] = + g_signal_new ("login-banner", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMVpnPluginOldClass, login_banner), + NULL, NULL, + NULL, + G_TYPE_NONE, 1, + G_TYPE_STRING); + + signals[FAILURE] = + g_signal_new ("failure", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMVpnPluginOldClass, failure), + NULL, NULL, + NULL, + G_TYPE_NONE, 1, + G_TYPE_UINT); + + signals[QUIT] = + g_signal_new ("quit", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMVpnPluginOldClass, quit), + NULL, NULL, + NULL, + G_TYPE_NONE, 0, + G_TYPE_NONE); + + setup_unix_signal_handler (); +} + +static void +nm_vpn_plugin_old_initable_iface_init (GInitableIface *iface) +{ + iface->init = init_sync; +} diff --git a/libnm/nm-vpn-plugin-old.h b/libnm/nm-vpn-plugin-old.h new file mode 100644 index 00000000..7fcc1c1c --- /dev/null +++ b/libnm/nm-vpn-plugin-old.h @@ -0,0 +1,136 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2007 - 2008 Novell, Inc. + * Copyright 2007 - 2013 Red Hat, Inc. + */ + +#ifndef __NM_VPN_PLUGIN_OLD_H__ +#define __NM_VPN_PLUGIN_OLD_H__ + +#include <gio/gio.h> +#include <nm-vpn-dbus-interface.h> +#include <nm-connection.h> + +G_BEGIN_DECLS + +#define NM_TYPE_VPN_PLUGIN_OLD (nm_vpn_plugin_old_get_type ()) +#define NM_VPN_PLUGIN_OLD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_VPN_PLUGIN_OLD, NMVpnPluginOld)) +#define NM_VPN_PLUGIN_OLD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_VPN_PLUGIN_OLD, NMVpnPluginOldClass)) +#define NM_IS_VPN_PLUGIN_OLD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_VPN_PLUGIN_OLD)) +#define NM_IS_VPN_PLUGIN_OLD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_VPN_PLUGIN_OLD)) +#define NM_VPN_PLUGIN_OLD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_VPN_PLUGIN_OLD, NMVpnPluginOldClass)) + +#define NM_VPN_PLUGIN_OLD_DBUS_SERVICE_NAME "service-name" +#define NM_VPN_PLUGIN_OLD_STATE "state" + +typedef struct { + GObject parent; +} NMVpnPluginOld; + +typedef struct { + GObjectClass parent; + + /* Signals */ + void (*state_changed) (NMVpnPluginOld *plugin, + NMVpnServiceState state); + + void (*ip4_config) (NMVpnPluginOld *plugin, + GVariant *ip4_config); + + void (*login_banner) (NMVpnPluginOld *plugin, + const char *banner); + + void (*failure) (NMVpnPluginOld *plugin, + NMVpnPluginFailure reason); + + void (*quit) (NMVpnPluginOld *plugin); + + void (*config) (NMVpnPluginOld *plugin, + GVariant *config); + + void (*ip6_config) (NMVpnPluginOld *plugin, + GVariant *config); + + /* virtual methods */ + gboolean (*connect) (NMVpnPluginOld *plugin, + NMConnection *connection, + GError **err); + + gboolean (*need_secrets) (NMVpnPluginOld *plugin, + NMConnection *connection, + char **setting_name, + GError **error); + + gboolean (*disconnect) (NMVpnPluginOld *plugin, + GError **err); + + gboolean (*new_secrets) (NMVpnPluginOld *plugin, + NMConnection *connection, + GError **error); + + gboolean (*connect_interactive) (NMVpnPluginOld *plugin, + NMConnection *connection, + GVariant *details, + GError **error); + + /*< private >*/ + gpointer padding[8]; +} NMVpnPluginOldClass; + +GType nm_vpn_plugin_old_get_type (void); + +GDBusConnection *nm_vpn_plugin_old_get_connection (NMVpnPluginOld *plugin); +NMVpnServiceState nm_vpn_plugin_old_get_state (NMVpnPluginOld *plugin); +void nm_vpn_plugin_old_set_state (NMVpnPluginOld *plugin, + NMVpnServiceState state); + +void nm_vpn_plugin_old_secrets_required (NMVpnPluginOld *plugin, + const char *message, + const char **hints); + +void nm_vpn_plugin_old_set_login_banner (NMVpnPluginOld *plugin, + const char *banner); + +void nm_vpn_plugin_old_failure (NMVpnPluginOld *plugin, + NMVpnPluginFailure reason); + +void nm_vpn_plugin_old_set_config (NMVpnPluginOld *plugin, + GVariant *config); + +void nm_vpn_plugin_old_set_ip4_config (NMVpnPluginOld *plugin, + GVariant *ip4_config); + +void nm_vpn_plugin_old_set_ip6_config (NMVpnPluginOld *plugin, + GVariant *ip6_config); + +gboolean nm_vpn_plugin_old_disconnect (NMVpnPluginOld *plugin, + GError **err); + +/* Utility functions */ + +gboolean nm_vpn_plugin_old_read_vpn_details (int fd, + GHashTable **out_data, + GHashTable **out_secrets); + +gboolean nm_vpn_plugin_old_get_secret_flags (GHashTable *data, + const char *secret_name, + NMSettingSecretFlags *out_flags); + +G_END_DECLS + +#endif /* __NM_VPN_PLUGIN_OLD_H__ */ diff --git a/libnm/nm-wimax-nsp.c b/libnm/nm-wimax-nsp.c new file mode 100644 index 00000000..0fed1c6e --- /dev/null +++ b/libnm/nm-wimax-nsp.c @@ -0,0 +1,290 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2011 Red Hat, Inc. + */ + +#include "config.h" + +#include <string.h> + +#include "nm-glib-compat.h" + +#include <nm-connection.h> +#include <nm-setting-connection.h> +#include <nm-setting-wimax.h> + +#include "nm-wimax-nsp.h" +#include "nm-dbus-interface.h" +#include "nm-object-private.h" +#include "nm-enum-types.h" + +G_DEFINE_TYPE (NMWimaxNsp, nm_wimax_nsp, NM_TYPE_OBJECT) + +#define NM_WIMAX_NSP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_WIMAX_NSP, NMWimaxNspPrivate)) + +typedef struct { + char *name; + guint32 signal_quality; + NMWimaxNspNetworkType network_type; +} NMWimaxNspPrivate; + +enum { + PROP_0, + PROP_NAME, + PROP_SIGNAL_QUALITY, + PROP_NETWORK_TYPE, + + LAST_PROP +}; + +/** + * nm_wimax_nsp_get_name: + * @nsp: a #NMWimaxNsp + * + * Gets the name of the wimax NSP + * + * Returns: the name + **/ +const char * +nm_wimax_nsp_get_name (NMWimaxNsp *nsp) +{ + g_return_val_if_fail (NM_IS_WIMAX_NSP (nsp), NULL); + + return NM_WIMAX_NSP_GET_PRIVATE (nsp)->name; +} + +/** + * nm_wimax_nsp_get_signal_quality: + * @nsp: a #NMWimaxNsp + * + * Gets the WPA signal quality of the wimax NSP. + * + * Returns: the signal quality + **/ +guint32 +nm_wimax_nsp_get_signal_quality (NMWimaxNsp *nsp) +{ + g_return_val_if_fail (NM_IS_WIMAX_NSP (nsp), 0); + + return NM_WIMAX_NSP_GET_PRIVATE (nsp)->signal_quality; +} + +/** + * nm_wimax_nsp_get_network_type: + * @nsp: a #NMWimaxNsp + * + * Gets the network type of the wimax NSP. + * + * Returns: the network type + **/ +NMWimaxNspNetworkType +nm_wimax_nsp_get_network_type (NMWimaxNsp *nsp) +{ + g_return_val_if_fail (NM_IS_WIMAX_NSP (nsp), NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN); + + return NM_WIMAX_NSP_GET_PRIVATE (nsp)->network_type; +} + +/** + * nm_wimax_nsp_connection_valid: + * @nsp: an #NMWimaxNsp to validate @connection against + * @connection: an #NMConnection to validate against @nsp + * + * Validates a given connection against a given WiMAX NSP to ensure that the + * connection may be activated with that NSP. The connection must match the + * @nsp's network name and other attributes. + * + * Returns: %TRUE if the connection may be activated with this WiMAX NSP, + * %FALSE if it cannot be. + **/ +gboolean +nm_wimax_nsp_connection_valid (NMWimaxNsp *nsp, NMConnection *connection) +{ + NMSettingConnection *s_con; + NMSettingWimax *s_wimax; + const char *ctype; + const char *nsp_name; + const char *setting_name; + + s_con = nm_connection_get_setting_connection (connection); + g_assert (s_con); + ctype = nm_setting_connection_get_connection_type (s_con); + if (strcmp (ctype, NM_SETTING_WIMAX_SETTING_NAME) != 0) + return FALSE; + + s_wimax = nm_connection_get_setting_wimax (connection); + if (!s_wimax) + return FALSE; + + setting_name = nm_setting_wimax_get_network_name (s_wimax); + if (!setting_name) + return FALSE; + + nsp_name = nm_wimax_nsp_get_name (nsp); + g_warn_if_fail (nsp_name != NULL); + if (g_strcmp0 (nsp_name, setting_name) != 0) + return FALSE; + + return TRUE; +} + +/** + * nm_wimax_nsp_filter_connections: + * @nsp: an #NMWimaxNsp to filter connections for + * @connections: (element-type NMConnection): an array of #NMConnections to + * filter + * + * Filters a given array of connections for a given #NMWimaxNsp object and + * return connections which may be activated with the NSP. Any returned + * connections will match the @nsp's network name and other attributes. + * + * Returns: (transfer container) (element-type NMConnection): an array of + * #NMConnections that could be activated with the given @nsp. The array should + * be freed with g_ptr_array_unref() when it is no longer required. + **/ +GPtrArray * +nm_wimax_nsp_filter_connections (NMWimaxNsp *nsp, const GPtrArray *connections) +{ + GPtrArray *filtered; + int i; + + filtered = g_ptr_array_new_with_free_func (g_object_unref); + for (i = 0; i < connections->len; i++) { + NMConnection *candidate = connections->pdata[i]; + + if (nm_wimax_nsp_connection_valid (nsp, candidate)) + g_ptr_array_add (filtered, g_object_ref (candidate)); + } + + return filtered; +} + +/************************************************************/ + +static void +nm_wimax_nsp_init (NMWimaxNsp *nsp) +{ +} + +static void +finalize (GObject *object) +{ + NMWimaxNspPrivate *priv = NM_WIMAX_NSP_GET_PRIVATE (object); + + g_free (priv->name); + + G_OBJECT_CLASS (nm_wimax_nsp_parent_class)->finalize (object); +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMWimaxNsp *nsp = NM_WIMAX_NSP (object); + + switch (prop_id) { + case PROP_NAME: + g_value_set_string (value, nm_wimax_nsp_get_name (nsp)); + break; + case PROP_SIGNAL_QUALITY: + g_value_set_uint (value, nm_wimax_nsp_get_signal_quality (nsp)); + break; + case PROP_NETWORK_TYPE: + g_value_set_enum (value, nm_wimax_nsp_get_network_type (nsp)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +init_dbus (NMObject *object) +{ + NMWimaxNspPrivate *priv = NM_WIMAX_NSP_GET_PRIVATE (object); + const NMPropertiesInfo property_info[] = { + { NM_WIMAX_NSP_NAME, &priv->name }, + { NM_WIMAX_NSP_SIGNAL_QUALITY, &priv->signal_quality }, + { NM_WIMAX_NSP_NETWORK_TYPE, &priv->network_type }, + { NULL }, + }; + + NM_OBJECT_CLASS (nm_wimax_nsp_parent_class)->init_dbus (object); + + _nm_object_register_properties (object, + NM_DBUS_INTERFACE_WIMAX_NSP, + property_info); +} + +static void +nm_wimax_nsp_class_init (NMWimaxNspClass *nsp_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (nsp_class); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (nsp_class); + + g_type_class_add_private (nsp_class, sizeof (NMWimaxNspPrivate)); + + _nm_object_class_add_interface (nm_object_class, NM_DBUS_INTERFACE_WIMAX_NSP); + + /* virtual methods */ + object_class->get_property = get_property; + object_class->finalize = finalize; + + nm_object_class->init_dbus = init_dbus; + + /* properties */ + + /** + * NMWimaxNsp:name: + * + * The name of the WiMAX NSP. + **/ + g_object_class_install_property + (object_class, PROP_NAME, + g_param_spec_string (NM_WIMAX_NSP_NAME, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMWimaxNsp:signal-quality: + * + * The signal quality of the WiMAX NSP. + **/ + g_object_class_install_property + (object_class, PROP_SIGNAL_QUALITY, + g_param_spec_uint (NM_WIMAX_NSP_SIGNAL_QUALITY, "", "", + 0, 100, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMWimaxNsp:network-type: + * + * The network type of the WiMAX NSP. + **/ + g_object_class_install_property + (object_class, PROP_NETWORK_TYPE, + g_param_spec_enum (NM_WIMAX_NSP_NETWORK_TYPE, "", "", + NM_TYPE_WIMAX_NSP_NETWORK_TYPE, + NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); +} diff --git a/libnm/nm-wimax-nsp.h b/libnm/nm-wimax-nsp.h new file mode 100644 index 00000000..cdc7b236 --- /dev/null +++ b/libnm/nm-wimax-nsp.h @@ -0,0 +1,85 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2011 Red Hat, Inc. + * Copyright 2009 Novell, Inc. + */ + +#ifndef __NM_WIMAX_NSP_H__ +#define __NM_WIMAX_NSP_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only <NetworkManager.h> can be included directly." +#endif + +#include <nm-object.h> + +G_BEGIN_DECLS + +#define NM_TYPE_WIMAX_NSP (nm_wimax_nsp_get_type ()) +#define NM_WIMAX_NSP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_WIMAX_NSP, NMWimaxNsp)) +#define NM_WIMAX_NSP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_WIMAX_NSP, NMWimaxNspClass)) +#define NM_IS_WIMAX_NSP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_WIMAX_NSP)) +#define NM_IS_WIMAX_NSP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_WIMAX_NSP)) +#define NM_WIMAX_NSP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_WIMAX_NSP, NMWimaxNspClass)) + +#define NM_WIMAX_NSP_NAME "name" +#define NM_WIMAX_NSP_SIGNAL_QUALITY "signal-quality" +#define NM_WIMAX_NSP_NETWORK_TYPE "network-type" + +/** + * NMWimaxNspNetworkType: + * @NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN: unknown network type + * @NM_WIMAX_NSP_NETWORK_TYPE_HOME: home network + * @NM_WIMAX_NSP_NETWORK_TYPE_PARTNER: partner network + * @NM_WIMAX_NSP_NETWORK_TYPE_ROAMING_PARTNER: roaming partner network + * + * WiMAX network type. + */ +typedef enum { + NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN = 0, + NM_WIMAX_NSP_NETWORK_TYPE_HOME = 1, + NM_WIMAX_NSP_NETWORK_TYPE_PARTNER = 2, + NM_WIMAX_NSP_NETWORK_TYPE_ROAMING_PARTNER = 3 +} NMWimaxNspNetworkType; + +struct _NMWimaxNsp { + NMObject parent; +}; + +typedef struct { + NMObjectClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMWimaxNspClass; + +GType nm_wimax_nsp_get_type (void); + +const char * nm_wimax_nsp_get_name (NMWimaxNsp *nsp); +guint32 nm_wimax_nsp_get_signal_quality (NMWimaxNsp *nsp); +NMWimaxNspNetworkType nm_wimax_nsp_get_network_type (NMWimaxNsp *nsp); + +GPtrArray * nm_wimax_nsp_filter_connections (NMWimaxNsp *nsp, + const GPtrArray *connections); + +gboolean nm_wimax_nsp_connection_valid (NMWimaxNsp *nsp, + NMConnection *connection); + +G_END_DECLS + +#endif /* __NM_WIMAX_NSP_H__ */ diff --git a/libnm/tests/Makefile.am b/libnm/tests/Makefile.am new file mode 100644 index 00000000..38449fad --- /dev/null +++ b/libnm/tests/Makefile.am @@ -0,0 +1,41 @@ +if ENABLE_TESTS + +AM_CPPFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/libnm \ + -I$(top_builddir)/libnm \ + -I$(top_srcdir)/libnm-core \ + -I$(top_builddir)/libnm-core \ + -DNETWORKMANAGER_COMPILATION \ + -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ + -DTEST_NM_SERVICE=\"$(abs_top_srcdir)/tools/test-networkmanager-service.py\" \ + $(GLIB_CFLAGS) + +LDADD = \ + $(top_builddir)/libnm/libnm.la \ + $(GLIB_LIBS) + +noinst_PROGRAMS = $(TESTS) + +TESTS = test-nm-client test-remote-settings-client test-secret-agent + +test_nm_client_SOURCES = \ + common.c \ + common.h \ + test-nm-client.c + +test_remote_settings_client_SOURCES = \ + common.c \ + common.h \ + test-remote-settings-client.c + +test_secret_agent_SOURCES = \ + common.c \ + common.h \ + test-secret-agent.c + +TESTS_ENVIRONMENT = $(srcdir)/libnm-test-launch.sh + +endif + +EXTRA_DIST = libnm-test-launch.sh diff --git a/libnm/tests/Makefile.in b/libnm/tests/Makefile.in new file mode 100644 index 00000000..ab5f794c --- /dev/null +++ b/libnm/tests/Makefile.in @@ -0,0 +1,918 @@ +# Makefile.in generated by automake 1.13.4 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 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@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +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@ +@ENABLE_TESTS_TRUE@noinst_PROGRAMS = $(am__EXEEXT_1) +@ENABLE_TESTS_TRUE@TESTS = test-nm-client$(EXEEXT) \ +@ENABLE_TESTS_TRUE@ test-remote-settings-client$(EXEEXT) \ +@ENABLE_TESTS_TRUE@ test-secret-agent$(EXEEXT) +subdir = libnm/tests +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/build-aux/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \ + $(top_srcdir)/m4/compiler_warnings.m4 \ + $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gnome-code-coverage.m4 \ + $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ + $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ + $(top_srcdir)/m4/introspection.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/vapigen.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 = +@ENABLE_TESTS_TRUE@am__EXEEXT_1 = test-nm-client$(EXEEXT) \ +@ENABLE_TESTS_TRUE@ test-remote-settings-client$(EXEEXT) \ +@ENABLE_TESTS_TRUE@ test-secret-agent$(EXEEXT) +PROGRAMS = $(noinst_PROGRAMS) +am__test_nm_client_SOURCES_DIST = common.c common.h test-nm-client.c +@ENABLE_TESTS_TRUE@am_test_nm_client_OBJECTS = common.$(OBJEXT) \ +@ENABLE_TESTS_TRUE@ test-nm-client.$(OBJEXT) +test_nm_client_OBJECTS = $(am_test_nm_client_OBJECTS) +test_nm_client_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +@ENABLE_TESTS_TRUE@test_nm_client_DEPENDENCIES = \ +@ENABLE_TESTS_TRUE@ $(top_builddir)/libnm/libnm.la \ +@ENABLE_TESTS_TRUE@ $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +am__test_remote_settings_client_SOURCES_DIST = common.c common.h \ + test-remote-settings-client.c +@ENABLE_TESTS_TRUE@am_test_remote_settings_client_OBJECTS = \ +@ENABLE_TESTS_TRUE@ common.$(OBJEXT) \ +@ENABLE_TESTS_TRUE@ test-remote-settings-client.$(OBJEXT) +test_remote_settings_client_OBJECTS = \ + $(am_test_remote_settings_client_OBJECTS) +test_remote_settings_client_LDADD = $(LDADD) +@ENABLE_TESTS_TRUE@test_remote_settings_client_DEPENDENCIES = \ +@ENABLE_TESTS_TRUE@ $(top_builddir)/libnm/libnm.la \ +@ENABLE_TESTS_TRUE@ $(am__DEPENDENCIES_1) +am__test_secret_agent_SOURCES_DIST = common.c common.h \ + test-secret-agent.c +@ENABLE_TESTS_TRUE@am_test_secret_agent_OBJECTS = common.$(OBJEXT) \ +@ENABLE_TESTS_TRUE@ test-secret-agent.$(OBJEXT) +test_secret_agent_OBJECTS = $(am_test_secret_agent_OBJECTS) +test_secret_agent_LDADD = $(LDADD) +@ENABLE_TESTS_TRUE@test_secret_agent_DEPENDENCIES = \ +@ENABLE_TESTS_TRUE@ $(top_builddir)/libnm/libnm.la \ +@ENABLE_TESTS_TRUE@ $(am__DEPENDENCIES_1) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +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_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(test_nm_client_SOURCES) \ + $(test_remote_settings_client_SOURCES) \ + $(test_secret_agent_SOURCES) +DIST_SOURCES = $(am__test_nm_client_SOURCES_DIST) \ + $(am__test_remote_settings_client_SOURCES_DIST) \ + $(am__test_secret_agent_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red='[0;31m'; \ + grn='[0;32m'; \ + lgn='[1;32m'; \ + blu='[1;34m'; \ + mgn='[0;35m'; \ + brg='[1m'; \ + std='[m'; \ + fi; \ +} +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BLUEZ5_CFLAGS = @BLUEZ5_CFLAGS@ +BLUEZ5_LIBS = @BLUEZ5_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CKDB_PATH = @CKDB_PATH@ +CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ +CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ +CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@ +DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DHCLIENT_PATH = @DHCLIENT_PATH@ +DHCPCD_PATH = @DHCPCD_PATH@ +DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@ +DLLTOOL = @DLLTOOL@ +DNSMASQ_PATH = @DNSMASQ_PATH@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GENHTML = @GENHTML@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MAKEFILE = @GLIB_MAKEFILE@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ +GNUTLS_LIBS = @GNUTLS_LIBS@ +GREP = @GREP@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +IPTABLES_PATH = @IPTABLES_PATH@ +IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@ +IWMX_SDK_LIBS = @IWMX_SDK_LIBS@ +KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDL = @LIBDL@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBNDP_CFLAGS = @LIBNDP_CFLAGS@ +LIBNDP_LIBS = @LIBNDP_LIBS@ +LIBNL_CFLAGS = @LIBNL_CFLAGS@ +LIBNL_LIBS = @LIBNL_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ +LIBSOUP_LIBS = @LIBSOUP_LIBS@ +LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@ +LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MM_GLIB_CFLAGS = @MM_GLIB_CFLAGS@ +MM_GLIB_LIBS = @MM_GLIB_LIBS@ +MOC = @MOC@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NEWT_CFLAGS = @NEWT_CFLAGS@ +NEWT_LIBS = @NEWT_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ +NM_MICRO_VERSION = @NM_MICRO_VERSION@ +NM_MINOR_VERSION = @NM_MINOR_VERSION@ +NM_MODIFY_SYSTEM_POLICY = @NM_MODIFY_SYSTEM_POLICY@ +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@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POLKIT_CFLAGS = @POLKIT_CFLAGS@ +POLKIT_LIBS = @POLKIT_LIBS@ +POSUB = @POSUB@ +PPPD_PATH = @PPPD_PATH@ +PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ +PPPOE_PATH = @PPPOE_PATH@ +QT_CFLAGS = @QT_CFLAGS@ +QT_LIBS = @QT_LIBS@ +RANLIB = @RANLIB@ +READLINE_LIBS = @READLINE_LIBS@ +SED = @SED@ +SELINUX_CFLAGS = @SELINUX_CFLAGS@ +SELINUX_LIBS = @SELINUX_LIBS@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@ +SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@ +SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@ +SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@ +SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ +SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@ +SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ +UDEV_DIR = @UDEV_DIR@ +USE_NLS = @USE_NLS@ +UUID_CFLAGS = @UUID_CFLAGS@ +UUID_LIBS = @UUID_LIBS@ +VALGRIND_RULES = @VALGRIND_RULES@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +nmbinary = @nmbinary@ +nmconfdir = @nmconfdir@ +nmdatadir = @nmdatadir@ +nmrundir = @nmrundir@ +nmstatedir = @nmstatedir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +with_dhclient = @with_dhclient@ +with_dhcpcd = @with_dhcpcd@ +with_netconfig = @with_netconfig@ +with_resolvconf = @with_resolvconf@ +with_valgrind = @with_valgrind@ +@ENABLE_TESTS_TRUE@AM_CPPFLAGS = \ +@ENABLE_TESTS_TRUE@ -I$(top_srcdir)/include \ +@ENABLE_TESTS_TRUE@ -I$(top_srcdir)/libnm \ +@ENABLE_TESTS_TRUE@ -I$(top_builddir)/libnm \ +@ENABLE_TESTS_TRUE@ -I$(top_srcdir)/libnm-core \ +@ENABLE_TESTS_TRUE@ -I$(top_builddir)/libnm-core \ +@ENABLE_TESTS_TRUE@ -DNETWORKMANAGER_COMPILATION \ +@ENABLE_TESTS_TRUE@ -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ +@ENABLE_TESTS_TRUE@ -DTEST_NM_SERVICE=\"$(abs_top_srcdir)/tools/test-networkmanager-service.py\" \ +@ENABLE_TESTS_TRUE@ $(GLIB_CFLAGS) + +@ENABLE_TESTS_TRUE@LDADD = \ +@ENABLE_TESTS_TRUE@ $(top_builddir)/libnm/libnm.la \ +@ENABLE_TESTS_TRUE@ $(GLIB_LIBS) + +@ENABLE_TESTS_TRUE@test_nm_client_SOURCES = \ +@ENABLE_TESTS_TRUE@ common.c \ +@ENABLE_TESTS_TRUE@ common.h \ +@ENABLE_TESTS_TRUE@ test-nm-client.c + +@ENABLE_TESTS_TRUE@test_remote_settings_client_SOURCES = \ +@ENABLE_TESTS_TRUE@ common.c \ +@ENABLE_TESTS_TRUE@ common.h \ +@ENABLE_TESTS_TRUE@ test-remote-settings-client.c + +@ENABLE_TESTS_TRUE@test_secret_agent_SOURCES = \ +@ENABLE_TESTS_TRUE@ common.c \ +@ENABLE_TESTS_TRUE@ common.h \ +@ENABLE_TESTS_TRUE@ test-secret-agent.c + +@ENABLE_TESTS_TRUE@TESTS_ENVIRONMENT = $(srcdir)/libnm-test-launch.sh +EXTRA_DIST = libnm-test-launch.sh +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libnm/tests/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu libnm/tests/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +test-nm-client$(EXEEXT): $(test_nm_client_OBJECTS) $(test_nm_client_DEPENDENCIES) $(EXTRA_test_nm_client_DEPENDENCIES) + @rm -f test-nm-client$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_nm_client_OBJECTS) $(test_nm_client_LDADD) $(LIBS) + +test-remote-settings-client$(EXEEXT): $(test_remote_settings_client_OBJECTS) $(test_remote_settings_client_DEPENDENCIES) $(EXTRA_test_remote_settings_client_DEPENDENCIES) + @rm -f test-remote-settings-client$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_remote_settings_client_OBJECTS) $(test_remote_settings_client_LDADD) $(LIBS) + +test-secret-agent$(EXEEXT): $(test_secret_agent_OBJECTS) $(test_secret_agent_DEPENDENCIES) $(EXTRA_test_secret_agent_DEPENDENCIES) + @rm -f test-secret-agent$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_secret_agent_OBJECTS) $(test_secret_agent_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-nm-client.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-remote-settings-client.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-secret-agent.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + 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-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + 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" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +check-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list=' $(TESTS) '; \ + $(am__tty_colors); \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + col=$$red; res=XPASS; \ + ;; \ + *) \ + col=$$grn; res=PASS; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xfail=`expr $$xfail + 1`; \ + col=$$lgn; res=XFAIL; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + col=$$red; res=FAIL; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + col=$$blu; res=SKIP; \ + fi; \ + echo "$${col}$$res$${std}: $$tst"; \ + done; \ + if test "$$all" -eq 1; then \ + tests="test"; \ + All=""; \ + else \ + tests="tests"; \ + All="All "; \ + fi; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="$$All$$all $$tests passed"; \ + else \ + if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ + banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all $$tests failed"; \ + else \ + if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ + banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + if test "$$skip" -eq 1; then \ + skipped="($$skip test was not run)"; \ + else \ + skipped="($$skip tests were not run)"; \ + fi; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + if test "$$failed" -eq 0; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + fi; \ + echo "$${col}$$dashes$${std}"; \ + echo "$${col}$$banner$${std}"; \ + test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \ + test -z "$$report" || echo "$${col}$$report$${std}"; \ + echo "$${col}$$dashes$${std}"; \ + test "$$failed" -eq 0; \ + else :; fi + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ + clean-generic clean-libtool clean-noinstPROGRAMS cscopelist-am \ + ctags ctags-am 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 tags-am uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libnm/tests/common.c b/libnm/tests/common.c new file mode 100644 index 00000000..a28e5112 --- /dev/null +++ b/libnm/tests/common.c @@ -0,0 +1,187 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * 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, 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 2010 - 2014 Red Hat, Inc. + * + */ + +#include "config.h" + +#include <glib.h> +#include <string.h> + +#include "NetworkManager.h" + +#include "common.h" + +static gboolean +name_exists (GDBusConnection *c, const char *name) +{ + GVariant *reply; + gboolean exists = FALSE; + + reply = g_dbus_connection_call_sync (c, + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", + "GetNameOwner", + g_variant_new ("(s)", name), + NULL, + G_DBUS_CALL_FLAGS_NO_AUTO_START, + -1, + NULL, + NULL); + if (reply != NULL) { + exists = TRUE; + g_variant_unref (reply); + } + + return exists; +} + +NMTestServiceInfo * +nm_test_service_init (void) +{ + NMTestServiceInfo *info; + const char *args[2] = { TEST_NM_SERVICE, NULL }; + GError *error = NULL; + int i; + + info = g_malloc0 (sizeof (*info)); + + info->bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); + g_assert_no_error (error); + + /* Spawn the test service. info->keepalive_fd will be a pipe to the service's + * stdin; if it closes, the service will exit immediately. We use this to + * make sure the service exits if the test program crashes. + */ + g_spawn_async_with_pipes (NULL, (char **) args, NULL, 0, NULL, NULL, + &info->pid, &info->keepalive_fd, NULL, NULL, &error); + g_assert_no_error (error); + + /* Wait until the service is registered on the bus */ + for (i = 100; i > 0; i--) { + if (name_exists (info->bus, "org.freedesktop.NetworkManager")) + break; + g_usleep (G_USEC_PER_SEC / 50); + } + g_assert (i > 0); + + /* Grab a proxy to our fake NM service to trigger tests */ + info->proxy = g_dbus_proxy_new_sync (info->bus, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | + G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS | + G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, + NULL, + NM_DBUS_SERVICE, + NM_DBUS_PATH, + "org.freedesktop.NetworkManager.LibnmGlibTest", + NULL, &error); + g_assert_no_error (error); + + return info; +} + +void +nm_test_service_cleanup (NMTestServiceInfo *info) +{ + int i; + + g_object_unref (info->proxy); + kill (info->pid, SIGTERM); + + /* Wait until the bus notices the service is gone */ + for (i = 100; i > 0; i--) { + if (!name_exists (info->bus, "org.freedesktop.NetworkManager")) + break; + g_usleep (G_USEC_PER_SEC / 50); + } + g_assert (i > 0); + + g_object_unref (info->bus); + close (info->keepalive_fd); + + memset (info, 0, sizeof (*info)); + g_free (info); +} + +typedef struct { + GMainLoop *loop; + const char *ifname; + char *path; + NMDevice *device; +} AddDeviceInfo; + +static void +device_added_cb (NMClient *client, + NMDevice *device, + gpointer user_data) +{ + AddDeviceInfo *info = user_data; + + g_assert (device); + g_assert_cmpstr (nm_object_get_path (NM_OBJECT (device)), ==, info->path); + g_assert_cmpstr (nm_device_get_iface (device), ==, info->ifname); + + info->device = device; + g_main_loop_quit (info->loop); +} + +static gboolean +timeout (gpointer user_data) +{ + g_assert_not_reached (); + return G_SOURCE_REMOVE; +} + +NMDevice * +nm_test_service_add_device (NMTestServiceInfo *sinfo, NMClient *client, + const char *method, const char *ifname) +{ + AddDeviceInfo info; + GError *error = NULL; + GVariant *ret; + guint timeout_id; + + ret = g_dbus_proxy_call_sync (sinfo->proxy, + method, + g_variant_new ("(s)", ifname), + G_DBUS_CALL_FLAGS_NO_AUTO_START, + 3000, + NULL, + &error); + g_assert_no_error (error); + g_assert (ret); + g_assert_cmpstr (g_variant_get_type_string (ret), ==, "(o)"); + g_variant_get (ret, "(o)", &info.path); + g_variant_unref (ret); + + /* Wait for libnm to find the device */ + info.ifname = ifname; + info.loop = g_main_loop_new (NULL, FALSE); + g_signal_connect (client, "device-added", + G_CALLBACK (device_added_cb), &info); + timeout_id = g_timeout_add_seconds (5, timeout, NULL); + g_main_loop_run (info.loop); + + g_source_remove (timeout_id); + g_signal_handlers_disconnect_by_func (client, device_added_cb, &info); + g_free (info.path); + g_main_loop_unref (info.loop); + + return info.device; +} diff --git a/libnm/tests/common.h b/libnm/tests/common.h new file mode 100644 index 00000000..aa15167b --- /dev/null +++ b/libnm/tests/common.h @@ -0,0 +1,37 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2014 Red Hat, Inc. + */ + +#include <gio/gio.h> +#include <NetworkManager.h> + +typedef struct { + GDBusConnection *bus; + GDBusProxy *proxy; + GPid pid; + int keepalive_fd; +} NMTestServiceInfo; + +NMTestServiceInfo *nm_test_service_init (void); +void nm_test_service_cleanup (NMTestServiceInfo *info); + +NMDevice *nm_test_service_add_device (NMTestServiceInfo *info, + NMClient *client, + const char *method, + const char *ifname); diff --git a/libnm/tests/libnm-test-launch.sh b/libnm/tests/libnm-test-launch.sh new file mode 100755 index 00000000..42d9fbe2 --- /dev/null +++ b/libnm/tests/libnm-test-launch.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +# Spawn DBus if there's none +if [ -z "$DBUS_SESSION_BUS_ADDRESS" ]; then + eval `dbus-launch --sh-syntax` + trap "kill $DBUS_SESSION_BUS_PID" EXIT +fi + +"$@" diff --git a/libnm/tests/test-nm-client.c b/libnm/tests/test-nm-client.c new file mode 100644 index 00000000..3541c741 --- /dev/null +++ b/libnm/tests/test-nm-client.c @@ -0,0 +1,1193 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * 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, 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 2010 - 2014 Red Hat, Inc. + * + */ + +#include "config.h" + +#include <glib.h> +#include <string.h> +#include <sys/types.h> +#include <signal.h> + +#include <NetworkManager.h> +#include "nm-glib-compat.h" + +#include "common.h" + +#include "nm-test-utils.h" + +static GMainLoop *loop = NULL; +static NMTestServiceInfo *sinfo; + +/*******************************************************************/ + +static gboolean +loop_quit (gpointer user_data) +{ + g_main_loop_quit ((GMainLoop *) user_data); + return G_SOURCE_REMOVE; +} + +/*******************************************************************/ + +static void +devices_notify_cb (NMClient *c, + GParamSpec *pspec, + gpointer user_data) +{ + gboolean *notified = user_data; + const GPtrArray *devices; + NMDevice *device; + + devices = nm_client_get_devices (c); + g_assert (devices); + g_assert_cmpint (devices->len, ==, 1); + + device = g_ptr_array_index (devices, 0); + g_assert (device); + g_assert_cmpstr (nm_device_get_iface (device), ==, "eth0"); + + *notified = TRUE; +} + +static void +test_device_added (void) +{ + NMClient *client; + const GPtrArray *devices; + NMDevice *device; + gboolean notified = FALSE; + GError *error = NULL; + + sinfo = nm_test_service_init (); + client = nm_client_new (NULL, &error); + g_assert_no_error (error); + + devices = nm_client_get_devices (client); + g_assert (devices->len == 0); + + g_signal_connect (client, + "notify::devices", + (GCallback) devices_notify_cb, + ¬ified); + + /* Tell the test service to add a new device */ + nm_test_service_add_device (sinfo, client, "AddWiredDevice", "eth0"); + + /* coverity[loop_condition] */ + while (!notified) + g_main_context_iteration (NULL, TRUE); + + g_signal_handlers_disconnect_by_func (client, devices_notify_cb, ¬ified); + + devices = nm_client_get_devices (client); + g_assert (devices); + g_assert_cmpint (devices->len, ==, 1); + + device = g_ptr_array_index (devices, 0); + g_assert (device); + g_assert_cmpstr (nm_device_get_iface (device), ==, "eth0"); + + /* Try deleting the device via the ordinary NM interface, which should fail */ + nm_device_delete (device, NULL, &error); + g_assert_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_NOT_SOFTWARE); + + g_object_unref (client); + g_clear_pointer (&sinfo, nm_test_service_cleanup); +} + +/*******************************************************************/ + +typedef enum { + SIGNAL_FIRST = 0x01, + SIGNAL_SECOND = 0x02, + SIGNAL_MASK = 0x0F, + NOTIFY_FIRST = 0x10, + NOTIFY_SECOND = 0x20, + NOTIFY_MASK = 0xF0 +} DeviceSignaledAfterInitType; + +static void +device_sai_added_cb (NMClient *c, + NMDevice *device, + gpointer user_data) +{ + guint *result = user_data; + + g_assert (device); + g_assert_cmpstr (nm_device_get_iface (device), ==, "eth0"); + + g_assert ((*result & SIGNAL_MASK) == 0); + *result |= *result ? SIGNAL_SECOND : SIGNAL_FIRST; +} + +static void +devices_sai_notify_cb (NMClient *c, + GParamSpec *pspec, + gpointer user_data) +{ + guint *result = user_data; + const GPtrArray *devices; + NMDevice *device; + + devices = nm_client_get_devices (c); + g_assert (devices); + g_assert_cmpint (devices->len, ==, 1); + + device = g_ptr_array_index (devices, 0); + g_assert (device); + g_assert_cmpstr (nm_device_get_iface (device), ==, "eth0"); + + g_assert ((*result & NOTIFY_MASK) == 0); + *result |= *result ? NOTIFY_SECOND : NOTIFY_FIRST; +} + +static void +test_device_added_signal_after_init (void) +{ + NMClient *client; + const GPtrArray *devices; + NMDevice *device; + guint result = 0; + GError *error = NULL; + + sinfo = nm_test_service_init (); + client = nm_client_new (NULL, &error); + g_assert_no_error (error); + + devices = nm_client_get_devices (client); + g_assert (devices->len == 0); + + g_signal_connect (client, + NM_CLIENT_DEVICE_ADDED, + (GCallback) device_sai_added_cb, + &result); + + g_signal_connect (client, + "notify::" NM_CLIENT_DEVICES, + (GCallback) devices_sai_notify_cb, + &result); + + /* Tell the test service to add a new device */ + nm_test_service_add_device (sinfo, client, "AddWiredDevice", "eth0"); + + /* Ensure the 'device-added' signal doesn't show up before + * the 'Devices' property change notification */ + /* coverity[loop_condition] */ + while (!(result & SIGNAL_MASK) && !(result & NOTIFY_MASK)) + g_main_context_iteration (NULL, TRUE); + + g_signal_handlers_disconnect_by_func (client, device_sai_added_cb, &result); + g_signal_handlers_disconnect_by_func (client, devices_sai_notify_cb, &result); + + g_assert ((result & SIGNAL_MASK) == SIGNAL_FIRST); + g_assert ((result & NOTIFY_MASK) == NOTIFY_SECOND); + + devices = nm_client_get_devices (client); + g_assert (devices); + g_assert_cmpint (devices->len, ==, 1); + + device = g_ptr_array_index (devices, 0); + g_assert (device); + g_assert_cmpstr (nm_device_get_iface (device), ==, "eth0"); + + g_object_unref (client); + g_clear_pointer (&sinfo, nm_test_service_cleanup); +} + +/*******************************************************************/ + +static const char *expected_bssid = "66:55:44:33:22:11"; + +typedef struct { + GMainLoop *loop; + gboolean found; + char *ap_path; + gboolean signaled; + gboolean notified; + guint quit_id; + guint quit_count; +} WifiApInfo; + +static void +wifi_check_quit (WifiApInfo *info) +{ + info->quit_count--; + if (info->quit_count == 0) { + g_source_remove (info->quit_id); + info->quit_id = 0; + g_main_loop_quit (info->loop); + } +} + +static void +got_ap_path (WifiApInfo *info, const char *path) +{ + if (info->ap_path) + g_assert_cmpstr (info->ap_path, ==, path); + else + info->ap_path = g_strdup (path); +} + +static void +wifi_ap_added_cb (NMDeviceWifi *w, + NMAccessPoint *ap, + WifiApInfo *info) +{ + g_assert (ap); + g_assert_cmpstr (nm_access_point_get_bssid (ap), ==, expected_bssid); + got_ap_path (info, nm_object_get_path (NM_OBJECT (ap))); + + info->signaled = TRUE; + wifi_check_quit (info); +} + +static void +wifi_ap_add_notify_cb (NMDeviceWifi *w, + GParamSpec *pspec, + WifiApInfo *info) +{ + const GPtrArray *aps; + NMAccessPoint *ap; + + aps = nm_device_wifi_get_access_points (w); + g_assert (aps); + g_assert_cmpint (aps->len, ==, 1); + + ap = g_ptr_array_index (aps, 0); + g_assert (ap); + g_assert_cmpstr (nm_access_point_get_bssid (ap), ==, "66:55:44:33:22:11"); + got_ap_path (info, nm_object_get_path (NM_OBJECT (ap))); + + info->notified = TRUE; + wifi_check_quit (info); +} + +static void +wifi_ap_removed_cb (NMDeviceWifi *w, + NMAccessPoint *ap, + WifiApInfo *info) +{ + g_assert (ap); + g_assert_cmpstr (info->ap_path, ==, nm_object_get_path (NM_OBJECT (ap))); + + info->signaled = TRUE; + wifi_check_quit (info); +} + +static void +wifi_ap_remove_notify_cb (NMDeviceWifi *w, + GParamSpec *pspec, + WifiApInfo *info) +{ + const GPtrArray *aps; + + aps = nm_device_wifi_get_access_points (w); + g_assert (aps->len == 0); + + info->notified = TRUE; + wifi_check_quit (info); +} + +static void +test_wifi_ap_added_removed (void) +{ + NMClient *client; + NMDeviceWifi *wifi; + WifiApInfo info = { loop, FALSE, FALSE, 0, 0 }; + GVariant *ret; + GError *error = NULL; + char *expected_path = NULL; + + sinfo = nm_test_service_init (); + client = nm_client_new (NULL, &error); + g_assert_no_error (error); + + /*************************************/ + /* Add the wifi device */ + wifi = (NMDeviceWifi *) nm_test_service_add_device (sinfo, client, "AddWifiDevice", "wlan0"); + g_assert (NM_IS_DEVICE_WIFI (wifi)); + + /*************************************/ + /* Add the wifi AP */ + info.signaled = FALSE; + info.notified = FALSE; + info.quit_id = 0; + + ret = g_dbus_proxy_call_sync (sinfo->proxy, + "AddWifiAp", + g_variant_new ("(sss)", "wlan0", "test-ap", expected_bssid), + G_DBUS_CALL_FLAGS_NO_AUTO_START, + 3000, + NULL, + &error); + g_assert_no_error (error); + g_assert (ret); + g_assert_cmpstr (g_variant_get_type_string (ret), ==, "(o)"); + g_variant_get (ret, "(o)", &expected_path); + g_variant_unref (ret); + + g_signal_connect (wifi, + "access-point-added", + (GCallback) wifi_ap_added_cb, + &info); + info.quit_count = 1; + + g_signal_connect (wifi, + "notify::access-points", + (GCallback) wifi_ap_add_notify_cb, + &info); + info.quit_count++; + + /* Wait for libnm to find the AP */ + info.quit_id = g_timeout_add_seconds (5, loop_quit, loop); + g_main_loop_run (loop); + + g_assert (info.signaled); + g_assert (info.notified); + g_assert (info.ap_path); + g_assert_cmpstr (info.ap_path, ==, expected_path); + g_signal_handlers_disconnect_by_func (wifi, wifi_ap_added_cb, &info); + g_signal_handlers_disconnect_by_func (wifi, wifi_ap_add_notify_cb, &info); + + /*************************************/ + /* Remove the wifi device */ + info.signaled = FALSE; + info.notified = FALSE; + info.quit_id = 0; + + ret = g_dbus_proxy_call_sync (sinfo->proxy, + "RemoveWifiAp", + g_variant_new ("(so)", "wlan0", expected_path), + G_DBUS_CALL_FLAGS_NO_AUTO_START, + 3000, + NULL, + &error); + g_assert_no_error (error); + g_clear_pointer (&ret, g_variant_unref); + + g_signal_connect (wifi, + "access-point-removed", + (GCallback) wifi_ap_removed_cb, + &info); + info.quit_count = 1; + + g_signal_connect (wifi, + "notify::access-points", + (GCallback) wifi_ap_remove_notify_cb, + &info); + info.quit_count++; + + /* Wait for libnm to find the AP */ + info.quit_id = g_timeout_add_seconds (5, loop_quit, loop); + g_main_loop_run (loop); + + g_assert (info.signaled); + g_assert (info.notified); + g_signal_handlers_disconnect_by_func (wifi, wifi_ap_removed_cb, &info); + g_signal_handlers_disconnect_by_func (wifi, wifi_ap_remove_notify_cb, &info); + + g_free (info.ap_path); + g_free (expected_path); + + g_object_unref (client); + g_clear_pointer (&sinfo, nm_test_service_cleanup); +} + +/*******************************************************************/ + +static const char *expected_nsp_name = "Clear"; + +typedef struct { + GMainLoop *loop; + gboolean found; + char *nsp_path; + gboolean signaled; + gboolean notified; + guint quit_id; + guint quit_count; +} WimaxNspInfo; + +static void +wimax_check_quit (WimaxNspInfo *info) +{ + info->quit_count--; + if (info->quit_count == 0) { + g_source_remove (info->quit_id); + info->quit_id = 0; + g_main_loop_quit (info->loop); + } +} + +static void +got_nsp_path (WimaxNspInfo *info, const char *path) +{ + if (info->nsp_path) + g_assert_cmpstr (info->nsp_path, ==, path); + else + info->nsp_path = g_strdup (path); +} + +static void +wimax_nsp_added_cb (NMDeviceWimax *w, + NMWimaxNsp *nsp, + WimaxNspInfo *info) +{ + g_assert (nsp); + g_assert_cmpstr (nm_wimax_nsp_get_name (nsp), ==, expected_nsp_name); + got_nsp_path (info, nm_object_get_path (NM_OBJECT (nsp))); + + info->signaled = TRUE; + wimax_check_quit (info); +} + +static void +wimax_nsp_add_notify_cb (NMDeviceWimax *w, + GParamSpec *pspec, + WimaxNspInfo *info) +{ + const GPtrArray *nsps; + NMWimaxNsp *nsp; + + nsps = nm_device_wimax_get_nsps (w); + g_assert (nsps); + g_assert_cmpint (nsps->len, ==, 1); + + nsp = g_ptr_array_index (nsps, 0); + g_assert (nsp); + g_assert_cmpstr (nm_wimax_nsp_get_name (nsp), ==, expected_nsp_name); + got_nsp_path (info, nm_object_get_path (NM_OBJECT (nsp))); + + info->notified = TRUE; + wimax_check_quit (info); +} + +static void +wimax_nsp_removed_cb (NMDeviceWimax *w, + NMWimaxNsp *nsp, + WimaxNspInfo *info) +{ + g_assert (nsp); + g_assert_cmpstr (info->nsp_path, ==, nm_object_get_path (NM_OBJECT (nsp))); + + info->signaled = TRUE; + wimax_check_quit (info); +} + +static void +wimax_nsp_remove_notify_cb (NMDeviceWimax *w, + GParamSpec *pspec, + WimaxNspInfo *info) +{ + const GPtrArray *nsps; + + nsps = nm_device_wimax_get_nsps (w); + g_assert (nsps->len == 0); + + info->notified = TRUE; + wimax_check_quit (info); +} + +static void +test_wimax_nsp_added_removed (void) +{ + NMClient *client; + NMDeviceWimax *wimax; + WimaxNspInfo info = { loop, FALSE, FALSE, 0, 0 }; + GVariant *ret; + GError *error = NULL; + char *expected_path = NULL; + + sinfo = nm_test_service_init (); + client = nm_client_new (NULL, &error); + g_assert_no_error (error); + + /*************************************/ + /* Add the wimax device */ + wimax = (NMDeviceWimax *) nm_test_service_add_device (sinfo, client, "AddWimaxDevice", "wmx0"); + g_assert (NM_IS_DEVICE_WIMAX (wimax)); + + /*************************************/ + /* Add the wimax NSP */ + info.signaled = FALSE; + info.notified = FALSE; + info.quit_id = 0; + + ret = g_dbus_proxy_call_sync (sinfo->proxy, + "AddWimaxNsp", + g_variant_new ("(ss)", "wmx0", expected_nsp_name), + G_DBUS_CALL_FLAGS_NO_AUTO_START, + 3000, + NULL, + &error); + g_assert_no_error (error); + g_assert (ret); + g_assert_cmpstr (g_variant_get_type_string (ret), ==, "(o)"); + g_variant_get (ret, "(o)", &expected_path); + g_variant_unref (ret); + + g_signal_connect (wimax, + "nsp-added", + (GCallback) wimax_nsp_added_cb, + &info); + info.quit_count = 1; + + g_signal_connect (wimax, + "notify::nsps", + (GCallback) wimax_nsp_add_notify_cb, + &info); + info.quit_count++; + + /* Wait for libnm to find the AP */ + info.quit_id = g_timeout_add_seconds (5, loop_quit, loop); + g_main_loop_run (loop); + + g_assert (info.signaled); + g_assert (info.notified); + g_assert (info.nsp_path); + g_assert_cmpstr (info.nsp_path, ==, expected_path); + g_signal_handlers_disconnect_by_func (wimax, wimax_nsp_added_cb, &info); + g_signal_handlers_disconnect_by_func (wimax, wimax_nsp_add_notify_cb, &info); + + /*************************************/ + /* Remove the wimax NSP */ + info.signaled = FALSE; + info.notified = FALSE; + info.quit_id = 0; + + ret = g_dbus_proxy_call_sync (sinfo->proxy, + "RemoveWimaxNsp", + g_variant_new ("(so)", "wmx0", expected_path), + G_DBUS_CALL_FLAGS_NO_AUTO_START, + 3000, + NULL, + &error); + g_assert_no_error (error); + g_clear_pointer (&ret, g_variant_unref); + + g_signal_connect (wimax, + "nsp-removed", + (GCallback) wimax_nsp_removed_cb, + &info); + info.quit_count = 1; + + g_signal_connect (wimax, + "notify::nsps", + (GCallback) wimax_nsp_remove_notify_cb, + &info); + info.quit_count++; + + /* Wait for libnm to find the AP */ + info.quit_id = g_timeout_add_seconds (5, loop_quit, loop); + g_main_loop_run (loop); + + g_assert (info.signaled); + g_assert (info.notified); + g_signal_handlers_disconnect_by_func (wimax, wimax_nsp_removed_cb, &info); + g_signal_handlers_disconnect_by_func (wimax, wimax_nsp_remove_notify_cb, &info); + + g_free (info.nsp_path); + g_free (expected_path); + + g_object_unref (client); + g_clear_pointer (&sinfo, nm_test_service_cleanup); +} + +/*******************************************************************/ + +typedef struct { + GMainLoop *loop; + gboolean signaled; + gboolean notified; + guint quit_count; + guint quit_id; +} DaInfo; + +static void +da_check_quit (DaInfo *info) +{ + info->quit_count--; + if (info->quit_count == 0) { + g_source_remove (info->quit_id); + info->quit_id = 0; + g_main_loop_quit (info->loop); + } +} + +static void +da_device_removed_cb (NMClient *c, + NMDevice *device, + DaInfo *info) +{ + g_assert_cmpstr (nm_device_get_iface (device), ==, "eth0"); + info->signaled = TRUE; + da_check_quit (info); +} + +static void +da_devices_notify_cb (NMClient *c, + GParamSpec *pspec, + DaInfo *info) +{ + const GPtrArray *devices; + NMDevice *device; + guint i; + const char *iface; + + devices = nm_client_get_devices (c); + g_assert (devices); + g_assert_cmpint (devices->len, ==, 2); + + for (i = 0; i < devices->len; i++) { + device = g_ptr_array_index (devices, i); + iface = nm_device_get_iface (device); + + g_assert (!strcmp (iface, "wlan0") || !strcmp (iface, "eth1")); + } + + info->notified = TRUE; + da_check_quit (info); +} + +static void +new_client_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + NMClient **out_client = user_data; + GError *error = NULL; + + *out_client = nm_client_new_finish (result, &error); + g_assert_no_error (error); + g_assert (*out_client != NULL); + + g_main_loop_quit (loop); +} + +static void +test_devices_array (void) +{ + NMClient *client = NULL; + DaInfo info = { loop }; + NMDevice *wlan0, *eth0, *eth1, *device; + const GPtrArray *devices; + GError *error = NULL; + GVariant *ret; + + sinfo = nm_test_service_init (); + + /* Make sure that we test the async codepath in at least one test... */ + nm_client_new_async (NULL, new_client_cb, &client); + g_main_loop_run (loop); + g_assert (client != NULL); + + /*************************************/ + /* Add some devices */ + wlan0 = nm_test_service_add_device (sinfo, client,"AddWifiDevice", "wlan0"); + eth0 = nm_test_service_add_device (sinfo, client, "AddWiredDevice", "eth0"); + eth1 = nm_test_service_add_device (sinfo, client, "AddWiredDevice", "eth1"); + + /* Ensure the devices now exist */ + devices = nm_client_get_devices (client); + g_assert (devices); + g_assert_cmpint (devices->len, ==, 3); + + device = nm_client_get_device_by_iface (client, "wlan0"); + g_assert (NM_IS_DEVICE_WIFI (device)); + g_assert (device == wlan0); + + device = nm_client_get_device_by_iface (client, "eth0"); + g_assert (NM_IS_DEVICE_ETHERNET (device)); + g_assert (device == eth0); + + device = nm_client_get_device_by_iface (client, "eth1"); + g_assert (NM_IS_DEVICE_ETHERNET (device)); + g_assert (device == eth1); + + /********************************/ + /* Now remove the device in the middle */ + ret = g_dbus_proxy_call_sync (sinfo->proxy, + "RemoveDevice", + g_variant_new ("(o)", nm_object_get_path (NM_OBJECT (eth0))), + G_DBUS_CALL_FLAGS_NO_AUTO_START, + 3000, + NULL, + &error); + g_assert_no_error (error); + g_assert (ret); + g_variant_unref (ret); + + g_signal_connect (client, + "device-removed", + (GCallback) da_device_removed_cb, + &info); + + g_signal_connect (client, + "notify::devices", + (GCallback) da_devices_notify_cb, + &info); + info.quit_count = 2; + + /* Wait for libnm to notice the changes */ + info.quit_id = g_timeout_add_seconds (5, loop_quit, loop); + g_main_loop_run (loop); + + g_assert_cmpint (info.quit_count, ==, 0); + g_signal_handlers_disconnect_by_func (client, da_device_removed_cb, &info); + g_signal_handlers_disconnect_by_func (client, da_devices_notify_cb, &info); + + /* Ensure only two are left */ + devices = nm_client_get_devices (client); + g_assert (devices); + g_assert_cmpint (devices->len, ==, 2); + + device = nm_client_get_device_by_iface (client, "wlan0"); + g_assert (NM_IS_DEVICE_WIFI (device)); + g_assert (device == wlan0); + + device = nm_client_get_device_by_iface (client, "eth1"); + g_assert (NM_IS_DEVICE_ETHERNET (device)); + g_assert (device == eth1); + + g_object_unref (client); + g_clear_pointer (&sinfo, nm_test_service_cleanup); +} + +static void +nm_running_changed (GObject *client, + GParamSpec *pspec, + gpointer user_data) +{ + int *running_changed = user_data; + + (*running_changed)++; + g_main_loop_quit (loop); +} + +static void +test_client_nm_running (void) +{ + NMClient *client1, *client2; + guint quit_id; + int running_changed = 0; + GError *error = NULL; + + client1 = nm_client_new (NULL, &error); + g_assert_no_error (error); + + g_assert (!nm_client_get_nm_running (client1)); + g_assert_cmpstr (nm_client_get_version (client1), ==, NULL); + + g_assert (!nm_client_networking_get_enabled (client1)); + /* This will have no effect, but it shouldn't cause any warnings either. */ + nm_client_networking_set_enabled (client1, TRUE, NULL); + g_assert (!nm_client_networking_get_enabled (client1)); + + /* OTOH, this should result in an error */ + nm_client_set_logging (client1, "DEFAULT", "INFO", &error); + g_assert_error (error, NM_CLIENT_ERROR, NM_CLIENT_ERROR_MANAGER_NOT_RUNNING); + g_clear_error (&error); + + /* Now start the test service. */ + sinfo = nm_test_service_init (); + client2 = nm_client_new (NULL, &error); + g_assert_no_error (error); + + /* client2 should know that NM is running, but the previously-created + * client1 hasn't gotten the news yet. + */ + g_assert (!nm_client_get_nm_running (client1)); + g_assert (nm_client_get_nm_running (client2)); + + g_signal_connect (client1, "notify::" NM_CLIENT_NM_RUNNING, + G_CALLBACK (nm_running_changed), &running_changed); + quit_id = g_timeout_add_seconds (5, loop_quit, loop); + g_main_loop_run (loop); + g_assert_cmpint (running_changed, ==, 1); + g_assert (nm_client_get_nm_running (client1)); + g_source_remove (quit_id); + + /* And kill it */ + g_clear_pointer (&sinfo, nm_test_service_cleanup); + + g_assert (nm_client_get_nm_running (client1)); + + quit_id = g_timeout_add_seconds (5, loop_quit, loop); + g_main_loop_run (loop); + g_assert_cmpint (running_changed, ==, 2); + g_assert (!nm_client_get_nm_running (client1)); + g_source_remove (quit_id); + + g_object_unref (client1); + g_object_unref (client2); +} + +typedef struct { + GMainLoop *loop; + NMActiveConnection *ac; + + int remaining; +} TestACInfo; + +static void +assert_ac_and_device (NMClient *client) +{ + const GPtrArray *devices, *acs, *ac_devices; + NMDevice *device, *ac_device; + NMActiveConnection *ac, *device_ac; + + acs = nm_client_get_active_connections (client); + g_assert (acs != NULL); + g_assert_cmpint (acs->len, ==, 1); + devices = nm_client_get_devices (client); + g_assert (devices != NULL); + g_assert_cmpint (devices->len, >=, 1); + + ac = acs->pdata[0]; + ac_devices = nm_active_connection_get_devices (ac); + g_assert (ac_devices != NULL); + g_assert_cmpint (ac_devices->len, ==, 1); + ac_device = ac_devices->pdata[0]; + g_assert (ac_device != NULL); + + device = devices->pdata[0]; + if (device != ac_device && devices->len > 1) + device = devices->pdata[1]; + device_ac = nm_device_get_active_connection (device); + g_assert (device_ac != NULL); + + g_assert_cmpstr (nm_object_get_path (NM_OBJECT (device)), ==, nm_object_get_path (NM_OBJECT (ac_device))); + g_assert (device == ac_device); + g_assert_cmpstr (nm_object_get_path (NM_OBJECT (ac)), ==, nm_object_get_path (NM_OBJECT (device_ac))); + g_assert (ac == device_ac); +} + +static void +add_and_activate_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + NMClient *client = NM_CLIENT (object); + TestACInfo *info = user_data; + GError *error = NULL; + + info->ac = nm_client_add_and_activate_connection_finish (client, result, &error); + g_assert_no_error (error); + g_assert (info->ac != NULL); + + assert_ac_and_device (client); + + info->remaining--; + if (!info->remaining) + g_main_loop_quit (info->loop); +} + +static void +client_acs_changed_cb (GObject *client, + GParamSpec *pspec, + gpointer user_data) +{ + TestACInfo *info = user_data; + const GPtrArray *acs; + + acs = nm_client_get_active_connections (NM_CLIENT (client)); + g_assert (acs != NULL); + g_assert_cmpint (acs->len, ==, 1); + + info->remaining--; + if (!info->remaining) + g_main_loop_quit (info->loop); +} + +static void +device_ac_changed_cb (GObject *device, + GParamSpec *pspec, + gpointer user_data) +{ + TestACInfo *info = user_data; + + g_assert (nm_device_get_active_connection (NM_DEVICE (device)) != NULL); + + info->remaining--; + if (!info->remaining) + g_main_loop_quit (info->loop); +} + +static void +test_active_connections (void) +{ + NMClient *client; + NMDevice *device; + NMConnection *conn; + TestACInfo info = { loop, NULL, 0 }; + GError *error = NULL; + + sinfo = nm_test_service_init (); + client = nm_client_new (NULL, &error); + g_assert_no_error (error); + + /* Tell the test service to add a new device */ + device = nm_test_service_add_device (sinfo, client, "AddWiredDevice", "eth0"); + + conn = nmtst_create_minimal_connection ("test-ac", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); + nm_client_add_and_activate_connection_async (client, conn, device, NULL, + NULL, add_and_activate_cb, &info); + g_object_unref (conn); + + g_signal_connect (client, "notify::" NM_CLIENT_ACTIVE_CONNECTIONS, + G_CALLBACK (client_acs_changed_cb), &info); + g_signal_connect (device, "notify::" NM_DEVICE_ACTIVE_CONNECTION, + G_CALLBACK (device_ac_changed_cb), &info); + + /* Two signals plus activate_cb */ + info.remaining = 3; + g_main_loop_run (loop); + g_signal_handlers_disconnect_by_func (client, client_acs_changed_cb, &info); + g_signal_handlers_disconnect_by_func (device, device_ac_changed_cb, &info); + + g_assert (info.ac != NULL); + + g_object_unref (info.ac); + g_object_unref (client); + + /* Ensure that we can correctly resolve the recursive property link between the + * AC and the Device in a newly-created client. + */ + client = nm_client_new (NULL, &error); + g_assert_no_error (error); + assert_ac_and_device (client); + g_object_unref (client); + + client = NULL; + nm_client_new_async (NULL, new_client_cb, &client); + g_main_loop_run (loop); + assert_ac_and_device (client); + g_object_unref (client); + + g_clear_pointer (&sinfo, nm_test_service_cleanup); +} + +static void +client_devices_changed_cb (GObject *client, + GParamSpec *pspec, + gpointer user_data) +{ + TestACInfo *info = user_data; + const GPtrArray *devices; + NMDevice *device; + + devices = nm_client_get_devices (NM_CLIENT (client)); + g_assert (devices != NULL); + if (devices->len < 2) + return; + g_assert_cmpint (devices->len, ==, 2); + + if (NM_IS_DEVICE_VLAN (devices->pdata[0])) + device = devices->pdata[0]; + else if (NM_IS_DEVICE_VLAN (devices->pdata[1])) + device = devices->pdata[1]; + else + g_assert_not_reached (); + + g_assert_cmpstr (nm_device_get_iface (device), ==, "eth0.1"); + + if (nm_device_get_active_connection (device)) + info->remaining--; + else { + g_signal_connect (device, "notify::" NM_DEVICE_ACTIVE_CONNECTION, + G_CALLBACK (device_ac_changed_cb), info); + } + + info->remaining--; + if (!info->remaining) + g_main_loop_quit (info->loop); +} + +typedef struct { + GMainLoop *loop; + NMRemoteConnection *remote; +} TestConnectionInfo; + +static void +add_connection_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + TestConnectionInfo *info = user_data; + GError *error = NULL; + + info->remote = nm_client_add_connection_finish (NM_CLIENT (object), result, &error); + g_assert_no_error (error); + g_main_loop_quit (info->loop); +} + +static void +activate_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + NMClient *client = NM_CLIENT (object); + TestACInfo *info = user_data; + GError *error = NULL; + + info->ac = nm_client_activate_connection_finish (client, result, &error); + g_assert_no_error (error); + g_assert (info->ac != NULL); + + assert_ac_and_device (client); + + info->remaining--; + if (!info->remaining) + g_main_loop_quit (info->loop); +} + +static void +test_activate_virtual (void) +{ + NMClient *client; + NMConnection *conn; + NMSettingConnection *s_con; + NMSettingVlan *s_vlan; + TestACInfo info = { loop, NULL, 0 }; + TestConnectionInfo conn_info = { loop, NULL }; + GError *error = NULL; + + sinfo = nm_test_service_init (); + client = nm_client_new (NULL, &error); + g_assert_no_error (error); + + nm_test_service_add_device (sinfo, client, "AddWiredDevice", "eth0"); + + conn = nmtst_create_minimal_connection ("test-ac", NULL, NM_SETTING_VLAN_SETTING_NAME, &s_con); + g_object_set (s_con, + NM_SETTING_CONNECTION_INTERFACE_NAME, "eth0.1", + NULL); + s_vlan = nm_connection_get_setting_vlan (conn); + g_object_set (s_vlan, + NM_SETTING_VLAN_ID, 1, + NM_SETTING_VLAN_PARENT, "eth0", + NULL); + + nm_client_add_connection_async (client, conn, TRUE, + NULL, add_connection_cb, &conn_info); + g_main_loop_run (loop); + g_object_unref (conn); + conn = NM_CONNECTION (conn_info.remote); + + nm_client_activate_connection_async (client, conn, NULL, NULL, + NULL, activate_cb, &info); + g_object_unref (conn); + + g_signal_connect (client, "notify::" NM_CLIENT_ACTIVE_CONNECTIONS, + G_CALLBACK (client_acs_changed_cb), &info); + g_signal_connect (client, "notify::" NM_CLIENT_DEVICES, + G_CALLBACK (client_devices_changed_cb), &info); + + /* As with test_active_connections() above, except that now we're waiting + * for NMClient:devices to change rather than NMDevice:active-connections. + */ + info.remaining = 3; + + g_main_loop_run (loop); + g_signal_handlers_disconnect_by_func (client, client_acs_changed_cb, &info); + g_signal_handlers_disconnect_by_func (client, client_devices_changed_cb, &info); + + g_assert (info.ac != NULL); + + g_object_unref (info.ac); + g_object_unref (client); + + g_clear_pointer (&sinfo, nm_test_service_cleanup); +} + +static void +activate_failed_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + NMClient *client = NM_CLIENT (object); + NMActiveConnection *ac; + GError *error = NULL; + + ac = nm_client_activate_connection_finish (client, result, &error); + g_assert (ac == NULL); + g_assert_error (error, NM_CLIENT_ERROR, NM_CLIENT_ERROR_OBJECT_CREATION_FAILED); + g_clear_error (&error); + + g_main_loop_quit (loop); +} + +static void +test_activate_failed (void) +{ + NMClient *client; + NMDevice *device; + NMConnection *conn; + GError *error = NULL; + + sinfo = nm_test_service_init (); + client = nm_client_new (NULL, &error); + g_assert_no_error (error); + + device = nm_test_service_add_device (sinfo, client, "AddWiredDevice", "eth0"); + + /* Note that test-networkmanager-service.py checks for this exact name */ + conn = nmtst_create_minimal_connection ("object-creation-failed-test", NULL, + NM_SETTING_WIRED_SETTING_NAME, NULL); + + nm_client_add_and_activate_connection_async (client, conn, device, NULL, + NULL, activate_failed_cb, NULL); + g_main_loop_run (loop); + + g_object_unref (conn); + g_object_unref (client); + + g_clear_pointer (&sinfo, nm_test_service_cleanup); +} + +/*******************************************************************/ + +NMTST_DEFINE (); + +int +main (int argc, char **argv) +{ + g_setenv ("LIBNM_USE_SESSION_BUS", "1", TRUE); + +#if !GLIB_CHECK_VERSION (2, 35, 0) + g_type_init (); +#endif + + nmtst_init (&argc, &argv, TRUE); + + loop = g_main_loop_new (NULL, FALSE); + + g_test_add_func ("/libnm/device-added", test_device_added); + g_test_add_func ("/libnm/device-added-signal-after-init", test_device_added_signal_after_init); + g_test_add_func ("/libnm/wifi-ap-added-removed", test_wifi_ap_added_removed); + g_test_add_func ("/libnm/wimax-nsp-added-removed", test_wimax_nsp_added_removed); + g_test_add_func ("/libnm/devices-array", test_devices_array); + g_test_add_func ("/libnm/client-nm-running", test_client_nm_running); + g_test_add_func ("/libnm/active-connections", test_active_connections); + g_test_add_func ("/libnm/activate-virtual", test_activate_virtual); + g_test_add_func ("/libnm/activate-failed", test_activate_failed); + + return g_test_run (); +} + diff --git a/libnm/tests/test-remote-settings-client.c b/libnm/tests/test-remote-settings-client.c new file mode 100644 index 00000000..8f9dc27f --- /dev/null +++ b/libnm/tests/test-remote-settings-client.c @@ -0,0 +1,547 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * 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, 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 2010 - 2011 Red Hat, Inc. + * + */ + +#include "config.h" + +#include <glib.h> +#include <string.h> +#include <sys/types.h> +#include <signal.h> + +#include <NetworkManager.h> + +#include "common.h" + +#include "nm-test-utils.h" + +static NMTestServiceInfo *sinfo; +static NMClient *client = NULL; +GDBusConnection *bus = NULL; +NMRemoteConnection *remote = NULL; + +/*******************************************************************/ + +static void +add_cb (GObject *s, + GAsyncResult *result, + gpointer user_data) +{ + gboolean *done = user_data; + GError *error = NULL; + + remote = nm_client_add_connection_finish (client, result, &error); + g_assert_no_error (error); + + *done = TRUE; + g_object_add_weak_pointer (G_OBJECT (remote), (void **) &remote); + + /* nm_client_add_connection_finish() adds a ref to @remote, but we + * want the weak pointer to be cleared as soon as @client drops its own ref. + * So drop ours. + */ + g_object_unref (remote); +} + +#define TEST_CON_ID "blahblahblah" + +static void +test_add_connection (void) +{ + NMConnection *connection; + time_t start, now; + gboolean done = FALSE; + + connection = nmtst_create_minimal_connection (TEST_CON_ID, NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); + + nm_client_add_connection_async (client, + connection, + TRUE, + NULL, + add_cb, + &done); + + start = time (NULL); + do { + now = time (NULL); + g_main_context_iteration (NULL, FALSE); + } while ((done == FALSE) && (now - start < 5)); + g_assert (done == TRUE); + g_assert (remote != NULL); + + /* Make sure the connection is the same as what we added */ + g_assert (nm_connection_compare (connection, + NM_CONNECTION (remote), + NM_SETTING_COMPARE_FLAG_EXACT) == TRUE); + g_object_unref (connection); +} + +/*******************************************************************/ + +static void +set_visible_cb (GObject *proxy, + GAsyncResult *result, + gpointer user_data) +{ + GError *error = NULL; + GVariant *ret; + + ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, &error); + g_assert_no_error (error); + g_variant_unref (ret); +} + +static void +visible_changed_cb (GObject *object, GParamSpec *pspec, gboolean *done) +{ + if (!nm_remote_connection_get_visible (NM_REMOTE_CONNECTION (object))) + *done = TRUE; +} + +static void +connection_removed_cb (NMClient *s, NMRemoteConnection *connection, gboolean *done) +{ + if (connection == remote) + *done = TRUE; +} + +static void +invis_has_settings_cb (NMSetting *setting, + const char *key, + const GValue *value, + GParamFlags flags, + gpointer user_data) +{ + *((gboolean *) user_data) = TRUE; +} + +static void +test_make_invisible (void) +{ + time_t start, now; + const GPtrArray *conns; + int i; + GDBusProxy *proxy; + gboolean visible_changed = FALSE, connection_removed = FALSE; + gboolean has_settings = FALSE; + char *path; + + g_assert (remote != NULL); + + /* Listen for the remove event when the connection becomes invisible */ + g_signal_connect (remote, "notify::" NM_REMOTE_CONNECTION_VISIBLE, G_CALLBACK (visible_changed_cb), &visible_changed); + g_signal_connect (client, "connection-removed", G_CALLBACK (connection_removed_cb), &connection_removed); + + path = g_strdup (nm_connection_get_path (NM_CONNECTION (remote))); + proxy = g_dbus_proxy_new_sync (bus, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, + NULL, + NM_DBUS_SERVICE, + path, + NM_DBUS_INTERFACE_SETTINGS_CONNECTION, + NULL, + NULL); + g_assert (proxy != NULL); + + /* Bypass the NMClient object so we can test it independently */ + g_dbus_proxy_call (proxy, + "SetVisible", + g_variant_new ("(b)", FALSE), + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, + set_visible_cb, NULL); + + /* Wait for the connection to be removed */ + start = time (NULL); + do { + now = time (NULL); + g_main_context_iteration (NULL, FALSE); + } while ((!visible_changed || !connection_removed) && (now - start < 5)); + g_assert (visible_changed == TRUE); + g_assert (connection_removed == TRUE); + + g_signal_handlers_disconnect_by_func (remote, G_CALLBACK (visible_changed_cb), &visible_changed); + g_signal_handlers_disconnect_by_func (client, G_CALLBACK (connection_removed_cb), &connection_removed); + + /* Ensure NMClient no longer has the connection */ + conns = nm_client_get_connections (client); + for (i = 0; i < conns->len; i++) { + NMConnection *candidate = NM_CONNECTION (conns->pdata[i]); + + g_assert ((gpointer) remote != (gpointer) candidate); + g_assert (strcmp (path, nm_connection_get_path (candidate)) != 0); + } + + /* And ensure the invisible connection no longer has any settings */ + g_assert (remote); + nm_connection_for_each_setting_value (NM_CONNECTION (remote), + invis_has_settings_cb, + &has_settings); + g_assert (has_settings == FALSE); + + g_free (path); + g_object_unref (proxy); +} + +/*******************************************************************/ + +static void +vis_new_connection_cb (NMClient *foo, + NMRemoteConnection *connection, + NMRemoteConnection **new) +{ + *new = connection; +} + +static void +test_make_visible (void) +{ + time_t start, now; + const GPtrArray *conns; + int i; + GDBusProxy *proxy; + gboolean found = FALSE; + char *path; + NMRemoteConnection *new = NULL; + + g_assert (remote != NULL); + + /* Wait for the new-connection signal when the connection is visible again */ + g_signal_connect (client, NM_CLIENT_CONNECTION_ADDED, + G_CALLBACK (vis_new_connection_cb), &new); + + path = g_strdup (nm_connection_get_path (NM_CONNECTION (remote))); + proxy = g_dbus_proxy_new_sync (bus, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, + NULL, + NM_DBUS_SERVICE, + path, + NM_DBUS_INTERFACE_SETTINGS_CONNECTION, + NULL, + NULL); + g_assert (proxy != NULL); + + /* Bypass the NMClient object so we can test it independently */ + g_dbus_proxy_call (proxy, + "SetVisible", + g_variant_new ("(b)", TRUE), + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, + set_visible_cb, NULL); + + /* Wait for the settings service to announce the connection again */ + start = time (NULL); + do { + now = time (NULL); + g_main_context_iteration (NULL, FALSE); + } while ((new == NULL) && (now - start < 5)); + + /* Ensure the new connection is the same as the one we made visible again */ + g_assert (new); + g_assert (new == remote); + + g_signal_handlers_disconnect_by_func (client, G_CALLBACK (vis_new_connection_cb), &new); + + /* Ensure NMClient has the connection */ + conns = nm_client_get_connections (client); + for (i = 0; i < conns->len; i++) { + NMConnection *candidate = NM_CONNECTION (conns->pdata[i]); + + if ((gpointer) remote == (gpointer) candidate) { + g_assert_cmpstr (path, ==, nm_connection_get_path (candidate)); + g_assert_cmpstr (TEST_CON_ID, ==, nm_connection_get_id (candidate)); + found = TRUE; + break; + } + } + g_assert (found == TRUE); + + g_free (path); + g_object_unref (proxy); +} + +/*******************************************************************/ + +static void +deleted_cb (GObject *proxy, + GAsyncResult *result, + gpointer user_data) +{ + GError *error = NULL; + GVariant *ret; + + ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, &error); + g_assert_no_error (error); + g_variant_unref (ret); +} + +static void +removed_cb (NMClient *s, NMRemoteConnection *connection, gboolean *done) +{ + if (connection == remote) + *done = TRUE; +} + +static void +test_remove_connection (void) +{ + NMRemoteConnection *connection; + time_t start, now; + const GPtrArray *conns; + int i; + GDBusProxy *proxy; + gboolean done = FALSE; + char *path; + + /* Find a connection to delete */ + conns = nm_client_get_connections (client); + g_assert_cmpint (conns->len, >, 0); + + connection = NM_REMOTE_CONNECTION (conns->pdata[0]); + g_assert (connection); + g_assert (remote == connection); + path = g_strdup (nm_connection_get_path (NM_CONNECTION (connection))); + g_signal_connect (client, "connection-removed", G_CALLBACK (removed_cb), &done); + + proxy = g_dbus_proxy_new_sync (bus, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, + NULL, + NM_DBUS_SERVICE, + path, + NM_DBUS_INTERFACE_SETTINGS_CONNECTION, + NULL, + NULL); + g_assert (proxy != NULL); + + /* Bypass the NMClient object so we can test it independently */ + g_dbus_proxy_call (proxy, + "Delete", + NULL, + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, + deleted_cb, NULL); + + start = time (NULL); + do { + now = time (NULL); + g_main_context_iteration (NULL, FALSE); + } while ((done == FALSE) && (now - start < 5)); + g_assert (done == TRUE); + + g_assert (!remote); + + /* Ensure NMClient no longer has the connection */ + conns = nm_client_get_connections (client); + for (i = 0; i < conns->len; i++) { + NMConnection *candidate = NM_CONNECTION (conns->pdata[i]); + + g_assert ((gpointer) connection != (gpointer) candidate); + g_assert_cmpstr (path, ==, nm_connection_get_path (candidate)); + } + + g_free (path); + g_object_unref (proxy); +} + +/*******************************************************************/ + +#define TEST_ADD_REMOVE_ID "add-remove-test-connection" + +static void +add_remove_cb (GObject *s, + GAsyncResult *result, + gpointer user_data) +{ + NMRemoteConnection *connection; + gboolean *done = user_data; + GError *error = NULL; + + connection = nm_client_add_connection_finish (client, result, &error); + g_assert_error (error, NM_CLIENT_ERROR, NM_CLIENT_ERROR_OBJECT_CREATION_FAILED); + g_assert (connection == NULL); + + *done = TRUE; +} + +static void +test_add_remove_connection (void) +{ + GVariant *ret; + GError *error = NULL; + NMConnection *connection; + time_t start, now; + gboolean done = FALSE; + + /* This will cause the test server to immediately delete the connection + * after creating it. + */ + ret = g_dbus_proxy_call_sync (sinfo->proxy, + "AutoRemoveNextConnection", + NULL, + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, + &error); + g_assert_no_error (error); + g_variant_unref (ret); + + connection = nmtst_create_minimal_connection (TEST_ADD_REMOVE_ID, NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); + nm_client_add_connection_async (client, + connection, + TRUE, + NULL, + add_remove_cb, + &done); + + start = time (NULL); + do { + now = time (NULL); + g_main_context_iteration (NULL, FALSE); + } while ((done == FALSE) && (now - start < 5)); + g_assert (done == TRUE); + + g_object_unref (connection); +} + +/*******************************************************************/ + +static void +add_bad_cb (GObject *s, + GAsyncResult *result, + gpointer user_data) +{ + gboolean *done = user_data; + GError *error = NULL; + + remote = nm_client_add_connection_finish (client, result, &error); + g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); + + *done = TRUE; +} + +static void +test_add_bad_connection (void) +{ + NMConnection *connection; + time_t start, now; + gboolean done = FALSE; + + /* The test daemon doesn't support bond connections */ + connection = nmtst_create_minimal_connection ("bad connection test", NULL, NM_SETTING_BOND_SETTING_NAME, NULL); + + nm_client_add_connection_async (client, + connection, + TRUE, + NULL, + add_bad_cb, + &done); + g_object_unref (connection); + + start = time (NULL); + do { + now = time (NULL); + g_main_context_iteration (NULL, FALSE); + } while ((done == FALSE) && (now - start < 5)); + g_assert (done == TRUE); + g_assert (remote == NULL); +} + +/*******************************************************************/ + +static void +save_hostname_cb (GObject *s, + GAsyncResult *result, + gpointer user_data) +{ + gboolean *done = user_data; + GError *error = NULL; + + nm_client_save_hostname_finish (client, result, &error); + g_assert_no_error (error); + + *done = TRUE; +} + +static void +test_save_hostname (void) +{ + time_t start, now; + gboolean done = FALSE; + GError *error = NULL; + + /* test-networkmanager-service.py requires the hostname to contain a '.' */ + nm_client_save_hostname (client, "foo", NULL, &error); + g_assert_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_HOSTNAME); + g_clear_error (&error); + + nm_client_save_hostname_async (client, "example.com", NULL, save_hostname_cb, &done); + + start = time (NULL); + do { + now = time (NULL); + g_main_context_iteration (NULL, FALSE); + } while ((done == FALSE) && (now - start < 5)); + g_assert (done == TRUE); + g_assert (remote == NULL); +} + +/*******************************************************************/ + +int +main (int argc, char **argv) +{ + int ret; + GError *error = NULL; + + g_setenv ("LIBNM_USE_SESSION_BUS", "1", TRUE); + +#if !GLIB_CHECK_VERSION (2, 35, 0) + g_type_init (); +#endif + + g_test_init (&argc, &argv, NULL); + + bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); + g_assert_no_error (error); + + sinfo = nm_test_service_init (); + + client = nm_client_new (NULL, &error); + g_assert_no_error (error); + g_assert (client != NULL); + + /* FIXME: these tests assume that they get run in order, but g_test_run() + * does not actually guarantee that! + */ + g_test_add_func ("/client/add_connection", test_add_connection); + g_test_add_func ("/client/make_invisible", test_make_invisible); + g_test_add_func ("/client/make_visible", test_make_visible); + g_test_add_func ("/client/remove_connection", test_remove_connection); + g_test_add_func ("/client/add_remove_connection", test_add_remove_connection); + g_test_add_func ("/client/add_bad_connection", test_add_bad_connection); + g_test_add_func ("/client/save_hostname", test_save_hostname); + + ret = g_test_run (); + + nm_test_service_cleanup (sinfo); + g_object_unref (client); + g_object_unref (bus); + + return ret; +} + diff --git a/libnm/tests/test-secret-agent.c b/libnm/tests/test-secret-agent.c new file mode 100644 index 00000000..0424b74e --- /dev/null +++ b/libnm/tests/test-secret-agent.c @@ -0,0 +1,655 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * 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, 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 2010 - 2014 Red Hat, Inc. + * + */ + +#include "config.h" + +#include <glib.h> +#include <string.h> +#include <sys/types.h> +#include <signal.h> + +#include <NetworkManager.h> +#include <nm-secret-agent-old.h> +#include "nm-glib-compat.h" +#include "nm-test-utils.h" + +#include "common.h" + +/*******************************************************************/ + +enum { + SECRET_REQUESTED, + + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +typedef NMSecretAgentOld TestSecretAgent; +typedef NMSecretAgentOldClass TestSecretAgentClass; + +GType test_secret_agent_get_type (void); +G_DEFINE_TYPE (TestSecretAgent, test_secret_agent, NM_TYPE_SECRET_AGENT_OLD) + +static void +test_secret_agent_init (TestSecretAgent *agent) +{ +} + +static void +test_secret_agent_get_secrets (NMSecretAgentOld *agent, + NMConnection *connection, + const char *connection_path, + const char *setting_name, + const char **hints, + NMSecretAgentGetSecretsFlags flags, + NMSecretAgentOldGetSecretsFunc callback, + gpointer callback_data) +{ + NMSettingWirelessSecurity *s_wsec; + GVariant *secrets = NULL; + GVariantBuilder secrets_builder, setting_builder; + char *secret = NULL; + GError *error = NULL; + + g_assert_cmpstr (setting_name, ==, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME); + + s_wsec = nm_connection_get_setting_wireless_security (connection); + g_assert (s_wsec); + g_assert_cmpstr (nm_setting_wireless_security_get_key_mgmt (s_wsec), ==, "wpa-psk"); + g_assert_cmpstr (nm_setting_wireless_security_get_psk (s_wsec), ==, NULL); + + g_signal_emit (agent, signals[SECRET_REQUESTED], 0, + connection, + connection_path, + NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_SECURITY_PSK, + &secret); + + if (!secret) { + error = g_error_new (NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_NO_SECRETS, + "No secrets"); + goto done; + } + + if (!strcmp (secret, "CANCEL")) { + error = g_error_new (NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_USER_CANCELED, + "User canceled"); + goto done; + } + + g_variant_builder_init (&setting_builder, NM_VARIANT_TYPE_SETTING); + g_variant_builder_add (&setting_builder, "{sv}", + NM_SETTING_WIRELESS_SECURITY_PSK, + g_variant_new_string (secret)); + + g_variant_builder_init (&secrets_builder, NM_VARIANT_TYPE_CONNECTION); + g_variant_builder_add (&secrets_builder, "{sa{sv}}", + setting_name, + &setting_builder); + secrets = g_variant_ref_sink (g_variant_builder_end (&secrets_builder)); + +done: + callback (agent, connection, secrets, error, callback_data); + g_clear_error (&error); + g_clear_pointer (&secrets, g_variant_unref); + g_free (secret); +} + +static void +test_secret_agent_cancel_get_secrets (NMSecretAgentOld *agent, + const gchar *connection_path, + const gchar *setting_name) +{ + g_assert_not_reached (); +} + +static void +test_secret_agent_save_secrets (NMSecretAgentOld *agent, + NMConnection *connection, + const gchar *connection_path, + NMSecretAgentOldSaveSecretsFunc callback, + gpointer callback_data) +{ + g_assert_not_reached (); +} + +static void +test_secret_agent_delete_secrets (NMSecretAgentOld *agent, + NMConnection *connection, + const gchar *connection_path, + NMSecretAgentOldDeleteSecretsFunc callback, + gpointer callback_data) +{ + g_assert_not_reached (); +} + +static void +test_secret_agent_class_init (TestSecretAgentClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMSecretAgentOldClass *agent_class = NM_SECRET_AGENT_OLD_CLASS (klass); + + agent_class->get_secrets = test_secret_agent_get_secrets; + agent_class->cancel_get_secrets = test_secret_agent_cancel_get_secrets; + agent_class->save_secrets = test_secret_agent_save_secrets; + agent_class->delete_secrets = test_secret_agent_delete_secrets; + + signals[SECRET_REQUESTED] = + g_signal_new ("secret-requested", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, NULL, + G_TYPE_STRING, 4, + NM_TYPE_CONNECTION, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING); + +} + +static NMSecretAgentOld * +test_secret_agent_new (void) +{ + NMSecretAgentOld *agent; + GError *error = NULL; + + agent = g_initable_new (test_secret_agent_get_type (), NULL, &error, + NM_SECRET_AGENT_OLD_IDENTIFIER, "test-secret-agent", + NM_SECRET_AGENT_OLD_AUTO_REGISTER, FALSE, + NULL); + g_assert_no_error (error); + + return agent; +} + +/*******************************************************************/ + +typedef struct { + NMTestServiceInfo *sinfo; + NMClient *client; + + NMSecretAgentOld *agent; + NMDevice *device; + NMConnection *connection; + + GMainLoop *loop; + guint timeout_id; + + char *ifname; + char *con_id; + + int secrets_requested; +} TestSecretAgentData; + +static gboolean +timeout_assert (gpointer user_data) +{ + g_assert_not_reached (); +} + +static void +connection_added_cb (GObject *s, + GAsyncResult *result, + gpointer user_data) +{ + TestSecretAgentData *sadata = user_data; + NMRemoteConnection *connection; + GError *error = NULL; + + connection = nm_client_add_connection_finish (sadata->client, result, &error); + + g_assert_no_error (error); + g_assert_cmpstr (nm_connection_get_id (NM_CONNECTION (connection)), ==, sadata->con_id); + + sadata->connection = NM_CONNECTION (connection); + g_main_loop_quit (sadata->loop); +} + +static void +register_cb (GObject *object, GAsyncResult *result, gpointer user_data) +{ + TestSecretAgentData *sadata = user_data; + GError *error = NULL; + + nm_secret_agent_old_register_finish (sadata->agent, result, &error); + g_assert_no_error (error); + g_assert (nm_secret_agent_old_get_registered (sadata->agent)); + + g_main_loop_quit (sadata->loop); +} + +#define TEST_CON_ID_PREFIX "test-secret-agent" + +static void +test_setup (TestSecretAgentData *sadata, gconstpointer test_data) +{ + static int counter = 0; + const char *agent_notes = test_data; + NMConnection *connection; + NMSettingConnection *s_con; + NMSettingWireless *s_wireless; + GBytes *ssid; + NMSetting *s_wsec; + GError *error = NULL; + + sadata->sinfo = nm_test_service_init (); + sadata->client = nm_client_new (NULL, &error); + g_assert_no_error (error); + + sadata->loop = g_main_loop_new (NULL, FALSE); + sadata->timeout_id = g_timeout_add_seconds (5, timeout_assert, NULL); + + sadata->ifname = g_strdup_printf ("wlan%d", counter); + sadata->con_id = g_strdup_printf ("%s-%d", TEST_CON_ID_PREFIX, counter); + counter++; + + /* Create the device */ + sadata->device = nm_test_service_add_device (sadata->sinfo, sadata->client, + "AddWifiDevice", sadata->ifname); + + /* Create the connection */ + connection = nmtst_create_minimal_connection (sadata->con_id, NULL, NM_SETTING_WIRELESS_SETTING_NAME, &s_con); + g_object_set (s_con, + NM_SETTING_CONNECTION_INTERFACE_NAME, sadata->ifname, + NULL); + + s_wireless = nm_connection_get_setting_wireless (connection); + ssid = g_bytes_new ("foo", 3); + g_object_set (s_wireless, + NM_SETTING_WIRELESS_SSID, ssid, + NULL); + g_bytes_unref (ssid); + + s_wsec = g_object_new (NM_TYPE_SETTING_WIRELESS_SECURITY, + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", + NULL); + nm_connection_add_setting (connection, s_wsec); + + nm_client_add_connection_async (sadata->client, + connection, + TRUE, + NULL, + connection_added_cb, + sadata); + g_object_unref (connection); + + g_main_loop_run (sadata->loop); + g_assert (sadata->connection); + + if (agent_notes) { + sadata->agent = test_secret_agent_new (); + + if (!strcmp (agent_notes, "sync")) { + nm_secret_agent_old_register (sadata->agent, NULL, &error); + g_assert_no_error (error); + g_assert (nm_secret_agent_old_get_registered (sadata->agent)); + } else { + nm_secret_agent_old_register_async (sadata->agent, NULL, + register_cb, sadata); + g_main_loop_run (sadata->loop); + } + } +} + +static void +test_cleanup (TestSecretAgentData *sadata, gconstpointer test_data) +{ + GVariant *ret; + GError *error = NULL; + + if (sadata->agent) { + if (nm_secret_agent_old_get_registered (sadata->agent)) { + nm_secret_agent_old_unregister (sadata->agent, NULL, &error); + g_assert_no_error (error); + } + g_object_unref (sadata->agent); + } + + ret = g_dbus_proxy_call_sync (sadata->sinfo->proxy, + "RemoveDevice", + g_variant_new ("(s)", nm_object_get_path (NM_OBJECT (sadata->device))), + G_DBUS_CALL_FLAGS_NO_AUTO_START, + 3000, + NULL, + &error); + g_assert_no_error (error); + g_variant_unref (ret); + + g_object_unref (sadata->connection); + g_object_unref (sadata->client); + + nm_test_service_cleanup (sadata->sinfo); + + g_source_remove (sadata->timeout_id); + g_main_loop_unref (sadata->loop); + + g_free (sadata->ifname); + g_free (sadata->con_id); +} + +/*******************************************************************/ + +static void +connection_activated_none_cb (GObject *c, + GAsyncResult *result, + gpointer user_data) +{ + TestSecretAgentData *sadata = user_data; + NMActiveConnection *ac; + GError *error = NULL; + + ac = nm_client_activate_connection_finish (sadata->client, result, &error); + g_assert_error (error, NM_AGENT_MANAGER_ERROR, NM_AGENT_MANAGER_ERROR_NO_SECRETS); + + g_main_loop_quit (sadata->loop); +} + +static void +test_secret_agent_none (TestSecretAgentData *sadata, gconstpointer test_data) +{ + nm_client_activate_connection_async (sadata->client, + sadata->connection, + sadata->device, + NULL, + NULL, + connection_activated_none_cb, + sadata); + g_main_loop_run (sadata->loop); +} + +/*******************************************************************/ + +static char * +secrets_requested_no_secrets_cb (TestSecretAgent *agent, + NMConnection *connection, + const char *connection_path, + const char *setting_name, + const char *secret_name, + gpointer user_data) +{ + TestSecretAgentData *sadata = user_data; + + g_assert_cmpstr (connection_path, ==, nm_connection_get_path (sadata->connection)); + sadata->secrets_requested++; + + return NULL; +} + +static void +connection_activated_no_secrets_cb (GObject *c, + GAsyncResult *result, + gpointer user_data) +{ + TestSecretAgentData *sadata = user_data; + NMActiveConnection *ac; + GError *error = NULL; + + ac = nm_client_activate_connection_finish (sadata->client, result, &error); + g_assert_error (error, NM_AGENT_MANAGER_ERROR, NM_AGENT_MANAGER_ERROR_NO_SECRETS); + g_main_loop_quit (sadata->loop); +} + +static void +test_secret_agent_no_secrets (TestSecretAgentData *sadata, gconstpointer test_data) +{ + g_signal_connect (sadata->agent, "secret-requested", + G_CALLBACK (secrets_requested_no_secrets_cb), + sadata); + + nm_client_activate_connection_async (sadata->client, + sadata->connection, + sadata->device, + NULL, + NULL, + connection_activated_no_secrets_cb, + sadata); + g_main_loop_run (sadata->loop); + + g_assert_cmpint (sadata->secrets_requested, ==, 1); +} + +/*******************************************************************/ + +static void +connection_activated_cancel_cb (GObject *c, + GAsyncResult *result, + gpointer user_data) +{ + TestSecretAgentData *sadata = user_data; + NMActiveConnection *ac; + GError *error = NULL; + + ac = nm_client_activate_connection_finish (sadata->client, result, &error); + g_assert_error (error, NM_AGENT_MANAGER_ERROR, NM_AGENT_MANAGER_ERROR_USER_CANCELED); + g_main_loop_quit (sadata->loop); +} + +static char * +secrets_requested_cancel_cb (TestSecretAgent *agent, + NMConnection *connection, + const char *connection_path, + const char *setting_name, + const char *secret_name, + gpointer user_data) +{ + TestSecretAgentData *sadata = user_data; + + g_assert_cmpstr (connection_path, ==, nm_connection_get_path (sadata->connection)); + sadata->secrets_requested++; + + return g_strdup ("CANCEL"); +} + +static void +test_secret_agent_cancel (TestSecretAgentData *sadata, gconstpointer test_data) +{ + g_signal_connect (sadata->agent, "secret-requested", + G_CALLBACK (secrets_requested_cancel_cb), + sadata); + + nm_client_activate_connection_async (sadata->client, + sadata->connection, + sadata->device, + NULL, + NULL, + connection_activated_cancel_cb, + sadata); + g_main_loop_run (sadata->loop); + + g_assert_cmpint (sadata->secrets_requested, ==, 1); +} + +/*******************************************************************/ + +static void +connection_activated_good_cb (GObject *c, + GAsyncResult *result, + gpointer user_data) +{ + TestSecretAgentData *sadata = user_data; + NMActiveConnection *ac; + GError *error = NULL; + + ac = nm_client_activate_connection_finish (sadata->client, result, &error); + g_assert_no_error (error); + + g_object_unref (ac); + + g_main_loop_quit (sadata->loop); +} + +static char * +secrets_requested_good_cb (TestSecretAgent *agent, + NMConnection *connection, + const char *connection_path, + const char *setting_name, + const char *secret_name, + gpointer user_data) +{ + TestSecretAgentData *sadata = user_data; + + g_assert_cmpstr (connection_path, ==, nm_connection_get_path (sadata->connection)); + sadata->secrets_requested++; + + return g_strdup ("password"); +} + +static void +test_secret_agent_good (TestSecretAgentData *sadata, gconstpointer test_data) +{ + g_signal_connect (sadata->agent, "secret-requested", + G_CALLBACK (secrets_requested_good_cb), + sadata); + + nm_client_activate_connection_async (sadata->client, + sadata->connection, + sadata->device, + NULL, + NULL, + connection_activated_good_cb, + sadata); + g_main_loop_run (sadata->loop); + + g_assert_cmpint (sadata->secrets_requested, ==, 1); +} + + +static void +async_init_cb (GObject *object, GAsyncResult *result, gpointer user_data) +{ + GMainLoop *loop = user_data; + GError *error = NULL; + GObject *agent; + + agent = g_async_initable_new_finish (G_ASYNC_INITABLE (object), result, &error); + g_assert_error (error, NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_FAILED); + g_assert (agent == NULL); + g_clear_error (&error); + + g_main_loop_quit (loop); +} + +static void +test_secret_agent_nm_not_running (void) +{ + NMSecretAgentOld *agent; + GMainLoop *loop; + GError *error = NULL; + + agent = g_initable_new (test_secret_agent_get_type (), NULL, &error, + NM_SECRET_AGENT_OLD_IDENTIFIER, "test-secret-agent", + NULL); + g_assert_error (error, NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_FAILED); + g_assert (agent == NULL); + g_clear_error (&error); + + loop = g_main_loop_new (NULL, FALSE); + g_async_initable_new_async (test_secret_agent_get_type (), + G_PRIORITY_DEFAULT, + NULL, async_init_cb, loop, + NM_SECRET_AGENT_OLD_IDENTIFIER, "test-secret-agent", + NULL); + g_main_loop_run (loop); + g_main_loop_unref (loop); +} + + +static void +registered_changed (GObject *object, GParamSpec *pspec, gpointer user_data) +{ + GMainLoop *loop = user_data; + + g_main_loop_quit (loop); +} + +static void +test_secret_agent_auto_register (void) +{ + NMTestServiceInfo *sinfo; + NMSecretAgentOld *agent; + GMainLoop *loop; + GError *error = NULL; + + sinfo = nm_test_service_init (); + loop = g_main_loop_new (NULL, FALSE); + + agent = test_secret_agent_new (); + g_object_set (agent, + NM_SECRET_AGENT_OLD_AUTO_REGISTER, TRUE, + NULL); + g_signal_connect (agent, "notify::" NM_SECRET_AGENT_OLD_REGISTERED, + G_CALLBACK (registered_changed), loop); + + g_assert (!nm_secret_agent_old_get_registered (agent)); + nm_secret_agent_old_register (agent, NULL, &error); + g_assert_no_error (error); + g_assert (nm_secret_agent_old_get_registered (agent)); + + /* Shut down test service */ + nm_test_service_cleanup (sinfo); + g_main_loop_run (loop); + g_assert (!nm_secret_agent_old_get_registered (agent)); + + /* Restart test service */ + sinfo = nm_test_service_init (); + g_main_loop_run (loop); + g_assert (nm_secret_agent_old_get_registered (agent)); + + /* Shut down test service again */ + nm_test_service_cleanup (sinfo); + g_main_loop_run (loop); + g_assert (!nm_secret_agent_old_get_registered (agent)); + + g_object_unref (agent); + g_main_loop_unref (loop); +} + +/*******************************************************************/ + +int +main (int argc, char **argv) +{ + int ret; + + g_setenv ("LIBNM_USE_SESSION_BUS", "1", TRUE); + +#if !GLIB_CHECK_VERSION (2, 35, 0) + g_type_init (); +#endif + + g_test_init (&argc, &argv, NULL); + + g_test_add ("/libnm/secret-agent/none", TestSecretAgentData, NULL, + test_setup, test_secret_agent_none, test_cleanup); + g_test_add ("/libnm/secret-agent/no-secrets", TestSecretAgentData, "sync", + test_setup, test_secret_agent_no_secrets, test_cleanup); + g_test_add ("/libnm/secret-agent/cancel", TestSecretAgentData, "async", + test_setup, test_secret_agent_cancel, test_cleanup); + g_test_add ("/libnm/secret-agent/good", TestSecretAgentData, "async", + test_setup, test_secret_agent_good, test_cleanup); + g_test_add_func ("/libnm/secret-agent/nm-not-running", test_secret_agent_nm_not_running); + g_test_add_func ("/libnm/secret-agent/auto-register", test_secret_agent_auto_register); + + ret = g_test_run (); + + return ret; +} + |