diff options
Diffstat (limited to 'callouts')
| -rw-r--r-- | callouts/Makefile.am | 20 | ||||
| -rw-r--r-- | callouts/Makefile.in | 53 | ||||
| -rw-r--r-- | callouts/nm-avahi-autoipd-action.c | 126 | ||||
| -rw-r--r-- | callouts/nm-avahi-autoipd.conf | 13 | ||||
| -rw-r--r-- | callouts/nm-dispatcher-api.h | 6 | ||||
| -rw-r--r-- | callouts/nm-dispatcher-utils.c | 43 | ||||
| -rw-r--r-- | callouts/nm-dispatcher-utils.h | 5 | ||||
| -rw-r--r-- | callouts/nm-dispatcher.c | 498 | ||||
| -rw-r--r-- | callouts/tests/Makefile.am | 11 | ||||
| -rw-r--r-- | callouts/tests/Makefile.in | 31 | ||||
| -rw-r--r-- | callouts/tests/dispatcher-down | 1 | ||||
| -rw-r--r-- | callouts/tests/dispatcher-external | 33 | ||||
| -rw-r--r-- | callouts/tests/dispatcher-up | 1 | ||||
| -rw-r--r-- | callouts/tests/dispatcher-vpn-down | 1 | ||||
| -rw-r--r-- | callouts/tests/dispatcher-vpn-up | 1 | ||||
| -rw-r--r-- | callouts/tests/test-dispatcher-envp.c | 39 |
16 files changed, 518 insertions, 364 deletions
diff --git a/callouts/Makefile.am b/callouts/Makefile.am index 2f9fc71d..6440a4de 100644 --- a/callouts/Makefile.am +++ b/callouts/Makefile.am @@ -1,12 +1,11 @@ SUBDIRS = . tests AM_CPPFLAGS = \ - -I${top_srcdir}/include \ - -I${top_builddir}/include \ + -I${top_srcdir}/shared \ + -I${top_builddir}/shared \ -I${top_srcdir}/libnm-core \ -I${top_builddir}/libnm-core \ $(GLIB_CFLAGS) \ - $(DBUS_CFLAGS) \ -DNETWORKMANAGER_COMPILATION \ -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ -DNMCONFDIR=\"$(nmconfdir)\" \ @@ -23,20 +22,10 @@ noinst_LTLIBRARIES = \ dbusservicedir = $(DBUS_SYS_DIR) dbusservice_DATA = \ - nm-dispatcher.conf \ - nm-avahi-autoipd.conf + nm-dispatcher.conf libexec_PROGRAMS = \ - nm-dispatcher \ - nm-avahi-autoipd.action - - -nm_avahi_autoipd_action_SOURCES = \ - nm-avahi-autoipd-action.c - -nm_avahi_autoipd_action_LDADD = \ - $(DBUS_LIBS) \ - $(GLIB_LIBS) + nm-dispatcher nm_dispatcher_SOURCES = \ @@ -106,6 +95,7 @@ install-data-hook: $(mkinstalldirs) -m 0755 $(DESTDIR)$(dispatcherdir) $(mkinstalldirs) -m 0755 $(DESTDIR)$(dispatcherdir)/pre-down.d $(mkinstalldirs) -m 0755 $(DESTDIR)$(dispatcherdir)/pre-up.d + $(mkinstalldirs) -m 0755 $(DESTDIR)$(dispatcherdir)/no-wait.d CLEANFILES = $(nodist_libnmdbus_dispatcher_la_SOURCES) $(dbusactivation_DATA) diff --git a/callouts/Makefile.in b/callouts/Makefile.in index 5a4458b4..2fa3d996 100644 --- a/callouts/Makefile.in +++ b/callouts/Makefile.in @@ -90,8 +90,7 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -libexec_PROGRAMS = nm-dispatcher$(EXEEXT) \ - nm-avahi-autoipd.action$(EXEEXT) +libexec_PROGRAMS = nm-dispatcher$(EXEEXT) subdir = callouts ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \ @@ -134,12 +133,6 @@ libtest_dispatcher_envp_la_OBJECTS = \ am__installdirs = "$(DESTDIR)$(libexecdir)" \ "$(DESTDIR)$(dbusactivationdir)" "$(DESTDIR)$(dbusservicedir)" PROGRAMS = $(libexec_PROGRAMS) -am_nm_avahi_autoipd_action_OBJECTS = \ - nm-avahi-autoipd-action.$(OBJEXT) -nm_avahi_autoipd_action_OBJECTS = \ - $(am_nm_avahi_autoipd_action_OBJECTS) -nm_avahi_autoipd_action_DEPENDENCIES = $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) am_nm_dispatcher_OBJECTS = nm-dispatcher.$(OBJEXT) \ nm-dispatcher-utils.$(OBJEXT) nm_dispatcher_OBJECTS = $(am_nm_dispatcher_OBJECTS) @@ -180,10 +173,9 @@ am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(nodist_libnmdbus_dispatcher_la_SOURCES) \ - $(libtest_dispatcher_envp_la_SOURCES) \ - $(nm_avahi_autoipd_action_SOURCES) $(nm_dispatcher_SOURCES) + $(libtest_dispatcher_envp_la_SOURCES) $(nm_dispatcher_SOURCES) DIST_SOURCES = $(libtest_dispatcher_envp_la_SOURCES) \ - $(nm_avahi_autoipd_action_SOURCES) $(nm_dispatcher_SOURCES) + $(nm_dispatcher_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ @@ -296,7 +288,6 @@ BLUEZ5_LIBS = @BLUEZ5_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ -CKDB_PATH = @CKDB_PATH@ CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ @@ -308,8 +299,6 @@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DBUS_CFLAGS = @DBUS_CFLAGS@ -DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@ -DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@ DBUS_LIBS = @DBUS_LIBS@ DBUS_SYS_DIR = @DBUS_SYS_DIR@ DEFS = @DEFS@ @@ -319,6 +308,7 @@ DHCPCD_PATH = @DHCPCD_PATH@ DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@ DLLTOOL = @DLLTOOL@ DNSMASQ_PATH = @DNSMASQ_PATH@ +DNSSEC_TRIGGER_SCRIPT = @DNSSEC_TRIGGER_SCRIPT@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ @@ -373,16 +363,13 @@ 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@ +LIBAUDIT_CFLAGS = @LIBAUDIT_CFLAGS@ +LIBAUDIT_LIBS = @LIBAUDIT_LIBS@ LIBDL = @LIBDL@ -LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ -LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ -LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ @@ -419,6 +406,8 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ +NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ NM_MICRO_VERSION = @NM_MICRO_VERSION@ NM_MINOR_VERSION = @NM_MINOR_VERSION@ @@ -447,7 +436,6 @@ POLKIT_LIBS = @POLKIT_LIBS@ POSUB = @POSUB@ PPPD_PATH = @PPPD_PATH@ PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ -PPPOE_PATH = @PPPOE_PATH@ QT_CFLAGS = @QT_CFLAGS@ QT_LIBS = @QT_LIBS@ RANLIB = @RANLIB@ @@ -462,6 +450,8 @@ 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_JOURNAL_CFLAGS = @SYSTEMD_JOURNAL_CFLAGS@ +SYSTEMD_JOURNAL_LIBS = @SYSTEMD_JOURNAL_LIBS@ SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@ SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ @@ -522,6 +512,7 @@ mkdir_p = @mkdir_p@ nmbinary = @nmbinary@ nmconfdir = @nmconfdir@ nmdatadir = @nmdatadir@ +nmlibdir = @nmlibdir@ nmrundir = @nmrundir@ nmstatedir = @nmstatedir@ oldincludedir = @oldincludedir@ @@ -529,6 +520,7 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -546,12 +538,11 @@ with_resolvconf = @with_resolvconf@ with_valgrind = @with_valgrind@ SUBDIRS = . tests AM_CPPFLAGS = \ - -I${top_srcdir}/include \ - -I${top_builddir}/include \ + -I${top_srcdir}/shared \ + -I${top_builddir}/shared \ -I${top_srcdir}/libnm-core \ -I${top_builddir}/libnm-core \ $(GLIB_CFLAGS) \ - $(DBUS_CFLAGS) \ -DNETWORKMANAGER_COMPILATION \ -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ -DNMCONFDIR=\"$(nmconfdir)\" \ @@ -568,15 +559,7 @@ noinst_LTLIBRARIES = libtest-dispatcher-envp.la \ libnmdbus-dispatcher.la dbusservicedir = $(DBUS_SYS_DIR) dbusservice_DATA = \ - nm-dispatcher.conf \ - nm-avahi-autoipd.conf - -nm_avahi_autoipd_action_SOURCES = \ - nm-avahi-autoipd-action.c - -nm_avahi_autoipd_action_LDADD = \ - $(DBUS_LIBS) \ - $(GLIB_LIBS) + nm-dispatcher.conf nm_dispatcher_SOURCES = \ nm-dispatcher.c \ @@ -727,10 +710,6 @@ clean-libexecPROGRAMS: echo " rm -f" $$list; \ rm -f $$list -nm-avahi-autoipd.action$(EXEEXT): $(nm_avahi_autoipd_action_OBJECTS) $(nm_avahi_autoipd_action_DEPENDENCIES) $(EXTRA_nm_avahi_autoipd_action_DEPENDENCIES) - @rm -f nm-avahi-autoipd.action$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(nm_avahi_autoipd_action_OBJECTS) $(nm_avahi_autoipd_action_LDADD) $(LIBS) - nm-dispatcher$(EXEEXT): $(nm_dispatcher_OBJECTS) $(nm_dispatcher_DEPENDENCIES) $(EXTRA_nm_dispatcher_DEPENDENCIES) @rm -f nm-dispatcher$(EXEEXT) $(AM_V_CCLD)$(LINK) $(nm_dispatcher_OBJECTS) $(nm_dispatcher_LDADD) $(LIBS) @@ -743,7 +722,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnmdbus_dispatcher_la-nmdbus-dispatcher.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtest_dispatcher_envp_la-nm-dispatcher-utils.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-avahi-autoipd-action.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-dispatcher-utils.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-dispatcher.Po@am__quote@ @@ -1140,6 +1118,7 @@ install-data-hook: $(mkinstalldirs) -m 0755 $(DESTDIR)$(dispatcherdir) $(mkinstalldirs) -m 0755 $(DESTDIR)$(dispatcherdir)/pre-down.d $(mkinstalldirs) -m 0755 $(DESTDIR)$(dispatcherdir)/pre-up.d + $(mkinstalldirs) -m 0755 $(DESTDIR)$(dispatcherdir)/no-wait.d # 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. diff --git a/callouts/nm-avahi-autoipd-action.c b/callouts/nm-avahi-autoipd-action.c deleted file mode 100644 index b28dae5d..00000000 --- a/callouts/nm-avahi-autoipd-action.c +++ /dev/null @@ -1,126 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2008, 2014 Red Hat, Inc. - */ - -#include "config.h" - -#include <stdlib.h> -#include <string.h> - -#include <gio/gio.h> - -#define NM_AVAHI_AUTOIPD_DBUS_SERVICE "org.freedesktop.nm_avahi_autoipd" -#define NM_AVAHI_AUTOIPD_DBUS_INTERFACE "org.freedesktop.nm_avahi_autoipd" - -static void -on_name_acquired (GDBusConnection *connection, - const gchar *name, - gpointer loop) -{ - g_main_loop_quit (loop); -} - -static void -on_name_lost (GDBusConnection *connection, - const gchar *name, - gpointer user_data) -{ - g_printerr ("Error: Could not acquire the NM autoipd service."); - exit (1); -} - -int -main (int argc, char *argv[]) -{ - GDBusConnection *connection; - char *event, *iface, *address; - GMainLoop *loop; - GError *error = NULL; - -#if !GLIB_CHECK_VERSION (2, 35, 0) - g_type_init (); -#endif - - if (argc != 4) { - g_printerr ("Error: expected 3 arguments (event, interface, address).\n"); - exit (1); - } - - event = argv[1]; - iface = argv[2]; - address = argv[3] ? argv[3] : ""; - - if (!event || !iface || !strlen (event) || !strlen (iface)) { - g_printerr ("Error: unexpected arguments received from avahi-autoipd.\n"); - exit (1); - } - - /* Get a connection to the system bus */ - connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error); - if (error) { - char *remote_error = g_dbus_error_get_remote_error (error); - - g_dbus_error_strip_remote_error (error); - g_printerr ("Error: could not get the system bus. Make sure " - "the message bus daemon is running! Message: (%s) %s\n", - remote_error, error->message); - g_free (remote_error); - g_error_free (error); - return 1; - } - - /* Acquire the bus name */ - loop = g_main_loop_new (NULL, FALSE); - g_bus_own_name_on_connection (connection, - NM_AVAHI_AUTOIPD_DBUS_SERVICE, - 0, - on_name_acquired, - on_name_lost, - loop, NULL); - g_main_loop_run (loop); - g_main_loop_unref (loop); - - /* Send the signal */ - if (!g_dbus_connection_emit_signal (connection, - NULL, - "/", - NM_AVAHI_AUTOIPD_DBUS_INTERFACE, - "Event", - g_variant_new ("(sss)", - event, - iface, - address), - &error)) { - g_dbus_error_strip_remote_error (error); - g_printerr ("Error: Could not send autoipd Event signal: %s\n", error->message); - g_error_free (error); - return 1; - } - - if (!g_dbus_connection_flush_sync (connection, NULL, &error)) { - g_dbus_error_strip_remote_error (error); - g_printerr ("Error: Could not flush D-Bus connection: %s\n", error->message); - g_error_free (error); - return 1; - } - - g_object_unref (connection); - return 0; -} - diff --git a/callouts/nm-avahi-autoipd.conf b/callouts/nm-avahi-autoipd.conf deleted file mode 100644 index 485ab429..00000000 --- a/callouts/nm-avahi-autoipd.conf +++ /dev/null @@ -1,13 +0,0 @@ -<!DOCTYPE busconfig PUBLIC - "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" - "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> -<busconfig> - <policy user="root"> - <allow own="org.freedesktop.nm_avahi_autoipd"/> - </policy> - <policy context="default"> - <deny own="org.freedesktop.nm_avahi_autoipd"/> - <deny send_destination="org.freedesktop.nm_avahi_autoipd"/> - </policy> -</busconfig> - diff --git a/callouts/nm-dispatcher-api.h b/callouts/nm-dispatcher-api.h index 9b2c3b32..d702ba68 100644 --- a/callouts/nm-dispatcher-api.h +++ b/callouts/nm-dispatcher-api.h @@ -21,10 +21,7 @@ #define NMD_SCRIPT_DIR_DEFAULT NMCONFDIR "/dispatcher.d" #define NMD_SCRIPT_DIR_PRE_UP NMD_SCRIPT_DIR_DEFAULT "/pre-up.d" #define NMD_SCRIPT_DIR_PRE_DOWN NMD_SCRIPT_DIR_DEFAULT "/pre-down.d" - -/* dbus-glib types for dispatcher call return value (used by src/nm-dispatcher.c) */ -#define DISPATCHER_TYPE_RESULT (dbus_g_type_get_struct ("GValueArray", G_TYPE_STRING, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_INVALID)) -#define DISPATCHER_TYPE_RESULT_ARRAY (dbus_g_type_get_collection ("GPtrArray", DISPATCHER_TYPE_RESULT)) +#define NMD_SCRIPT_DIR_NO_WAIT NMD_SCRIPT_DIR_DEFAULT "/no-wait.d" #define NM_DISPATCHER_DBUS_SERVICE "org.freedesktop.nm_dispatcher" #define NM_DISPATCHER_DBUS_INTERFACE "org.freedesktop.nm_dispatcher" @@ -32,6 +29,7 @@ #define NMD_CONNECTION_PROPS_PATH "path" #define NMD_CONNECTION_PROPS_FILENAME "filename" +#define NMD_CONNECTION_PROPS_EXTERNAL "external" #define NMD_DEVICE_PROPS_INTERFACE "interface" #define NMD_DEVICE_PROPS_IP_INTERFACE "ip-interface" diff --git a/callouts/nm-dispatcher-utils.c b/callouts/nm-dispatcher-utils.c index e7a6f6a2..6079d019 100644 --- a/callouts/nm-dispatcher-utils.c +++ b/callouts/nm-dispatcher-utils.c @@ -22,7 +22,6 @@ #include <string.h> -#include <glib-object.h> #include <nm-dbus-interface.h> #include <nm-connection.h> @@ -30,6 +29,7 @@ #include <nm-setting-ip6-config.h> #include <nm-setting-connection.h> +#include "nm-default.h" #include "nm-dispatcher-api.h" #include "nm-utils.h" @@ -331,30 +331,46 @@ nm_dispatcher_utils_construct_envp (const char *action, const char *vpn_ip_iface, GVariant *vpn_ip4_props, GVariant *vpn_ip6_props, - char **out_iface) + char **out_iface, + const char **out_error_message) { const char *iface = NULL, *ip_iface = NULL; - const char *uuid = NULL, *id = NULL, *path; + const char *uuid = NULL, *id = NULL, *path = NULL; const char *filename = NULL; + gboolean external; NMDeviceState dev_state = NM_DEVICE_STATE_UNKNOWN; GVariant *value; char **envp = NULL, *path_item; GSList *items = NULL, *iter; guint i; GVariant *con_setting; + const char *error_message_backup; + + if (!out_error_message) + out_error_message = &error_message_backup; g_return_val_if_fail (action != NULL, NULL); g_return_val_if_fail (out_iface != NULL, NULL); g_return_val_if_fail (*out_iface == NULL, NULL); /* Hostname changes don't require a device nor contain a connection */ - if (!strcmp (action, "hostname")) + if (!strcmp (action, NMD_ACTION_HOSTNAME)) goto done; - /* config filename */ + /* Connection properties */ + if (!g_variant_lookup (connection_props, NMD_CONNECTION_PROPS_PATH, "&o", &path)) { + *out_error_message = "Missing or invalid required value " NMD_CONNECTION_PROPS_PATH "!"; + return NULL; + } + items = g_slist_prepend (items, g_strdup_printf ("CONNECTION_DBUS_PATH=%s", path)); + + if (g_variant_lookup (connection_props, NMD_CONNECTION_PROPS_EXTERNAL, "b", &external) && external) + items = g_slist_prepend (items, g_strdup ("CONNECTION_EXTERNAL=1")); + if (g_variant_lookup (connection_props, NMD_CONNECTION_PROPS_FILENAME, "&s", &filename)) items = g_slist_prepend (items, g_strdup_printf ("CONNECTION_FILENAME=%s", filename)); + /* Canonicalize the VPN interface name; "" is used when passing it through * D-Bus so make sure that's fixed up here. */ @@ -363,7 +379,7 @@ nm_dispatcher_utils_construct_envp (const char *action, /* interface name */ if (!g_variant_lookup (device_props, NMD_DEVICE_PROPS_INTERFACE, "&s", &iface)) { - g_warning ("Missing or invalid required value " NMD_DEVICE_PROPS_INTERFACE "!"); + *out_error_message = "Missing or invalid required value " NMD_DEVICE_PROPS_INTERFACE "!"; return NULL; } if (!*iface) @@ -373,7 +389,7 @@ nm_dispatcher_utils_construct_envp (const char *action, value = g_variant_lookup_value (device_props, NMD_DEVICE_PROPS_IP_INTERFACE, NULL); if (value) { if (!g_variant_is_of_type (value, G_VARIANT_TYPE_STRING)) { - g_warning ("Invalid value " NMD_DEVICE_PROPS_IP_INTERFACE "!"); + *out_error_message = "Invalid value " NMD_DEVICE_PROPS_IP_INTERFACE "!"; return NULL; } g_variant_unref (value); @@ -382,14 +398,14 @@ nm_dispatcher_utils_construct_envp (const char *action, /* Device type */ if (!g_variant_lookup (device_props, NMD_DEVICE_PROPS_TYPE, "u", NULL)) { - g_warning ("Missing or invalid required value " NMD_DEVICE_PROPS_TYPE "!"); + *out_error_message = "Missing or invalid required value " NMD_DEVICE_PROPS_TYPE "!"; return NULL; } /* Device state */ value = g_variant_lookup_value (device_props, NMD_DEVICE_PROPS_STATE, G_VARIANT_TYPE_UINT32); if (!value) { - g_warning ("Missing or invalid required value " NMD_DEVICE_PROPS_STATE "!"); + *out_error_message = "Missing or invalid required value " NMD_DEVICE_PROPS_STATE "!"; return NULL; } dev_state = g_variant_get_uint32 (value); @@ -397,25 +413,25 @@ nm_dispatcher_utils_construct_envp (const char *action, /* device itself */ if (!g_variant_lookup (device_props, NMD_DEVICE_PROPS_PATH, "o", NULL)) { - g_warning ("Missing or invalid required value " NMD_DEVICE_PROPS_PATH "!"); + *out_error_message = "Missing or invalid required value " NMD_DEVICE_PROPS_PATH "!"; return NULL; } /* UUID and ID */ con_setting = g_variant_lookup_value (connection_dict, NM_SETTING_CONNECTION_SETTING_NAME, NM_VARIANT_TYPE_SETTING); if (!con_setting) { - g_warning ("Failed to read connection setting"); + *out_error_message = "Failed to read connection setting"; return NULL; } if (!g_variant_lookup (con_setting, NM_SETTING_CONNECTION_UUID, "&s", &uuid)) { - g_warning ("Connection hash did not contain the UUID"); + *out_error_message = "Connection hash did not contain the UUID"; g_variant_unref (con_setting); return NULL; } if (!g_variant_lookup (con_setting, NM_SETTING_CONNECTION_ID, "&s", &id)) { - g_warning ("Connection hash did not contain the ID"); + *out_error_message = "Connection hash did not contain the ID"; g_variant_unref (con_setting); return NULL; } @@ -462,6 +478,7 @@ nm_dispatcher_utils_construct_envp (const char *action, envp[i] = (char *) iter->data; g_slist_free (items); + *out_error_message = NULL; return envp; } diff --git a/callouts/nm-dispatcher-utils.h b/callouts/nm-dispatcher-utils.h index 665a0d4e..40a0d41f 100644 --- a/callouts/nm-dispatcher-utils.h +++ b/callouts/nm-dispatcher-utils.h @@ -21,7 +21,7 @@ #ifndef __NETWORKMANAGER_DISPATCHER_UTILS_H__ #define __NETWORKMANAGER_DISPATCHER_UTILS_H__ -#include <glib.h> +#include "nm-default.h" char ** nm_dispatcher_utils_construct_envp (const char *action, @@ -35,7 +35,8 @@ nm_dispatcher_utils_construct_envp (const char *action, const char *vpn_ip_iface, GVariant *vpn_ip4_props, GVariant *vpn_ip6_props, - char **out_iface); + char **out_iface, + const char **out_error_message); #endif /* __NETWORKMANAGER_DISPATCHER_UTILS_H__ */ diff --git a/callouts/nm-dispatcher.c b/callouts/nm-dispatcher.c index 09eb0d3a..a635e216 100644 --- a/callouts/nm-dispatcher.c +++ b/callouts/nm-dispatcher.c @@ -32,13 +32,13 @@ #include <errno.h> #include <arpa/inet.h> -#include <glib.h> #include <glib-unix.h> - +#include "nm-default.h" #include "nm-dispatcher-api.h" #include "nm-dispatcher-utils.h" -#include "nm-glib-compat.h" +#include "nm-macros-internal.h" +#include "gsystem-local-alloc.h" #include "nmdbus-dispatcher.h" @@ -46,6 +46,7 @@ static GMainLoop *loop = NULL; static gboolean debug = FALSE; static gboolean persist = FALSE; static guint quit_id; +static guint request_id_counter = 0; typedef struct Request Request; @@ -56,7 +57,8 @@ typedef struct { NMDBusDispatcher *dbus_dispatcher; Request *current_request; - GQueue *pending_requests; + GQueue *requests_waiting; + gint num_requests_pending; } Handler; typedef struct { @@ -91,7 +93,7 @@ handle_action (NMDBusDispatcher *dbus_dispatcher, static void handler_init (Handler *h) { - h->pending_requests = g_queue_new (); + h->requests_waiting = g_queue_new (); h->dbus_dispatcher = nmdbus_dispatcher_skeleton_new (); g_signal_connect (h->dbus_dispatcher, "handle-action", G_CALLBACK (handle_action), h); @@ -102,7 +104,7 @@ handler_class_init (HandlerClass *h_class) { } -static void dispatch_one_script (Request *request); +static gboolean dispatch_one_script (Request *request); typedef struct { Request *request; @@ -111,11 +113,17 @@ typedef struct { GPid pid; DispatchResult result; char *error; + gboolean wait; + gboolean dispatched; + guint watch_id; + guint timeout_id; } ScriptInfo; struct Request { Handler *handler; + guint request_id; + GDBusMethodInvocation *context; char *action; char *iface; @@ -124,11 +132,61 @@ struct Request { GPtrArray *scripts; /* list of ScriptInfo */ guint idx; - - guint script_watch_id; - guint script_timeout_id; + gint num_scripts_done; + gint num_scripts_nowait; }; +/*****************************************************************************/ + +#define __LOG_print(print_cmd, _request, _script, ...) \ + G_STMT_START { \ + nm_assert ((_request) && (!(_script) || (_script)->request == (_request))); \ + print_cmd ("#%u '%s'%s%s%s%s%s%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ + (_request)->request_id, \ + (_request)->action, \ + (_request)->iface ? " [" : "", \ + (_request)->iface ? (_request)->iface : "", \ + (_request)->iface ? "]" : "", \ + (_script) ? ", \"" : "", \ + (_script) ? (_script)->script : "", \ + (_script) ? "\"" : "" \ + _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ + } G_STMT_END + +#define _LOG(_request, _script, log_always, print_cmd, ...) \ + G_STMT_START { \ + const Request *__request = (_request); \ + const ScriptInfo *__script = (_script); \ + \ + if (!__request) \ + __request = __script->request; \ + nm_assert (__request && (!__script || __script->request == __request)); \ + if ((log_always) || __request->debug) { \ + if (FALSE) { \ + /* g_message() alone does not warn about invalid format. Add a dummy printf() statement to + * get a compiler warning about wrong format. */ \ + __LOG_print (printf, __request, __script, __VA_ARGS__); \ + } \ + __LOG_print (print_cmd, __request, __script, __VA_ARGS__); \ + } \ + } G_STMT_END + +static gboolean +_LOG_R_D_enabled (const Request *request) +{ + return request->debug; +} + +#define _LOG_R_D(_request, ...) _LOG(_request, NULL, FALSE, g_message, __VA_ARGS__) +#define _LOG_R_I(_request, ...) _LOG(_request, NULL, TRUE, g_message, __VA_ARGS__) +#define _LOG_R_W(_request, ...) _LOG(_request, NULL, TRUE, g_warning, __VA_ARGS__) + +#define _LOG_S_D(_script, ...) _LOG(NULL, _script, FALSE, g_message, __VA_ARGS__) +#define _LOG_S_I(_script, ...) _LOG(NULL, _script, TRUE, g_message, __VA_ARGS__) +#define _LOG_S_W(_script, ...) _LOG(NULL, _script, TRUE, g_warning, __VA_ARGS__) + +/*****************************************************************************/ + static void script_info_free (gpointer ptr) { @@ -136,17 +194,22 @@ script_info_free (gpointer ptr) g_free (info->script); g_free (info->error); - g_free (info); + g_slice_free (ScriptInfo, info); } static void request_free (Request *request) { + g_assert_cmpuint (request->num_scripts_done, ==, request->scripts->len); + g_assert_cmpuint (request->num_scripts_nowait, ==, 0); + g_free (request->action); g_free (request->iface); g_strfreev (request->envp); if (request->scripts) g_ptr_array_free (request->scripts, TRUE); + + g_slice_free (Request, request); } static gboolean @@ -157,64 +220,78 @@ quit_timeout_cb (gpointer user_data) } static void -quit_timeout_cancel (void) -{ - if (quit_id) { - g_source_remove (quit_id); - quit_id = 0; - } -} - -static void quit_timeout_reschedule (void) { - quit_timeout_cancel (); - if (!persist) + if (!persist) { + nm_clear_g_source (&quit_id); quit_id = g_timeout_add_seconds (10, quit_timeout_cb, NULL); + } } -static void -start_request (Request *request) +/** + * next_request: + * + * @h: the handler + * @request: (allow-none): the request to set as next. If %NULL, dequeue the next + * waiting request. Otherwise, try to set the given request. + * + * Sets the currently active request (@current_request). The current request + * is a request that has at least on "wait" script, because requests that only + * consist of "no-wait" scripts are handled right away and not enqueued to + * @requests_waiting nor set as @current_request. + * + * Returns: %TRUE, if there was currently not request in process and it set + * a new request as current. + */ +static gboolean +next_request (Handler *h, Request *request) { - if (request->iface) - g_message ("Dispatching action '%s' for %s", request->action, request->iface); - else - g_message ("Dispatching action '%s'", request->action); + if (request) { + if (h->current_request) { + g_queue_push_tail (h->requests_waiting, request); + return FALSE; + } + } else { + /* when calling next_request() without explicit @request, we always + * forcefully clear @current_request. That one is certainly + * handled already. */ + h->current_request = NULL; - request->handler->current_request = request; - dispatch_one_script (request); -} + request = g_queue_pop_head (h->requests_waiting); + if (!request) + return FALSE; + } -static void -next_request (Handler *h) -{ - Request *request = g_queue_pop_head (h->pending_requests); + _LOG_R_I (request, "start running ordered scripts..."); - if (request) { - start_request (request); - return; - } + h->current_request = request; - h->current_request = NULL; - quit_timeout_reschedule (); + return TRUE; } -static gboolean -next_script (gpointer user_data) +/** + * complete_request: + * @request: the request + * + * Checks if all the scripts for the request have terminated and in such case + * it sends the D-Bus response and releases the request resources. + * + * It also decreases @num_requests_pending and possibly does quit_timeout_reschedule(). + */ +static void +complete_request (Request *request) { - Request *request = user_data; - Handler *h = request->handler; GVariantBuilder results; GVariant *ret; guint i; + Handler *handler = request->handler; - request->idx++; - if (request->idx < request->scripts->len) { - dispatch_one_script (request); - return FALSE; - } + nm_assert (request); + + /* Are there still pending scripts? Then do nothing (for now). */ + if (request->num_scripts_done < request->scripts->len) + return; - /* All done */ g_variant_builder_init (&results, G_VARIANT_TYPE ("a(sus)")); for (i = 0; i < request->scripts->len; i++) { ScriptInfo *script = g_ptr_array_index (request->scripts, i); @@ -228,16 +305,87 @@ next_script (gpointer user_data) ret = g_variant_new ("(a(sus))", &results); g_dbus_method_invocation_return_value (request->context, ret); - if (request->debug) { - if (request->iface) - g_message ("Dispatch '%s' on %s complete", request->action, request->iface); - else - g_message ("Dispatch '%s' complete", request->action); - } + _LOG_R_D (request, "completed (%u scripts)", request->scripts->len); + + if (handler->current_request == request) + handler->current_request = NULL; + request_free (request); - next_request (h); - return FALSE; + g_assert_cmpuint (handler->num_requests_pending, >, 0); + if (--handler->num_requests_pending <= 0) { + nm_assert (!handler->current_request && !g_queue_peek_head (handler->requests_waiting)); + quit_timeout_reschedule (); + } +} + +static void +complete_script (ScriptInfo *script) +{ + Handler *handler; + Request *request; + gboolean wait = script->wait; + + request = script->request; + + if (wait) { + /* for "wait" scripts, try to schedule the next blocking script. + * If that is successful, return (as we must wait for its completion). */ + if (dispatch_one_script (request)) + return; + } + + handler = request->handler; + + nm_assert (!wait || handler->current_request == request); + + /* Try to complete the request. @request will be possibly free'd, + * making @script and @request a dangling pointer. */ + complete_request (request); + + if (!wait) { + /* this was a "no-wait" script. We either completed the request, + * or there is nothing to do. Especially, there is no need to + * queue the next_request() -- because no-wait scripts don't block + * requests. However, if this was the last "no-wait" script and + * there are "wait" scripts ready to run, launch them. + */ + if ( handler->current_request == request + && handler->current_request->num_scripts_nowait == 0) { + + if (dispatch_one_script (handler->current_request)) + return; + + complete_request (handler->current_request); + } else + return; + } else { + /* if the script is a "wait" script, we already tried above to + * dispatch the next script. As we didn't do that, it means we + * just completed the last script of @request and we can continue + * with the next request... + * + * Also, it cannot be that there is another request currently being + * processed because only requests with "wait" scripts can become + * @current_request. As there can only be one "wait" script running + * at any time, it means complete_request() above completed @request. */ + nm_assert (!handler->current_request); + } + + while (next_request (handler, NULL)) { + request = handler->current_request; + + if (dispatch_one_script (request)) + return; + + /* Try to complete the request. It will be either completed + * now, or when all pending "no-wait" scripts return. */ + complete_request (request); + + /* We can immediately start next_request(), because our current + * @request has obviously no more "wait" scripts either. + * Repeat... */ + } } static void @@ -248,9 +396,11 @@ script_watch_cb (GPid pid, gint status, gpointer user_data) g_assert (pid == script->pid); - script->request->script_watch_id = 0; - g_source_remove (script->request->script_timeout_id); - script->request->script_timeout_id = 0; + script->watch_id = 0; + nm_clear_g_source (&script->timeout_id); + script->request->num_scripts_done++; + if (!script->wait) + script->request->num_scripts_nowait--; if (WIFEXITED (status)) { err = WEXITSTATUS (status); @@ -272,15 +422,15 @@ script_watch_cb (GPid pid, gint status, gpointer user_data) } if (script->result == DISPATCH_RESULT_SUCCESS) { - if (script->request->debug) - g_message ("Script '%s' complete", script->script); + _LOG_S_D (script, "complete"); } else { script->result = DISPATCH_RESULT_FAILED; - g_warning ("%s", script->error); + _LOG_S_W (script, "complete: failed with %s", script->error); } g_spawn_close_pid (script->pid); - next_script (script->request); + + complete_script (script); } static gboolean @@ -288,11 +438,13 @@ script_timeout_cb (gpointer user_data) { ScriptInfo *script = user_data; - g_source_remove (script->request->script_watch_id); - script->request->script_watch_id = 0; - script->request->script_timeout_id = 0; + script->timeout_id = 0; + nm_clear_g_source (&script->watch_id); + script->request->num_scripts_done++; + if (!script->wait) + script->request->num_scripts_nowait--; - g_warning ("Script '%s' took too long; killing it.", script->script); + _LOG_S_W (script, "complete: timeout (kill script)"); kill (script->pid, SIGKILL); again: @@ -305,7 +457,9 @@ again: script->result = DISPATCH_RESULT_TIMEOUT; g_spawn_close_pid (script->pid); - g_idle_add (next_script, script->request); + + complete_script (script); + return FALSE; } @@ -366,34 +520,58 @@ check_filename (const char *file_name) #define SCRIPT_TIMEOUT 600 /* 10 minutes */ -static void -dispatch_one_script (Request *request) +static gboolean +script_dispatch (ScriptInfo *script) { GError *error = NULL; gchar *argv[4]; - ScriptInfo *script = g_ptr_array_index (request->scripts, request->idx); + Request *request = script->request; + + if (script->dispatched) + return FALSE; + + script->dispatched = TRUE; argv[0] = script->script; - argv[1] = request->iface ? request->iface : "none"; + argv[1] = request->iface + ? request->iface + : (!strcmp (request->action, NMD_ACTION_HOSTNAME) ? "none" : ""); argv[2] = request->action; argv[3] = NULL; - if (request->debug) - g_message ("Running script '%s'", script->script); + _LOG_S_D (script, "run script%s", script->wait ? "" : " (no-wait)"); - if (g_spawn_async ("/", argv, request->envp, G_SPAWN_DO_NOT_REAP_CHILD, NULL, request, &script->pid, &error)) { - request->script_watch_id = g_child_watch_add (script->pid, (GChildWatchFunc) script_watch_cb, script); - request->script_timeout_id = g_timeout_add_seconds (SCRIPT_TIMEOUT, script_timeout_cb, script); + if (g_spawn_async ("/", argv, request->envp, G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &script->pid, &error)) { + script->watch_id = g_child_watch_add (script->pid, (GChildWatchFunc) script_watch_cb, script); + script->timeout_id = g_timeout_add_seconds (SCRIPT_TIMEOUT, script_timeout_cb, script); + if (!script->wait) + request->num_scripts_nowait++; + return TRUE; } else { - g_warning ("Failed to execute script '%s': (%d) %s", - script->script, error->code, error->message); + _LOG_S_W (script, "complete: failed to execute script: %s (%d)", + error->message, error->code); script->result = DISPATCH_RESULT_EXEC_FAILED; script->error = g_strdup (error->message); + request->num_scripts_done++; g_clear_error (&error); + return FALSE; + } +} - /* Try the next script */ - g_idle_add (next_script, request); +static gboolean +dispatch_one_script (Request *request) +{ + if (request->num_scripts_nowait > 0) + return TRUE; + + while (request->idx < request->scripts->len) { + ScriptInfo *script; + + script = g_ptr_array_index (request->scripts, request->idx++); + if (script_dispatch (script)) + return TRUE; } + return FALSE; } static GSList * @@ -415,7 +593,7 @@ find_scripts (const char *str_action) dirname = NMD_SCRIPT_DIR_DEFAULT; if (!(dir = g_dir_open (dirname, 0, &error))) { - g_message ("Failed to open dispatcher directory '%s': (%d) %s", + g_message ("find-scripts: Failed to open dispatcher directory '%s': (%d) %s", dirname, error->code, error->message); g_error_free (error); return NULL; @@ -434,11 +612,11 @@ find_scripts (const char *str_action) err = stat (path, &st); if (err) - g_warning ("Failed to stat '%s': %d", path, err); + g_warning ("find-scripts: Failed to stat '%s': %d", path, err); else if (S_ISDIR (st.st_mode)) ; /* silently skip. */ else if (!check_permissions (&st, &err_msg)) - g_warning ("Cannot execute '%s': %s", path, err_msg); + g_warning ("find-scripts: Cannot execute '%s': %s", path, err_msg); else { /* success */ sorted = g_slist_insert_sorted (sorted, path, (GCompareFunc) g_strcmp0); @@ -452,6 +630,34 @@ find_scripts (const char *str_action) } static gboolean +script_must_wait (const char *path) +{ + gs_free char *link = NULL; + gs_free char *dir = NULL; + gs_free char *real = NULL; + char *tmp; + + link = g_file_read_link (path, NULL); + if (link) { + if (!g_path_is_absolute (link)) { + dir = g_path_get_dirname (path); + tmp = g_build_path ("/", dir, link, NULL); + g_free (link); + g_free (dir); + link = tmp; + } + + dir = g_path_get_dirname (link); + real = realpath (dir, NULL); + + if (real && !strcmp (real, NMD_SCRIPT_DIR_NO_WAIT)) + return FALSE; + } + + return TRUE; +} + +static gboolean handle_action (NMDBusDispatcher *dbus_dispatcher, GDBusMethodInvocation *context, const char *str_action, @@ -473,21 +679,13 @@ handle_action (NMDBusDispatcher *dbus_dispatcher, GSList *iter; Request *request; char **p; - char *iface = NULL; + guint i, num_nowait = 0; + const char *error_message = NULL; sorted_scripts = find_scripts (str_action); - if (!sorted_scripts) { - GVariant *results; - - results = g_variant_new_array (G_VARIANT_TYPE ("(sus)"), NULL, 0); - g_dbus_method_invocation_return_value (context, g_variant_new ("(@a(sus))", results)); - return TRUE; - } - - quit_timeout_cancel (); - - request = g_malloc0 (sizeof (*request)); + request = g_slice_new0 (Request); + request->request_id = ++request_id_counter; request->handler = h; request->debug = request_debug || debug; request->context = context; @@ -504,31 +702,88 @@ handle_action (NMDBusDispatcher *dbus_dispatcher, vpn_ip_iface, vpn_ip4_props, vpn_ip6_props, - &iface); - - if (request->debug) { - g_message ("------------ Action ID %p '%s' Interface %s Environment ------------", - context, str_action, iface ? iface : "(none)"); - for (p = request->envp; *p; p++) - g_message (" %s", *p); - g_message ("\n"); - } - - request->iface = g_strdup (iface); + &request->iface, + &error_message); request->scripts = g_ptr_array_new_full (5, script_info_free); for (iter = sorted_scripts; iter; iter = g_slist_next (iter)) { - ScriptInfo *s = g_malloc0 (sizeof (*s)); + ScriptInfo *s; + + s = g_slice_new0 (ScriptInfo); s->request = request; s->script = iter->data; + s->wait = script_must_wait (s->script); g_ptr_array_add (request->scripts, s); } g_slist_free (sorted_scripts); - if (h->current_request) - g_queue_push_tail (h->pending_requests, request); - else - start_request (request); + _LOG_R_I (request, "new request (%u scripts)", request->scripts->len); + if ( _LOG_R_D_enabled (request) + && request->envp) { + for (p = request->envp; *p; p++) + _LOG_R_D (request, "environment: %s", *p); + } + + if (error_message || request->scripts->len == 0) { + GVariant *results; + + if (error_message) + _LOG_R_W (request, "completed: invalid request: %s", error_message); + else + _LOG_R_I (request, "completed: no scripts"); + + results = g_variant_new_array (G_VARIANT_TYPE ("(sus)"), NULL, 0); + g_dbus_method_invocation_return_value (context, g_variant_new ("(@a(sus))", results)); + request->num_scripts_done = request->scripts->len; + request_free (request); + return TRUE; + } + + nm_clear_g_source (&quit_id); + + h->num_requests_pending++; + + for (i = 0; i < request->scripts->len; i++) { + ScriptInfo *s = g_ptr_array_index (request->scripts, i); + + if (!s->wait) { + script_dispatch (s); + num_nowait++; + } + } + + if (num_nowait < request->scripts->len) { + /* The request has at least one wait script. + * Try next_request() to schedule the request for + * execution. This either enqueues the request or + * sets it as h->current_request. */ + if (next_request (h, request)) { + /* @request is now @current_request. Go ahead and + * schedule the first wait script. */ + if (!dispatch_one_script (request)) { + /* If that fails, we might be already finished with the + * request. Try complete_request(). */ + complete_request (request); + + if (next_request (h, NULL)) { + /* As @request was successfully scheduled as next_request(), there is no + * other request in queue that can be scheduled afterwards. Assert against + * that, but call next_request() to clear current_request. */ + g_assert_not_reached (); + } + } + } + } else { + /* The request contains only no-wait scripts. Try to complete + * the request right away (we might have failed to schedule any + * of the scripts). It will be either completed now, or later + * when the pending scripts return. + * We don't enqueue it to h->requests_waiting. + * There is no need to handle next_request(), because @request is + * not the current request anyway and does not interfere with requests + * that have any "wait" scripts. */ + complete_request (request); + } return TRUE; } @@ -571,7 +826,7 @@ log_handler (const gchar *log_domain, const gchar *message, gpointer ignored) { - int syslog_priority; + int syslog_priority; switch (log_level) { case G_LOG_LEVEL_ERROR: @@ -603,7 +858,7 @@ static void logging_setup (void) { openlog (G_LOG_DOMAIN, LOG_CONS, LOG_DAEMON); - g_log_set_handler (G_LOG_DOMAIN, + g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION, log_handler, NULL); @@ -645,16 +900,14 @@ main (int argc, char **argv) g_option_context_add_main_entries (opt_ctx, entries, NULL); if (!g_option_context_parse (opt_ctx, &argc, &argv, &error)) { - g_warning ("%s\n", error->message); + g_warning ("Error parsing command line arguments: %s", error->message); g_error_free (error); return 1; } g_option_context_free (opt_ctx); -#if !GLIB_CHECK_VERSION (2, 35, 0) - g_type_init (); -#endif + nm_g_type_init (); g_unix_signal_add (SIGTERM, signal_handler, GINT_TO_POINTER (SIGTERM)); g_unix_signal_add (SIGINT, signal_handler, GINT_TO_POINTER (SIGINT)); @@ -691,12 +944,11 @@ main (int argc, char **argv) NULL, NULL); g_object_unref (bus); - if (!persist) - quit_id = g_timeout_add_seconds (10, quit_timeout_cb, NULL); + quit_timeout_reschedule (); g_main_loop_run (loop); - g_queue_free (handler->pending_requests); + g_queue_free (handler->requests_waiting); g_object_unref (handler); if (!debug) diff --git a/callouts/tests/Makefile.am b/callouts/tests/Makefile.am index 394fedab..ee3f647d 100644 --- a/callouts/tests/Makefile.am +++ b/callouts/tests/Makefile.am @@ -1,8 +1,8 @@ if ENABLE_TESTS AM_CPPFLAGS = \ - -I$(top_srcdir)/include \ - -I$(top_builddir)/include \ + -I$(top_srcdir)/shared \ + -I$(top_builddir)/shared \ -I$(top_srcdir)/libnm-core \ -I$(top_builddir)/libnm-core \ -I$(top_srcdir)/callouts \ @@ -10,8 +10,7 @@ AM_CPPFLAGS = \ -DNETWORKMANAGER_COMPILATION \ -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ -DSRCDIR=\"$(abs_srcdir)\" \ - $(GLIB_CFLAGS) \ - $(DBUS_CFLAGS) + $(GLIB_CFLAGS) noinst_PROGRAMS = \ test-dispatcher-envp @@ -24,8 +23,7 @@ test_dispatcher_envp_SOURCES = \ test_dispatcher_envp_LDADD = \ $(top_builddir)/libnm/libnm.la \ $(top_builddir)/callouts/libtest-dispatcher-envp.la \ - $(GLIB_LIBS) \ - $(DBUS_LIBS) + $(GLIB_LIBS) ########################################### @@ -36,6 +34,7 @@ endif EXTRA_DIST= \ dispatcher-down \ + dispatcher-external \ dispatcher-up \ dispatcher-vpn-down \ dispatcher-vpn-up diff --git a/callouts/tests/Makefile.in b/callouts/tests/Makefile.in index f3cb7386..eeaf70d6 100644 --- a/callouts/tests/Makefile.in +++ b/callouts/tests/Makefile.in @@ -121,7 +121,7 @@ am__DEPENDENCIES_1 = @ENABLE_TESTS_TRUE@test_dispatcher_envp_DEPENDENCIES = \ @ENABLE_TESTS_TRUE@ $(top_builddir)/libnm/libnm.la \ @ENABLE_TESTS_TRUE@ $(top_builddir)/callouts/libtest-dispatcher-envp.la \ -@ENABLE_TESTS_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +@ENABLE_TESTS_TRUE@ $(am__DEPENDENCIES_1) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent @@ -408,7 +408,6 @@ BLUEZ5_LIBS = @BLUEZ5_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ -CKDB_PATH = @CKDB_PATH@ CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ @@ -420,8 +419,6 @@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DBUS_CFLAGS = @DBUS_CFLAGS@ -DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@ -DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@ DBUS_LIBS = @DBUS_LIBS@ DBUS_SYS_DIR = @DBUS_SYS_DIR@ DEFS = @DEFS@ @@ -431,6 +428,7 @@ DHCPCD_PATH = @DHCPCD_PATH@ DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@ DLLTOOL = @DLLTOOL@ DNSMASQ_PATH = @DNSMASQ_PATH@ +DNSSEC_TRIGGER_SCRIPT = @DNSSEC_TRIGGER_SCRIPT@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ @@ -485,16 +483,13 @@ 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@ +LIBAUDIT_CFLAGS = @LIBAUDIT_CFLAGS@ +LIBAUDIT_LIBS = @LIBAUDIT_LIBS@ LIBDL = @LIBDL@ -LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ -LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ -LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ @@ -531,6 +526,8 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ +NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ NM_MICRO_VERSION = @NM_MICRO_VERSION@ NM_MINOR_VERSION = @NM_MINOR_VERSION@ @@ -559,7 +556,6 @@ POLKIT_LIBS = @POLKIT_LIBS@ POSUB = @POSUB@ PPPD_PATH = @PPPD_PATH@ PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ -PPPOE_PATH = @PPPOE_PATH@ QT_CFLAGS = @QT_CFLAGS@ QT_LIBS = @QT_LIBS@ RANLIB = @RANLIB@ @@ -574,6 +570,8 @@ 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_JOURNAL_CFLAGS = @SYSTEMD_JOURNAL_CFLAGS@ +SYSTEMD_JOURNAL_LIBS = @SYSTEMD_JOURNAL_LIBS@ SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@ SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ @@ -634,6 +632,7 @@ mkdir_p = @mkdir_p@ nmbinary = @nmbinary@ nmconfdir = @nmconfdir@ nmdatadir = @nmdatadir@ +nmlibdir = @nmlibdir@ nmrundir = @nmrundir@ nmstatedir = @nmstatedir@ oldincludedir = @oldincludedir@ @@ -641,6 +640,7 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -657,8 +657,8 @@ with_netconfig = @with_netconfig@ with_resolvconf = @with_resolvconf@ with_valgrind = @with_valgrind@ @ENABLE_TESTS_TRUE@AM_CPPFLAGS = \ -@ENABLE_TESTS_TRUE@ -I$(top_srcdir)/include \ -@ENABLE_TESTS_TRUE@ -I$(top_builddir)/include \ +@ENABLE_TESTS_TRUE@ -I$(top_srcdir)/shared \ +@ENABLE_TESTS_TRUE@ -I$(top_builddir)/shared \ @ENABLE_TESTS_TRUE@ -I$(top_srcdir)/libnm-core \ @ENABLE_TESTS_TRUE@ -I$(top_builddir)/libnm-core \ @ENABLE_TESTS_TRUE@ -I$(top_srcdir)/callouts \ @@ -666,8 +666,7 @@ with_valgrind = @with_valgrind@ @ENABLE_TESTS_TRUE@ -DNETWORKMANAGER_COMPILATION \ @ENABLE_TESTS_TRUE@ -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ @ENABLE_TESTS_TRUE@ -DSRCDIR=\"$(abs_srcdir)\" \ -@ENABLE_TESTS_TRUE@ $(GLIB_CFLAGS) \ -@ENABLE_TESTS_TRUE@ $(DBUS_CFLAGS) +@ENABLE_TESTS_TRUE@ $(GLIB_CFLAGS) ####### dispatcher envp ####### @@ -677,11 +676,11 @@ with_valgrind = @with_valgrind@ @ENABLE_TESTS_TRUE@test_dispatcher_envp_LDADD = \ @ENABLE_TESTS_TRUE@ $(top_builddir)/libnm/libnm.la \ @ENABLE_TESTS_TRUE@ $(top_builddir)/callouts/libtest-dispatcher-envp.la \ -@ENABLE_TESTS_TRUE@ $(GLIB_LIBS) \ -@ENABLE_TESTS_TRUE@ $(DBUS_LIBS) +@ENABLE_TESTS_TRUE@ $(GLIB_LIBS) EXTRA_DIST = \ dispatcher-down \ + dispatcher-external \ dispatcher-up \ dispatcher-vpn-down \ dispatcher-vpn-up diff --git a/callouts/tests/dispatcher-down b/callouts/tests/dispatcher-down index da97d3f6..f766595c 100644 --- a/callouts/tests/dispatcher-down +++ b/callouts/tests/dispatcher-down @@ -14,6 +14,7 @@ path=/org/freedesktop/NetworkManager/Devices/0 [env] PATH= CONNECTION_UUID=3fd2a33a-d81b-423f-ae99-e6baba742311 +CONNECTION_DBUS_PATH=/org/freedesktop/NetworkManager/Connections/5 CONNECTION_ID=Random Connection CONNECTION_FILENAME=/callouts/tests/dispatcher-down DEVICE_IFACE=wlan0 diff --git a/callouts/tests/dispatcher-external b/callouts/tests/dispatcher-external new file mode 100644 index 00000000..5430bec2 --- /dev/null +++ b/callouts/tests/dispatcher-external @@ -0,0 +1,33 @@ +[main] +action=up +expected-iface=virbr0 +uuid=92bbc2fb-7304-46be-8ebb-6093dbe19a6a +id=virbr0 +external=1 + +[device] +state=100 +ip-interface=virbr0 +type=13 +interface=virbr0 +path=/org/freedesktop/NetworkManager/Devices/0 + +[ip4] +addresses=192.168.122.1/24 0.0.0.0 +domains= +gateway=0.0.0.0 + +[env] +PATH= +CONNECTION_UUID=92bbc2fb-7304-46be-8ebb-6093dbe19a6a +CONNECTION_DBUS_PATH=/org/freedesktop/NetworkManager/Connections/5 +CONNECTION_FILENAME=/callouts/tests/dispatcher-external +CONNECTION_ID=virbr0 +CONNECTION_EXTERNAL=1 +DEVICE_IFACE=virbr0 +DEVICE_IP_IFACE=virbr0 +IP4_NUM_ADDRESSES=1 +IP4_ADDRESS_0=192.168.122.1/24 0.0.0.0 +IP4_GATEWAY=0.0.0.0 +IP4_NUM_ROUTES=0 + diff --git a/callouts/tests/dispatcher-up b/callouts/tests/dispatcher-up index 78cfadad..463409e2 100644 --- a/callouts/tests/dispatcher-up +++ b/callouts/tests/dispatcher-up @@ -33,6 +33,7 @@ domains=hsd1.mn.comcast.net. [env] PATH= CONNECTION_UUID=3fd2a33a-d81b-423f-ae99-e6baba742311 +CONNECTION_DBUS_PATH=/org/freedesktop/NetworkManager/Connections/5 CONNECTION_ID=Random Connection CONNECTION_FILENAME=/callouts/tests/dispatcher-up DEVICE_IFACE=wlan0 diff --git a/callouts/tests/dispatcher-vpn-down b/callouts/tests/dispatcher-vpn-down index eb4dc2ca..18267f84 100644 --- a/callouts/tests/dispatcher-vpn-down +++ b/callouts/tests/dispatcher-vpn-down @@ -33,6 +33,7 @@ domains=hsd1.mn.comcast.net. [env] PATH= CONNECTION_UUID=355653c0-34d3-4777-ad25-f9a498b7ef8e +CONNECTION_DBUS_PATH=/org/freedesktop/NetworkManager/Connections/5 CONNECTION_ID=Random Connection CONNECTION_FILENAME=/callouts/tests/dispatcher-vpn-down DEVICE_IFACE=wlan0 diff --git a/callouts/tests/dispatcher-vpn-up b/callouts/tests/dispatcher-vpn-up index 8ae78a31..181ecb53 100644 --- a/callouts/tests/dispatcher-vpn-up +++ b/callouts/tests/dispatcher-vpn-up @@ -33,6 +33,7 @@ domains=hsd1.mn.comcast.net. [env] PATH= CONNECTION_UUID=355653c0-34d3-4777-ad25-f9a498b7ef8e +CONNECTION_DBUS_PATH=/org/freedesktop/NetworkManager/Connections/5 CONNECTION_ID=Random Connection CONNECTION_FILENAME=/callouts/tests/dispatcher-vpn-up DEVICE_IFACE=wlan0 diff --git a/callouts/tests/test-dispatcher-envp.c b/callouts/tests/test-dispatcher-envp.c index 6ae3fab0..27f088f6 100644 --- a/callouts/tests/test-dispatcher-envp.c +++ b/callouts/tests/test-dispatcher-envp.c @@ -23,13 +23,14 @@ #include <arpa/inet.h> #include <stdlib.h> #include <string.h> -#include <glib.h> -#include <glib-object.h> +#include "nm-default.h" #include "nm-core-internal.h" #include "nm-dispatcher-utils.h" #include "nm-dispatcher-api.h" +#include "nm-test-utils.h" + /*******************************************/ static gboolean @@ -81,13 +82,21 @@ parse_main (GKeyFile *kf, g_variant_builder_init (&props, G_VARIANT_TYPE ("a{sv}")); g_variant_builder_add (&props, "{sv}", - "connection-path", + NMD_CONNECTION_PROPS_PATH, g_variant_new_object_path ("/org/freedesktop/NetworkManager/Connections/5")); + /* Strip out the non-fixed portion of the filename */ filename = strstr (filename, "/callouts"); g_variant_builder_add (&props, "{sv}", "filename", g_variant_new_string (filename)); + + if (g_key_file_get_boolean (kf, "main", "external", NULL)) { + g_variant_builder_add (&props, "{sv}", + "external", + g_variant_new_boolean (TRUE)); + } + *out_con_props = g_variant_builder_end (&props); return TRUE; @@ -449,6 +458,7 @@ test_generic (const char *file, const char *override_vpn_ip_iface) char *expected_iface = NULL; char *action = NULL; char *out_iface = NULL; + const char *error_message = NULL; GHashTable *expected_env = NULL; GError *error = NULL; gboolean success; @@ -488,7 +498,13 @@ test_generic (const char *file, const char *override_vpn_ip_iface) override_vpn_ip_iface ? override_vpn_ip_iface : vpn_ip_iface, vpn_ip4_props, vpn_ip6_props, - &out_iface); + &out_iface, + &error_message); + + g_assert ((!denv && error_message) || (denv && !error_message)); + + if (error_message) + g_warning ("%s", error_message); /* Print out environment for now */ #ifdef DEBUG @@ -581,6 +597,12 @@ test_vpn_down (void) } static void +test_external (void) +{ + test_generic ("dispatcher-external", NULL); +} + +static void test_up_empty_vpn_iface (void) { /* Test that an empty VPN iface variable, like is passed through D-Bus @@ -591,19 +613,18 @@ test_up_empty_vpn_iface (void) /*******************************************/ +NMTST_DEFINE (); + int main (int argc, char **argv) { - g_test_init (&argc, &argv, NULL); - -#if !GLIB_CHECK_VERSION (2, 35, 0) - g_type_init (); -#endif + nmtst_init (&argc, &argv, TRUE); g_test_add_func ("/dispatcher/up", test_up); g_test_add_func ("/dispatcher/down", test_down); g_test_add_func ("/dispatcher/vpn_up", test_vpn_up); g_test_add_func ("/dispatcher/vpn_down", test_vpn_down); + g_test_add_func ("/dispatcher/external", test_external); g_test_add_func ("/dispatcher/up_empty_vpn_iface", test_up_empty_vpn_iface); |