summary refs log tree commit diff
path: root/libnm-core/nm-utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'libnm-core/nm-utils.c')
-rw-r--r--libnm-core/nm-utils.c313
1 files changed, 138 insertions, 175 deletions
diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c
index ea4c52c0..062ff393 100644
--- a/libnm-core/nm-utils.c
+++ b/libnm-core/nm-utils.c
@@ -802,53 +802,7 @@ _nm_utils_hash_values_to_slist (GHashTable *hash)
 static GVariant *
 _nm_utils_strdict_to_dbus (const GValue *prop_value)
 {
-	GHashTable *hash;
-	GHashTableIter iter;
-	const char *key, *value;
-	GVariantBuilder builder;
-	guint i, len;
-
-	g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{ss}"));
-
-	hash = g_value_get_boxed (prop_value);
-	if (!hash)
-		goto out;
-	len = g_hash_table_size (hash);
-	if (!len)
-		goto out;
-
-	g_hash_table_iter_init (&iter, hash);
-	if (!g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &value))
-		nm_assert_not_reached ();
-
-	if (len == 1)
-		g_variant_builder_add (&builder, "{ss}", key, value);
-	else {
-		gs_free NMUtilsNamedValue *idx_free = NULL;
-		NMUtilsNamedValue *idx;
-
-		if (len > 300 / sizeof (NMUtilsNamedValue)) {
-			idx_free = g_new (NMUtilsNamedValue, len);
-			idx = idx_free;
-		} else
-			idx = g_alloca (sizeof (NMUtilsNamedValue) * len);
-
-		i = 0;
-		do {
-			idx[i].name = key;
-			idx[i].value_str = value;
-			i++;
-		} while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &value));
-		nm_assert (i == len);
-
-		nm_utils_named_value_list_sort (idx, len, NULL, NULL);
-
-		for (i = 0; i < len; i++)
-			g_variant_builder_add (&builder, "{ss}", idx[i].name, idx[i].value_str);
-	}
-
-out:
-	return g_variant_builder_end (&builder);
+	return nm_utils_strdict_to_variant_ass (g_value_get_boxed (prop_value));
 }
 
 void
@@ -1119,8 +1073,14 @@ nm_utils_ap_mode_security_valid (NMUtilsSecurityType type,
 	case NMU_SEC_WPA_PSK:
 	case NMU_SEC_WPA2_PSK:
 	case NMU_SEC_SAE:
+	case NMU_SEC_OWE:
 		return TRUE;
-	default:
+	case NMU_SEC_LEAP:
+	case NMU_SEC_DYNAMIC_WEP:
+	case NMU_SEC_WPA_ENTERPRISE:
+	case NMU_SEC_WPA2_ENTERPRISE:
+		return FALSE;
+	case NMU_SEC_INVALID:
 		break;
 	}
 	return FALSE;
@@ -1159,48 +1119,46 @@ nm_utils_security_valid (NMUtilsSecurityType type,
                          NM80211ApSecurityFlags ap_wpa,
                          NM80211ApSecurityFlags ap_rsn)
 {
-	gboolean good = TRUE;
-
-	if (!have_ap) {
-		if (type == NMU_SEC_NONE)
-			return TRUE;
-		if (   (type == NMU_SEC_STATIC_WEP)
-		    || ((type == NMU_SEC_DYNAMIC_WEP) && !adhoc)
-		    || ((type == NMU_SEC_LEAP) && !adhoc)) {
-			if (wifi_caps & (NM_WIFI_DEVICE_CAP_CIPHER_WEP40 | NM_WIFI_DEVICE_CAP_CIPHER_WEP104))
-				return TRUE;
-			else
-				return FALSE;
-		}
-	}
-
 	switch (type) {
 	case NMU_SEC_NONE:
-		g_assert (have_ap);
+		if (!have_ap)
+			return TRUE;
 		if (ap_flags & NM_802_11_AP_FLAGS_PRIVACY)
 			return FALSE;
-		if (ap_wpa || ap_rsn)
+		if (   ap_wpa
+		    || ap_rsn)
 			return FALSE;
-		break;
+		return TRUE;
 	case NMU_SEC_LEAP: /* require PRIVACY bit for LEAP? */
 		if (adhoc)
 			return FALSE;
 		/* fall-through */
 	case NMU_SEC_STATIC_WEP:
-		g_assert (have_ap);
+		if (!have_ap) {
+			if (wifi_caps & (NM_WIFI_DEVICE_CAP_CIPHER_WEP40 | NM_WIFI_DEVICE_CAP_CIPHER_WEP104))
+				return TRUE;
+			return FALSE;
+		}
 		if (!(ap_flags & NM_802_11_AP_FLAGS_PRIVACY))
 			return FALSE;
-		if (ap_wpa || ap_rsn) {
-			if (!device_supports_ap_ciphers (wifi_caps, ap_wpa, TRUE))
+		if (   ap_wpa
+		    || ap_rsn) {
+			if (!device_supports_ap_ciphers (wifi_caps, ap_wpa, TRUE)) {
 				if (!device_supports_ap_ciphers (wifi_caps, ap_rsn, TRUE))
 					return FALSE;
+			}
 		}
-		break;
+		return TRUE;
 	case NMU_SEC_DYNAMIC_WEP:
 		if (adhoc)
 			return FALSE;
-		g_assert (have_ap);
-		if (ap_rsn || !(ap_flags & NM_802_11_AP_FLAGS_PRIVACY))
+		if (!have_ap) {
+			if (wifi_caps & (NM_WIFI_DEVICE_CAP_CIPHER_WEP40 | NM_WIFI_DEVICE_CAP_CIPHER_WEP104))
+				return TRUE;
+			return FALSE;
+		}
+		if (   ap_rsn
+		    || !(ap_flags & NM_802_11_AP_FLAGS_PRIVACY))
 			return FALSE;
 		/* Some APs broadcast minimal WPA-enabled beacons that must be handled */
 		if (ap_wpa) {
@@ -1209,102 +1167,99 @@ nm_utils_security_valid (NMUtilsSecurityType type,
 			if (!device_supports_ap_ciphers (wifi_caps, ap_wpa, FALSE))
 				return FALSE;
 		}
-		break;
+		return TRUE;
 	case NMU_SEC_WPA_PSK:
 		if (adhoc)
 			return FALSE;
 		if (!(wifi_caps & NM_WIFI_DEVICE_CAP_WPA))
 			return FALSE;
-		if (have_ap) {
-			if (ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_PSK) {
-				if (   (ap_wpa & NM_802_11_AP_SEC_PAIR_TKIP)
-				    && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP))
-					return TRUE;
-				if (   (ap_wpa & NM_802_11_AP_SEC_PAIR_CCMP)
-				    && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP))
-					return TRUE;
-			}
-			return FALSE;
+		if (!have_ap)
+			return TRUE;
+		if (ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_PSK) {
+			if (   (ap_wpa & NM_802_11_AP_SEC_PAIR_TKIP)
+			    && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP))
+				return TRUE;
+			if (   (ap_wpa & NM_802_11_AP_SEC_PAIR_CCMP)
+			    && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP))
+				return TRUE;
 		}
-		break;
+		return FALSE;
 	case NMU_SEC_WPA2_PSK:
 		if (!(wifi_caps & NM_WIFI_DEVICE_CAP_RSN))
 			return FALSE;
-		if (have_ap) {
-			if (adhoc) {
-				if (!(wifi_caps & NM_WIFI_DEVICE_CAP_IBSS_RSN))
-					return FALSE;
-				if (   (ap_rsn & NM_802_11_AP_SEC_PAIR_CCMP)
-				    && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP))
-					return TRUE;
-			} else {
-				if (ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_PSK) {
-					if (   (ap_rsn & NM_802_11_AP_SEC_PAIR_TKIP)
-					    && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP))
-						return TRUE;
-					if (   (ap_rsn & NM_802_11_AP_SEC_PAIR_CCMP)
-					    && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP))
-						return TRUE;
-				}
-			}
+		if (!have_ap)
+			return TRUE;
+		if (adhoc) {
+			if (!(wifi_caps & NM_WIFI_DEVICE_CAP_IBSS_RSN))
+				return FALSE;
+			if (   (ap_rsn & NM_802_11_AP_SEC_PAIR_CCMP)
+			    && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP))
+				return TRUE;
 			return FALSE;
 		}
-		break;
+		if (ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_PSK) {
+			if (   (ap_rsn & NM_802_11_AP_SEC_PAIR_TKIP)
+			    && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP))
+				return TRUE;
+			if (   (ap_rsn & NM_802_11_AP_SEC_PAIR_CCMP)
+			    && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP))
+				return TRUE;
+		}
+		return FALSE;
 	case NMU_SEC_WPA_ENTERPRISE:
 		if (adhoc)
 			return FALSE;
 		if (!(wifi_caps & NM_WIFI_DEVICE_CAP_WPA))
 			return FALSE;
-		if (have_ap) {
-			if (!(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_802_1X))
-				return FALSE;
-			/* Ensure at least one WPA cipher is supported */
-			if (!device_supports_ap_ciphers (wifi_caps, ap_wpa, FALSE))
-				return FALSE;
-		}
-		break;
+		if (!have_ap)
+			return TRUE;
+		if (!(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_802_1X))
+			return FALSE;
+		/* Ensure at least one WPA cipher is supported */
+		if (!device_supports_ap_ciphers (wifi_caps, ap_wpa, FALSE))
+			return FALSE;
+		return TRUE;
 	case NMU_SEC_WPA2_ENTERPRISE:
 		if (adhoc)
 			return FALSE;
 		if (!(wifi_caps & NM_WIFI_DEVICE_CAP_RSN))
 			return FALSE;
-		if (have_ap) {
-			if (!(ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_802_1X))
-				return FALSE;
-			/* Ensure at least one WPA cipher is supported */
-			if (!device_supports_ap_ciphers (wifi_caps, ap_rsn, FALSE))
-				return FALSE;
-		}
-		break;
+		if (!have_ap)
+			return TRUE;
+		if (!(ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_802_1X))
+			return FALSE;
+		/* Ensure at least one WPA cipher is supported */
+		if (!device_supports_ap_ciphers (wifi_caps, ap_rsn, FALSE))
+			return FALSE;
+		return TRUE;
 	case NMU_SEC_SAE:
 		if (!(wifi_caps & NM_WIFI_DEVICE_CAP_RSN))
 			return FALSE;
-		if (have_ap) {
-			if (adhoc) {
-				if (!(wifi_caps & NM_WIFI_DEVICE_CAP_IBSS_RSN))
-					return FALSE;
-				if (   (ap_rsn & NM_802_11_AP_SEC_PAIR_CCMP)
-				    && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP))
-					return TRUE;
-			} else {
-				if (ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_SAE) {
-					if (   (ap_rsn & NM_802_11_AP_SEC_PAIR_TKIP)
-					    && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP))
-						return TRUE;
-					if (   (ap_rsn & NM_802_11_AP_SEC_PAIR_CCMP)
-					    && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP))
-						return TRUE;
-				}
-			}
+		if (adhoc)
 			return FALSE;
+		if (!have_ap)
+			return TRUE;
+		if (ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_SAE) {
+			if (   (ap_rsn & NM_802_11_AP_SEC_PAIR_CCMP)
+			    && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP))
+				return TRUE;
 		}
-		break;
-	default:
-		good = FALSE;
+		return FALSE;
+	case NMU_SEC_OWE:
+		if (adhoc)
+			return FALSE;
+		if (!(wifi_caps & NM_WIFI_DEVICE_CAP_RSN))
+			return FALSE;
+		if (!have_ap)
+			return TRUE;
+		if (!(ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_OWE))
+			return FALSE;
+		return TRUE;
+	case NMU_SEC_INVALID:
 		break;
 	}
 
-	return good;
+	return FALSE;
 }
 
 /**
@@ -2298,7 +2253,7 @@ _nm_utils_parse_tc_handle (const char *str, GError **error)
 
 	nm_assert (str);
 
-	maj = g_ascii_strtoll (str, (char **) &sep, 0x10);
+	maj = nm_g_ascii_strtoll (str, (char **) &sep, 0x10);
 	if (sep == str)
 		goto fail;
 
@@ -2307,7 +2262,7 @@ _nm_utils_parse_tc_handle (const char *str, GError **error)
 	if (sep[0] == ':') {
 		const char *str2 = &sep[1];
 
-		min = g_ascii_strtoll (str2, (char **) &sep, 0x10);
+		min = nm_g_ascii_strtoll (str2, (char **) &sep, 0x10);
 		sep = nm_str_skip_leading_spaces (sep);
 		if (sep[0] != '\0')
 			goto fail;
@@ -4231,6 +4186,41 @@ _nm_utils_hwaddr_canonical_or_invalid (const char *mac, gssize length)
 		return g_strdup (mac);
 }
 
+/*
+ * Determine if given Ethernet address is link-local
+ *
+ * Return value: %TRUE if @mac is link local
+ * reserved addr (01:80:c2:00:00:0X) per IEEE 802.1Q 8.6.3 Frame filtering, %FALSE if not.
+ */
+gboolean
+_nm_utils_hwaddr_link_local_valid (const char *mac)
+{
+	guint8 mac_net[ETH_ALEN];
+	static const guint8 eth_reserved_addr_base[] = {
+		0x01, 0x80,
+		0xc2, 0x00,
+		0x00
+	};
+
+	if (!mac)
+		return FALSE;
+
+	if (!nm_utils_hwaddr_aton (mac, mac_net, ETH_ALEN))
+		return FALSE;
+
+	if (   memcmp (mac_net,
+	               eth_reserved_addr_base, ETH_ALEN - 1)
+	    || (mac_net[5] & 0xF0))
+		return FALSE;
+
+	if (   mac_net[5] == 1  /* 802.3x Pause address */
+	    || mac_net[5] == 2  /* 802.3ad Slow protocols */
+	    || mac_net[5] == 3) /* 802.1X PAE address */
+		return FALSE;
+
+	return TRUE;
+}
+
 /**
  * nm_utils_hwaddr_matches:
  * @hwaddr1: (nullable): pointer to a binary or ASCII hardware address, or %NULL
@@ -4487,7 +4477,7 @@ _nm_utils_hwaddr_from_dbus (GVariant *dbus_value,
 	g_value_take_string (prop_value, str);
 }
 
-const NMSettInfoPropertType nm_sett_info_propert_type_mac_addrees = {
+const NMSettInfoPropertType nm_sett_info_propert_type_mac_address = {
 	.dbus_type           = G_VARIANT_TYPE_BYTESTRING,
 	.gprop_to_dbus_fcn   = _nm_utils_hwaddr_to_dbus,
 	.gprop_from_dbus_fcn = _nm_utils_hwaddr_from_dbus,
@@ -4728,7 +4718,7 @@ nm_utils_is_valid_iface_name (const char *name, GError **error)
  *
  * Validate the network interface name.
  *
- * Deprecated: 1.6: use nm_utils_is_valid_iface_name() instead, with better error reporting.
+ * Deprecated: 1.6: Use nm_utils_is_valid_iface_name() instead, with better error reporting.
  *
  * Returns: %TRUE if interface name is valid, otherwise %FALSE is returned.
  *
@@ -4781,23 +4771,6 @@ nm_utils_is_uuid (const char *str)
 
 static char _nm_utils_inet_ntop_buffer[NM_UTILS_INET_ADDRSTRLEN];
 
-const char *
-nm_utils_inet_ntop (int addr_family, gconstpointer addr, char *dst)
-{
-	const char *s;
-
-	nm_assert_addr_family (addr_family);
-	nm_assert (addr);
-	nm_assert (dst);
-
-	s = inet_ntop (addr_family,
-	               addr,
-	               dst,
-	               addr_family == AF_INET6 ? INET6_ADDRSTRLEN : INET_ADDRSTRLEN);
-	nm_assert (s);
-	return s;
-}
-
 /**
  * nm_utils_inet4_ntop: (skip)
  * @inaddr: the address that should be converted to string.
@@ -4823,8 +4796,7 @@ nm_utils_inet4_ntop (in_addr_t inaddr, char *dst)
 	 *
 	 * However, still support it to be lenient against mistakes and because
 	 * this is public API of libnm. */
-	return inet_ntop (AF_INET, &inaddr, dst ?: _nm_utils_inet_ntop_buffer,
-	                  INET_ADDRSTRLEN);
+	return _nm_utils_inet4_ntop (inaddr, dst ?: _nm_utils_inet_ntop_buffer);
 }
 
 /**
@@ -4854,8 +4826,7 @@ nm_utils_inet6_ntop (const struct in6_addr *in6addr, char *dst)
 	 * However, still support it to be lenient against mistakes and because
 	 * this is public API of libnm. */
 	g_return_val_if_fail (in6addr, NULL);
-	return inet_ntop (AF_INET6, in6addr, dst ?: _nm_utils_inet_ntop_buffer,
-	                  INET6_ADDRSTRLEN);
+	return _nm_utils_inet6_ntop (in6addr, dst ?: _nm_utils_inet_ntop_buffer);
 }
 
 /**
@@ -4871,17 +4842,9 @@ nm_utils_inet6_ntop (const struct in6_addr *in6addr, char *dst)
 gboolean
 nm_utils_ipaddr_valid (int family, const char *ip)
 {
-	guint8 buf[sizeof (struct in6_addr)];
-
 	g_return_val_if_fail (family == AF_INET || family == AF_INET6 || family == AF_UNSPEC, FALSE);
 
-	if (!ip)
-		return FALSE;
-
-	if (family == AF_UNSPEC)
-		family = strchr (ip, ':') ? AF_INET6 : AF_INET;
-
-	return inet_pton (family, ip, buf) == 1;
+	return nm_utils_ipaddr_is_valid (family, ip);
 }
 
 /**
@@ -5835,7 +5798,7 @@ nm_utils_get_timestamp_msec (void)
 {
 	gint64 ts;
 
-	ts = nm_utils_clock_gettime_ms (CLOCK_BOOTTIME);
+	ts = nm_utils_clock_gettime_msec (CLOCK_BOOTTIME);
 	if (ts >= 0)
 		return ts;
 
@@ -5844,7 +5807,7 @@ nm_utils_get_timestamp_msec (void)
 		 * criminally old kernel, prior to 2.6.39 (released on 18 May, 2011).
 		 * That happens during buildcheck on old builders, we don't expect to
 		 * be actually runs on kernels that old. */
-		ts = nm_utils_clock_gettime_ms (CLOCK_MONOTONIC);
+		ts = nm_utils_clock_gettime_msec (CLOCK_MONOTONIC);
 		if (ts >= 0)
 			return ts;
 	}