diff --git a/system-settings/plugins/ifcfg-rh/reader.c b/system-settings/plugins/ifcfg-rh/reader.c index a445d5b17..32575f395 100644 --- a/system-settings/plugins/ifcfg-rh/reader.c +++ b/system-settings/plugins/ifcfg-rh/reader.c @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2008 - 2009 Red Hat, Inc. + * Copyright (C) 2008 - 2010 Red Hat, Inc. */ #include @@ -1115,6 +1115,7 @@ static NMSetting * make_ip4_setting (shvarFile *ifcfg, const char *network_file, const char *iscsiadm_path, + gboolean valid_ip6_config, GError **error) { NMSettingIP4Config *s_ip4 = NULL; @@ -1192,14 +1193,17 @@ make_ip4_setting (shvarFile *ifcfg, g_set_error (error, ifcfg_plugin_error_quark (), 0, "Unknown BOOTPROTO '%s'", value); g_free (value); - goto error; + goto done; } g_free (value); } else { char *tmp_ip4, *tmp_prefix, *tmp_netmask; - /* If there is no BOOTPROTO, no IPADDR, no PREFIX, and no NETMASK, - * assume DHCP is to be used. Happens with minimal ifcfg files like: + /* If there is no BOOTPROTO, no IPADDR, no PREFIX, no NETMASK, but + * valid IPv6 configuration, assume that IPv4 is disabled. Otherwise, + * if there is no IPv6 configuration, assume DHCP is to be used. + * Happens with minimal ifcfg files like the following that anaconda + * sometimes used to write out: * * DEVICE=eth0 * HWADDR=11:22:33:44:55:66 @@ -1208,8 +1212,14 @@ make_ip4_setting (shvarFile *ifcfg, tmp_ip4 = svGetValue (ifcfg, "IPADDR", FALSE); tmp_prefix = svGetValue (ifcfg, "PREFIX", FALSE); tmp_netmask = svGetValue (ifcfg, "NETMASK", FALSE); - if (!tmp_ip4 && !tmp_prefix && !tmp_netmask) + if (!tmp_ip4 && !tmp_prefix && !tmp_netmask) { + if (valid_ip6_config) { + /* Nope, no IPv4 */ + goto done; + } + method = NM_SETTING_IP4_CONFIG_METHOD_AUTO; + } g_free (tmp_ip4); g_free (tmp_prefix); g_free (tmp_netmask); @@ -1229,7 +1239,7 @@ make_ip4_setting (shvarFile *ifcfg, for (i = 1; i < 256; i++) { addr = read_full_ip4_address (ifcfg, network_file, i, error); if (error && *error) - goto error; + goto done; if (!addr) break; @@ -1271,7 +1281,7 @@ make_ip4_setting (shvarFile *ifcfg, } if (!tmp_success) { g_free (tag); - goto error; + goto done; } g_clear_error (error); } @@ -1305,7 +1315,7 @@ make_ip4_setting (shvarFile *ifcfg, if (!route_path) { g_set_error (error, ifcfg_plugin_error_quark (), 0, "Could not get route file path for '%s'", ifcfg->fileName); - goto error; + goto done; } /* First test new/legacy syntax */ @@ -1319,7 +1329,7 @@ make_ip4_setting (shvarFile *ifcfg, route = read_one_ip4_route (route_ifcfg, network_file, i, error); if (error && *error) { svCloseFile (route_ifcfg); - goto error; + goto done; } if (!route) break; @@ -1334,7 +1344,7 @@ make_ip4_setting (shvarFile *ifcfg, read_route_file_legacy (route_path, s_ip4, error); g_free (route_path); if (error && *error) - goto error; + goto done; } /* Legacy value NM used for a while but is incorrect (rh #459370) */ @@ -1360,7 +1370,7 @@ make_ip4_setting (shvarFile *ifcfg, return NM_SETTING (s_ip4); -error: +done: g_object_unref (s_ip4); return NULL; } @@ -3058,6 +3068,7 @@ connection_from_file (const char *filename, NMSetting *s_ip4, *s_ip6; const char *ifcfg_name = NULL; gboolean nm_controlled = TRUE; + gboolean ip6_used = FALSE; g_return_val_if_fail (filename != NULL, NULL); g_return_val_if_fail (unmanaged != NULL, NULL); @@ -3161,22 +3172,27 @@ connection_from_file (const char *filename, if (!connection || *unmanaged) goto done; - s_ip4 = make_ip4_setting (parsed, network_file, iscsiadm_path, error); - if (*error) { - g_object_unref (connection); - connection = NULL; - goto done; - } else if (s_ip4) { - nm_connection_add_setting (connection, s_ip4); - } - s_ip6 = make_ip6_setting (parsed, network_file, iscsiadm_path, error); if (*error) { g_object_unref (connection); connection = NULL; goto done; - } else if (s_ip6) + } else if (s_ip6) { + const char *method; + nm_connection_add_setting (connection, s_ip6); + method = nm_setting_ip6_config_get_method (NM_SETTING_IP6_CONFIG (s_ip6)); + if (method && strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) + ip6_used = TRUE; + } + + s_ip4 = make_ip4_setting (parsed, network_file, iscsiadm_path, ip6_used, error); + if (*error) { + g_object_unref (connection); + connection = NULL; + goto done; + } else if (s_ip4) + nm_connection_add_setting (connection, s_ip4); /* iSCSI / ibft connections are read-only since their settings are * stored in NVRAM and can only be changed in BIOS. diff --git a/system-settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am b/system-settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am index b5c94dd3b..f6879633d 100644 --- a/system-settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am +++ b/system-settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am @@ -57,7 +57,8 @@ EXTRA_DIST = \ route6-test-wired-ipv6-manual \ ifcfg-test-wired-static-no-prefix-8 \ ifcfg-test-wired-static-no-prefix-16 \ - ifcfg-test-wired-static-no-prefix-24 + ifcfg-test-wired-static-no-prefix-24 \ + ifcfg-test-wired-ipv6-only check-local: @for f in $(EXTRA_DIST); do \ diff --git a/system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv6-only b/system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv6-only new file mode 100644 index 000000000..59ec32e5b --- /dev/null +++ b/system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv6-only @@ -0,0 +1,14 @@ +# Intel Corporation 82567LM Gigabit Network Connection +TYPE=Ethernet +DEVICE=eth2 +HWADDR=00:11:22:33:44:ee +ONBOOT=yes +USERCTL=yes +NM_CONTROLLED=yes +PEERDNS=yes +DNS1=1:2:3:4::a +DOMAIN="lorem.com ipsum.org dolor.edu" +IPV6INIT=yes +IPV6_AUTOCONF=no +IPV6ADDR="1001:abba::1234/56" + diff --git a/system-settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/system-settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c index 8855a3219..cfe93d6ec 100644 --- a/system-settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/system-settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2008 - 2009 Red Hat, Inc. + * Copyright (C) 2008 - 2010 Red Hat, Inc. */ #include @@ -2142,6 +2142,155 @@ test_read_wired_ipv6_manual (void) g_object_unref (connection); } +#define TEST_IFCFG_WIRED_IPV6_ONLY TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-ipv6-only" + +static void +test_read_wired_ipv6_only (void) +{ + NMConnection *connection; + NMSettingConnection *s_con; + NMSettingWired *s_wired; + NMSettingIP4Config *s_ip4; + NMSettingIP6Config *s_ip6; + 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 test-wired-ipv6-only"; + const char *expected_address1 = "1001:abba::1234"; + guint32 expected_prefix1 = 56; + const char *expected_dns1 = "1:2:3:4::a"; + NMIP6Address *ip6_addr; + struct in6_addr addr; + + connection = connection_from_file (TEST_IFCFG_WIRED_IPV6_ONLY, + NULL, + TYPE_ETHERNET, + NULL, + &unmanaged, + &keyfile, + &routefile, + &route6file, + &error, + &ignore_error); + ASSERT (connection != NULL, + "wired-ipv6-only-read", "failed to read %s: %s", TEST_IFCFG_WIRED_IPV6_ONLY, error->message); + + ASSERT (nm_connection_verify (connection, &error), + "wired-ipv6-only-verify", "failed to verify %s: %s", TEST_IFCFG_WIRED_IPV6_ONLY, error->message); + + ASSERT (unmanaged == FALSE, + "wired-ipv6-only-verify", "failed to verify %s: unexpected unmanaged value", TEST_IFCFG_WIRED_IPV6_MANUAL); + + /* ===== CONNECTION SETTING ===== */ + + s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION)); + ASSERT (s_con != NULL, + "wired-ipv6-only-verify-connection", "failed to verify %s: missing %s setting", + TEST_IFCFG_WIRED_IPV6_MANUAL, + NM_SETTING_CONNECTION_SETTING_NAME); + + /* ID */ + tmp = nm_setting_connection_get_id (s_con); + ASSERT (tmp != NULL, + "wired-ipv6-only-verify-connection", "failed to verify %s: missing %s / %s key", + TEST_IFCFG_WIRED_IPV6_MANUAL, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_ID); + ASSERT (strcmp (tmp, expected_id) == 0, + "wired-ipv6-only-verify-connection", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIRED_IPV6_MANUAL, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_ID); + + /* ===== WIRED SETTING ===== */ + + s_wired = NM_SETTING_WIRED (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED)); + ASSERT (s_wired != NULL, + "wired-ipv6-only-verify-wired", "failed to verify %s: missing %s setting", + TEST_IFCFG_WIRED_IPV6_MANUAL, + NM_SETTING_WIRED_SETTING_NAME); + + /* ===== IPv4 SETTING ===== */ + + s_ip4 = NM_SETTING_IP4_CONFIG (nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG)); + ASSERT (s_ip4 == NULL, + "wired-ipv6-only-verify-ip4", "failed to verify %s: unexpected %s setting", + TEST_IFCFG_WIRED_IPV6_MANUAL, + NM_SETTING_IP4_CONFIG_SETTING_NAME); + + /* ===== IPv6 SETTING ===== */ + + s_ip6 = NM_SETTING_IP6_CONFIG (nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG)); + ASSERT (s_ip6 != NULL, + "wired-ipv6-only-verify-ip6", "failed to verify %s: missing %s setting", + TEST_IFCFG_WIRED_IPV6_MANUAL, + 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, + "wired-ipv6-only-verify-ip6", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIRED_IPV6_MANUAL, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_METHOD); + + /* IP addresses */ + ASSERT (nm_setting_ip6_config_get_num_addresses (s_ip6) == 1, + "wired-ipv6-only-verify-ip6", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIRED_IPV6_MANUAL, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_ADDRESSES); + + /* Address #1 */ + ip6_addr = nm_setting_ip6_config_get_address (s_ip6, 0); + ASSERT (ip6_addr, + "wired-ipv6-only-verify-ip6", "failed to verify %s: missing IP6 address #1", + TEST_IFCFG_WIRED_IPV6_MANUAL); + + ASSERT (nm_ip6_address_get_prefix (ip6_addr) == expected_prefix1, + "wired-ipv6-only-verify-ip6", "failed to verify %s: unexpected IP6 address #1 prefix", + TEST_IFCFG_WIRED_IPV6_MANUAL); + + ASSERT (inet_pton (AF_INET6, expected_address1, &addr) > 0, + "wired-ipv6-only-verify-ip6", "failed to verify %s: couldn't convert IP address #1", + TEST_IFCFG_WIRED_IPV6_MANUAL); + ASSERT (IN6_ARE_ADDR_EQUAL (nm_ip6_address_get_address (ip6_addr), &addr), + "wired-ipv6-only-verify-ip6", "failed to verify %s: unexpected IP6 address #1", + TEST_IFCFG_WIRED_IPV6_MANUAL); + + /* DNS Addresses */ + ASSERT (nm_setting_ip6_config_get_num_dns (s_ip6) == 1, + "wired-ipv6-only-verify-ip6", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIRED_IPV6_MANUAL, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_DNS); + + ASSERT (inet_pton (AF_INET6, expected_dns1, &addr) > 0, + "wired-ipv6-only-verify-ip6", "failed to verify %s: couldn't convert DNS IP address #1", + TEST_IFCFG_WIRED_IPV6_MANUAL); + ASSERT (IN6_ARE_ADDR_EQUAL (nm_setting_ip6_config_get_dns (s_ip6, 0), &addr), + "wired-ipv6-only-verify-ip6", "failed to verify %s: unexpected %s / %s key value #1", + TEST_IFCFG_WIRED_IPV6_MANUAL, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_DNS); + + /* DNS domains - none as domains are stuffed to 'ipv4' setting */ + ASSERT (nm_setting_ip6_config_get_num_dns_searches (s_ip6) == 0, + "wired-ipv6-only-verify-ip6", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIRED_IPV6_MANUAL, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_DNS); + + g_free (keyfile); + g_free (routefile); + g_free (route6file); + g_object_unref (connection); +} + #define TEST_IFCFG_ONBOOT_NO TEST_IFCFG_DIR"/network-scripts/ifcfg-test-onboot-no" static void @@ -5108,6 +5257,140 @@ test_write_wired_dhcp (void) g_object_unref (reread); } +static void +test_write_wired_static_ip6_only (void) +{ + NMConnection *connection; + NMConnection *reread; + NMSettingConnection *s_con; + NMSettingWired *s_wired; + NMSettingIP6Config *s_ip6; + static unsigned char tmpmac[] = { 0x31, 0x33, 0x33, 0x37, 0xbe, 0xcd }; + GByteArray *mac; + char *uuid; + guint64 timestamp = 0x12344433L; + struct in6_addr ip6; + struct in6_addr dns6; + NMIP6Address *addr6; + gboolean success; + GError *error = NULL; + char *testfile = NULL; + char *unmanaged = NULL; + char *keyfile = NULL; + char *routefile = NULL; + char *route6file = NULL; + gboolean ignore_error = FALSE; + + inet_pton (AF_INET6, "1003:1234:abcd::1", &ip6); + inet_pton (AF_INET6, "fade:0102:0103::face", &dns6); + + connection = nm_connection_new (); + ASSERT (connection != NULL, + "wired-static-ip6-only-write", "failed to allocate new connection"); + + /* Connection setting */ + s_con = (NMSettingConnection *) nm_setting_connection_new (); + ASSERT (s_con != NULL, + "wired-static-ip6-only-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, "Test Write Wired Static IP6 Only", + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_CONNECTION_TIMESTAMP, timestamp, + NULL); + g_free (uuid); + + /* Wired setting */ + s_wired = (NMSettingWired *) nm_setting_wired_new (); + ASSERT (s_wired != NULL, + "wired-static-ip6-only-write", "failed to allocate new %s setting", + NM_SETTING_WIRED_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_wired)); + + mac = g_byte_array_sized_new (sizeof (tmpmac)); + g_byte_array_append (mac, &tmpmac[0], sizeof (tmpmac)); + g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, mac, NULL); + g_byte_array_free (mac, TRUE); + + /* IP6 setting */ + s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new (); + ASSERT (s_ip6 != NULL, + "wired-static-ip6-only-write", "failed to allocate new %s setting", + NM_SETTING_IP6_CONFIG_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_ip6)); + + g_object_set (s_ip6, + NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_MANUAL, + NULL); + + /* Add addresses */ + addr6 = nm_ip6_address_new (); + nm_ip6_address_set_address (addr6, &ip6); + nm_ip6_address_set_prefix (addr6, 11); + nm_setting_ip6_config_add_address (s_ip6, addr6); + nm_ip6_address_unref (addr6); + + /* DNS server */ + nm_setting_ip6_config_add_dns (s_ip6, &dns6); + + ASSERT (nm_connection_verify (connection, &error) == TRUE, + "wired-static-ip6-only-write", "failed to verify connection: %s", + (error && error->message) ? error->message : "(unknown)"); + + /* Save the ifcfg */ + success = writer_new_connection (connection, + TEST_SCRATCH_DIR "/network-scripts/", + &testfile, + &error); + ASSERT (success == TRUE, + "wired-static-ip6-only-write", "failed to write connection to disk: %s", + (error && error->message) ? error->message : "(unknown)"); + + ASSERT (testfile != NULL, + "wired-static-ip6-only-write", "didn't get ifcfg file path back after writing connection"); + + /* re-read the connection for comparison */ + reread = connection_from_file (testfile, + NULL, + TYPE_ETHERNET, + NULL, + &unmanaged, + &keyfile, + &routefile, + &route6file, + &error, + &ignore_error); + unlink (testfile); + + ASSERT (reread != NULL, + "wired-static-ip6-only-write-reread", "failed to read %s: %s", testfile, error->message); + + ASSERT (nm_connection_verify (reread, &error), + "wired-static-ip6-only-write-reread-verify", "failed to verify %s: %s", testfile, error->message); + + ASSERT (nm_connection_get_setting (reread, NM_TYPE_SETTING_IP4_CONFIG) == NULL, + "wired-static-ip6-only-write-reread-verify", "unexpected IPv4 setting"); + + ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE, + "wired-static-ip6-only-write", "written and re-read connection weren't the same."); + + if (route6file) + unlink (route6file); + + g_free (testfile); + g_free (keyfile); + g_free (routefile); + g_free (route6file); + g_object_unref (connection); + g_object_unref (reread); +} + + #define TEST_IFCFG_READ_WRITE_STATIC_ROUTES_LEGACY TEST_IFCFG_DIR"/network-scripts/ifcfg-test-static-routes-legacy" static void @@ -7813,6 +8096,7 @@ int main (int argc, char **argv) test_read_wired_static_routes (); test_read_wired_static_routes_legacy (); test_read_wired_ipv6_manual (); + test_read_wired_ipv6_only (); test_read_onboot_no (); test_read_wired_8021x_peap_mschapv2 (); test_read_wifi_open (); @@ -7835,6 +8119,7 @@ int main (int argc, char **argv) test_read_wifi_wep_eap_ttls_chap (); test_write_wired_static (); + test_write_wired_static_ip6_only (); test_write_wired_static_routes (); test_read_write_static_routes_legacy (); test_write_wired_dhcp (); diff --git a/system-settings/plugins/ifcfg-rh/writer.c b/system-settings/plugins/ifcfg-rh/writer.c index 74f3a59a5..cc24a96f5 100644 --- a/system-settings/plugins/ifcfg-rh/writer.c +++ b/system-settings/plugins/ifcfg-rh/writer.c @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2009 Red Hat, Inc. + * Copyright (C) 2009 - 2010 Red Hat, Inc. */ #include @@ -911,9 +911,30 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG); if (!s_ip4) { - g_set_error (error, ifcfg_plugin_error_quark (), 0, - "Missing '%s' setting", NM_SETTING_IP4_CONFIG_SETTING_NAME); - return FALSE; + int result; + + /* IPv4 disabled, clear IPv4 related parameters */ + svSetValue (ifcfg, "BOOTPROTO", NULL, FALSE); + for (i = 0; i < 254; i++) { + if (i == 0) { + addr_key = g_strdup ("IPADDR"); + prefix_key = g_strdup ("PREFIX"); + gw_key = g_strdup ("GATEWAY"); + } else { + addr_key = g_strdup_printf ("IPADDR%d", i + 1); + prefix_key = g_strdup_printf ("PREFIX%d", i + 1); + gw_key = g_strdup_printf ("GATEWAY%d", i + 1); + } + + svSetValue (ifcfg, addr_key, NULL, FALSE); + svSetValue (ifcfg, prefix_key, NULL, FALSE); + svSetValue (ifcfg, gw_key, NULL, FALSE); + } + + route_path = utils_get_route_path (ifcfg->fileName); + result = unlink (route_path); + g_free (route_path); + return TRUE; } value = nm_setting_ip4_config_get_method (s_ip4);