summary refs log tree commit diff
path: root/clients
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2020-07-13 22:03:16 +0200
committerMichael Biebl <biebl@debian.org>2020-07-13 22:03:16 +0200
commit136d191f1c96dbae1489fed7c2565f5e1b1f8d40 (patch)
treeb219a4d9541be3533b0ea62d99a41828e148e3ef /clients
parent10ae7d8cd706062742d0cdb1803d49909aef9e06 (diff)
New upstream version 1.26.0 upstream/1.26.0
Diffstat (limited to 'clients')
-rw-r--r--clients/cli/connections.c64
-rw-r--r--clients/cli/devices.c46
-rw-r--r--clients/cli/utils.h18
-rw-r--r--clients/cloud-setup/nm-cloud-setup-utils.c2
-rw-r--r--clients/common/nm-meta-setting-desc.c25
-rw-r--r--clients/common/nm-meta-setting-desc.h7
-rw-r--r--clients/tui/nmt-page-bond.c146
7 files changed, 192 insertions, 116 deletions
diff --git a/clients/cli/connections.c b/clients/cli/connections.c
index 44e34d56..2b9c4a25 100644
--- a/clients/cli/connections.c
+++ b/clients/cli/connections.c
@@ -4273,45 +4273,36 @@ set_bond_option (NmCli *nmc, NMConnection *con, const OptionInfo *option, const
 {
 	NMSettingBond *s_bond;
 	gboolean success;
+	gs_free char *name = NULL;
+	char *p;
 
 	s_bond = nm_connection_get_setting_bond (con);
 	g_return_val_if_fail (s_bond, FALSE);
 
-	if (!value)
-		return TRUE;
-
-	if (strcmp (option->option, "mode") == 0) {
-		value = nmc_bond_validate_mode (value, error);
-		if (!value)
-			return FALSE;
+	name = g_strdup (option->option);
+	for (p = name; p[0]; p++) {
+		if (p[0] == '-')
+			p[0] = '_';
+	}
 
-		if (g_strcmp0 (value, "active-backup") == 0) {
-			const char *primary[] = { "primary", NULL };
-			enable_options (NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS, primary);
-		}
+	if (nm_str_is_empty (value)) {
+		nm_setting_bond_remove_option (s_bond, name);
+		success = TRUE;
+	} else
+		success = _nm_meta_setting_bond_add_option (NM_SETTING (s_bond), name, value, error);
 
-		success = nm_setting_bond_add_option (s_bond, NM_SETTING_BOND_OPTION_MODE, value);
-	} else if (strcmp (option->option, "primary") == 0)
-		success = nm_setting_bond_add_option (s_bond, NM_SETTING_BOND_OPTION_PRIMARY, value);
-	else if (strcmp (option->option, "miimon") == 0)
-		success = nm_setting_bond_add_option (s_bond, NM_SETTING_BOND_OPTION_MIIMON, value);
-	else if (strcmp (option->option, "downdelay") == 0)
-		success = nm_setting_bond_add_option (s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY, value);
-	else if (strcmp (option->option, "updelay") == 0)
-		success = nm_setting_bond_add_option (s_bond, NM_SETTING_BOND_OPTION_UPDELAY, value);
-	else if (strcmp (option->option, "arp-interval") == 0)
-		success = nm_setting_bond_add_option (s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL, value);
-	else if (strcmp (option->option, "arp-ip-target") == 0)
-		success = nm_setting_bond_add_option (s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET, value);
-	else if (strcmp (option->option, "lacp-rate") == 0)
-		success = nm_setting_bond_add_option (s_bond, NM_SETTING_BOND_OPTION_LACP_RATE, value);
-	else
-		g_return_val_if_reached (FALSE);
+	if (!success)
+		return FALSE;
 
-	if (!success) {
-		g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
-		             _("Error: error adding bond option '%s=%s'."),
-		             option->option, value);
+	if (success) {
+		if (nm_streq (name, NM_SETTING_BOND_OPTION_MODE)) {
+			value = nmc_bond_validate_mode (value, error);
+			if (nm_streq (value, "active-backup")) {
+				enable_options (NM_SETTING_BOND_SETTING_NAME,
+				                NM_SETTING_BOND_OPTIONS,
+				                NM_MAKE_STRV ("primary"));
+			}
+		}
 	}
 
 	return success;
@@ -4718,13 +4709,18 @@ nmc_process_connection_properties (NmCli *nmc,
 		ensure_settings (connection, slv_settings);
 		ensure_settings (connection, type_settings);
 
-		option_orig = **argv;
-		if (!option_orig) {
+		if (*argc <= 0) {
 			g_set_error_literal (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
 			                     _("Error: <setting>.<property> argument is missing."));
 			return FALSE;
 		}
 
+		nm_assert (argv);
+		nm_assert (*argv);
+		nm_assert (**argv);
+
+		option_orig = **argv;
+
 		switch (option_orig[0]) {
 		case '+': modifier = NM_META_ACCESSOR_MODIFIER_ADD; option = &option_orig[1]; break;
 		case '-': modifier = NM_META_ACCESSOR_MODIFIER_DEL; option = &option_orig[1]; break;
diff --git a/clients/cli/devices.c b/clients/cli/devices.c
index 27f72e77..38201b33 100644
--- a/clients/cli/devices.c
+++ b/clients/cli/devices.c
@@ -168,14 +168,14 @@ _metagen_device_detail_general_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_ARGS)
 		return nm_device_get_product (d);
 	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DRIVER:
 		s = nm_device_get_driver (d);
-		return s ?: nmc_meta_generic_get_str_i18n (N_("(unknown)"), get_type);
+		return s ?: nmc_meta_generic_get_unknown (get_type);
 	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_DRIVER_VERSION:
 		return nm_device_get_driver_version (d);
 	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_FIRMWARE_VERSION:
 		return nm_device_get_firmware_version (d);
 	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_HWADDR:
 		s = nm_device_get_hw_address (d);
-		return s ?: nmc_meta_generic_get_str_i18n (N_("(unknown)"), get_type);
+		return s ?: nmc_meta_generic_get_unknown (get_type);
 	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_MTU:
 		return (*out_to_free = g_strdup_printf ("%u", (guint) nm_device_get_mtu (d)));
 	case NMC_GENERIC_INFO_TYPE_DEVICE_DETAIL_GENERAL_STATE:
@@ -2268,10 +2268,19 @@ typedef struct {
 } ModifyInfo;
 
 static void
+modify_info_free (ModifyInfo *info)
+{
+	g_strfreev (info->argv);
+	nm_g_slice_free (info);
+}
+
+NM_AUTO_DEFINE_FCN_VOID0 (ModifyInfo *, _auto_free_modify_info, modify_info_free)
+
+static void
 modify_reapply_cb (GObject *object, GAsyncResult *result, gpointer user_data)
 {
 	NMDevice *device = NM_DEVICE (object);
-	ModifyInfo *info = user_data;
+	nm_auto (_auto_free_modify_info) ModifyInfo *info = user_data;
 	NmCli *nmc = info->nmc;
 	GError *error = NULL;
 
@@ -2289,7 +2298,6 @@ modify_reapply_cb (GObject *object, GAsyncResult *result, gpointer user_data)
 		         nm_device_get_iface (device));
 	}
 
-	g_slice_free (ModifyInfo, info);
 	quit ();
 }
 
@@ -2299,7 +2307,7 @@ modify_get_applied_cb (GObject *object,
                        gpointer user_data)
 {
 	NMDevice *device = NM_DEVICE (object);
-	ModifyInfo *info = user_data;
+	nm_auto (_auto_free_modify_info) ModifyInfo *info = user_data;
 	NmCli *nmc = info->nmc;
 	gs_free_error GError *error = NULL;
 	NMConnection *connection;
@@ -2317,7 +2325,6 @@ modify_get_applied_cb (GObject *object,
 		                 nm_object_get_path (NM_OBJECT (device)),
 		                 error->message);
 		nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
-		g_slice_free (ModifyInfo, info);
 		quit ();
 		return;
 	}
@@ -2328,22 +2335,29 @@ modify_get_applied_cb (GObject *object,
 	if (!nmc_process_connection_properties (info->nmc, connection, &argc, &argv, TRUE, &error)) {
 		g_string_assign (nmc->return_text, error->message);
 		nmc->return_value = error->code;
-		g_slice_free (ModifyInfo, info);
 		quit ();
 		return;
 	}
 
-	if (nmc->complete)
+	if (nmc->complete) {
 		quit ();
-	else
-		nm_device_reapply_async (device, connection, version_id, 0, NULL, modify_reapply_cb, info);
+		return;
+	}
+
+	nm_device_reapply_async (device,
+	                         connection,
+	                         version_id,
+	                         0,
+	                         NULL,
+	                         modify_reapply_cb,
+	                         g_steal_pointer (&info));
 }
 
 static void
 do_device_modify (const NMCCommand *cmd, NmCli *nmc, int argc, const char *const*argv)
 {
 	NMDevice *device = NULL;
-	ModifyInfo *info = NULL;
+	ModifyInfo *info;
 	gs_free_error GError *error = NULL;
 
 	next_arg (nmc, &argc, &argv, NULL);
@@ -2360,10 +2374,12 @@ do_device_modify (const NMCCommand *cmd, NmCli *nmc, int argc, const char *const
 	nmc->nowait_flag = (nmc->timeout == 0);
 	nmc->should_wait++;
 
-	info = g_slice_new0 (ModifyInfo);
-	info->nmc = nmc;
-	info->argc = argc;
-	info->argv = nm_utils_strv_dup ((char **) argv, argc, TRUE);
+	info = g_slice_new (ModifyInfo);
+	*info = (ModifyInfo) {
+		.nmc  = nmc,
+		.argc = argc,
+		.argv = nm_utils_strv_dup ((char **) argv, argc, TRUE),
+	};
 
 	nm_device_get_applied_connection_async (device, 0, NULL, modify_get_applied_cb, info);
 }
diff --git a/clients/cli/utils.h b/clients/cli/utils.h
index d7ad738f..02b81b70 100644
--- a/clients/cli/utils.h
+++ b/clients/cli/utils.h
@@ -289,6 +289,24 @@ nmc_meta_generic_get_str_i18n (const char *s, NMMetaAccessorGetType get_type)
 }
 
 static inline const char *
+nmc_meta_generic_get_str_i18n_null (const char *s, NMMetaAccessorGetType get_type)
+{
+	if (get_type == NM_META_ACCESSOR_GET_TYPE_PARSABLE) {
+		/* in parsable mode, return NULL. That is useful if @s is a pretty string
+		 * to describe a missing value (like "(unknown)"). We don't want to print
+		 * that for parsable mode. */
+		return NULL;
+	}
+	return nmc_meta_generic_get_str_i18n (s, get_type);
+}
+
+static inline const char *
+nmc_meta_generic_get_unknown (NMMetaAccessorGetType get_type)
+{
+	return nmc_meta_generic_get_str_i18n_null (N_("(unknown)"), get_type);
+}
+
+static inline const char *
 nmc_meta_generic_get_bool (gboolean val, NMMetaAccessorGetType get_type)
 {
 	return nmc_meta_generic_get_str_i18n (val ? N_("yes") : N_("no"), get_type);
diff --git a/clients/cloud-setup/nm-cloud-setup-utils.c b/clients/cloud-setup/nm-cloud-setup-utils.c
index a32003cb..ff059e7a 100644
--- a/clients/cloud-setup/nm-cloud-setup-utils.c
+++ b/clients/cloud-setup/nm-cloud-setup-utils.c
@@ -389,8 +389,8 @@ _poll_cancelled_cb (GObject *object, gpointer user_data)
  */
 void
 nmcs_utils_poll (int poll_timeout_ms,
-                 int sleep_timeout_ms,
                  int ratelimit_timeout_ms,
+                 int sleep_timeout_ms,
                  NMCSUtilsPollProbeStartFcn probe_start_fcn,
                  NMCSUtilsPollProbeFinishFcn probe_finish_fcn,
                  gpointer probe_user_data,
diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c
index dd5fd6f3..2ac91b41 100644
--- a/clients/common/nm-meta-setting-desc.c
+++ b/clients/common/nm-meta-setting-desc.c
@@ -2357,8 +2357,8 @@ _get_fcn_bond_options (ARGS_GET_FCN)
 	RETURN_STR_TO_FREE (g_string_free (str, FALSE));
 }
 
-static gboolean
-_optionlist_set_fcn_bond_options (NMSetting *setting,
+gboolean
+_nm_meta_setting_bond_add_option (NMSetting *setting,
                                   const char *name,
                                   const char *value,
                                   GError **error)
@@ -2366,8 +2366,14 @@ _optionlist_set_fcn_bond_options (NMSetting *setting,
 	gs_free char *tmp_value = NULL;
 	char *p;
 
-	if (!value) {
-		nm_setting_bond_remove_option (NM_SETTING_BOND (setting), name);
+	if (   !value
+	    || !value[0]) {
+		if (!nm_setting_bond_remove_option (NM_SETTING_BOND (setting), name)) {
+			nm_utils_error_set (error, NM_UTILS_ERROR_INVALID_ARGUMENT,
+			                    _("failed to unset bond option \"%s\""),
+			                    name);
+			return FALSE;
+		}
 		return TRUE;
 	}
 
@@ -2388,6 +2394,15 @@ _optionlist_set_fcn_bond_options (NMSetting *setting,
 		                    name);
 		return FALSE;
 	}
+
+	if (nm_streq (name, NM_SETTING_BOND_OPTION_ARP_INTERVAL)) {
+		if (_nm_utils_ascii_str_to_int64 (value, 10, 0, G_MAXINT, 0) > 0)
+			_nm_setting_bond_remove_options_miimon (NM_SETTING_BOND (setting));
+	} else if (nm_streq (name, NM_SETTING_BOND_OPTION_MIIMON)) {
+		if (_nm_utils_ascii_str_to_int64 (value, 10, 0, G_MAXINT, 0) > 0)
+			_nm_setting_bond_remove_options_arp_interval (NM_SETTING_BOND (setting));
+	}
+
 	return TRUE;
 }
 
@@ -4883,7 +4898,7 @@ static const NMMetaPropertyInfo property_info_BOND_OPTIONS =
 	    ),
 	    .property_typ_data = DEFINE_PROPERTY_TYP_DATA (
 	        PROPERTY_TYP_DATA_SUBTYPE (optionlist,
-	            .set_fcn =              _optionlist_set_fcn_bond_options,
+	            .set_fcn =              _nm_meta_setting_bond_add_option,
 	        ),
 	        .nested =                   &nm_meta_property_typ_data_bond,
 	    ),
diff --git a/clients/common/nm-meta-setting-desc.h b/clients/common/nm-meta-setting-desc.h
index 24689720..68c03d05 100644
--- a/clients/common/nm-meta-setting-desc.h
+++ b/clients/common/nm-meta-setting-desc.h
@@ -524,4 +524,11 @@ extern const NMMetaPropertyTypDataNested nm_meta_property_typ_data_bond;
 
 /*****************************************************************************/
 
+gboolean _nm_meta_setting_bond_add_option (NMSetting *setting,
+                                           const char *name,
+                                           const char *value,
+                                           GError **error);
+
+/*****************************************************************************/
+
 #endif /* __NM_META_SETTING_DESC_H__ */
diff --git a/clients/tui/nmt-page-bond.c b/clients/tui/nmt-page-bond.c
index b9cd9a0b..e92b9f6c 100644
--- a/clients/tui/nmt-page-bond.c
+++ b/clients/tui/nmt-page-bond.c
@@ -16,6 +16,7 @@
 
 #include "nmt-page-bond.h"
 
+#include "nm-libnm-core-intern/nm-libnm-core-utils.h"
 #include "nmt-mac-entry.h"
 #include "nmt-address-list.h"
 #include "nmt-slave-list.h"
@@ -52,6 +53,14 @@ typedef struct {
 	gboolean updating;
 } NmtPageBondPrivate;
 
+/*****************************************************************************/
+
+static void arp_ip_target_widget_changed (GObject    *object,
+                                          GParamSpec *pspec,
+                                          gpointer    user_data);
+
+/*****************************************************************************/
+
 NmtEditorPage *
 nmt_page_bond_new (NMConnection   *conn,
                    NmtDeviceEntry *deventry)
@@ -97,8 +106,10 @@ bond_options_changed (GObject    *object,
 	NMSettingBond *s_bond = NM_SETTING_BOND (object);
 	NmtPageBond *bond = NMT_PAGE_BOND (user_data);
 	NmtPageBondPrivate *priv = NMT_PAGE_BOND_GET_PRIVATE (bond);
+	gs_free const char **ips = NULL;
 	const char *val;
-	char **ips;
+	gboolean visible_mii;
+	NMBondMode mode;
 
 	if (priv->updating)
 		return;
@@ -108,54 +119,47 @@ bond_options_changed (GObject    *object,
 	val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_MODE);
 	nmt_newt_popup_set_active_id (priv->mode, val);
 
-	if (!strcmp (val, "active-backup")) {
-		nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->primary), TRUE);
-		val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_PRIMARY);
-		nmt_newt_entry_set_text (priv->primary, val);
-	} else
-		nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->primary), FALSE);
+	mode = _nm_setting_bond_mode_from_string (val ?: "");
+
+	val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_PRIMARY);
+	nmt_newt_entry_set_text (priv->primary, val);
+
+	nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->primary), mode == NM_BOND_MODE_ACTIVEBACKUP);
 
 	if (priv->monitoring_mode == NMT_PAGE_BOND_MONITORING_UNKNOWN) {
 		val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
-		if (val && strcmp (val, "0") != 0)
+		if (_nm_utils_ascii_str_to_int64 (val, 10, 0, G_MAXINT, 0) > 0)
 			priv->monitoring_mode = NMT_PAGE_BOND_MONITORING_ARP;
 		else
 			priv->monitoring_mode = NMT_PAGE_BOND_MONITORING_MII;
 	}
 	nmt_newt_popup_set_active (priv->monitoring, priv->monitoring_mode);
 
-	if (priv->monitoring_mode == NMT_PAGE_BOND_MONITORING_MII) {
-		nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->miimon), TRUE);
-		val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_MIIMON);
-		nmt_newt_entry_set_text (priv->miimon, val);
+	val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_MIIMON);
+	nmt_newt_entry_set_text (priv->miimon, val ?: "0");
 
-		nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->updelay), TRUE);
-		val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_UPDELAY);
-		nmt_newt_entry_set_text (priv->updelay, val);
+	val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_UPDELAY);
+	nmt_newt_entry_set_text (priv->updelay, val ?: "0");
 
-		nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->downdelay), TRUE);
-		val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY);
-		nmt_newt_entry_set_text (priv->downdelay, val);
+	val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY);
+	nmt_newt_entry_set_text (priv->downdelay, val ?: "0");
 
-		nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->arp_interval), FALSE);
-		nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->arp_ip_target), FALSE);
-	} else {
-		nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->arp_interval), TRUE);
-		val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
-		nmt_newt_entry_set_text (priv->arp_interval, val);
-
-		nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->arp_ip_target), TRUE);
-		val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
-		ips = g_strsplit (val, ",", -1);
-		g_object_set (G_OBJECT (priv->arp_ip_target),
-		              "strings", ips,
-		              NULL);
-		g_strfreev (ips);
-
-		nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->miimon), FALSE);
-		nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->updelay), FALSE);
-		nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->downdelay), FALSE);
-	}
+	val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
+	nmt_newt_entry_set_text (priv->arp_interval, val ?: "0");
+
+	val = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
+	ips = nm_utils_bond_option_arp_ip_targets_split (val);
+	g_object_set (G_OBJECT (priv->arp_ip_target),
+	              "strings", ips ?: NM_PTRARRAY_EMPTY (const char *),
+	              NULL);
+
+	visible_mii = (priv->monitoring_mode == NMT_PAGE_BOND_MONITORING_MII);
+
+	nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->miimon), visible_mii);
+	nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->updelay), visible_mii);
+	nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->downdelay), visible_mii);
+	nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->arp_interval), !visible_mii);
+	nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->arp_ip_target), !visible_mii);
 
 	priv->updating = FALSE;
 }
@@ -193,7 +197,23 @@ slaves_changed (GObject    *object,
 		nmt_newt_component_set_sensitive (NMT_NEWT_COMPONENT (priv->mode), TRUE);
 }
 
-#define WIDGET_CHANGED_FUNC(widget, func, option) \
+static void
+_bond_add_option (NMSettingBond *s_bond,
+                  const char *option,
+                  const char *value)
+{
+	if (nm_str_is_empty (value))
+		nm_setting_bond_remove_option (s_bond, option);
+	else
+		nm_setting_bond_add_option (s_bond, option, value);
+
+	if (nm_streq (option, NM_SETTING_BOND_OPTION_ARP_INTERVAL))
+		_nm_setting_bond_remove_options_miimon (s_bond);
+	else if (nm_streq (option, NM_SETTING_BOND_OPTION_MIIMON))
+		_nm_setting_bond_remove_options_arp_interval (s_bond);
+}
+
+#define WIDGET_CHANGED_FUNC(widget, func, option, dflt) \
 static void \
 widget ## _widget_changed (GObject    *object, \
                            GParamSpec *pspec, \
@@ -201,20 +221,22 @@ widget ## _widget_changed (GObject    *object, \
 { \
     NmtPageBond *bond = NMT_PAGE_BOND (user_data); \
     NmtPageBondPrivate *priv = NMT_PAGE_BOND_GET_PRIVATE (bond); \
+    const char *v; \
     \
     if (priv->updating) \
         return; \
     \
+    v = func (priv->widget); \
     priv->updating = TRUE; \
-    nm_setting_bond_add_option (priv->s_bond, option, func (priv->widget)); \
+    _bond_add_option (priv->s_bond, option, v ?: dflt); \
     priv->updating = FALSE; \
 }
 
-WIDGET_CHANGED_FUNC (primary, nmt_newt_entry_get_text, NM_SETTING_BOND_OPTION_PRIMARY)
-WIDGET_CHANGED_FUNC (miimon, nmt_newt_entry_get_text, NM_SETTING_BOND_OPTION_MIIMON)
-WIDGET_CHANGED_FUNC (updelay, nmt_newt_entry_get_text, NM_SETTING_BOND_OPTION_UPDELAY)
-WIDGET_CHANGED_FUNC (downdelay, nmt_newt_entry_get_text, NM_SETTING_BOND_OPTION_DOWNDELAY)
-WIDGET_CHANGED_FUNC (arp_interval, nmt_newt_entry_get_text, NM_SETTING_BOND_OPTION_ARP_INTERVAL)
+WIDGET_CHANGED_FUNC (primary, nmt_newt_entry_get_text, NM_SETTING_BOND_OPTION_PRIMARY, NULL)
+WIDGET_CHANGED_FUNC (miimon, nmt_newt_entry_get_text, NM_SETTING_BOND_OPTION_MIIMON, "0")
+WIDGET_CHANGED_FUNC (updelay, nmt_newt_entry_get_text, NM_SETTING_BOND_OPTION_UPDELAY, "0")
+WIDGET_CHANGED_FUNC (downdelay, nmt_newt_entry_get_text, NM_SETTING_BOND_OPTION_DOWNDELAY, "0")
+WIDGET_CHANGED_FUNC (arp_interval, nmt_newt_entry_get_text, NM_SETTING_BOND_OPTION_ARP_INTERVAL, "0")
 
 static void
 mode_widget_changed (GObject    *object,
@@ -230,7 +252,7 @@ mode_widget_changed (GObject    *object,
 
 	mode = nmt_newt_popup_get_active_id (priv->mode);
 	priv->updating = TRUE;
-	nm_setting_bond_add_option (priv->s_bond, NM_SETTING_BOND_OPTION_MODE, mode);
+	_bond_add_option (priv->s_bond, NM_SETTING_BOND_OPTION_MODE, mode);
 	priv->updating = FALSE;
 
 	if (!strcmp (mode, "balance-tlb") || !strcmp (mode, "balance-alb")) {
@@ -241,8 +263,8 @@ mode_widget_changed (GObject    *object,
 
 	if (!strcmp (mode, "active-backup")) {
 		nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->primary), TRUE);
-		nm_setting_bond_add_option (priv->s_bond, NM_SETTING_BOND_OPTION_PRIMARY,
-		                            nmt_newt_entry_get_text (priv->primary));
+		_bond_add_option (priv->s_bond, NM_SETTING_BOND_OPTION_PRIMARY,
+		                  nmt_newt_entry_get_text (priv->primary));
 	} else {
 		nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->primary), FALSE);
 		nm_setting_bond_remove_option (priv->s_bond, NM_SETTING_BOND_OPTION_PRIMARY);
@@ -256,25 +278,27 @@ monitoring_widget_changed (GObject    *object,
 {
 	NmtPageBond *bond = NMT_PAGE_BOND (user_data);
 	NmtPageBondPrivate *priv = NMT_PAGE_BOND_GET_PRIVATE (bond);
+	gboolean visible_mii;
 
 	if (priv->updating)
 		return;
 
 	priv->monitoring_mode = nmt_newt_popup_get_active (priv->monitoring);
-	if (priv->monitoring_mode == NMT_PAGE_BOND_MONITORING_MII) {
-		nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->miimon), TRUE);
-		nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->updelay), TRUE);
-		nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->downdelay), TRUE);
-
-		nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->arp_interval), FALSE);
-		nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->arp_ip_target), FALSE);
+	visible_mii = (priv->monitoring_mode == NMT_PAGE_BOND_MONITORING_MII);
+
+	nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->miimon), visible_mii);
+	nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->updelay), visible_mii);
+	nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->downdelay), visible_mii);
+	nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->arp_interval), !visible_mii);
+	nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->arp_ip_target), !visible_mii);
+
+	if (visible_mii) {
+		miimon_widget_changed (NULL, NULL, bond);
+		updelay_widget_changed (NULL, NULL, bond);
+		downdelay_widget_changed (NULL, NULL, bond);
 	} else {
-		nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->arp_interval), TRUE);
-		nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->arp_ip_target), TRUE);
-
-		nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->miimon), FALSE);
-		nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->updelay), FALSE);
-		nmt_newt_widget_set_visible (NMT_NEWT_WIDGET (priv->downdelay), FALSE);
+		arp_interval_widget_changed (NULL, NULL, bond);
+		arp_ip_target_widget_changed (NULL, NULL, bond);
 	}
 }
 
@@ -296,7 +320,7 @@ arp_ip_target_widget_changed (GObject    *object,
 	target = g_strjoinv (",", ips);
 
 	priv->updating = TRUE;
-	nm_setting_bond_add_option (priv->s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET, target);
+	_bond_add_option (priv->s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET, target);
 	priv->updating = FALSE;
 
 	g_free (target);