diff options
author | Lubomir Rintel <lkundrak@v3.sk> | 2019-04-30 15:53:59 +0200 |
---|---|---|
committer | Lubomir Rintel <lkundrak@v3.sk> | 2019-04-30 15:53:59 +0200 |
commit | 7574b722a6bb803679f2d7a603a24f175a0225fa (patch) | |
tree | ca8dcaddfa8ec232da4f491d7f37a9ada3ca78e2 | |
parent | 5aff6fc83b65b400b010163563bc4765def298b1 (diff) | |
parent | 14eaf6a40b2ccf2b0daedbbaf0730287fd6a4d3b (diff) | |
download | NetworkManager-7574b722a6bb803679f2d7a603a24f175a0225fa.tar.gz |
merge: branch 'lr/dispatcher-split'
https://github.com/NetworkManager/NetworkManager/pull/253
-rw-r--r-- | Makefile.am | 15 | ||||
-rw-r--r-- | contrib/fedora/rpm/NetworkManager.spec | 9 | ||||
-rw-r--r-- | dispatcher/nm-dispatcher.c | 103 | ||||
-rw-r--r-- | shared/nm-libnm-core-aux/nm-dispatcher-api.h | 5 | ||||
-rw-r--r-- | src/nm-dispatcher.c | 149 | ||||
-rwxr-xr-x | tools/meson-post-install.sh | 3 |
6 files changed, 91 insertions, 193 deletions
diff --git a/Makefile.am b/Makefile.am index 1bba093e25..e86dbcd702 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3891,14 +3891,15 @@ dispatcher/org.freedesktop.nm_dispatcher.service: $(srcdir)/dispatcher/org.freed dbusactivation_DATA += dispatcher/org.freedesktop.nm_dispatcher.service CLEANFILES += dispatcher/org.freedesktop.nm_dispatcher.service - -dispatcherdir=$(sysconfdir)/NetworkManager/dispatcher.d - install-data-hook-dispatcher: - $(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 + $(mkinstalldirs) -m 0755 $(DESTDIR)$(nmconfdir)/dispatcher.d + $(mkinstalldirs) -m 0755 $(DESTDIR)$(nmconfdir)/dispatcher.d/pre-down.d + $(mkinstalldirs) -m 0755 $(DESTDIR)$(nmconfdir)/dispatcher.d/pre-up.d + $(mkinstalldirs) -m 0755 $(DESTDIR)$(nmconfdir)/dispatcher.d/no-wait.d + $(mkinstalldirs) -m 0755 $(DESTDIR)$(nmlibdir)/dispatcher.d + $(mkinstalldirs) -m 0755 $(DESTDIR)$(nmlibdir)/dispatcher.d/pre-down.d + $(mkinstalldirs) -m 0755 $(DESTDIR)$(nmlibdir)/dispatcher.d/pre-up.d + $(mkinstalldirs) -m 0755 $(DESTDIR)$(nmlibdir)/dispatcher.d/no-wait.d install_data_hook += install-data-hook-dispatcher diff --git a/contrib/fedora/rpm/NetworkManager.spec b/contrib/fedora/rpm/NetworkManager.spec index c237866a87..39252c1010 100644 --- a/contrib/fedora/rpm/NetworkManager.spec +++ b/contrib/fedora/rpm/NetworkManager.spec @@ -242,6 +242,8 @@ BuildRequires: libubsan %endif %endif +Provides: %{name}-dispatcher%{?_isa} = %{epoch}:%{version}-%{release} + # NetworkManager uses various parts of systemd-networkd internally, including # DHCP client, IPv4 Link-Local address negotiation or LLDP support. # This provide is essentially here so that NetworkManager shows on Security @@ -824,13 +826,15 @@ fi %{_sbindir}/%{name} %{_bindir}/nmcli %{_datadir}/bash-completion/completions/nmcli -%dir %{_sysconfdir}/%{name}/ +%dir %{_sysconfdir}/%{name} +%dir %{_sysconfdir}/%{name}/conf.d %dir %{_sysconfdir}/%{name}/dispatcher.d %dir %{_sysconfdir}/%{name}/dispatcher.d/pre-down.d %dir %{_sysconfdir}/%{name}/dispatcher.d/pre-up.d %dir %{_sysconfdir}/%{name}/dispatcher.d/no-wait.d %dir %{_sysconfdir}/%{name}/dnsmasq.d %dir %{_sysconfdir}/%{name}/dnsmasq-shared.d +%dir %{_sysconfdir}/%{name}/system-connections %config(noreplace) %{_sysconfdir}/%{name}/NetworkManager.conf %{_bindir}/nm-online %{_libexecdir}/nm-ifup @@ -847,8 +851,6 @@ fi %if %{with nmtui} %exclude %{_mandir}/man1/nmtui* %endif -%dir %{_sysconfdir}/%{name} -%dir %{_sysconfdir}/%{name}/conf.d %dir %{nmlibdir} %dir %{nmlibdir}/conf.d %dir %{nmlibdir}/VPN @@ -857,7 +859,6 @@ fi %{_mandir}/man7/nmcli-examples.7* %{_mandir}/man8/* %dir %{_localstatedir}/lib/NetworkManager -%dir %{_sysconfdir}/NetworkManager/system-connections %dir %{_sysconfdir}/sysconfig/network-scripts %{_datadir}/dbus-1/system-services/org.freedesktop.nm_dispatcher.service %{_datadir}/polkit-1/actions/*.policy diff --git a/dispatcher/nm-dispatcher.c b/dispatcher/nm-dispatcher.c index fe6eaa17ad..231a3f9a83 100644 --- a/dispatcher/nm-dispatcher.c +++ b/dispatcher/nm-dispatcher.c @@ -466,12 +466,6 @@ check_permissions (struct stat *s, const char **out_error_msg) g_return_val_if_fail (out_error_msg != NULL, FALSE); g_return_val_if_fail (*out_error_msg == NULL, FALSE); - /* Only accept regular files */ - if (!S_ISREG (s->st_mode)) { - *out_error_msg = "not a regular file."; - return FALSE; - } - /* Only accept files owned by root */ if (s->st_uid != 0) { *out_error_msg = "not owned by root."; @@ -573,59 +567,104 @@ dispatch_one_script (Request *request) return FALSE; } -static GSList * -find_scripts (const char *str_action) +static int +_compare_basenames (gconstpointer a, gconstpointer b) +{ + const char *basename_a = strrchr (a, '/'); + const char *basename_b = strrchr (b, '/'); + int ret; + + nm_assert (basename_a); + nm_assert (basename_b); + + ret = strcmp (++basename_a, ++basename_b); + if (ret) + return ret; + + nm_assert_not_reached (); + return 0; +} + +static void +_find_scripts (GHashTable *scripts, const char *base, const char *subdir) { - GDir *dir; const char *filename; - GSList *sorted = NULL; + gs_free char *dirname = NULL; GError *error = NULL; - const char *dirname; + GDir *dir; - if ( strcmp (str_action, NMD_ACTION_PRE_UP) == 0 - || strcmp (str_action, NMD_ACTION_VPN_PRE_UP) == 0) - dirname = NMD_SCRIPT_DIR_PRE_UP; - else if ( strcmp (str_action, NMD_ACTION_PRE_DOWN) == 0 - || strcmp (str_action, NMD_ACTION_VPN_PRE_DOWN) == 0) - dirname = NMD_SCRIPT_DIR_PRE_DOWN; - else - dirname = NMD_SCRIPT_DIR_DEFAULT; + dirname = g_build_filename (base, "dispatcher.d", subdir, NULL); if (!(dir = g_dir_open (dirname, 0, &error))) { g_message ("find-scripts: Failed to open dispatcher directory '%s': %s", dirname, error->message); g_error_free (error); - return NULL; + return; } while ((filename = g_dir_read_name (dir))) { - char *path; + if (!check_filename (filename)) + continue; + + g_hash_table_insert (scripts, + g_strdup (filename), + g_build_filename (dirname, filename, NULL)); + } + + g_dir_close (dir); +} + +static GSList * +find_scripts (const char *str_action) +{ + gs_unref_hashtable GHashTable *scripts = NULL; + GSList *script_list = NULL; + GHashTableIter iter; + const char *subdir = NULL; + char *path; + char *filename; + + if ( strcmp (str_action, NMD_ACTION_PRE_UP) == 0 + || strcmp (str_action, NMD_ACTION_VPN_PRE_UP) == 0) + subdir = "pre-up.d"; + else if ( strcmp (str_action, NMD_ACTION_PRE_DOWN) == 0 + || strcmp (str_action, NMD_ACTION_VPN_PRE_DOWN) == 0) + subdir = "pre-down.d"; + + scripts = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + + _find_scripts (scripts, NMLIBDIR, subdir); + _find_scripts (scripts, NMCONFDIR, subdir); + + g_hash_table_iter_init (&iter, scripts); + while (g_hash_table_iter_next (&iter, (gpointer *) &filename, (gpointer *) &path)) { struct stat st; + char *link_target; int err; const char *err_msg = NULL; - if (!check_filename (filename)) + link_target = g_file_read_link (path, NULL); + if (g_strcmp0 (link_target, "/dev/null") == 0) { + g_free (link_target); continue; - - path = g_build_filename (dirname, filename, NULL); + } + g_free (link_target); err = stat (path, &st); if (err) g_warning ("find-scripts: Failed to stat '%s': %d", path, err); - else if (S_ISDIR (st.st_mode)) + else if (!S_ISREG (st.st_mode)) ; /* silently skip. */ else if (!check_permissions (&st, &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); - path = NULL; + script_list = g_slist_prepend (script_list, g_strdup (path)); + continue; } - g_free (path); } - g_dir_close (dir); - return sorted; + return g_slist_sort (script_list, _compare_basenames); } static gboolean @@ -636,6 +675,7 @@ script_must_wait (const char *path) gs_free char *real = NULL; char *tmp; + link = g_file_read_link (path, NULL); if (link) { if (!g_path_is_absolute (link)) { @@ -648,8 +688,7 @@ script_must_wait (const char *path) dir = g_path_get_dirname (link); real = realpath (dir, NULL); - - if (real && !strcmp (real, NMD_SCRIPT_DIR_NO_WAIT)) + if (real && !g_str_has_suffix (real, "/no-wait.d")) return FALSE; } diff --git a/shared/nm-libnm-core-aux/nm-dispatcher-api.h b/shared/nm-libnm-core-aux/nm-dispatcher-api.h index e6d0d92f85..2da5bd88f1 100644 --- a/shared/nm-libnm-core-aux/nm-dispatcher-api.h +++ b/shared/nm-libnm-core-aux/nm-dispatcher-api.h @@ -21,11 +21,6 @@ #ifndef __NM_DISPACHER_API_H__ #define __NM_DISPACHER_API_H__ -#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" -#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" #define NM_DISPATCHER_DBUS_PATH "/org/freedesktop/nm_dispatcher" diff --git a/src/nm-dispatcher.c b/src/nm-dispatcher.c index d656edc844..8ac18ed44a 100644 --- a/src/nm-dispatcher.c +++ b/src/nm-dispatcher.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) 2004 - 2017 Red Hat, Inc. + * Copyright (C) 2004 - 2018 Red Hat, Inc. * Copyright (C) 2005 - 2008 Novell, Inc. */ @@ -47,42 +47,6 @@ static GDBusProxy *dispatcher_proxy; static GHashTable *requests = NULL; -typedef struct { - GFileMonitor *monitor; - const char *const description; - const char *const dir; - const guint16 dir_len; - char has_scripts; -} Monitor; - -enum { - MONITOR_INDEX_DEFAULT, - MONITOR_INDEX_PRE_UP, - MONITOR_INDEX_PRE_DOWN, -}; - -static Monitor monitors[3] = { -#define MONITORS_INIT_SET(INDEX, USE, SCRIPT_DIR) [INDEX] = { .dir_len = NM_STRLEN (SCRIPT_DIR), .dir = SCRIPT_DIR, .description = ("" USE), .has_scripts = TRUE } - MONITORS_INIT_SET (MONITOR_INDEX_DEFAULT, "default", NMD_SCRIPT_DIR_DEFAULT), - MONITORS_INIT_SET (MONITOR_INDEX_PRE_UP, "pre-up", NMD_SCRIPT_DIR_PRE_UP), - MONITORS_INIT_SET (MONITOR_INDEX_PRE_DOWN, "pre-down", NMD_SCRIPT_DIR_PRE_DOWN), -}; - -static const Monitor* -_get_monitor_by_action (NMDispatcherAction action) -{ - switch (action) { - case NM_DISPATCHER_ACTION_PRE_UP: - case NM_DISPATCHER_ACTION_VPN_PRE_UP: - return &monitors[MONITOR_INDEX_PRE_UP]; - case NM_DISPATCHER_ACTION_PRE_DOWN: - case NM_DISPATCHER_ACTION_VPN_PRE_DOWN: - return &monitors[MONITOR_INDEX_PRE_DOWN]; - default: - return &monitors[MONITOR_INDEX_DEFAULT]; - } -} - static void dump_proxy_to_props (NMProxyConfig *proxy, GVariantBuilder *builder) { @@ -379,7 +343,6 @@ dispatcher_results_process (guint request_id, NMDispatcherAction action, GVarian { const char *script, *err; guint32 result; - const Monitor *monitor = _get_monitor_by_action (action); g_return_if_fail (results != NULL); @@ -389,31 +352,14 @@ dispatcher_results_process (guint request_id, NMDispatcherAction action, GVarian } while (g_variant_iter_next (results, "(&su&s)", &script, &result, &err)) { - const char *script_validation_msg = ""; - - if (!*script) { - script_validation_msg = " (path is NULL)"; - script = "(unknown)"; - } else if (!strncmp (script, monitor->dir, monitor->dir_len) /* check: prefixed by script directory */ - && script[monitor->dir_len] == '/' && script[monitor->dir_len+1] /* check: with additional "/?" */ - && !strchr (&script[monitor->dir_len+1], '/')) { /* check: and no further '/' */ - /* we expect the script to lie inside monitor->dir. If it does, - * strip the directory name. Otherwise show the full path and a warning. */ - script += monitor->dir_len + 1; - } else - script_validation_msg = " (unexpected path)"; - if (result == DISPATCH_RESULT_SUCCESS) { - _LOGD ("(%u) %s succeeded%s", - request_id, - script, script_validation_msg); + _LOGD ("(%u) %s succeeded", request_id, script); } else { - _LOGW ("(%u) %s failed (%s): %s%s", + _LOGW ("(%u) %s failed (%s): %s", request_id, script, dispatch_result_to_string (result), - err, - script_validation_msg); + err); } } } @@ -475,18 +421,6 @@ action_to_string (NMDispatcherAction action) } static gboolean -dispatcher_idle_cb (gpointer user_data) -{ - DispatchInfo *info = user_data; - - info->idle_id = 0; - if (info->callback) - info->callback (info->request_id, info->user_data); - dispatcher_info_cleanup (info); - return G_SOURCE_REMOVE; -} - -static gboolean _dispatcher_call (NMDispatcherAction action, gboolean blocking, NMDevice *device, @@ -551,21 +485,6 @@ _dispatcher_call (NMDispatcherAction action, : (callback ? " (with callback)" : "")); } - if (!_get_monitor_by_action(action)->has_scripts) { - if (blocking == FALSE && (out_call_id || callback)) { - info = g_malloc0 (sizeof (*info)); - info->action = action; - info->request_id = reqid; - info->callback = callback; - info->user_data = user_data; - info->idle_id = g_idle_add (dispatcher_idle_cb, info); - _LOGD ("(%u) simulate request; no scripts in %s", reqid, _get_monitor_by_action(action)->dir); - } else - _LOGD ("(%u) ignoring request; no scripts in %s", reqid, _get_monitor_by_action(action)->dir); - success = TRUE; - goto done; - } - if (applied_connection) connection_dict = nm_connection_to_dbus (applied_connection, NM_CONNECTION_SERIALIZE_NO_SECRETS); else @@ -698,7 +617,6 @@ _dispatcher_call (NMDispatcherAction action, g_variant_unref (device_dhcp4_props); g_variant_unref (device_dhcp6_props); -done: if (success && info) { /* Track the request in case of cancelation */ g_hash_table_insert (requests, GUINT_TO_POINTER (info->request_id), info); @@ -931,70 +849,11 @@ nm_dispatcher_call_cancel (guint call_id) } } -static void -dispatcher_dir_changed (GFileMonitor *monitor, - GFile *file, - GFile *other_file, - GFileMonitorEvent event_type, - Monitor *item) -{ - const char *name; - char *full_name; - GDir *dir; - GError *error = NULL; - - dir = g_dir_open (item->dir, 0, &error); - if (dir) { - int errsv = 0; - - item->has_scripts = FALSE; - errno = 0; - while (!item->has_scripts - && (name = g_dir_read_name (dir))) { - full_name = g_build_filename (item->dir, name, NULL); - item->has_scripts = g_file_test (full_name, G_FILE_TEST_IS_EXECUTABLE); - g_free (full_name); - } - errsv = errno; - g_dir_close (dir); - if (item->has_scripts) - _LOGD ("%s script directory '%s' has scripts", item->description, item->dir); - else if (errsv == 0) - _LOGD ("%s script directory '%s' has no scripts", item->description, item->dir); - else { - _LOGD ("%s script directory '%s' error reading (%s)", item->description, item->dir, nm_strerror_native (errsv)); - item->has_scripts = TRUE; - } - } else { - if (g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) { - _LOGD ("%s script directory '%s' does not exist", item->description, item->dir); - item->has_scripts = FALSE; - } else { - _LOGD ("%s script directory '%s' error (%s)", item->description, item->dir, error->message); - item->has_scripts = TRUE; - } - g_error_free (error); - } - -} - void nm_dispatcher_init (void) { - GFile *file; - guint i; GError *error = NULL; - for (i = 0; i < G_N_ELEMENTS (monitors); i++) { - file = g_file_new_for_path (monitors[i].dir); - monitors[i].monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL); - if (monitors[i].monitor) { - g_signal_connect (monitors[i].monitor, "changed", G_CALLBACK (dispatcher_dir_changed), &monitors[i]); - dispatcher_dir_changed (monitors[i].monitor, file, NULL, 0, &monitors[i]); - } - g_object_unref (file); - } - dispatcher_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, diff --git a/tools/meson-post-install.sh b/tools/meson-post-install.sh index 2037c0ceb4..d2474f475d 100755 --- a/tools/meson-post-install.sh +++ b/tools/meson-post-install.sh @@ -27,6 +27,9 @@ for dir in "${pkgconfdir}/conf.d" \ "${pkgconfdir}/dnsmasq.d" \ "${pkgconfdir}/dnsmasq-shared.d" \ "${pkglibdir}/conf.d" \ + "${pkglibdir}/dispatcher.d/no-wait.d" \ + "${pkglibdir}/dispatcher.d/pre-down.d" \ + "${pkglibdir}/dispatcher.d/pre-up.d" \ "${pkglibdir}/VPN"; do mkdir -p "${DESTDIR}${dir}" chmod 0755 "${DESTDIR}${dir}" |