From 33491bc4279481db8ae47213e34a6d695a0e8830 Mon Sep 17 00:00:00 2001 From: Michael Biebl Date: Sun, 6 Jul 2014 02:16:10 +0200 Subject: Imported Upstream version 0.9.10.0 --- src/vpn-manager/Makefile.am | 49 -- src/vpn-manager/Makefile.in | 784 -------------------- src/vpn-manager/nm-vpn-connection.c | 1383 +++++++++++++++++++++++------------ src/vpn-manager/nm-vpn-connection.h | 15 +- src/vpn-manager/nm-vpn-manager.c | 202 ++--- src/vpn-manager/nm-vpn-manager.h | 10 +- src/vpn-manager/nm-vpn-service.c | 390 ++++------ src/vpn-manager/nm-vpn-service.h | 18 +- 8 files changed, 1148 insertions(+), 1703 deletions(-) delete mode 100644 src/vpn-manager/Makefile.am delete mode 100644 src/vpn-manager/Makefile.in (limited to 'src/vpn-manager') diff --git a/src/vpn-manager/Makefile.am b/src/vpn-manager/Makefile.am deleted file mode 100644 index 94809ddd..00000000 --- a/src/vpn-manager/Makefile.am +++ /dev/null @@ -1,49 +0,0 @@ -noinst_LTLIBRARIES = libvpn-manager.la - -libvpn_manager_la_SOURCES = \ - nm-vpn-manager.c \ - nm-vpn-manager.h \ - nm-vpn-service.c \ - nm-vpn-service.h \ - nm-vpn-connection.c \ - nm-vpn-connection.h - -libvpn_manager_la_CPPFLAGS = \ - -I${top_srcdir} \ - -I${top_builddir}/include \ - -I${top_srcdir}/include \ - -I${top_builddir}/libnm-util \ - -I${top_srcdir}/libnm-util \ - -I${top_builddir}/src/generated \ - -I${top_srcdir}/src/generated \ - -I${top_srcdir}/src/logging \ - -I${top_srcdir}/src/posix-signals \ - -I${top_srcdir}/src \ - -I${top_srcdir}/src/dns-manager \ - $(LIBNL_CFLAGS) \ - $(DBUS_CFLAGS) \ - $(GLIB_CFLAGS) \ - -DVPN_NAME_FILES_DIR=\""$(sysconfdir)/NetworkManager/VPN"\" - -libvpn_manager_la_LIBADD = \ - $(top_builddir)/src/generated/libnm-generated.la \ - $(top_builddir)/src/logging/libnm-logging.la \ - $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ - $(top_builddir)/libnm-util/libnm-util.la \ - $(LIBNL_LIBS) \ - $(DBUS_LIBS) \ - $(GLIB_LIBS) - -nm-vpn-connection-glue.h: $(top_srcdir)/introspection/nm-vpn-connection.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_vpn_connection --mode=glib-server --output=$@ $< - -nm-vpn-plugin-bindings.h: $(top_srcdir)/introspection/nm-vpn-plugin.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_vpn_plugin --mode=glib-client --output=$@ $< - - -BUILT_SOURCES = \ - nm-vpn-connection-glue.h \ - nm-vpn-plugin-bindings.h - -CLEANFILES = $(BUILT_SOURCES) - diff --git a/src/vpn-manager/Makefile.in b/src/vpn-manager/Makefile.in deleted file mode 100644 index 94e33078..00000000 --- a/src/vpn-manager/Makefile.in +++ /dev/null @@ -1,784 +0,0 @@ -# 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@ -subdir = src/vpn-manager -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/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 = -LTLIBRARIES = $(noinst_LTLIBRARIES) -am__DEPENDENCIES_1 = -libvpn_manager_la_DEPENDENCIES = \ - $(top_builddir)/src/generated/libnm-generated.la \ - $(top_builddir)/src/logging/libnm-logging.la \ - $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ - $(top_builddir)/libnm-util/libnm-util.la $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) -am_libvpn_manager_la_OBJECTS = libvpn_manager_la-nm-vpn-manager.lo \ - libvpn_manager_la-nm-vpn-service.lo \ - libvpn_manager_la-nm-vpn-connection.lo -libvpn_manager_la_OBJECTS = $(am_libvpn_manager_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 = -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 = $(libvpn_manager_la_SOURCES) -DIST_SOURCES = $(libvpn_manager_la_SOURCES) -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 -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@ -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_LIBS = @DBUS_LIBS@ -DBUS_SYS_DIR = @DBUS_SYS_DIR@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -DHCLIENT_PATH = @DHCLIENT_PATH@ -DHCPCD_PATH = @DHCPCD_PATH@ -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_CHECK_PATH = @GTKDOC_CHECK_PATH@ -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@ -LIBNL_CFLAGS = @LIBNL_CFLAGS@ -LIBNL_LIBS = @LIBNL_LIBS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ -LIBSOUP_LIBS = @LIBSOUP_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@ -NM = @NM@ -NMEDIT = @NMEDIT@ -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@ -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_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ -QT_CFLAGS = @QT_CFLAGS@ -QT_LIBS = @QT_LIBS@ -RANLIB = @RANLIB@ -SED = @SED@ -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_BASE_DIR = @UDEV_BASE_DIR@ -USE_NLS = @USE_NLS@ -UUID_CFLAGS = @UUID_CFLAGS@ -UUID_LIBS = @UUID_LIBS@ -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@ -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@ -noinst_LTLIBRARIES = libvpn-manager.la -libvpn_manager_la_SOURCES = \ - nm-vpn-manager.c \ - nm-vpn-manager.h \ - nm-vpn-service.c \ - nm-vpn-service.h \ - nm-vpn-connection.c \ - nm-vpn-connection.h - -libvpn_manager_la_CPPFLAGS = \ - -I${top_srcdir} \ - -I${top_builddir}/include \ - -I${top_srcdir}/include \ - -I${top_builddir}/libnm-util \ - -I${top_srcdir}/libnm-util \ - -I${top_builddir}/src/generated \ - -I${top_srcdir}/src/generated \ - -I${top_srcdir}/src/logging \ - -I${top_srcdir}/src/posix-signals \ - -I${top_srcdir}/src \ - -I${top_srcdir}/src/dns-manager \ - $(LIBNL_CFLAGS) \ - $(DBUS_CFLAGS) \ - $(GLIB_CFLAGS) \ - -DVPN_NAME_FILES_DIR=\""$(sysconfdir)/NetworkManager/VPN"\" - -libvpn_manager_la_LIBADD = \ - $(top_builddir)/src/generated/libnm-generated.la \ - $(top_builddir)/src/logging/libnm-logging.la \ - $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ - $(top_builddir)/libnm-util/libnm-util.la \ - $(LIBNL_LIBS) \ - $(DBUS_LIBS) \ - $(GLIB_LIBS) - -BUILT_SOURCES = \ - nm-vpn-connection-glue.h \ - nm-vpn-plugin-bindings.h - -CLEANFILES = $(BUILT_SOURCES) -all: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) all-am - -.SUFFIXES: -.SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ - && { if test -f $@; then exit 0; else break; fi; }; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/vpn-manager/Makefile'; \ - $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu src/vpn-manager/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(am__aclocal_m4_deps): - -clean-noinstLTLIBRARIES: - -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) - @list='$(noinst_LTLIBRARIES)'; \ - 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}; \ - } - -libvpn-manager.la: $(libvpn_manager_la_OBJECTS) $(libvpn_manager_la_DEPENDENCIES) $(EXTRA_libvpn_manager_la_DEPENDENCIES) - $(AM_V_CCLD)$(LINK) $(libvpn_manager_la_OBJECTS) $(libvpn_manager_la_LIBADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvpn_manager_la-nm-vpn-connection.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvpn_manager_la-nm-vpn-manager.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvpn_manager_la-nm-vpn-service.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 $@ $< - -libvpn_manager_la-nm-vpn-manager.lo: nm-vpn-manager.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvpn_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libvpn_manager_la-nm-vpn-manager.lo -MD -MP -MF $(DEPDIR)/libvpn_manager_la-nm-vpn-manager.Tpo -c -o libvpn_manager_la-nm-vpn-manager.lo `test -f 'nm-vpn-manager.c' || echo '$(srcdir)/'`nm-vpn-manager.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libvpn_manager_la-nm-vpn-manager.Tpo $(DEPDIR)/libvpn_manager_la-nm-vpn-manager.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-vpn-manager.c' object='libvpn_manager_la-nm-vpn-manager.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvpn_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libvpn_manager_la-nm-vpn-manager.lo `test -f 'nm-vpn-manager.c' || echo '$(srcdir)/'`nm-vpn-manager.c - -libvpn_manager_la-nm-vpn-service.lo: nm-vpn-service.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvpn_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libvpn_manager_la-nm-vpn-service.lo -MD -MP -MF $(DEPDIR)/libvpn_manager_la-nm-vpn-service.Tpo -c -o libvpn_manager_la-nm-vpn-service.lo `test -f 'nm-vpn-service.c' || echo '$(srcdir)/'`nm-vpn-service.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libvpn_manager_la-nm-vpn-service.Tpo $(DEPDIR)/libvpn_manager_la-nm-vpn-service.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-vpn-service.c' object='libvpn_manager_la-nm-vpn-service.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvpn_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libvpn_manager_la-nm-vpn-service.lo `test -f 'nm-vpn-service.c' || echo '$(srcdir)/'`nm-vpn-service.c - -libvpn_manager_la-nm-vpn-connection.lo: nm-vpn-connection.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvpn_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libvpn_manager_la-nm-vpn-connection.lo -MD -MP -MF $(DEPDIR)/libvpn_manager_la-nm-vpn-connection.Tpo -c -o libvpn_manager_la-nm-vpn-connection.lo `test -f 'nm-vpn-connection.c' || echo '$(srcdir)/'`nm-vpn-connection.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libvpn_manager_la-nm-vpn-connection.Tpo $(DEPDIR)/libvpn_manager_la-nm-vpn-connection.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nm-vpn-connection.c' object='libvpn_manager_la-nm-vpn-connection.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvpn_manager_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libvpn_manager_la-nm-vpn-connection.lo `test -f 'nm-vpn-connection.c' || echo '$(srcdir)/'`nm-vpn-connection.c - -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 - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d "$(distdir)/$$file"; then \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ - find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ - fi; \ - cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ - else \ - test -f "$(distdir)/$$file" \ - || cp -p $$d/$$file "$(distdir)/$$file" \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) check-am -all-am: Makefile $(LTLIBRARIES) -installdirs: -install: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - 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) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." - -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) -clean: clean-am - -clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ - mostlyclean-am - -distclean: distclean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -html-am: - -info: info-am - -info-am: - -install-data-am: - -install-dvi: install-dvi-am - -install-dvi-am: - -install-exec-am: - -install-html: install-html-am - -install-html-am: - -install-info: install-info-am - -install-info-am: - -install-man: - -install-pdf: install-pdf-am - -install-pdf-am: - -install-ps: install-ps-am - -install-ps-am: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: - -.MAKE: all check install install-am install-strip - -.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ - clean-libtool clean-noinstLTLIBRARIES 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 - - -nm-vpn-connection-glue.h: $(top_srcdir)/introspection/nm-vpn-connection.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_vpn_connection --mode=glib-server --output=$@ $< - -nm-vpn-plugin-bindings.h: $(top_srcdir)/introspection/nm-vpn-plugin.xml - $(AM_V_GEN) dbus-binding-tool --prefix=nm_vpn_plugin --mode=glib-client --output=$@ $< - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c index f2e31a8d..d66dcfdb 100644 --- a/src/vpn-manager/nm-vpn-connection.c +++ b/src/vpn-manager/nm-vpn-connection.c @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2005 - 2012 Red Hat, Inc. + * Copyright (C) 2005 - 2013 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ @@ -34,20 +34,16 @@ #include "nm-setting-vpn.h" #include "nm-setting-ip4-config.h" #include "nm-dbus-manager.h" -#include "nm-system.h" +#include "nm-platform.h" #include "nm-logging.h" #include "nm-utils.h" -#include "nm-vpn-plugin-bindings.h" -#include "nm-marshal.h" #include "nm-active-connection.h" -#include "nm-properties-changed-signal.h" #include "nm-dbus-glib-types.h" #include "NetworkManagerUtils.h" -#include "nm-netlink-monitor.h" -#include "nm-netlink-utils.h" #include "nm-glib-compat.h" #include "settings/nm-settings-connection.h" #include "nm-dispatcher.h" +#include "nm-agent-manager.h" #include "nm-vpn-connection-glue.h" @@ -60,28 +56,41 @@ typedef enum { SECRETS_REQ_EXISTING = 1, /* New secrets required; ask an agent */ SECRETS_REQ_NEW = 2, + /* Plugin requests secrets interactively */ + SECRETS_REQ_INTERACTIVE = 3, /* Placeholder for bounds checking */ SECRETS_REQ_LAST } SecretsReq; -typedef struct { - gboolean disposed; +/* Internal VPN states, private to NMVPNConnection */ +typedef enum { + STATE_UNKNOWN = 0, + STATE_WAITING, + STATE_PREPARE, + STATE_NEED_AUTH, + STATE_CONNECT, + STATE_IP_CONFIG_GET, + STATE_PRE_UP, + STATE_ACTIVATED, + STATE_DEACTIVATING, + STATE_DISCONNECTED, + STATE_FAILED, +} VpnState; +typedef struct { NMConnection *connection; guint32 secrets_id; SecretsReq secrets_idx; char *username; - NMDevice *parent_dev; - gulong device_monitor; - gulong device_ip4; - gulong device_ip6; - - NMVPNConnectionState vpn_state; + VpnState vpn_state; + guint dispatcher_id; NMVPNConnectionStateReason failure_reason; + DBusGProxy *proxy; - guint ipconfig_timeout; + GHashTable *connect_hash; + guint connect_timeout; gboolean has_ip4; NMIP4Config *ip4_config; guint32 ip4_internal_gw; @@ -94,14 +103,11 @@ typedef struct { int ip_ifindex; char *banner; guint32 mtu; - - struct rtnl_route *gw_route; } NMVPNConnectionPrivate; #define NM_VPN_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_VPN_CONNECTION, NMVPNConnectionPrivate)) enum { - PROPERTIES_CHANGED, VPN_STATE_CHANGED, INTERNAL_STATE_CHANGED, @@ -114,27 +120,81 @@ enum { PROP_0, PROP_VPN_STATE, PROP_BANNER, + PROP_IP4_CONFIG, + PROP_IP6_CONFIG, PROP_MASTER = 2000, LAST_PROP }; -static void get_secrets (NMVPNConnection *self, SecretsReq secrets_idx); +static void get_secrets (NMVPNConnection *self, + SecretsReq secrets_idx, + const char **hints); + +static void plugin_interactive_secrets_required (DBusGProxy *proxy, + const char *message, + const char **secrets, + gpointer user_data); + +static void _set_vpn_state (NMVPNConnection *connection, + VpnState vpn_state, + NMVPNConnectionStateReason reason, + gboolean quitting); + +/*********************************************************************/ + +static NMVPNConnectionState +_state_to_nm_vpn_state (VpnState state) +{ + switch (state) { + case STATE_WAITING: + case STATE_PREPARE: + return NM_VPN_CONNECTION_STATE_PREPARE; + case STATE_NEED_AUTH: + return NM_VPN_CONNECTION_STATE_NEED_AUTH; + case STATE_CONNECT: + return NM_VPN_CONNECTION_STATE_CONNECT; + case STATE_IP_CONFIG_GET: + case STATE_PRE_UP: + return NM_VPN_CONNECTION_STATE_IP_CONFIG_GET; + case STATE_ACTIVATED: + return NM_VPN_CONNECTION_STATE_ACTIVATED; + case STATE_DEACTIVATING: { + /* Map DEACTIVATING to ACTIVATED to preserve external API behavior, + * since our API has no DEACTIVATING state of its own. Since this can + * take some time, and the VPN isn't actually disconnected until it + * hits the DISCONNECTED state, to clients it should still appear + * connected. + */ + return NM_VPN_CONNECTION_STATE_ACTIVATED; + } + case STATE_DISCONNECTED: + return NM_VPN_CONNECTION_STATE_DISCONNECTED; + case STATE_FAILED: + return NM_VPN_CONNECTION_STATE_FAILED; + default: + return STATE_UNKNOWN; + } +} static NMActiveConnectionState -ac_state_from_vpn_state (NMVPNConnectionState vpn_state) +_state_to_ac_state (VpnState vpn_state) { /* Set the NMActiveConnection state based on VPN state */ switch (vpn_state) { - case NM_VPN_CONNECTION_STATE_PREPARE: - case NM_VPN_CONNECTION_STATE_NEED_AUTH: - case NM_VPN_CONNECTION_STATE_CONNECT: - case NM_VPN_CONNECTION_STATE_IP_CONFIG_GET: + case STATE_WAITING: + case STATE_PREPARE: + case STATE_NEED_AUTH: + case STATE_CONNECT: + case STATE_IP_CONFIG_GET: + case STATE_PRE_UP: return NM_ACTIVE_CONNECTION_STATE_ACTIVATING; - case NM_VPN_CONNECTION_STATE_ACTIVATED: + case STATE_ACTIVATED: return NM_ACTIVE_CONNECTION_STATE_ACTIVATED; - case NM_VPN_CONNECTION_STATE_FAILED: - case NM_VPN_CONNECTION_STATE_DISCONNECTED: + case STATE_DEACTIVATING: + return NM_ACTIVE_CONNECTION_STATE_DEACTIVATING; + case STATE_DISCONNECTED: + case STATE_FAILED: return NM_ACTIVE_CONNECTION_STATE_DEACTIVATED; default: break; @@ -149,10 +209,12 @@ call_plugin_disconnect (NMVPNConnection *self) GError *error = NULL; if (priv->proxy) { - org_freedesktop_NetworkManager_VPN_Plugin_disconnect (priv->proxy, &error); - if (error) + if (!dbus_g_proxy_call (priv->proxy, "Disconnect", &error, + G_TYPE_INVALID, + G_TYPE_INVALID)) { nm_log_warn (LOGD_VPN, "error disconnecting VPN: %s", error->message); - g_clear_error (&error); + g_error_free (error); + } g_object_unref (priv->proxy); priv->proxy = NULL; @@ -160,21 +222,18 @@ call_plugin_disconnect (NMVPNConnection *self) } static void -vpn_cleanup (NMVPNConnection *connection) +vpn_cleanup (NMVPNConnection *connection, NMDevice *parent_dev) { NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); if (priv->ip_ifindex) { - nm_system_iface_set_up (priv->ip_ifindex, FALSE, NULL); - nm_system_iface_flush_routes (priv->ip_ifindex, AF_UNSPEC); - nm_system_iface_flush_addresses (priv->ip_ifindex, AF_UNSPEC); + nm_platform_link_set_down (priv->ip_ifindex); + nm_platform_route_flush (priv->ip_ifindex); + nm_platform_address_flush (priv->ip_ifindex); } - if (priv->gw_route) { - nm_netlink_route_delete (priv->gw_route); - rtnl_route_put (priv->gw_route); - priv->gw_route = NULL; - } + nm_device_set_vpn4_config (parent_dev, NULL); + nm_device_set_vpn6_config (parent_dev, NULL); g_free (priv->banner); priv->banner = NULL; @@ -191,12 +250,46 @@ vpn_cleanup (NMVPNConnection *connection) } static void -nm_vpn_connection_set_vpn_state (NMVPNConnection *connection, - NMVPNConnectionState vpn_state, - NMVPNConnectionStateReason reason) +dispatcher_pre_down_done (guint call_id, gpointer user_data) +{ + NMVPNConnection *self = NM_VPN_CONNECTION (user_data); + NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self); + + priv->dispatcher_id = 0; + _set_vpn_state (self, STATE_DISCONNECTED, NM_VPN_CONNECTION_STATE_REASON_NONE, FALSE); +} + +static void +dispatcher_pre_up_done (guint call_id, gpointer user_data) +{ + NMVPNConnection *self = NM_VPN_CONNECTION (user_data); + NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self); + + priv->dispatcher_id = 0; + _set_vpn_state (self, STATE_ACTIVATED, NM_VPN_CONNECTION_STATE_REASON_NONE, FALSE); +} + +static void +dispatcher_cleanup (NMVPNConnection *self) +{ + NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self); + + if (priv->dispatcher_id) { + nm_dispatcher_call_cancel (priv->dispatcher_id); + priv->dispatcher_id = 0; + } +} + +static void +_set_vpn_state (NMVPNConnection *connection, + VpnState vpn_state, + NMVPNConnectionStateReason reason, + gboolean quitting) { NMVPNConnectionPrivate *priv; - NMVPNConnectionState old_vpn_state; + VpnState old_vpn_state; + NMVPNConnectionState new_external_state, old_external_state; + NMDevice *parent_dev = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (connection)); g_return_if_fail (NM_IS_VPN_CONNECTION (connection)); @@ -208,16 +301,23 @@ nm_vpn_connection_set_vpn_state (NMVPNConnection *connection, old_vpn_state = priv->vpn_state; priv->vpn_state = vpn_state; + /* The device gets destroyed by active connection when it enters + * the deactivated state, so we need to ref it for usage below. + */ + if (parent_dev) + g_object_ref (parent_dev); + /* Update active connection base class state */ nm_active_connection_set_state (NM_ACTIVE_CONNECTION (connection), - ac_state_from_vpn_state (vpn_state)); + _state_to_ac_state (vpn_state)); /* Clear any in-progress secrets request */ if (priv->secrets_id) { nm_settings_connection_cancel_secrets (NM_SETTINGS_CONNECTION (priv->connection), priv->secrets_id); priv->secrets_id = 0; } - priv->secrets_idx = SECRETS_REQ_SYSTEM; + + dispatcher_cleanup (connection); /* The connection gets destroyed by the VPN manager when it enters the * disconnected/failed state, but we need to keep it around for a bit @@ -225,144 +325,254 @@ nm_vpn_connection_set_vpn_state (NMVPNConnection *connection, */ g_object_ref (connection); - g_signal_emit (connection, signals[VPN_STATE_CHANGED], 0, vpn_state, reason); - g_signal_emit (connection, signals[INTERNAL_STATE_CHANGED], 0, vpn_state, old_vpn_state, reason); - g_object_notify (G_OBJECT (connection), NM_VPN_CONNECTION_VPN_STATE); + old_external_state = _state_to_nm_vpn_state (old_vpn_state); + new_external_state = _state_to_nm_vpn_state (priv->vpn_state); + if (new_external_state != old_external_state) { + g_signal_emit (connection, signals[VPN_STATE_CHANGED], 0, new_external_state, reason); + g_signal_emit (connection, signals[INTERNAL_STATE_CHANGED], 0, + new_external_state, + old_external_state, + reason); + g_object_notify (G_OBJECT (connection), NM_VPN_CONNECTION_VPN_STATE); + } switch (vpn_state) { - case NM_VPN_CONNECTION_STATE_NEED_AUTH: - /* Kick off the secrets requests; first we get existing system secrets - * and ask the plugin if these are sufficient, next we get all existing - * secrets from system and from user agents and ask the plugin again, - * and last we ask the user for new secrets if required. + case STATE_NEED_AUTH: + /* Do nothing; not part of 'default' because we don't want to touch + * priv->secrets_req as NEED_AUTH is re-entered during interactive + * secrets. */ - get_secrets (connection, SECRETS_REQ_SYSTEM); break; - case NM_VPN_CONNECTION_STATE_ACTIVATED: + case STATE_PRE_UP: + if (!nm_dispatcher_call_vpn (DISPATCHER_ACTION_VPN_PRE_UP, + priv->connection, + parent_dev, + priv->ip_iface, + priv->ip4_config, + priv->ip6_config, + dispatcher_pre_up_done, + connection, + &priv->dispatcher_id)) { + /* Just proceed on errors */ + dispatcher_pre_up_done (0, connection); + } + break; + case STATE_ACTIVATED: /* Secrets no longer needed now that we're connected */ nm_connection_clear_secrets (priv->connection); /* Let dispatcher scripts know we're up and running */ nm_dispatcher_call_vpn (DISPATCHER_ACTION_VPN_UP, priv->connection, - priv->parent_dev, + parent_dev, priv->ip_iface, priv->ip4_config, priv->ip6_config, NULL, + NULL, NULL); break; - case NM_VPN_CONNECTION_STATE_FAILED: - case NM_VPN_CONNECTION_STATE_DISCONNECTED: - if (old_vpn_state == NM_VPN_CONNECTION_STATE_ACTIVATED) { + case STATE_DEACTIVATING: + if (quitting) { + nm_dispatcher_call_vpn_sync (DISPATCHER_ACTION_VPN_PRE_DOWN, + priv->connection, + parent_dev, + priv->ip_iface, + priv->ip4_config, + priv->ip6_config); + } else { + if (!nm_dispatcher_call_vpn (DISPATCHER_ACTION_VPN_PRE_DOWN, + priv->connection, + parent_dev, + priv->ip_iface, + priv->ip4_config, + priv->ip6_config, + dispatcher_pre_down_done, + connection, + &priv->dispatcher_id)) { + /* Just proceed on errors */ + dispatcher_pre_down_done (0, connection); + } + } + break; + case STATE_FAILED: + case STATE_DISCONNECTED: + if ( old_vpn_state >= STATE_ACTIVATED + && old_vpn_state <= STATE_DEACTIVATING) { /* Let dispatcher scripts know we're about to go down */ - nm_dispatcher_call_vpn (DISPATCHER_ACTION_VPN_DOWN, - priv->connection, - priv->parent_dev, - priv->ip_iface, - NULL, - NULL, - NULL, - NULL); + if (quitting) { + nm_dispatcher_call_vpn_sync (DISPATCHER_ACTION_VPN_DOWN, + priv->connection, + parent_dev, + priv->ip_iface, + NULL, + NULL); + } else { + nm_dispatcher_call_vpn (DISPATCHER_ACTION_VPN_DOWN, + priv->connection, + parent_dev, + priv->ip_iface, + NULL, + NULL, + NULL, + NULL, + NULL); + } } /* Tear down and clean up the connection */ call_plugin_disconnect (connection); - vpn_cleanup (connection); - break; + vpn_cleanup (connection, parent_dev); + /* Fall through */ default: + priv->secrets_idx = SECRETS_REQ_SYSTEM; break; } g_object_unref (connection); + if (parent_dev) + g_object_unref (parent_dev); } static void -device_state_changed (NMDevice *device, +device_state_changed (NMActiveConnection *active, + NMDevice *device, NMDeviceState new_state, - NMDeviceState old_state, - NMDeviceStateReason reason, - gpointer user_data) + NMDeviceState old_state) { - NMVPNConnection *connection = NM_VPN_CONNECTION (user_data); - if (new_state <= NM_DEVICE_STATE_DISCONNECTED) { - nm_vpn_connection_set_vpn_state (connection, - NM_VPN_CONNECTION_STATE_DISCONNECTED, - NM_VPN_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED); + _set_vpn_state (NM_VPN_CONNECTION (active), + STATE_DISCONNECTED, + NM_VPN_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED, + FALSE); } else if (new_state == NM_DEVICE_STATE_FAILED) { - nm_vpn_connection_set_vpn_state (connection, - NM_VPN_CONNECTION_STATE_FAILED, - NM_VPN_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED); + _set_vpn_state (NM_VPN_CONNECTION (active), + STATE_FAILED, + NM_VPN_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED, + FALSE); } + + /* FIXME: map device DEACTIVATING state to VPN DEACTIVATING state and + * block device deactivation on VPN deactivation. + */ } static void -device_ip4_config_changed (NMDevice *device, - GParamSpec *pspec, - gpointer user_data) +add_ip4_vpn_gateway_route (NMIP4Config *config, NMDevice *parent_device, guint32 vpn_gw) { - NMVPNConnection *vpn = NM_VPN_CONNECTION (user_data); - NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (vpn); + NMIP4Config *parent_config; + guint32 parent_gw; + NMPlatformIP4Route route; + + g_return_if_fail (NM_IS_IP4_CONFIG (config)); + g_return_if_fail (NM_IS_DEVICE (parent_device)); + g_return_if_fail (vpn_gw != 0); - if ( (priv->vpn_state != NM_VPN_CONNECTION_STATE_ACTIVATED) - || !nm_device_get_ip4_config (device)) + /* Set up a route to the VPN gateway's public IP address through the default + * network device if the VPN gateway is on a different subnet. + */ + + parent_config = nm_device_get_ip4_config (parent_device); + g_return_if_fail (parent_config != NULL); + parent_gw = nm_ip4_config_get_gateway (parent_config); + if (!parent_gw) return; - /* Re-add the VPN gateway route */ - if (priv->ip4_external_gw) { - if (priv->gw_route) - rtnl_route_put (priv->gw_route); - priv->gw_route = nm_system_add_ip4_vpn_gateway_route (priv->parent_dev, - priv->ip4_external_gw); - } + memset (&route, 0, sizeof (route)); + route.network = vpn_gw; + route.plen = 32; + route.gateway = parent_gw; + + /* If the VPN gateway is in the same subnet as one of the parent device's + * IP addresses, don't add the host route to it, but a route through the + * parent device. + */ + if (nm_ip4_config_destination_is_direct (parent_config, vpn_gw, 32)) + route.gateway = 0; + + route.source = NM_PLATFORM_SOURCE_VPN; + route.metric = nm_device_get_priority (parent_device); + nm_ip4_config_add_route (config, &route); + + /* Ensure there's a route to the parent device's gateway through the + * parent device, since if the VPN claims the default route and the VPN + * routes include a subnet that matches the parent device's subnet, + * the parent device's gateway would get routed through the VPN and fail. + */ + memset (&route, 0, sizeof (route)); + route.network = parent_gw; + route.plen = 32; + route.source = NM_PLATFORM_SOURCE_VPN; + route.metric = nm_device_get_priority (parent_device); + + nm_ip4_config_add_route (config, &route); } static void -device_ip6_config_changed (NMDevice *device, - GParamSpec *pspec, - gpointer user_data) +add_ip6_vpn_gateway_route (NMIP6Config *config, + NMDevice *parent_device, + const struct in6_addr *vpn_gw) { - NMVPNConnection *vpn = NM_VPN_CONNECTION (user_data); - NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (vpn); - - if ( (priv->vpn_state != NM_VPN_CONNECTION_STATE_ACTIVATED) - || !nm_device_get_ip6_config (device)) + NMIP6Config *parent_config; + const struct in6_addr *parent_gw; + NMPlatformIP6Route route; + + g_return_if_fail (NM_IS_IP6_CONFIG (config)); + g_return_if_fail (NM_IS_DEVICE (parent_device)); + g_return_if_fail (vpn_gw != NULL); + + parent_config = nm_device_get_ip6_config (parent_device); + g_return_if_fail (parent_config != NULL); + parent_gw = nm_ip6_config_get_gateway (parent_config); + if (!parent_gw) return; - /* Re-add the VPN gateway route */ - if (priv->ip6_external_gw) { - if (priv->gw_route) - rtnl_route_put (priv->gw_route); - priv->gw_route = nm_system_add_ip6_vpn_gateway_route (priv->parent_dev, - priv->ip6_external_gw); - } + memset (&route, 0, sizeof (route)); + route.network = *vpn_gw; + route.plen = 128; + route.gateway = *parent_gw; + + /* If the VPN gateway is in the same subnet as one of the parent device's + * IP addresses, don't add the host route to it, but a route through the + * parent device. + */ + if (nm_ip6_config_destination_is_direct (parent_config, vpn_gw, 128)) + route.gateway = in6addr_any; + + route.source = NM_PLATFORM_SOURCE_VPN; + route.metric = nm_device_get_priority (parent_device); + nm_ip6_config_add_route (config, &route); + + /* Ensure there's a route to the parent device's gateway through the + * parent device, since if the VPN claims the default route and the VPN + * routes include a subnet that matches the parent device's subnet, + * the parent device's gateway would get routed through the VPN and fail. + */ + memset (&route, 0, sizeof (route)); + route.network = *parent_gw; + route.plen = 128; + route.source = NM_PLATFORM_SOURCE_VPN; + route.metric = nm_device_get_priority (parent_device); + + nm_ip6_config_add_route (config, &route); } NMVPNConnection * nm_vpn_connection_new (NMConnection *connection, NMDevice *parent_device, const char *specific_object, - gboolean user_requested, - gulong user_uid) + NMAuthSubject *subject) { - NMVPNConnection *self; - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); g_return_val_if_fail (NM_IS_DEVICE (parent_device), NULL); - self = (NMVPNConnection *) g_object_new (NM_TYPE_VPN_CONNECTION, + return (NMVPNConnection *) g_object_new (NM_TYPE_VPN_CONNECTION, NM_ACTIVE_CONNECTION_INT_CONNECTION, connection, NM_ACTIVE_CONNECTION_INT_DEVICE, parent_device, NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT, specific_object, - NM_ACTIVE_CONNECTION_INT_USER_REQUESTED, user_requested, - NM_ACTIVE_CONNECTION_INT_USER_UID, user_uid, + NM_ACTIVE_CONNECTION_INT_SUBJECT, subject, NM_ACTIVE_CONNECTION_VPN, TRUE, NULL); - if (self) - nm_active_connection_export (NM_ACTIVE_CONNECTION (self)); - - return self; } static const char * @@ -375,14 +585,31 @@ nm_vpn_connection_get_service (NMVPNConnection *connection) return nm_setting_vpn_get_service_type (s_vpn); } +static const char * +vpn_plugin_failure_to_string (NMVPNPluginFailure failure) +{ + switch (failure) { + case NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED: + return "login-failed"; + case NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED: + return "connect-failed"; + case NM_VPN_PLUGIN_FAILURE_BAD_IP_CONFIG: + return "bad-ip-config"; + default: + break; + } + return "unknown"; +} + static void plugin_failed (DBusGProxy *proxy, - NMVPNPluginFailure plugin_failure, - gpointer user_data) + NMVPNPluginFailure plugin_failure, + gpointer user_data) { NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (user_data); - nm_log_warn (LOGD_VPN, "VPN plugin failed: %d", plugin_failure); + nm_log_warn (LOGD_VPN, "VPN plugin failed: %s (%d)", + vpn_plugin_failure_to_string (plugin_failure), plugin_failure); switch (plugin_failure) { case NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED: @@ -397,7 +624,7 @@ plugin_failed (DBusGProxy *proxy, } static const char * -vpn_state_to_string (NMVPNServiceState state) +vpn_service_state_to_string (NMVPNServiceState state) { switch (state) { case NM_VPN_SERVICE_STATE_INIT: @@ -418,6 +645,60 @@ vpn_state_to_string (NMVPNServiceState state) return "unknown"; } +static const char *state_table[] = { + [STATE_UNKNOWN] = "unknown", + [STATE_WAITING] = "waiting", + [STATE_PREPARE] = "prepare", + [STATE_NEED_AUTH] = "need-auth", + [STATE_CONNECT] = "connect", + [STATE_IP_CONFIG_GET] = "ip-config-get", + [STATE_PRE_UP] = "pre-up", + [STATE_ACTIVATED] = "activated", + [STATE_DEACTIVATING] = "deactivating", + [STATE_DISCONNECTED] = "disconnected", + [STATE_FAILED] = "failed", +}; + +static const char * +vpn_state_to_string (VpnState state) +{ + if (state >= 0 && state < G_N_ELEMENTS (state_table)) + return state_table[state]; + return "unknown"; +} + +static const char * +vpn_reason_to_string (NMVPNConnectionStateReason reason) +{ + switch (reason) { + case NM_VPN_CONNECTION_STATE_REASON_NONE: + return "none"; + case NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED: + return "user-disconnected"; + case NM_VPN_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED: + return "device-disconnected"; + case NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED: + return "service-stopped"; + case NM_VPN_CONNECTION_STATE_REASON_IP_CONFIG_INVALID: + return "ip-config-invalid"; + case NM_VPN_CONNECTION_STATE_REASON_CONNECT_TIMEOUT: + return "connect-timeout"; + case NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT: + return "service-start-timeout"; + case NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_FAILED: + return "service-start-failed"; + case NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS: + return "no-secrets"; + case NM_VPN_CONNECTION_STATE_REASON_LOGIN_FAILED: + return "login-failed"; + case NM_VPN_CONNECTION_STATE_REASON_CONNECTION_REMOVED: + return "connection-removed"; + default: + break; + } + return "unknown"; +} + static void plugin_state_changed (DBusGProxy *proxy, NMVPNServiceState state, @@ -427,7 +708,7 @@ plugin_state_changed (DBusGProxy *proxy, NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); nm_log_info (LOGD_VPN, "VPN plugin state changed: %s (%d)", - vpn_state_to_string (state), state); + vpn_service_state_to_string (state), state); if (state == NM_VPN_SERVICE_STATE_STOPPED) { /* Clear connection secrets to ensure secrets get requested each time the @@ -435,107 +716,66 @@ plugin_state_changed (DBusGProxy *proxy, */ nm_connection_clear_secrets (priv->connection); - switch (nm_vpn_connection_get_vpn_state (connection)) { - case NM_VPN_CONNECTION_STATE_PREPARE: - case NM_VPN_CONNECTION_STATE_NEED_AUTH: - case NM_VPN_CONNECTION_STATE_CONNECT: - case NM_VPN_CONNECTION_STATE_IP_CONFIG_GET: - case NM_VPN_CONNECTION_STATE_ACTIVATED: - nm_log_info (LOGD_VPN, "VPN plugin state change reason: %d", priv->failure_reason); - nm_vpn_connection_set_vpn_state (connection, - NM_VPN_CONNECTION_STATE_FAILED, - priv->failure_reason); + if ((priv->vpn_state >= STATE_WAITING) && (priv->vpn_state <= STATE_ACTIVATED)) { + nm_log_info (LOGD_VPN, "VPN plugin state change reason: %s (%d)", + vpn_reason_to_string (priv->failure_reason), priv->failure_reason); + _set_vpn_state (connection, STATE_FAILED, priv->failure_reason, FALSE); /* Reset the failure reason */ priv->failure_reason = NM_VPN_CONNECTION_STATE_REASON_UNKNOWN; - break; - default: - break; } } } -static char addr_to_string_buf[INET6_ADDRSTRLEN + 1]; - -static const char * -ip_address_to_string (guint32 numeric) -{ - struct in_addr temp_addr; - - memset (&addr_to_string_buf, '\0', sizeof (addr_to_string_buf)); - temp_addr.s_addr = numeric; - - if (inet_ntop (AF_INET, &temp_addr, addr_to_string_buf, INET_ADDRSTRLEN)) { - return addr_to_string_buf; - } else { - nm_log_warn (LOGD_VPN, "error converting IP4 address 0x%X", - ntohl (temp_addr.s_addr)); - return NULL; - } -} - -static const char * -ip6_address_to_string (const struct in6_addr *addr) -{ - memset (addr_to_string_buf, '\0', sizeof (addr_to_string_buf)); - if (inet_ntop (AF_INET6, addr, addr_to_string_buf, INET6_ADDRSTRLEN)) { - return addr_to_string_buf; - } else { - nm_log_warn (LOGD_VPN, "error converting IP6 address"); - return NULL; - } -} - static void print_vpn_config (NMVPNConnection *connection) { NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); - NMIP4Address *addr; - NMIP6Address *addr6; + const NMPlatformIP4Address *address4; + const NMPlatformIP6Address *address6; char *dns_domain = NULL; guint32 num, i; + char buf[NM_UTILS_INET_ADDRSTRLEN]; if (priv->ip4_external_gw) { nm_log_info (LOGD_VPN, "VPN Gateway: %s", - ip_address_to_string (priv->ip4_external_gw)); + nm_utils_inet4_ntop (priv->ip4_external_gw, NULL)); } else if (priv->ip6_external_gw) { nm_log_info (LOGD_VPN, "VPN Gateway: %s", - ip6_address_to_string (priv->ip6_external_gw)); - } + nm_utils_inet6_ntop (priv->ip6_external_gw, NULL)); + } - nm_log_info (LOGD_VPN, "Tunnel Device: %s", priv->ip_iface); + nm_log_info (LOGD_VPN, "Tunnel Device: %s", priv->ip_iface ? priv->ip_iface : "(none)"); if (priv->ip4_config) { nm_log_info (LOGD_VPN, "IPv4 configuration:"); - addr = nm_ip4_config_get_address (priv->ip4_config, 0); + address4 = nm_ip4_config_get_address (priv->ip4_config, 0); if (priv->ip4_internal_gw) - nm_log_info (LOGD_VPN, " Internal Gateway: %s", ip_address_to_string (priv->ip4_internal_gw)); - nm_log_info (LOGD_VPN, " Internal Address: %s", ip_address_to_string (nm_ip4_address_get_address (addr))); - nm_log_info (LOGD_VPN, " Internal Prefix: %d", nm_ip4_address_get_prefix (addr)); - nm_log_info (LOGD_VPN, " Internal Point-to-Point Address: %s", - ip_address_to_string (nm_ip4_config_get_ptp_address (priv->ip4_config))); + nm_log_info (LOGD_VPN, " Internal Gateway: %s", nm_utils_inet4_ntop (priv->ip4_internal_gw, NULL)); + nm_log_info (LOGD_VPN, " Internal Address: %s", nm_utils_inet4_ntop (address4->address, NULL)); + nm_log_info (LOGD_VPN, " Internal Prefix: %d", address4->plen); + nm_log_info (LOGD_VPN, " Internal Point-to-Point Address: %s", nm_utils_inet4_ntop (address4->peer_address, NULL)); nm_log_info (LOGD_VPN, " Maximum Segment Size (MSS): %d", nm_ip4_config_get_mss (priv->ip4_config)); num = nm_ip4_config_get_num_routes (priv->ip4_config); for (i = 0; i < num; i++) { - NMIP4Route *route; + const NMPlatformIP4Route *route = nm_ip4_config_get_route (priv->ip4_config, i); - route = nm_ip4_config_get_route (priv->ip4_config, i); nm_log_info (LOGD_VPN, " Static Route: %s/%d Next Hop: %s", - ip_address_to_string (nm_ip4_route_get_dest (route)), - nm_ip4_route_get_prefix (route), - ip_address_to_string (nm_ip4_route_get_next_hop (route))); + nm_utils_inet4_ntop (route->network, NULL), + route->plen, + nm_utils_inet4_ntop (route->gateway, buf)); } nm_log_info (LOGD_VPN, " Forbid Default Route: %s", - nm_ip4_config_get_never_default (priv->ip4_config) ? "yes" : "no"); + nm_ip4_config_get_never_default (priv->ip4_config) ? "yes" : "no"); num = nm_ip4_config_get_num_nameservers (priv->ip4_config); for (i = 0; i < num; i++) { nm_log_info (LOGD_VPN, " Internal DNS: %s", - ip_address_to_string (nm_ip4_config_get_nameserver (priv->ip4_config, i))); + nm_utils_inet4_ntop (nm_ip4_config_get_nameserver (priv->ip4_config, i), NULL)); } if (nm_ip4_config_get_num_domains (priv->ip4_config) > 0) @@ -548,34 +788,32 @@ print_vpn_config (NMVPNConnection *connection) if (priv->ip6_config) { nm_log_info (LOGD_VPN, "IPv6 configuration:"); - addr6 = nm_ip6_config_get_address (priv->ip6_config, 0); + address6 = nm_ip6_config_get_address (priv->ip6_config, 0); if (priv->ip6_internal_gw) - nm_log_info (LOGD_VPN, " Internal Gateway: %s", ip6_address_to_string (priv->ip6_internal_gw)); - nm_log_info (LOGD_VPN, " Internal Address: %s", ip6_address_to_string (nm_ip6_address_get_address (addr6))); - nm_log_info (LOGD_VPN, " Internal Prefix: %d", nm_ip6_address_get_prefix (addr6)); - nm_log_info (LOGD_VPN, " Internal Point-to-Point Address: %s", - ip6_address_to_string (nm_ip6_config_get_ptp_address (priv->ip6_config))); + nm_log_info (LOGD_VPN, " Internal Gateway: %s", nm_utils_inet6_ntop (priv->ip6_internal_gw, NULL)); + nm_log_info (LOGD_VPN, " Internal Address: %s", nm_utils_inet6_ntop (&address6->address, NULL)); + nm_log_info (LOGD_VPN, " Internal Prefix: %d", address6->plen); + nm_log_info (LOGD_VPN, " Internal Point-to-Point Address: %s", nm_utils_inet6_ntop (&address6->peer_address, NULL)); nm_log_info (LOGD_VPN, " Maximum Segment Size (MSS): %d", nm_ip6_config_get_mss (priv->ip6_config)); num = nm_ip6_config_get_num_routes (priv->ip6_config); for (i = 0; i < num; i++) { - NMIP6Route *route; + const NMPlatformIP6Route *route = nm_ip6_config_get_route (priv->ip6_config, i); - route = nm_ip6_config_get_route (priv->ip6_config, i); nm_log_info (LOGD_VPN, " Static Route: %s/%d Next Hop: %s", - ip6_address_to_string (nm_ip6_route_get_dest (route)), - nm_ip6_route_get_prefix (route), - ip6_address_to_string (nm_ip6_route_get_next_hop (route))); + nm_utils_inet6_ntop (&route->network, NULL), + route->plen, + nm_utils_inet6_ntop (&route->gateway, buf)); } nm_log_info (LOGD_VPN, " Forbid Default Route: %s", - nm_ip6_config_get_never_default (priv->ip6_config) ? "yes" : "no"); + nm_ip6_config_get_never_default (priv->ip6_config) ? "yes" : "no"); num = nm_ip6_config_get_num_nameservers (priv->ip6_config); for (i = 0; i < num; i++) { nm_log_info (LOGD_VPN, " Internal DNS: %s", - ip6_address_to_string (nm_ip6_config_get_nameserver (priv->ip6_config, i))); + nm_utils_inet6_ntop (nm_ip6_config_get_nameserver (priv->ip6_config, i), NULL)); } if (nm_ip6_config_get_num_domains (priv->ip6_config) > 0) @@ -597,38 +835,59 @@ static gboolean nm_vpn_connection_apply_config (NMVPNConnection *connection) { NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); + NMDevice *parent_dev = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (connection)); + NMIP4Config *vpn4_parent_config = NULL; + NMIP6Config *vpn6_parent_config = NULL; - nm_system_iface_set_up (priv->ip_ifindex, TRUE, NULL); + if (priv->ip_ifindex > 0) { + nm_platform_link_set_up (priv->ip_ifindex); - if (priv->ip4_config) { - if (!nm_system_apply_ip4_config (priv->ip_ifindex, priv->ip4_config, - 0, NM_IP4_COMPARE_FLAG_ALL)) - return FALSE; + if (priv->ip4_config) { + if (!nm_ip4_config_commit (priv->ip4_config, priv->ip_ifindex)) + return FALSE; + } + + if (priv->ip6_config) { + if (!nm_ip6_config_commit (priv->ip6_config, priv->ip_ifindex)) + return FALSE; + } + + if (priv->ip4_config) + vpn4_parent_config = nm_ip4_config_new (); + if (priv->ip6_config) + vpn6_parent_config = nm_ip6_config_new (); + } else { + /* If the VPN didn't return a network interface, it is a route-based + * VPN (like kernel IPSec) and all IP addressing and routing should + * be done on the parent interface instead. + */ + + if (priv->ip4_config) + vpn4_parent_config = g_object_ref (priv->ip4_config); + if (priv->ip6_config) + vpn6_parent_config = g_object_ref (priv->ip6_config); } - if (priv->ip6_config) { - if (!nm_system_apply_ip6_config (priv->ip_ifindex, priv->ip6_config, - 0, NM_IP6_COMPARE_FLAG_ALL)) - /* FIXME: remove ip4 config */ - return FALSE; + if (vpn4_parent_config) { + /* Add any explicit route to the VPN gateway through the parent device */ + if (priv->ip4_external_gw) + add_ip4_vpn_gateway_route (vpn4_parent_config, parent_dev, priv->ip4_external_gw); + + nm_device_set_vpn4_config (parent_dev, vpn4_parent_config); + g_object_unref (vpn4_parent_config); } + if (vpn6_parent_config) { + /* Add any explicit route to the VPN gateway through the parent device */ + if (priv->ip6_external_gw) + add_ip6_vpn_gateway_route (vpn6_parent_config, parent_dev, priv->ip6_external_gw); - /* Add any explicit route to the VPN gateway through the parent device */ - if (priv->ip4_external_gw) { - priv->gw_route = nm_system_add_ip4_vpn_gateway_route (priv->parent_dev, - priv->ip4_external_gw); - } else if (priv->ip6_external_gw) { - priv->gw_route = nm_system_add_ip6_vpn_gateway_route (priv->parent_dev, - priv->ip6_external_gw); - } else { - priv->gw_route = NULL; + nm_device_set_vpn6_config (parent_dev, vpn6_parent_config); + g_object_unref (vpn6_parent_config); } nm_log_info (LOGD_VPN, "VPN connection '%s' (IP Config Get) complete.", nm_connection_get_id (priv->connection)); - nm_vpn_connection_set_vpn_state (connection, - NM_VPN_CONNECTION_STATE_ACTIVATED, - NM_VPN_CONNECTION_STATE_REASON_NONE); + _set_vpn_state (connection, STATE_PRE_UP, NM_VPN_CONNECTION_STATE_REASON_NONE, FALSE); return TRUE; } @@ -638,7 +897,7 @@ nm_vpn_connection_config_maybe_complete (NMVPNConnection *connection, { NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); - if (priv->ipconfig_timeout == 0) { + if (priv->connect_timeout == 0) { /* config_complete() was already called with an error; * ignore further calls. */ @@ -653,8 +912,8 @@ nm_vpn_connection_config_maybe_complete (NMVPNConnection *connection, } } - g_source_remove (priv->ipconfig_timeout); - priv->ipconfig_timeout = 0; + g_source_remove (priv->connect_timeout); + priv->connect_timeout = 0; if (success) { print_vpn_config (connection); @@ -668,11 +927,13 @@ nm_vpn_connection_config_maybe_complete (NMVPNConnection *connection, nm_log_warn (LOGD_VPN, "VPN connection '%s' did not receive valid IP config information.", nm_connection_get_id (priv->connection)); - nm_vpn_connection_set_vpn_state (connection, - NM_VPN_CONNECTION_STATE_FAILED, - NM_VPN_CONNECTION_STATE_REASON_IP_CONFIG_INVALID); + _set_vpn_state (connection, STATE_FAILED, NM_VPN_CONNECTION_STATE_REASON_IP_CONFIG_INVALID, FALSE); } +#define LOG_INVALID_ARG(property) \ + nm_log_dbg (LOGD_VPN, "VPN connection '%s' has invalid argument %s", \ + nm_connection_get_id (priv->connection), property) + static gboolean process_generic_config (NMVPNConnection *connection, GHashTable *config_hash) @@ -680,41 +941,51 @@ process_generic_config (NMVPNConnection *connection, NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); GValue *val; + g_clear_pointer (&priv->ip_iface, g_free); val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_CONFIG_TUNDEV); - if (val) - priv->ip_iface = g_strdup (g_value_get_string (val)); - else { - nm_log_err (LOGD_VPN, "invalid or missing tunnel device received!"); - nm_vpn_connection_config_maybe_complete (connection, FALSE); - return FALSE; + if (val) { + if (G_VALUE_HOLDS (val, G_TYPE_STRING)) { + const char *tmp = g_value_get_string (val); + + /* Backwards compat with NM-openswan */ + if (g_strcmp0 (tmp, "_none_") != 0) + priv->ip_iface = g_strdup (tmp); + } else + LOG_INVALID_ARG (NM_VPN_PLUGIN_CONFIG_TUNDEV); } - /* Grab the interface index for address/routing operations */ - priv->ip_ifindex = nm_netlink_iface_to_index (priv->ip_iface); - if (priv->ip_ifindex <= 0) { - nm_log_err (LOGD_VPN, "(%s): failed to look up VPN interface index", priv->ip_iface); - nm_vpn_connection_config_maybe_complete (connection, FALSE); - return FALSE; + if (priv->ip_iface) { + /* Grab the interface index for address/routing operations */ + priv->ip_ifindex = nm_platform_link_get_ifindex (priv->ip_iface); + if (!priv->ip_ifindex) { + nm_log_err (LOGD_VPN, "(%s): failed to look up VPN interface index", priv->ip_iface); + nm_vpn_connection_config_maybe_complete (connection, FALSE); + return FALSE; + } } + g_clear_pointer (&priv->banner, g_free); val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_CONFIG_BANNER); if (val) { - g_free (priv->banner); - priv->banner = g_strdup (g_value_get_string (val)); + if (G_VALUE_HOLDS (val, G_TYPE_STRING)) + priv->banner = g_strdup (g_value_get_string (val)); + else + LOG_INVALID_ARG (NM_VPN_PLUGIN_CONFIG_BANNER); } /* External world-visible address of the VPN server */ priv->ip4_external_gw = 0; - priv->ip6_external_gw = NULL; + g_clear_pointer (&priv->ip6_external_gw, g_free); val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_CONFIG_EXT_GATEWAY); if (val) { + GByteArray *ba; + if (G_VALUE_HOLDS (val, G_TYPE_UINT)) { priv->ip4_external_gw = g_value_get_uint (val); - } else if (G_VALUE_HOLDS (val, DBUS_TYPE_G_UCHAR_ARRAY)) { - GByteArray *ba = g_value_get_boxed (val); - - if (ba->len == sizeof (struct in6_addr)) - priv->ip6_external_gw = g_memdup (ba->data, ba->len); + } else if (G_VALUE_HOLDS (val, DBUS_TYPE_G_UCHAR_ARRAY) && + (ba = g_value_get_boxed (val)) && + ba->len == sizeof (struct in6_addr)) { + priv->ip6_external_gw = g_memdup (ba->data, ba->len); } else { nm_log_err (LOGD_VPN, "(%s): VPN gateway is neither IPv4 nor IPv6", priv->ip_iface); nm_vpn_connection_config_maybe_complete (connection, FALSE); @@ -726,11 +997,14 @@ process_generic_config (NMVPNConnection *connection, * like it's IP4-specific. So we store it for now and retrieve it * later in ip4_config_get. */ + priv->mtu = 0; val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_CONFIG_MTU); - if (val) - priv->mtu = g_value_get_uint (val); - else - priv->mtu = 0; + if (val) { + if (G_VALUE_HOLDS (val, G_TYPE_UINT)) { + priv->mtu = g_value_get_uint (val); + } else + LOG_INVALID_ARG (NM_VPN_PLUGIN_CONFIG_MTU); + } return TRUE; } @@ -747,19 +1021,48 @@ nm_vpn_connection_config_get (DBusGProxy *proxy, nm_log_info (LOGD_VPN, "VPN connection '%s' (IP Config Get) reply received.", nm_connection_get_id (priv->connection)); + if (priv->vpn_state == STATE_CONNECT) + _set_vpn_state (connection, STATE_IP_CONFIG_GET, NM_VPN_CONNECTION_STATE_REASON_NONE, FALSE); + if (!process_generic_config (connection, config_hash)) return; /* Note whether to expect IPv4 and IPv6 configs */ val = g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_CONFIG_HAS_IP4); - priv->has_ip4 = val ? g_value_get_boolean (val) : FALSE; + priv->has_ip4 = FALSE; + if (val) { + if (G_VALUE_HOLDS (val, G_TYPE_BOOLEAN)) + priv->has_ip4 = g_value_get_boolean (val); + else + LOG_INVALID_ARG (NM_VPN_PLUGIN_CONFIG_HAS_IP4); + } g_clear_object (&priv->ip4_config); val = g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_CONFIG_HAS_IP6); - priv->has_ip6 = val ? g_value_get_boolean (val) : FALSE; + priv->has_ip6 = FALSE; + if (val) { + if (G_VALUE_HOLDS (val, G_TYPE_BOOLEAN)) + priv->has_ip6 = g_value_get_boolean (val); + else + LOG_INVALID_ARG (NM_VPN_PLUGIN_CONFIG_HAS_IP6); + } g_clear_object (&priv->ip6_config); } +static guint +vpn_routing_metric (NMVPNConnection *connection) +{ + NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); + + if (priv->ip_ifindex) + return NM_PLATFORM_ROUTE_METRIC_DEFAULT; + else { + NMDevice *parent_dev = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (connection)); + + return nm_device_get_priority (parent_dev); + } +} + static void nm_vpn_connection_ip4_config_get (DBusGProxy *proxy, GHashTable *config_hash, @@ -767,12 +1070,14 @@ nm_vpn_connection_ip4_config_get (DBusGProxy *proxy, { NMVPNConnection *connection = NM_VPN_CONNECTION (user_data); NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); - NMSettingIP4Config *s_ip4; - NMIP4Address *addr; + NMPlatformIP4Address address; NMIP4Config *config; GValue *val; int i; + if (priv->vpn_state == STATE_CONNECT) + _set_vpn_state (connection, STATE_IP_CONFIG_GET, NM_VPN_CONNECTION_STATE_REASON_NONE, FALSE); + if (priv->has_ip4) { nm_log_info (LOGD_VPN, "VPN connection '%s' (IP4 Config Get) reply received.", nm_connection_get_id (priv->connection)); @@ -798,10 +1103,10 @@ nm_vpn_connection_ip4_config_get (DBusGProxy *proxy, config = nm_ip4_config_new (); - addr = nm_ip4_address_new (); - nm_ip4_address_set_prefix (addr, 24); /* default to class C */ + memset (&address, 0, sizeof (address)); + address.plen = 24; if (priv->ip4_external_gw) - nm_ip4_address_set_gateway (addr, priv->ip4_external_gw); + nm_ip4_config_set_gateway (config, priv->ip4_external_gw); /* Internal address of the VPN subnet's gateway */ val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP4_CONFIG_INT_GATEWAY); @@ -810,21 +1115,21 @@ nm_vpn_connection_ip4_config_get (DBusGProxy *proxy, val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP4_CONFIG_ADDRESS); if (val) - nm_ip4_address_set_address (addr, g_value_get_uint (val)); + address.address = g_value_get_uint (val); val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP4_CONFIG_PTP); if (val) - nm_ip4_config_set_ptp_address (config, g_value_get_uint (val)); + address.peer_address = g_value_get_uint (val); val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP4_CONFIG_PREFIX); if (val) - nm_ip4_address_set_prefix (addr, g_value_get_uint (val)); + address.plen = g_value_get_uint (val); - if (nm_ip4_address_get_address (addr) && nm_ip4_address_get_prefix (addr)) { - nm_ip4_config_take_address (config, addr); + if (address.address && address.plen) { + address.source = NM_PLATFORM_SOURCE_VPN; + nm_ip4_config_add_address (config, &address); } else { nm_log_err (LOGD_VPN, "invalid IP4 config received!"); - nm_ip4_address_unref (addr); g_object_unref (config); nm_vpn_connection_config_maybe_complete (connection, FALSE); return; @@ -873,25 +1178,29 @@ nm_vpn_connection_ip4_config_get (DBusGProxy *proxy, routes = nm_utils_ip4_routes_from_gvalue (val); for (iter = routes; iter; iter = iter->next) { - NMIP4Route *route = iter->data; + NMIP4Route *item = iter->data; + NMPlatformIP4Route route; + + memset (&route, 0, sizeof (route)); + route.network = nm_ip4_route_get_dest (item); + route.plen = nm_ip4_route_get_prefix (item); + route.gateway = nm_ip4_route_get_next_hop (item); + route.source = NM_PLATFORM_SOURCE_VPN; + route.metric = vpn_routing_metric (connection); /* Ignore host routes to the VPN gateway since NM adds one itself * below. Since NM knows more about the routing situation than * the VPN server, we want to use the NM created route instead of * whatever the server provides. */ - if ( priv->ip4_external_gw - && nm_ip4_route_get_dest (route) == priv->ip4_external_gw - && nm_ip4_route_get_prefix (route) == 32) { - nm_ip4_route_unref (route); + if (priv->ip4_external_gw && route.network == priv->ip4_external_gw && route.plen == 32) continue; - } /* Otherwise accept the VPN-provided route */ - nm_ip4_config_take_route (config, route); + nm_ip4_config_add_route (config, &route); } - g_slist_free (routes); + g_slist_free_full (routes, (GDestroyNotify) nm_ip4_route_unref); } val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP4_CONFIG_NEVER_DEFAULT); @@ -899,10 +1208,13 @@ nm_vpn_connection_ip4_config_get (DBusGProxy *proxy, nm_ip4_config_set_never_default (config, g_value_get_boolean (val)); /* Merge in user overrides from the NMConnection's IPv4 setting */ - s_ip4 = nm_connection_get_setting_ip4_config (priv->connection); - nm_utils_merge_ip4_config (config, s_ip4); + nm_ip4_config_merge_setting (config, + nm_connection_get_setting_ip4_config (priv->connection), + vpn_routing_metric (connection)); priv->ip4_config = config; + nm_ip4_config_export (config); + g_object_notify (G_OBJECT (connection), NM_ACTIVE_CONNECTION_IP4_CONFIG); nm_vpn_connection_config_maybe_complete (connection, TRUE); } @@ -913,8 +1225,7 @@ nm_vpn_connection_ip6_config_get (DBusGProxy *proxy, { NMVPNConnection *connection = NM_VPN_CONNECTION (user_data); NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); - NMSettingIP6Config *s_ip6; - NMIP6Address *addr; + NMPlatformIP6Address address; NMIP6Config *config; GValue *val; int i; @@ -922,6 +1233,9 @@ nm_vpn_connection_ip6_config_get (DBusGProxy *proxy, nm_log_info (LOGD_VPN, "VPN connection '%s' (IP6 Config Get) reply received.", nm_connection_get_id (priv->connection)); + if (priv->vpn_state == STATE_CONNECT) + _set_vpn_state (connection, STATE_IP_CONFIG_GET, NM_VPN_CONNECTION_STATE_REASON_NONE, FALSE); + if (g_hash_table_size (config_hash) == 0) { priv->has_ip6 = FALSE; nm_vpn_connection_config_maybe_complete (connection, TRUE); @@ -930,12 +1244,13 @@ nm_vpn_connection_ip6_config_get (DBusGProxy *proxy, config = nm_ip6_config_new (); - addr = nm_ip6_address_new (); - nm_ip6_address_set_prefix (addr, 128); /* default to class C */ + memset (&address, 0, sizeof (address)); + address.plen = 128; if (priv->ip6_external_gw) - nm_ip6_address_set_gateway (addr, priv->ip6_external_gw); + nm_ip6_config_set_gateway (config, priv->ip6_external_gw); /* Internal address of the VPN subnet's gateway */ + g_clear_pointer (&priv->ip6_internal_gw, g_free); val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP6_CONFIG_INT_GATEWAY); if (val) { GByteArray *ba = g_value_get_boxed (val); @@ -949,7 +1264,7 @@ nm_vpn_connection_ip6_config_get (DBusGProxy *proxy, GByteArray *ba = g_value_get_boxed (val); if (ba->len == sizeof (struct in6_addr)) - nm_ip6_address_set_address (addr, (struct in6_addr *)ba->data); + address.address = *(struct in6_addr *) ba->data; } val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP6_CONFIG_PTP); @@ -957,18 +1272,18 @@ nm_vpn_connection_ip6_config_get (DBusGProxy *proxy, GByteArray *ba = g_value_get_boxed (val); if (ba->len == sizeof (struct in6_addr)) - nm_ip6_config_set_ptp_address (config, (struct in6_addr *)ba->data); + address.peer_address = *(struct in6_addr *) ba->data; } val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP6_CONFIG_PREFIX); if (val) - nm_ip6_address_set_prefix (addr, g_value_get_uint (val)); + address.plen = g_value_get_uint (val); - if (nm_ip6_address_get_address (addr) && nm_ip6_address_get_prefix (addr)) { - nm_ip6_config_take_address (config, addr); + if (!IN6_IS_ADDR_UNSPECIFIED (&address.address) && address.plen) { + address.source = NM_PLATFORM_SOURCE_VPN; + nm_ip6_config_add_address (config, &address); } else { nm_log_err (LOGD_VPN, "invalid IP6 config received!"); - nm_ip6_address_unref (addr); g_object_unref (config); nm_vpn_connection_config_maybe_complete (connection, FALSE); } @@ -1009,26 +1324,29 @@ nm_vpn_connection_ip6_config_get (DBusGProxy *proxy, routes = nm_utils_ip6_routes_from_gvalue (val); for (iter = routes; iter; iter = iter->next) { - NMIP6Route *route = iter->data; + NMIP6Route *item = iter->data; + NMPlatformIP6Route route; + + memset (&route, 0, sizeof (route)); + route.network = *nm_ip6_route_get_dest (item); + route.plen = nm_ip6_route_get_prefix (item); + route.gateway = *nm_ip6_route_get_next_hop (item); + route.source = NM_PLATFORM_SOURCE_VPN; + route.metric = vpn_routing_metric (connection); /* Ignore host routes to the VPN gateway since NM adds one itself * below. Since NM knows more about the routing situation than * the VPN server, we want to use the NM created route instead of * whatever the server provides. */ - if ( priv->ip6_external_gw - && nm_ip6_route_get_prefix (route) == 128 - && memcmp (nm_ip6_route_get_dest (route), priv->ip6_external_gw, - sizeof (struct in6_addr)) == 0) { - nm_ip6_route_unref (route); + if (priv->ip6_external_gw && IN6_ARE_ADDR_EQUAL (&route.network, priv->ip6_external_gw) && route.plen == 128) continue; - } /* Otherwise accept the VPN-provided route */ - nm_ip6_config_take_route (config, route); + nm_ip6_config_add_route (config, &route); } - g_slist_free (routes); + g_slist_free_full (routes, (GDestroyNotify) nm_ip6_route_unref); } val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP6_CONFIG_NEVER_DEFAULT); @@ -1036,57 +1354,96 @@ nm_vpn_connection_ip6_config_get (DBusGProxy *proxy, nm_ip6_config_set_never_default (config, g_value_get_boolean (val)); /* Merge in user overrides from the NMConnection's IPv6 setting */ - s_ip6 = nm_connection_get_setting_ip6_config (priv->connection); - nm_utils_merge_ip6_config (config, s_ip6); + nm_ip6_config_merge_setting (config, + nm_connection_get_setting_ip6_config (priv->connection), + vpn_routing_metric (connection)); priv->ip6_config = config; + nm_ip6_config_export (config); + g_object_notify (G_OBJECT (connection), NM_ACTIVE_CONNECTION_IP6_CONFIG); nm_vpn_connection_config_maybe_complete (connection, TRUE); } static gboolean -nm_vpn_connection_ip_config_timeout (gpointer user_data) +connect_timeout_cb (gpointer user_data) { NMVPNConnection *connection = NM_VPN_CONNECTION (user_data); NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); - priv->ipconfig_timeout = 0; + priv->connect_timeout = 0; - /* If the activation request's state is still IP_CONFIG_GET and we're - * in this timeout, cancel activation because it's taken too long. - */ - if (nm_vpn_connection_get_vpn_state (connection) == NM_VPN_CONNECTION_STATE_IP_CONFIG_GET) { - nm_log_warn (LOGD_VPN, "VPN connection '%s' (IP Config Get) timeout exceeded.", + /* Cancel activation if it's taken too long */ + if (priv->vpn_state == STATE_CONNECT || + priv->vpn_state == STATE_IP_CONFIG_GET) { + nm_log_warn (LOGD_VPN, "VPN connection '%s' connect timeout exceeded.", nm_connection_get_id (priv->connection)); - nm_vpn_connection_set_vpn_state (connection, - NM_VPN_CONNECTION_STATE_FAILED, - NM_VPN_CONNECTION_STATE_REASON_CONNECT_TIMEOUT); + _set_vpn_state (connection, STATE_FAILED, NM_VPN_CONNECTION_STATE_REASON_CONNECT_TIMEOUT, FALSE); } return FALSE; } static void -nm_vpn_connection_connect_cb (DBusGProxy *proxy, GError *err, gpointer user_data) +connect_success (NMVPNConnection *connection) { - NMVPNConnection *connection = NM_VPN_CONNECTION (user_data); NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); + /* 40 second timeout waiting for IP config signal from VPN service */ + priv->connect_timeout = g_timeout_add_seconds (40, connect_timeout_cb, connection); + + g_hash_table_destroy (priv->connect_hash); + priv->connect_hash = NULL; +} + +static void +connect_cb (DBusGProxy *proxy, DBusGProxyCall *call, void *user_data) +{ + NMVPNConnection *self = NM_VPN_CONNECTION (user_data); + NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self); + GError *err = NULL; + nm_log_info (LOGD_VPN, "VPN connection '%s' (Connect) reply received.", nm_connection_get_id (priv->connection)); - if (err) { - nm_log_warn (LOGD_VPN, "VPN connection '%s' failed to connect: '%s'.", - nm_connection_get_id (priv->connection), err->message); - nm_vpn_connection_set_vpn_state (connection, - NM_VPN_CONNECTION_STATE_FAILED, - NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_FAILED); + dbus_g_proxy_end_call (proxy, call, &err, G_TYPE_INVALID); + if (!err) { + connect_success (self); + return; + } + + nm_log_warn (LOGD_VPN, "VPN connection '%s' failed to connect: '%s'.", + nm_connection_get_id (priv->connection), err->message); + g_error_free (err); + _set_vpn_state (self, STATE_FAILED, NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_FAILED, FALSE); +} + +static void +connect_interactive_cb (DBusGProxy *proxy, DBusGProxyCall *call, void *user_data) +{ + NMVPNConnection *self = NM_VPN_CONNECTION (user_data); + NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self); + GError *err = NULL; + + nm_log_info (LOGD_VPN, "VPN connection '%s' (ConnectInteractive) reply received.", + nm_connection_get_id (priv->connection)); + + dbus_g_proxy_end_call (proxy, call, &err, G_TYPE_INVALID); + if (!err) { + connect_success (self); + return; + } + + if (dbus_g_error_has_name (err, NM_DBUS_VPN_ERROR_PREFIX "." NM_DBUS_VPN_INTERACTIVE_NOT_SUPPORTED)) { + /* Fall back to Connect() */ + dbus_g_proxy_begin_call (priv->proxy, "Connect", + connect_cb, self, NULL, + DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, priv->connect_hash, + G_TYPE_INVALID); } else { - nm_vpn_connection_set_vpn_state (connection, - NM_VPN_CONNECTION_STATE_IP_CONFIG_GET, - NM_VPN_CONNECTION_STATE_REASON_NONE); - - /* 40 second timeout waiting for IP config signal from VPN service */ - priv->ipconfig_timeout = g_timeout_add_seconds (40, nm_vpn_connection_ip_config_timeout, connection); + nm_log_warn (LOGD_VPN, "VPN connection '%s' failed to connect interactively: '%s'.", + nm_connection_get_id (priv->connection), err->message); + g_error_free (err); + _set_vpn_state (self, STATE_FAILED, NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_FAILED, FALSE); } } @@ -1122,74 +1479,90 @@ static void really_activate (NMVPNConnection *connection, const char *username) { NMVPNConnectionPrivate *priv; - GHashTable *hash; + NMAgentManager *agent_mgr; + GHashTable *details; g_return_if_fail (NM_IS_VPN_CONNECTION (connection)); - g_return_if_fail (nm_vpn_connection_get_vpn_state (connection) == NM_VPN_CONNECTION_STATE_NEED_AUTH); priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); + g_return_if_fail (priv->vpn_state == STATE_NEED_AUTH); dbus_g_object_register_marshaller (g_cclosure_marshal_VOID__BOXED, - G_TYPE_NONE, G_TYPE_VALUE, G_TYPE_INVALID); + G_TYPE_NONE, G_TYPE_VALUE, G_TYPE_INVALID); - /* Config signal */ - dbus_g_proxy_add_signal (priv->proxy, "Config", - DBUS_TYPE_G_MAP_OF_VARIANT, - G_TYPE_INVALID); + dbus_g_proxy_add_signal (priv->proxy, "Config", DBUS_TYPE_G_MAP_OF_VARIANT, G_TYPE_INVALID); dbus_g_proxy_connect_signal (priv->proxy, "Config", - G_CALLBACK (nm_vpn_connection_config_get), - connection, NULL); + G_CALLBACK (nm_vpn_connection_config_get), + connection, NULL); /* Ip4Config signal */ - dbus_g_proxy_add_signal (priv->proxy, "Ip4Config", - DBUS_TYPE_G_MAP_OF_VARIANT, - G_TYPE_INVALID); + dbus_g_proxy_add_signal (priv->proxy, "Ip4Config", DBUS_TYPE_G_MAP_OF_VARIANT, G_TYPE_INVALID); dbus_g_proxy_connect_signal (priv->proxy, "Ip4Config", - G_CALLBACK (nm_vpn_connection_ip4_config_get), - connection, NULL); + G_CALLBACK (nm_vpn_connection_ip4_config_get), + connection, NULL); /* Ip6Config signal */ - dbus_g_proxy_add_signal (priv->proxy, "Ip6Config", - DBUS_TYPE_G_MAP_OF_VARIANT, - G_TYPE_INVALID); + dbus_g_proxy_add_signal (priv->proxy, "Ip6Config", DBUS_TYPE_G_MAP_OF_VARIANT, G_TYPE_INVALID); dbus_g_proxy_connect_signal (priv->proxy, "Ip6Config", - G_CALLBACK (nm_vpn_connection_ip6_config_get), - connection, NULL); - - hash = _hash_with_username (priv->connection, username); - org_freedesktop_NetworkManager_VPN_Plugin_connect_async (priv->proxy, - hash, - nm_vpn_connection_connect_cb, - connection); - g_hash_table_destroy (hash); - - nm_vpn_connection_set_vpn_state (connection, - NM_VPN_CONNECTION_STATE_CONNECT, - NM_VPN_CONNECTION_STATE_REASON_NONE); + G_CALLBACK (nm_vpn_connection_ip6_config_get), + connection, NULL); + + if (priv->connect_hash) + g_hash_table_destroy (priv->connect_hash); + priv->connect_hash = _hash_with_username (priv->connection, username); + details = g_hash_table_new (g_str_hash, g_str_equal); + + /* If at least one agent doesn't support VPN hints, then we can't use + * ConnectInteractive(), because that agent won't be able to pass hints + * from the VPN plugin's interactive secrets requests to the VPN authentication + * dialog and we won't get the secrets we need. In this case fall back to + * the old Connect() call. + */ + agent_mgr = nm_agent_manager_get (); + if (nm_agent_manager_all_agents_have_capability (agent_mgr, + nm_active_connection_get_subject (NM_ACTIVE_CONNECTION (connection)), + NM_SECRET_AGENT_CAPABILITY_VPN_HINTS)) { + nm_log_dbg (LOGD_VPN, "Allowing interactive secrets as all agents have that capability"); + dbus_g_proxy_begin_call (priv->proxy, "ConnectInteractive", + connect_interactive_cb, connection, NULL, + DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, priv->connect_hash, + DBUS_TYPE_G_MAP_OF_VARIANT, details, + G_TYPE_INVALID); + } else { + nm_log_dbg (LOGD_VPN, "Calling old Connect function as not all agents support interactive secrets"); + dbus_g_proxy_begin_call (priv->proxy, "Connect", + connect_cb, connection, NULL, + DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, priv->connect_hash, + G_TYPE_INVALID); + } + g_object_unref (agent_mgr); + g_hash_table_destroy (details); + + _set_vpn_state (connection, STATE_CONNECT, NM_VPN_CONNECTION_STATE_REASON_NONE, FALSE); } void nm_vpn_connection_activate (NMVPNConnection *connection) { NMVPNConnectionPrivate *priv; - NMDBusManager *dbus_mgr; + DBusGConnection *bus; g_return_if_fail (NM_IS_VPN_CONNECTION (connection)); - g_return_if_fail (nm_vpn_connection_get_vpn_state (connection) == NM_VPN_CONNECTION_STATE_PREPARE); priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); - dbus_mgr = nm_dbus_manager_get (); - priv->proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (dbus_mgr), + _set_vpn_state (connection, STATE_PREPARE, NM_VPN_CONNECTION_STATE_REASON_NONE, FALSE); + + bus = nm_dbus_manager_get_connection (nm_dbus_manager_get ()); + priv->proxy = dbus_g_proxy_new_for_name (bus, nm_vpn_connection_get_service (connection), NM_VPN_DBUS_PLUGIN_PATH, NM_VPN_DBUS_PLUGIN_INTERFACE); - g_object_unref (dbus_mgr); dbus_g_proxy_add_signal (priv->proxy, "Failure", G_TYPE_UINT, G_TYPE_INVALID); dbus_g_proxy_connect_signal (priv->proxy, "Failure", - G_CALLBACK (plugin_failed), - connection, NULL); + G_CALLBACK (plugin_failed), + connection, NULL); /* StateChanged signal */ dbus_g_proxy_add_signal (priv->proxy, "StateChanged", G_TYPE_UINT, G_TYPE_INVALID); @@ -1197,9 +1570,21 @@ nm_vpn_connection_activate (NMVPNConnection *connection) G_CALLBACK (plugin_state_changed), connection, NULL); - nm_vpn_connection_set_vpn_state (connection, - NM_VPN_CONNECTION_STATE_NEED_AUTH, - NM_VPN_CONNECTION_STATE_REASON_NONE); + dbus_g_object_register_marshaller (g_cclosure_marshal_generic, + G_TYPE_NONE, G_TYPE_STRING, G_TYPE_STRV, G_TYPE_INVALID); + dbus_g_proxy_add_signal (priv->proxy, "SecretsRequired", G_TYPE_STRING, G_TYPE_STRV, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->proxy, "SecretsRequired", + G_CALLBACK (plugin_interactive_secrets_required), + connection, NULL); + + _set_vpn_state (connection, STATE_NEED_AUTH, NM_VPN_CONNECTION_STATE_REASON_NONE, FALSE); + + /* Kick off the secrets requests; first we get existing system secrets + * and ask the plugin if these are sufficient, next we get all existing + * secrets from system and from user agents and ask the plugin again, + * and last we ask the user for new secrets if required. + */ + get_secrets (connection, SECRETS_REQ_SYSTEM, NULL); } NMConnection * @@ -1215,7 +1600,7 @@ nm_vpn_connection_get_vpn_state (NMVPNConnection *connection) { g_return_val_if_fail (NM_IS_VPN_CONNECTION (connection), NM_VPN_CONNECTION_STATE_UNKNOWN); - return NM_VPN_CONNECTION_GET_PRIVATE (connection)->vpn_state; + return _state_to_nm_vpn_state (NM_VPN_CONNECTION_GET_PRIVATE (connection)->vpn_state); } const char * @@ -1258,14 +1643,6 @@ nm_vpn_connection_get_ip_ifindex (NMVPNConnection *connection) return NM_VPN_CONNECTION_GET_PRIVATE (connection)->ip_ifindex; } -NMDevice * -nm_vpn_connection_get_parent_device (NMVPNConnection *connection) -{ - g_return_val_if_fail (NM_IS_VPN_CONNECTION (connection), NULL); - - return NM_VPN_CONNECTION_GET_PRIVATE (connection)->parent_dev; -} - guint32 nm_vpn_connection_get_ip4_internal_gateway (NMVPNConnection *connection) { @@ -1283,38 +1660,46 @@ nm_vpn_connection_get_ip6_internal_gateway (NMVPNConnection *connection) } void -nm_vpn_connection_fail (NMVPNConnection *connection, - NMVPNConnectionStateReason reason) +nm_vpn_connection_disconnect (NMVPNConnection *connection, + NMVPNConnectionStateReason reason, + gboolean quitting) { g_return_if_fail (NM_IS_VPN_CONNECTION (connection)); - nm_vpn_connection_set_vpn_state (connection, - NM_VPN_CONNECTION_STATE_FAILED, - reason); + _set_vpn_state (connection, STATE_DISCONNECTED, reason, quitting); } -void -nm_vpn_connection_disconnect (NMVPNConnection *connection, - NMVPNConnectionStateReason reason) +gboolean +nm_vpn_connection_deactivate (NMVPNConnection *connection, + NMVPNConnectionStateReason reason, + gboolean quitting) { - g_return_if_fail (NM_IS_VPN_CONNECTION (connection)); + NMVPNConnectionPrivate *priv; + gboolean success = FALSE; - nm_vpn_connection_set_vpn_state (connection, - NM_VPN_CONNECTION_STATE_DISCONNECTED, - reason); + g_return_val_if_fail (NM_IS_VPN_CONNECTION (connection), FALSE); + + priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); + if (priv->vpn_state > STATE_UNKNOWN && priv->vpn_state <= STATE_DEACTIVATING) { + _set_vpn_state (connection, STATE_DEACTIVATING, reason, quitting); + success = TRUE; + } + return success; } /******************************************************************************/ static void -plugin_need_secrets_cb (DBusGProxy *proxy, - char *setting_name, - GError *error, - gpointer user_data) +plugin_need_secrets_cb (DBusGProxy *proxy, DBusGProxyCall *call, void *user_data) { NMVPNConnection *self = NM_VPN_CONNECTION (user_data); NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self); + GError *error = NULL; + char *setting_name; + dbus_g_proxy_end_call (proxy, call, &error, + G_TYPE_STRING, &setting_name, + G_TYPE_INVALID); if (error) { nm_log_err (LOGD_VPN, "(%s/%s) plugin NeedSecrets request #%d failed: %s %s", nm_connection_get_uuid (priv->connection), @@ -1322,7 +1707,8 @@ plugin_need_secrets_cb (DBusGProxy *proxy, priv->secrets_idx + 1, g_quark_to_string (error->domain), error->message); - nm_vpn_connection_fail (self, NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS); + _set_vpn_state (self, STATE_FAILED, NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS, FALSE); + g_error_free (error); return; } @@ -1333,13 +1719,13 @@ plugin_need_secrets_cb (DBusGProxy *proxy, nm_log_err (LOGD_VPN, "(%s/%s) final secrets request failed to provide sufficient secrets", nm_connection_get_uuid (priv->connection), nm_connection_get_id (priv->connection)); - nm_vpn_connection_fail (self, NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS); + _set_vpn_state (self, STATE_FAILED, NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS, FALSE); } else { nm_log_dbg (LOGD_VPN, "(%s/%s) service indicated additional secrets required", nm_connection_get_uuid (priv->connection), nm_connection_get_id (priv->connection)); - get_secrets (self, priv->secrets_idx + 1); + get_secrets (self, priv->secrets_idx + 1, NULL); } return; } @@ -1352,6 +1738,24 @@ plugin_need_secrets_cb (DBusGProxy *proxy, really_activate (self, priv->username); } +static void +plugin_new_secrets_cb (DBusGProxy *proxy, DBusGProxyCall *call, void *user_data) +{ + NMVPNConnection *self = NM_VPN_CONNECTION (user_data); + NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self); + GError *error = NULL; + + if (!dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID)) { + nm_log_err (LOGD_VPN, "(%s/%s) sending new secrets to the plugin failed: %s %s", + nm_connection_get_uuid (priv->connection), + nm_connection_get_id (priv->connection), + g_quark_to_string (error->domain), + error->message); + _set_vpn_state (self, STATE_FAILED, NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS, FALSE); + g_error_free (error); + } +} + static void get_secrets_cb (NMSettingsConnection *connection, guint32 call_id, @@ -1372,41 +1776,54 @@ get_secrets_cb (NMSettingsConnection *connection, if (error) { nm_log_err (LOGD_VPN, "Failed to request VPN secrets #%d: (%d) %s", priv->secrets_idx + 1, error->code, error->message); - nm_vpn_connection_fail (self, NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS); + _set_vpn_state (self, STATE_FAILED, NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS, FALSE); } else { - nm_log_dbg (LOGD_VPN, "(%s/%s) asking service if additional secrets are required", - nm_connection_get_uuid (priv->connection), - nm_connection_get_id (priv->connection)); - /* Cache the username for later */ if (agent_username) { g_free (priv->username); priv->username = g_strdup (agent_username); } - /* Ask the VPN service if more secrets are required */ hash = _hash_with_username (priv->connection, priv->username); - org_freedesktop_NetworkManager_VPN_Plugin_need_secrets_async (priv->proxy, - hash, - plugin_need_secrets_cb, - self); + + if (priv->secrets_idx == SECRETS_REQ_INTERACTIVE) { + nm_log_dbg (LOGD_VPN, "(%s/%s) sending secrets to the plugin", + nm_connection_get_uuid (priv->connection), + nm_connection_get_id (priv->connection)); + + /* Send the secrets back to the plugin */ + dbus_g_proxy_begin_call (priv->proxy, "NewSecrets", + plugin_new_secrets_cb, self, NULL, + DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, hash, + G_TYPE_INVALID); + } else { + nm_log_dbg (LOGD_VPN, "(%s/%s) asking service if additional secrets are required", + nm_connection_get_uuid (priv->connection), + nm_connection_get_id (priv->connection)); + + /* Ask the VPN service if more secrets are required */ + dbus_g_proxy_begin_call (priv->proxy, "NeedSecrets", + plugin_need_secrets_cb, self, NULL, + DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, hash, + G_TYPE_INVALID); + } + g_hash_table_destroy (hash); } } static void -get_secrets (NMVPNConnection *self, SecretsReq secrets_idx) +get_secrets (NMVPNConnection *self, + SecretsReq secrets_idx, + const char **hints) { NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self); NMSettingsGetSecretsFlags flags = NM_SETTINGS_GET_SECRETS_FLAG_NONE; GError *error = NULL; - gboolean filter_by_uid; g_return_if_fail (secrets_idx < SECRETS_REQ_LAST); priv->secrets_idx = secrets_idx; - filter_by_uid = nm_active_connection_get_user_requested (NM_ACTIVE_CONNECTION (self)); - nm_log_dbg (LOGD_VPN, "(%s/%s) requesting VPN secrets pass #%d", nm_connection_get_uuid (priv->connection), nm_connection_get_id (priv->connection), @@ -1415,12 +1832,12 @@ get_secrets (NMVPNConnection *self, SecretsReq secrets_idx) switch (priv->secrets_idx) { case SECRETS_REQ_SYSTEM: flags = NM_SETTINGS_GET_SECRETS_FLAG_ONLY_SYSTEM; - filter_by_uid = FALSE; break; case SECRETS_REQ_EXISTING: flags = NM_SETTINGS_GET_SECRETS_FLAG_NONE; break; case SECRETS_REQ_NEW: + case SECRETS_REQ_INTERACTIVE: flags = NM_SETTINGS_GET_SECRETS_FLAG_ALLOW_INTERACTION; break; default: @@ -1431,11 +1848,10 @@ get_secrets (NMVPNConnection *self, SecretsReq secrets_idx) flags |= NM_SETTINGS_GET_SECRETS_FLAG_USER_REQUESTED; priv->secrets_id = nm_settings_connection_get_secrets (NM_SETTINGS_CONNECTION (priv->connection), - filter_by_uid, - nm_active_connection_get_user_uid (NM_ACTIVE_CONNECTION (self)), + nm_active_connection_get_subject (NM_ACTIVE_CONNECTION (self)), NM_SETTING_VPN_SETTING_NAME, flags, - NULL, + hints, get_secrets_cb, self, &error); @@ -1444,46 +1860,63 @@ get_secrets (NMVPNConnection *self, SecretsReq secrets_idx) nm_log_err (LOGD_VPN, "failed to request VPN secrets #%d: (%d) %s", priv->secrets_idx + 1, error->code, error->message); } - nm_vpn_connection_fail (self, NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS); + _set_vpn_state (self, STATE_FAILED, NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS, FALSE); g_clear_error (&error); } } +static void +plugin_interactive_secrets_required (DBusGProxy *proxy, + const char *message, + const char **secrets, + gpointer user_data) +{ + NMVPNConnection *connection = NM_VPN_CONNECTION (user_data); + NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); + guint32 secrets_len = secrets ? g_strv_length ((char **) secrets) : 0; + char **hints; + guint32 i; + + nm_log_info (LOGD_VPN, "VPN plugin requested secrets; state %s (%d)", + vpn_state_to_string (priv->vpn_state), priv->vpn_state); + + g_return_if_fail (priv->vpn_state == STATE_CONNECT || + priv->vpn_state == STATE_NEED_AUTH); + + priv->secrets_idx = SECRETS_REQ_INTERACTIVE; + _set_vpn_state (connection, STATE_NEED_AUTH, NM_VPN_CONNECTION_STATE_REASON_NONE, FALSE); + + /* Copy hints and add message to the end */ + hints = g_malloc0 (sizeof (char *) * (secrets_len + 2)); + for (i = 0; i < secrets_len; i++) + hints[i] = g_strdup (secrets[i]); + if (message) + hints[i] = g_strdup_printf ("x-vpn-message:%s", message); + + get_secrets (connection, SECRETS_REQ_INTERACTIVE, (const char **) hints); + g_strfreev (hints); +} + /******************************************************************************/ static void nm_vpn_connection_init (NMVPNConnection *self) { - NM_VPN_CONNECTION_GET_PRIVATE (self)->vpn_state = NM_VPN_CONNECTION_STATE_PREPARE; + NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self); + + priv->vpn_state = STATE_WAITING; + priv->secrets_idx = SECRETS_REQ_SYSTEM; } static void constructed (GObject *object) { - NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (object); NMConnection *connection; - NMDevice *device; G_OBJECT_CLASS (nm_vpn_connection_parent_class)->constructed (object); connection = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (object)); - priv->connection = g_object_ref (connection); - - device = (NMDevice *) nm_active_connection_get_device (NM_ACTIVE_CONNECTION (object)); - g_assert (device); - - priv->parent_dev = g_object_ref (device); - - priv->device_monitor = g_signal_connect (device, "state-changed", - G_CALLBACK (device_state_changed), - object); - - priv->device_ip4 = g_signal_connect (device, "notify::" NM_DEVICE_IP4_CONFIG, - G_CALLBACK (device_ip4_config_changed), - object); - priv->device_ip6 = g_signal_connect (device, "notify::" NM_DEVICE_IP6_CONFIG, - G_CALLBACK (device_ip6_config_changed), - object); + NM_VPN_CONNECTION_GET_PRIVATE (object)->connection = g_object_ref (connection); } static void @@ -1491,47 +1924,28 @@ dispose (GObject *object) { NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (object); - if (priv->disposed) { - G_OBJECT_CLASS (nm_vpn_connection_parent_class)->dispose (object); - return; + if (priv->connect_hash) { + g_hash_table_destroy (priv->connect_hash); + priv->connect_hash = NULL; } - priv->disposed = TRUE; - - if (priv->gw_route) - rtnl_route_put (priv->gw_route); - if (priv->ip6_internal_gw) - g_free (priv->ip6_internal_gw); - if (priv->ip6_external_gw) - g_free (priv->ip6_external_gw); - - if (priv->device_ip4) - g_signal_handler_disconnect (priv->parent_dev, priv->device_ip4); - if (priv->device_ip6) - g_signal_handler_disconnect (priv->parent_dev, priv->device_ip6); - if (priv->device_monitor) - g_signal_handler_disconnect (priv->parent_dev, priv->device_monitor); - - g_clear_object (&priv->parent_dev); - - if (priv->ip4_config) - g_object_unref (priv->ip4_config); - if (priv->ip6_config) - g_object_unref (priv->ip6_config); - - if (priv->ipconfig_timeout) - g_source_remove (priv->ipconfig_timeout); + if (priv->connect_timeout) { + g_source_remove (priv->connect_timeout); + priv->connect_timeout = 0; + } - if (priv->proxy) - g_object_unref (priv->proxy); + dispatcher_cleanup (NM_VPN_CONNECTION (object)); if (priv->secrets_id) { nm_settings_connection_cancel_secrets (NM_SETTINGS_CONNECTION (priv->connection), priv->secrets_id); + priv->secrets_id = 0; } + g_clear_object (&priv->ip4_config); + g_clear_object (&priv->ip6_config); + g_clear_object (&priv->proxy); g_clear_object (&priv->connection); - g_free (priv->username); G_OBJECT_CLASS (nm_vpn_connection_parent_class)->dispose (object); } @@ -1543,25 +1957,48 @@ finalize (GObject *object) g_free (priv->banner); g_free (priv->ip_iface); + g_free (priv->username); + g_free (priv->ip6_internal_gw); + g_free (priv->ip6_external_gw); G_OBJECT_CLASS (nm_vpn_connection_parent_class)->finalize (object); } +static gboolean +ip_config_valid (VpnState state) +{ + return (state == STATE_PRE_UP || state == STATE_ACTIVATED); +} + static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (object); + NMDevice *parent_dev; switch (prop_id) { case PROP_VPN_STATE: - g_value_set_uint (value, priv->vpn_state); + g_value_set_uint (value, _state_to_nm_vpn_state (priv->vpn_state)); break; case PROP_BANNER: g_value_set_string (value, priv->banner ? priv->banner : ""); break; + case PROP_IP4_CONFIG: + if (ip_config_valid (priv->vpn_state) && priv->ip4_config) + g_value_set_boxed (value, nm_ip4_config_get_dbus_path (priv->ip4_config)); + else + g_value_set_boxed (value, "/"); + break; + case PROP_IP6_CONFIG: + if (ip_config_valid (priv->vpn_state) && priv->ip6_config) + g_value_set_boxed (value, nm_ip6_config_get_dbus_path (priv->ip6_config)); + else + g_value_set_boxed (value, "/"); + break; case PROP_MASTER: - g_value_set_boxed (value, nm_device_get_path (priv->parent_dev)); + parent_dev = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (object)); + g_value_set_boxed (value, parent_dev ? nm_device_get_path (parent_dev) : "/"); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -1573,6 +2010,7 @@ static void nm_vpn_connection_class_init (NMVPNConnectionClass *connection_class) { GObjectClass *object_class = G_OBJECT_CLASS (connection_class); + NMActiveConnectionClass *active_class = NM_ACTIVE_CONNECTION_CLASS (connection_class); g_type_class_add_private (connection_class, sizeof (NMVPNConnectionPrivate)); @@ -1581,6 +2019,7 @@ nm_vpn_connection_class_init (NMVPNConnectionClass *connection_class) object_class->constructed = constructed; object_class->dispose = dispose; object_class->finalize = finalize; + active_class->device_state_changed = device_state_changed; g_object_class_override_property (object_class, PROP_MASTER, NM_ACTIVE_CONNECTION_MASTER); @@ -1601,24 +2040,28 @@ nm_vpn_connection_class_init (NMVPNConnectionClass *connection_class) NULL, G_PARAM_READABLE)); + g_object_class_override_property (object_class, PROP_IP4_CONFIG, + NM_ACTIVE_CONNECTION_IP4_CONFIG); + g_object_class_override_property (object_class, PROP_IP6_CONFIG, + NM_ACTIVE_CONNECTION_IP6_CONFIG); + /* signals */ signals[VPN_STATE_CHANGED] = g_signal_new ("vpn-state-changed", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, - _nm_marshal_VOID__UINT_UINT, + 0, NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); signals[INTERNAL_STATE_CHANGED] = g_signal_new (NM_VPN_CONNECTION_INTERNAL_STATE_CHANGED, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, - _nm_marshal_VOID__UINT_UINT_UINT, + 0, NULL, NULL, NULL, G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT); - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (object_class), - &dbus_glib_nm_vpn_connection_object_info); + nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), + G_TYPE_FROM_CLASS (object_class), + &dbus_glib_nm_vpn_connection_object_info); } diff --git a/src/vpn-manager/nm-vpn-connection.h b/src/vpn-manager/nm-vpn-connection.h index bf543345..c9c88cda 100644 --- a/src/vpn-manager/nm-vpn-connection.h +++ b/src/vpn-manager/nm-vpn-connection.h @@ -26,6 +26,7 @@ #include #include "NetworkManagerVPN.h" #include "nm-device.h" +#include "nm-auth-subject.h" #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)) @@ -67,22 +68,24 @@ GType nm_vpn_connection_get_type (void); NMVPNConnection * nm_vpn_connection_new (NMConnection *connection, NMDevice *parent_device, const char *specific_object, - gboolean user_requested, - gulong user_uid); + NMAuthSubject *subject); void nm_vpn_connection_activate (NMVPNConnection *connection); NMConnection * nm_vpn_connection_get_connection (NMVPNConnection *connection); NMVPNConnectionState nm_vpn_connection_get_vpn_state (NMVPNConnection *connection); const char * nm_vpn_connection_get_banner (NMVPNConnection *connection); -void nm_vpn_connection_fail (NMVPNConnection *connection, - NMVPNConnectionStateReason reason); + +gboolean nm_vpn_connection_deactivate (NMVPNConnection *connection, + NMVPNConnectionStateReason reason, + gboolean quitting); void nm_vpn_connection_disconnect (NMVPNConnection *connection, - NMVPNConnectionStateReason reason); + NMVPNConnectionStateReason reason, + gboolean quitting); + NMIP4Config * nm_vpn_connection_get_ip4_config (NMVPNConnection *connection); NMIP6Config * nm_vpn_connection_get_ip6_config (NMVPNConnection *connection); const char * nm_vpn_connection_get_ip_iface (NMVPNConnection *connection); int nm_vpn_connection_get_ip_ifindex (NMVPNConnection *connection); -NMDevice * nm_vpn_connection_get_parent_device (NMVPNConnection *connection); guint32 nm_vpn_connection_get_ip4_internal_gateway (NMVPNConnection *connection); struct in6_addr * nm_vpn_connection_get_ip6_internal_gateway (NMVPNConnection *connection); diff --git a/src/vpn-manager/nm-vpn-manager.c b/src/vpn-manager/nm-vpn-manager.c index 7743fddd..5550d4d6 100644 --- a/src/vpn-manager/nm-vpn-manager.c +++ b/src/vpn-manager/nm-vpn-manager.c @@ -28,17 +28,16 @@ #include "nm-setting-vpn.h" #include "nm-dbus-manager.h" #include "NetworkManagerVPN.h" -#include "nm-marshal.h" #include "nm-enum-types.h" #include "nm-logging.h" +#define VPN_NAME_FILES_DIR NMCONFDIR "/VPN" + G_DEFINE_TYPE (NMVPNManager, nm_vpn_manager, G_TYPE_OBJECT) #define NM_VPN_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_VPN_MANAGER, NMVPNManagerPrivate)) typedef struct { - gboolean disposed; - GHashTable *services; GFileMonitor *monitor; guint monitor_id; @@ -76,93 +75,47 @@ get_service_by_namefile (NMVPNManager *self, const char *namefile) return NULL; } -static NMVPNConnection * -find_active_vpn_connection_by_connection (NMVPNManager *self, NMConnection *connection) -{ - NMVPNManagerPrivate *priv = NM_VPN_MANAGER_GET_PRIVATE (self); - GHashTableIter iter; - gpointer data; - const GSList *active, *aiter; - NMVPNConnection *found = NULL; - - g_return_val_if_fail (connection, NULL); - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - g_hash_table_iter_init (&iter, priv->services); - while (g_hash_table_iter_next (&iter, NULL, &data) && (found == NULL)) { - active = nm_vpn_service_get_active_connections (NM_VPN_SERVICE (data)); - for (aiter = active; aiter; aiter = g_slist_next (aiter)) { - NMVPNConnection *vpn = NM_VPN_CONNECTION (aiter->data); - - if (nm_vpn_connection_get_connection (vpn) == connection) { - found = vpn; - break; - } - } - } - return found; -} - -NMActiveConnection * +gboolean nm_vpn_manager_activate_connection (NMVPNManager *manager, - NMConnection *connection, - NMDevice *device, - const char *specific_object, - gboolean user_requested, - gulong user_uid, + NMVPNConnection *vpn, GError **error) { - NMSettingVPN *vpn_setting; + NMConnection *connection; + NMSettingVPN *s_vpn; NMVPNService *service; - NMVPNConnection *vpn = NULL; const char *service_name; + NMDevice *device; - g_return_val_if_fail (NM_IS_VPN_MANAGER (manager), NULL); - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - g_return_val_if_fail (NM_IS_DEVICE (device), NULL); - g_return_val_if_fail (error != NULL, NULL); - g_return_val_if_fail (*error == NULL, NULL); + g_return_val_if_fail (NM_IS_VPN_MANAGER (manager), FALSE); + g_return_val_if_fail (NM_IS_VPN_CONNECTION (vpn), FALSE); + g_return_val_if_fail (error != NULL, FALSE); + g_return_val_if_fail (*error == NULL, FALSE); + device = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (vpn)); + g_assert (device); if ( nm_device_get_state (device) != NM_DEVICE_STATE_ACTIVATED && nm_device_get_state (device) != NM_DEVICE_STATE_SECONDARIES) { - g_set_error (error, - NM_VPN_MANAGER_ERROR, NM_VPN_MANAGER_ERROR_DEVICE_NOT_ACTIVE, - "%s", "The base device for the VPN connection was not active."); - return NULL; - } - - vpn_setting = nm_connection_get_setting_vpn (connection); - if (!vpn_setting) { - g_set_error (error, - NM_VPN_MANAGER_ERROR, NM_VPN_MANAGER_ERROR_CONNECTION_INVALID, - "%s", "The connection was not a VPN connection."); - return NULL; + g_set_error_literal (error, NM_VPN_MANAGER_ERROR, NM_VPN_MANAGER_ERROR_DEVICE_NOT_ACTIVE, + "The base device for the VPN connection was not active."); + return FALSE; } - vpn = find_active_vpn_connection_by_connection (manager, connection); - if (vpn) { - nm_vpn_connection_disconnect (vpn, NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED); - vpn = NULL; - } + connection = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (vpn)); + g_assert (connection); + s_vpn = nm_connection_get_setting_vpn (connection); + g_assert (s_vpn); - service_name = nm_setting_vpn_get_service_type (vpn_setting); + service_name = nm_setting_vpn_get_service_type (s_vpn); g_assert (service_name); service = g_hash_table_lookup (NM_VPN_MANAGER_GET_PRIVATE (manager)->services, service_name); if (!service) { - g_set_error (error, - NM_VPN_MANAGER_ERROR, NM_VPN_MANAGER_ERROR_SERVICE_INVALID, + g_set_error (error, NM_VPN_MANAGER_ERROR, NM_VPN_MANAGER_ERROR_SERVICE_INVALID, "The VPN service '%s' was not installed.", service_name); - return NULL; + return FALSE; } - return (NMActiveConnection *) nm_vpn_service_activate (service, - connection, - device, - specific_object, - user_requested, - user_uid, - error); + return nm_vpn_service_activate (service, vpn, error); } gboolean @@ -170,51 +123,7 @@ nm_vpn_manager_deactivate_connection (NMVPNManager *self, NMVPNConnection *connection, NMVPNConnectionStateReason reason) { - NMVPNManagerPrivate *priv; - GHashTableIter iter; - gpointer data; - const GSList *active, *aiter; - gboolean success = FALSE; - - g_return_val_if_fail (self, FALSE); - g_return_val_if_fail (NM_IS_VPN_MANAGER (self), FALSE); - g_return_val_if_fail (connection != NULL, FALSE); - - priv = NM_VPN_MANAGER_GET_PRIVATE (self); - g_hash_table_iter_init (&iter, priv->services); - while (g_hash_table_iter_next (&iter, NULL, &data) && (success == FALSE)) { - active = nm_vpn_service_get_active_connections (NM_VPN_SERVICE (data)); - for (aiter = active; aiter; aiter = g_slist_next (aiter)) { - NMVPNConnection *candidate = aiter->data; - - if (connection == candidate) { - nm_vpn_connection_disconnect (connection, reason); - success = TRUE; - break; - } - } - } - - return success; -} - -static char * -service_name_from_file (const char *path) -{ - GKeyFile *kf = NULL; - char *service_name = NULL; - - g_return_val_if_fail (g_path_is_absolute (path), NULL); - - if (!g_str_has_suffix (path, ".name")) - return NULL; - - kf = g_key_file_new (); - if (g_key_file_load_from_file (kf, path, G_KEY_FILE_NONE, NULL)) - service_name = g_key_file_get_string (kf, VPN_CONNECTION_GROUP, "service", NULL); - - g_key_file_free (kf); - return service_name; + return nm_vpn_connection_deactivate (connection, reason, FALSE); } static void @@ -222,34 +131,32 @@ try_add_service (NMVPNManager *self, const char *namefile) { NMVPNManagerPrivate *priv = NM_VPN_MANAGER_GET_PRIVATE (self); NMVPNService *service = NULL; + GHashTableIter iter; GError *error = NULL; const char *service_name; - char *tmp; g_return_if_fail (g_path_is_absolute (namefile)); /* Make sure we don't add dupes */ - tmp = service_name_from_file (namefile); - if (tmp) - service = g_hash_table_lookup (priv->services, tmp); - g_free (tmp); - if (service) - return; + g_hash_table_iter_init (&iter, priv->services); + while (g_hash_table_iter_next (&iter, NULL, (gpointer) &service)) { + if (g_strcmp0 (namefile, nm_vpn_service_get_name_file (service)) == 0) + return; + } - /* New service, add it */ + /* New service */ service = nm_vpn_service_new (namefile, &error); - if (!service) { + if (service) { + service_name = nm_vpn_service_get_dbus_service (service); + g_hash_table_insert (priv->services, (char *) service_name, service); + nm_log_info (LOGD_VPN, "VPN: loaded %s", service_name); + } else { nm_log_warn (LOGD_VPN, "failed to load VPN service file %s: (%d) %s", namefile, error ? error->code : -1, error && error->message ? error->message : "(unknown)"); g_clear_error (&error); - return; } - - service_name = nm_vpn_service_get_dbus_service (service); - g_hash_table_insert (priv->services, (char *) service_name, service); - nm_log_info (LOGD_VPN, "VPN: loaded %s", service_name); } static void @@ -279,7 +186,7 @@ vpn_dir_changed (GFileMonitor *monitor, const char *service_name = nm_vpn_service_get_dbus_service (service); /* Stop active VPN connections and destroy the service */ - nm_vpn_service_connections_stop (service, TRUE, + nm_vpn_service_stop_connections (service, FALSE, NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED); nm_log_info (LOGD_VPN, "VPN: unloaded %s", service_name); g_hash_table_remove (priv->services, service_name); @@ -350,22 +257,37 @@ nm_vpn_manager_init (NMVPNManager *self) } } +static void +stop_all_services (NMVPNManager *self) +{ + NMVPNManagerPrivate *priv = NM_VPN_MANAGER_GET_PRIVATE (self); + GHashTableIter iter; + NMVPNService *service; + + g_hash_table_iter_init (&iter, priv->services); + while (g_hash_table_iter_next (&iter, NULL, (gpointer) &service)) { + nm_vpn_service_stop_connections (service, + TRUE, + NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED); + } +} + static void dispose (GObject *object) { NMVPNManagerPrivate *priv = NM_VPN_MANAGER_GET_PRIVATE (object); - if (!priv->disposed) { - priv->disposed = TRUE; - - if (priv->monitor) { - if (priv->monitor_id) - g_signal_handler_disconnect (priv->monitor, priv->monitor_id); - g_file_monitor_cancel (priv->monitor); - g_object_unref (priv->monitor); - } + if (priv->monitor) { + if (priv->monitor_id) + g_signal_handler_disconnect (priv->monitor, priv->monitor_id); + g_file_monitor_cancel (priv->monitor); + g_clear_object (&priv->monitor); + } + if (priv->services) { + stop_all_services (NM_VPN_MANAGER (object)); g_hash_table_destroy (priv->services); + priv->services = NULL; } G_OBJECT_CLASS (nm_vpn_manager_parent_class)->dispose (object); diff --git a/src/vpn-manager/nm-vpn-manager.h b/src/vpn-manager/nm-vpn-manager.h index 1d398ea2..57f947b0 100644 --- a/src/vpn-manager/nm-vpn-manager.h +++ b/src/vpn-manager/nm-vpn-manager.h @@ -59,13 +59,9 @@ GType nm_vpn_manager_get_type (void); NMVPNManager *nm_vpn_manager_get (void); -NMActiveConnection *nm_vpn_manager_activate_connection (NMVPNManager *manager, - NMConnection *connection, - NMDevice *device, - const char *specific_object, - gboolean user_requested, - gulong user_uid, - GError **error); +gboolean nm_vpn_manager_activate_connection (NMVPNManager *manager, + NMVPNConnection *vpn, + GError **error); gboolean nm_vpn_manager_deactivate_connection (NMVPNManager *manager, NMVPNConnection *connection, diff --git a/src/vpn-manager/nm-vpn-service.c b/src/vpn-manager/nm-vpn-service.c index 668cbf2e..824543fa 100644 --- a/src/vpn-manager/nm-vpn-service.c +++ b/src/vpn-manager/nm-vpn-service.c @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2005 - 2012 Red Hat, Inc. + * Copyright (C) 2005 - 2014 Red Hat, Inc. * Copyright (C) 2005 - 2008 Novell, Inc. */ @@ -38,30 +38,30 @@ G_DEFINE_TYPE (NMVPNService, nm_vpn_service, G_TYPE_OBJECT) typedef struct { - gboolean disposed; - - NMDBusManager *dbus_mgr; char *name; char *dbus_service; char *program; char *namefile; - GPid pid; - GSList *connections; + NMVPNConnection *active; + GSList *pending; + guint start_timeout; - guint quit_timeout; - guint child_watch; - gulong name_owner_id; + gboolean service_running; } NMVPNServicePrivate; #define NM_VPN_SERVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_VPN_SERVICE, NMVPNServicePrivate)) +#define VPN_CONNECTION_GROUP "VPN Connection" + +static gboolean start_pending_vpn (NMVPNService *self); + NMVPNService * nm_vpn_service_new (const char *namefile, GError **error) { - NMVPNService *self = NULL; + NMVPNService *self; + NMVPNServicePrivate *priv; GKeyFile *kf; - char *dbus_service = NULL, *program = NULL, *name = NULL; g_return_val_if_fail (namefile != NULL, NULL); g_return_val_if_fail (g_path_is_absolute (namefile), NULL); @@ -72,41 +72,31 @@ nm_vpn_service_new (const char *namefile, GError **error) return NULL; } - dbus_service = g_key_file_get_string (kf, VPN_CONNECTION_GROUP, "service", NULL); - if (!dbus_service) { - g_set_error (error, 0, 0, "VPN service file %s had no 'service' key", namefile); - goto out; - } + self = (NMVPNService *) g_object_new (NM_TYPE_VPN_SERVICE, NULL); + priv = NM_VPN_SERVICE_GET_PRIVATE (self); + priv->namefile = g_strdup (namefile); - program = g_key_file_get_string (kf, VPN_CONNECTION_GROUP, "program", NULL); - if (!program) { - g_set_error (error, 0, 0, "VPN service file %s had no 'program' key", namefile); - goto out; - } + priv->dbus_service = g_key_file_get_string (kf, VPN_CONNECTION_GROUP, "service", error); + if (!priv->dbus_service) + goto error; - name = g_key_file_get_string (kf, VPN_CONNECTION_GROUP, "name", NULL); - if (!name) { - g_set_error (error, 0, 0, "VPN service file %s had no 'name' key", namefile); - goto out; - } + priv->program = g_key_file_get_string (kf, VPN_CONNECTION_GROUP, "program", error); + if (!priv->program) + goto error; - self = (NMVPNService *) g_object_new (NM_TYPE_VPN_SERVICE, NULL); - if (!self) { - g_set_error (error, 0, 0, "out of memory creating VPN service object"); - goto out; - } + priv->name = g_key_file_get_string (kf, VPN_CONNECTION_GROUP, "name", error); + if (!priv->name) + goto error; - NM_VPN_SERVICE_GET_PRIVATE (self)->name = g_strdup (name); - NM_VPN_SERVICE_GET_PRIVATE (self)->dbus_service = g_strdup (dbus_service); - NM_VPN_SERVICE_GET_PRIVATE (self)->program = g_strdup (program); - NM_VPN_SERVICE_GET_PRIVATE (self)->namefile = g_strdup (namefile); + priv->service_running = nm_dbus_manager_name_has_owner (nm_dbus_manager_get (), priv->dbus_service); - out: g_key_file_free (kf); - g_free (dbus_service); - g_free (program); - g_free (name); return self; + +error: + g_object_unref (self); + g_key_file_free (kf); + return NULL; } const char * @@ -125,46 +115,60 @@ nm_vpn_service_get_name_file (NMVPNService *service) return NM_VPN_SERVICE_GET_PRIVATE (service)->namefile; } +static void +connection_vpn_state_changed (NMVPNConnection *connection, + NMVPNConnectionState new_state, + NMVPNConnectionState old_state, + NMVPNConnectionStateReason reason, + gpointer user_data) +{ + NMVPNService *self = NM_VPN_SERVICE (user_data); + NMVPNServicePrivate *priv = NM_VPN_SERVICE_GET_PRIVATE (self); + + if (new_state == NM_VPN_CONNECTION_STATE_FAILED || + new_state == NM_VPN_CONNECTION_STATE_DISCONNECTED) { + g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (connection_vpn_state_changed), self); + if (connection == priv->active) { + priv->active = NULL; + start_pending_vpn (self); + } else + priv->pending = g_slist_remove (priv->pending, connection); + g_object_unref (connection); + } +} + void -nm_vpn_service_connections_stop (NMVPNService *service, - gboolean fail, +nm_vpn_service_stop_connections (NMVPNService *service, + gboolean quitting, NMVPNConnectionStateReason reason) { NMVPNServicePrivate *priv = NM_VPN_SERVICE_GET_PRIVATE (service); - GSList *iter, *copy; + GSList *iter; - /* Copy because stopping the connection may remove it from the list - * in the the NMVPNService objects' VPN connection state handler. + /* Just add priv->active to the beginning of priv->pending, + * since we're going to clear priv->pending immediately anyway. */ - copy = g_slist_copy (priv->connections); - for (iter = copy; iter; iter = iter->next) { - if (fail) - nm_vpn_connection_fail (NM_VPN_CONNECTION (iter->data), reason); - else - nm_vpn_connection_disconnect (NM_VPN_CONNECTION (iter->data), reason); + if (priv->active) { + priv->pending = g_slist_prepend (priv->pending, priv->active); + priv->active = NULL; } - g_slist_free (copy); -} -static void -clear_quit_timeout (NMVPNService *self) -{ - NMVPNServicePrivate *priv = NM_VPN_SERVICE_GET_PRIVATE (self); + for (iter = priv->pending; iter; iter = iter->next) { + NMVPNConnection *vpn = NM_VPN_CONNECTION (iter->data); - if (priv->quit_timeout) { - g_source_remove (priv->quit_timeout); - priv->quit_timeout = 0; + g_signal_handlers_disconnect_by_func (vpn, G_CALLBACK (connection_vpn_state_changed), service); + if (quitting) { + /* Deactivate to allow pre-down before disconnecting */ + nm_vpn_connection_deactivate (vpn, reason, quitting); + } + nm_vpn_connection_disconnect (vpn, reason, quitting); + g_object_unref (vpn); } + g_clear_pointer (&priv->pending, g_slist_free); } -/* - * nm_vpn_service_child_setup - * - * Set the process group ID of the newly forked process - * - */ static void -nm_vpn_service_child_setup (gpointer user_data G_GNUC_UNUSED) +_daemon_setup (gpointer user_data G_GNUC_UNUSED) { /* We are in the child process at this point */ pid_t pid = getpid (); @@ -177,73 +181,37 @@ nm_vpn_service_child_setup (gpointer user_data G_GNUC_UNUSED) nm_unblock_posix_signals (NULL); } -static void -vpn_service_watch_cb (GPid pid, gint status, gpointer user_data) -{ - NMVPNService *service = NM_VPN_SERVICE (user_data); - NMVPNServicePrivate *priv = NM_VPN_SERVICE_GET_PRIVATE (service); - - if (WIFEXITED (status)) { - guint err = WEXITSTATUS (status); - - if (err != 0) { - nm_log_warn (LOGD_VPN, "VPN service '%s' exited with error: %d", - priv->name, WSTOPSIG (status)); - } - } else if (WIFSTOPPED (status)) { - nm_log_warn (LOGD_VPN, "VPN service '%s' stopped unexpectedly with signal %d", - priv->name, WSTOPSIG (status)); - } else if (WIFSIGNALED (status)) { - nm_log_warn (LOGD_VPN, "VPN service '%s' died with signal %d", - priv->name, WTERMSIG (status)); - } else { - nm_log_warn (LOGD_VPN, "VPN service '%s' died from an unknown cause", - priv->name); - } - - priv->pid = 0; - priv->child_watch = 0; - clear_quit_timeout (service); - - nm_vpn_service_connections_stop (service, TRUE, NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED); -} - static gboolean -nm_vpn_service_timeout (gpointer data) +_daemon_exec_timeout (gpointer data) { NMVPNService *self = NM_VPN_SERVICE (data); NMVPNServicePrivate *priv = NM_VPN_SERVICE_GET_PRIVATE (self); nm_log_warn (LOGD_VPN, "VPN service '%s' start timed out", priv->name); priv->start_timeout = 0; - nm_vpn_service_connections_stop (self, TRUE, NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT); - return FALSE; + nm_vpn_service_stop_connections (self, FALSE, NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT); + return G_SOURCE_REMOVE; } static gboolean nm_vpn_service_daemon_exec (NMVPNService *service, GError **error) { NMVPNServicePrivate *priv = NM_VPN_SERVICE_GET_PRIVATE (service); + GPid pid; char *vpn_argv[2]; gboolean success = FALSE; GError *spawn_error = NULL; g_return_val_if_fail (NM_IS_VPN_SERVICE (service), FALSE); - g_return_val_if_fail (error != NULL, FALSE); - g_return_val_if_fail (*error == NULL, FALSE); vpn_argv[0] = priv->program; vpn_argv[1] = NULL; - success = g_spawn_async (NULL, vpn_argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, - nm_vpn_service_child_setup, NULL, &priv->pid, - &spawn_error); + success = g_spawn_async (NULL, vpn_argv, NULL, 0, _daemon_setup, NULL, &pid, &spawn_error); if (success) { - nm_log_info (LOGD_VPN, "VPN service '%s' started (%s), PID %d", - priv->name, priv->dbus_service, priv->pid); - - priv->child_watch = g_child_watch_add (priv->pid, vpn_service_watch_cb, service); - priv->start_timeout = g_timeout_add_seconds (5, nm_vpn_service_timeout, service); + nm_log_info (LOGD_VPN, "VPN service '%s' started (%s), PID %ld", + priv->name, priv->dbus_service, (long int) pid); + priv->start_timeout = g_timeout_add_seconds (5, _daemon_exec_timeout, service); } else { nm_log_warn (LOGD_VPN, "VPN service '%s': could not launch the VPN service. error: (%d) %s.", priv->name, @@ -254,7 +222,7 @@ nm_vpn_service_daemon_exec (NMVPNService *service, GError **error) NM_VPN_MANAGER_ERROR, NM_VPN_MANAGER_ERROR_SERVICE_START_FAILED, "%s", spawn_error ? spawn_error->message : "unknown g_spawn_async() error"); - nm_vpn_service_connections_stop (service, TRUE, NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_FAILED); + nm_vpn_service_stop_connections (service, FALSE, NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_FAILED); if (spawn_error) g_error_free (spawn_error); } @@ -263,132 +231,88 @@ nm_vpn_service_daemon_exec (NMVPNService *service, GError **error) } static gboolean -ensure_killed (gpointer data) +start_active_vpn (NMVPNService *self, GError **error) { - int pid = GPOINTER_TO_INT (data); + NMVPNServicePrivate *priv = NM_VPN_SERVICE_GET_PRIVATE (self); - if (kill (pid, 0) == 0) - kill (pid, SIGKILL); + if (!priv->active) + return TRUE; - /* ensure the child is reaped */ - nm_log_dbg (LOGD_VPN, "waiting for VPN service pid %d to exit", pid); - waitpid (pid, NULL, 0); - nm_log_dbg (LOGD_VPN, "VPN service pid %d cleaned up", pid); + if (priv->service_running) { + /* Just activate the VPN */ + nm_vpn_connection_activate (priv->active); + return TRUE; + } else if (priv->start_timeout == 0) { + /* VPN service not running, start it */ + nm_log_info (LOGD_VPN, "Starting VPN service '%s'...", priv->name); + return nm_vpn_service_daemon_exec (self, error); + } - return FALSE; + /* Already started VPN service, waiting for it to appear on D-Bus */ + return TRUE; } static gboolean -service_quit (gpointer user_data) +start_pending_vpn (NMVPNService *self) { - NMVPNServicePrivate *priv = NM_VPN_SERVICE_GET_PRIVATE (user_data); - - if (priv->pid) { - if (kill (priv->pid, SIGTERM) == 0) - g_timeout_add_seconds (2, ensure_killed, GINT_TO_POINTER (priv->pid)); - else { - kill (priv->pid, SIGKILL); - - /* ensure the child is reaped */ - nm_log_dbg (LOGD_VPN, "waiting for VPN service pid %d to exit", priv->pid); - waitpid (priv->pid, NULL, 0); - nm_log_dbg (LOGD_VPN, "VPN service pid %d cleaned up", priv->pid); - } - priv->pid = 0; - } - priv->quit_timeout = 0; + NMVPNServicePrivate *priv = NM_VPN_SERVICE_GET_PRIVATE (self); - return FALSE; -} + g_assert (priv->active == NULL); -static void -connection_vpn_state_changed (NMVPNConnection *connection, - NMVPNConnectionState new_state, - NMVPNConnectionState old_state, - NMVPNConnectionStateReason reason, - gpointer user_data) -{ - NMVPNServicePrivate *priv = NM_VPN_SERVICE_GET_PRIVATE (user_data); + if (!priv->pending) + return TRUE; - switch (new_state) { - case NM_VPN_CONNECTION_STATE_FAILED: - case NM_VPN_CONNECTION_STATE_DISCONNECTED: - /* Remove the connection from our list */ - priv->connections = g_slist_remove (priv->connections, connection); - g_object_unref (connection); + /* Make next VPN active */ + priv->active = g_slist_nth_data (priv->pending, 0); + priv->pending = g_slist_remove (priv->pending, priv->active); - if (priv->connections == NULL) { - /* Tell the service to quit in a few seconds */ - if (!priv->quit_timeout) - priv->quit_timeout = g_timeout_add_seconds (5, service_quit, user_data); - } - break; - default: - break; - } + return start_active_vpn (self, NULL); } -NMVPNConnection * +gboolean nm_vpn_service_activate (NMVPNService *service, - NMConnection *connection, - NMDevice *device, - const char *specific_object, - gboolean user_requested, - gulong user_uid, + NMVPNConnection *vpn, GError **error) { - NMVPNConnection *vpn; NMVPNServicePrivate *priv; - g_return_val_if_fail (NM_IS_VPN_SERVICE (service), NULL); - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - g_return_val_if_fail (NM_IS_DEVICE (device), NULL); - g_return_val_if_fail (error != NULL, NULL); - g_return_val_if_fail (*error == NULL, NULL); + g_return_val_if_fail (NM_IS_VPN_SERVICE (service), FALSE); + g_return_val_if_fail (NM_IS_VPN_CONNECTION (vpn), FALSE); + g_return_val_if_fail (error != NULL, FALSE); + g_return_val_if_fail (*error == NULL, FALSE); priv = NM_VPN_SERVICE_GET_PRIVATE (service); - clear_quit_timeout (service); - - vpn = nm_vpn_connection_new (connection, device, specific_object, user_requested, user_uid); g_signal_connect (vpn, NM_VPN_CONNECTION_INTERNAL_STATE_CHANGED, G_CALLBACK (connection_vpn_state_changed), service); - priv->connections = g_slist_prepend (priv->connections, g_object_ref (vpn)); + /* Queue up the new VPN connection */ + priv->pending = g_slist_append (priv->pending, g_object_ref (vpn)); - if (nm_dbus_manager_name_has_owner (priv->dbus_mgr, priv->dbus_service)) { - // FIXME: fill in error when errors happen - nm_vpn_connection_activate (vpn); - } else if (priv->start_timeout == 0) { - nm_log_info (LOGD_VPN, "Starting VPN service '%s'...", priv->name); - if (!nm_vpn_service_daemon_exec (service, error)) - vpn = NULL; + /* Tell the active VPN to deactivate and wait for it to quit before we + * start the next VPN. The just-queued VPN will then be started from + * connection_vpn_state_changed(). + */ + if (priv->active) { + nm_vpn_connection_deactivate (priv->active, NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED, FALSE); + return TRUE; } - return vpn; -} - -const GSList * -nm_vpn_service_get_active_connections (NMVPNService *service) -{ - g_return_val_if_fail (NM_IS_VPN_SERVICE (service), NULL); - - return NM_VPN_SERVICE_GET_PRIVATE (service)->connections; + /* Otherwise start the next VPN */ + return start_pending_vpn (service); } static void -nm_vpn_service_name_owner_changed (NMDBusManager *mgr, - const char *name, - const char *old, - const char *new, - gpointer user_data) +_name_owner_changed (NMDBusManager *mgr, + const char *name, + const char *old, + const char *new, + gpointer user_data) { NMVPNService *service = NM_VPN_SERVICE (user_data); NMVPNServicePrivate *priv = NM_VPN_SERVICE_GET_PRIVATE (service); - gboolean old_owner_good; - gboolean new_owner_good; - GSList *iter; + gboolean old_owner_good, new_owner_good, success; if (strcmp (name, priv->dbus_service)) return; @@ -399,20 +323,21 @@ nm_vpn_service_name_owner_changed (NMDBusManager *mgr, priv->start_timeout = 0; } - old_owner_good = (old && (strlen (old) > 0)); - new_owner_good = (new && (strlen (new) > 0)); + old_owner_good = (old && old[0]); + new_owner_good = (new && new[0]); if (!old_owner_good && new_owner_good) { - /* service just appeared */ + /* service appeared */ + priv->service_running = TRUE; nm_log_info (LOGD_VPN, "VPN service '%s' appeared; activating connections", priv->name); - clear_quit_timeout (service); - - for (iter = priv->connections; iter; iter = iter->next) - nm_vpn_connection_activate (NM_VPN_CONNECTION (iter->data)); + /* Expect success because the VPN service has already appeared */ + success = start_active_vpn (service, NULL); + g_warn_if_fail (success); } else if (old_owner_good && !new_owner_good) { /* service went away */ + priv->service_running = FALSE; nm_log_info (LOGD_VPN, "VPN service '%s' disappeared", priv->name); - nm_vpn_service_connections_stop (service, TRUE, NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED); + nm_vpn_service_stop_connections (service, FALSE, NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED); } } @@ -421,13 +346,10 @@ nm_vpn_service_name_owner_changed (NMDBusManager *mgr, static void nm_vpn_service_init (NMVPNService *self) { - NMVPNServicePrivate *priv = NM_VPN_SERVICE_GET_PRIVATE (self); - - priv->dbus_mgr = nm_dbus_manager_get (); - priv->name_owner_id = g_signal_connect (priv->dbus_mgr, - NM_DBUS_MANAGER_NAME_OWNER_CHANGED, - G_CALLBACK (nm_vpn_service_name_owner_changed), - self); + g_signal_connect (nm_dbus_manager_get (), + NM_DBUS_MANAGER_NAME_OWNER_CHANGED, + G_CALLBACK (_name_owner_changed), + self); } static void @@ -436,34 +358,33 @@ dispose (GObject *object) NMVPNService *self = NM_VPN_SERVICE (object); NMVPNServicePrivate *priv = NM_VPN_SERVICE_GET_PRIVATE (self); - if (priv->disposed) - goto out; - priv->disposed = TRUE; - - if (priv->start_timeout) + if (priv->start_timeout) { g_source_remove (priv->start_timeout); + priv->start_timeout = 0; + } - nm_vpn_service_connections_stop (NM_VPN_SERVICE (object), - FALSE, - NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED); - - g_signal_handler_disconnect (priv->dbus_mgr, priv->name_owner_id); + /* VPNService owner is required to stop connections before releasing */ + g_assert (priv->active == NULL); + g_assert (priv->pending == NULL); - if (priv->child_watch) - g_source_remove (priv->child_watch); + g_signal_handlers_disconnect_by_func (nm_dbus_manager_get (), + G_CALLBACK (_name_owner_changed), + self); - clear_quit_timeout (self); - service_quit (self); + G_OBJECT_CLASS (nm_vpn_service_parent_class)->dispose (object); +} - g_object_unref (priv->dbus_mgr); +static void +finalize (GObject *object) +{ + NMVPNServicePrivate *priv = NM_VPN_SERVICE_GET_PRIVATE (object); g_free (priv->name); g_free (priv->dbus_service); g_free (priv->program); g_free (priv->namefile); -out: - G_OBJECT_CLASS (nm_vpn_service_parent_class)->dispose (object); + G_OBJECT_CLASS (nm_vpn_service_parent_class)->finalize (object); } static void @@ -475,4 +396,5 @@ nm_vpn_service_class_init (NMVPNServiceClass *service_class) /* virtual methods */ object_class->dispose = dispose; + object_class->finalize = finalize; } diff --git a/src/vpn-manager/nm-vpn-service.h b/src/vpn-manager/nm-vpn-service.h index e883d55f..4545d1f0 100644 --- a/src/vpn-manager/nm-vpn-service.h +++ b/src/vpn-manager/nm-vpn-service.h @@ -34,8 +34,6 @@ #define NM_IS_VPN_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_VPN_SERVICE)) #define NM_VPN_SERVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_VPN_SERVICE, NMVPNServiceClass)) -#define VPN_CONNECTION_GROUP "VPN Connection" - typedef struct { GObject parent; } NMVPNService; @@ -54,18 +52,12 @@ const char *nm_vpn_service_get_dbus_service (NMVPNService *service); /* Returns the path of the VPN service's .name file */ const char *nm_vpn_service_get_name_file (NMVPNService *service); -NMVPNConnection * nm_vpn_service_activate (NMVPNService *service, - NMConnection *connection, - NMDevice *device, - const char *specific_object, - gboolean user_requested, - gulong user_uid, - GError **error); - -const GSList *nm_vpn_service_get_active_connections (NMVPNService *service); +gboolean nm_vpn_service_activate (NMVPNService *service, + NMVPNConnection *vpn, + GError **error); -void nm_vpn_service_connections_stop (NMVPNService *service, - gboolean fail, +void nm_vpn_service_stop_connections (NMVPNService *service, + gboolean quitting, NMVPNConnectionStateReason reason); #endif /* NM_VPN_VPN_SERVICE_H */ -- cgit 1.3.0-6-gf8a5