diff --git a/src/settings/plugins/ifcfg-rh/reader.c b/src/settings/plugins/ifcfg-rh/reader.c index b2abfff854..0957e82a5c 100644 --- a/src/settings/plugins/ifcfg-rh/reader.c +++ b/src/settings/plugins/ifcfg-rh/reader.c @@ -1359,26 +1359,8 @@ make_ip4_setting (shvarFile *ifcfg, if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0) return NM_SETTING (s_ip4); - /* Handle manual settings */ - if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) { - for (i = -1; i < 256; i++) { - NMIP4Address *addr = NULL; - - if (!read_full_ip4_address (ifcfg, network_file, i, &addr, error)) - goto done; - if (!addr) { - /* The first mandatory variable is 2-indexed (IPADDR2) - * Variables IPADDR, IPADDR0 and IPADDR1 are optional */ - if (i > 1) - break; - continue; - } - - if (!nm_setting_ip4_config_add_address (s_ip4, addr)) - PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: duplicate IP4 address"); - nm_ip4_address_unref (addr); - } - } else if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) { + /* Handle DHCP settings */ + if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) { value = svGetValue (ifcfg, "DHCP_HOSTNAME", FALSE); if (value && strlen (value)) g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME, value, NULL); @@ -1390,6 +1372,29 @@ make_ip4_setting (shvarFile *ifcfg, g_free (value); } + /* Read static IP addresses. + * Read them even for AUTO method - in this case the addresses are + * added to the automatic ones. Note that this is not currently supported by + * the legacy 'network' service (ifup-eth). + */ + for (i = -1; i < 256; i++) { + NMIP4Address *addr = NULL; + + if (!read_full_ip4_address (ifcfg, network_file, i, &addr, error)) + goto done; + if (!addr) { + /* The first mandatory variable is 2-indexed (IPADDR2) + * Variables IPADDR, IPADDR0 and IPADDR1 are optional */ + if (i > 1) + break; + continue; + } + + if (!nm_setting_ip4_config_add_address (s_ip4, addr)) + PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: duplicate IP4 address"); + nm_ip4_address_unref (addr); + } + /* DNS servers * Pick up just IPv4 addresses (IPv6 addresses are taken by make_ip6_setting()) */ @@ -1516,6 +1521,8 @@ make_ip6_setting (shvarFile *ifcfg, char *route6_path = NULL; gboolean ipv6init, ipv6forwarding, ipv6_autoconf, dhcp6 = FALSE; char *method = NM_SETTING_IP6_CONFIG_METHOD_MANUAL; + char *ipv6addr, *ipv6addr_secondaries; + char **list = NULL, **iter; guint32 i; shvarFile *network_ifcfg; gboolean never_default = FALSE; @@ -1632,38 +1639,8 @@ make_ip6_setting (shvarFile *ifcfg, if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) == 0) return NM_SETTING (s_ip6); - if (!strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) { - char *val; - char *ipv6addr, *ipv6addr_secondaries; - char **list = NULL, **iter; - - ipv6addr = svGetValue (ifcfg, "IPV6ADDR", FALSE); - ipv6addr_secondaries = svGetValue (ifcfg, "IPV6ADDR_SECONDARIES", FALSE); - - val = g_strjoin (ipv6addr && ipv6addr_secondaries ? " " : NULL, - ipv6addr ? ipv6addr : "", - ipv6addr_secondaries ? ipv6addr_secondaries : "", - NULL); - g_free (ipv6addr); - g_free (ipv6addr_secondaries); - - list = g_strsplit_set (val, " ", 0); - g_free (val); - for (iter = list, i = 0; iter && *iter; iter++, i++) { - NMIP6Address *addr = NULL; - - if (!parse_full_ip6_address (ifcfg, network_file, *iter, i, &addr, error)) { - g_strfreev (list); - goto error; - } - - if (!nm_setting_ip6_config_add_address (s_ip6, addr)) - PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: duplicate IP6 address"); - nm_ip6_address_unref (addr); - } - g_strfreev (list); - } else if ( !strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) - || !strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP)) { + if ( !strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) + || !strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP)) { /* METHOD_AUTO may trigger DHCPv6, so save the hostname to send to DHCP */ value = svGetValue (ifcfg, "DHCP_HOSTNAME", FALSE); if (value && value[0]) @@ -1671,6 +1648,37 @@ make_ip6_setting (shvarFile *ifcfg, g_free (value); } + /* Read static IP addresses. + * Read them even for AUTO and DHCP methods - in this case the addresses are + * added to the automatic ones. Note that this is not currently supported by + * the legacy 'network' service (ifup-eth). + */ + ipv6addr = svGetValue (ifcfg, "IPV6ADDR", FALSE); + ipv6addr_secondaries = svGetValue (ifcfg, "IPV6ADDR_SECONDARIES", FALSE); + + value = g_strjoin (ipv6addr && ipv6addr_secondaries ? " " : NULL, + ipv6addr ? ipv6addr : "", + ipv6addr_secondaries ? ipv6addr_secondaries : "", + NULL); + g_free (ipv6addr); + g_free (ipv6addr_secondaries); + + list = g_strsplit_set (value, " ", 0); + g_free (value); + for (iter = list, i = 0; iter && *iter; iter++, i++) { + NMIP6Address *addr = NULL; + + if (!parse_full_ip6_address (ifcfg, network_file, *iter, i, &addr, error)) { + g_strfreev (list); + goto error; + } + + if (!nm_setting_ip6_config_add_address (s_ip6, addr)) + PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: duplicate IP6 address"); + nm_ip6_address_unref (addr); + } + g_strfreev (list); + /* DNS servers * Pick up just IPv6 addresses (IPv4 addresses are taken by make_ip4_setting()) */ 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 9f0c7334f4..ee9b5db9f8 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am @@ -5,6 +5,7 @@ EXTRA_DIST = \ ifcfg-test-wired-static \ ifcfg-test-wired-static-bootproto \ ifcfg-test-wired-dhcp \ + ifcfg-test-wired-dhcp-plus-ip \ ifcfg-test-wired-dhcp6-only \ ifcfg-test-wired-global-gateway \ network-test-wired-global-gateway \ diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp-plus-ip b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp-plus-ip new file mode 100644 index 0000000000..f0c022a9d0 --- /dev/null +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp-plus-ip @@ -0,0 +1,26 @@ +# Intel Corporation 82540EP Gigabit Ethernet Controller (Mobile) +TYPE=Ethernet +DEVICE=eth0 +HWADDR=00:11:22:33:44:ee +BOOTPROTO=dhcp +ONBOOT=yes +IPV6INIT=yes +IPV6_AUTOCONF=yes +USERCTL=yes +NM_CONTROLLED=yes +PEERDNS=no +DNS1=4.2.2.1 +DNS2=4.2.2.2 +DNS3=1:2:3:4::a +DNS4=1:2:3:4::b + +# additional IPs +IPADDR0=1.2.3.4 +PREFIX0=24 +GATEWAY0=1.1.1.1 +IPADDR1=9.8.7.6 +PREFIX1=16 + +IPV6ADDR="1001:abba::1234/56" +IPV6ADDR_SECONDARIES="2001:abba::2234/64 3001:abba::3234/96" + 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 43d07bcee7..51aef533a4 100644 --- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -666,6 +666,93 @@ test_read_wired_dhcp (void) g_object_unref (connection); } +static void +test_read_wired_dhcp_plus_ip (void) +{ + NMConnection *connection; + NMSettingIP4Config *s_ip4; + NMSettingIP6Config *s_ip6; + GError *error = NULL; + guint32 addr4; + struct in6_addr addr6; + NMIP4Address *ip4_addr; + NMIP6Address *ip6_addr; + gboolean success; + + connection = connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-dhcp-plus-ip", + NULL, TYPE_ETHERNET, NULL, NULL, + NULL, NULL, NULL, &error, NULL); + g_assert_no_error (error); + g_assert (connection); + success = nm_connection_verify (connection, &error); + g_assert_no_error (error); + g_assert (success); + + /* ===== IPv4 SETTING ===== */ + s_ip4 = nm_connection_get_setting_ip4_config (connection); + g_assert (s_ip4); + g_assert_cmpstr (nm_setting_ip4_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); + g_assert (nm_setting_ip4_config_get_may_fail (s_ip4)); + + /* DNS Addresses */ + g_assert_cmpint (nm_setting_ip4_config_get_num_dns (s_ip4), ==, 2); + g_assert_cmpint (inet_pton (AF_INET, "4.2.2.1", &addr4), >, 0); + g_assert_cmpint (nm_setting_ip4_config_get_dns (s_ip4, 0), ==, addr4); + g_assert_cmpint (inet_pton (AF_INET, "4.2.2.2", &addr4), >, 0); + g_assert_cmpint (nm_setting_ip4_config_get_dns (s_ip4, 1), ==, addr4); + + /* IP addresses */ + g_assert_cmpint (nm_setting_ip4_config_get_num_addresses (s_ip4), ==, 2); + ip4_addr = nm_setting_ip4_config_get_address (s_ip4, 0); + g_assert (ip4_addr); + g_assert_cmpint (nm_ip4_address_get_prefix (ip4_addr), ==, 24); + g_assert_cmpint (inet_pton (AF_INET, "1.2.3.4", &addr4), >, 0); + g_assert_cmpint (nm_ip4_address_get_address (ip4_addr), ==, addr4); + g_assert_cmpint (inet_pton (AF_INET, "1.1.1.1", &addr4), >, 0); + g_assert_cmpint (nm_ip4_address_get_gateway (ip4_addr), ==, addr4); + + ip4_addr = nm_setting_ip4_config_get_address (s_ip4, 1); + g_assert (ip4_addr); + g_assert_cmpint (nm_ip4_address_get_prefix (ip4_addr), ==, 16); + g_assert_cmpint (inet_pton (AF_INET, "9.8.7.6", &addr4), >, 0); + g_assert_cmpint (nm_ip4_address_get_address (ip4_addr), ==, addr4); + + /* ===== IPv6 SETTING ===== */ + s_ip6 = nm_connection_get_setting_ip6_config (connection); + g_assert (s_ip6); + g_assert_cmpstr (nm_setting_ip6_config_get_method (s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO); + g_assert (nm_setting_ip6_config_get_may_fail (s_ip6)); + + /* DNS Addresses */ + g_assert_cmpint (nm_setting_ip6_config_get_num_dns (s_ip6), ==, 2); + g_assert_cmpint (inet_pton (AF_INET6, "1:2:3:4::a", &addr6), >, 0); + g_assert (IN6_ARE_ADDR_EQUAL (nm_setting_ip6_config_get_dns (s_ip6, 0), &addr6)); + g_assert_cmpint (inet_pton (AF_INET6, "1:2:3:4::b", &addr6), >, 0); + g_assert (IN6_ARE_ADDR_EQUAL (nm_setting_ip6_config_get_dns (s_ip6, 1), &addr6)); + + /* IP addresses */ + g_assert_cmpint (nm_setting_ip6_config_get_num_addresses (s_ip6), ==, 3); + ip6_addr = nm_setting_ip6_config_get_address (s_ip6, 0); + g_assert (ip6_addr); + g_assert_cmpint (nm_ip6_address_get_prefix (ip6_addr), ==, 56); + g_assert_cmpint (inet_pton (AF_INET6, "1001:abba::1234", &addr6), >, 0); + g_assert (IN6_ARE_ADDR_EQUAL (nm_ip6_address_get_address (ip6_addr), &addr6)); + + ip6_addr = nm_setting_ip6_config_get_address (s_ip6, 1); + g_assert (ip6_addr); + g_assert_cmpint (nm_ip6_address_get_prefix (ip6_addr), ==, 64); + g_assert_cmpint (inet_pton (AF_INET6, "2001:abba::2234", &addr6), >, 0); + g_assert (IN6_ARE_ADDR_EQUAL (nm_ip6_address_get_address (ip6_addr), &addr6)); + + ip6_addr = nm_setting_ip6_config_get_address (s_ip6, 2); + g_assert (ip6_addr); + g_assert_cmpint (nm_ip6_address_get_prefix (ip6_addr), ==, 96); + g_assert_cmpint (inet_pton (AF_INET6, "3001:abba::3234", &addr6), >, 0); + g_assert (IN6_ARE_ADDR_EQUAL (nm_ip6_address_get_address (ip6_addr), &addr6)); + + g_object_unref (connection); +} + #define TEST_IFCFG_WIRED_GLOBAL_GATEWAY TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-global-gateway" #define TEST_NETWORK_WIRED_GLOBAL_GATEWAY TEST_IFCFG_DIR"/network-scripts/network-test-wired-global-gateway" @@ -6386,6 +6473,49 @@ test_write_wired_dhcp (void) g_object_unref (reread); } +static void +test_write_wired_dhcp_plus_ip (void) +{ + NMConnection *connection, *reread; + char *written = NULL; + GError *error = NULL; + gboolean success = FALSE; + + connection = connection_from_file (TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-dhcp-plus-ip", + NULL, TYPE_ETHERNET, NULL, NULL, + NULL, NULL, NULL, &error, NULL); + g_assert_no_error (error); + g_assert (connection != NULL); + + success = writer_new_connection (connection, + TEST_SCRATCH_DIR "/network-scripts/", + &written, + &error); + g_assert (success); + + /* reread will be normalized, so we must normalize connection too. */ + nm_utils_normalize_connection (connection, TRUE); + + /* re-read the connection for comparison */ + reread = connection_from_file (written, NULL, TYPE_ETHERNET, NULL, NULL, + NULL, NULL, NULL, &error, NULL); + unlink (written); + g_free (written); + + g_assert_no_error (error); + g_assert (reread != NULL); + + success = nm_connection_verify (reread, &error); + g_assert_no_error (error); + g_assert (success); + + success = nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT); + g_assert (success); + + g_object_unref (connection); + g_object_unref (reread); +} + static void test_write_wired_static_ip6_only (void) { @@ -12627,6 +12757,7 @@ int main (int argc, char **argv) test_read_wired_static (TEST_IFCFG_WIRED_STATIC, "System test-wired-static", TRUE); test_read_wired_static (TEST_IFCFG_WIRED_STATIC_BOOTPROTO, "System test-wired-static-bootproto", FALSE); test_read_wired_dhcp (); + g_test_add_func (TPATH "dhcp-plus-ip", test_read_wired_dhcp_plus_ip); test_read_wired_global_gateway (); test_read_wired_never_default (); test_read_wired_defroute_no (); @@ -12688,6 +12819,7 @@ int main (int argc, char **argv) test_write_wired_static_routes (); test_read_write_static_routes_legacy (); test_write_wired_dhcp (); + g_test_add_func (TPATH "dhcp-plus-ip", test_write_wired_dhcp_plus_ip); test_write_wired_dhcp_8021x_peap_mschapv2 (); test_write_wired_8021x_tls (NM_SETTING_802_1X_CK_SCHEME_PATH, NM_SETTING_SECRET_FLAG_AGENT_OWNED); test_write_wired_8021x_tls (NM_SETTING_802_1X_CK_SCHEME_PATH, NM_SETTING_SECRET_FLAG_NOT_SAVED); diff --git a/src/settings/plugins/ifcfg-rh/writer.c b/src/settings/plugins/ifcfg-rh/writer.c index 11e1d7b90a..077f1be9d4 100644 --- a/src/settings/plugins/ifcfg-rh/writer.c +++ b/src/settings/plugins/ifcfg-rh/writer.c @@ -1955,6 +1955,7 @@ write_ip6_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) guint32 i, num, num4; GString *searches; char buf[INET6_ADDRSTRLEN]; + char ipv6_defaultgw[INET6_ADDRSTRLEN]; NMIP6Address *addr; const struct in6_addr *ip; GString *ip_str1, *ip_str2, *ip_ptr; @@ -2005,51 +2006,41 @@ write_ip6_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) /* TODO */ } - if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) { - char ipv6_defaultgw[INET6_ADDRSTRLEN]; + /* Write out IP addresses */ + num = nm_setting_ip6_config_get_num_addresses (s_ip6); + ip_str1 = g_string_new (NULL); + ip_str2 = g_string_new (NULL); + ipv6_defaultgw[0] = 0; + for (i = 0; i < num; i++) { + if (i == 0) + ip_ptr = ip_str1; + else + ip_ptr = ip_str2; - /* Write out IP addresses */ - num = nm_setting_ip6_config_get_num_addresses (s_ip6); + addr = nm_setting_ip6_config_get_address (s_ip6, i); + ip = nm_ip6_address_get_address (addr); + prefix = g_strdup_printf ("%u", nm_ip6_address_get_prefix (addr)); + memset (buf, 0, sizeof (buf)); + inet_ntop (AF_INET6, (const void *) ip, buf, sizeof (buf)); + if (i > 1) + g_string_append_c (ip_ptr, ' '); /* separate addresses in IPV6ADDR_SECONDARIES */ + g_string_append (ip_ptr, buf); + g_string_append_c (ip_ptr, '/'); + g_string_append (ip_ptr, prefix); + g_free (prefix); - ip_str1 = g_string_new (NULL); - ip_str2 = g_string_new (NULL); - ipv6_defaultgw[0] = 0; - for (i = 0; i < num; i++) { - if (i == 0) - ip_ptr = ip_str1; - else - ip_ptr = ip_str2; - - addr = nm_setting_ip6_config_get_address (s_ip6, i); - ip = nm_ip6_address_get_address (addr); - prefix = g_strdup_printf ("%u", nm_ip6_address_get_prefix (addr)); - memset (buf, 0, sizeof (buf)); - inet_ntop (AF_INET6, (const void *) ip, buf, sizeof (buf)); - if (i > 1) - g_string_append_c (ip_ptr, ' '); /* separate addresses in IPV6ADDR_SECONDARIES */ - g_string_append (ip_ptr, buf); - g_string_append_c (ip_ptr, '/'); - g_string_append (ip_ptr, prefix); - g_free (prefix); - - /* We only support gateway for the first IP address for now */ - if (i == 0) { - ip = nm_ip6_address_get_gateway (addr); - if (!IN6_IS_ADDR_UNSPECIFIED (ip)) - inet_ntop (AF_INET6, ip, ipv6_defaultgw, sizeof (ipv6_defaultgw)); - } + /* We only support gateway for the first IP address for now */ + if (i == 0) { + ip = nm_ip6_address_get_gateway (addr); + if (!IN6_IS_ADDR_UNSPECIFIED (ip)) + inet_ntop (AF_INET6, ip, ipv6_defaultgw, sizeof (ipv6_defaultgw)); } - - svSetValue (ifcfg, "IPV6ADDR", ip_str1->str, FALSE); - svSetValue (ifcfg, "IPV6ADDR_SECONDARIES", ip_str2->str, FALSE); - svSetValue (ifcfg, "IPV6_DEFAULTGW", ipv6_defaultgw, FALSE); - g_string_free (ip_str1, TRUE); - g_string_free (ip_str2, TRUE); - } else { - svSetValue (ifcfg, "IPV6ADDR", NULL, FALSE); - svSetValue (ifcfg, "IPV6ADDR_SECONDARIES", NULL, FALSE); - svSetValue (ifcfg, "IPV6_DEFAULTGW", NULL, FALSE); } + svSetValue (ifcfg, "IPV6ADDR", ip_str1->str, FALSE); + svSetValue (ifcfg, "IPV6ADDR_SECONDARIES", ip_str2->str, FALSE); + svSetValue (ifcfg, "IPV6_DEFAULTGW", ipv6_defaultgw, FALSE); + g_string_free (ip_str1, TRUE); + g_string_free (ip_str2, TRUE); /* Write out DNS - 'DNS' key is used both for IPv4 and IPv6 */ s_ip4 = nm_connection_get_setting_ip4_config (connection);