summary refs log tree commit diff
path: root/src/NetworkManagerUtils.c
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2019-03-26 23:25:23 +0100
committerMichael Biebl <biebl@debian.org>2019-03-26 23:25:23 +0100
commit9a6dcbf895f9da01768e64b73cec88c16157d91e (patch)
treea359958930d731e9f1b59344642e10754419fe84 /src/NetworkManagerUtils.c
parent964ae8cc391520440cf5aa13e2b9cc34850ea6c2 (diff)
New upstream version 1.16.0 upstream/1.16.0
Diffstat (limited to 'src/NetworkManagerUtils.c')
-rw-r--r--src/NetworkManagerUtils.c226
1 files changed, 139 insertions, 87 deletions
diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c
index e3766809..71bfbf7c 100644
--- a/src/NetworkManagerUtils.c
+++ b/src/NetworkManagerUtils.c
@@ -34,6 +34,7 @@
 
 #include "platform/nm-platform.h"
 #include "nm-auth-utils.h"
+#include "systemd/nm-sd-utils-shared.h"
 
 /*****************************************************************************/
 
@@ -48,11 +49,11 @@ nm_utils_get_shared_wifi_permission (NMConnection *connection)
 {
 	NMSettingWireless *s_wifi;
 	NMSettingWirelessSecurity *s_wsec;
-	const char *method = NULL;
+	const char *method;
 
-	method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG);
-	if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) != 0)
-		return NULL;  /* Not shared */
+	method = nm_utils_get_ip_config_method (connection, AF_INET);
+	if (!nm_streq (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED))
+		return NULL;
 
 	s_wifi = nm_connection_get_setting_wireless (connection);
 	if (s_wifi) {
@@ -160,38 +161,39 @@ next:
 
 const char *
 nm_utils_get_ip_config_method (NMConnection *connection,
-                               GType         ip_setting_type)
+                               int addr_family)
 {
 	NMSettingConnection *s_con;
-	NMSettingIPConfig *s_ip4, *s_ip6;
+	NMSettingIPConfig *s_ip;
 	const char *method;
 
 	s_con = nm_connection_get_setting_connection (connection);
 
-	if (ip_setting_type == NM_TYPE_SETTING_IP4_CONFIG) {
+	if (addr_family == AF_INET) {
 		g_return_val_if_fail (s_con != NULL, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
 
-		s_ip4 = nm_connection_get_setting_ip4_config (connection);
-		if (!s_ip4)
+		s_ip = nm_connection_get_setting_ip4_config (connection);
+		if (!s_ip)
 			return NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
-		method = nm_setting_ip_config_get_method (s_ip4);
-		g_return_val_if_fail (method != NULL, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
 
+		method = nm_setting_ip_config_get_method (s_ip);
+		g_return_val_if_fail (method != NULL, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
 		return method;
+	}
 
-	} else if (ip_setting_type == NM_TYPE_SETTING_IP6_CONFIG) {
+	if (addr_family == AF_INET6) {
 		g_return_val_if_fail (s_con != NULL, NM_SETTING_IP6_CONFIG_METHOD_AUTO);
 
-		s_ip6 = nm_connection_get_setting_ip6_config (connection);
-		if (!s_ip6)
+		s_ip = nm_connection_get_setting_ip6_config (connection);
+		if (!s_ip)
 			return NM_SETTING_IP6_CONFIG_METHOD_IGNORE;
-		method = nm_setting_ip_config_get_method (s_ip6);
-		g_return_val_if_fail (method != NULL, NM_SETTING_IP6_CONFIG_METHOD_AUTO);
 
+		method = nm_setting_ip_config_get_method (s_ip);
+		g_return_val_if_fail (method != NULL, NM_SETTING_IP6_CONFIG_METHOD_AUTO);
 		return method;
+	}
 
-	} else
-		g_assert_not_reached ();
+	g_return_val_if_reached ("" /* bogus */);
 }
 
 gboolean
@@ -210,10 +212,7 @@ nm_utils_connection_has_default_route (NMConnection *connection,
 	if (!connection)
 		goto out;
 
-	if (addr_family == AF_INET)
-		s_ip = nm_connection_get_setting_ip4_config (connection);
-	else
-		s_ip = nm_connection_get_setting_ip6_config (connection);
+	s_ip = nm_connection_get_setting_ip_config (connection, addr_family);
 	if (!s_ip)
 		goto out;
 	if (nm_setting_ip_config_get_never_default (s_ip)) {
@@ -221,16 +220,13 @@ nm_utils_connection_has_default_route (NMConnection *connection,
 		goto out;
 	}
 
+	method = nm_utils_get_ip_config_method (connection, addr_family);
 	if (addr_family == AF_INET) {
-		method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG);
-		if (NM_IN_STRSET (method, NULL,
-		                          NM_SETTING_IP4_CONFIG_METHOD_DISABLED,
+		if (NM_IN_STRSET (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED,
 		                          NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL))
 			goto out;
 	} else {
-		method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG);
-		if (NM_IN_STRSET (method, NULL,
-		                          NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
+		if (NM_IN_STRSET (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
 		                          NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL))
 			goto out;
 	}
@@ -341,29 +337,28 @@ check_ip6_method (NMConnection *orig,
 	if (!props)
 		return TRUE;
 
-	/* If the generated connection is 'link-local' and the candidate is both 'auto'
-	 * and may-fail=TRUE, then the candidate is OK to use.  may-fail is included
-	 * in the decision because if the candidate is 'auto' but may-fail=FALSE, then
-	 * the connection could not possibly have been previously activated on the
-	 * device if the device has no non-link-local IPv6 address.
-	 */
-	orig_ip6_method = nm_utils_get_ip_config_method (orig, NM_TYPE_SETTING_IP6_CONFIG);
-	candidate_ip6_method = nm_utils_get_ip_config_method (candidate, NM_TYPE_SETTING_IP6_CONFIG);
+	orig_ip6_method = nm_utils_get_ip_config_method (orig, AF_INET6);
+	candidate_ip6_method = nm_utils_get_ip_config_method (candidate, AF_INET6);
 	candidate_ip6 = nm_connection_get_setting_ip6_config (candidate);
 
-	if (   strcmp (orig_ip6_method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0
-	    && strcmp (candidate_ip6_method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0
-	    && (!candidate_ip6 || nm_setting_ip_config_get_may_fail (candidate_ip6))) {
+	if (   nm_streq (orig_ip6_method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)
+	    && nm_streq (candidate_ip6_method, NM_SETTING_IP6_CONFIG_METHOD_AUTO)
+	    && (   !candidate_ip6
+	        || nm_setting_ip_config_get_may_fail (candidate_ip6))) {
+		/* If the generated connection is 'link-local' and the candidate is both 'auto'
+		 * and may-fail=TRUE, then the candidate is OK to use.  may-fail is included
+		 * in the decision because if the candidate is 'auto' but may-fail=FALSE, then
+		 * the connection could not possibly have been previously activated on the
+		 * device if the device has no non-link-local IPv6 address.
+		 */
 		allow = TRUE;
-	}
-
-	/* If the generated connection method is 'link-local' or 'auto' and the candidate
-	 * method is 'ignore' we can take the connection, because NM didn't simply take care
-	 * of IPv6.
-	 */
-	if (  (   strcmp (orig_ip6_method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0
-	       || strcmp (orig_ip6_method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0)
-	    && strcmp (candidate_ip6_method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) == 0) {
+	} else if (   NM_IN_STRSET (orig_ip6_method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL,
+	                                             NM_SETTING_IP6_CONFIG_METHOD_AUTO)
+	           && nm_streq0 (candidate_ip6_method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) {
+		/* If the generated connection method is 'link-local' or 'auto' and the candidate
+		 * method is 'ignore' we can take the connection, because NM didn't simply take care
+		 * of IPv6.
+		 */
 		allow = TRUE;
 	}
 
@@ -372,46 +367,43 @@ check_ip6_method (NMConnection *orig,
 		                  NM_SETTING_IP6_CONFIG_SETTING_NAME,
 		                  NM_SETTING_IP_CONFIG_METHOD);
 	}
+
 	return allow;
 }
 
 static int
 route_compare (NMIPRoute *route1, NMIPRoute *route2, gint64 default_metric)
 {
-	gint64 r, metric1, metric2;
+	NMIPAddr a1;
+	NMIPAddr a2;
+	guint64 m1;
+	guint64 m2;
 	int family;
 	guint plen;
-	NMIPAddr a1 = { 0 }, a2 = { 0 };
 
 	family = nm_ip_route_get_family (route1);
-	r = family - nm_ip_route_get_family (route2);
-	if (r)
-		return r > 0 ? 1 : -1;
+	NM_CMP_DIRECT (family, nm_ip_route_get_family (route2));
+
+	nm_assert_addr_family (family);
 
 	plen = nm_ip_route_get_prefix (route1);
-	r = plen - nm_ip_route_get_prefix (route2);
-	if (r)
-		return r > 0 ? 1 : -1;
-
-	metric1 = nm_ip_route_get_metric (route1) == -1 ? default_metric : nm_ip_route_get_metric (route1);
-	metric2 = nm_ip_route_get_metric (route2) == -1 ? default_metric : nm_ip_route_get_metric (route2);
-
-	r = metric1 - metric2;
-	if (r)
-		return r > 0 ? 1 : -1;
-
-	r = g_strcmp0 (nm_ip_route_get_next_hop (route1), nm_ip_route_get_next_hop (route2));
-	if (r)
-		return r;
-
-	/* NMIPRoute validates family and dest. inet_pton() is not expected to fail. */
-	inet_pton (family, nm_ip_route_get_dest (route1), &a1);
-	inet_pton (family, nm_ip_route_get_dest (route2), &a2);
-	nm_utils_ipx_address_clear_host_address (family, &a1, &a1, plen);
-	nm_utils_ipx_address_clear_host_address (family, &a2, &a2, plen);
-	r = memcmp (&a1, &a2, sizeof (a1));
-	if (r)
-		return r;
+	NM_CMP_DIRECT (plen, nm_ip_route_get_prefix (route2));
+
+	m1 = nm_ip_route_get_metric (route1);
+	m2 = nm_ip_route_get_metric (route2);
+	NM_CMP_DIRECT (m1 == -1 ? default_metric : m1,
+	               m2 == -1 ? default_metric : m2);
+
+	NM_CMP_DIRECT_STRCMP0 (nm_ip_route_get_next_hop (route1),
+	                       nm_ip_route_get_next_hop (route2));
+
+	if (!inet_pton (family, nm_ip_route_get_dest (route1), &a1))
+		nm_assert_not_reached ();
+	if (!inet_pton (family, nm_ip_route_get_dest (route2), &a2))
+		nm_assert_not_reached ();
+	nm_utils_ipx_address_clear_host_address (family, &a1, NULL, plen);
+	nm_utils_ipx_address_clear_host_address (family, &a2, NULL, plen);
+	NM_CMP_DIRECT_MEMCMP (&a1, &a2, nm_utils_addr_family_to_size (family));
 
 	return 0;
 }
@@ -519,19 +511,20 @@ check_ip4_method (NMConnection *orig,
 	if (!props)
 		return TRUE;
 
-	/* If the generated connection is 'disabled' (device had no IP addresses)
-	 * but it has no carrier, that most likely means that IP addressing could
-	 * not complete and thus no IP addresses were assigned.  In that case, allow
-	 * matching to the "auto" method.
-	 */
-	orig_ip4_method = nm_utils_get_ip_config_method (orig, NM_TYPE_SETTING_IP4_CONFIG);
-	candidate_ip4_method = nm_utils_get_ip_config_method (candidate, NM_TYPE_SETTING_IP4_CONFIG);
+	orig_ip4_method = nm_utils_get_ip_config_method (orig, AF_INET);
+	candidate_ip4_method = nm_utils_get_ip_config_method (candidate, AF_INET);
 	candidate_ip4 = nm_connection_get_setting_ip4_config (candidate);
 
-	if (   strcmp (orig_ip4_method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) == 0
-	    && strcmp (candidate_ip4_method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0
-	    && (!candidate_ip4 || nm_setting_ip_config_get_may_fail (candidate_ip4))
-	    && (device_has_carrier == FALSE)) {
+	if (   nm_streq (orig_ip4_method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)
+	    && nm_streq (candidate_ip4_method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)
+	    && (   !candidate_ip4
+	        || nm_setting_ip_config_get_may_fail (candidate_ip4))
+	    && !device_has_carrier) {
+		/* If the generated connection is 'disabled' (device had no IP addresses)
+		 * but it has no carrier, that most likely means that IP addressing could
+		 * not complete and thus no IP addresses were assigned.  In that case, allow
+		 * matching to the "auto" method.
+		 */
 		remove_from_hash (settings, props,
 		                  NM_SETTING_IP4_CONFIG_SETTING_NAME,
 		                  NM_SETTING_IP_CONFIG_METHOD);
@@ -1000,3 +993,62 @@ nm_shutdown_wait_obj_unregister (NMShutdownWaitObjHandle *handle)
 	g_object_weak_unref (handle->watched_obj, _shutdown_waitobj_cb, handle);
 	_shutdown_waitobj_unregister (handle);
 }
+
+/*****************************************************************************/
+
+/**
+ * nm_utils_file_is_in_path:
+ * @abs_filename: the absolute filename to test
+ * @abs_path: the absolute path, to check whether filename is in.
+ *
+ * This tests, whether @abs_filename is a file which lies inside @abs_path.
+ * Basically, this checks whether @abs_filename is the same as @abs_path +
+ * basename(@abs_filename). It allows simple normalizations, like coalescing
+ * multiple "//".
+ *
+ * However, beware that this function is purely filename based. That means,
+ * it will reject files that reference the same file (i.e. inode) via
+ * symlinks or bind mounts. Maybe one would like to check for file (inode)
+ * identity, but that is not really possible based on the file name alone.
+ *
+ * This means, that nm_utils_file_is_in_path("/var/run/some-file", "/var/run")
+ * will succeed, but nm_utils_file_is_in_path("/run/some-file", "/var/run")
+ * will not (although, it's well known that they reference the same path).
+ *
+ * Also, note that @abs_filename must not have trailing slashes itself.
+ * So, this will reject nm_utils_file_is_in_path("/usr/lib/", "/usr") as
+ * invalid, because the function searches for file names (and "lib/" is
+ * clearly a directory).
+ *
+ * Returns: if @abs_filename is a file inside @abs_path, returns the
+ *   trailing part of @abs_filename which is the filename. Otherwise
+ *   %NULL.
+ */
+const char *
+nm_utils_file_is_in_path (const char *abs_filename,
+                          const char *abs_path)
+{
+	const char *path;
+
+	g_return_val_if_fail (abs_filename && abs_filename[0] == '/', NULL);
+	g_return_val_if_fail (abs_path && abs_path[0] == '/', NULL);
+
+	path = nm_sd_utils_path_startswith (abs_filename, abs_path);
+	if (!path)
+		return NULL;
+
+	nm_assert (path[0] != '/');
+	nm_assert (path > abs_filename);
+	nm_assert (path <= &abs_filename[strlen (abs_filename)]);
+
+	/* we require a non-empty remainder with no slashes. That is, only a filename.
+	 *
+	 * Note this will reject "/var/run/" as not being in "/var",
+	 * while "/var/run" would pass. The function searches for files
+	 * only, so a trailing slash (indicating a directory) is not allowed).
+	 * This is despite that the function cannot determine whether "/var/run"
+	 * is itself a file or a directory. "*/
+	return path[0] && !strchr (path, '/')
+	       ? path
+	       : NULL;
+}