summary refs log tree commit diff
path: root/src/nm-config.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nm-config.c')
-rw-r--r--src/nm-config.c146
1 files changed, 85 insertions, 61 deletions
diff --git a/src/nm-config.c b/src/nm-config.c
index 3e82bdec..d1279814 100644
--- a/src/nm-config.c
+++ b/src/nm-config.c
@@ -1,4 +1,3 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
 /* NetworkManager -- Network link manager
  *
  * This program is free software; you can redistribute it and/or modify
@@ -67,7 +66,7 @@ struct NMConfigCmdLineOptions {
 	 *
 	 * It is true, if NM is started the first time -- contrary to a restart
 	 * during the same boot up. That is determined by the content of the
-	 * /var/run/NetworManager state directory. */
+	 * /run/NetworManager state directory. */
 	bool first_start;
 };
 
@@ -100,8 +99,6 @@ typedef struct {
 	char *no_auto_default_file;
 	char *intern_config_file;
 
-	gboolean monitor_connection_files;
-
 	char *log_level;
 	char *log_domains;
 
@@ -313,14 +310,6 @@ nm_config_get_data_orig (NMConfig *config)
 	return NM_CONFIG_GET_PRIVATE (config)->config_data_orig;
 }
 
-gboolean
-nm_config_get_monitor_connection_files (NMConfig *config)
-{
-	g_return_val_if_fail (config != NULL, FALSE);
-
-	return NM_CONFIG_GET_PRIVATE (config)->monitor_connection_files;
-}
-
 const char *
 nm_config_get_log_level (NMConfig *config)
 {
@@ -360,47 +349,44 @@ nm_config_get_first_start (NMConfig *config)
 static char **
 no_auto_default_from_file (const char *no_auto_default_file)
 {
-	GPtrArray *no_auto_default_new;
-	char **list;
-	guint i;
-	char *data;
-
-	no_auto_default_new = g_ptr_array_new ();
+	gs_free char *data = NULL;
+	const char **list = NULL;
+	gsize i;
 
 	if (   no_auto_default_file
-	    && g_file_get_contents (no_auto_default_file, &data, NULL, NULL)) {
-		list = g_strsplit (data, "\n", -1);
-		for (i = 0; list[i]; i++) {
-			if (   *list[i]
-			    && nm_utils_hwaddr_valid (list[i], -1)
-			    && nm_utils_strv_find_first (list, i, list[i]) < 0)
-				g_ptr_array_add (no_auto_default_new, list[i]);
-			else
-				g_free (list[i]);
-		}
-		g_free (list);
-		g_free (data);
+	    && g_file_get_contents (no_auto_default_file, &data, NULL, NULL))
+		list = nm_utils_strsplit_set (data, "\n");
+
+	if (list) {
+		for (i = 0; list[i]; i++)
+			list[i] = nm_utils_str_utf8safe_unescape_cp (list[i]);
 	}
 
-	g_ptr_array_add (no_auto_default_new, NULL);
-	return (char **) g_ptr_array_free (no_auto_default_new, FALSE);
+	/* The returned buffer here is not at all compact. That means, it has additional
+	 * memory allocations and is larger than needed. That means, you should not keep
+	 * this result around, only process it further and free it. */
+	return (char **) list;
 }
 
 static gboolean
 no_auto_default_to_file (const char *no_auto_default_file, const char *const*no_auto_default, GError **error)
 {
-	GString *data;
-	gboolean success;
-	guint i;
+	nm_auto_free_gstring GString *data = NULL;
+	gsize i;
 
 	data = g_string_new ("");
 	for (i = 0; no_auto_default && no_auto_default[i]; i++) {
-		g_string_append (data, no_auto_default[i]);
+		gs_free char *s_to_free = NULL;
+		const char *s = no_auto_default[i];
+
+		s = nm_utils_str_utf8safe_escape (s,
+		                                    NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL
+		                                  | NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII,
+		                                  &s_to_free);
+		g_string_append (data, s);
 		g_string_append_c (data, '\n');
 	}
-	success = g_file_set_contents (no_auto_default_file, data->str, data->len, error);
-	g_string_free (data, TRUE);
-	return success;
+	return  g_file_set_contents (no_auto_default_file, data->str, data->len, error);
 }
 
 gboolean
@@ -424,44 +410,76 @@ nm_config_set_no_auto_default_for_device (NMConfig *self, NMDevice *device)
 	NMConfigPrivate *priv;
 	GError *error = NULL;
 	NMConfigData *new_data = NULL;
+	gs_free char *spec_to_free = NULL;
+	const char *ifname;
 	const char *hw_address;
+	const char *spec;
 	const char *const*no_auto_default_current;
-	GPtrArray *no_auto_default_new = NULL;
-	guint i;
+	gs_free const char **no_auto_default_new = NULL;
+	gboolean is_fake;
+	gsize len;
+	gssize idx;
 
 	g_return_if_fail (NM_IS_CONFIG (self));
 	g_return_if_fail (NM_IS_DEVICE (device));
 
 	priv = NM_CONFIG_GET_PRIVATE (self);
 
-	hw_address = nm_device_get_permanent_hw_address (device);
-	if (!hw_address)
+	hw_address = nm_device_get_permanent_hw_address_full (device, TRUE, &is_fake);
+
+	if (!hw_address) {
+		/* No MAC address, not even a fake one. We don't do anything for this device. */
 		return;
+	}
+
+	if (is_fake) {
+		/* A fake MAC address, no point in storing it to the file.
+		 * Also, nm_match_spec_device() would ignore fake MAC addresses.
+		 *
+		 * Instead, try the interface-name...  */
+		ifname = nm_device_get_ip_iface (device);
+		if (!nm_utils_is_valid_iface_name (ifname, NULL))
+			return;
+
+		spec_to_free = g_strdup_printf (NM_MATCH_SPEC_INTERFACE_NAME_TAG"=%s", ifname);
+		spec = spec_to_free;
+	} else
+		spec = hw_address;
 
 	no_auto_default_current = nm_config_data_get_no_auto_default (priv->config_data);
 
-	if (nm_utils_strv_find_first ((char **) no_auto_default_current, -1, hw_address) >= 0) {
-		/* @hw_address is already blocked. We don't have to update our in-memory representation.
+	len = NM_PTRARRAY_LEN (no_auto_default_current);
+
+	idx = nm_utils_ptrarray_find_binary_search ((gconstpointer *) no_auto_default_current,
+	                                            len,
+	                                            spec,
+	                                            nm_strcmp_with_data,
+	                                            NULL,
+	                                            NULL,
+	                                            NULL);
+	if (idx >= 0) {
+		/* @spec is already blocked. We don't have to update our in-memory representation.
 		 * Maybe we should write to no_auto_default_file anew, but let's save that too. */
 		return;
 	}
 
-	no_auto_default_new = g_ptr_array_new ();
-	for (i = 0; no_auto_default_current && no_auto_default_current[i]; i++)
-		g_ptr_array_add (no_auto_default_new, (char *) no_auto_default_current[i]);
-	g_ptr_array_add (no_auto_default_new, (char *) hw_address);
-	g_ptr_array_add (no_auto_default_new, NULL);
+	idx = ~idx;
+
+	no_auto_default_new = g_new (const char *, len + 2);
+	if (idx > 0)
+		memcpy (no_auto_default_new, no_auto_default_current, sizeof (const char *) * idx);
+	no_auto_default_new[idx] = spec;
+	if (idx < len)
+		memcpy (&no_auto_default_new[idx + 1], &no_auto_default_current[idx], sizeof (const char *) * (len - idx));
+	no_auto_default_new[len + 1] = NULL;
 
-	if (!no_auto_default_to_file (priv->no_auto_default_file, (const char *const*) no_auto_default_new->pdata, &error)) {
+	if (!no_auto_default_to_file (priv->no_auto_default_file, no_auto_default_new, &error)) {
 		_LOGW ("Could not update no-auto-default.state file: %s",
 		       error->message);
 		g_error_free (error);
 	}
 
-	new_data = nm_config_data_new_update_no_auto_default (priv->config_data, (const char *const*) no_auto_default_new->pdata);
-
-	/* unref no_auto_default_set here. Note that _set_config_data() probably invalidates the content of the array. */
-	g_ptr_array_unref (no_auto_default_new);
+	new_data = nm_config_data_new_update_no_auto_default (priv->config_data, no_auto_default_new);
 
 	_set_config_data (self, new_data, NM_CONFIG_CHANGE_CAUSE_NO_AUTO_DEFAULT);
 }
@@ -2187,6 +2205,7 @@ _nm_config_state_set (NMConfig *self,
 #define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_ROUTE_METRIC_DEFAULT_ASPIRED   "route-metric-default-aspired"
 #define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_ROUTE_METRIC_DEFAULT_EFFECTIVE "route-metric-default-effective"
 #define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_ROOT_PATH           "root-path"
+#define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_NEXT_SERVER         "next-server"
 
 NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_device_state_managed_type_to_str, NMConfigDeviceStateManagedType,
 	NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT ("unknown"),
@@ -2385,6 +2404,7 @@ nm_config_device_state_write (int ifindex,
                               int nm_owned,
                               guint32 route_metric_default_aspired,
                               guint32 route_metric_default_effective,
+                              const char *next_server,
                               const char *root_path)
 {
 	char path[NM_STRLEN (NM_CONFIG_DEVICE_STATE_DIR) + 60];
@@ -2439,6 +2459,12 @@ nm_config_device_state_write (int ifindex,
 			                      route_metric_default_aspired);
 		}
 	}
+	if (next_server) {
+		g_key_file_set_string (kf,
+		                       DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE,
+		                       DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_NEXT_SERVER,
+		                       next_server);
+	}
 	if (root_path) {
 		g_key_file_set_string (kf,
 		                       DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE,
@@ -2451,13 +2477,14 @@ nm_config_device_state_write (int ifindex,
 		g_error_free (local);
 		return FALSE;
 	}
-	_LOGT ("device-state: write #%d (%s); managed=%s%s%s%s%s%s%s, route-metric-default=%"G_GUINT32_FORMAT"-%"G_GUINT32_FORMAT"%s%s%s",
+	_LOGT ("device-state: write #%d (%s); managed=%s%s%s%s%s%s%s, route-metric-default=%"G_GUINT32_FORMAT"-%"G_GUINT32_FORMAT"%s%s%s%s%s%s",
 	       ifindex, path,
 	       _device_state_managed_type_to_str (managed),
 	       NM_PRINT_FMT_QUOTED (connection_uuid, ", connection-uuid=", connection_uuid, "", ""),
 	       NM_PRINT_FMT_QUOTED (perm_hw_addr_fake, ", perm-hw-addr-fake=", perm_hw_addr_fake, "", ""),
 	       route_metric_default_aspired,
 	       route_metric_default_effective,
+	       NM_PRINT_FMT_QUOTED (next_server, ", next-server=", next_server, "", ""),
 	       NM_PRINT_FMT_QUOTED (root_path, ", root-path=", root_path, "", ""));
 	return TRUE;
 }
@@ -2709,7 +2736,8 @@ nm_config_setup (const NMConfigCmdLineOptions *cli, char **atomic_section_prefix
 
 		/* usually, you would not see this logging line because when creating the
 		 * NMConfig instance, the logging is not yet set up to print debug message. */
-		nm_log_dbg (LOGD_CORE, "setup %s singleton (%p)", "NMConfig", singleton_instance);
+		nm_log_dbg (LOGD_CORE, "setup %s singleton ("NM_HASH_OBFUSCATE_PTR_FMT")",
+		            "NMConfig", NM_HASH_OBFUSCATE_PTR (singleton_instance));
 	}
 	return singleton_instance;
 }
@@ -2803,10 +2831,6 @@ init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
 	else
 		priv->no_auto_default_file = g_strdup (DEFAULT_NO_AUTO_DEFAULT_FILE);
 
-	priv->monitor_connection_files = nm_config_keyfile_get_boolean (keyfile,
-	                                                                NM_CONFIG_KEYFILE_GROUP_MAIN,
-	                                                                NM_CONFIG_KEYFILE_KEY_MAIN_MONITOR_CONNECTION_FILES,
-	                                                                FALSE);
 	priv->log_level = nm_strstrip (g_key_file_get_string (keyfile,
 	                                                      NM_CONFIG_KEYFILE_GROUP_LOGGING,
 	                                                      NM_CONFIG_KEYFILE_KEY_LOGGING_LEVEL,