summary refs log tree commit diff
path: root/libnm-core/nm-setting-ip4-config.c
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2020-10-05 22:27:18 +0200
committerMichael Biebl <biebl@debian.org>2020-10-05 22:27:18 +0200
commitaafc1dbe4712c86189bbc1d4d54ad8cb4c69be7e (patch)
treea2a9bb4d007339a0b1304540388230ccedac32bd /libnm-core/nm-setting-ip4-config.c
parente7b44ef4c80907346ec7492a09c45277459924fc (diff)
New upstream version 1.27.90 upstream/1.27.90
Diffstat (limited to 'libnm-core/nm-setting-ip4-config.c')
-rw-r--r--libnm-core/nm-setting-ip4-config.c1603
1 files changed, 850 insertions, 753 deletions
diff --git a/libnm-core/nm-setting-ip4-config.c b/libnm-core/nm-setting-ip4-config.c
index 31c82220..46579ba9 100644
--- a/libnm-core/nm-setting-ip4-config.c
+++ b/libnm-core/nm-setting-ip4-config.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: LGPL-2.1+
+/* SPDX-License-Identifier: LGPL-2.1+ */
 /*
  * Copyright (C) 2014 Red Hat, Inc.
  */
@@ -35,19 +35,20 @@
 
 /*****************************************************************************/
 
-NM_GOBJECT_PROPERTIES_DEFINE_BASE (
-	PROP_DHCP_CLIENT_ID,
-	PROP_DHCP_FQDN,
-);
+NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_DHCP_CLIENT_ID,
+                                  PROP_DHCP_FQDN,
+                                  PROP_DHCP_VENDOR_CLASS_IDENTIFIER, );
 
 typedef struct {
-	char *dhcp_client_id;
-	char *dhcp_fqdn;
+    char *dhcp_client_id;
+    char *dhcp_fqdn;
+    char *dhcp_vendor_class_identifier;
 } NMSettingIP4ConfigPrivate;
 
-G_DEFINE_TYPE (NMSettingIP4Config, nm_setting_ip4_config, NM_TYPE_SETTING_IP_CONFIG)
+G_DEFINE_TYPE(NMSettingIP4Config, nm_setting_ip4_config, NM_TYPE_SETTING_IP_CONFIG)
 
-#define NM_SETTING_IP4_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_IP4_CONFIG, NMSettingIP4ConfigPrivate))
+#define NM_SETTING_IP4_CONFIG_GET_PRIVATE(o) \
+    (G_TYPE_INSTANCE_GET_PRIVATE((o), NM_TYPE_SETTING_IP4_CONFIG, NMSettingIP4ConfigPrivate))
 
 /*****************************************************************************/
 
@@ -62,11 +63,11 @@ G_DEFINE_TYPE (NMSettingIP4Config, nm_setting_ip4_config, NM_TYPE_SETTING_IP_CON
  * addresses via DHCP.
  **/
 const char *
-nm_setting_ip4_config_get_dhcp_client_id (NMSettingIP4Config *setting)
+nm_setting_ip4_config_get_dhcp_client_id(NMSettingIP4Config *setting)
 {
-	g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), NULL);
+    g_return_val_if_fail(NM_IS_SETTING_IP4_CONFIG(setting), NULL);
 
-	return NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting)->dhcp_client_id;
+    return NM_SETTING_IP4_CONFIG_GET_PRIVATE(setting)->dhcp_client_id;
 }
 
 /**
@@ -81,432 +82,507 @@ nm_setting_ip4_config_get_dhcp_client_id (NMSettingIP4Config *setting)
  * Since: 1.2
  **/
 const char *
-nm_setting_ip4_config_get_dhcp_fqdn (NMSettingIP4Config *setting)
+nm_setting_ip4_config_get_dhcp_fqdn(NMSettingIP4Config *setting)
 {
-	g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), NULL);
+    g_return_val_if_fail(NM_IS_SETTING_IP4_CONFIG(setting), NULL);
 
-	return NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting)->dhcp_fqdn;
+    return NM_SETTING_IP4_CONFIG_GET_PRIVATE(setting)->dhcp_fqdn;
+}
+
+/**
+ * nm_setting_ip4_config_get_dhcp_vendor_class_identifier:
+ * @setting: the #NMSettingIP4Config
+ *
+ * Returns the value contained in the #NMSettingIP4Config:dhcp_vendor_class_identifier
+ * property.
+ *
+ * Returns: the vendor class identifier option to send to the DHCP server
+ *
+ * Since: 1.28
+ **/
+const char *
+nm_setting_ip4_config_get_dhcp_vendor_class_identifier(NMSettingIP4Config *setting)
+{
+    g_return_val_if_fail(NM_IS_SETTING_IP4_CONFIG(setting), NULL);
+
+    return NM_SETTING_IP4_CONFIG_GET_PRIVATE(setting)->dhcp_vendor_class_identifier;
 }
 
 static gboolean
-verify (NMSetting *setting, NMConnection *connection, GError **error)
+verify(NMSetting *setting, NMConnection *connection, GError **error)
 {
-	NMSettingIP4ConfigPrivate *priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting);
-	NMSettingIPConfig *s_ip = NM_SETTING_IP_CONFIG (setting);
-	NMSettingVerifyResult ret;
-	const char *method;
-
-	ret = NM_SETTING_CLASS (nm_setting_ip4_config_parent_class)->verify (setting, connection, error);
-	if (ret != NM_SETTING_VERIFY_SUCCESS)
-		return ret;
-
-	method = nm_setting_ip_config_get_method (s_ip);
-	/* Base class already checked that it exists */
-	g_assert (method);
-
-	if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) {
-		if (nm_setting_ip_config_get_num_addresses (s_ip) == 0) {
-			g_set_error (error,
-			             NM_CONNECTION_ERROR,
-			             NM_CONNECTION_ERROR_MISSING_PROPERTY,
-			             _("this property cannot be empty for '%s=%s'"),
-			             NM_SETTING_IP_CONFIG_METHOD, method);
-			g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_ADDRESSES);
-			return FALSE;
-		}
-	} else if (   !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)
-	           || !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)
-	           || !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) {
-		if (nm_setting_ip_config_get_num_dns (s_ip) > 0) {
-			g_set_error (error,
-			             NM_CONNECTION_ERROR,
-			             NM_CONNECTION_ERROR_INVALID_PROPERTY,
-			             _("this property is not allowed for '%s=%s'"),
-			             NM_SETTING_IP_CONFIG_METHOD, method);
-			g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_DNS);
-			return FALSE;
-		}
-
-		if (nm_setting_ip_config_get_num_dns_searches (s_ip) > 0) {
-			g_set_error (error,
-			             NM_CONNECTION_ERROR,
-			             NM_CONNECTION_ERROR_INVALID_PROPERTY,
-			             _("this property is not allowed for '%s=%s'"),
-			             NM_SETTING_IP_CONFIG_METHOD, method);
-			g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_DNS_SEARCH);
-			return FALSE;
-		}
-
-		/* Shared allows IP addresses; link-local and disabled do not */
-		if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) != 0) {
-			if (nm_setting_ip_config_get_num_addresses (s_ip) > 0) {
-				g_set_error (error,
-				             NM_CONNECTION_ERROR,
-				             NM_CONNECTION_ERROR_INVALID_PROPERTY,
-				             _("this property is not allowed for '%s=%s'"),
-				             NM_SETTING_IP_CONFIG_METHOD, method);
-				g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_ADDRESSES);
-				return FALSE;
-			}
-		}
-	} else if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) {
-		/* nothing to do */
-	} else {
-		g_set_error_literal (error,
-		                     NM_CONNECTION_ERROR,
-		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
-		                     _("property is invalid"));
-		g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_METHOD);
-		return FALSE;
-	}
-
-	if (priv->dhcp_client_id && !priv->dhcp_client_id[0]) {
-		g_set_error_literal (error,
-		                     NM_CONNECTION_ERROR,
-		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
-		                     _("property is empty"));
-		g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID);
-		return FALSE;
-	}
-
-	if (priv->dhcp_fqdn && !*priv->dhcp_fqdn) {
-		g_set_error_literal (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY,
-		                     _("property is empty"));
-		g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP4_CONFIG_DHCP_FQDN);
-		return FALSE;
-	}
-
-	if (priv->dhcp_fqdn && !strchr (priv->dhcp_fqdn, '.')) {
-		g_set_error (error,
-		             NM_CONNECTION_ERROR,
-		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
-		             _("'%s' is not a valid FQDN"), priv->dhcp_fqdn);
-		g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP4_CONFIG_DHCP_FQDN);
-		return FALSE;
-	}
-
-	if (priv->dhcp_fqdn && nm_setting_ip_config_get_dhcp_hostname (s_ip)) {
-		g_set_error_literal (error,
-		                     NM_CONNECTION_ERROR,
-		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
-		                     _("property cannot be set when dhcp-hostname is also set"));
-		g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP4_CONFIG_DHCP_FQDN);
-		return FALSE;
-	}
-
-	if (   NM_FLAGS_ANY (nm_setting_ip_config_get_dhcp_hostname_flags (s_ip),
-	                     NM_DHCP_HOSTNAME_FLAGS_FQDN_MASK)
-	    && !priv->dhcp_fqdn) {
-		/* Currently we send a FQDN option only when ipv4.dhcp-fqdn is set */
-		g_set_error_literal (error,
-		                     NM_CONNECTION_ERROR,
-		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
-		                     _("FQDN flags requires a FQDN set"));
-		g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_DHCP_HOSTNAME_FLAGS);
-		return FALSE;
-	}
-
-	/* Failures from here on are NORMALIZABLE_ERROR... */
-
-	if (   nm_streq (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)
-	    && nm_setting_ip_config_get_num_addresses (s_ip) > 1) {
-		g_set_error (error,
-		             NM_CONNECTION_ERROR,
-		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
-		             _("multiple addresses are not allowed for '%s=%s'"),
-		             NM_SETTING_IP_CONFIG_METHOD,
-		             NM_SETTING_IP4_CONFIG_METHOD_SHARED);
-		g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_ADDRESSES);
-		return NM_SETTING_VERIFY_NORMALIZABLE_ERROR;
-	}
-
-	/* Failures from here on are NORMALIZABLE... */
-
-	if (   !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)
-	    && !nm_setting_ip_config_get_may_fail (s_ip)) {
-		g_set_error_literal (error,
-		                     NM_CONNECTION_ERROR,
-		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
-		                     _("property should be TRUE when method is set to disabled"));
-		g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_MAY_FAIL);
-		return NM_SETTING_VERIFY_NORMALIZABLE;
-	}
-
-	return TRUE;
+    NMSettingIP4ConfigPrivate *priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE(setting);
+    NMSettingIPConfig *        s_ip = NM_SETTING_IP_CONFIG(setting);
+    NMSettingVerifyResult      ret;
+    const char *               method;
+
+    ret = NM_SETTING_CLASS(nm_setting_ip4_config_parent_class)->verify(setting, connection, error);
+    if (ret != NM_SETTING_VERIFY_SUCCESS)
+        return ret;
+
+    method = nm_setting_ip_config_get_method(s_ip);
+    /* Base class already checked that it exists */
+    g_assert(method);
+
+    if (!strcmp(method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) {
+        if (nm_setting_ip_config_get_num_addresses(s_ip) == 0) {
+            g_set_error(error,
+                        NM_CONNECTION_ERROR,
+                        NM_CONNECTION_ERROR_MISSING_PROPERTY,
+                        _("this property cannot be empty for '%s=%s'"),
+                        NM_SETTING_IP_CONFIG_METHOD,
+                        method);
+            g_prefix_error(error,
+                           "%s.%s: ",
+                           NM_SETTING_IP4_CONFIG_SETTING_NAME,
+                           NM_SETTING_IP_CONFIG_ADDRESSES);
+            return FALSE;
+        }
+    } else if (!strcmp(method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)
+               || !strcmp(method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)
+               || !strcmp(method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) {
+        if (nm_setting_ip_config_get_num_dns(s_ip) > 0) {
+            g_set_error(error,
+                        NM_CONNECTION_ERROR,
+                        NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                        _("this property is not allowed for '%s=%s'"),
+                        NM_SETTING_IP_CONFIG_METHOD,
+                        method);
+            g_prefix_error(error,
+                           "%s.%s: ",
+                           NM_SETTING_IP4_CONFIG_SETTING_NAME,
+                           NM_SETTING_IP_CONFIG_DNS);
+            return FALSE;
+        }
+
+        if (nm_setting_ip_config_get_num_dns_searches(s_ip) > 0) {
+            g_set_error(error,
+                        NM_CONNECTION_ERROR,
+                        NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                        _("this property is not allowed for '%s=%s'"),
+                        NM_SETTING_IP_CONFIG_METHOD,
+                        method);
+            g_prefix_error(error,
+                           "%s.%s: ",
+                           NM_SETTING_IP4_CONFIG_SETTING_NAME,
+                           NM_SETTING_IP_CONFIG_DNS_SEARCH);
+            return FALSE;
+        }
+
+        /* Shared allows IP addresses; link-local and disabled do not */
+        if (strcmp(method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) != 0) {
+            if (nm_setting_ip_config_get_num_addresses(s_ip) > 0) {
+                g_set_error(error,
+                            NM_CONNECTION_ERROR,
+                            NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                            _("this property is not allowed for '%s=%s'"),
+                            NM_SETTING_IP_CONFIG_METHOD,
+                            method);
+                g_prefix_error(error,
+                               "%s.%s: ",
+                               NM_SETTING_IP4_CONFIG_SETTING_NAME,
+                               NM_SETTING_IP_CONFIG_ADDRESSES);
+                return FALSE;
+            }
+        }
+    } else if (!strcmp(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) {
+        /* nothing to do */
+    } else {
+        g_set_error_literal(error,
+                            NM_CONNECTION_ERROR,
+                            NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                            _("property is invalid"));
+        g_prefix_error(error,
+                       "%s.%s: ",
+                       NM_SETTING_IP4_CONFIG_SETTING_NAME,
+                       NM_SETTING_IP_CONFIG_METHOD);
+        return FALSE;
+    }
+
+    if (priv->dhcp_client_id && !priv->dhcp_client_id[0]) {
+        g_set_error_literal(error,
+                            NM_CONNECTION_ERROR,
+                            NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                            _("property is empty"));
+        g_prefix_error(error,
+                       "%s.%s: ",
+                       NM_SETTING_IP4_CONFIG_SETTING_NAME,
+                       NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID);
+        return FALSE;
+    }
+
+    if (priv->dhcp_fqdn && !*priv->dhcp_fqdn) {
+        g_set_error_literal(error,
+                            NM_CONNECTION_ERROR,
+                            NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                            _("property is empty"));
+        g_prefix_error(error,
+                       "%s.%s: ",
+                       NM_SETTING_IP4_CONFIG_SETTING_NAME,
+                       NM_SETTING_IP4_CONFIG_DHCP_FQDN);
+        return FALSE;
+    }
+
+    if (priv->dhcp_fqdn && !strchr(priv->dhcp_fqdn, '.')) {
+        g_set_error(error,
+                    NM_CONNECTION_ERROR,
+                    NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                    _("'%s' is not a valid FQDN"),
+                    priv->dhcp_fqdn);
+        g_prefix_error(error,
+                       "%s.%s: ",
+                       NM_SETTING_IP4_CONFIG_SETTING_NAME,
+                       NM_SETTING_IP4_CONFIG_DHCP_FQDN);
+        return FALSE;
+    }
+
+    if (priv->dhcp_fqdn && nm_setting_ip_config_get_dhcp_hostname(s_ip)) {
+        g_set_error_literal(error,
+                            NM_CONNECTION_ERROR,
+                            NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                            _("property cannot be set when dhcp-hostname is also set"));
+        g_prefix_error(error,
+                       "%s.%s: ",
+                       NM_SETTING_IP4_CONFIG_SETTING_NAME,
+                       NM_SETTING_IP4_CONFIG_DHCP_FQDN);
+        return FALSE;
+    }
+
+    if (NM_FLAGS_ANY(nm_setting_ip_config_get_dhcp_hostname_flags(s_ip),
+                     NM_DHCP_HOSTNAME_FLAGS_FQDN_MASK)
+        && !priv->dhcp_fqdn) {
+        /* Currently, we send a FQDN option only when ipv4.dhcp-fqdn is set */
+        g_set_error_literal(error,
+                            NM_CONNECTION_ERROR,
+                            NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                            _("FQDN flags requires a FQDN set"));
+        g_prefix_error(error,
+                       "%s.%s: ",
+                       NM_SETTING_IP4_CONFIG_SETTING_NAME,
+                       NM_SETTING_IP_CONFIG_DHCP_HOSTNAME_FLAGS);
+        return FALSE;
+    }
+
+    if (priv->dhcp_vendor_class_identifier
+        && !nm_utils_validate_dhcp4_vendor_class_id(priv->dhcp_vendor_class_identifier, error))
+        return FALSE;
+
+    /* Failures from here on are NORMALIZABLE_ERROR... */
+
+    if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)
+        && nm_setting_ip_config_get_num_addresses(s_ip) > 1) {
+        g_set_error(error,
+                    NM_CONNECTION_ERROR,
+                    NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                    _("multiple addresses are not allowed for '%s=%s'"),
+                    NM_SETTING_IP_CONFIG_METHOD,
+                    NM_SETTING_IP4_CONFIG_METHOD_SHARED);
+        g_prefix_error(error,
+                       "%s.%s: ",
+                       NM_SETTING_IP4_CONFIG_SETTING_NAME,
+                       NM_SETTING_IP_CONFIG_ADDRESSES);
+        return NM_SETTING_VERIFY_NORMALIZABLE_ERROR;
+    }
+
+    /* Failures from here on are NORMALIZABLE... */
+
+    if (!strcmp(method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)
+        && !nm_setting_ip_config_get_may_fail(s_ip)) {
+        g_set_error_literal(error,
+                            NM_CONNECTION_ERROR,
+                            NM_CONNECTION_ERROR_INVALID_PROPERTY,
+                            _("property should be TRUE when method is set to disabled"));
+        g_prefix_error(error,
+                       "%s.%s: ",
+                       NM_SETTING_IP4_CONFIG_SETTING_NAME,
+                       NM_SETTING_IP_CONFIG_MAY_FAIL);
+        return NM_SETTING_VERIFY_NORMALIZABLE;
+    }
+
+    return TRUE;
 }
 
 static GVariant *
-ip4_dns_to_dbus (const GValue *prop_value)
+ip4_dns_to_dbus(const GValue *prop_value)
 {
-	return nm_utils_ip4_dns_to_variant (g_value_get_boxed (prop_value));
+    return nm_utils_ip4_dns_to_variant(g_value_get_boxed(prop_value));
 }
 
 static void
-ip4_dns_from_dbus (GVariant *dbus_value,
-                   GValue *prop_value)
+ip4_dns_from_dbus(GVariant *dbus_value, GValue *prop_value)
 {
-	g_value_take_boxed (prop_value, nm_utils_ip4_dns_from_variant (dbus_value));
+    g_value_take_boxed(prop_value, nm_utils_ip4_dns_from_variant(dbus_value));
 }
 
 static GVariant *
-ip4_addresses_get (const NMSettInfoSetting *sett_info,
-                   guint property_idx,
-                   NMConnection *connection,
-                   NMSetting *setting,
-                   NMConnectionSerializationFlags flags,
-                   const NMConnectionSerializationOptions *options)
+ip4_addresses_get(const NMSettInfoSetting *               sett_info,
+                  guint                                   property_idx,
+                  NMConnection *                          connection,
+                  NMSetting *                             setting,
+                  NMConnectionSerializationFlags          flags,
+                  const NMConnectionSerializationOptions *options)
 {
-	gs_unref_ptrarray GPtrArray *addrs = NULL;
-	const char *gateway;
+    gs_unref_ptrarray GPtrArray *addrs = NULL;
+    const char *                 gateway;
 
-	g_object_get (setting, NM_SETTING_IP_CONFIG_ADDRESSES, &addrs, NULL);
-	gateway = nm_setting_ip_config_get_gateway (NM_SETTING_IP_CONFIG (setting));
-	return nm_utils_ip4_addresses_to_variant (addrs, gateway);
+    g_object_get(setting, NM_SETTING_IP_CONFIG_ADDRESSES, &addrs, NULL);
+    gateway = nm_setting_ip_config_get_gateway(NM_SETTING_IP_CONFIG(setting));
+    return nm_utils_ip4_addresses_to_variant(addrs, gateway);
 }
 
 static gboolean
-ip4_addresses_set (NMSetting  *setting,
-                   GVariant   *connection_dict,
-                   const char *property,
-                   GVariant   *value,
-                   NMSettingParseFlags parse_flags,
-                   GError    **error)
+ip4_addresses_set(NMSetting *         setting,
+                  GVariant *          connection_dict,
+                  const char *        property,
+                  GVariant *          value,
+                  NMSettingParseFlags parse_flags,
+                  GError **           error)
 {
-	GPtrArray *addrs;
-	GVariant *s_ip4;
-	char **labels, *gateway = NULL;
-	int i;
-
-	/* FIXME: properly handle errors */
-
-	if (!_nm_setting_use_legacy_property (setting, connection_dict, "addresses", "address-data"))
-		return TRUE;
-
-	addrs = nm_utils_ip4_addresses_from_variant (value, &gateway);
-
-	s_ip4 = g_variant_lookup_value (connection_dict, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
-	if (g_variant_lookup (s_ip4, "address-labels", "^as", &labels)) {
-		for (i = 0; i < addrs->len && labels[i]; i++)
-			if (*labels[i])
-				nm_ip_address_set_attribute (addrs->pdata[i], NM_IP_ADDRESS_ATTRIBUTE_LABEL, g_variant_new_string (labels[i]));
-		g_strfreev (labels);
-	}
-	g_variant_unref (s_ip4);
-
-	g_object_set (setting,
-	              NM_SETTING_IP_CONFIG_ADDRESSES, addrs,
-	              NM_SETTING_IP_CONFIG_GATEWAY, gateway,
-	              NULL);
-	g_ptr_array_unref (addrs);
-	g_free (gateway);
-	return TRUE;
+    GPtrArray *addrs;
+    GVariant * s_ip4;
+    char **    labels, *gateway = NULL;
+    int        i;
+
+    /* FIXME: properly handle errors */
+
+    if (!_nm_setting_use_legacy_property(setting, connection_dict, "addresses", "address-data"))
+        return TRUE;
+
+    addrs = nm_utils_ip4_addresses_from_variant(value, &gateway);
+
+    s_ip4 = g_variant_lookup_value(connection_dict,
+                                   NM_SETTING_IP4_CONFIG_SETTING_NAME,
+                                   NM_VARIANT_TYPE_SETTING);
+    if (g_variant_lookup(s_ip4, "address-labels", "^as", &labels)) {
+        for (i = 0; i < addrs->len && labels[i]; i++)
+            if (*labels[i])
+                nm_ip_address_set_attribute(addrs->pdata[i],
+                                            NM_IP_ADDRESS_ATTRIBUTE_LABEL,
+                                            g_variant_new_string(labels[i]));
+        g_strfreev(labels);
+    }
+    g_variant_unref(s_ip4);
+
+    g_object_set(setting,
+                 NM_SETTING_IP_CONFIG_ADDRESSES,
+                 addrs,
+                 NM_SETTING_IP_CONFIG_GATEWAY,
+                 gateway,
+                 NULL);
+    g_ptr_array_unref(addrs);
+    g_free(gateway);
+    return TRUE;
 }
 
 static GVariant *
-ip4_address_labels_get (const NMSettInfoSetting *sett_info,
-                        guint property_idx,
-                        NMConnection *connection,
-                        NMSetting *setting,
-                        NMConnectionSerializationFlags flags,
-                        const NMConnectionSerializationOptions *options)
+ip4_address_labels_get(const NMSettInfoSetting *               sett_info,
+                       guint                                   property_idx,
+                       NMConnection *                          connection,
+                       NMSetting *                             setting,
+                       NMConnectionSerializationFlags          flags,
+                       const NMConnectionSerializationOptions *options)
 {
-	NMSettingIPConfig *s_ip = NM_SETTING_IP_CONFIG (setting);
-	gboolean have_labels = FALSE;
-	GPtrArray *labels;
-	GVariant *ret;
-	int num_addrs, i;
-
-	if (flags & NM_CONNECTION_SERIALIZE_ONLY_SECRETS)
-		return NULL;
-
-	num_addrs = nm_setting_ip_config_get_num_addresses (s_ip);
-	for (i = 0; i < num_addrs; i++) {
-		NMIPAddress *addr = nm_setting_ip_config_get_address (s_ip, i);
-		GVariant *label = nm_ip_address_get_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL);
-
-		if (label) {
-			have_labels = TRUE;
-			break;
-		}
-	}
-	if (!have_labels)
-		return NULL;
-
-	labels = g_ptr_array_sized_new (num_addrs);
-	for (i = 0; i < num_addrs; i++) {
-		NMIPAddress *addr = nm_setting_ip_config_get_address (s_ip, i);
-		GVariant *label = nm_ip_address_get_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL);
-
-		g_ptr_array_add (labels, (char *) (label ? g_variant_get_string (label, NULL) : ""));
-	}
-
-	ret = g_variant_new_strv ((const char * const *) labels->pdata, labels->len);
-	g_ptr_array_unref (labels);
-
-	return ret;
+    NMSettingIPConfig *s_ip        = NM_SETTING_IP_CONFIG(setting);
+    gboolean           have_labels = FALSE;
+    GPtrArray *        labels;
+    GVariant *         ret;
+    int                num_addrs, i;
+
+    if (flags & NM_CONNECTION_SERIALIZE_ONLY_SECRETS)
+        return NULL;
+
+    num_addrs = nm_setting_ip_config_get_num_addresses(s_ip);
+    for (i = 0; i < num_addrs; i++) {
+        NMIPAddress *addr  = nm_setting_ip_config_get_address(s_ip, i);
+        GVariant *   label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL);
+
+        if (label) {
+            have_labels = TRUE;
+            break;
+        }
+    }
+    if (!have_labels)
+        return NULL;
+
+    labels = g_ptr_array_sized_new(num_addrs);
+    for (i = 0; i < num_addrs; i++) {
+        NMIPAddress *addr  = nm_setting_ip_config_get_address(s_ip, i);
+        GVariant *   label = nm_ip_address_get_attribute(addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL);
+
+        g_ptr_array_add(labels, (char *) (label ? g_variant_get_string(label, NULL) : ""));
+    }
+
+    ret = g_variant_new_strv((const char *const *) labels->pdata, labels->len);
+    g_ptr_array_unref(labels);
+
+    return ret;
 }
 
 static GVariant *
-ip4_address_data_get (const NMSettInfoSetting *sett_info,
-                      guint property_idx,
-                      NMConnection *connection,
-                      NMSetting *setting,
-                      NMConnectionSerializationFlags flags,
-                      const NMConnectionSerializationOptions *options)
+ip4_address_data_get(const NMSettInfoSetting *               sett_info,
+                     guint                                   property_idx,
+                     NMConnection *                          connection,
+                     NMSetting *                             setting,
+                     NMConnectionSerializationFlags          flags,
+                     const NMConnectionSerializationOptions *options)
 {
-	gs_unref_ptrarray GPtrArray *addrs = NULL;
+    gs_unref_ptrarray GPtrArray *addrs = NULL;
 
-	if (flags & NM_CONNECTION_SERIALIZE_ONLY_SECRETS)
-		return NULL;
+    if (flags & NM_CONNECTION_SERIALIZE_ONLY_SECRETS)
+        return NULL;
 
-	g_object_get (setting, NM_SETTING_IP_CONFIG_ADDRESSES, &addrs, NULL);
-	return nm_utils_ip_addresses_to_variant (addrs);
+    g_object_get(setting, NM_SETTING_IP_CONFIG_ADDRESSES, &addrs, NULL);
+    return nm_utils_ip_addresses_to_variant(addrs);
 }
 
 static gboolean
-ip4_address_data_set (NMSetting  *setting,
-                      GVariant   *connection_dict,
-                      const char *property,
-                      GVariant   *value,
-                      NMSettingParseFlags parse_flags,
-                      GError    **error)
+ip4_address_data_set(NMSetting *         setting,
+                     GVariant *          connection_dict,
+                     const char *        property,
+                     GVariant *          value,
+                     NMSettingParseFlags parse_flags,
+                     GError **           error)
 {
-	GPtrArray *addrs;
+    GPtrArray *addrs;
 
-	/* FIXME: properly handle errors */
+    /* FIXME: properly handle errors */
 
-	/* Ignore 'address-data' if we're going to process 'addresses' */
-	if (_nm_setting_use_legacy_property (setting, connection_dict, "addresses", "address-data"))
-		return TRUE;
+    /* Ignore 'address-data' if we're going to process 'addresses' */
+    if (_nm_setting_use_legacy_property(setting, connection_dict, "addresses", "address-data"))
+        return TRUE;
 
-	addrs = nm_utils_ip_addresses_from_variant (value, AF_INET);
-	g_object_set (setting, NM_SETTING_IP_CONFIG_ADDRESSES, addrs, NULL);
-	g_ptr_array_unref (addrs);
-	return TRUE;
+    addrs = nm_utils_ip_addresses_from_variant(value, AF_INET);
+    g_object_set(setting, NM_SETTING_IP_CONFIG_ADDRESSES, addrs, NULL);
+    g_ptr_array_unref(addrs);
+    return TRUE;
 }
 
 static GVariant *
-ip4_routes_get (const NMSettInfoSetting *sett_info,
-                guint property_idx,
-                NMConnection *connection,
-                NMSetting *setting,
-                NMConnectionSerializationFlags flags,
-                const NMConnectionSerializationOptions *options)
+ip4_routes_get(const NMSettInfoSetting *               sett_info,
+               guint                                   property_idx,
+               NMConnection *                          connection,
+               NMSetting *                             setting,
+               NMConnectionSerializationFlags          flags,
+               const NMConnectionSerializationOptions *options)
 {
-	gs_unref_ptrarray GPtrArray *routes = NULL;
+    gs_unref_ptrarray GPtrArray *routes = NULL;
 
-	g_object_get (setting, NM_SETTING_IP_CONFIG_ROUTES, &routes, NULL);
-	return nm_utils_ip4_routes_to_variant (routes);
+    g_object_get(setting, NM_SETTING_IP_CONFIG_ROUTES, &routes, NULL);
+    return nm_utils_ip4_routes_to_variant(routes);
 }
 
 static gboolean
-ip4_routes_set (NMSetting  *setting,
-                GVariant   *connection_dict,
-                const char *property,
-                GVariant   *value,
-                NMSettingParseFlags parse_flags,
-                GError    **error)
+ip4_routes_set(NMSetting *         setting,
+               GVariant *          connection_dict,
+               const char *        property,
+               GVariant *          value,
+               NMSettingParseFlags parse_flags,
+               GError **           error)
 {
-	GPtrArray *routes;
+    GPtrArray *routes;
 
-	/* FIXME: properly handle errors */
+    /* FIXME: properly handle errors */
 
-	if (!_nm_setting_use_legacy_property (setting, connection_dict, "routes", "route-data"))
-		return TRUE;
+    if (!_nm_setting_use_legacy_property(setting, connection_dict, "routes", "route-data"))
+        return TRUE;
 
-	routes = nm_utils_ip4_routes_from_variant (value);
-	g_object_set (setting, property, routes, NULL);
-	g_ptr_array_unref (routes);
-	return TRUE;
+    routes = nm_utils_ip4_routes_from_variant(value);
+    g_object_set(setting, property, routes, NULL);
+    g_ptr_array_unref(routes);
+    return TRUE;
 }
 
 static GVariant *
-ip4_route_data_get (const NMSettInfoSetting *sett_info,
-                    guint property_idx,
-                    NMConnection *connection,
-                    NMSetting *setting,
-                    NMConnectionSerializationFlags flags,
-                    const NMConnectionSerializationOptions *options)
+ip4_route_data_get(const NMSettInfoSetting *               sett_info,
+                   guint                                   property_idx,
+                   NMConnection *                          connection,
+                   NMSetting *                             setting,
+                   NMConnectionSerializationFlags          flags,
+                   const NMConnectionSerializationOptions *options)
 {
-	gs_unref_ptrarray GPtrArray *routes = NULL;
+    gs_unref_ptrarray GPtrArray *routes = NULL;
 
-	if (flags & NM_CONNECTION_SERIALIZE_ONLY_SECRETS)
-		return NULL;
+    if (flags & NM_CONNECTION_SERIALIZE_ONLY_SECRETS)
+        return NULL;
 
-	g_object_get (setting, NM_SETTING_IP_CONFIG_ROUTES, &routes, NULL);
-	return nm_utils_ip_routes_to_variant (routes);
+    g_object_get(setting, NM_SETTING_IP_CONFIG_ROUTES, &routes, NULL);
+    return nm_utils_ip_routes_to_variant(routes);
 }
 
 static gboolean
-ip4_route_data_set (NMSetting  *setting,
-                    GVariant   *connection_dict,
-                    const char *property,
-                    GVariant   *value,
-                    NMSettingParseFlags parse_flags,
-                    GError    **error)
+ip4_route_data_set(NMSetting *         setting,
+                   GVariant *          connection_dict,
+                   const char *        property,
+                   GVariant *          value,
+                   NMSettingParseFlags parse_flags,
+                   GError **           error)
 {
-	GPtrArray *routes;
+    GPtrArray *routes;
 
-	/* FIXME: properly handle errors */
+    /* FIXME: properly handle errors */
 
-	/* Ignore 'route-data' if we're going to process 'routes' */
-	if (_nm_setting_use_legacy_property (setting, connection_dict, "routes", "route-data"))
-		return TRUE;
+    /* Ignore 'route-data' if we're going to process 'routes' */
+    if (_nm_setting_use_legacy_property(setting, connection_dict, "routes", "route-data"))
+        return TRUE;
 
-	routes = nm_utils_ip_routes_from_variant (value, AF_INET);
-	g_object_set (setting, NM_SETTING_IP_CONFIG_ROUTES, routes, NULL);
-	g_ptr_array_unref (routes);
-	return TRUE;
+    routes = nm_utils_ip_routes_from_variant(value, AF_INET);
+    g_object_set(setting, NM_SETTING_IP_CONFIG_ROUTES, routes, NULL);
+    g_ptr_array_unref(routes);
+    return TRUE;
 }
 
 /*****************************************************************************/
 
 static void
-get_property (GObject *object, guint prop_id,
-              GValue *value, GParamSpec *pspec)
+get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
 {
-	NMSettingIP4Config *s_ip4 = NM_SETTING_IP4_CONFIG (object);
-
-	switch (prop_id) {
-	case PROP_DHCP_CLIENT_ID:
-		g_value_set_string (value, nm_setting_ip4_config_get_dhcp_client_id (s_ip4));
-		break;
-	case PROP_DHCP_FQDN:
-		g_value_set_string (value, nm_setting_ip4_config_get_dhcp_fqdn (s_ip4));
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-		break;
-	}
+    NMSettingIP4Config *s_ip4 = NM_SETTING_IP4_CONFIG(object);
+
+    switch (prop_id) {
+    case PROP_DHCP_CLIENT_ID:
+        g_value_set_string(value, nm_setting_ip4_config_get_dhcp_client_id(s_ip4));
+        break;
+    case PROP_DHCP_FQDN:
+        g_value_set_string(value, nm_setting_ip4_config_get_dhcp_fqdn(s_ip4));
+        break;
+    case PROP_DHCP_VENDOR_CLASS_IDENTIFIER:
+        g_value_set_string(value, nm_setting_ip4_config_get_dhcp_vendor_class_identifier(s_ip4));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
 }
 
 static void
-set_property (GObject *object, guint prop_id,
-              const GValue *value, GParamSpec *pspec)
+set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
 {
-	NMSettingIP4ConfigPrivate *priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (object);
-
-	switch (prop_id) {
-	case PROP_DHCP_CLIENT_ID:
-		g_free (priv->dhcp_client_id);
-		priv->dhcp_client_id = g_value_dup_string (value);
-		break;
-	case PROP_DHCP_FQDN:
-		g_free (priv->dhcp_fqdn);
-		priv->dhcp_fqdn = g_value_dup_string (value);
-		break;
-	default:
-		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-		break;
-	}
+    NMSettingIP4ConfigPrivate *priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE(object);
+
+    switch (prop_id) {
+    case PROP_DHCP_CLIENT_ID:
+        g_free(priv->dhcp_client_id);
+        priv->dhcp_client_id = g_value_dup_string(value);
+        break;
+    case PROP_DHCP_FQDN:
+        g_free(priv->dhcp_fqdn);
+        priv->dhcp_fqdn = g_value_dup_string(value);
+        break;
+    case PROP_DHCP_VENDOR_CLASS_IDENTIFIER:
+        g_free(priv->dhcp_vendor_class_identifier);
+        priv->dhcp_vendor_class_identifier = g_value_dup_string(value);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
 }
 
 /*****************************************************************************/
 
 static void
-nm_setting_ip4_config_init (NMSettingIP4Config *setting)
-{
-}
+nm_setting_ip4_config_init(NMSettingIP4Config *setting)
+{}
 
 /**
  * nm_setting_ip4_config_new:
@@ -516,410 +592,431 @@ nm_setting_ip4_config_init (NMSettingIP4Config *setting)
  * Returns: (transfer full): the new empty #NMSettingIP4Config object
  **/
 NMSetting *
-nm_setting_ip4_config_new (void)
+nm_setting_ip4_config_new(void)
 {
-	return (NMSetting *) g_object_new (NM_TYPE_SETTING_IP4_CONFIG, NULL);
+    return (NMSetting *) g_object_new(NM_TYPE_SETTING_IP4_CONFIG, NULL);
 }
 
 static void
-finalize (GObject *object)
+finalize(GObject *object)
 {
-	NMSettingIP4ConfigPrivate *priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (object);
+    NMSettingIP4ConfigPrivate *priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE(object);
 
-	g_free (priv->dhcp_client_id);
-	g_free (priv->dhcp_fqdn);
+    g_free(priv->dhcp_client_id);
+    g_free(priv->dhcp_fqdn);
+    g_free(priv->dhcp_vendor_class_identifier);
 
-	G_OBJECT_CLASS (nm_setting_ip4_config_parent_class)->finalize (object);
+    G_OBJECT_CLASS(nm_setting_ip4_config_parent_class)->finalize(object);
 }
 
 static void
-nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *klass)
+nm_setting_ip4_config_class_init(NMSettingIP4ConfigClass *klass)
 {
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-	NMSettingClass *setting_class = NM_SETTING_CLASS (klass);
-	GArray *properties_override = _nm_sett_info_property_override_create_array_ip_config ();
-
-	g_type_class_add_private (setting_class, sizeof (NMSettingIP4ConfigPrivate));
-
-	object_class->get_property = get_property;
-	object_class->set_property = set_property;
-	object_class->finalize     = finalize;
-
-	setting_class->verify = verify;
-
-	/* ---ifcfg-rh---
-	 * property: method
-	 * variable: BOOTPROTO
-	 * format:   string
-	 * values:   none, dhcp (bootp), static, ibft, autoip, shared
-	 * default:  none
-	 * description: Method used for IPv4 protocol configuration.
-	 * ---end---
-	 */
-
-	/* ---keyfile---
-	 * property: dns
-	 * format: list of DNS IP addresses
-	 * description: List of DNS servers.
-	 * example: dns=1.2.3.4;8.8.8.8;8.8.4.4;
-	 * ---end---
-	 * ---ifcfg-rh---
-	 * property: dns
-	 * variable: DNS1, DNS2, ...
-	 * format:   string
-	 * description: List of DNS servers. Even if NetworkManager supports many DNS
-	 *   servers, initscripts and resolver only care about the first three, usually.
-	 * example: DNS1=1.2.3.4 DNS2=10.0.0.254 DNS3=8.8.8.8
-	 * ---end---
-	 */
-
-	/* ---ifcfg-rh---
-	 * property: dns-search
-	 * variable: DOMAIN
-	 * format:   string (space-separated domains)
-	 * description: List of DNS search domains.
-	 * ---end---
-	 */
-
-	/* ---keyfile---
-	 * property: addresses
-	 * variable: address1, address2, ...
-	 * format: address/plen
-	 * description: List of static IP addresses.
-	 * example: address1=192.168.100.100/24 address2=10.1.1.5/24
-	 * ---end---
-	 * ---ifcfg-rh---
-	 * property: addresses
-	 * variable: IPADDR, PREFIX, IPADDR1, PREFIX1, ...
-	 * description: List of static IP addresses.
-	 * example: IPADDR=10.5.5.23 PREFIX=24 IPADDR1=1.1.1.2 PREFIX1=16
-	 * ---end---
-	 */
-
-	/* ---keyfile---
-	 * property: gateway
-	 * variable: gateway
-	 * format: string
-	 * description: Gateway IP addresses as a string.
-	 * example: gateway=192.168.100.1
-	 * ---end---
-	 * ---ifcfg-rh---
-	 * property: gateway
-	 * variable: GATEWAY
-	 * description: Gateway IP address.
-	 * example: GATEWAY=10.5.5.1
-	 * ---end---
-	 */
-
-	/* ---keyfile---
-	 * property: routes
-	 * variable: route1, route2, ...
-	 * format: route/plen[,gateway,metric]
-	 * description: List of IP routes.
-	 * example: route1=8.8.8.0/24,10.1.1.1,77
-	 *   route2=7.7.0.0/16
-	 * ---end---
-	 * ---ifcfg-rh---
-	 * property: routes
-	 * variable: ADDRESS1, NETMASK1, GATEWAY1, METRIC1, OPTIONS1, ...
-	 * description: List of static routes. They are not stored in ifcfg-* file,
-	 *   but in route-* file instead.
-	 * ---end---
-	 */
-
-	/* ---ifcfg-rh---
-	 * property: ignore-auto-routes
-	 * variable: PEERROUTES(+)
-	 * default: yes
-	 * description: PEERROUTES has the opposite meaning as 'ignore-auto-routes' property.
-	 * ---end---
-	 */
-
-	/* ---ifcfg-rh---
-	 * property: ignore-auto-dns
-	 * variable: PEERDNS
-	 * default: yes
-	 * description: PEERDNS has the opposite meaning as 'ignore-auto-dns' property.
-	 * ---end---
-	 */
-
-	/* ---ifcfg-rh---
-	 * property: dhcp-send-hostname
-	 * variable: DHCP_SEND_HOSTNAME(+)
-	 * default: yes
-	 * description: Whether DHCP_HOSTNAME should be sent to the DHCP server.
-	 * ---end---
-	 */
-
-	/* ---ifcfg-rh---
-	 * property: dhcp-hostname
-	 * variable: DHCP_HOSTNAME
-	 * description: Hostname to send to the DHCP server. When both DHCP_HOSTNAME and
-	 *    DHCP_FQDN are specified only the latter is used.
-	 * ---end---
-	 */
-
-	/* ---ifcfg-rh---
-	 * property: never-default
-	 * variable: DEFROUTE (GATEWAYDEV in /etc/sysconfig/network)
-	 * default: yes
-	 * description: DEFROUTE=no tells NetworkManager that this connection
-	 *   should not be assigned the default route. DEFROUTE has the opposite
-	 *   meaning as 'never-default' property.
-	 * ---end---
-	 */
-
-	/* ---ifcfg-rh---
-	 * property: may-fail
-	 * variable: IPV4_FAILURE_FATAL(+)
-	 * default: no
-	 * description: IPV4_FAILURE_FATAL has the opposite meaning as 'may-fail' property.
-	 * ---end---
-	 */
-
-	/* ---ifcfg-rh---
-	 * property: route-metric
-	 * variable: IPV4_ROUTE_METRIC(+)
-	 * default: -1
-	 * description: IPV4_ROUTE_METRIC is the default IPv4 metric for routes on this connection.
-	 *   If set to -1, a default metric based on the device type is used.
-	 * ---end---
-	 */
-
-	/* ---ifcfg-rh---
-	 * property: route-table
-	 * variable: IPV4_ROUTE_TABLE(+)
-	 * default: 0
-	 * description: IPV4_ROUTE_TABLE enables policy-routing and sets the default routing table.
-	 * ---end---
-	 */
-
-	/* ---ifcfg-rh---
-	 * property: dns-options
-	 * variable: RES_OPTIONS(+)
-	 * description: List of DNS options to be added to /etc/resolv.conf
-	 * example: RES_OPTIONS=ndots:2 timeout:3
-	 * ---end---
-	 */
-
-	/* ---ifcfg-rh---
-	 * property: dns-priority
-	 * variable: IPV4_DNS_PRIORITY(+)
-	 * description: The priority for DNS servers of this connection. Lower values have higher priority.
-	 *    If zero, the default value will be used (50 for VPNs, 100 for other connections).
-	 *    A negative value prevents DNS from other connections with greater values to be used.
-	 * default: 0
-	 * example: IPV4_DNS_PRIORITY=20
-	 * ---end---
-	 */
-
-	/**
-	 * NMSettingIP4Config:dhcp-client-id:
-	 *
-	 * A string sent to the DHCP server to identify the local machine which the
-	 * DHCP server may use to customize the DHCP lease and options.
-	 * When the property is a hex string ('aa:bb:cc') it is interpreted as a
-	 * binary client ID, in which case the first byte is assumed to be the
-	 * 'type' field as per RFC 2132 section 9.14 and the remaining bytes may be
-	 * an hardware address (e.g. '01:xx:xx:xx:xx:xx:xx' where 1 is the Ethernet
-	 * ARP type and the rest is a MAC address).
-	 * If the property is not a hex string it is considered as a
-	 * non-hardware-address client ID and the 'type' field is set to 0.
-	 *
-	 * The special values "mac" and "perm-mac" are supported, which use the
-	 * current or permanent MAC address of the device to generate a client identifier
-	 * with type ethernet (01). Currently, these options only work for ethernet
-	 * type of links.
-	 *
-	 * The special value "duid" generates a RFC4361-compliant client identifier based
-	 * on a hash of the interface name as IAID and /etc/machine-id.
-	 *
-	 * The special value "stable" is supported to generate a type 0 client identifier based
-	 * on the stable-id (see connection.stable-id) and a per-host key. If you set the
-	 * stable-id, you may want to include the "${DEVICE}" or "${MAC}" specifier to get a
-	 * per-device key.
-	 *
-	 * If unset, a globally configured default is used. If still unset, the default
-	 * depends on the DHCP plugin.
-	 **/
-	/* ---ifcfg-rh---
-	 * property: dhcp-client-id
-	 * variable: DHCP_CLIENT_ID(+)
-	 * description: A string sent to the DHCP server to identify the local machine.
-	 *    A binary value can be specified using hex notation ('aa:bb:cc').
-	 * example: DHCP_CLIENT_ID=ax-srv-1; DHCP_CLIENT_ID=01:44:44:44:44:44:44
-	 * ---end---
-	 */
-	obj_properties[PROP_DHCP_CLIENT_ID] =
-	    g_param_spec_string (NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID, "", "",
-	                         NULL,
-	                         G_PARAM_READWRITE |
-	                         G_PARAM_STATIC_STRINGS);
-
-	/* ---ifcfg-rh---
-	 * property: dad-timeout
-	 * variable: ACD_TIMEOUT(+), ARPING_WAIT
-	 * default: missing variable means global default (config override or zero)
-	 * description: Timeout (in milliseconds for ACD_TIMEOUT or in seconds
-	 *   for ARPING_WAIT) for address conflict detection before configuring
-	 *   IPv4 addresses. 0 turns off the ACD completely, -1 means default value.
-	 * example: ACD_TIMEOUT=2000 or ARPING_WAIT=2
-	 * ---end---
-	 */
-
-	/* ---ifcfg-rh---
-	 * property: dhcp-timeout
-	 * variable: IPV4_DHCP_TIMEOUT(+)
-	 * description: A timeout after which the DHCP transaction fails in case of no response.
-	 * example: IPV4_DHCP_TIMEOUT=10
-	 * ---end---
-	 */
-
-	/* ---ifcfg-rh---
-	 * property: dhcp-hostname-flags
-	 * variable: DHCP_HOSTNAME_FLAGS
-	 * description: flags for the DHCP hostname and FQDN properties
-	 * example: DHCP_HOSTNAME_FLAGS=5
-	 */
-
-	/**
-	 * NMSettingIP4Config:dhcp-fqdn:
-	 *
-	 * If the #NMSettingIPConfig:dhcp-send-hostname property is %TRUE, then the
-	 * specified FQDN will be sent to the DHCP server when acquiring a lease. This
-	 * property and #NMSettingIPConfig:dhcp-hostname are mutually exclusive and
-	 * cannot be set at the same time.
-	 *
-	 * Since: 1.2
-	 */
-	/* ---ifcfg-rh---
-	 * property: dhcp-fqdn
-	 * variable: DHCP_FQDN
-	 * description: FQDN to send to the DHCP server. When both DHCP_HOSTNAME and
-	 *    DHCP_FQDN are specified only the latter is used.
-	 * example: DHCP_FQDN=foo.bar.com
-	 * ---end---
-	 */
-	obj_properties[PROP_DHCP_FQDN] =
-	    g_param_spec_string (NM_SETTING_IP4_CONFIG_DHCP_FQDN, "", "",
-	                         NULL,
-	                         G_PARAM_READWRITE |
-	                         G_PARAM_STATIC_STRINGS);
-
-	/* IP4-specific property overrides */
-
-	/* ---dbus---
-	 * property: dns
-	 * format: array of uint32
-	 * description: Array of IP addresses of DNS servers (as network-byte-order
-	 *   integers)
-	 * ---end---
-	 */
-	_nm_properties_override_gobj (properties_override,
-	                              g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                            NM_SETTING_IP_CONFIG_DNS),
-	                              NM_SETT_INFO_PROPERT_TYPE (
-	                                  .dbus_type           = NM_G_VARIANT_TYPE ("au"),
-	                                  .gprop_to_dbus_fcn   = ip4_dns_to_dbus,
-	                                  .gprop_from_dbus_fcn = ip4_dns_from_dbus,
-	                              ));
-
-	/* ---dbus---
-	 * property: addresses
-	 * format: array of array of uint32
-	 * description: Deprecated in favor of the 'address-data' and 'gateway'
-	 *   properties, but this can be used for backward-compatibility with older
-	 *   daemons. Note that if you send this property the daemon will ignore
-	 *   'address-data' and 'gateway'.
-	 *
-	 *   Array of IPv4 address structures.  Each IPv4 address structure is
-	 *   composed of 3 32-bit values; the first being the IPv4 address (network
-	 *   byte order), the second the prefix (1 - 32), and last the IPv4 gateway
-	 *   (network byte order). The gateway may be left as 0 if no gateway exists
-	 *   for that subnet.
-	 * ---end---
-	 */
-	_nm_properties_override_gobj (properties_override,
-	                              g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                            NM_SETTING_IP_CONFIG_ADDRESSES),
-	                              NM_SETT_INFO_PROPERT_TYPE (
-	                                  .dbus_type     = NM_G_VARIANT_TYPE ("aau"),
-	                                  .to_dbus_fcn   = ip4_addresses_get,
-	                                  .from_dbus_fcn = ip4_addresses_set,
-	                              ));
-	_nm_properties_override_dbus (properties_override,
-	                              "address-labels",
-	                              NM_SETT_INFO_PROPERT_TYPE (
-	                                  .dbus_type   = G_VARIANT_TYPE_STRING_ARRAY,
-	                                  .to_dbus_fcn = ip4_address_labels_get,
-	                              ));
-
-	/* ---dbus---
-	 * property: address-data
-	 * format: array of vardict
-	 * description: Array of IPv4 addresses. Each address dictionary contains at
-	 *   least 'address' and 'prefix' entries, containing the IP address as a
-	 *   string, and the prefix length as a uint32. Additional attributes may
-	 *   also exist on some addresses.
-	 * ---end---
-	 */
-	_nm_properties_override_dbus (properties_override,
-	                              "address-data",
-	                              NM_SETT_INFO_PROPERT_TYPE (
-	                                  .dbus_type     = NM_G_VARIANT_TYPE ("aa{sv}"),
-	                                  .to_dbus_fcn   = ip4_address_data_get,
-	                                  .from_dbus_fcn = ip4_address_data_set,
-	                              ));
-
-	/* ---dbus---
-	 * property: routes
-	 * format: array of array of uint32
-	 * description: Deprecated in favor of the 'route-data' property, but this
-	 *   can be used for backward-compatibility with older daemons. Note that if
-	 *   you send this property the daemon will ignore 'route-data'.
-	 *
-	 *   Array of IPv4 route structures.  Each IPv4 route structure is composed
-	 *   of 4 32-bit values; the first being the destination IPv4 network or
-	 *   address (network byte order), the second the destination network or
-	 *   address prefix (1 - 32), the third being the next-hop (network byte
-	 *   order) if any, and the fourth being the route metric. If the metric is
-	 *   0, NM will choose an appropriate default metric for the device. (There
-	 *   is no way to explicitly specify an actual metric of 0 with this
-	 *   property.)
-	 * ---end---
-	 */
-	_nm_properties_override_gobj (properties_override,
-	                              g_object_class_find_property (G_OBJECT_CLASS (setting_class),
-	                                                            NM_SETTING_IP_CONFIG_ROUTES),
-	                              NM_SETT_INFO_PROPERT_TYPE (
-	                                  .dbus_type     = NM_G_VARIANT_TYPE ("aau"),
-	                                  .to_dbus_fcn   = ip4_routes_get,
-	                                  .from_dbus_fcn = ip4_routes_set,
-	                              ));
-
-	/* ---dbus---
-	 * property: route-data
-	 * format: array of vardict
-	 * description: Array of IPv4 routes. Each route dictionary contains at
-	 *   least 'dest' and 'prefix' entries, containing the destination IP
-	 *   address as a string, and the prefix length as a uint32. Most routes
-	 *   will also have a 'gateway' entry, containing the gateway IP address as
-	 *   a string. If the route has a 'metric' entry (containing a uint32), that
-	 *   will be used as the metric for the route (otherwise NM will pick a
-	 *   default value appropriate to the device). Additional attributes may
-	 *   also exist on some routes.
-	 * ---end---
-	 */
-	_nm_properties_override_dbus (properties_override,
-	                              "route-data",
-	                              NM_SETT_INFO_PROPERT_TYPE (
-	                                  .dbus_type     = NM_G_VARIANT_TYPE ("aa{sv}"),
-	                                  .to_dbus_fcn   = ip4_route_data_get,
-	                                  .from_dbus_fcn = ip4_route_data_set,
-	                              ));
-
-	g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
-
-	_nm_setting_class_commit_full (setting_class, NM_META_SETTING_TYPE_IP4_CONFIG,
-	                               NULL, properties_override);
+    GObjectClass *  object_class        = G_OBJECT_CLASS(klass);
+    NMSettingClass *setting_class       = NM_SETTING_CLASS(klass);
+    GArray *        properties_override = _nm_sett_info_property_override_create_array_ip_config();
+
+    g_type_class_add_private(setting_class, sizeof(NMSettingIP4ConfigPrivate));
+
+    object_class->get_property = get_property;
+    object_class->set_property = set_property;
+    object_class->finalize     = finalize;
+
+    setting_class->verify = verify;
+
+    /* ---ifcfg-rh---
+     * property: method
+     * variable: BOOTPROTO
+     * format:   string
+     * values:   none, dhcp (bootp), static, ibft, autoip, shared
+     * default:  none
+     * description: Method used for IPv4 protocol configuration.
+     * ---end---
+     */
+
+    /* ---keyfile---
+     * property: dns
+     * format: list of DNS IP addresses
+     * description: List of DNS servers.
+     * example: dns=1.2.3.4;8.8.8.8;8.8.4.4;
+     * ---end---
+     * ---ifcfg-rh---
+     * property: dns
+     * variable: DNS1, DNS2, ...
+     * format:   string
+     * description: List of DNS servers. Even if NetworkManager supports many DNS
+     *   servers, initscripts and resolver only care about the first three, usually.
+     * example: DNS1=1.2.3.4 DNS2=10.0.0.254 DNS3=8.8.8.8
+     * ---end---
+     */
+
+    /* ---ifcfg-rh---
+     * property: dns-search
+     * variable: DOMAIN
+     * format:   string (space-separated domains)
+     * description: List of DNS search domains.
+     * ---end---
+     */
+
+    /* ---keyfile---
+     * property: addresses
+     * variable: address1, address2, ...
+     * format: address/plen
+     * description: List of static IP addresses.
+     * example: address1=192.168.100.100/24 address2=10.1.1.5/24
+     * ---end---
+     * ---ifcfg-rh---
+     * property: addresses
+     * variable: IPADDR, PREFIX, IPADDR1, PREFIX1, ...
+     * description: List of static IP addresses.
+     * example: IPADDR=10.5.5.23 PREFIX=24 IPADDR1=1.1.1.2 PREFIX1=16
+     * ---end---
+     */
+
+    /* ---keyfile---
+     * property: gateway
+     * variable: gateway
+     * format: string
+     * description: Gateway IP addresses as a string.
+     * example: gateway=192.168.100.1
+     * ---end---
+     * ---ifcfg-rh---
+     * property: gateway
+     * variable: GATEWAY
+     * description: Gateway IP address.
+     * example: GATEWAY=10.5.5.1
+     * ---end---
+     */
+
+    /* ---keyfile---
+     * property: routes
+     * variable: route1, route2, ...
+     * format: route/plen[,gateway,metric]
+     * description: List of IP routes.
+     * example: route1=8.8.8.0/24,10.1.1.1,77
+     *   route2=7.7.0.0/16
+     * ---end---
+     * ---ifcfg-rh---
+     * property: routes
+     * variable: ADDRESS1, NETMASK1, GATEWAY1, METRIC1, OPTIONS1, ...
+     * description: List of static routes. They are not stored in ifcfg-* file,
+     *   but in route-* file instead.
+     * ---end---
+     */
+
+    /* ---ifcfg-rh---
+     * property: ignore-auto-routes
+     * variable: PEERROUTES(+)
+     * default: yes
+     * description: PEERROUTES has the opposite meaning as 'ignore-auto-routes' property.
+     * ---end---
+     */
+
+    /* ---ifcfg-rh---
+     * property: ignore-auto-dns
+     * variable: PEERDNS
+     * default: yes
+     * description: PEERDNS has the opposite meaning as 'ignore-auto-dns' property.
+     * ---end---
+     */
+
+    /* ---ifcfg-rh---
+     * property: dhcp-send-hostname
+     * variable: DHCP_SEND_HOSTNAME(+)
+     * default: yes
+     * description: Whether DHCP_HOSTNAME should be sent to the DHCP server.
+     * ---end---
+     */
+
+    /* ---ifcfg-rh---
+     * property: dhcp-hostname
+     * variable: DHCP_HOSTNAME
+     * description: Hostname to send to the DHCP server. When both DHCP_HOSTNAME and
+     *    DHCP_FQDN are specified only the latter is used.
+     * ---end---
+     */
+
+    /* ---ifcfg-rh---
+     * property: never-default
+     * variable: DEFROUTE (GATEWAYDEV in /etc/sysconfig/network)
+     * default: yes
+     * description: DEFROUTE=no tells NetworkManager that this connection
+     *   should not be assigned the default route. DEFROUTE has the opposite
+     *   meaning as 'never-default' property.
+     * ---end---
+     */
+
+    /* ---ifcfg-rh---
+     * property: may-fail
+     * variable: IPV4_FAILURE_FATAL(+)
+     * default: no
+     * description: IPV4_FAILURE_FATAL has the opposite meaning as 'may-fail' property.
+     * ---end---
+     */
+
+    /* ---ifcfg-rh---
+     * property: route-metric
+     * variable: IPV4_ROUTE_METRIC(+)
+     * default: -1
+     * description: IPV4_ROUTE_METRIC is the default IPv4 metric for routes on this connection.
+     *   If set to -1, a default metric based on the device type is used.
+     * ---end---
+     */
+
+    /* ---ifcfg-rh---
+     * property: route-table
+     * variable: IPV4_ROUTE_TABLE(+)
+     * default: 0
+     * description: IPV4_ROUTE_TABLE enables policy-routing and sets the default routing table.
+     * ---end---
+     */
+
+    /* ---ifcfg-rh---
+     * property: dns-options
+     * variable: RES_OPTIONS(+)
+     * description: List of DNS options to be added to /etc/resolv.conf
+     * example: RES_OPTIONS=ndots:2 timeout:3
+     * ---end---
+     */
+
+    /* ---ifcfg-rh---
+     * property: dns-priority
+     * variable: IPV4_DNS_PRIORITY(+)
+     * description: The priority for DNS servers of this connection. Lower values have higher priority.
+     *    If zero, the default value will be used (50 for VPNs, 100 for other connections).
+     *    A negative value prevents DNS from other connections with greater values to be used.
+     * default: 0
+     * example: IPV4_DNS_PRIORITY=20
+     * ---end---
+     */
+
+    /**
+     * NMSettingIP4Config:dhcp-client-id:
+     *
+     * A string sent to the DHCP server to identify the local machine which the
+     * DHCP server may use to customize the DHCP lease and options.
+     * When the property is a hex string ('aa:bb:cc') it is interpreted as a
+     * binary client ID, in which case the first byte is assumed to be the
+     * 'type' field as per RFC 2132 section 9.14 and the remaining bytes may be
+     * an hardware address (e.g. '01:xx:xx:xx:xx:xx:xx' where 1 is the Ethernet
+     * ARP type and the rest is a MAC address).
+     * If the property is not a hex string it is considered as a
+     * non-hardware-address client ID and the 'type' field is set to 0.
+     *
+     * The special values "mac" and "perm-mac" are supported, which use the
+     * current or permanent MAC address of the device to generate a client identifier
+     * with type ethernet (01). Currently, these options only work for ethernet
+     * type of links.
+     *
+     * The special value "duid" generates a RFC4361-compliant client identifier based
+     * on a hash of the interface name as IAID and /etc/machine-id.
+     *
+     * The special value "stable" is supported to generate a type 0 client identifier based
+     * on the stable-id (see connection.stable-id) and a per-host key. If you set the
+     * stable-id, you may want to include the "${DEVICE}" or "${MAC}" specifier to get a
+     * per-device key.
+     *
+     * If unset, a globally configured default is used. If still unset, the default
+     * depends on the DHCP plugin.
+     **/
+    /* ---ifcfg-rh---
+     * property: dhcp-client-id
+     * variable: DHCP_CLIENT_ID(+)
+     * description: A string sent to the DHCP server to identify the local machine.
+     *    A binary value can be specified using hex notation ('aa:bb:cc').
+     * example: DHCP_CLIENT_ID=ax-srv-1; DHCP_CLIENT_ID=01:44:44:44:44:44:44
+     * ---end---
+     */
+    obj_properties[PROP_DHCP_CLIENT_ID] =
+        g_param_spec_string(NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID,
+                            "",
+                            "",
+                            NULL,
+                            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /* ---ifcfg-rh---
+     * property: dad-timeout
+     * variable: ACD_TIMEOUT(+), ARPING_WAIT
+     * default: missing variable means global default (config override or zero)
+     * description: Timeout (in milliseconds for ACD_TIMEOUT or in seconds
+     *   for ARPING_WAIT) for address conflict detection before configuring
+     *   IPv4 addresses. 0 turns off the ACD completely, -1 means default value.
+     * example: ACD_TIMEOUT=2000 or ARPING_WAIT=2
+     * ---end---
+     */
+
+    /* ---ifcfg-rh---
+     * property: dhcp-timeout
+     * variable: IPV4_DHCP_TIMEOUT(+)
+     * description: A timeout after which the DHCP transaction fails in case of no response.
+     * example: IPV4_DHCP_TIMEOUT=10
+     * ---end---
+     */
+
+    /* ---ifcfg-rh---
+     * property: dhcp-hostname-flags
+     * variable: DHCP_HOSTNAME_FLAGS
+     * description: flags for the DHCP hostname and FQDN properties
+     * example: DHCP_HOSTNAME_FLAGS=5
+     */
+
+    /**
+     * NMSettingIP4Config:dhcp-fqdn:
+     *
+     * If the #NMSettingIPConfig:dhcp-send-hostname property is %TRUE, then the
+     * specified FQDN will be sent to the DHCP server when acquiring a lease. This
+     * property and #NMSettingIPConfig:dhcp-hostname are mutually exclusive and
+     * cannot be set at the same time.
+     *
+     * Since: 1.2
+     */
+    /* ---ifcfg-rh---
+     * property: dhcp-fqdn
+     * variable: DHCP_FQDN
+     * description: FQDN to send to the DHCP server. When both DHCP_HOSTNAME and
+     *    DHCP_FQDN are specified only the latter is used.
+     * example: DHCP_FQDN=foo.bar.com
+     * ---end---
+     */
+    obj_properties[PROP_DHCP_FQDN] =
+        g_param_spec_string(NM_SETTING_IP4_CONFIG_DHCP_FQDN,
+                            "",
+                            "",
+                            NULL,
+                            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /**
+     * NMSettingIP4Config:dhcp-vendor-class-identifier:
+     *
+     * The Vendor Class Identifier DHCP option (60).
+     * Special characters in the data string may be escaped using C-style escapes,
+     * nevertheless this property cannot contain nul bytes.
+     * If the per-profile value is unspecified (the default),
+     * a global connection default gets consulted.
+     * If still unspecified, the DHCP option is not sent to the server.
+     *
+     * Since 1.28
+     */
+    /* ---ifcfg-rh---
+     * property: dhcp-vendor-class-identifier
+     * variable: DHCP_VENDOR_CLASS_IDENTIFIER(+)
+     * description: The Vendor Class Identifier DHCP option (60).
+     * example: DHCP_VENDOR_CLASS_IDENTIFIER=foo
+     * ---end---
+     */
+    obj_properties[PROP_DHCP_VENDOR_CLASS_IDENTIFIER] =
+        g_param_spec_string(NM_SETTING_IP4_CONFIG_DHCP_VENDOR_CLASS_IDENTIFIER,
+                            "",
+                            "",
+                            NULL,
+                            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+    /* IP4-specific property overrides */
+
+    /* ---dbus---
+     * property: dns
+     * format: array of uint32
+     * description: Array of IP addresses of DNS servers (as network-byte-order
+     *   integers)
+     * ---end---
+     */
+    _nm_properties_override_gobj(
+        properties_override,
+        g_object_class_find_property(G_OBJECT_CLASS(setting_class), NM_SETTING_IP_CONFIG_DNS),
+        NM_SETT_INFO_PROPERT_TYPE(.dbus_type           = NM_G_VARIANT_TYPE("au"),
+                                  .gprop_to_dbus_fcn   = ip4_dns_to_dbus,
+                                  .gprop_from_dbus_fcn = ip4_dns_from_dbus, ));
+
+    /* ---dbus---
+     * property: addresses
+     * format: array of array of uint32
+     * description: Deprecated in favor of the 'address-data' and 'gateway'
+     *   properties, but this can be used for backward-compatibility with older
+     *   daemons. Note that if you send this property the daemon will ignore
+     *   'address-data' and 'gateway'.
+     *
+     *   Array of IPv4 address structures.  Each IPv4 address structure is
+     *   composed of 3 32-bit values; the first being the IPv4 address (network
+     *   byte order), the second the prefix (1 - 32), and last the IPv4 gateway
+     *   (network byte order). The gateway may be left as 0 if no gateway exists
+     *   for that subnet.
+     * ---end---
+     */
+    _nm_properties_override_gobj(
+        properties_override,
+        g_object_class_find_property(G_OBJECT_CLASS(setting_class), NM_SETTING_IP_CONFIG_ADDRESSES),
+        NM_SETT_INFO_PROPERT_TYPE(.dbus_type     = NM_G_VARIANT_TYPE("aau"),
+                                  .to_dbus_fcn   = ip4_addresses_get,
+                                  .from_dbus_fcn = ip4_addresses_set, ));
+    _nm_properties_override_dbus(
+        properties_override,
+        "address-labels",
+        NM_SETT_INFO_PROPERT_TYPE(.dbus_type   = G_VARIANT_TYPE_STRING_ARRAY,
+                                  .to_dbus_fcn = ip4_address_labels_get, ));
+
+    /* ---dbus---
+     * property: address-data
+     * format: array of vardict
+     * description: Array of IPv4 addresses. Each address dictionary contains at
+     *   least 'address' and 'prefix' entries, containing the IP address as a
+     *   string, and the prefix length as a uint32. Additional attributes may
+     *   also exist on some addresses.
+     * ---end---
+     */
+    _nm_properties_override_dbus(
+        properties_override,
+        "address-data",
+        NM_SETT_INFO_PROPERT_TYPE(.dbus_type     = NM_G_VARIANT_TYPE("aa{sv}"),
+                                  .to_dbus_fcn   = ip4_address_data_get,
+                                  .from_dbus_fcn = ip4_address_data_set, ));
+
+    /* ---dbus---
+     * property: routes
+     * format: array of array of uint32
+     * description: Deprecated in favor of the 'route-data' property, but this
+     *   can be used for backward-compatibility with older daemons. Note that if
+     *   you send this property the daemon will ignore 'route-data'.
+     *
+     *   Array of IPv4 route structures.  Each IPv4 route structure is composed
+     *   of 4 32-bit values; the first being the destination IPv4 network or
+     *   address (network byte order), the second the destination network or
+     *   address prefix (1 - 32), the third being the next-hop (network byte
+     *   order) if any, and the fourth being the route metric. If the metric is
+     *   0, NM will choose an appropriate default metric for the device. (There
+     *   is no way to explicitly specify an actual metric of 0 with this
+     *   property.)
+     * ---end---
+     */
+    _nm_properties_override_gobj(
+        properties_override,
+        g_object_class_find_property(G_OBJECT_CLASS(setting_class), NM_SETTING_IP_CONFIG_ROUTES),
+        NM_SETT_INFO_PROPERT_TYPE(.dbus_type     = NM_G_VARIANT_TYPE("aau"),
+                                  .to_dbus_fcn   = ip4_routes_get,
+                                  .from_dbus_fcn = ip4_routes_set, ));
+
+    /* ---dbus---
+     * property: route-data
+     * format: array of vardict
+     * description: Array of IPv4 routes. Each route dictionary contains at
+     *   least 'dest' and 'prefix' entries, containing the destination IP
+     *   address as a string, and the prefix length as a uint32. Most routes
+     *   will also have a 'next-hop' entry, containing the next hop IP address as
+     *   a string. If the route has a 'metric' entry (containing a uint32), that
+     *   will be used as the metric for the route (otherwise NM will pick a
+     *   default value appropriate to the device). Additional attributes may
+     *   also exist on some routes.
+     * ---end---
+     */
+    _nm_properties_override_dbus(properties_override,
+                                 "route-data",
+                                 NM_SETT_INFO_PROPERT_TYPE(.dbus_type = NM_G_VARIANT_TYPE("aa{sv}"),
+                                                           .to_dbus_fcn   = ip4_route_data_get,
+                                                           .from_dbus_fcn = ip4_route_data_set, ));
+
+    g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
+
+    _nm_setting_class_commit_full(setting_class,
+                                  NM_META_SETTING_TYPE_IP4_CONFIG,
+                                  NULL,
+                                  properties_override);
 }