diff --git a/src/settings/plugins/ifupdown/parser.c b/src/settings/plugins/ifupdown/parser.c index 37f98b6e6..97e2ce534 100644 --- a/src/settings/plugins/ifupdown/parser.c +++ b/src/settings/plugins/ifupdown/parser.c @@ -432,15 +432,27 @@ eni_plugin_error_quark() { return error_quark; } - + static void -ifupdown_add_search_item(gpointer data, gpointer user_data) +ifupdown_ip4_add_search_item(gpointer data, gpointer user_data) { const char *dns_search = data; NMSettingIP4Config *ip4_setting = user_data; if (!nm_setting_ip4_config_add_dns_search (ip4_setting, dns_search)) - PLUGIN_WARN ("SCPlugin-Ifupdown", " warning: duplicate DNS domain '%s'", dns_search); + PLUGIN_WARN ("SCPlugin-Ifupdown", + " warning: duplicate DNS domain '%s'", dns_search); +} + +static void +ifupdown_ip6_add_search_item(gpointer data, gpointer user_data) +{ + const char *dns_search = data; + NMSettingIP6Config *ip6_setting = user_data; + + if (!nm_setting_ip6_config_add_dns_search (ip6_setting, dns_search)) + PLUGIN_WARN ("SCPlugin-Ifupdown", + " warning: duplicate DNS domain '%s'", dns_search); } static void @@ -527,8 +539,8 @@ update_ip4_setting_from_if_block(NMConnection *connection, PLUGIN_PRINT("SCPlugin-Ifupdown", "No dns-nameserver configured in /etc/network/interfaces"); /* DNS searches */ - if (search_list) { - g_slist_foreach (search_list, (GFunc) ifupdown_add_search_item, ip4_setting); + if (search_list) { + g_slist_foreach (search_list, (GFunc) ifupdown_ip4_add_search_item, ip4_setting); g_slist_foreach (search_list, (GFunc) g_free, NULL); g_slist_free (search_list); } @@ -544,6 +556,105 @@ update_ip4_setting_from_if_block(NMConnection *connection, nm_connection_add_setting(connection, NM_SETTING(ip4_setting)); } +static void +update_ip6_setting_from_if_block(NMConnection *connection, + if_block *block) +{ + NMSettingIP6Config *ip6_setting = NM_SETTING_IP6_CONFIG (nm_setting_ip6_config_new()); + const char *type = ifparser_getkey(block, "inet6"); + gboolean is_static = type && (!strcmp("static", type) || + !strcmp("v4tunnel", type)); + + if(!is_static) { + g_object_set(ip6_setting, + NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, + NULL); + } else { + struct in6_addr tmp_ip6_addr; + NMIP6Address *ip6_addr = nm_ip6_address_new (); + + const char *address_v = ifparser_getkey(block, "address"); + const char *prefix_v = ifparser_getkey(block, "netmask"); + const char *gateway_v = ifparser_getkey(block, "gateway"); + const char *nameserver_v = ifparser_getkey(block, "dns-nameserver"); + const char *nameservers_v = ifparser_getkey(block, "dns-nameservers"); + const char *search_v = ifparser_getkey(block, "dns-search"); + int prefix_int; + GSList* nameservers_list = NULL; + GSList* nameservers_list_i = NULL; + GSList* search_list = NULL; + GError *error = NULL; + + if(nameservers_v) + nameservers_list_i = nameservers_list = string_to_glist_of_strings (nameservers_v); + if(nameserver_v) + nameservers_list_i = nameservers_list = g_slist_append(nameservers_list, g_strdup(nameserver_v)); + if(search_v) + search_list = string_to_glist_of_strings (search_v); + + if (!address_v) + address_v = g_strdup ("::"); + + if (inet_pton (AF_INET6, address_v, &tmp_ip6_addr)) + nm_ip6_address_set_address (ip6_addr, &tmp_ip6_addr); + else + g_set_error (&error, eni_plugin_error_quark (), 0, + "Invalid %s IP6 address '%s'", "address", address_v); + if (!prefix_v) + prefix_v = g_strdup( "128"); + + prefix_int = g_ascii_strtoll(prefix_v, NULL, 10); + nm_ip6_address_set_prefix (ip6_addr, prefix_int); + + if (!gateway_v) + gateway_v = g_strdup (address_v); + + if (inet_pton (AF_INET, gateway_v, &tmp_ip6_addr)) + nm_ip6_address_set_gateway (ip6_addr, &tmp_ip6_addr); + else + g_set_error (&error, eni_plugin_error_quark (), 0, + "Invalid %s IP6 address '%s'", "gateway", gateway_v); + + if (nm_setting_ip6_config_add_address (ip6_setting, ip6_addr)) { + PLUGIN_PRINT("SCPlugin-Ifupdown", "addresses count: %d", + nm_setting_ip6_config_get_num_addresses (ip6_setting)); + } else { + PLUGIN_PRINT("SCPlugin-Ifupdown", "ignoring duplicate IP6 address"); + } + + while (nameservers_list_i) { + gchar *dns = nameservers_list_i->data; + nameservers_list_i = nameservers_list_i->next; + if (!dns) + continue; + if (inet_pton (AF_INET6, dns, &tmp_ip6_addr)) { + if (!nm_setting_ip6_config_add_dns (ip6_setting, &tmp_ip6_addr)) + PLUGIN_PRINT("SCPlugin-Ifupdown", "ignoring duplicate DNS server '%s'", dns); + } else + g_set_error (&error, eni_plugin_error_quark (), 0, + "Invalid %s IP6 address nameserver '%s'", "nameserver", dns); + } + if (!nm_setting_ip6_config_get_num_dns (ip6_setting)) + PLUGIN_PRINT("SCPlugin-Ifupdown", "No dns-nameserver configured in /etc/network/interfaces"); + + /* DNS searches */ + if (search_list) { + g_slist_foreach (search_list, (GFunc) ifupdown_ip6_add_search_item, ip6_setting); + g_slist_foreach (search_list, (GFunc) g_free, NULL); + g_slist_free (search_list); + } + + g_object_set (ip6_setting, + NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_MANUAL, + NULL); + + g_slist_foreach (nameservers_list, (GFunc) g_free, NULL); + g_slist_free (nameservers_list); + } + + nm_connection_add_setting(connection, NM_SETTING(ip6_setting)); +} + gboolean ifupdown_update_connection_from_if_block (NMConnection *connection, if_block *block, @@ -581,13 +692,16 @@ ifupdown_update_connection_from_if_block (NMConnection *connection, block->name, type, idstr, nm_setting_connection_get_uuid (s_con)); if (!strcmp (NM_SETTING_WIRED_SETTING_NAME, type)) - update_wired_setting_from_if_block (connection, block); + update_wired_setting_from_if_block (connection, block); else if (!strcmp (NM_SETTING_WIRELESS_SETTING_NAME, type)) { update_wireless_setting_from_if_block (connection, block); update_wireless_security_setting_from_if_block (connection, block); } - update_ip4_setting_from_if_block (connection, block); + if (ifparser_haskey(block, "inet6")) + update_ip6_setting_from_if_block (connection, block); + else + update_ip4_setting_from_if_block (connection, block); success = nm_connection_verify (connection, error); diff --git a/src/settings/plugins/ifupdown/tests/test-ifupdown.c b/src/settings/plugins/ifupdown/tests/test-ifupdown.c index 312e37ff9..01020bdfd 100644 --- a/src/settings/plugins/ifupdown/tests/test-ifupdown.c +++ b/src/settings/plugins/ifupdown/tests/test-ifupdown.c @@ -637,6 +637,207 @@ test17_read_static_ipv4 (const char *path) g_object_unref (connection); } +static void +test18_read_static_ipv6 (const char *path) +{ + NMConnection *connection; + NMSettingConnection *s_con; + NMSettingIP6Config *s_ip6; + NMSettingWired *s_wired; + char *unmanaged = NULL; + GError *error = NULL; + const char* tmp; + const char *expected_address = "fc00::1"; + const char *expected_id = "Ifupdown (myip6tunnel)"; + const char *expected_dns1 = "fc00::2"; + const char *expected_dns2 = "fc00::3"; + const char *expected_search1 = "example.com"; + const char *expected_search2 = "foo.example.com"; + guint32 expected_prefix = 64; + NMIP6Address *ip6_addr; + struct in6_addr addr; + if_block *block = NULL; +#define TEST18_NAME "wired-static-verify-ip6" + const char* file = "test18-" TEST18_NAME; + + init_ifparser_with_file (path, file); + block = ifparser_getfirst (); + connection = nm_connection_new(); + ifupdown_update_connection_from_if_block(connection, block, &error); + + ASSERT (connection != NULL, + TEST18_NAME + "failed to read %s: %s", file, error->message); + + ASSERT (nm_connection_verify (connection, &error), + TEST18_NAME, + "failed to verify %s: %s", file, error->message); + + ASSERT (unmanaged == NULL, + TEST18_NAME, + "failed to verify %s: unexpected unmanaged value", file); + + /* ===== CONNECTION SETTING ===== */ + + s_con = nm_connection_get_setting_connection (connection); + ASSERT (s_con != NULL, + TEST18_NAME, "failed to verify %s: missing %s setting", + file, + NM_SETTING_CONNECTION_SETTING_NAME); + + /* ID */ + tmp = nm_setting_connection_get_id (s_con); + ASSERT (tmp != NULL, + TEST18_NAME, + "failed to verify %s: missing %s / %s key", + file, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_ID); + + ASSERT (strcmp (tmp, expected_id) == 0, + TEST18_NAME, + "failed to verify %s: unexpected %s / %s key value", + file, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_ID); + + /* ===== WIRED SETTING ===== */ + + s_wired = nm_connection_get_setting_wired (connection); + ASSERT (s_wired != NULL, + TEST18_NAME, "failed to verify %s: missing %s setting", + file, + NM_SETTING_WIRED_SETTING_NAME); + + /* ===== IPv6 SETTING ===== */ + + ASSERT (inet_pton (AF_INET6, expected_address, &addr) > 0, + TEST18_NAME, + "failed to verify %s: couldn't convert IP address #1", + file); + + s_ip6 = nm_connection_get_setting_ip6_config (connection); + ASSERT (s_ip6 != NULL, + TEST18_NAME, + "failed to verify %s: missing %s setting", + file, + NM_SETTING_IP6_CONFIG_SETTING_NAME); + + /* Method */ + tmp = nm_setting_ip6_config_get_method (s_ip6); + ASSERT (strcmp (tmp, NM_SETTING_IP6_CONFIG_METHOD_MANUAL) == 0, + TEST18_NAME, + "failed to verify %s: unexpected %s / %s key value", + file, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_METHOD); + + /* IP addresses */ + ASSERT (nm_setting_ip6_config_get_num_addresses (s_ip6) == 1, + TEST18_NAME, + "failed to verify %s: unexpected number of %s / %s", + file, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_ADDRESSES); + + ip6_addr = nm_setting_ip6_config_get_address (s_ip6, 0); + ASSERT (ip6_addr, + TEST18_NAME, + "failed to verify %s: missing %s / %s #1", + file, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_ADDRESSES); + + ASSERT (nm_ip6_address_get_prefix (ip6_addr) == expected_prefix, + TEST18_NAME + "failed to verify %s: unexpected %s / %s prefix", + file, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_ADDRESSES); + + ASSERT (IN6_ARE_ADDR_EQUAL (nm_ip6_address_get_address (ip6_addr), + &addr), + TEST18_NAME, + "failed to verify %s: unexpected %s / %s", + file, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_ADDRESSES); + + /* DNS Addresses */ + ASSERT (nm_setting_ip6_config_get_num_dns (s_ip6) == 2, + TEST18_NAME, + "failed to verify %s: unexpected number of %s / %s values", + file, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_DNS); + + ASSERT (inet_pton (AF_INET6, expected_dns1, &addr) > 0, + TEST18_NAME, + "failed to verify %s: couldn't convert DNS IP address #1", + file); + + ASSERT (IN6_ARE_ADDR_EQUAL (nm_setting_ip6_config_get_dns (s_ip6, 0), + &addr), + TEST18_NAME, + "failed to verify %s: unexpected %s / %s #1", + file, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_DNS); + + ASSERT (inet_pton (AF_INET6, expected_dns2, &addr) > 0, + TEST18_NAME, + "failed to verify %s: couldn't convert DNS IP address #2", + file); + + ASSERT (IN6_ARE_ADDR_EQUAL (nm_setting_ip6_config_get_dns (s_ip6, 1), + &addr), + TEST18_NAME, "failed to verify %s: unexpected %s / %s #2", + file, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_DNS); + + /* DNS search domains */ + ASSERT (nm_setting_ip6_config_get_num_dns_searches (s_ip6) == 2, + TEST18_NAME, + "failed to verify %s: unexpected number of %s / %s values", + file, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_DNS_SEARCH); + + tmp = nm_setting_ip6_config_get_dns_search (s_ip6, 0); + ASSERT (tmp != NULL, + "wired-ipv6-manual-verify-ip6", + "failed to verify %s: missing %s / %s #1", + file, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_DNS_SEARCH); + + ASSERT (strcmp (tmp, expected_search1) == 0, + "wired-ipv6-manual-verify-ip6", + "failed to verify %s: unexpected %s / %s #1", + file, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_DNS_SEARCH); + + tmp = nm_setting_ip6_config_get_dns_search (s_ip6, 1); + ASSERT (tmp != NULL, + TEST18_NAME, + "failed to verify %s: missing %s / %s #2", + file, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_DNS_SEARCH); + + ASSERT (strcmp (tmp, expected_search2) == 0, + TEST18_NAME, + "failed to verify %s: unexpected %s / %s #2", + file, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_DNS_SEARCH); + + g_free (unmanaged); + g_object_unref (connection); +} + #if GLIB_CHECK_VERSION(2,25,12) typedef GTestFixtureFunc TCFunc; @@ -679,6 +880,7 @@ int main (int argc, char **argv) g_test_suite_add (suite, TESTCASE (test15_trailing_space, TEST_ENI_DIR)); g_test_suite_add (suite, TESTCASE (test16_missing_newline, TEST_ENI_DIR)); g_test_suite_add (suite, TESTCASE (test17_read_static_ipv4, TEST_ENI_DIR)); + g_test_suite_add (suite, TESTCASE (test18_read_static_ipv6, TEST_ENI_DIR)); return g_test_run (); } diff --git a/src/settings/plugins/ifupdown/tests/test18-wired-static-verify-ip6 b/src/settings/plugins/ifupdown/tests/test18-wired-static-verify-ip6 new file mode 100644 index 000000000..29546a611 --- /dev/null +++ b/src/settings/plugins/ifupdown/tests/test18-wired-static-verify-ip6 @@ -0,0 +1,6 @@ +iface myip6tunnel inet6 v4tunnel + address fc00::1 + netmask 64 + endpoint 78.35.24.124 + dns-nameservers fc00::2 fc00::3 + dns-search example.com foo.example.com