ifcfg-rh: allow handling complex routing rules via dispatcher (rh #1160013)
authorDan Winship <danw@redhat.com>
Wed, 17 Dec 2014 13:50:05 +0000 (08:50 -0500)
committerDan Winship <danw@redhat.com>
Mon, 12 Jan 2015 14:53:24 +0000 (09:53 -0500)
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
examples/dispatcher/10-ifcfg-rh-routes.sh [new file with mode: 0755]
examples/dispatcher/Makefile.am
src/settings/plugins/ifcfg-rh/common.h
src/settings/plugins/ifcfg-rh/nm-ifcfg-connection.c
src/settings/plugins/ifcfg-rh/reader.c
src/settings/plugins/ifcfg-rh/utils.c
src/settings/plugins/ifcfg-rh/utils.h
src/settings/plugins/ifcfg-rh/writer.c

index 241ab4a..70884ff 100644 (file)
@@ -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 (executable)
index 0000000..78f009e
--- /dev/null
@@ -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
index 0db71a0..0089d5f 100644 (file)
@@ -1,3 +1,4 @@
 EXTRA_DIST = \
+       10-ifcfg-rh-routes.sh \
        70-wifi-wired-exclusive.sh
 
index d78f375..7736d26 100644 (file)
@@ -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 "~"
index 3281da9..32ef72a 100644 (file)
@@ -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 */
index e892394..f2da541 100644 (file)
@@ -1071,14 +1071,10 @@ make_ip4_setting (shvarFile *ifcfg,
 
        /* Static routes  - route-<name> 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-<interface> 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-<interface> 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:
index 4378c6e..c57f2cf 100644 (file)
@@ -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)
 {
index 95af828..27c5e46 100644 (file)
@@ -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);
 
index 300b0c1..86b56cc 100644 (file)
@@ -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);
 }