mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-27 12:50:09 +01:00
config: fix evaluation of no-auto-default setting
We used to merge the spec list for no-auto-default from keyfile with the
content of the state file. Since the addition of the "except:" spec this
is wrong.
For example, if the user configured:
no-auto-default=except:mac:11:11:11:11:11
and statefile contained "11:11:11:11:11" and "22:22:22:22:22", we would
wrongly not match "11:11:11:11:11". The two lists must be kept separate,
so that devices that are blocked by internal decision always match.
This separation is also clearer. Now the spec list is devided into a
part that comes from user configuration, and a part that comes from
internal decision.
(cherry picked from commit 3e4458659b)
This commit is contained in:
parent
a325abc425
commit
4adecd466e
3 changed files with 97 additions and 82 deletions
|
|
@ -60,6 +60,7 @@ typedef struct {
|
|||
struct {
|
||||
char **arr;
|
||||
GSList *specs;
|
||||
GSList *specs_config;
|
||||
} no_auto_default;
|
||||
|
||||
GSList *ignore_carrier;
|
||||
|
|
@ -144,12 +145,17 @@ nm_config_data_get_no_auto_default (const NMConfigData *self)
|
|||
return (const char *const*) NM_CONFIG_DATA_GET_PRIVATE (self)->no_auto_default.arr;
|
||||
}
|
||||
|
||||
const GSList *
|
||||
nm_config_data_get_no_auto_default_list (const NMConfigData *self)
|
||||
gboolean
|
||||
nm_config_data_get_no_auto_default_for_device (const NMConfigData *self, NMDevice *device)
|
||||
{
|
||||
g_return_val_if_fail (self, NULL);
|
||||
NMConfigDataPrivate *priv;
|
||||
|
||||
return NM_CONFIG_DATA_GET_PRIVATE (self)->no_auto_default.specs;
|
||||
g_return_val_if_fail (NM_IS_CONFIG_DATA (self), FALSE);
|
||||
g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
|
||||
|
||||
priv = NM_CONFIG_DATA_GET_PRIVATE (self);
|
||||
return nm_device_spec_match_list (device, priv->no_auto_default.specs)
|
||||
|| nm_device_spec_match_list (device, priv->no_auto_default.specs_config);
|
||||
}
|
||||
|
||||
const char *
|
||||
|
|
@ -306,12 +312,21 @@ _keyfile_a_contains_all_in_b (GKeyFile *kf_a, GKeyFile *kf_b)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_slist_str_equals (GSList *a, GSList *b)
|
||||
{
|
||||
while (a && b && g_strcmp0 (a->data, b->data) == 0) {
|
||||
a = a->next;
|
||||
b = b->next;
|
||||
}
|
||||
return !a && !b;
|
||||
}
|
||||
|
||||
NMConfigChangeFlags
|
||||
nm_config_data_diff (NMConfigData *old_data, NMConfigData *new_data)
|
||||
{
|
||||
NMConfigChangeFlags changes = NM_CONFIG_CHANGE_NONE;
|
||||
NMConfigDataPrivate *priv_old, *priv_new;
|
||||
GSList *spec_old, *spec_new;
|
||||
|
||||
g_return_val_if_fail (NM_IS_CONFIG_DATA (old_data), NM_CONFIG_CHANGE_NONE);
|
||||
g_return_val_if_fail (NM_IS_CONFIG_DATA (new_data), NM_CONFIG_CHANGE_NONE);
|
||||
|
|
@ -332,13 +347,8 @@ nm_config_data_diff (NMConfigData *old_data, NMConfigData *new_data)
|
|||
|| g_strcmp0 (nm_config_data_get_connectivity_response (old_data), nm_config_data_get_connectivity_response (new_data)))
|
||||
changes |= NM_CONFIG_CHANGE_CONNECTIVITY;
|
||||
|
||||
spec_old = priv_old->no_auto_default.specs;
|
||||
spec_new = priv_new->no_auto_default.specs;
|
||||
while (spec_old && spec_new && strcmp (spec_old->data, spec_new->data) == 0) {
|
||||
spec_old = spec_old->next;
|
||||
spec_new = spec_new->next;
|
||||
}
|
||||
if (spec_old || spec_new)
|
||||
if ( !_slist_str_equals (priv_old->no_auto_default.specs, priv_new->no_auto_default.specs)
|
||||
|| !_slist_str_equals (priv_old->no_auto_default.specs_config, priv_new->no_auto_default.specs_config))
|
||||
changes |= NM_CONFIG_CHANGE_NO_AUTO_DEFAULT;
|
||||
|
||||
if (g_strcmp0 (nm_config_data_get_dns_mode (old_data), nm_config_data_get_dns_mode (new_data)))
|
||||
|
|
@ -364,9 +374,6 @@ get_property (GObject *object,
|
|||
case PROP_CONFIG_DESCRIPTION:
|
||||
g_value_set_string (value, nm_config_data_get_config_description (self));
|
||||
break;
|
||||
case PROP_NO_AUTO_DEFAULT:
|
||||
g_value_take_boxed (value, g_strdupv ((char **) nm_config_data_get_no_auto_default (self)));
|
||||
break;
|
||||
case PROP_CONNECTIVITY_URI:
|
||||
g_value_set_string (value, nm_config_data_get_connectivity_uri (self));
|
||||
break;
|
||||
|
|
@ -390,7 +397,6 @@ set_property (GObject *object,
|
|||
{
|
||||
NMConfigData *self = NM_CONFIG_DATA (object);
|
||||
NMConfigDataPrivate *priv = NM_CONFIG_DATA_GET_PRIVATE (self);
|
||||
guint i;
|
||||
|
||||
/* This type is immutable. All properties are construct only. */
|
||||
switch (prop_id) {
|
||||
|
|
@ -406,12 +412,24 @@ set_property (GObject *object,
|
|||
priv->keyfile = nm_config_create_keyfile ();
|
||||
break;
|
||||
case PROP_NO_AUTO_DEFAULT:
|
||||
priv->no_auto_default.arr = g_strdupv (g_value_get_boxed (value));
|
||||
if (!priv->no_auto_default.arr)
|
||||
priv->no_auto_default.arr = g_new0 (char *, 1);
|
||||
for (i = 0; priv->no_auto_default.arr[i]; i++)
|
||||
priv->no_auto_default.specs = g_slist_prepend (priv->no_auto_default.specs, priv->no_auto_default.arr[i]);
|
||||
priv->no_auto_default.specs = g_slist_reverse (priv->no_auto_default.specs);
|
||||
{
|
||||
char **value_arr = g_value_get_boxed (value);
|
||||
guint i, j = 0;
|
||||
|
||||
priv->no_auto_default.arr = g_new (char *, g_strv_length (value_arr) + 1);
|
||||
priv->no_auto_default.specs = NULL;
|
||||
|
||||
for (i = 0; value_arr && value_arr[i]; i++) {
|
||||
if ( *value_arr[i]
|
||||
&& nm_utils_hwaddr_valid (value_arr[i], -1)
|
||||
&& _nm_utils_strv_find_first (value_arr, i, value_arr[i]) < 0) {
|
||||
priv->no_auto_default.arr[j++] = g_strdup (value_arr[i]);
|
||||
priv->no_auto_default.specs = g_slist_prepend (priv->no_auto_default.specs, g_strdup_printf ("mac:%s", value_arr[i]));
|
||||
}
|
||||
}
|
||||
priv->no_auto_default.arr[j++] = NULL;
|
||||
priv->no_auto_default.specs = g_slist_reverse (priv->no_auto_default.specs);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
|
|
@ -436,7 +454,8 @@ finalize (GObject *gobject)
|
|||
g_free (priv->connectivity.uri);
|
||||
g_free (priv->connectivity.response);
|
||||
|
||||
g_slist_free (priv->no_auto_default.specs);
|
||||
g_slist_free_full (priv->no_auto_default.specs, g_free);
|
||||
g_slist_free_full (priv->no_auto_default.specs_config, g_free);
|
||||
g_strfreev (priv->no_auto_default.arr);
|
||||
|
||||
g_free (priv->dns_mode);
|
||||
|
|
@ -487,6 +506,8 @@ constructed (GObject *object)
|
|||
priv->ignore_carrier = nm_config_get_device_match_spec (priv->keyfile, "main", "ignore-carrier");
|
||||
priv->assume_ipv6ll_only = nm_config_get_device_match_spec (priv->keyfile, "main", "assume-ipv6ll-only");
|
||||
|
||||
priv->no_auto_default.specs_config = nm_config_get_device_match_spec (priv->keyfile, "main", "no-auto-default");
|
||||
|
||||
G_OBJECT_CLASS (nm_config_data_parent_class)->constructed (object);
|
||||
}
|
||||
|
||||
|
|
@ -580,7 +601,7 @@ nm_config_data_class_init (NMConfigDataClass *config_class)
|
|||
(object_class, PROP_NO_AUTO_DEFAULT,
|
||||
g_param_spec_boxed (NM_CONFIG_DATA_NO_AUTO_DEFAULT, "", "",
|
||||
G_TYPE_STRV,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_WRITABLE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ const guint nm_config_data_get_connectivity_interval (const NMConfigData *config
|
|||
const char *nm_config_data_get_connectivity_response (const NMConfigData *config_data);
|
||||
|
||||
const char *const*nm_config_data_get_no_auto_default (const NMConfigData *config_data);
|
||||
const GSList * nm_config_data_get_no_auto_default_list (const NMConfigData *config_data);
|
||||
gboolean nm_config_data_get_no_auto_default_for_device (const NMConfigData *self, NMDevice *device);
|
||||
|
||||
const char *nm_config_data_get_dns_mode (const NMConfigData *self);
|
||||
|
||||
|
|
|
|||
108
src/nm-config.c
108
src/nm-config.c
|
|
@ -260,94 +260,99 @@ nm_config_get_configure_and_quit (NMConfig *config)
|
|||
/************************************************************************/
|
||||
|
||||
static char **
|
||||
no_auto_default_merge_from_file (const char *no_auto_default_file, const char *const* no_auto_default)
|
||||
no_auto_default_from_file (const char *no_auto_default_file)
|
||||
{
|
||||
GPtrArray *updated;
|
||||
GPtrArray *no_auto_default_new;
|
||||
char **list;
|
||||
int i, j;
|
||||
guint i;
|
||||
char *data;
|
||||
|
||||
updated = g_ptr_array_new ();
|
||||
if (no_auto_default) {
|
||||
for (i = 0; no_auto_default[i]; i++)
|
||||
g_ptr_array_add (updated, g_strdup (no_auto_default[i]));
|
||||
}
|
||||
no_auto_default_new = g_ptr_array_new ();
|
||||
|
||||
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])
|
||||
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]);
|
||||
else {
|
||||
for (j = 0; j < updated->len; j++) {
|
||||
if (!strcmp (list[i], updated->pdata[j]))
|
||||
break;
|
||||
}
|
||||
if (j == updated->len)
|
||||
g_ptr_array_add (updated, list[i]);
|
||||
else
|
||||
g_free (list[i]);
|
||||
}
|
||||
}
|
||||
g_free (list);
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
g_ptr_array_add (updated, NULL);
|
||||
return (char **) g_ptr_array_free (updated, FALSE);
|
||||
g_ptr_array_add (no_auto_default_new, NULL);
|
||||
return (char **) g_ptr_array_free (no_auto_default_new, FALSE);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
data = g_string_new ("");
|
||||
for (i = 0; no_auto_default && no_auto_default[i]; i++) {
|
||||
g_string_append (data, no_auto_default[i]);
|
||||
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;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_config_get_no_auto_default_for_device (NMConfig *self, NMDevice *device)
|
||||
{
|
||||
NMConfigData *config_data;
|
||||
|
||||
g_return_val_if_fail (NM_IS_CONFIG (self), FALSE);
|
||||
g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
|
||||
|
||||
config_data = NM_CONFIG_GET_PRIVATE (self)->config_data;
|
||||
return nm_device_spec_match_list (device, nm_config_data_get_no_auto_default_list (config_data));
|
||||
return nm_config_data_get_no_auto_default_for_device (NM_CONFIG_GET_PRIVATE (self)->config_data, device);
|
||||
}
|
||||
|
||||
void
|
||||
nm_config_set_no_auto_default_for_device (NMConfig *self, NMDevice *device)
|
||||
{
|
||||
NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (self);
|
||||
char *current;
|
||||
GString *updated;
|
||||
GError *error = NULL;
|
||||
char **no_auto_default;
|
||||
NMConfigData *new_data = NULL;
|
||||
const char *hw_address;
|
||||
const char *const*no_auto_default_current;
|
||||
GPtrArray *no_auto_default_new = NULL;
|
||||
guint i;
|
||||
|
||||
g_return_if_fail (NM_IS_CONFIG (self));
|
||||
g_return_if_fail (NM_IS_DEVICE (device));
|
||||
|
||||
if (nm_config_get_no_auto_default_for_device (self, device))
|
||||
return;
|
||||
hw_address = nm_device_get_hw_address (device);
|
||||
|
||||
updated = g_string_new (NULL);
|
||||
if (g_file_get_contents (priv->no_auto_default_file, ¤t, NULL, NULL)) {
|
||||
g_string_append (updated, current);
|
||||
g_free (current);
|
||||
if (updated->str[updated->len - 1] != '\n')
|
||||
g_string_append_c (updated, '\n');
|
||||
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.
|
||||
* Maybe we should write to no_auto_default_file anew, but let's save that too. */
|
||||
return;
|
||||
}
|
||||
|
||||
g_string_append (updated, nm_device_get_hw_address (device));
|
||||
g_string_append_c (updated, '\n');
|
||||
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);
|
||||
|
||||
if (!g_file_set_contents (priv->no_auto_default_file, updated->str, updated->len, &error)) {
|
||||
if (!no_auto_default_to_file (priv->no_auto_default_file, (const char *const*) no_auto_default_new->pdata, &error)) {
|
||||
nm_log_warn (LOGD_SETTINGS, "Could not update no-auto-default.state file: %s",
|
||||
error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
g_string_free (updated, TRUE);
|
||||
new_data = nm_config_data_new_update_no_auto_default (priv->config_data, (const char *const*) no_auto_default_new->pdata);
|
||||
|
||||
no_auto_default = no_auto_default_merge_from_file (priv->no_auto_default_file, nm_config_data_get_no_auto_default (priv->config_data));
|
||||
new_data = nm_config_data_new_update_no_auto_default (priv->config_data, (const char *const*) no_auto_default);
|
||||
g_strfreev (no_auto_default);
|
||||
/* 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);
|
||||
|
||||
_set_config_data (self, new_data, 0);
|
||||
}
|
||||
|
|
@ -949,9 +954,7 @@ init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
|
|||
GKeyFile *keyfile;
|
||||
char *config_main_file = NULL;
|
||||
char *config_description = NULL;
|
||||
char **no_auto_default;
|
||||
GSList *no_auto_default_orig_list;
|
||||
GPtrArray *no_auto_default_orig;
|
||||
gs_strfreev char **no_auto_default = NULL;
|
||||
|
||||
if (priv->config_dir) {
|
||||
/* Object is already initialized. */
|
||||
|
|
@ -998,19 +1001,10 @@ init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
|
|||
|
||||
priv->configure_and_quit = nm_config_keyfile_get_boolean (keyfile, "main", "configure-and-quit", FALSE);
|
||||
|
||||
no_auto_default_orig_list = nm_config_get_device_match_spec (keyfile, "main", "no-auto-default");
|
||||
|
||||
no_auto_default_orig = _nm_utils_copy_slist_to_array (no_auto_default_orig_list, NULL, NULL);
|
||||
g_ptr_array_add (no_auto_default_orig, NULL);
|
||||
no_auto_default = no_auto_default_merge_from_file (priv->no_auto_default_file, (const char *const *) no_auto_default_orig->pdata);
|
||||
g_ptr_array_unref (no_auto_default_orig);
|
||||
|
||||
g_slist_free_full (no_auto_default_orig_list, g_free);
|
||||
no_auto_default = no_auto_default_from_file (priv->no_auto_default_file);
|
||||
|
||||
priv->config_data_orig = nm_config_data_new (config_main_file, config_description, (const char *const*) no_auto_default, keyfile);
|
||||
|
||||
g_strfreev (no_auto_default);
|
||||
|
||||
priv->config_data = g_object_ref (priv->config_data_orig);
|
||||
|
||||
g_free (config_main_file);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue