summary refs log tree commit diff
path: root/libnm-util/nm-setting-bond.c
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2014-07-06 02:16:10 +0200
committerMichael Biebl <biebl@debian.org>2014-07-06 02:16:10 +0200
commit33491bc4279481db8ae47213e34a6d695a0e8830 (patch)
tree097d2b0fdff3fae6885381ae5e57a182cd8cbbba /libnm-util/nm-setting-bond.c
parent59c3714a494c3b3765657c0551ad82842d98a7d2 (diff)
Imported Upstream version 0.9.10.0 upstream/0.9.10.0
Diffstat (limited to 'libnm-util/nm-setting-bond.c')
-rw-r--r--libnm-util/nm-setting-bond.c315
1 files changed, 244 insertions, 71 deletions
diff --git a/libnm-util/nm-setting-bond.c b/libnm-util/nm-setting-bond.c
index e8e7b639..5f919027 100644
--- a/libnm-util/nm-setting-bond.c
+++ b/libnm-util/nm-setting-bond.c
@@ -18,12 +18,16 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  * Boston, MA 02110-1301 USA.
  *
- * (C) Copyright 2011 - 2012 Red Hat, Inc.
+ * (C) Copyright 2011 - 2013 Red Hat, Inc.
  */
 
 #include <string.h>
 #include <stdlib.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
 #include <dbus/dbus-glib.h>
+#include <glib/gi18n.h>
 
 #include "nm-setting-bond.h"
 #include "nm-param-spec-specialized.h"
@@ -80,18 +84,44 @@ enum {
 	LAST_PROP
 };
 
+enum {
+	TYPE_INT,
+	TYPE_STR,
+	TYPE_BOTH,
+	TYPE_IP,
+	TYPE_IFNAME,
+};
+
 typedef struct {
 	const char *opt;
 	const char *val;
+	guint opt_type;
+	guint min;
+	guint max;
+	char *list[10];
 } BondDefault;
 
 static const BondDefault defaults[] = {
-	{ NM_SETTING_BOND_OPTION_MODE,          "balance-rr" },
-	{ NM_SETTING_BOND_OPTION_MIIMON,        "100"        },
-	{ NM_SETTING_BOND_OPTION_DOWNDELAY,     "0"          },
-	{ NM_SETTING_BOND_OPTION_UPDELAY,       "0"          },
-	{ NM_SETTING_BOND_OPTION_ARP_INTERVAL,  "0"          },
-	{ NM_SETTING_BOND_OPTION_ARP_IP_TARGET, ""           },
+	{ NM_SETTING_BOND_OPTION_MODE,             "balance-rr", TYPE_BOTH, 0, 6,
+	  { "balance-rr", "active-backup", "balance-xor", "broadcast", "802.3ad", "balance-tlb", "balance-alb", NULL } },
+	{ NM_SETTING_BOND_OPTION_MIIMON,           "100",        TYPE_INT, 0, G_MAXINT },
+	{ NM_SETTING_BOND_OPTION_DOWNDELAY,        "0",          TYPE_INT, 0, G_MAXINT },
+	{ NM_SETTING_BOND_OPTION_UPDELAY,          "0",          TYPE_INT, 0, G_MAXINT },
+	{ NM_SETTING_BOND_OPTION_ARP_INTERVAL,     "0",          TYPE_INT, 0, G_MAXINT },
+	{ NM_SETTING_BOND_OPTION_ARP_IP_TARGET,    "",           TYPE_IP },
+	{ NM_SETTING_BOND_OPTION_ARP_VALIDATE,     "0",          TYPE_BOTH, 0, 3,
+	  { "none", "active", "backup", "all", NULL } },
+	{ NM_SETTING_BOND_OPTION_PRIMARY,          "",           TYPE_IFNAME },
+	{ NM_SETTING_BOND_OPTION_PRIMARY_RESELECT, "0",          TYPE_BOTH, 0, 2,
+	  { "always", "better", "failure", NULL } },
+	{ NM_SETTING_BOND_OPTION_FAIL_OVER_MAC,    "0",          TYPE_BOTH, 0, 2,
+	  { "none", "active", "follow", NULL } },
+	{ NM_SETTING_BOND_OPTION_USE_CARRIER,      "1",          TYPE_INT, 0, 1 },
+	{ NM_SETTING_BOND_OPTION_AD_SELECT,        "0",          TYPE_BOTH, 0, 2,
+	  { "stable", "bandwidth", "count", NULL } },
+	{ NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY, "0",          TYPE_BOTH, 0, 2,
+	  { "layer2", "layer3+4", "layer2+3", NULL } },
+	{ NM_SETTING_BOND_OPTION_RESEND_IGMP,      "1",          TYPE_INT, 0, 255 },
 };
 
 /**
@@ -190,17 +220,109 @@ nm_setting_bond_get_option (NMSettingBond *setting,
 }
 
 static gboolean
-validate_option (const char *name)
+validate_int (const char *name, const char *value, const BondDefault *def)
 {
+	glong num;
 	guint i;
 
-	g_return_val_if_fail (name != NULL, FALSE);
-	g_return_val_if_fail (name[0] != '\0', FALSE);
+	for (i = 0; i < strlen (value); i++) {
+		if (!g_ascii_isdigit (value[i]) && value[i] != '-')
+			return FALSE;
+	}
 
-	for (i = 0; i < G_N_ELEMENTS (defaults); i++) {
-		if (g_strcmp0 (defaults[i].opt, name) == 0)
+	errno = 0;
+	num = strtol (value, NULL, 10);
+	if (errno)
+		return FALSE;
+	if (num < def->min || num > def->max)
+		return FALSE;
+
+	return TRUE;
+}
+
+static gboolean
+validate_list (const char *name, const char *value, const BondDefault *def)
+{
+	guint i;
+
+	for (i = 0; i < G_N_ELEMENTS (def->list) && def->list[i]; i++) {
+		if (g_strcmp0 (def->list[i], value) == 0)
 			return TRUE;
 	}
+
+	/* empty validation list means all values pass */
+	return def->list[0] == NULL ? TRUE : FALSE;
+}
+
+static gboolean
+validate_ip (const char *name, const char *value)
+{
+	char **ips, **iter;
+	gboolean success = TRUE;
+	struct in_addr addr;
+
+	if (!value || !value[0])
+		return FALSE;
+
+	ips = g_strsplit_set (value, ",", 0);
+	for (iter = ips; iter && *iter && success; iter++)
+		success = !!inet_aton (*iter, &addr);
+	g_strfreev (ips);
+
+	return success;
+}
+
+static gboolean
+validate_ifname (const char *name, const char *value)
+{
+	if (!value || !value[0])
+		return FALSE;
+
+	return nm_utils_iface_valid_name (value);
+}
+
+/**
+ * nm_setting_bond_validate_option:
+ * @name: the name of the option to validate
+ * @value: the value of the option to validate
+ *
+ * Checks whether @name is a valid bond option and @value is a valid value for
+ * the @name. If @value is %NULL, the function only validates the option name.
+ *
+ * Returns: %TRUE, if the @value is valid for the given name.
+ * If the @name is not a valid option, %FALSE will be returned.
+ *
+ * Since: 0.9.10
+ **/
+gboolean
+nm_setting_bond_validate_option (const char *name,
+                                 const char *value)
+{
+	guint i;
+
+	if (!name || !name[0])
+		return FALSE;
+
+	for (i = 0; i < G_N_ELEMENTS (defaults); i++) {
+		if (g_strcmp0 (defaults[i].opt, name) == 0) {
+			if (value == NULL)
+				return TRUE;
+			switch (defaults[i].opt_type) {
+			case TYPE_INT:
+				return validate_int (name, value, &defaults[i]);
+			case TYPE_STR:
+				return validate_list (name, value, &defaults[i]);
+			case TYPE_BOTH:
+				return    validate_int (name, value, &defaults[i])
+				       || validate_list (name, value, &defaults[i]);
+			case TYPE_IP:
+				return validate_ip (name, value);
+			case TYPE_IFNAME:
+				return validate_ifname (name, value);
+			}
+			return FALSE;
+		}
+	}
 	return FALSE;
 }
 
@@ -220,7 +342,9 @@ nm_setting_bond_get_option_by_name (NMSettingBond *setting,
                                     const char *name)
 {
 	g_return_val_if_fail (NM_IS_SETTING_BOND (setting), NULL);
-	g_return_val_if_fail (validate_option (name), NULL);
+
+	if (!nm_setting_bond_validate_option (name, NULL))
+		return NULL;
 
 	return g_hash_table_lookup (NM_SETTING_BOND_GET_PRIVATE (setting)->options, name);
 }
@@ -236,24 +360,25 @@ nm_setting_bond_get_option_by_name (NMSettingBond *setting,
  * (ie [a-zA-Z0-9]).  Adding a new name replaces any existing name/value pair
  * that may already exist.
  *
+ * The order of how to set several options is relevant because there are options
+ * that conflict with each other.
+ *
  * Returns: %TRUE if the option was valid and was added to the internal option
  * list, %FALSE if it was not.
  **/
-gboolean nm_setting_bond_add_option (NMSettingBond *setting,
-                                     const char *name,
-                                     const char *value)
+gboolean
+nm_setting_bond_add_option (NMSettingBond *setting,
+                            const char *name,
+                            const char *value)
 {
 	NMSettingBondPrivate *priv;
-	size_t value_len;
 
 	g_return_val_if_fail (NM_IS_SETTING_BOND (setting), FALSE);
-	g_return_val_if_fail (validate_option (name), FALSE);
-	g_return_val_if_fail (value != NULL, FALSE);
 
-	priv = NM_SETTING_BOND_GET_PRIVATE (setting);
+	if (!value || !nm_setting_bond_validate_option (name, value))
+		return FALSE;
 
-	value_len = strlen (value);
-	g_return_val_if_fail (value_len > 0 && value_len < 200, FALSE);
+	priv = NM_SETTING_BOND_GET_PRIVATE (setting);
 
 	g_hash_table_insert (priv->options, g_strdup (name), g_strdup (value));
 
@@ -268,6 +393,8 @@ gboolean nm_setting_bond_add_option (NMSettingBond *setting,
 		g_hash_table_remove (priv->options, NM_SETTING_BOND_OPTION_UPDELAY);
 	}
 
+	g_object_notify (G_OBJECT (setting), NM_SETTING_BOND_OPTIONS);
+
 	return TRUE;
 }
 
@@ -286,10 +413,17 @@ gboolean
 nm_setting_bond_remove_option (NMSettingBond *setting,
                                const char *name)
 {
+	gboolean found;
+
 	g_return_val_if_fail (NM_IS_SETTING_BOND (setting), FALSE);
-	g_return_val_if_fail (validate_option (name), FALSE);
 
-	return g_hash_table_remove (NM_SETTING_BOND_GET_PRIVATE (setting)->options, name);
+	if (!nm_setting_bond_validate_option (name, NULL))
+		return FALSE;
+
+	found = g_hash_table_remove (NM_SETTING_BOND_GET_PRIVATE (setting)->options, name);
+	if (found)
+		g_object_notify (G_OBJECT (setting), NM_SETTING_BOND_OPTIONS);
+	return found;
 }
 
 /**
@@ -329,25 +463,16 @@ nm_setting_bond_get_option_default (NMSettingBond *setting, const char *name)
 	guint i;
 
 	g_return_val_if_fail (NM_IS_SETTING_BOND (setting), NULL);
-	g_return_val_if_fail (validate_option (name), NULL);
+	g_return_val_if_fail (nm_setting_bond_validate_option (name, NULL), NULL);
 
 	for (i = 0; i < G_N_ELEMENTS (defaults); i++) {
 		if (g_strcmp0 (defaults[i].opt, name) == 0)
 			return defaults[i].val;
 	}
-	/* Any option that passes validate_option() should also be found in defaults */
+	/* Any option that passes nm_setting_bond_validate_option() should also be found in defaults */
 	g_assert_not_reached ();
 }
 
-static gint
-find_setting_by_name (gconstpointer a, gconstpointer b)
-{
-	NMSetting *setting = NM_SETTING (a);
-	const char *str = (const char *) b;
-
-	return strcmp (nm_setting_get_name (setting), str);
-}
-
 static gboolean
 verify (NMSetting *setting, GSList *all_settings, GError **error)
 {
@@ -364,33 +489,35 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 	                              NULL };
 	int miimon = 0, arp_interval = 0;
 	const char *arp_ip_target = NULL;
+	const char *primary;
 
 	if (!priv->interface_name || !strlen(priv->interface_name)) {
-		g_set_error (error,
-		             NM_SETTING_BOND_ERROR,
-		             NM_SETTING_BOND_ERROR_MISSING_PROPERTY,
-		             NM_SETTING_BOND_INTERFACE_NAME);
+		g_set_error_literal (error,
+		                     NM_SETTING_BOND_ERROR,
+		                     NM_SETTING_BOND_ERROR_MISSING_PROPERTY,
+		                     _("property is missing"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_INTERFACE_NAME);
 		return FALSE;
 	}
 
 	if (!nm_utils_iface_valid_name (priv->interface_name)) {
-		g_set_error (error,
-		             NM_SETTING_BOND_ERROR,
-		             NM_SETTING_BOND_ERROR_INVALID_PROPERTY,
-		             NM_SETTING_BOND_INTERFACE_NAME);
+		g_set_error_literal (error,
+		                     NM_SETTING_BOND_ERROR,
+		                     NM_SETTING_BOND_ERROR_INVALID_PROPERTY,
+		                     _("property is invalid"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_INTERFACE_NAME);
 		return FALSE;
 	}
 
 	g_hash_table_iter_init (&iter, priv->options);
 	while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &value)) {
-		if (   !validate_option (key)
-		    || !value[0]
-		    || (strlen (value) > 200)
-		    || strchr (value, ' ')) {
-			g_set_error_literal (error,
-			                     NM_SETTING_BOND_ERROR,
-			                     NM_SETTING_BOND_ERROR_INVALID_OPTION,
-			                     key);
+		if (!value[0] || !nm_setting_bond_validate_option (key, value)) {
+			g_set_error (error,
+			             NM_SETTING_BOND_ERROR,
+			             NM_SETTING_BOND_ERROR_INVALID_OPTION,
+			             _("invalid option '%s' or its value '%s'"),
+			             key, value);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
 			return FALSE;
 		}
 	}
@@ -407,7 +534,10 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 		g_set_error (error,
 		             NM_SETTING_BOND_ERROR,
 		             NM_SETTING_BOND_ERROR_INVALID_OPTION,
+		             _("only one of '%s' and '%s' can be set"),
+		             NM_SETTING_BOND_OPTION_MIIMON,
 		             NM_SETTING_BOND_OPTION_ARP_INTERVAL);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
 	}
 
 	value = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_MODE);
@@ -415,14 +545,18 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 		g_set_error (error,
 		             NM_SETTING_BOND_ERROR,
 		             NM_SETTING_BOND_ERROR_MISSING_OPTION,
+		             _("mandatory option '%s' is missing"),
 		             NM_SETTING_BOND_OPTION_MODE);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
 		return FALSE;
 	}
 	if (!_nm_utils_string_in_list (value, valid_modes)) {
 		g_set_error (error,
 		             NM_SETTING_BOND_ERROR,
 		             NM_SETTING_BOND_ERROR_INVALID_OPTION,
-		             NM_SETTING_BOND_OPTION_MODE);
+		             _("'%s' is not a valid value for '%s'"),
+		             value, NM_SETTING_BOND_OPTION_MODE);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
 		return FALSE;
 	}
 
@@ -433,15 +567,45 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 			g_set_error (error,
 			             NM_SETTING_BOND_ERROR,
 			             NM_SETTING_BOND_ERROR_INVALID_OPTION,
-			             NM_SETTING_BOND_OPTION_ARP_INTERVAL);
+			             _("'%s=%s' is incompatible with '%s > 0'"),
+			             NM_SETTING_BOND_OPTION_MODE, value, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
+			return FALSE;
 		}
 	}
-	if (g_slist_find_custom (all_settings, NM_SETTING_INFINIBAND_SETTING_NAME, find_setting_by_name)) {
+
+	primary = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_PRIMARY);
+	if (strcmp (value, "active-backup") == 0) {
+		if (primary && !nm_utils_iface_valid_name (primary)) {
+			g_set_error (error,
+			             NM_SETTING_BOND_ERROR,
+			             NM_SETTING_BOND_ERROR_INVALID_OPTION,
+			             _("'%s' is not a valid interface name for '%s' option"),
+			             primary, NM_SETTING_BOND_OPTION_PRIMARY);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
+			return FALSE;
+		}
+	} else {
+		if (primary) {
+			g_set_error (error,
+			             NM_SETTING_BOND_ERROR,
+			             NM_SETTING_BOND_ERROR_INVALID_OPTION,
+			             _("'%s' option is only valid for '%s=%s'"),
+			             NM_SETTING_BOND_OPTION_PRIMARY,
+			             NM_SETTING_BOND_OPTION_MODE, "active-backup");
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
+			return FALSE;
+		}
+	}
+
+	if (nm_setting_find_in_list (all_settings, NM_SETTING_INFINIBAND_SETTING_NAME)) {
 		if (strcmp (value, "active-backup") != 0) {
 			g_set_error (error,
 			             NM_SETTING_BOND_ERROR,
 			             NM_SETTING_BOND_ERROR_INVALID_OPTION,
-			             NM_SETTING_BOND_OPTION_MODE);
+			             _("'%s=%s' is not a valid configuration for '%s'"),
+			             NM_SETTING_BOND_OPTION_MODE, value, NM_SETTING_INFINIBAND_SETTING_NAME);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
 			return FALSE;
 		}
 	}
@@ -452,14 +616,18 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 			g_set_error (error,
 			             NM_SETTING_BOND_ERROR,
 			             NM_SETTING_BOND_ERROR_INVALID_OPTION,
-			             NM_SETTING_BOND_OPTION_UPDELAY);
+			             _("'%s' option requires '%s' option to be set"),
+			             NM_SETTING_BOND_OPTION_UPDELAY, NM_SETTING_BOND_OPTION_MIIMON);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
 			return FALSE;
 		}
 		if (g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_DOWNDELAY)) {
 			g_set_error (error,
 			             NM_SETTING_BOND_ERROR,
 			             NM_SETTING_BOND_ERROR_INVALID_OPTION,
-			             NM_SETTING_BOND_OPTION_DOWNDELAY);
+			             _("'%s' option requires '%s' option to be set"),
+			             NM_SETTING_BOND_OPTION_DOWNDELAY, NM_SETTING_BOND_OPTION_MIIMON);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
 			return FALSE;
 		}
 	}
@@ -477,27 +645,33 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 			g_set_error (error,
 			             NM_SETTING_BOND_ERROR,
 			             NM_SETTING_BOND_ERROR_MISSING_OPTION,
-			             NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
+			             _("'%s' option requires '%s' option to be set"),
+			             NM_SETTING_BOND_OPTION_ARP_INTERVAL, NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
 			return FALSE;
 		}
 
 		addrs = g_strsplit (arp_ip_target, ",", -1);
 		if (!addrs[0]) {
-			g_strfreev (addrs);
 			g_set_error (error,
 			             NM_SETTING_BOND_ERROR,
 			             NM_SETTING_BOND_ERROR_INVALID_OPTION,
+			             _("'%s' option is empty"),
 			             NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
+			g_strfreev (addrs);
 			return FALSE;
 		}
 
 		for (i = 0; addrs[i]; i++) {
 			if (!inet_pton (AF_INET, addrs[i], &addr)) {
-				g_strfreev (addrs);
 				g_set_error (error,
 				             NM_SETTING_BOND_ERROR,
 				             NM_SETTING_BOND_ERROR_INVALID_OPTION,
-				             NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
+				             _("'%s' is not a valid IPv4 address for '%s' option"),
+				             NM_SETTING_BOND_OPTION_ARP_IP_TARGET, addrs[i]);
+				g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
+				g_strfreev (addrs);
 				return FALSE;
 			}
 		}
@@ -507,7 +681,9 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
 			g_set_error (error,
 			             NM_SETTING_BOND_ERROR,
 			             NM_SETTING_BOND_ERROR_INVALID_OPTION,
-			             NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
+			             _("'%s' option requires '%s' option to be set"),
+			             NM_SETTING_BOND_OPTION_ARP_IP_TARGET, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
 			return FALSE;
 		}
 	}
@@ -528,14 +704,10 @@ nm_setting_bond_init (NMSettingBond *setting)
 {
 	NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE (setting);
 
-	g_object_set (setting, NM_SETTING_NAME, NM_SETTING_BOND_SETTING_NAME,
-	              NULL);
-
 	priv->options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
 
 	/* Default values: */
 	nm_setting_bond_add_option (setting, NM_SETTING_BOND_OPTION_MODE, "balance-rr");
-	nm_setting_bond_add_option (setting, NM_SETTING_BOND_OPTION_MIIMON, "100");
 }
 
 static void
@@ -564,6 +736,7 @@ set_property (GObject *object, guint prop_id,
 
 	switch (prop_id) {
 	case PROP_INTERFACE_NAME:
+		g_free (priv->interface_name);
 		priv->interface_name = g_value_dup_string (value);
 		break;
 	case PROP_OPTIONS:
@@ -626,14 +799,14 @@ nm_setting_bond_class_init (NMSettingBondClass *setting_class)
 		                      "InterfaceName",
 		                      "The name of the virtual in-kernel bonding network interface",
 		                      NULL,
-		                      G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+		                      G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE));
 
 	/**
 	 * NMSettingBond:options:
 	 *
-	 * Dictionary of key/value pairs of bonding options.  Both keys
-	 * and values must be strings. Option names must contain only
-	 * alphanumeric characters (ie, [a-zA-Z0-9]).
+	 * Dictionary of key/value pairs of bonding options.  Both keys and values
+	 * must be strings. Option names must contain only alphanumeric characters
+	 * (ie, [a-zA-Z0-9]).
 	 **/
 	 g_object_class_install_property
 		 (object_class, PROP_OPTIONS,
@@ -644,5 +817,5 @@ nm_setting_bond_class_init (NMSettingBondClass *setting_class)
 		                             "strings.  Option names must contain only "
 		                             "alphanumeric characters (ie, [a-zA-Z0-9]).",
 		                             DBUS_TYPE_G_MAP_OF_STRING,
-		                             G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
+		                             G_PARAM_READWRITE | NM_SETTING_PARAM_INFERRABLE));
 }