summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Winship <danw@gnome.org>2014-02-19 16:10:36 -0500
committerDan Winship <danw@gnome.org>2014-03-26 10:53:59 -0400
commit73e011d0b67a198913e098ba7f5e246aa2dd21bf (patch)
tree079069fdbe47ca5186389d6617db6c5c68399436
parent8fbd56258a7aed92a1d22ce19559b3c06ac332ef (diff)
downloadNetworkManager-73e011d0b67a198913e098ba7f5e246aa2dd21bf.tar.gz
ifcfg-rh: add support for reading and writing ifcfg alias files
-rw-r--r--src/settings/plugins/ifcfg-rh/plugin.c15
-rw-r--r--src/settings/plugins/ifcfg-rh/reader.c127
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am18
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem012
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:12
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:22
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:992
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem112
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem1:12
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem1:23
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c471
-rw-r--r--src/settings/plugins/ifcfg-rh/utils.c46
-rw-r--r--src/settings/plugins/ifcfg-rh/utils.h3
-rw-r--r--src/settings/plugins/ifcfg-rh/writer.c176
14 files changed, 841 insertions, 50 deletions
diff --git a/src/settings/plugins/ifcfg-rh/plugin.c b/src/settings/plugins/ifcfg-rh/plugin.c
index 0f8fcb8a00..4b70813221 100644
--- a/src/settings/plugins/ifcfg-rh/plugin.c
+++ b/src/settings/plugins/ifcfg-rh/plugin.c
@@ -377,7 +377,7 @@ ifcfg_dir_changed (GFileMonitor *monitor,
gpointer user_data)
{
SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (user_data);
- char *path, *ifcfg_path;
+ char *path, *base, *ifcfg_path;
NMIfcfgConnection *connection;
path = g_file_get_path (file);
@@ -386,8 +386,14 @@ ifcfg_dir_changed (GFileMonitor *monitor,
return;
}
- /* Given any ifcfg, keys, or routes file, get the ifcfg file path */
- ifcfg_path = utils_get_ifcfg_path (path);
+ base = g_file_get_basename (file);
+ if (utils_is_ifcfg_alias_file (base, NULL)) {
+ /* Alias file changed. Get the base ifcfg file from it */
+ ifcfg_path = utils_get_ifcfg_from_alias (path);
+ } else {
+ /* Given any ifcfg, keys, or routes file, get the ifcfg file path */
+ ifcfg_path = utils_get_ifcfg_path (path);
+ }
if (ifcfg_path) {
connection = find_by_path (plugin, ifcfg_path);
switch (event_type) {
@@ -407,6 +413,7 @@ ifcfg_dir_changed (GFileMonitor *monitor,
g_free (ifcfg_path);
}
g_free (path);
+ g_free (base);
}
static void
@@ -459,6 +466,8 @@ read_connections (SCPluginIfcfg *plugin)
if (utils_should_ignore_file (item, TRUE))
continue;
+ if (utils_is_ifcfg_alias_file (item, NULL))
+ continue;
full_path = g_build_filename (IFCFG_DIR, item, NULL);
if (!utils_get_ifcfg_name (full_path, TRUE))
diff --git a/src/settings/plugins/ifcfg-rh/reader.c b/src/settings/plugins/ifcfg-rh/reader.c
index c1fd181463..65142b92f5 100644
--- a/src/settings/plugins/ifcfg-rh/reader.c
+++ b/src/settings/plugins/ifcfg-rh/reader.c
@@ -50,6 +50,7 @@
#include <nm-setting-bridge-port.h>
#include <nm-setting-dcb.h>
#include <nm-setting-generic.h>
+#include <nm-util-private.h>
#include <nm-utils.h>
#include "wifi-utils.h"
@@ -641,10 +642,9 @@ static gboolean
read_full_ip4_address (shvarFile *ifcfg,
const char *network_file,
gint32 which,
- NMIP4Address **out_address,
+ NMIP4Address *addr,
GError **error)
{
- NMIP4Address *addr;
char *ip_tag, *prefix_tag, *netmask_tag, *gw_tag;
guint32 tmp;
gboolean success = FALSE;
@@ -654,12 +654,10 @@ read_full_ip4_address (shvarFile *ifcfg,
g_return_val_if_fail (which >= -1, FALSE);
g_return_val_if_fail (ifcfg != NULL, FALSE);
g_return_val_if_fail (network_file != NULL, FALSE);
- g_return_val_if_fail (out_address != NULL, FALSE);
- g_return_val_if_fail (*out_address == NULL, FALSE);
+ g_return_val_if_fail (addr != NULL, FALSE);
if (error)
g_return_val_if_fail (*error == NULL, FALSE);
- addr = nm_ip4_address_new ();
ip_tag = get_numbered_tag ("IPADDR", which);
prefix_tag = get_numbered_tag ("PREFIX", which);
netmask_tag = get_numbered_tag ("NETMASK", which);
@@ -668,13 +666,12 @@ read_full_ip4_address (shvarFile *ifcfg,
/* IP address */
if (!read_ip4_address (ifcfg, ip_tag, &tmp, error))
goto done;
- if (!tmp) {
- nm_ip4_address_unref (addr);
- addr = NULL;
- success = TRUE; /* done */
+ if (tmp)
+ nm_ip4_address_set_address (addr, tmp);
+ else if (!nm_ip4_address_get_address (addr)) {
+ success = TRUE;
goto done;
}
- nm_ip4_address_set_address (addr, tmp);
/* Gateway */
if (!read_ip4_address (ifcfg, gw_tag, &tmp, error))
@@ -741,13 +738,9 @@ read_full_ip4_address (shvarFile *ifcfg,
goto done;
}
- *out_address = addr;
success = TRUE;
done:
- if (!success && addr)
- nm_ip4_address_unref (addr);
-
g_free (ip_tag);
g_free (prefix_tag);
g_free (netmask_tag);
@@ -1387,9 +1380,12 @@ make_ip4_setting (shvarFile *ifcfg,
for (i = -1; i < 256; i++) {
NMIP4Address *addr = NULL;
- if (!read_full_ip4_address (ifcfg, network_file, i, &addr, error))
+ addr = nm_ip4_address_new ();
+ if (!read_full_ip4_address (ifcfg, network_file, i, addr, error))
goto done;
- if (!addr) {
+ if (!nm_ip4_address_get_address (addr)) {
+ nm_ip4_address_unref (addr);
+
/* The first mandatory variable is 2-indexed (IPADDR2)
* Variables IPADDR, IPADDR0 and IPADDR1 are optional */
if (i > 1)
@@ -1516,6 +1512,101 @@ done:
return NULL;
}
+static void
+read_aliases (NMSettingIP4Config *s_ip4, const char *filename, const char *network_file)
+{
+ GDir *dir;
+ char *dirname, *base;
+ shvarFile *parsed;
+ NMIP4Address *base_addr;
+ GError *err = NULL;
+
+ g_return_if_fail (s_ip4 != NULL);
+ g_return_if_fail (filename != NULL);
+
+ base_addr = nm_setting_ip4_config_get_address (s_ip4, 0);
+ if (!base_addr)
+ return;
+
+ dirname = g_path_get_dirname (filename);
+ g_return_if_fail (dirname != NULL);
+ base = g_path_get_basename (filename);
+ g_return_if_fail (base != NULL);
+
+ dir = g_dir_open (dirname, 0, &err);
+ if (dir) {
+ const char *item;
+ NMIP4Address *addr;
+ gboolean ok;
+
+ while ((item = g_dir_read_name (dir))) {
+ char *full_path, *device;
+ const char *p;
+
+ if (!utils_is_ifcfg_alias_file (item, base))
+ continue;
+
+ full_path = g_build_filename (dirname, item, NULL);
+
+ p = strchr (item, ':');
+ g_assert (p != NULL); /* we know this is true from utils_is_ifcfg_alias_file() */
+ for (p++; *p; p++) {
+ if (!g_ascii_isalnum (*p) && *p != '_') {
+ PLUGIN_WARN (IFCFG_PLUGIN_NAME, " alias: ignoring alias file '%s' with invalid name", full_path);
+ g_free (full_path);
+ continue;
+ }
+ }
+
+ parsed = svNewFile (full_path);
+ if (!parsed) {
+ PLUGIN_WARN (IFCFG_PLUGIN_NAME, " alias: couldn't parse file '%s'", full_path);
+ g_free (full_path);
+ continue;
+ }
+
+ device = svGetValue (parsed, "DEVICE", FALSE);
+ if (!device) {
+ PLUGIN_WARN (IFCFG_PLUGIN_NAME, " alias: file '%s' has no DEVICE", full_path);
+ svCloseFile (parsed);
+ g_free (full_path);
+ continue;
+ }
+ /* We know that item starts with IFCFG_TAG from utils_is_ifcfg_alias_file() */
+ if (strcmp (device, item + strlen (IFCFG_TAG)) != 0) {
+ PLUGIN_WARN (IFCFG_PLUGIN_NAME, " alias: file '%s' has invalid DEVICE (%s) for filename", full_path, device);
+ g_free (device);
+ svCloseFile (parsed);
+ g_free (full_path);
+ continue;
+ }
+
+ addr = nm_ip4_address_dup (base_addr);
+ ok = read_full_ip4_address (parsed, network_file, -1, addr, &err);
+ svCloseFile (parsed);
+ if (ok) {
+ if (!NM_UTIL_PRIVATE_CALL (nm_setting_ip4_config_add_address_with_label (s_ip4, addr, device)))
+ PLUGIN_WARN (IFCFG_PLUGIN_NAME, " alias: duplicate IP4 address in alias file %s", item);
+ } else {
+ PLUGIN_WARN (IFCFG_PLUGIN_NAME, " alias: error reading IP4 address from '%s': %s", full_path, err ? err->message : "no address")
+ g_clear_error (&err);
+ }
+ nm_ip4_address_unref (addr);
+
+ g_free (device);
+ g_free (full_path);
+ }
+
+ g_dir_close (dir);
+ } else {
+ PLUGIN_WARN (IFCFG_PLUGIN_NAME, " alias: can not read directory '%s': %s", dirname, err->message);
+ g_error_free (err);
+ }
+
+ g_free (base);
+ g_free (dirname);
+}
+
static NMSetting *
make_ip6_setting (shvarFile *ifcfg,
const char *network_file,
@@ -5106,8 +5197,10 @@ connection_from_file (const char *filename,
g_object_unref (connection);
connection = NULL;
goto done;
- } else
+ } else {
+ read_aliases (NM_SETTING_IP4_CONFIG (s_ip4), filename, network_file);
nm_connection_add_setting (connection, s_ip4);
+ }
/* There is only one DOMAIN variable and it is read and put to IPv4 config
* But if IPv4 is disabled or the config fails for some reason, we read
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am
index db9cba22b7..ef22288588 100644
--- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am
@@ -117,8 +117,24 @@ EXTRA_DIST = \
ifcfg-test-team-port \
ifcfg-test-team-port-empty-config
+# make target dependencies can't have colons in their names, which ends up
+# meaning that we can't add the alias files to EXTRA_DIST
+ALIAS_FILES = \
+ ifcfg-aliasem0 \
+ ifcfg-aliasem0:1 \
+ ifcfg-aliasem0:2 \
+ ifcfg-aliasem0:99 \
+ ifcfg-aliasem1 \
+ ifcfg-aliasem1:1 \
+ ifcfg-aliasem1:2
+
+dist-hook:
+ @for f in $(ALIAS_FILES); do \
+ cp $(abs_srcdir)/$$f $(distdir)/; \
+ done
+
check-local:
- @for f in $(EXTRA_DIST); do \
+ @for f in $(EXTRA_DIST) $(ALIAS_FILES); do \
chmod 0600 $(abs_srcdir)/$$f; \
done
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0
new file mode 100644
index 0000000000..4f9d645c8a
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0
@@ -0,0 +1,12 @@
+TYPE=Ethernet
+DEVICE=aliasem0
+HWADDR=00:11:22:33:44:55
+BOOTPROTO=none
+ONBOOT=yes
+DNS1=4.2.2.1
+DNS2=4.2.2.2
+IPADDR=192.168.1.5
+PREFIX=24
+NETMASK=255.255.255.0
+GATEWAY=192.168.1.1
+IPV6INIT=no
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:1 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:1
new file mode 100644
index 0000000000..37c0df1185
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:1
@@ -0,0 +1,2 @@
+DEVICE=aliasem0:1
+IPADDR=192.168.1.6
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:2 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:2
new file mode 100644
index 0000000000..0c3b6a7e91
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:2
@@ -0,0 +1,2 @@
+DEVICE=aliasem0:2
+IPADDR=192.168.1.9
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:99 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:99
new file mode 100644
index 0000000000..5df3f154b1
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:99
@@ -0,0 +1,2 @@
+DEVICE=aliasem0:99
+IPADDR=192.168.1.99
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem1 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem1
new file mode 100644
index 0000000000..f6fefc0d0c
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem1
@@ -0,0 +1,12 @@
+TYPE=Ethernet
+DEVICE=aliasem1
+HWADDR=00:11:22:33:44:55
+BOOTPROTO=none
+ONBOOT=yes
+DNS1=4.2.2.1
+DNS2=4.2.2.2
+IPADDR=192.168.1.5
+PREFIX=24
+NETMASK=255.255.255.0
+GATEWAY=192.168.1.1
+IPV6INIT=no
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem1:1 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem1:1
new file mode 100644
index 0000000000..21971611ef
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem1:1
@@ -0,0 +1,2 @@
+# bad, no DEVICE
+IPADDR=192.168.1.12
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem1:2 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem1:2
new file mode 100644
index 0000000000..b2ea218024
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem1:2
@@ -0,0 +1,3 @@
+# bad: wrong DEVICE
+DEVICE=aliasem0:2
+IPADDR=192.168.1.20
diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
index e4346c6bc3..f45d788ece 100644
--- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
+++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
@@ -46,6 +46,7 @@
#include <nm-setting-serial.h>
#include <nm-setting-vlan.h>
#include <nm-setting-dcb.h>
+#include <nm-util-private.h>
#include "nm-test-helpers.h"
#include "NetworkManagerUtils.h"
@@ -2829,6 +2830,271 @@ test_read_write_802_1X_subj_matches (void)
g_object_unref (reread);
}
+#define TEST_IFCFG_ALIASES_GOOD TEST_IFCFG_DIR"/network-scripts/ifcfg-aliasem0"
+
+static void
+test_read_wired_aliases_good (void)
+{
+ NMConnection *connection;
+ NMSettingConnection *s_con;
+ NMSettingIP4Config *s_ip4;
+ char *unmanaged = NULL;
+ char *keyfile = NULL;
+ char *routefile = NULL;
+ char *route6file = NULL;
+ gboolean ignore_error = FALSE;
+ GError *error = NULL;
+ const char *tmp;
+ const char *expected_id = "System aliasem0";
+ int expected_num_addresses = 4, expected_prefix = 24;
+ const char *expected_address[4] = { "192.168.1.5", "192.168.1.6", "192.168.1.9", "192.168.1.99" };
+ const char *expected_label[4] = { NULL, "aliasem0:1", "aliasem0:2", "aliasem0:99" };
+ const char *expected_gateway[4] = { "192.168.1.1", "192.168.1.1", "192.168.1.1", "192.168.1.1" };
+ int i, j;
+
+ connection = connection_from_file (TEST_IFCFG_ALIASES_GOOD,
+ NULL,
+ TYPE_ETHERNET,
+ NULL,
+ &unmanaged,
+ &keyfile,
+ &routefile,
+ &route6file,
+ &error,
+ &ignore_error);
+ ASSERT (connection != NULL,
+ "aliases-good-read", "failed to read %s: %s", TEST_IFCFG_ALIASES_GOOD, error->message);
+
+ ASSERT (nm_connection_verify (connection, &error),
+ "aliases-good-verify", "failed to verify %s: %s", TEST_IFCFG_ALIASES_GOOD, error->message);
+
+ /* ===== CONNECTION SETTING ===== */
+
+ s_con = nm_connection_get_setting_connection (connection);
+ ASSERT (s_con != NULL,
+ "aliases-good-verify-connection", "failed to verify %s: missing %s setting",
+ TEST_IFCFG_ALIASES_GOOD,
+ NM_SETTING_CONNECTION_SETTING_NAME);
+
+ /* ID */
+ tmp = nm_setting_connection_get_id (s_con);
+ ASSERT (tmp != NULL,
+ "aliases-good-verify-connection", "failed to verify %s: missing %s / %s key",
+ TEST_IFCFG_ALIASES_GOOD,
+ NM_SETTING_CONNECTION_SETTING_NAME,
+ NM_SETTING_CONNECTION_ID);
+ ASSERT (strcmp (tmp, expected_id) == 0,
+ "aliases-good-verify-connection", "failed to verify %s: unexpected %s / %s key value",
+ TEST_IFCFG_ALIASES_GOOD,
+ NM_SETTING_CONNECTION_SETTING_NAME,
+ NM_SETTING_CONNECTION_ID);
+
+ /* ===== IPv4 SETTING ===== */
+
+ s_ip4 = nm_connection_get_setting_ip4_config (connection);
+ ASSERT (s_ip4 != NULL,
+ "aliases-good-verify-ip4", "failed to verify %s: missing %s setting",
+ TEST_IFCFG_ALIASES_GOOD,
+ NM_SETTING_IP4_CONFIG_SETTING_NAME);
+
+ /* Method */
+ tmp = nm_setting_ip4_config_get_method (s_ip4);
+ ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0,
+ "aliases-good-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
+ TEST_IFCFG_ALIASES_GOOD,
+ NM_SETTING_IP4_CONFIG_SETTING_NAME,
+ NM_SETTING_IP4_CONFIG_METHOD);
+
+ ASSERT (nm_setting_ip4_config_get_num_addresses (s_ip4) == expected_num_addresses,
+ "aliases-good-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
+ TEST_IFCFG_ALIASES_GOOD,
+ NM_SETTING_IP4_CONFIG_SETTING_NAME,
+ NM_SETTING_IP4_CONFIG_ADDRESSES);
+
+ /* Addresses */
+ for (i = 0; i < expected_num_addresses; i++) {
+ NMIP4Address *ip4_addr;
+ char buf[INET_ADDRSTRLEN];
+ struct in_addr addr;
+
+ ip4_addr = nm_setting_ip4_config_get_address (s_ip4, i);
+ ASSERT (ip4_addr,
+ "aliases-good-verify-ip4", "failed to verify %s: missing IP4 address #%d",
+ TEST_IFCFG_ALIASES_GOOD,
+ i);
+
+ addr.s_addr = nm_ip4_address_get_address (ip4_addr);
+ ASSERT (inet_ntop (AF_INET, &addr, buf, sizeof (buf)) > 0,
+ "aliases-good-verify-ip4", "failed to verify %s: couldn't convert IP address #%d",
+ TEST_IFCFG_ALIASES_GOOD,
+ i);
+
+ for (j = 0; j < expected_num_addresses; j++) {
+ if (!g_strcmp0 (buf, expected_address[j]))
+ break;
+ }
+
+ ASSERT (j < expected_num_addresses,
+ "aliases-good-verify-ip4", "failed to verify %s: unexpected IP4 address #%d",
+ TEST_IFCFG_ALIASES_GOOD,
+ i);
+
+ ASSERT (nm_ip4_address_get_prefix (ip4_addr) == expected_prefix,
+ "aliases-good-verify-ip4", "failed to verify %s: unexpected IP4 address prefix #%d",
+ TEST_IFCFG_ALIASES_GOOD,
+ i);
+
+ if (expected_gateway[j]) {
+ ASSERT (inet_pton (AF_INET, expected_gateway[j], &addr) > 0,
+ "aliases-good-verify-ip4", "failed to verify %s: couldn't convert IP address gateway #%d",
+ TEST_IFCFG_ALIASES_GOOD,
+ i);
+ } else
+ addr.s_addr = 0;
+ ASSERT (nm_ip4_address_get_gateway (ip4_addr) == addr.s_addr,
+ "aliases-good-verify-ip4", "failed to verify %s: unexpected IP4 address gateway #%d",
+ TEST_IFCFG_ALIASES_GOOD,
+ i);
+
+ ASSERT (g_strcmp0 (NM_UTIL_PRIVATE_CALL (nm_setting_ip4_config_get_address_label (s_ip4, i)), expected_label[j]) == 0,
+ "aliases-good-verify-ip4", "failed to verify %s: unexpected IP4 address label #%d",
+ TEST_IFCFG_ALIASES_GOOD,
+ i);
+
+ expected_address[j] = NULL;
+ expected_gateway[j] = NULL;
+ expected_label[j] = NULL;
+ }
+
+ for (i = 0; i < expected_num_addresses; i++) {
+ ASSERT (expected_address[i] == NULL,
+ "aliases-good-verify-ip4", "failed to verify %s: did not find IP4 address %s",
+ TEST_IFCFG_ALIASES_GOOD,
+ expected_address[i]);
+ }
+
+ g_free (keyfile);
+ g_free (routefile);
+ g_free (route6file);
+ g_object_unref (connection);
+}
+
+#define TEST_IFCFG_ALIASES_BAD TEST_IFCFG_DIR"/network-scripts/ifcfg-aliasem1"
+
+static void
+test_read_wired_aliases_bad (void)
+{
+ NMConnection *connection;
+ NMSettingConnection *s_con;
+ NMSettingIP4Config *s_ip4;
+ char *unmanaged = NULL;
+ char *keyfile = NULL;
+ char *routefile = NULL;
+ char *route6file = NULL;
+ gboolean ignore_error = FALSE;
+ GError *error = NULL;
+ const char *tmp;
+ const char *expected_id = "System aliasem1";
+ int expected_num_addresses = 1, expected_prefix = 24;
+ const char *expected_address = "192.168.1.5";
+ const char *expected_label = NULL;
+ const char *expected_gateway = "192.168.1.1";
+ NMIP4Address *ip4_addr;
+ struct in_addr addr;
+
+ connection = connection_from_file (TEST_IFCFG_ALIASES_BAD,
+ NULL,
+ TYPE_ETHERNET,
+ NULL,
+ &unmanaged,
+ &keyfile,
+ &routefile,
+ &route6file,
+ &error,
+ &ignore_error);
+ ASSERT (connection != NULL,
+ "aliases-bad-read", "failed to read %s: %s", TEST_IFCFG_ALIASES_BAD, error->message);
+
+ ASSERT (nm_connection_verify (connection, &error),
+ "aliases-bad-verify", "failed to verify %s: %s", TEST_IFCFG_ALIASES_BAD, error->message);
+
+ /* ===== CONNECTION SETTING ===== */
+
+ s_con = nm_connection_get_setting_connection (connection);
+ ASSERT (s_con != NULL,
+ "aliases-bad-verify-connection", "failed to verify %s: missing %s setting",
+ TEST_IFCFG_ALIASES_BAD,
+ NM_SETTING_CONNECTION_SETTING_NAME);
+
+ /* ID */
+ tmp = nm_setting_connection_get_id (s_con);
+ ASSERT (tmp != NULL,
+ "aliases-bad-verify-connection", "failed to verify %s: missing %s / %s key",
+ TEST_IFCFG_ALIASES_BAD,
+ NM_SETTING_CONNECTION_SETTING_NAME,
+ NM_SETTING_CONNECTION_ID);
+ ASSERT (strcmp (tmp, expected_id) == 0,
+ "aliases-bad-verify-connection", "failed to verify %s: unexpected %s / %s key value",
+ TEST_IFCFG_ALIASES_BAD,
+ NM_SETTING_CONNECTION_SETTING_NAME,
+ NM_SETTING_CONNECTION_ID);
+
+ /* ===== IPv4 SETTING ===== */
+
+ s_ip4 = nm_connection_get_setting_ip4_config (connection);
+ ASSERT (s_ip4 != NULL,
+ "aliases-bad-verify-ip4", "failed to verify %s: missing %s setting",
+ TEST_IFCFG_ALIASES_BAD,
+ NM_SETTING_IP4_CONFIG_SETTING_NAME);
+
+ /* Method */
+ tmp = nm_setting_ip4_config_get_method (s_ip4);
+ ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0,
+ "aliases-bad-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
+ TEST_IFCFG_ALIASES_BAD,
+ NM_SETTING_IP4_CONFIG_SETTING_NAME,
+ NM_SETTING_IP4_CONFIG_METHOD);
+
+ ASSERT (nm_setting_ip4_config_get_num_addresses (s_ip4) == expected_num_addresses,
+ "aliases-bad-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
+ TEST_IFCFG_ALIASES_BAD,
+ NM_SETTING_IP4_CONFIG_SETTING_NAME,
+ NM_SETTING_IP4_CONFIG_ADDRESSES);
+
+ /* Addresses */
+ ip4_addr = nm_setting_ip4_config_get_address (s_ip4, 0);
+ ASSERT (ip4_addr,
+ "aliases-bad-verify-ip4", "failed to verify %s: missing IP4 address",
+ TEST_IFCFG_ALIASES_BAD);
+
+ ASSERT (inet_pton (AF_INET, expected_address, &addr) > 0,
+ "aliases-bad-verify-ip4", "failed to verify %s: couldn't convert IP address",
+ TEST_IFCFG_ALIASES_BAD);
+ ASSERT (nm_ip4_address_get_address (ip4_addr) == addr.s_addr,
+ "aliases-bad-verify-ip4", "failed to verify %s: unexpected IP4 address",
+ TEST_IFCFG_ALIASES_BAD);
+
+ ASSERT (nm_ip4_address_get_prefix (ip4_addr) == expected_prefix,
+ "aliases-bad-verify-ip4", "failed to verify %s: unexpected IP4 address prefix",
+ TEST_IFCFG_ALIASES_BAD);
+
+ ASSERT (inet_pton (AF_INET, expected_gateway, &addr) > 0,
+ "aliases-bad-verify-ip4", "failed to verify %s: couldn't convert IP address gateway",
+ TEST_IFCFG_ALIASES_BAD);
+ ASSERT (nm_ip4_address_get_gateway (ip4_addr) == addr.s_addr,
+ "aliases-bad-verify-ip4", "failed to verify %s: unexpected IP4 address gateway",
+ TEST_IFCFG_ALIASES_BAD);
+
+ ASSERT (g_strcmp0 (NM_UTIL_PRIVATE_CALL (nm_setting_ip4_config_get_address_label (s_ip4, 0)), expected_label) == 0,
+ "aliases-bad-verify-ip4", "failed to verify %s: unexpected IP4 address label",
+ TEST_IFCFG_ALIASES_BAD);
+
+ g_free (keyfile);
+ g_free (routefile);
+ g_free (route6file);
+ g_object_unref (connection);
+}
+
#define TEST_IFCFG_WIFI_OPEN TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-open"
static void
@@ -7799,6 +8065,208 @@ test_write_wired_8021x_tls (NMSetting8021xCKScheme scheme,
g_object_unref (reread);
}
+#define TEST_SCRATCH_ALIAS_BASE TEST_SCRATCH_DIR "/network-scripts/ifcfg-alias0"
+
+static void
+test_write_wired_aliases (void)
+{
+ NMConnection *connection;
+ NMConnection *reread;
+ NMSettingConnection *s_con;
+ NMSettingWired *s_wired;
+ NMSettingIP4Config *s_ip4;
+ char *uuid;
+ int num_addresses = 4;
+ guint32 ip[] = { 0x01010101, 0x01010102, 0x01010103, 0x01010104 };
+ const char *label[] = { NULL, "alias0:2", NULL, "alias0:3" };
+ const guint32 gw = htonl (0x01010101);
+ const guint32 prefix = 24;
+ NMIP4Address *addr;
+ gboolean success;
+ GError *error = NULL;
+ char *testfile = NULL;
+ char *unmanaged = NULL;
+ char *keyfile = NULL;
+ char *routefile = NULL;
+ char *route6file = NULL;
+ gboolean ignore_error = FALSE;
+ shvarFile *ifcfg;
+ int i, j;
+
+ connection = nm_connection_new ();
+ ASSERT (connection != NULL,
+ "wired-aliases-write", "failed to allocate new connection");
+
+ /* Connection setting */
+ s_con = (NMSettingConnection *) nm_setting_connection_new ();
+ ASSERT (s_con != NULL,
+ "wired-aliases-write", "failed to allocate new %s setting",
+ NM_SETTING_CONNECTION_SETTING_NAME);
+ nm_connection_add_setting (connection, NM_SETTING (s_con));
+
+ uuid = nm_utils_uuid_generate ();
+ g_object_set (s_con,
+ NM_SETTING_CONNECTION_ID, "alias0",
+ NM_SETTING_CONNECTION_UUID, uuid,
+ NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
+ NULL);
+ g_free (uuid);
+
+ /* Wired setting */
+ s_wired = (NMSettingWired *) nm_setting_wired_new ();
+ ASSERT (s_wired != NULL,
+ "wired-aliases-write", "failed to allocate new %s setting",
+ NM_SETTING_WIRED_SETTING_NAME);
+ nm_connection_add_setting (connection, NM_SETTING (s_wired));
+
+ /* IP4 setting */
+ s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
+ ASSERT (s_ip4 != NULL,
+ "wired-aliases-write", "failed to allocate new %s setting",
+ NM_SETTING_IP4_CONFIG_SETTING_NAME);
+ nm_connection_add_setting (connection, NM_SETTING (s_ip4));
+
+ g_object_set (s_ip4,
+ NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
+ NM_SETTING_IP4_CONFIG_MAY_FAIL, TRUE,
+ NULL);
+
+ for (i = 0; i < num_addresses; i++) {
+ addr = nm_ip4_address_new ();
+ nm_ip4_address_set_address (addr, ip[i]);
+ nm_ip4_address_set_prefix (addr, prefix);
+ nm_ip4_address_set_gateway (addr, gw);
+ NM_UTIL_PRIVATE_CALL (nm_setting_ip4_config_add_address_with_label (s_ip4, addr, label[i]));
+ nm_ip4_address_unref (addr);
+ }
+
+ ASSERT (nm_connection_verify (connection, &error) == TRUE,
+ "wired-aliases-write", "failed to verify connection: %s",
+ (error && error->message) ? error->message : "(unknown)");
+
+ /* Create some pre-existing alias files, to make sure they get overwritten / deleted. */
+ ifcfg = svCreateFile (TEST_SCRATCH_ALIAS_BASE ":2");
+ svSetValue (ifcfg, "DEVICE", "alias0:2", FALSE);
+ svSetValue (ifcfg, "IPADDR", "192.168.1.2", FALSE);
+ svWriteFile (ifcfg, 0644);
+ svCloseFile (ifcfg);
+ ASSERT (g_file_test (TEST_SCRATCH_ALIAS_BASE ":2", G_FILE_TEST_EXISTS),
+ "wired-aliases-write", "failed to write extra alias file");
+
+ ifcfg = svCreateFile (TEST_SCRATCH_ALIAS_BASE ":5");
+ svSetValue (ifcfg, "DEVICE", "alias0:5", FALSE);
+ svSetValue (ifcfg, "IPADDR", "192.168.1.5", FALSE);
+ svWriteFile (ifcfg, 0644);
+ svCloseFile (ifcfg);
+ ASSERT (g_file_test (TEST_SCRATCH_ALIAS_BASE ":5", G_FILE_TEST_EXISTS),
+ "wired-aliases-write", "failed to write extra alias file");
+
+ /* Save the ifcfg */
+ success = writer_new_connection (connection,
+ TEST_SCRATCH_DIR "/network-scripts/",
+ &testfile,
+ &error);
+ ASSERT (success == TRUE,
+ "wired-aliases-write", "failed to write connection to disk: %s",
+ (error && error->message) ? error->message : "(unknown)");
+
+ ASSERT (testfile != NULL,
+ "wired-aliases-write", "didn't get ifcfg file path back after writing connection");
+
+ /* Re-check the alias files */
+ ASSERT (g_file_test (TEST_SCRATCH_ALIAS_BASE ":2", G_FILE_TEST_EXISTS),
+ "wired-aliases-write", "saving failed to write ifcfg-alias0:2");
+ ASSERT (g_file_test (TEST_SCRATCH_ALIAS_BASE ":3", G_FILE_TEST_EXISTS),
+ "wired-aliases-write", "saving failed to write ifcfg-alias0:3");
+ ASSERT (!g_file_test (TEST_SCRATCH_ALIAS_BASE ":5", G_FILE_TEST_EXISTS),
+ "wired-aliases-write", "saving failed to delete unused ifcfg-alias0:5");
+
+ /* re-read the connection for comparison */
+ reread = connection_from_file (testfile,
+ NULL,
+ TYPE_ETHERNET,
+ NULL,
+ &unmanaged,
+ &keyfile,
+ &routefile,
+ &route6file,
+ &error,
+ &ignore_error);
+ unlink (testfile);
+ unlink (TEST_SCRATCH_ALIAS_BASE ":2");
+ unlink (TEST_SCRATCH_ALIAS_BASE ":3");
+
+ ASSERT (reread != NULL,
+ "wired-aliases-write-reread", "failed to read %s: %s", testfile, error->message);
+
+ ASSERT (nm_connection_verify (reread, &error),
+ "wired-aliases-write-reread-verify", "failed to verify %s: %s", testfile, error->message);
+
+ /* nm_connection_compare() is not guaranteed to succeed, because the
+ * aliases get read back in essentially random order. So just
+ * verify the aliases manually.
+ */
+ s_ip4 = nm_connection_get_setting_ip4_config (connection);
+ ASSERT (nm_setting_ip4_config_get_num_addresses (s_ip4) == num_addresses,
+ "wired-aliases-write-verify-ip4", "failed to verify %s: unexpected %s / %s key value",
+ testfile,
+ NM_SETTING_IP4_CONFIG_SETTING_NAME,
+ NM_SETTING_IP4_CONFIG_ADDRESSES);
+
+ /* Addresses */
+ for (i = 0; i < num_addresses; i++) {
+ guint32 addrbytes;
+
+ addr = nm_setting_ip4_config_get_address (s_ip4, i);
+ ASSERT (addr,
+ "wired-aliases-write-verify-ip4", "failed to verify %s: missing IP4 address #%d",
+ testfile,
+ i);
+
+ addrbytes = nm_ip4_address_get_address (addr);
+ for (j = 0; j < num_addresses; j++) {
+ if (addrbytes == ip[j])
+ break;
+ }
+
+ ASSERT (j < num_addresses,
+ "wired-aliases-write-verify-ip4", "failed to verify %s: unexpected IP4 address #%d",
+ testfile,
+ i);
+
+ ASSERT (nm_ip4_address_get_prefix (addr) == prefix,
+ "wired-aliases-write-verify-ip4", "failed to verify %s: unexpected IP4 address prefix #%d",
+ testfile,
+ i);
+
+ ASSERT (nm_ip4_address_get_gateway (addr) == gw,
+ "wired-aliases-write-verify-ip4", "failed to verify %s: unexpected IP4 address gateway #%d",
+ testfile,
+ i);
+
+ ASSERT (g_strcmp0 (NM_UTIL_PRIVATE_CALL (nm_setting_ip4_config_get_address_label (s_ip4, i)), label[j]) == 0,
+ "wired-aliases-write-verify-ip4", "failed to verify %s: unexpected IP4 address label #%d",
+ testfile,
+ i);
+
+ ip[j] = 0;
+ }
+
+ for (i = 0; i < num_addresses; i++) {
+ ASSERT (ip[i] == 0,
+ "wired-aliases-write-verify-ip4", "failed to verify %s: did not find IP4 address 0x%08x",
+ testfile,
+ ip[i]);
+ }
+
+ g_free (testfile);
+ g_free (keyfile);
+ g_free (routefile);
+ g_free (route6file);
+ g_object_unref (connection);
+ g_object_unref (reread);
+}
+
static void
test_write_wifi_open (void)
{
@@ -13869,6 +14337,8 @@ int main (int argc, char **argv)
test_read_wired_8021x_tls_secret_flags (TEST_IFCFG_WIRED_8021X_TLS_ALWAYS,
NM_SETTING_SECRET_FLAG_AGENT_OWNED | NM_SETTING_SECRET_FLAG_NOT_SAVED);
g_test_add_func (TPATH "802-1x/subj-mathes", test_read_write_802_1X_subj_matches);
+ test_read_wired_aliases_good ();
+ test_read_wired_aliases_bad ();
test_read_wifi_open ();
test_read_wifi_open_auto ();
test_read_wifi_open_ssid_hex ();
@@ -13918,6 +14388,7 @@ int main (int argc, char **argv)
test_write_wired_8021x_tls (NM_SETTING_802_1X_CK_SCHEME_PATH, NM_SETTING_SECRET_FLAG_NOT_SAVED);
test_write_wired_8021x_tls (NM_SETTING_802_1X_CK_SCHEME_PATH, NM_SETTING_SECRET_FLAG_AGENT_OWNED | NM_SETTING_SECRET_FLAG_NOT_SAVED);
test_write_wired_8021x_tls (NM_SETTING_802_1X_CK_SCHEME_BLOB, NM_SETTING_SECRET_FLAG_NONE);
+ test_write_wired_aliases ();
test_write_wifi_open ();
test_write_wifi_open_hex_ssid ();
test_write_wifi_wep ();
diff --git a/src/settings/plugins/ifcfg-rh/utils.c b/src/settings/plugins/ifcfg-rh/utils.c
index 0c87a7f973..5abb4282e5 100644
--- a/src/settings/plugins/ifcfg-rh/utils.c
+++ b/src/settings/plugins/ifcfg-rh/utils.c
@@ -367,3 +367,49 @@ utils_ignore_ip_config (NMConnection *connection)
return FALSE;
}
+
+/* Find out if the 'alias' file name might be an alias file for 'ifcfg' file name,
+ * or any alias when 'ifcfg' is NULL. Does not check that it's actually a valid
+ * alias name; that happens in reader.c
+ */
+gboolean
+utils_is_ifcfg_alias_file (const char *alias, const char *ifcfg)
+{
+ g_return_val_if_fail (alias != NULL, FALSE);
+
+ if (strncmp (alias, IFCFG_TAG, strlen (IFCFG_TAG)))
+ return FALSE;
+
+ if (ifcfg) {
+ size_t len = strlen (ifcfg);
+
+ return (strncmp (alias, ifcfg, len) == 0 && alias[len] == ':');
+ } else {
+ return (strchr (alias, ':') != NULL);
+ }
+}
+
+char *
+utils_get_ifcfg_from_alias (const char *alias)
+{
+ char *base, *ptr, *ifcfg = NULL;
+
+ g_return_val_if_fail (alias != NULL, NULL);
+
+ base = g_path_get_basename (alias);
+ g_return_val_if_fail (base != NULL, NULL);
+
+ if (utils_is_ifcfg_alias_file (base, NULL)) {
+ ifcfg = g_strdup (alias);
+ ptr = strrchr (ifcfg, ':');
+ if (ptr)
+ *ptr = '\0';
+ else {
+ g_free (ifcfg);
+ ifcfg = NULL;
+ }
+ }
+
+ g_free (base);
+ return ifcfg;
+}
diff --git a/src/settings/plugins/ifcfg-rh/utils.h b/src/settings/plugins/ifcfg-rh/utils.h
index 2c94aacaa0..95af828bb1 100644
--- a/src/settings/plugins/ifcfg-rh/utils.h
+++ b/src/settings/plugins/ifcfg-rh/utils.h
@@ -50,5 +50,8 @@ gboolean utils_has_route_file_new_syntax (const char *filename);
gboolean utils_ignore_ip_config (NMConnection *connection);
+gboolean utils_is_ifcfg_alias_file (const char *alias, const char *ifcfg);
+char *utils_get_ifcfg_from_alias (const char *alias);
+
#endif /* _UTILS_H_ */
diff --git a/src/settings/plugins/ifcfg-rh/writer.c b/src/settings/plugins/ifcfg-rh/writer.c
index 5584f6ed3e..720616d1d5 100644
--- a/src/settings/plugins/ifcfg-rh/writer.c
+++ b/src/settings/plugins/ifcfg-rh/writer.c
@@ -39,6 +39,7 @@
#include <nm-setting-vlan.h>
#include <nm-setting-team.h>
#include <nm-setting-team-port.h>
+#include <nm-util-private.h>
#include <nm-utils.h>
#include "common.h"
@@ -1845,7 +1846,7 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
char *addr_key, *prefix_key, *netmask_key, *gw_key, *metric_key, *tmp;
char *route_path = NULL;
gint32 j;
- guint32 i, num;
+ guint32 i, n, num;
GString *searches;
gboolean success = FALSE;
gboolean fake_ip4 = FALSE;
@@ -1909,48 +1910,68 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
else if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED))
svSetValue (ifcfg, "BOOTPROTO", "shared", FALSE);
- /* Write out IPADDR0 .. IPADDR255, PREFIX0 .. PREFIX255, GATEWAY0 .. GATEWAY255
- * Possible NETMASK<n> is removed only (it's obsolete) */
- num = nm_setting_ip4_config_get_num_addresses (s_ip4);
+ /* Clear out un-numbered IP address fields */
svSetValue (ifcfg, "IPADDR", NULL, FALSE);
svSetValue (ifcfg, "PREFIX", NULL, FALSE);
svSetValue (ifcfg, "NETMASK", NULL, FALSE);
svSetValue (ifcfg, "GATEWAY", NULL, FALSE);
- for (i = 0; i < 256; i++) {
+
+ /* Write out IPADDR<n>, PREFIX<n>, GATEWAY<n> for current IP addresses
+ * without labels. Unset obsolete NETMASK<n>.
+ */
+ num = nm_setting_ip4_config_get_num_addresses (s_ip4);
+ for (i = n = 0; i < num; i++) {
char buf[INET_ADDRSTRLEN];
NMIP4Address *addr;
guint32 ip;
- addr_key = g_strdup_printf ("IPADDR%d", i);
- prefix_key = g_strdup_printf ("PREFIX%d", i);
- netmask_key = g_strdup_printf ("NETMASK%d", i);
- gw_key = g_strdup_printf ("GATEWAY%d", i);
+ if (i > 0 && NM_UTIL_PRIVATE_CALL (nm_setting_ip4_config_get_address_label (s_ip4, i)))
+ continue;
- if (i >= num) {
- svSetValue (ifcfg, addr_key, NULL, FALSE);
- svSetValue (ifcfg, prefix_key, NULL, FALSE);
- svSetValue (ifcfg, netmask_key, NULL, FALSE);
- svSetValue (ifcfg, gw_key, NULL, FALSE);
- } else {
- addr = nm_setting_ip4_config_get_address (s_ip4, i);
+ addr_key = g_strdup_printf ("IPADDR%d", n);
+ prefix_key = g_strdup_printf ("PREFIX%d", n);
+ netmask_key = g_strdup_printf ("NETMASK%d", n);
+ gw_key = g_strdup_printf ("GATEWAY%d", n);
+
+ addr = nm_setting_ip4_config_get_address (s_ip4, i);
+
+ memset (buf, 0, sizeof (buf));
+ ip = nm_ip4_address_get_address (addr);
+ inet_ntop (AF_INET, (const void *) &ip, &buf[0], sizeof (buf));
+ svSetValue (ifcfg, addr_key, &buf[0], FALSE);
+ tmp = g_strdup_printf ("%u", nm_ip4_address_get_prefix (addr));
+ svSetValue (ifcfg, prefix_key, tmp, FALSE);
+ g_free (tmp);
+
+ svSetValue (ifcfg, netmask_key, NULL, FALSE);
+
+ if (nm_ip4_address_get_gateway (addr)) {
memset (buf, 0, sizeof (buf));
- ip = nm_ip4_address_get_address (addr);
+ ip = nm_ip4_address_get_gateway (addr);
inet_ntop (AF_INET, (const void *) &ip, &buf[0], sizeof (buf));
- svSetValue (ifcfg, addr_key, &buf[0], FALSE);
+ svSetValue (ifcfg, gw_key, &buf[0], FALSE);
+ } else
+ svSetValue (ifcfg, gw_key, NULL, FALSE);
- tmp = g_strdup_printf ("%u", nm_ip4_address_get_prefix (addr));
- svSetValue (ifcfg, prefix_key, tmp, FALSE);
- g_free (tmp);
+ g_free (addr_key);
+ g_free (prefix_key);
+ g_free (netmask_key);
+ g_free (gw_key);
+ n++;
+ }
- if (nm_ip4_address_get_gateway (addr)) {
- memset (buf, 0, sizeof (buf));
- ip = nm_ip4_address_get_gateway (addr);
- inet_ntop (AF_INET, (const void *) &ip, &buf[0], sizeof (buf));
- svSetValue (ifcfg, gw_key, &buf[0], FALSE);
- } else
- svSetValue (ifcfg, gw_key, NULL, FALSE);
- }
+ /* Clear remaining IPADDR<n..255>, etc */
+ for (; n < 256; n++) {
+ addr_key = g_strdup_printf ("IPADDR%d", n);
+ prefix_key = g_strdup_printf ("PREFIX%d", n);
+ netmask_key = g_strdup_printf ("NETMASK%d", n);
+ gw_key = g_strdup_printf ("GATEWAY%d", n);
+
+ svSetValue (ifcfg, addr_key, NULL, FALSE);
+ svSetValue (ifcfg, prefix_key, NULL, FALSE);
+ svSetValue (ifcfg, netmask_key, NULL, FALSE);
+ svSetValue (ifcfg, gw_key, NULL, FALSE);
g_free (addr_key);
g_free (prefix_key);
@@ -2120,6 +2141,102 @@ out:
return success;
}
+static void
+write_ip4_aliases (NMConnection *connection, char *base_ifcfg_path)
+{
+ NMSettingIP4Config *s_ip4;
+ char *base_ifcfg_dir, *base_ifcfg_name, *base_name;
+ int i, num, base_ifcfg_path_len, base_ifcfg_name_len, base_name_len;
+ GDir *dir;
+
+ base_ifcfg_path_len = strlen (base_ifcfg_path);
+ base_ifcfg_dir = g_path_get_dirname (base_ifcfg_path);
+ base_ifcfg_name = g_path_get_basename (base_ifcfg_path);
+ base_ifcfg_name_len = strlen (base_ifcfg_name);
+ base_name = base_ifcfg_name + strlen (IFCFG_TAG);
+ base_name_len = strlen (base_name);
+
+ /* Remove all existing aliases for this file first */
+ dir = g_dir_open (base_ifcfg_dir, 0, NULL);
+ if (dir) {
+ const char *item;
+
+ while ((item = g_dir_read_name (dir))) {
+ char *full_path;
+
+ if ( strncmp (item, base_ifcfg_name, base_ifcfg_name_len) != 0
+ || item[base_ifcfg_name_len] != ':')
+ continue;
+
+ full_path = g_build_filename (base_ifcfg_dir, item, NULL);
+ unlink (full_path);
+ g_free (full_path);
+ }
+
+ g_dir_close (dir);
+ }
+
+ if (utils_ignore_ip_config (connection))
+ return;
+
+ s_ip4 = nm_connection_get_setting_ip4_config (connection);
+ if (!s_ip4)
+ return;
+
+ num = nm_setting_ip4_config_get_num_addresses (s_ip4);
+ for (i = 0; i < num; i++) {
+ const char *label, *p;
+ char buf[INET_ADDRSTRLEN], *path, *tmp;
+ NMIP4Address *addr;
+ guint32 ip;
+ shvarFile *ifcfg;
+
+ label = NM_UTIL_PRIVATE_CALL (nm_setting_ip4_config_get_address_label (s_ip4, i));
+ if (!label)
+ continue;
+ if ( strncmp (label, base_name, base_name_len) != 0
+ || label[base_name_len] != ':')
+ continue;
+
+ for (p = label; *p; p++) {
+ if (!g_ascii_isalnum (*p) && *p != '_' && *p != ':')
+ break;
+ }
+ if (*p)
+ continue;
+
+ path = g_strdup_printf ("%s%s", base_ifcfg_path, label + base_name_len);
+ ifcfg = svCreateFile (path);
+ g_free (path);
+
+ svSetValue (ifcfg, "DEVICE", label, FALSE);
+
+ addr = nm_setting_ip4_config_get_address (s_ip4, i);
+
+ memset (buf, 0, sizeof (buf));
+ ip = nm_ip4_address_get_address (addr);
+ inet_ntop (AF_INET, (const void *) &ip, &buf[0], sizeof (buf));
+ svSetValue (ifcfg, "IPADDR", &buf[0], FALSE);
+
+ tmp = g_strdup_printf ("%u", nm_ip4_address_get_prefix (addr));
+ svSetValue (ifcfg, "PREFIX", tmp, FALSE);
+ g_free (tmp);
+
+ if (nm_ip4_address_get_gateway (addr)) {
+ memset (buf, 0, sizeof (buf));
+ ip = nm_ip4_address_get_gateway (addr);
+ inet_ntop (AF_INET, (const void *) &ip, &buf[0], sizeof (buf));
+ svSetValue (ifcfg, "GATEWAY", &buf[0], FALSE);
+ }
+
+ svWriteFile (ifcfg, 0644);
+ svCloseFile (ifcfg);
+ }
+
+ g_free (base_ifcfg_name);
+ g_free (base_ifcfg_dir);
+}
+
static gboolean
write_route6_file (const char *filename, NMSettingIP6Config *s_ip6, GError **error)
{
@@ -2517,6 +2634,7 @@ write_connection (NMConnection *connection,
if (!write_ip4_setting (connection, ifcfg, error))
goto out;
+ write_ip4_aliases (connection, ifcfg_name);
if (!write_ip6_setting (connection, ifcfg, error))
goto out;