about summary refs log tree commit diff
path: root/libnm-core
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 /libnm-core
parent10ae7d8cd706062742d0cdb1803d49909aef9e06 (diff)
New upstream version 1.26.0 upstream/1.26.0
Diffstat (limited to 'libnm-core')
-rw-r--r--libnm-core/nm-core-internal.h15
-rw-r--r--libnm-core/nm-libnm-core-intern/nm-libnm-core-utils.c49
-rw-r--r--libnm-core/nm-libnm-core-intern/nm-libnm-core-utils.h24
-rw-r--r--libnm-core/nm-setting-bond.c254
-rw-r--r--libnm-core/nm-utils.c3
5 files changed, 188 insertions, 157 deletions
diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h
index 1d67b094..3a15d2e9 100644
--- a/libnm-core/nm-core-internal.h
+++ b/libnm-core/nm-core-internal.h
@@ -567,21 +567,6 @@ NMConnectionMultiConnect _nm_connection_get_multi_connect (NMConnection *connect
 
 /*****************************************************************************/
 
-typedef enum {
-	NM_BOND_MODE_UNKNOWN      = -1,
-
-	/* The numeric values correspond to kernel's numbering of the modes. */
-	NM_BOND_MODE_ROUNDROBIN   = 0,
-	NM_BOND_MODE_ACTIVEBACKUP = 1,
-	NM_BOND_MODE_XOR          = 2,
-	NM_BOND_MODE_BROADCAST    = 3,
-	NM_BOND_MODE_8023AD       = 4,
-	NM_BOND_MODE_TLB          = 5,
-	NM_BOND_MODE_ALB          = 6,
-	_NM_BOND_MODE_NUM,
-} NMBondMode;
-
-NMBondMode _nm_setting_bond_mode_from_string (const char *str);
 gboolean _nm_setting_bond_option_supported (const char *option, NMBondMode mode);
 
 /*****************************************************************************/
diff --git a/libnm-core/nm-libnm-core-intern/nm-libnm-core-utils.c b/libnm-core/nm-libnm-core-intern/nm-libnm-core-utils.c
index 8d2ea09c..f2c85cc6 100644
--- a/libnm-core/nm-libnm-core-intern/nm-libnm-core-utils.c
+++ b/libnm-core/nm-libnm-core-intern/nm-libnm-core-utils.c
@@ -10,6 +10,54 @@
 
 /*****************************************************************************/
 
+const char **
+nm_utils_bond_option_arp_ip_targets_split (const char *arp_ip_target)
+{
+	return nm_utils_strsplit_set_full (arp_ip_target, ",", NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP);
+}
+
+void
+_nm_setting_bond_remove_options_miimon (NMSettingBond *s_bond)
+{
+	g_return_if_fail (NM_IS_SETTING_BOND (s_bond));
+
+	nm_setting_bond_remove_option (s_bond, NM_SETTING_BOND_OPTION_MIIMON);
+	nm_setting_bond_remove_option (s_bond, NM_SETTING_BOND_OPTION_UPDELAY);
+	nm_setting_bond_remove_option (s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY);
+}
+
+void
+_nm_setting_bond_remove_options_arp_interval (NMSettingBond *s_bond)
+{
+	g_return_if_fail (NM_IS_SETTING_BOND (s_bond));
+
+	nm_setting_bond_remove_option (s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
+	nm_setting_bond_remove_option (s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
+}
+
+NM_UTILS_STRING_TABLE_LOOKUP_DEFINE (
+	_nm_setting_bond_mode_from_string,
+	NMBondMode,
+	{ g_return_val_if_fail (name, NM_BOND_MODE_UNKNOWN); },
+	{ return NM_BOND_MODE_UNKNOWN; },
+	{ "0",             NM_BOND_MODE_ROUNDROBIN   },
+	{ "1",             NM_BOND_MODE_ACTIVEBACKUP },
+	{ "2",             NM_BOND_MODE_XOR          },
+	{ "3",             NM_BOND_MODE_BROADCAST    },
+	{ "4",             NM_BOND_MODE_8023AD       },
+	{ "5",             NM_BOND_MODE_TLB          },
+	{ "6",             NM_BOND_MODE_ALB          },
+	{ "802.3ad",       NM_BOND_MODE_8023AD       },
+	{ "active-backup", NM_BOND_MODE_ACTIVEBACKUP },
+	{ "balance-alb",   NM_BOND_MODE_ALB          },
+	{ "balance-rr",    NM_BOND_MODE_ROUNDROBIN   },
+	{ "balance-tlb",   NM_BOND_MODE_TLB          },
+	{ "balance-xor",   NM_BOND_MODE_XOR          },
+	{ "broadcast",     NM_BOND_MODE_BROADCAST    },
+);
+
+/*****************************************************************************/
+
 gboolean
 nm_utils_vlan_priority_map_parse_str (NMVlanPriorityMap map_type,
                                       const char *str,
@@ -207,4 +255,5 @@ NM_UTILS_ENUM2STR_DEFINE (nm_utils_route_type2str, guint8,
 	NM_UTILS_ENUM2STR (RTN_THROW, "throw"),
 	NM_UTILS_ENUM2STR (RTN_UNICAST, "unicast"),
 	NM_UTILS_ENUM2STR (RTN_UNREACHABLE, "unreachable"),
+	NM_UTILS_ENUM2STR (RTN_UNSPEC, "unspecified"),
 );
diff --git a/libnm-core/nm-libnm-core-intern/nm-libnm-core-utils.h b/libnm-core/nm-libnm-core-intern/nm-libnm-core-utils.h
index afc214d4..bb3fa5fc 100644
--- a/libnm-core/nm-libnm-core-intern/nm-libnm-core-utils.h
+++ b/libnm-core/nm-libnm-core-intern/nm-libnm-core-utils.h
@@ -5,6 +5,7 @@
 
 /****************************************************************************/
 
+#include "nm-setting-bond.h"
 #include "nm-setting-bridge.h"
 #include "nm-setting-connection.h"
 #include "nm-setting-ip-config.h"
@@ -46,6 +47,29 @@ NM_AUTO_DEFINE_FCN0 (NMWireGuardPeer *, _nm_auto_unref_wgpeer, nm_wireguard_peer
 
 /****************************************************************************/
 
+const char **nm_utils_bond_option_arp_ip_targets_split (const char *arp_ip_target);
+
+void _nm_setting_bond_remove_options_miimon (NMSettingBond *s_bond);
+void _nm_setting_bond_remove_options_arp_interval (NMSettingBond *s_bond);
+
+typedef enum {
+	NM_BOND_MODE_UNKNOWN      = -1,
+
+	/* The numeric values correspond to kernel's numbering of the modes. */
+	NM_BOND_MODE_ROUNDROBIN   = 0,
+	NM_BOND_MODE_ACTIVEBACKUP = 1,
+	NM_BOND_MODE_XOR          = 2,
+	NM_BOND_MODE_BROADCAST    = 3,
+	NM_BOND_MODE_8023AD       = 4,
+	NM_BOND_MODE_TLB          = 5,
+	NM_BOND_MODE_ALB          = 6,
+	_NM_BOND_MODE_NUM,
+} NMBondMode;
+
+NMBondMode _nm_setting_bond_mode_from_string (const char *str);
+
+/*****************************************************************************/
+
 static inline guint32
 nm_utils_vlan_priority_map_get_max_prio (NMVlanPriorityMap map, gboolean from)
 {
diff --git a/libnm-core/nm-setting-bond.c b/libnm-core/nm-setting-bond.c
index 8986e434..6e0a5e5b 100644
--- a/libnm-core/nm-setting-bond.c
+++ b/libnm-core/nm-setting-bond.c
@@ -11,6 +11,7 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
+#include "nm-libnm-core-intern/nm-libnm-core-utils.h"
 #include "nm-utils.h"
 #include "nm-utils-private.h"
 #include "nm-connection-private.h"
@@ -250,9 +251,7 @@ _bond_get_option_normalized (NMSettingBond* self,
                              const char* option,
                              gboolean get_default_only)
 {
-	const char *arp_interval_str;
 	const char *mode_str;
-	gint64 arp_interval;
 	NMBondMode mode;
 	const char *value = NULL;
 
@@ -261,7 +260,12 @@ _bond_get_option_normalized (NMSettingBond* self,
 
 	mode_str = _bond_get_option_or_default (self, NM_SETTING_BOND_OPTION_MODE);
 	mode = _nm_setting_bond_mode_from_string (mode_str);
-	g_return_val_if_fail (mode != NM_BOND_MODE_UNKNOWN, NULL);
+
+	if (mode == NM_BOND_MODE_UNKNOWN) {
+		/* the mode is unknown, consequently, there is no normalized/default
+		 * value either. */
+		return NULL;
+	}
 
 	if (!_nm_setting_bond_option_supported (option, mode))
 		return NULL;
@@ -269,46 +273,44 @@ _bond_get_option_normalized (NMSettingBond* self,
 	/* Apply custom NetworkManager policies here */
 	if (!get_default_only) {
 		if (NM_IN_STRSET (option,
-		                  NM_SETTING_BOND_OPTION_UPDELAY,
-		                  NM_SETTING_BOND_OPTION_DOWNDELAY,
-		                  NM_SETTING_BOND_OPTION_MIIMON)) {
+		                  NM_SETTING_BOND_OPTION_ARP_INTERVAL,
+		                  NM_SETTING_BOND_OPTION_ARP_IP_TARGET)) {
+			int miimon;
+
 			/* if arp_interval is explicitly set and miimon is not, then disable miimon
 			 * (and related updelay and downdelay) as recommended by the kernel docs */
-			arp_interval_str = _bond_get_option (self, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
-			arp_interval = _nm_utils_ascii_str_to_int64 (arp_interval_str, 10, 0, G_MAXINT, 0);
-
-			if (!arp_interval || _bond_get_option (self, NM_SETTING_BOND_OPTION_MIIMON)) {
-				value = _bond_get_option (self, option);
-			} else {
-				return NULL;
+			miimon = _nm_utils_ascii_str_to_int64 (_bond_get_option (self, NM_SETTING_BOND_OPTION_MIIMON),
+			                                       10, 0, G_MAXINT, 0);
+			if (miimon != 0) {
+				/* miimon is enabled. arp_interval values are unset. */
+				if (nm_streq (option, NM_SETTING_BOND_OPTION_ARP_INTERVAL))
+					return "0";
+				return "";
 			}
+			value = _bond_get_option (self, option);
 		} else if (NM_IN_STRSET (option,
 		                         NM_SETTING_BOND_OPTION_NUM_GRAT_ARP,
 		                         NM_SETTING_BOND_OPTION_NUM_UNSOL_NA)) {
 			/* just get one of the 2, at kernel level they're the same bond option */
 			value = _bond_get_option (self, NM_SETTING_BOND_OPTION_NUM_GRAT_ARP);
-			if (!value) {
+			if (!value)
 				value = _bond_get_option (self, NM_SETTING_BOND_OPTION_NUM_UNSOL_NA);
-			}
-		} else {
+		} else
 			value = _bond_get_option (self, option);
-		}
+
+		if (value)
+			return value;
 	}
 
-	if (!value) {
-		/* Apply rules that change the default value of an option */
-		if (nm_streq (option, NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM)) {
-			/* The default value depends on the current mode */
-			if (NM_IN_STRSET (mode_str, "4", "802.3ad"))
-				return "00:00:00:00:00:00";
-			else
-				return "";
-		} else {
-			return _bond_get_option_or_default (self, option);
-		}
+	/* Apply rules that change the default value of an option */
+	if (nm_streq (option, NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM)) {
+		/* The default value depends on the current mode */
+		if (mode == NM_BOND_MODE_8023AD)
+			return "00:00:00:00:00:00";
+		return "";
 	}
 
-	return value;
+	return _bond_get_option_or_default (self, option);
 }
 
 const char*
@@ -447,34 +449,30 @@ validate_list (const char *name, const char *value, const OptionMeta *option_met
 }
 
 static gboolean
-validate_ip (const char *name, const char *value)
+validate_ip (const char *name, const char *value, GError **error)
 {
-	gs_free char *value_clone = NULL;
-	struct in_addr addr;
+	gs_free const char **addrs = NULL;
+	gsize i;
 
-	if (!value || !value[0])
+	addrs = nm_utils_bond_option_arp_ip_targets_split (value);
+	if (!addrs) {
+		g_set_error (error,
+		             NM_CONNECTION_ERROR,
+		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		             _("'%s' option is empty"),
+		             name);
 		return FALSE;
-
-	value_clone = g_strdup (value);
-	value = value_clone;
-	for (;;) {
-		char *eow;
-
-		/* we do not skip over empty words. E.g
-		 * "192.168.1.1," is an error.
-		 *
-		 * ... for no particular reason. */
-
-		eow = strchr (value, ',');
-		if (eow)
-			*eow = '\0';
-
-		if (inet_pton (AF_INET, value, &addr) != 1)
+	}
+	for (i = 0; addrs[i]; i++) {
+		if (!nm_utils_parse_inaddr_bin (AF_INET, addrs[i], NULL, NULL)) {
+			g_set_error (error,
+			             NM_CONNECTION_ERROR,
+			             NM_CONNECTION_ERROR_INVALID_PROPERTY,
+			             _("'%s' is not a valid IPv4 address for '%s' option"),
+			             addrs[i],
+			             name);
 			return FALSE;
-
-		if (!eow)
-			break;
-		value = eow + 1;
+		}
 	}
 	return TRUE;
 }
@@ -485,46 +483,83 @@ validate_ifname (const char *name, const char *value)
 	return nm_utils_ifname_valid_kernel (value, NULL);
 }
 
-/**
- * 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.
- **/
-gboolean
-nm_setting_bond_validate_option (const char *name,
-                                 const char *value)
+static gboolean
+_setting_bond_validate_option (const char *name,
+                               const char *value,
+                               GError **error)
 {
 	const OptionMeta *option_meta;
+	gboolean success;
 
 	option_meta = _get_option_meta (name);
-	if (!option_meta)
+	if (!option_meta) {
+		if (!name) {
+			g_set_error (error,
+			             NM_CONNECTION_ERROR,
+			             NM_CONNECTION_ERROR_INVALID_PROPERTY,
+			             _("missing option name"));
+		} else {
+			g_set_error (error,
+			             NM_CONNECTION_ERROR,
+			             NM_CONNECTION_ERROR_INVALID_PROPERTY,
+			             _("invalid option '%s'"),
+			             name);
+		}
 		return FALSE;
+	}
 
 	if (!value)
 		return TRUE;
 
 	switch (option_meta->opt_type) {
 	case NM_BOND_OPTION_TYPE_INT:
-		return validate_int (name, value, option_meta);
+		success = validate_int (name, value, option_meta);
+		goto handle_error;
 	case NM_BOND_OPTION_TYPE_BOTH:
-		return (   validate_int (name, value, option_meta)
-		        || validate_list (name, value, option_meta));
+		success = (   validate_int (name, value, option_meta)
+		           || validate_list (name, value, option_meta));
+		goto handle_error;
 	case NM_BOND_OPTION_TYPE_IP:
-		return validate_ip (name, value);
+		nm_assert (nm_streq0 (name, NM_SETTING_BOND_OPTION_ARP_IP_TARGET));
+		return validate_ip (name, value, error);
 	case NM_BOND_OPTION_TYPE_MAC:
-		return nm_utils_hwaddr_valid (value, ETH_ALEN);
+		success = nm_utils_hwaddr_valid (value, ETH_ALEN);
+		goto handle_error;
 	case NM_BOND_OPTION_TYPE_IFNAME:
-		return validate_ifname (name, value);
+		success = validate_ifname (name, value);
+		goto handle_error;
 	}
 
 	nm_assert_not_reached ();
-	return FALSE;
+	success = FALSE;
+
+handle_error:
+	if (!success) {
+		g_set_error (error,
+		             NM_CONNECTION_ERROR,
+		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		             _("invalid value '%s' for option '%s'"),
+		             value, name);
+	}
+	return success;
+}
+
+/**
+ * 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.
+ **/
+gboolean
+nm_setting_bond_validate_option (const char *name,
+                                 const char *value)
+{
+	return _setting_bond_validate_option (name, value, NULL);
 }
 
 /**
@@ -576,7 +611,8 @@ nm_setting_bond_add_option (NMSettingBond *setting,
 
 	g_return_val_if_fail (NM_IS_SETTING_BOND (setting), FALSE);
 
-	if (!value || !nm_setting_bond_validate_option (name, value))
+	if (   !value
+	    || !nm_setting_bond_validate_option (name, value))
 		return FALSE;
 
 	priv = NM_SETTING_BOND_GET_PRIVATE (setting);
@@ -650,9 +686,8 @@ nm_setting_bond_get_option_default (NMSettingBond *setting, const char *name)
 {
 	g_return_val_if_fail (NM_IS_SETTING_BOND (setting), NULL);
 
-	if (!name) {
+	if (!name)
 		return NULL;
-	}
 
 	return _bond_get_option_normalized (setting,
 	                                    name,
@@ -703,27 +738,6 @@ _nm_setting_bond_get_option_type (NMSettingBond *setting, const char *name)
 	return option_meta->opt_type;
 }
 
-NM_UTILS_STRING_TABLE_LOOKUP_DEFINE (
-	_nm_setting_bond_mode_from_string,
-	NMBondMode,
-	{ g_return_val_if_fail (name, NM_BOND_MODE_UNKNOWN); },
-	{ return NM_BOND_MODE_UNKNOWN; },
-	{ "0",             NM_BOND_MODE_ROUNDROBIN   },
-	{ "1",             NM_BOND_MODE_ACTIVEBACKUP },
-	{ "2",             NM_BOND_MODE_XOR          },
-	{ "3",             NM_BOND_MODE_BROADCAST    },
-	{ "4",             NM_BOND_MODE_8023AD       },
-	{ "5",             NM_BOND_MODE_TLB          },
-	{ "6",             NM_BOND_MODE_ALB          },
-	{ "802.3ad",       NM_BOND_MODE_8023AD       },
-	{ "active-backup", NM_BOND_MODE_ACTIVEBACKUP },
-	{ "balance-alb",   NM_BOND_MODE_ALB          },
-	{ "balance-rr",    NM_BOND_MODE_ROUNDROBIN   },
-	{ "balance-tlb",   NM_BOND_MODE_TLB          },
-	{ "balance-xor",   NM_BOND_MODE_XOR          },
-	{ "broadcast",     NM_BOND_MODE_BROADCAST    },
-);
-
 /*****************************************************************************/
 
 static gboolean
@@ -750,12 +764,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 			n = &priv->options_idx_cache[i];
 
 			if (   !n->value_str
-			    || !nm_setting_bond_validate_option (n->name, n->value_str)) {
-				g_set_error (error,
-				             NM_CONNECTION_ERROR,
-				             NM_CONNECTION_ERROR_INVALID_PROPERTY,
-				             _("invalid option '%s' or its value '%s'"),
-				             n->name, n->value_str);
+			    || !_setting_bond_validate_option (n->name, n->value_str, error)) {
 				g_prefix_error (error,
 				                "%s.%s: ",
 				                NM_SETTING_BOND_SETTING_NAME,
@@ -902,9 +911,6 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 	 */
 	arp_ip_target = _bond_get_option (self, NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
 	if (arp_interval > 0) {
-		char **addrs;
-		guint32 addr;
-
 		if (!arp_ip_target) {
 			g_set_error (error,
 			             NM_CONNECTION_ERROR,
@@ -918,38 +924,6 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 			                NM_SETTING_BOND_OPTIONS);
 			return FALSE;
 		}
-
-		addrs = g_strsplit (arp_ip_target, ",", -1);
-		if (!addrs[0]) {
-			g_set_error (error,
-			             NM_CONNECTION_ERROR,
-			             NM_CONNECTION_ERROR_INVALID_PROPERTY,
-			             _("'%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_set_error (error,
-				             NM_CONNECTION_ERROR,
-				             NM_CONNECTION_ERROR_INVALID_PROPERTY,
-				             _("'%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;
-			}
-		}
-		g_strfreev (addrs);
 	} else {
 		if (arp_ip_target) {
 			g_set_error (error,
diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c
index c88afb32..425c3027 100644
--- a/libnm-core/nm-utils.c
+++ b/libnm-core/nm-utils.c
@@ -5428,7 +5428,7 @@ gboolean
 nm_utils_is_json_object (const char *str, GError **error)
 {
 #if WITH_JSON_VALIDATION
-	json_t *json;
+	nm_auto_decref_json json_t *json = NULL;
 	json_error_t jerror;
 
 	g_return_val_if_fail (!error || !*error, FALSE);
@@ -5465,7 +5465,6 @@ nm_utils_is_json_object (const char *str, GError **error)
 		return FALSE;
 	}
 
-	json_decref (json);
 	return TRUE;
 #else /* !WITH_JSON_VALIDATION */
 	g_return_val_if_fail (!error || !*error, FALSE);