ifcfg-rh: fix IPv6-only configurations (rh #538499)
authorDan Williams <dcbw@redhat.com>
Mon, 12 Apr 2010 23:24:07 +0000 (16:24 -0700)
committerDan Williams <dcbw@redhat.com>
Mon, 12 Apr 2010 23:24:07 +0000 (16:24 -0700)
system-settings/plugins/ifcfg-rh/reader.c
system-settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am
system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv6-only [new file with mode: 0644]
system-settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
system-settings/plugins/ifcfg-rh/writer.c

index a445d5b..32575f3 100644 (file)
@@ -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 <stdlib.h>
@@ -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);
+       s_ip6 = make_ip6_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);
+       } 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_ip6 = make_ip6_setting (parsed, network_file, iscsiadm_path, error);
+       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_ip6)
-               nm_connection_add_setting (connection, s_ip6);
+       } 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.
index b5c94dd..f687963 100644 (file)
@@ -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 (file)
index 0000000..59ec32e
--- /dev/null
@@ -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"
+
index 8855a32..cfe93d6 100644 (file)
@@ -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 <stdio.h>
@@ -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 ();
index 74f3a59..cc24a96 100644 (file)
@@ -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 <ctype.h>
@@ -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);