about summary refs log tree commit diff
path: root/src/settings/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/settings/plugins')
-rw-r--r--src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c112
-rw-r--r--src/settings/plugins/ifcfg-rh/shvar.c22
-rw-r--r--src/settings/plugins/ifcfg-rh/shvar.h2
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-114
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1.cexpected23
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c62
6 files changed, 169 insertions, 66 deletions
diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
index d6f33c49..d2b7ff67 100644
--- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
+++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c
@@ -1926,12 +1926,8 @@ get_route_attributes_string (NMIPRoute *route, int family)
 static gboolean
 write_route_file_legacy (const char *filename, NMSettingIPConfig *s_ip4, GError **error)
 {
-	const char *dest, *next_hop;
-	char **route_items;
-	gs_free char *route_contents = NULL;
+	nm_auto_free_gstring GString *contents = NULL;
 	NMIPRoute *route;
-	guint32 prefix;
-	gint64 metric;
 	guint32 i, num;
 
 	g_return_val_if_fail (filename != NULL, FALSE);
@@ -1945,36 +1941,34 @@ write_route_file_legacy (const char *filename, NMSettingIPConfig *s_ip4, GError
 		return TRUE;
 	}
 
-	route_items = g_malloc0 (sizeof (char *) * (num + 1));
+	contents = g_string_new ("");
+
 	for (i = 0; i < num; i++) {
+		const char *next_hop;
 		gs_free char *options = NULL;
+		gint64 metric;
 
 		route = nm_setting_ip_config_get_route (s_ip4, i);
-
-		dest = nm_ip_route_get_dest (route);
-		prefix = nm_ip_route_get_prefix (route);
 		next_hop = nm_ip_route_get_next_hop (route);
 		metric = nm_ip_route_get_metric (route);
-
 		options = get_route_attributes_string (route, AF_INET);
 
-		if (metric == -1) {
-			route_items[i] = g_strdup_printf ("%s/%u via %s%s%s\n",
-			                                  dest, prefix, next_hop,
-			                                  options ? " " : "",
-			                                  options ?: "");
-		} else {
-			route_items[i] = g_strdup_printf ("%s/%u via %s metric %u%s%s\n",
-			                                  dest, prefix, next_hop, (guint32) metric,
-			                                  options ? " " : "",
-			                                  options ?: "");
+		g_string_append_printf (contents, "%s/%u",
+		                        nm_ip_route_get_dest (route),
+		                        nm_ip_route_get_prefix (route));
+		if (next_hop)
+			g_string_append_printf (contents, " via %s", next_hop);
+		if (metric >= 0)
+			g_string_append_printf (contents, " metric %u", (guint) metric);
+		if (options) {
+			g_string_append_c (contents, ' ');
+			g_string_append (contents, options);
 		}
+
+		g_string_append_c (contents, '\n');
 	}
-	route_items[num] = NULL;
-	route_contents = g_strjoinv (NULL, route_items);
-	g_strfreev (route_items);
 
-	if (!g_file_set_contents (filename, route_contents, -1, NULL)) {
+	if (!g_file_set_contents (filename, contents->str, contents->len, NULL)) {
 		g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
 		             "Writing route file '%s' failed", filename);
 		return FALSE;
@@ -2073,6 +2067,7 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
 	int timeout;
 	GString *searches;
 	const char *method = NULL;
+	gboolean has_netmask;
 
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
 	if (!s_ip4) {
@@ -2145,16 +2140,7 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
 	else if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED))
 		svSetValueStr (ifcfg, "BOOTPROTO", "shared");
 
-	/* Clear out un-numbered IP address fields */
-	svUnsetValue (ifcfg, "IPADDR");
-	svUnsetValue (ifcfg, "PREFIX");
-	svUnsetValue (ifcfg, "NETMASK");
-	svUnsetValue (ifcfg, "GATEWAY");
-	/* Clear out zero-indexed IP address fields */
-	svUnsetValue (ifcfg, "IPADDR0");
-	svUnsetValue (ifcfg, "PREFIX0");
-	svUnsetValue (ifcfg, "NETMASK0");
-	svUnsetValue (ifcfg, "GATEWAY0");
+	has_netmask = !!svFindFirstKeyWithPrefix (ifcfg, "NETMASK");
 
 	/* Write out IPADDR<n>, PREFIX<n>, GATEWAY<n> for current IP addresses
 	 * without labels. Unset obsolete NETMASK<n>.
@@ -2198,19 +2184,30 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
 		g_free (tmp);
 
 		/* If the legacy "NETMASK" is present, keep it. */
-		if (svGetValue (ifcfg, netmask_key, &tmp)) {
+		if (has_netmask) {
 			char buf[INET_ADDRSTRLEN];
 
-			g_free (tmp);
-			svSetValueStr (ifcfg, netmask_key, nm_utils_inet4_ntop (prefix, buf));
-		}
+			svSetValueStr (ifcfg, netmask_key,
+			               nm_utils_inet4_ntop (nm_utils_ip4_prefix_to_netmask (prefix), buf));
+		} else
+			svUnsetValue (ifcfg, netmask_key);
 
 		svUnsetValue (ifcfg, gw_key);
 		n++;
 	}
 
-	/* Clear remaining IPADDR<n..255>, etc */
-	for (i = n; i < 256; i++) {
+	svUnsetValue (ifcfg, "IPADDR0");
+	svUnsetValue (ifcfg, "PREFIX0");
+	svUnsetValue (ifcfg, "NETMASK0");
+	svUnsetValue (ifcfg, "GATEWAY0");
+	if (n == 0) {
+		svUnsetValue (ifcfg, "IPADDR");
+		svUnsetValue (ifcfg, "PREFIX");
+		svUnsetValue (ifcfg, "NETMASK");
+		i = 1;
+	} else
+		i = n;
+	for (; i < 256; i++) {
 		nm_sprintf_buf (addr_key, "IPADDR%u", i);
 		nm_sprintf_buf (prefix_key, "PREFIX%u", i);
 		nm_sprintf_buf (netmask_key, "NETMASK%u", i);
@@ -2492,32 +2489,33 @@ write_route6_file (const char *filename, NMSettingIPConfig *s_ip6, GError **erro
 	}
 
 	contents = g_string_new ("");
+
 	for (i = 0; i < num; i++) {
 		gs_free char *options = NULL;
+		const char *next_hop;
+		gint64 metric;
 
 		route = nm_setting_ip_config_get_route (s_ip6, i);
+		next_hop = nm_ip_route_get_next_hop (route);
+		metric = nm_ip_route_get_metric (route);
 		options = get_route_attributes_string (route, AF_INET6);
 
-		if (nm_ip_route_get_metric (route) == -1) {
-			g_string_append_printf (contents, "%s/%u via %s%s%s",
-			                                  nm_ip_route_get_dest (route),
-			                                  nm_ip_route_get_prefix (route),
-			                                  nm_ip_route_get_next_hop (route),
-			                                  options ? " " : "",
-			                                  options ?: "");
-		} else {
-			g_string_append_printf (contents, "%s/%u via %s metric %u%s%s",
-			                                  nm_ip_route_get_dest (route),
-			                                  nm_ip_route_get_prefix (route),
-			                                  nm_ip_route_get_next_hop (route),
-			                                  (unsigned) nm_ip_route_get_metric (route),
-			                                  options ? " " : "",
-			                                  options ?: "");
+		g_string_append_printf (contents, "%s/%u",
+		                        nm_ip_route_get_dest (route),
+		                        nm_ip_route_get_prefix (route));
+		if (next_hop)
+			g_string_append_printf (contents, " via %s", next_hop);
+		if (metric >= 0)
+			g_string_append_printf (contents, " metric %u", (guint) metric);
+		if (options) {
+			g_string_append_c (contents, ' ');
+			g_string_append (contents, options);
 		}
-		g_string_append (contents, "\n");
+
+		g_string_append_c (contents, '\n');
 	}
 
-	if (!g_file_set_contents (filename, contents->str, -1, NULL)) {
+	if (!g_file_set_contents (filename, contents->str, contents->len, NULL)) {
 		g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
 		             "Writing route6 file '%s' failed", filename);
 		return FALSE;
diff --git a/src/settings/plugins/ifcfg-rh/shvar.c b/src/settings/plugins/ifcfg-rh/shvar.c
index 9fce5aa1..47ad5a23 100644
--- a/src/settings/plugins/ifcfg-rh/shvar.c
+++ b/src/settings/plugins/ifcfg-rh/shvar.c
@@ -905,6 +905,28 @@ svGetKeys (shvarFile *s)
 
 /*****************************************************************************/
 
+const char *
+svFindFirstKeyWithPrefix (shvarFile *s, const char *key_prefix)
+{
+	const GList *current;
+	const shvarLine *l;
+
+	g_return_val_if_fail (s, NULL);
+	g_return_val_if_fail (key_prefix, NULL);
+
+	for (current = s->lineList; current; current = current->next) {
+		l = current->data;
+		if (   l->key
+		    && l->line
+		    && g_str_has_prefix (l->key, key_prefix))
+			return l->key;
+	}
+
+	return NULL;
+}
+
+/*****************************************************************************/
+
 static const char *
 _svGetValue (shvarFile *s, const char *key, char **to_free)
 {
diff --git a/src/settings/plugins/ifcfg-rh/shvar.h b/src/settings/plugins/ifcfg-rh/shvar.h
index 9d8c2364..a13920a1 100644
--- a/src/settings/plugins/ifcfg-rh/shvar.h
+++ b/src/settings/plugins/ifcfg-rh/shvar.h
@@ -44,6 +44,8 @@ shvarFile *svCreateFile (const char *name);
 /* Open the file <name>, return shvarFile on success, NULL on failure */
 shvarFile *svOpenFile (const char *name, GError **error);
 
+const char *svFindFirstKeyWithPrefix (shvarFile *s, const char *key_prefix);
+
 /* Get the value associated with the key, and leave the current pointer
  * pointing at the line containing the value.  The char* returned MUST
  * be freed by the caller.
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1
new file mode 100644
index 00000000..ecb36c37
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1
@@ -0,0 +1,14 @@
+DNS1="192.0.2.1"
+IPADDR="102.0.2.2"
+GATEWAY="192.0.2.1"
+NETMASK="255.254.0.0"
+BOOTPROTO="static"
+DEVICE="eth1"
+ONBOOT="yes"
+IPV6INIT="yes"
+
+#bogus
+PREFIX1=25
+NETMASK0=255.255.0.0
+
+#end
diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1.cexpected b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1.cexpected
new file mode 100644
index 00000000..5dfdce4d
--- /dev/null
+++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1.cexpected
@@ -0,0 +1,23 @@
+DNS1=192.0.2.1
+IPADDR=102.0.2.2
+GATEWAY=192.0.2.1
+NETMASK=255.254.0.0
+BOOTPROTO="static"
+DEVICE=eth1
+ONBOOT=yes
+IPV6INIT=yes
+
+#bogus
+
+#end
+TYPE=Ethernet
+PROXY_METHOD=none
+BROWSER_ONLY=no
+PREFIX=15
+DEFROUTE=yes
+IPV4_FAILURE_FATAL=no
+IPV6_AUTOCONF=yes
+IPV6_DEFROUTE=yes
+IPV6_FAILURE_FATAL=no
+NAME="System netmask-1"
+UUID=${UUID}
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 babb068d..496a164b 100644
--- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
+++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
@@ -399,6 +399,47 @@ _writer_new_connection_fail (NMConnection *connection,
 
 /*****************************************************************************/
 
+static void
+test_read_netmask_1 (void)
+{
+	nmtst_auto_unlinkfile char *testfile = NULL;
+	gs_unref_object NMConnection *connection = NULL;
+	gs_free char *content = NULL;
+	NMSettingConnection *s_con;
+	NMSettingIPConfig *s_ip4;
+	NMIPAddress *ip4_addr;
+	const char *FILENAME = TEST_IFCFG_DIR "/network-scripts/ifcfg-netmask-1";
+
+	connection = _connection_from_file (FILENAME, NULL, TYPE_ETHERNET, NULL);
+
+	s_con = nm_connection_get_setting_connection (connection);
+	g_assert (s_con);
+	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "System netmask-1");
+
+	s_ip4 = nm_connection_get_setting_ip4_config (connection);
+	g_assert (s_ip4);
+	g_assert_cmpuint (nm_setting_ip_config_get_num_dns (s_ip4), ==, 1);
+	ip4_addr = nm_setting_ip_config_get_address (s_ip4, 0);
+	g_assert (ip4_addr);
+	g_assert_cmpstr (nm_ip_address_get_address (ip4_addr), ==, "102.0.2.2");
+	g_assert_cmpint (nm_ip_address_get_prefix (ip4_addr), ==, 15);
+
+	nmtst_assert_connection_verifies_without_normalization (connection);
+
+	content = nmtst_file_get_contents (FILENAME);
+
+	testfile = g_strdup (TEST_SCRATCH_DIR "/network-scripts/ifcfg-netmask-1.copy");
+
+	nmtst_file_set_contents (testfile, content);
+
+	_writer_update_connection (connection,
+	                           TEST_SCRATCH_DIR "/network-scripts/",
+	                           testfile,
+	                           TEST_IFCFG_DIR "/network-scripts/ifcfg-netmask-1.cexpected");
+}
+
+/*****************************************************************************/
+
 static gboolean
 verify_cert_or_key (NMSetting8021x *s_compare,
                     const char *file,
@@ -4928,15 +4969,16 @@ test_write_wired_aliases (void)
 			if (!g_strcmp0 (addrstr, ip[j]))
 				break;
 		}
-		g_assert (j < num_addresses);
-
-		g_assert_cmpint (nm_ip_address_get_prefix (addr), ==, 24);
-		if (label[j])
-			g_assert_cmpstr (g_variant_get_string (nm_ip_address_get_attribute (addr, "label"), NULL), ==, label[j]);
-		else
-			g_assert (nm_ip_address_get_attribute (addr, "label") == NULL);
-
-		ip[j] = NULL;
+		if (j >= num_addresses)
+			g_assert_not_reached ();
+		else {
+			g_assert_cmpint (nm_ip_address_get_prefix (addr), ==, 24);
+			if (label[j])
+				g_assert_cmpstr (g_variant_get_string (nm_ip_address_get_attribute (addr, "label"), NULL), ==, label[j]);
+			else
+				g_assert (nm_ip_address_get_attribute (addr, "label") == NULL);
+			ip[j] = NULL;
+		}
 	}
 
 	for (i = 0; i < num_addresses; i++)
@@ -9348,6 +9390,8 @@ int main (int argc, char **argv)
 	nmtst_add_test_func (TPATH "read-static",           test_read_wired_static, TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-static",           "System test-wired-static",           GINT_TO_POINTER (TRUE));
 	nmtst_add_test_func (TPATH "read-static-bootproto", test_read_wired_static, TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-static-bootproto", "System test-wired-static-bootproto", GINT_TO_POINTER (FALSE));
 
+	g_test_add_func (TPATH "read-netmask-1", test_read_netmask_1);
+
 	g_test_add_func (TPATH "read-dhcp", test_read_wired_dhcp);
 	g_test_add_func (TPATH "read-dhcp-plus-ip", test_read_wired_dhcp_plus_ip);
 	g_test_add_func (TPATH "read-shared-plus-ip", test_read_wired_shared_plus_ip);