From f79d62692ec4fe5ba21bbeab26286b2a3b250fdd Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 17 Dec 2014 08:50:05 -0500 Subject: [PATCH] ifcfg-rh: allow handling complex routing rules via dispatcher (rh #1160013) If a connection has an associated "rule-NAME" or "rule6-NAME" file, don't try to read in the routes, since NetworkManager won't be able to parse them correctly. Instead, log a warning that they will need to be applied via a dispatcher script, and provide a script that would do that in examples/dispatcher/. --- contrib/fedora/rpm/NetworkManager.spec | 7 +++++ examples/dispatcher/10-ifcfg-rh-routes.sh | 21 +++++++++++++++ examples/dispatcher/Makefile.am | 1 + src/settings/plugins/ifcfg-rh/common.h | 2 ++ .../plugins/ifcfg-rh/nm-ifcfg-connection.c | 23 ++++++++++++++++ src/settings/plugins/ifcfg-rh/reader.c | 27 +++++++------------ src/settings/plugins/ifcfg-rh/utils.c | 24 +++++++++++++++++ src/settings/plugins/ifcfg-rh/utils.h | 1 + src/settings/plugins/ifcfg-rh/writer.c | 6 +++++ 9 files changed, 95 insertions(+), 17 deletions(-) create mode 100755 examples/dispatcher/10-ifcfg-rh-routes.sh diff --git a/contrib/fedora/rpm/NetworkManager.spec b/contrib/fedora/rpm/NetworkManager.spec index 241ab4a96..70884ffa0 100644 --- a/contrib/fedora/rpm/NetworkManager.spec +++ b/contrib/fedora/rpm/NetworkManager.spec @@ -450,6 +450,12 @@ mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/%{name}/conf.d # create a dnsmasq.d directory %{__mkdir_p} $RPM_BUILD_ROOT%{_sysconfdir}/NetworkManager/dnsmasq.d +# create dispatcher directories +mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/%{name}/dispatcher.d +mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/%{name}/dispatcher.d/pre-up.d +mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/%{name}/dispatcher.d/pre-down.d +%{__cp} examples/dispatcher/10-ifcfg-rh-routes.sh $RPM_BUILD_ROOT%{_sysconfdir}/%{name}/dispatcher.d/pre-up.d + %{__mkdir_p} $RPM_BUILD_ROOT%{_datadir}/gnome-vpn-properties %{__mkdir_p} $RPM_BUILD_ROOT%{_localstatedir}/lib/NetworkManager @@ -509,6 +515,7 @@ fi %dir %{_sysconfdir}/%{name}/dispatcher.d %dir %{_sysconfdir}/%{name}/dispatcher.d/pre-down.d %dir %{_sysconfdir}/%{name}/dispatcher.d/pre-up.d +%{_sysconfdir}/%{name}/dispatcher.d/pre-up.d/10-ifcfg-rh-routes.sh %dir %{_sysconfdir}/%{name}/dnsmasq.d %dir %{_sysconfdir}/%{name}/VPN %config(noreplace) %{_sysconfdir}/%{name}/NetworkManager.conf diff --git a/examples/dispatcher/10-ifcfg-rh-routes.sh b/examples/dispatcher/10-ifcfg-rh-routes.sh new file mode 100755 index 000000000..78f009ef6 --- /dev/null +++ b/examples/dispatcher/10-ifcfg-rh-routes.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# This ifcfg-rh-specific script runs +# /etc/sysconfig/network-scripts/ifup-routes when bringing up +# interfaces that have routing rules associated with them that can't +# be expressed by NMSettingIPConfig. (Eg, policy-based routing.) + +# This should be installed in dispatcher.d/pre-up.d/ + +dir=$(dirname "$CONNECTION_FILENAME") +if [ "$dir" != "/etc/sysconfig/network-scripts" ]; then + exit 0 +fi +profile=$(basename "$CONNECTION_FILENAME" | sed -ne 's/^ifcfg-//p') +if [ -z "$profile" ]; then + exit 0 +fi + +if [ -f "$dir/rule-$profile" -o -f "$dir/rule6-$profile" ]; then + /etc/sysconfig/network-scripts/ifup-routes "$DEVICE_IP_IFACE" "$profile" +fi diff --git a/examples/dispatcher/Makefile.am b/examples/dispatcher/Makefile.am index 0db71a0d4..0089d5fe7 100644 --- a/examples/dispatcher/Makefile.am +++ b/examples/dispatcher/Makefile.am @@ -1,3 +1,4 @@ EXTRA_DIST = \ + 10-ifcfg-rh-routes.sh \ 70-wifi-wired-exclusive.sh diff --git a/src/settings/plugins/ifcfg-rh/common.h b/src/settings/plugins/ifcfg-rh/common.h index d78f37525..7736d2632 100644 --- a/src/settings/plugins/ifcfg-rh/common.h +++ b/src/settings/plugins/ifcfg-rh/common.h @@ -26,7 +26,9 @@ #define IFCFG_TAG "ifcfg-" #define KEYS_TAG "keys-" #define ROUTE_TAG "route-" +#define RULE_TAG "rule-" #define ROUTE6_TAG "route6-" +#define RULE6_TAG "rule6-" #define BAK_TAG ".bak" #define TILDE_TAG "~" diff --git a/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c b/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c index 3281da945..32ef72af7 100644 --- a/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c +++ b/src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c @@ -331,6 +331,28 @@ nm_ifcfg_connection_get_unrecognized_spec (NMIfcfgConnection *self) return NM_IFCFG_CONNECTION_GET_PRIVATE (self)->unrecognized_spec; } +static void +replace_and_commit (NMSettingsConnection *connection, + NMConnection *new_connection, + NMSettingsConnectionCommitFunc callback, + gpointer user_data) +{ + const char *filename; + GError *error = NULL; + + filename = nm_settings_connection_get_filename (connection); + if (filename && utils_has_complex_routes (filename)) { + if (callback) { + error = g_error_new_literal (NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, + "Cannot modify a connection that has an associated 'rule-' or 'rule6-' file"); + callback (connection, error, user_data); + g_clear_error (&error); + } + } + + NM_SETTINGS_CONNECTION_CLASS (nm_ifcfg_connection_parent_class)->replace_and_commit (connection, new_connection, callback, user_data); +} + static void commit_changes (NMSettingsConnection *connection, NMSettingsConnectionCommitFunc callback, @@ -493,6 +515,7 @@ nm_ifcfg_connection_class_init (NMIfcfgConnectionClass *ifcfg_connection_class) object_class->get_property = get_property; object_class->dispose = dispose; settings_class->delete = do_delete; + settings_class->replace_and_commit = replace_and_commit; settings_class->commit_changes = commit_changes; /* Properties */ diff --git a/src/settings/plugins/ifcfg-rh/reader.c b/src/settings/plugins/ifcfg-rh/reader.c index e892394dc..f2da5416c 100644 --- a/src/settings/plugins/ifcfg-rh/reader.c +++ b/src/settings/plugins/ifcfg-rh/reader.c @@ -1071,14 +1071,10 @@ make_ip4_setting (shvarFile *ifcfg, /* Static routes - route- file */ route_path = utils_get_route_path (ifcfg->fileName); - if (!route_path) { - g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Could not get route file path for '%s'", ifcfg->fileName); - goto done; - } - /* First test new/legacy syntax */ - if (utils_has_route_file_new_syntax (route_path)) { + if (utils_has_complex_routes (route_path)) { + PARSE_WARNING ("'rule-' or 'rule6-' file is present; you will need to use a dispatcher script to apply these routes"); + } else if (utils_has_route_file_new_syntax (route_path)) { /* Parse route file in new syntax */ route_ifcfg = utils_get_route_ifcfg (ifcfg->fileName, FALSE); if (route_ifcfg) { @@ -1465,18 +1461,15 @@ make_ip6_setting (shvarFile *ifcfg, /* DNS searches ('DOMAIN' key) are read by make_ip4_setting() and included in NMSettingIPConfig */ - /* Read static routes from route6- file */ - route6_path = utils_get_route6_path (ifcfg->fileName); - if (!route6_path) { - g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Could not get route6 file path for '%s'", ifcfg->fileName); - goto error; - } + if (!utils_has_complex_routes (ifcfg->fileName)) { + /* Read static routes from route6- file */ + route6_path = utils_get_route6_path (ifcfg->fileName); + if (!read_route6_file (route6_path, s_ip6, error)) + goto error; - if (!read_route6_file (route6_path, s_ip6, error)) - goto error; + g_free (route6_path); + } - g_free (route6_path); return NM_SETTING (s_ip6); error: diff --git a/src/settings/plugins/ifcfg-rh/utils.c b/src/settings/plugins/ifcfg-rh/utils.c index 4378c6ebd..c57f2cfed 100644 --- a/src/settings/plugins/ifcfg-rh/utils.c +++ b/src/settings/plugins/ifcfg-rh/utils.c @@ -360,6 +360,30 @@ gone: return ret; } +gboolean +utils_has_complex_routes (const char *filename) +{ + char *rules; + + g_return_val_if_fail (filename != NULL, TRUE); + + rules = utils_get_extra_path (filename, RULE_TAG); + if (g_file_test (rules, G_FILE_TEST_EXISTS)) { + g_free (rules); + return TRUE; + } + g_free (rules); + + rules = utils_get_extra_path (filename, RULE6_TAG); + if (g_file_test (rules, G_FILE_TEST_EXISTS)) { + g_free (rules); + return TRUE; + } + g_free (rules); + + return FALSE; +} + gboolean utils_ignore_ip_config (NMConnection *connection) { diff --git a/src/settings/plugins/ifcfg-rh/utils.h b/src/settings/plugins/ifcfg-rh/utils.h index 95af828bb..27c5e4610 100644 --- a/src/settings/plugins/ifcfg-rh/utils.h +++ b/src/settings/plugins/ifcfg-rh/utils.h @@ -47,6 +47,7 @@ shvarFile *utils_get_route_ifcfg (const char *parent, gboolean should_create); shvarFile *utils_get_route6_ifcfg (const char *parent, gboolean should_create); gboolean utils_has_route_file_new_syntax (const char *filename); +gboolean utils_has_complex_routes (const char *filename); gboolean utils_ignore_ip_config (NMConnection *connection); diff --git a/src/settings/plugins/ifcfg-rh/writer.c b/src/settings/plugins/ifcfg-rh/writer.c index 300b0c166..86b56cce4 100644 --- a/src/settings/plugins/ifcfg-rh/writer.c +++ b/src/settings/plugins/ifcfg-rh/writer.c @@ -2638,6 +2638,12 @@ writer_update_connection (NMConnection *connection, const char *keyfile, GError **error) { + if (utils_has_complex_routes (filename)) { + g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, + "Cannot modify a connection that has an associated 'rule-' or 'rule6-' file"); + return FALSE; + } + return write_connection (connection, ifcfg_dir, filename, keyfile, NULL, error); } -- 2.17.1