mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-05-02 17:48:07 +02:00
all: merge branch 'th/various-for-wireguard-1'
https://github.com/NetworkManager/NetworkManager/pull/282
This commit is contained in:
commit
81da34eb1e
13 changed files with 544 additions and 296 deletions
|
|
@ -102,10 +102,16 @@ setting_changed_cb (NMSetting *setting,
|
|||
g_signal_emit (self, signals[CHANGED], 0);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_setting_release (gpointer key, gpointer value, gpointer user_data)
|
||||
static void
|
||||
_setting_release (NMConnection *connection, NMSetting *setting)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (user_data, setting_changed_cb, value);
|
||||
g_signal_handlers_disconnect_by_func (setting, setting_changed_cb, connection);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_setting_release_hfr (gpointer key, gpointer value, gpointer user_data)
|
||||
{
|
||||
_setting_release (user_data, value);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -123,9 +129,10 @@ _nm_connection_add_setting (NMConnection *connection, NMSetting *setting)
|
|||
setting_type = G_OBJECT_TYPE (setting);
|
||||
|
||||
if ((s_old = g_hash_table_lookup (priv->settings, _gtype_to_hash_key (setting_type))))
|
||||
g_signal_handlers_disconnect_by_func (s_old, setting_changed_cb, connection);
|
||||
_setting_release (connection, s_old);
|
||||
|
||||
g_hash_table_insert (priv->settings, _gtype_to_hash_key (setting_type), setting);
|
||||
/* Listen for property changes so we can emit the 'changed' signal */
|
||||
|
||||
g_signal_connect (setting, "notify", (GCallback) setting_changed_cb, connection);
|
||||
}
|
||||
|
||||
|
|
@ -409,7 +416,7 @@ _nm_connection_replace_settings (NMConnection *connection,
|
|||
}
|
||||
|
||||
if (g_hash_table_size (priv->settings) > 0) {
|
||||
g_hash_table_foreach_remove (priv->settings, _setting_release, connection);
|
||||
g_hash_table_foreach_remove (priv->settings, _setting_release_hfr, connection);
|
||||
changed = TRUE;
|
||||
} else
|
||||
changed = (settings != NULL);
|
||||
|
|
@ -494,7 +501,7 @@ nm_connection_replace_settings_from_connection (NMConnection *connection,
|
|||
new_priv = NM_CONNECTION_GET_PRIVATE (new_connection);
|
||||
|
||||
if ((changed = g_hash_table_size (priv->settings) > 0))
|
||||
g_hash_table_foreach_remove (priv->settings, _setting_release, connection);
|
||||
g_hash_table_foreach_remove (priv->settings, _setting_release_hfr, connection);
|
||||
|
||||
if (g_hash_table_size (new_priv->settings)) {
|
||||
g_hash_table_iter_init (&iter, new_priv->settings);
|
||||
|
|
@ -523,7 +530,7 @@ nm_connection_clear_settings (NMConnection *connection)
|
|||
priv = NM_CONNECTION_GET_PRIVATE (connection);
|
||||
|
||||
if (g_hash_table_size (priv->settings) > 0) {
|
||||
g_hash_table_foreach_remove (priv->settings, _setting_release, connection);
|
||||
g_hash_table_foreach_remove (priv->settings, _setting_release_hfr, connection);
|
||||
g_signal_emit (connection, signals[CHANGED], 0);
|
||||
}
|
||||
}
|
||||
|
|
@ -1832,26 +1839,14 @@ nm_connection_need_secrets (NMConnection *connection,
|
|||
void
|
||||
nm_connection_clear_secrets (NMConnection *connection)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
NMSetting *setting;
|
||||
|
||||
g_return_if_fail (NM_IS_CONNECTION (connection));
|
||||
|
||||
g_hash_table_iter_init (&iter, NM_CONNECTION_GET_PRIVATE (connection)->settings);
|
||||
while (g_hash_table_iter_next (&iter, NULL, (gpointer) &setting)) {
|
||||
g_signal_handlers_block_by_func (setting, (GCallback) setting_changed_cb, connection);
|
||||
_nm_setting_clear_secrets (setting);
|
||||
g_signal_handlers_unblock_by_func (setting, (GCallback) setting_changed_cb, connection);
|
||||
}
|
||||
|
||||
g_signal_emit (connection, signals[SECRETS_CLEARED], 0);
|
||||
return nm_connection_clear_secrets_with_flags (connection, NULL, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_connection_clear_secrets_with_flags:
|
||||
* @connection: the #NMConnection
|
||||
* @func: (scope call): function to be called to determine whether a
|
||||
* specific secret should be cleared or not
|
||||
* @func: (scope call): (allow-none): function to be called to determine whether a
|
||||
* specific secret should be cleared or not. If %NULL, all secrets are cleared.
|
||||
* @user_data: caller-supplied data passed to @func
|
||||
*
|
||||
* Clears and frees secrets determined by @func.
|
||||
|
|
@ -1869,7 +1864,7 @@ nm_connection_clear_secrets_with_flags (NMConnection *connection,
|
|||
g_hash_table_iter_init (&iter, NM_CONNECTION_GET_PRIVATE (connection)->settings);
|
||||
while (g_hash_table_iter_next (&iter, NULL, (gpointer) &setting)) {
|
||||
g_signal_handlers_block_by_func (setting, (GCallback) setting_changed_cb, connection);
|
||||
_nm_setting_clear_secrets_with_flags (setting, func, user_data);
|
||||
_nm_setting_clear_secrets (setting, func, user_data);
|
||||
g_signal_handlers_unblock_by_func (setting, (GCallback) setting_changed_cb, connection);
|
||||
}
|
||||
|
||||
|
|
@ -2973,7 +2968,7 @@ nm_connection_private_free (NMConnectionPrivate *priv)
|
|||
{
|
||||
NMConnection *self = priv->self;
|
||||
|
||||
g_hash_table_foreach_remove (priv->settings, _setting_release, self);
|
||||
g_hash_table_foreach_remove (priv->settings, _setting_release_hfr, self);
|
||||
g_hash_table_destroy (priv->settings);
|
||||
g_free (priv->path);
|
||||
|
||||
|
|
|
|||
|
|
@ -48,10 +48,9 @@ typedef enum NMSettingUpdateSecretResult {
|
|||
NMSettingUpdateSecretResult _nm_setting_update_secrets (NMSetting *setting,
|
||||
GVariant *secrets,
|
||||
GError **error);
|
||||
gboolean _nm_setting_clear_secrets (NMSetting *setting);
|
||||
gboolean _nm_setting_clear_secrets_with_flags (NMSetting *setting,
|
||||
NMSettingClearSecretsWithFlagsFn func,
|
||||
gpointer user_data);
|
||||
gboolean _nm_setting_clear_secrets (NMSetting *setting,
|
||||
NMSettingClearSecretsWithFlagsFn func,
|
||||
gpointer user_data);
|
||||
|
||||
/* The property of the #NMSetting should be considered during comparisons that
|
||||
* use the %NM_SETTING_COMPARE_FLAG_INFERRABLE flag. Properties that don't have
|
||||
|
|
|
|||
|
|
@ -813,29 +813,43 @@ compare_property (const NMSettInfoSetting *sett_info,
|
|||
}
|
||||
|
||||
static gboolean
|
||||
clear_secrets_with_flags (NMSetting *setting,
|
||||
GParamSpec *pspec,
|
||||
NMSettingClearSecretsWithFlagsFn func,
|
||||
gpointer user_data)
|
||||
clear_secrets (const NMSettInfoSetting *sett_info,
|
||||
guint property_idx,
|
||||
NMSetting *setting,
|
||||
NMSettingClearSecretsWithFlagsFn func,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (setting);
|
||||
GParamSpec *prop_spec = sett_info->property_infos[property_idx].param_spec;
|
||||
GHashTableIter iter;
|
||||
const char *secret;
|
||||
gboolean changed = TRUE;
|
||||
|
||||
if (priv->secrets == NULL)
|
||||
if ( !prop_spec
|
||||
|| !NM_FLAGS_HAS (prop_spec->flags, NM_SETTING_PARAM_SECRET))
|
||||
return FALSE;
|
||||
|
||||
nm_assert (nm_streq (prop_spec->name, NM_SETTING_VPN_SECRETS));
|
||||
|
||||
if (!priv->secrets)
|
||||
return FALSE;
|
||||
|
||||
/* Iterate through secrets hash and check each entry */
|
||||
g_hash_table_iter_init (&iter, priv->secrets);
|
||||
while (g_hash_table_iter_next (&iter, (gpointer) &secret, NULL)) {
|
||||
NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;
|
||||
|
||||
nm_setting_get_secret_flags (setting, secret, &flags, NULL);
|
||||
if (func (setting, pspec->name, flags, user_data) == TRUE) {
|
||||
g_hash_table_iter_remove (&iter);
|
||||
changed = TRUE;
|
||||
}
|
||||
if (func) {
|
||||
NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;
|
||||
|
||||
if (!nm_setting_get_secret_flags (setting, secret, &flags, NULL))
|
||||
nm_assert_not_reached ();
|
||||
|
||||
if (!func (setting, secret, flags, user_data))
|
||||
continue;
|
||||
} else
|
||||
nm_assert (nm_setting_get_secret_flags (setting, secret, NULL, NULL));
|
||||
|
||||
g_hash_table_iter_remove (&iter);
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
|
|
@ -963,13 +977,13 @@ nm_setting_vpn_class_init (NMSettingVpnClass *klass)
|
|||
object_class->set_property = set_property;
|
||||
object_class->finalize = finalize;
|
||||
|
||||
setting_class->verify = verify;
|
||||
setting_class->update_one_secret = update_one_secret;
|
||||
setting_class->get_secret_flags = get_secret_flags;
|
||||
setting_class->set_secret_flags = set_secret_flags;
|
||||
setting_class->need_secrets = need_secrets;
|
||||
setting_class->compare_property = compare_property;
|
||||
setting_class->clear_secrets_with_flags = clear_secrets_with_flags;
|
||||
setting_class->verify = verify;
|
||||
setting_class->update_one_secret = update_one_secret;
|
||||
setting_class->get_secret_flags = get_secret_flags;
|
||||
setting_class->set_secret_flags = set_secret_flags;
|
||||
setting_class->need_secrets = need_secrets;
|
||||
setting_class->compare_property = compare_property;
|
||||
setting_class->clear_secrets = clear_secrets;
|
||||
|
||||
/**
|
||||
* NMSettingVpn:service-type:
|
||||
|
|
|
|||
|
|
@ -539,12 +539,16 @@ _nm_sett_info_setting_get_property_info (const NMSettInfoSetting *sett_info,
|
|||
const NMSettInfoSetting *
|
||||
_nm_setting_class_get_sett_info (NMSettingClass *setting_class)
|
||||
{
|
||||
if ( NM_IS_SETTING_CLASS (setting_class)
|
||||
&& setting_class->setting_info) {
|
||||
nm_assert (setting_class->setting_info->meta_type < G_N_ELEMENTS (_sett_info_settings));
|
||||
return &_sett_info_settings[setting_class->setting_info->meta_type];
|
||||
}
|
||||
return NULL;
|
||||
const NMSettInfoSetting *sett_info;
|
||||
|
||||
if ( !NM_IS_SETTING_CLASS (setting_class)
|
||||
|| !setting_class->setting_info)
|
||||
return NULL;
|
||||
|
||||
nm_assert (setting_class->setting_info->meta_type < G_N_ELEMENTS (_sett_info_settings));
|
||||
sett_info = &_sett_info_settings[setting_class->setting_info->meta_type];
|
||||
nm_assert (sett_info->setting_class == setting_class);
|
||||
return sett_info;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -876,53 +880,41 @@ _nm_setting_new_from_dbus (GType setting_type,
|
|||
}
|
||||
|
||||
for (i = 0; i < sett_info->property_infos_len; i++) {
|
||||
const NMSettInfoProperty *property = &sett_info->property_infos[i];
|
||||
const NMSettInfoProperty *property_info = &sett_info->property_infos[i];
|
||||
gs_unref_variant GVariant *value = NULL;
|
||||
gs_free_error GError *local = NULL;
|
||||
|
||||
if (property->param_spec && !(property->param_spec->flags & G_PARAM_WRITABLE))
|
||||
if ( property_info->param_spec
|
||||
&& !(property_info->param_spec->flags & G_PARAM_WRITABLE))
|
||||
continue;
|
||||
|
||||
value = g_variant_lookup_value (setting_dict, property->name, NULL);
|
||||
value = g_variant_lookup_value (setting_dict, property_info->name, NULL);
|
||||
|
||||
if (value && keys)
|
||||
g_hash_table_remove (keys, property->name);
|
||||
g_hash_table_remove (keys, property_info->name);
|
||||
|
||||
if (value && property->set_func) {
|
||||
if ( value
|
||||
&& property_info->set_func) {
|
||||
|
||||
if (!g_variant_type_equal (g_variant_get_type (value), property->dbus_type)) {
|
||||
if (!g_variant_type_equal (g_variant_get_type (value), property_info->dbus_type)) {
|
||||
/* for backward behavior, fail unless best-effort is chosen. */
|
||||
if (NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_BEST_EFFORT))
|
||||
continue;
|
||||
g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("can't set property of type '%s' from value of type '%s'"),
|
||||
property->dbus_type ?
|
||||
g_variant_type_peek_string (property->dbus_type) :
|
||||
property->param_spec ?
|
||||
g_type_name (property->param_spec->value_type) : "(unknown)",
|
||||
property_info->dbus_type ?
|
||||
g_variant_type_peek_string (property_info->dbus_type) :
|
||||
property_info->param_spec ?
|
||||
g_type_name (property_info->param_spec->value_type) : "(unknown)",
|
||||
g_variant_get_type_string (value));
|
||||
g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), property->name);
|
||||
g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), property_info->name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!property->set_func (setting,
|
||||
connection_dict,
|
||||
property->name,
|
||||
value,
|
||||
parse_flags,
|
||||
&local)) {
|
||||
if (!NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_STRICT))
|
||||
continue;
|
||||
g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("failed to set property: %s"),
|
||||
local->message);
|
||||
g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), property->name);
|
||||
return NULL;
|
||||
}
|
||||
} else if (!value && property->not_set_func) {
|
||||
if (!property->not_set_func (setting,
|
||||
if (!property_info->set_func (setting,
|
||||
connection_dict,
|
||||
property->name,
|
||||
property_info->name,
|
||||
value,
|
||||
parse_flags,
|
||||
&local)) {
|
||||
if (!NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_STRICT))
|
||||
|
|
@ -930,35 +922,52 @@ _nm_setting_new_from_dbus (GType setting_type,
|
|||
g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("failed to set property: %s"),
|
||||
local->message);
|
||||
g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), property->name);
|
||||
g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), property_info->name);
|
||||
return NULL;
|
||||
}
|
||||
} else if (value && property->param_spec) {
|
||||
} else if ( !value
|
||||
&& property_info->not_set_func) {
|
||||
if (!property_info->not_set_func (setting,
|
||||
connection_dict,
|
||||
property_info->name,
|
||||
parse_flags,
|
||||
&local)) {
|
||||
if (!NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_STRICT))
|
||||
continue;
|
||||
g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("failed to set property: %s"),
|
||||
local->message);
|
||||
g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), property_info->name);
|
||||
return NULL;
|
||||
}
|
||||
} else if ( value
|
||||
&& property_info->param_spec) {
|
||||
nm_auto_unset_gvalue GValue object_value = G_VALUE_INIT;
|
||||
|
||||
g_value_init (&object_value, property->param_spec->value_type);
|
||||
if (!set_property_from_dbus (property, value, &object_value)) {
|
||||
g_value_init (&object_value, property_info->param_spec->value_type);
|
||||
if (!set_property_from_dbus (property_info, value, &object_value)) {
|
||||
/* for backward behavior, fail unless best-effort is chosen. */
|
||||
if (NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_BEST_EFFORT))
|
||||
continue;
|
||||
g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("can't set property of type '%s' from value of type '%s'"),
|
||||
property->dbus_type ?
|
||||
g_variant_type_peek_string (property->dbus_type) :
|
||||
property->param_spec ?
|
||||
g_type_name (property->param_spec->value_type) : "(unknown)",
|
||||
property_info->dbus_type
|
||||
? g_variant_type_peek_string (property_info->dbus_type)
|
||||
: ( property_info->param_spec
|
||||
? g_type_name (property_info->param_spec->value_type)
|
||||
: "(unknown)"),
|
||||
g_variant_get_type_string (value));
|
||||
g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), property->name);
|
||||
g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), property_info->name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!nm_g_object_set_property (G_OBJECT (setting), property->param_spec->name, &object_value, &local)) {
|
||||
if (!nm_g_object_set_property (G_OBJECT (setting), property_info->param_spec->name, &object_value, &local)) {
|
||||
if (!NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_STRICT))
|
||||
continue;
|
||||
g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("can not set property: %s"),
|
||||
local->message);
|
||||
g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), property->name);
|
||||
g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), property_info->name);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
|
@ -1065,34 +1074,18 @@ _gobject_copy_property (GObject *src,
|
|||
g_object_set_property (dst, property_name, &value);
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_setting_duplicate:
|
||||
* @setting: the #NMSetting to duplicate
|
||||
*
|
||||
* Duplicates a #NMSetting.
|
||||
*
|
||||
* Returns: (transfer full): a new #NMSetting containing the same properties and values as the
|
||||
* source #NMSetting
|
||||
**/
|
||||
NMSetting *
|
||||
nm_setting_duplicate (NMSetting *setting)
|
||||
static void
|
||||
duplicate_copy_properties (const NMSettInfoSetting *sett_info,
|
||||
NMSetting *src,
|
||||
NMSetting *dst)
|
||||
{
|
||||
const NMSettInfoSetting *sett_info;
|
||||
GObject *dup;
|
||||
|
||||
g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
|
||||
|
||||
dup = g_object_new (G_OBJECT_TYPE (setting), NULL);
|
||||
|
||||
sett_info = _nm_setting_class_get_sett_info (NM_SETTING_GET_CLASS (setting));
|
||||
|
||||
if (sett_info->detail.gendata_info) {
|
||||
GenData *gendata = _gendata_hash (setting, FALSE);
|
||||
GenData *gendata = _gendata_hash (src, FALSE);
|
||||
|
||||
if ( gendata
|
||||
&& g_hash_table_size (gendata->hash) > 0) {
|
||||
GHashTableIter iter;
|
||||
GHashTable *h = _gendata_hash (NM_SETTING (dup), TRUE)->hash;
|
||||
GHashTable *h = _gendata_hash (dst, TRUE)->hash;
|
||||
const char *key;
|
||||
GVariant *val;
|
||||
|
||||
|
|
@ -1110,29 +1103,58 @@ nm_setting_duplicate (NMSetting *setting)
|
|||
guint i;
|
||||
|
||||
for (i = 0; i < sett_info->property_infos_len; i++) {
|
||||
GParamSpec *prop_spec = sett_info->property_infos[i].param_spec;
|
||||
const NMSettInfoProperty *property_info = &sett_info->property_infos[i];
|
||||
|
||||
if (!prop_spec)
|
||||
continue;
|
||||
if ((prop_spec->flags & (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)) != G_PARAM_WRITABLE)
|
||||
continue;
|
||||
if (property_info->param_spec) {
|
||||
if ((property_info->param_spec->flags & (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)) != G_PARAM_WRITABLE)
|
||||
continue;
|
||||
|
||||
if (!frozen) {
|
||||
g_object_freeze_notify (dup);
|
||||
frozen = TRUE;
|
||||
if (!frozen) {
|
||||
g_object_freeze_notify (G_OBJECT (dst));
|
||||
frozen = TRUE;
|
||||
}
|
||||
_gobject_copy_property (G_OBJECT (src),
|
||||
G_OBJECT (dst),
|
||||
property_info->param_spec->name,
|
||||
G_PARAM_SPEC_VALUE_TYPE (property_info->param_spec));
|
||||
continue;
|
||||
}
|
||||
|
||||
_gobject_copy_property (G_OBJECT (setting),
|
||||
dup,
|
||||
prop_spec->name,
|
||||
G_PARAM_SPEC_VALUE_TYPE (prop_spec));
|
||||
}
|
||||
|
||||
if (frozen)
|
||||
g_object_thaw_notify (dup);
|
||||
g_object_thaw_notify (G_OBJECT (dst));
|
||||
}
|
||||
}
|
||||
|
||||
return NM_SETTING (dup);
|
||||
/**
|
||||
* nm_setting_duplicate:
|
||||
* @setting: the #NMSetting to duplicate
|
||||
*
|
||||
* Duplicates a #NMSetting.
|
||||
*
|
||||
* Returns: (transfer full): a new #NMSetting containing the same properties and values as the
|
||||
* source #NMSetting
|
||||
**/
|
||||
NMSetting *
|
||||
nm_setting_duplicate (NMSetting *setting)
|
||||
{
|
||||
const NMSettInfoSetting *sett_info;
|
||||
NMSettingClass *klass;
|
||||
NMSetting *dst;
|
||||
|
||||
g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
|
||||
|
||||
klass = NM_SETTING_GET_CLASS (setting);
|
||||
nm_assert (NM_IS_SETTING_CLASS (klass));
|
||||
nm_assert (klass->duplicate_copy_properties);
|
||||
|
||||
dst = g_object_new (G_TYPE_FROM_CLASS (klass), NULL);
|
||||
|
||||
sett_info = _nm_setting_class_get_sett_info (klass);
|
||||
nm_assert (sett_info);
|
||||
|
||||
klass->duplicate_copy_properties (sett_info, setting, dst);
|
||||
return dst;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1818,81 +1840,47 @@ _nm_setting_aggregate (NMSetting *setting,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* _nm_setting_clear_secrets:
|
||||
* @setting: the #NMSetting
|
||||
*
|
||||
* Resets and clears any secrets in the setting. Secrets should be added to the
|
||||
* setting only when needed, and cleared immediately after use to prevent
|
||||
* leakage of information.
|
||||
*
|
||||
* Returns: %TRUE if the setting changed at all
|
||||
**/
|
||||
gboolean
|
||||
_nm_setting_clear_secrets (NMSetting *setting)
|
||||
{
|
||||
const NMSettInfoSetting *sett_info;
|
||||
gboolean changed = FALSE;
|
||||
guint i;
|
||||
|
||||
g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
|
||||
|
||||
sett_info = _nm_setting_class_get_sett_info (NM_SETTING_GET_CLASS (setting));
|
||||
for (i = 0; i < sett_info->property_infos_len; i++) {
|
||||
GParamSpec *prop_spec = sett_info->property_infos[i].param_spec;
|
||||
|
||||
if (!prop_spec)
|
||||
continue;
|
||||
|
||||
if (prop_spec->flags & NM_SETTING_PARAM_SECRET) {
|
||||
GValue value = G_VALUE_INIT;
|
||||
|
||||
g_value_init (&value, prop_spec->value_type);
|
||||
g_object_get_property (G_OBJECT (setting), prop_spec->name, &value);
|
||||
if (!g_param_value_defaults (prop_spec, &value)) {
|
||||
g_param_value_set_default (prop_spec, &value);
|
||||
g_object_set_property (G_OBJECT (setting), prop_spec->name, &value);
|
||||
changed = TRUE;
|
||||
}
|
||||
g_value_unset (&value);
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clear_secrets_with_flags (NMSetting *setting,
|
||||
GParamSpec *pspec,
|
||||
NMSettingClearSecretsWithFlagsFn func,
|
||||
gpointer user_data)
|
||||
clear_secrets (const NMSettInfoSetting *sett_info,
|
||||
guint property_idx,
|
||||
NMSetting *setting,
|
||||
NMSettingClearSecretsWithFlagsFn func,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;
|
||||
gboolean changed = FALSE;
|
||||
GParamSpec *param_spec = sett_info->property_infos[property_idx].param_spec;
|
||||
|
||||
g_return_val_if_fail (!NM_IS_SETTING_VPN (setting), FALSE);
|
||||
if (!param_spec)
|
||||
return FALSE;
|
||||
|
||||
/* Clear the secret if the user function says to do so */
|
||||
if (!nm_setting_get_secret_flags (setting, pspec->name, &flags, NULL))
|
||||
g_return_val_if_reached (FALSE);
|
||||
if (!NM_FLAGS_HAS (param_spec->flags, NM_SETTING_PARAM_SECRET))
|
||||
return FALSE;
|
||||
|
||||
if (func (setting, pspec->name, flags, user_data) == TRUE) {
|
||||
GValue value = G_VALUE_INIT;
|
||||
if (func) {
|
||||
if (!nm_setting_get_secret_flags (setting, param_spec->name, &flags, NULL))
|
||||
nm_assert_not_reached ();
|
||||
if (!func (setting, param_spec->name, flags, user_data))
|
||||
return FALSE;
|
||||
} else
|
||||
nm_assert (nm_setting_get_secret_flags (setting, param_spec->name, NULL, NULL));
|
||||
|
||||
g_value_init (&value, pspec->value_type);
|
||||
g_object_get_property (G_OBJECT (setting), pspec->name, &value);
|
||||
if (!g_param_value_defaults (pspec, &value)) {
|
||||
g_param_value_set_default (pspec, &value);
|
||||
g_object_set_property (G_OBJECT (setting), pspec->name, &value);
|
||||
changed = TRUE;
|
||||
}
|
||||
g_value_unset (&value);
|
||||
{
|
||||
nm_auto_unset_gvalue GValue value = G_VALUE_INIT;
|
||||
|
||||
g_value_init (&value, param_spec->value_type);
|
||||
g_object_get_property (G_OBJECT (setting), param_spec->name, &value);
|
||||
if (g_param_value_defaults (param_spec, &value))
|
||||
return FALSE;
|
||||
|
||||
g_param_value_set_default (param_spec, &value);
|
||||
g_object_set_property (G_OBJECT (setting), param_spec->name, &value);
|
||||
}
|
||||
|
||||
return changed;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* _nm_setting_clear_secrets_with_flags:
|
||||
* _nm_setting_clear_secrets:
|
||||
* @setting: the #NMSetting
|
||||
* @func: (scope call): function to be called to determine whether a
|
||||
* specific secret should be cleared or not
|
||||
|
|
@ -1903,31 +1891,30 @@ clear_secrets_with_flags (NMSetting *setting,
|
|||
* Returns: %TRUE if the setting changed at all
|
||||
**/
|
||||
gboolean
|
||||
_nm_setting_clear_secrets_with_flags (NMSetting *setting,
|
||||
NMSettingClearSecretsWithFlagsFn func,
|
||||
gpointer user_data)
|
||||
_nm_setting_clear_secrets (NMSetting *setting,
|
||||
NMSettingClearSecretsWithFlagsFn func,
|
||||
gpointer user_data)
|
||||
{
|
||||
const NMSettInfoSetting *sett_info;
|
||||
gboolean changed = FALSE;
|
||||
guint i;
|
||||
gboolean (*my_clear_secrets) (const struct _NMSettInfoSetting *sett_info,
|
||||
guint property_idx,
|
||||
NMSetting *setting,
|
||||
NMSettingClearSecretsWithFlagsFn func,
|
||||
gpointer user_data);
|
||||
|
||||
g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
|
||||
g_return_val_if_fail (func != NULL, FALSE);
|
||||
|
||||
my_clear_secrets = NM_SETTING_GET_CLASS (setting)->clear_secrets;
|
||||
|
||||
sett_info = _nm_setting_class_get_sett_info (NM_SETTING_GET_CLASS (setting));
|
||||
for (i = 0; i < sett_info->property_infos_len; i++) {
|
||||
GParamSpec *prop_spec = sett_info->property_infos[i].param_spec;
|
||||
|
||||
if (!prop_spec)
|
||||
continue;
|
||||
|
||||
if (!NM_FLAGS_HAS (prop_spec->flags, NM_SETTING_PARAM_SECRET))
|
||||
continue;
|
||||
|
||||
changed |= NM_SETTING_GET_CLASS (setting)->clear_secrets_with_flags (setting,
|
||||
prop_spec,
|
||||
func,
|
||||
user_data);
|
||||
changed |= my_clear_secrets (sett_info,
|
||||
i,
|
||||
setting,
|
||||
func,
|
||||
user_data);
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
|
@ -2579,11 +2566,12 @@ nm_setting_class_init (NMSettingClass *setting_class)
|
|||
object_class->get_property = get_property;
|
||||
object_class->finalize = finalize;
|
||||
|
||||
setting_class->update_one_secret = update_one_secret;
|
||||
setting_class->get_secret_flags = get_secret_flags;
|
||||
setting_class->set_secret_flags = set_secret_flags;
|
||||
setting_class->compare_property = compare_property;
|
||||
setting_class->clear_secrets_with_flags = clear_secrets_with_flags;
|
||||
setting_class->update_one_secret = update_one_secret;
|
||||
setting_class->get_secret_flags = get_secret_flags;
|
||||
setting_class->set_secret_flags = set_secret_flags;
|
||||
setting_class->compare_property = compare_property;
|
||||
setting_class->clear_secrets = clear_secrets;
|
||||
setting_class->duplicate_copy_properties = duplicate_copy_properties;
|
||||
|
||||
/**
|
||||
* NMSetting:name:
|
||||
|
|
|
|||
|
|
@ -200,10 +200,12 @@ typedef struct {
|
|||
NMSettingSecretFlags flags,
|
||||
GError **error);
|
||||
|
||||
gboolean (*clear_secrets_with_flags) (NMSetting *setting,
|
||||
GParamSpec *pspec,
|
||||
NMSettingClearSecretsWithFlagsFn func,
|
||||
gpointer user_data);
|
||||
/*< private >*/
|
||||
gboolean (*clear_secrets) (const struct _NMSettInfoSetting *sett_info,
|
||||
guint property_idx,
|
||||
NMSetting *setting,
|
||||
NMSettingClearSecretsWithFlagsFn func,
|
||||
gpointer user_data);
|
||||
|
||||
/* compare_property() returns a ternary, where DEFAULT means that the property should not
|
||||
* be compared due to the compare @flags. A TRUE/FALSE result means that the property is
|
||||
|
|
@ -218,11 +220,16 @@ typedef struct {
|
|||
NMSetting *other,
|
||||
NMSettingCompareFlags flags);
|
||||
|
||||
/*< private >*/
|
||||
void (*duplicate_copy_properties) (const struct _NMSettInfoSetting *sett_info,
|
||||
NMSetting *src,
|
||||
NMSetting *dst);
|
||||
|
||||
/*< private >*/
|
||||
const struct _NMMetaSettingInfo *setting_info;
|
||||
|
||||
/*< private >*/
|
||||
gpointer padding[6];
|
||||
gpointer padding[5];
|
||||
} NMSettingClass;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ typedef struct {
|
|||
union {
|
||||
guint8 addr_ptr[1];
|
||||
in_addr_t addr4;
|
||||
struct in_addr addr4_struct;
|
||||
struct in6_addr addr6;
|
||||
|
||||
/* NMIPAddr is really a union for IP addresses.
|
||||
|
|
@ -255,10 +256,12 @@ nm_memdup (gconstpointer data, gsize size)
|
|||
static inline char *
|
||||
_nm_strndup_a_step (char *s, const char *str, gsize len)
|
||||
{
|
||||
NM_PRAGMA_WARNING_DISABLE ("-Wstringop-truncation");
|
||||
if (len > 0)
|
||||
strncpy (s, str, len);
|
||||
s[len] = '\0';
|
||||
return s;
|
||||
NM_PRAGMA_WARNING_REENABLE;
|
||||
}
|
||||
|
||||
/* Similar to g_strndup(), however, if the string (including the terminating
|
||||
|
|
@ -269,7 +272,12 @@ _nm_strndup_a_step (char *s, const char *str, gsize len)
|
|||
*
|
||||
* In case malloc() is necessary, @out_str_free will be set (this string
|
||||
* must be freed afterwards). It is permissible to pass %NULL as @out_str_free,
|
||||
* if you ensure that len < alloca_maxlen. */
|
||||
* if you ensure that len < alloca_maxlen.
|
||||
*
|
||||
* Note that just like g_strndup(), this always returns a buffer with @len + 1
|
||||
* bytes, even if strlen(@str) is shorter than that (NUL terminated early). We fill
|
||||
* the buffer with strncpy(), which means, that @str is copied up to the first
|
||||
* NUL character and then filled with NUL characters. */
|
||||
#define nm_strndup_a(alloca_maxlen, str, len, out_str_free) \
|
||||
({ \
|
||||
const gsize _alloca_maxlen = (alloca_maxlen); \
|
||||
|
|
|
|||
|
|
@ -152,6 +152,58 @@ test_nm_strdup_int (void)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
test_nm_strndup_a (void)
|
||||
{
|
||||
int run;
|
||||
|
||||
for (run = 0; run < 20; run++) {
|
||||
gs_free char *input = NULL;
|
||||
char ch;
|
||||
gsize i, l;
|
||||
|
||||
input = g_strnfill (nmtst_get_rand_int () % 20, 'x');
|
||||
|
||||
for (i = 0; input[i]; i++) {
|
||||
while ((ch = ((char) nmtst_get_rand_int ())) == '\0') {
|
||||
/* repeat. */
|
||||
}
|
||||
input[i] = ch;
|
||||
}
|
||||
|
||||
{
|
||||
gs_free char *dup_free = NULL;
|
||||
const char *dup;
|
||||
|
||||
l = strlen (input) + 1;
|
||||
dup = nm_strndup_a (10, input, l - 1, &dup_free);
|
||||
g_assert_cmpstr (dup, ==, input);
|
||||
if (strlen (dup) < 10)
|
||||
g_assert (!dup_free);
|
||||
else
|
||||
g_assert (dup == dup_free);
|
||||
}
|
||||
|
||||
{
|
||||
gs_free char *dup_free = NULL;
|
||||
const char *dup;
|
||||
|
||||
l = nmtst_get_rand_int () % 23;
|
||||
dup = nm_strndup_a (10, input, l, &dup_free);
|
||||
g_assert (strncmp (dup, input, l) == 0);
|
||||
g_assert (strlen (dup) <= l);
|
||||
if (l < 10)
|
||||
g_assert (!dup_free);
|
||||
else
|
||||
g_assert (dup == dup_free);
|
||||
if (strlen (input) < l)
|
||||
g_assert (nm_utils_memeqzero (&dup[strlen (input)], l - strlen (input)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
NMTST_DEFINE ();
|
||||
|
||||
int main (int argc, char **argv)
|
||||
|
|
@ -162,6 +214,7 @@ int main (int argc, char **argv)
|
|||
g_test_add_func ("/general/test_nmhash", test_nmhash);
|
||||
g_test_add_func ("/general/test_nm_make_strv", test_make_strv);
|
||||
g_test_add_func ("/general/test_nm_strdup_int", test_nm_strdup_int);
|
||||
g_test_add_func ("/general/test_nm_strndup_a", test_nm_strndup_a);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -481,30 +481,6 @@ static struct nl_sock *_genl_sock (NMLinuxPlatform *platform);
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static int
|
||||
_sock_addr_set_unaligned (NMSockAddrUnion *dst,
|
||||
gconstpointer src,
|
||||
gsize src_len)
|
||||
{
|
||||
int f_expected;
|
||||
struct sockaddr sa;
|
||||
|
||||
if (src_len == sizeof (struct sockaddr_in))
|
||||
f_expected = AF_INET;
|
||||
else if (src_len == sizeof (struct sockaddr_in6))
|
||||
f_expected = AF_INET6;
|
||||
else
|
||||
return AF_UNSPEC;
|
||||
|
||||
memcpy (&sa.sa_family, &((struct sockaddr *) src)->sa_family, sizeof (sa.sa_family));
|
||||
if (sa.sa_family != f_expected)
|
||||
return AF_UNSPEC;
|
||||
memcpy (dst, src, src_len);
|
||||
return f_expected;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static int
|
||||
wait_for_nl_response_to_nmerr (WaitForNlResponseResult seq_result)
|
||||
{
|
||||
|
|
@ -2038,11 +2014,11 @@ _wireguard_update_from_peers_nla (CList *peers,
|
|||
nm_explicit_bzero (nla_data (tb[WGPEER_A_PRESHARED_KEY]),
|
||||
nla_len (tb[WGPEER_A_PRESHARED_KEY]));
|
||||
}
|
||||
if (tb[WGPEER_A_ENDPOINT]) {
|
||||
_sock_addr_set_unaligned (&peer_c->data.endpoint,
|
||||
nla_data (tb[WGPEER_A_ENDPOINT]),
|
||||
nla_len (tb[WGPEER_A_ENDPOINT]));
|
||||
}
|
||||
|
||||
nm_sock_addr_union_cpy_untrusted (&peer_c->data.endpoint,
|
||||
tb[WGPEER_A_ENDPOINT] ? nla_data (tb[WGPEER_A_ENDPOINT]) : NULL,
|
||||
tb[WGPEER_A_ENDPOINT] ? nla_len (tb[WGPEER_A_ENDPOINT]) : 0);
|
||||
|
||||
if (tb[WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL])
|
||||
peer_c->data.persistent_keepalive_interval = nla_get_u64 (tb[WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL]);
|
||||
if (tb[WGPEER_A_LAST_HANDSHAKE_TIME])
|
||||
|
|
@ -2398,6 +2374,7 @@ _wireguard_create_change_nlmsgs (NMPlatform *platform,
|
|||
const NMPlatformLnkWireGuard *lnk_wireguard,
|
||||
const NMPWireGuardPeer *peers,
|
||||
guint peers_len,
|
||||
gboolean replace_peers,
|
||||
GPtrArray **out_msgs)
|
||||
{
|
||||
gs_unref_ptrarray GPtrArray *msgs = NULL;
|
||||
|
|
@ -2446,7 +2423,9 @@ again:
|
|||
NLA_PUT (msg, WGDEVICE_A_PRIVATE_KEY, sizeof (lnk_wireguard->private_key), lnk_wireguard->private_key);
|
||||
NLA_PUT_U16 (msg, WGDEVICE_A_LISTEN_PORT, lnk_wireguard->listen_port);
|
||||
NLA_PUT_U32 (msg, WGDEVICE_A_FWMARK, lnk_wireguard->fwmark);
|
||||
NLA_PUT_U32 (msg, WGDEVICE_A_FLAGS, WGDEVICE_F_REPLACE_PEERS);
|
||||
|
||||
NLA_PUT_U32 (msg, WGDEVICE_A_FLAGS,
|
||||
replace_peers ? WGDEVICE_F_REPLACE_PEERS : ((guint32) 0u));
|
||||
}
|
||||
|
||||
if (peers_len == 0)
|
||||
|
|
@ -2483,15 +2462,16 @@ again:
|
|||
if (nla_put_uint32 (msg, WGPEER_A_FLAGS, WGPEER_F_REPLACE_ALLOWEDIPS) < 0)
|
||||
goto toobig_peers;
|
||||
|
||||
g_return_val_if_fail (NM_IN_SET (p->endpoint.sa.sa_family, AF_INET, AF_INET6), -NME_BUG);
|
||||
|
||||
if (nla_put (msg,
|
||||
WGPEER_A_ENDPOINT,
|
||||
p->endpoint.sa.sa_family == AF_INET
|
||||
? sizeof (p->endpoint.in)
|
||||
: sizeof (p->endpoint.in6),
|
||||
&p->endpoint) < 0)
|
||||
goto toobig_peers;
|
||||
if (NM_IN_SET (p->endpoint.sa.sa_family, AF_INET, AF_INET6)) {
|
||||
if (nla_put (msg,
|
||||
WGPEER_A_ENDPOINT,
|
||||
p->endpoint.sa.sa_family == AF_INET
|
||||
? sizeof (p->endpoint.in)
|
||||
: sizeof (p->endpoint.in6),
|
||||
&p->endpoint) < 0)
|
||||
goto toobig_peers;
|
||||
} else
|
||||
nm_assert (p->endpoint.sa.sa_family == AF_UNSPEC);
|
||||
}
|
||||
|
||||
if (p->allowed_ips_len > 0) {
|
||||
|
|
@ -2575,7 +2555,8 @@ link_wireguard_change (NMPlatform *platform,
|
|||
int ifindex,
|
||||
const NMPlatformLnkWireGuard *lnk_wireguard,
|
||||
const NMPWireGuardPeer *peers,
|
||||
guint peers_len)
|
||||
guint peers_len,
|
||||
gboolean replace_peers)
|
||||
{
|
||||
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||
gs_unref_ptrarray GPtrArray *msgs = NULL;
|
||||
|
|
@ -2593,6 +2574,7 @@ link_wireguard_change (NMPlatform *platform,
|
|||
lnk_wireguard,
|
||||
peers,
|
||||
peers_len,
|
||||
replace_peers,
|
||||
&msgs);
|
||||
if (r < 0) {
|
||||
_LOGW ("wireguard: set-device, cannot construct netlink message: %s", nm_strerror (r));
|
||||
|
|
|
|||
|
|
@ -1997,8 +1997,9 @@ int
|
|||
nm_platform_link_wireguard_change (NMPlatform *self,
|
||||
int ifindex,
|
||||
const NMPlatformLnkWireGuard *lnk_wireguard,
|
||||
const struct _NMPWireGuardPeer *peers,
|
||||
guint peers_len)
|
||||
const NMPWireGuardPeer *peers,
|
||||
guint peers_len,
|
||||
gboolean replace_peers)
|
||||
{
|
||||
_CHECK_SELF (self, klass, -NME_BUG);
|
||||
|
||||
|
|
@ -2024,18 +2025,20 @@ nm_platform_link_wireguard_change (NMPlatform *self,
|
|||
nm_utils_strbuf_append_str (&b, &len, "}");
|
||||
}
|
||||
|
||||
_LOG3D ("link: change wireguard ifindex %d, %s, %u peers%s",
|
||||
_LOG3D ("link: change wireguard ifindex %d, %s, %u peers%s%s",
|
||||
ifindex,
|
||||
nm_platform_lnk_wireguard_to_string (lnk_wireguard, buf_lnk, sizeof (buf_lnk)),
|
||||
peers_len,
|
||||
buf_peers);
|
||||
buf_peers,
|
||||
replace_peers ? " (replace-peers)" : " (update-peers)");
|
||||
}
|
||||
|
||||
return klass->link_wireguard_change (self,
|
||||
ifindex,
|
||||
lnk_wireguard,
|
||||
peers,
|
||||
peers_len);
|
||||
peers_len,
|
||||
replace_peers);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -5604,33 +5607,24 @@ nm_platform_wireguard_peer_to_string (const NMPWireGuardPeer *peer, char *buf, g
|
|||
{
|
||||
char *buf0 = buf;
|
||||
gs_free char *public_key_b64 = NULL;
|
||||
char s_endpoint[NM_UTILS_INET_ADDRSTRLEN + 100];
|
||||
char s_sockaddr[NM_UTILS_INET_ADDRSTRLEN + 100];
|
||||
char s_endpoint[20 + sizeof (s_sockaddr)];
|
||||
char s_addr[NM_UTILS_INET_ADDRSTRLEN];
|
||||
char s_scope_id[40];
|
||||
guint i;
|
||||
|
||||
nm_utils_to_string_buffer_init (&buf, &len);
|
||||
|
||||
if (peer->endpoint.sa.sa_family == AF_INET) {
|
||||
public_key_b64 = g_base64_encode (peer->public_key, sizeof (peer->public_key));
|
||||
|
||||
if (peer->endpoint.sa.sa_family != AF_UNSPEC) {
|
||||
nm_sprintf_buf (s_endpoint,
|
||||
" endpoint %s:%u",
|
||||
nm_utils_inet4_ntop (peer->endpoint.in.sin_addr.s_addr, s_addr),
|
||||
(guint) htons (peer->endpoint.in.sin_port));
|
||||
} else if (peer->endpoint.sa.sa_family == AF_INET6) {
|
||||
if (peer->endpoint.in6.sin6_scope_id != 0)
|
||||
nm_sprintf_buf (s_scope_id, "@%u", peer->endpoint.in6.sin6_scope_id);
|
||||
else
|
||||
s_scope_id[0] = '\0';
|
||||
nm_sprintf_buf (s_endpoint,
|
||||
" endpoint [%s]%s:%u",
|
||||
nm_utils_inet6_ntop (&peer->endpoint.in6.sin6_addr, s_addr),
|
||||
s_scope_id,
|
||||
(guint) htons (peer->endpoint.in6.sin6_port));
|
||||
" endpoint %s",
|
||||
nm_sock_addr_union_to_string (&peer->endpoint,
|
||||
s_sockaddr,
|
||||
sizeof (s_sockaddr)));
|
||||
} else
|
||||
s_endpoint[0] = '\0';
|
||||
|
||||
public_key_b64 = g_base64_encode (peer->public_key, sizeof (peer->public_key));
|
||||
|
||||
nm_utils_strbuf_append (&buf, &len,
|
||||
"public-key %s"
|
||||
"%s" /* preshared-key */
|
||||
|
|
|
|||
|
|
@ -831,7 +831,8 @@ typedef struct {
|
|||
int ifindex,
|
||||
const NMPlatformLnkWireGuard *lnk_wireguard,
|
||||
const struct _NMPWireGuardPeer *peers,
|
||||
guint peers_len);
|
||||
guint peers_len,
|
||||
gboolean replace_peers);
|
||||
|
||||
gboolean (*vlan_add) (NMPlatform *, const char *name, int parent, int vlanid, guint32 vlanflags, const NMPlatformLink **out_link);
|
||||
gboolean (*link_vlan_change) (NMPlatform *self,
|
||||
|
|
@ -1393,7 +1394,8 @@ int nm_platform_link_wireguard_change (NMPlatform *self,
|
|||
int ifindex,
|
||||
const NMPlatformLnkWireGuard *lnk_wireguard,
|
||||
const struct _NMPWireGuardPeer *peers,
|
||||
guint peers_len);
|
||||
guint peers_len,
|
||||
gboolean replace_peers);
|
||||
|
||||
const NMPlatformIP6Address *nm_platform_ip6_address_get (NMPlatform *self, int ifindex, struct in6_addr address);
|
||||
|
||||
|
|
|
|||
|
|
@ -89,6 +89,192 @@ struct _NMPCache {
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
int
|
||||
nm_sock_addr_union_cmp (const NMSockAddrUnion *a, const NMSockAddrUnion *b)
|
||||
{
|
||||
nm_assert (!a || NM_IN_SET (a->sa.sa_family, AF_UNSPEC, AF_INET, AF_INET6));
|
||||
nm_assert (!b || NM_IN_SET (b->sa.sa_family, AF_UNSPEC, AF_INET, AF_INET6));
|
||||
|
||||
NM_CMP_SELF (a, b);
|
||||
|
||||
NM_CMP_FIELD (a, b, sa.sa_family);
|
||||
switch (a->sa.sa_family) {
|
||||
case AF_INET:
|
||||
NM_CMP_DIRECT (ntohl (a->in.sin_addr.s_addr), ntohl (b->in.sin_addr.s_addr));
|
||||
NM_CMP_DIRECT (htons (a->in.sin_port), htons (b->in.sin_port));
|
||||
break;
|
||||
case AF_INET6:
|
||||
NM_CMP_DIRECT_IN6ADDR (&a->in6.sin6_addr, &b->in6.sin6_addr);
|
||||
NM_CMP_DIRECT (htons (a->in6.sin6_port), htons (b->in6.sin6_port));
|
||||
NM_CMP_FIELD (a, b, in6.sin6_scope_id);
|
||||
NM_CMP_FIELD (a, b, in6.sin6_flowinfo);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
nm_sock_addr_union_hash_update (const NMSockAddrUnion *a, NMHashState *h)
|
||||
{
|
||||
if (!a) {
|
||||
nm_hash_update_val (h, 1241364739u);
|
||||
return;
|
||||
}
|
||||
|
||||
nm_assert (NM_IN_SET (a->sa.sa_family, AF_UNSPEC, AF_INET, AF_INET6));
|
||||
|
||||
switch (a->sa.sa_family) {
|
||||
case AF_INET:
|
||||
nm_hash_update_vals (h,
|
||||
a->in.sin_family,
|
||||
a->in.sin_addr.s_addr,
|
||||
a->in.sin_port);
|
||||
return;
|
||||
case AF_INET6:
|
||||
nm_hash_update_vals (h,
|
||||
a->in6.sin6_family,
|
||||
a->in6.sin6_addr,
|
||||
a->in6.sin6_port,
|
||||
a->in6.sin6_scope_id,
|
||||
a->in6.sin6_flowinfo);
|
||||
return;
|
||||
default:
|
||||
nm_hash_update_val (h, a->sa.sa_family);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_sock_addr_union_cpy:
|
||||
* @dst: the destination #NMSockAddrUnion. It will always be fully initialized,
|
||||
* to one of the address families AF_INET, AF_INET6, or AF_UNSPEC (in case of
|
||||
* error).
|
||||
* @src: (allow-none): the source buffer with an sockaddr to copy. It may be unaligned in
|
||||
* memory. If not %NULL, the buffer must be at least large enough to contain
|
||||
* sa.sa_family, and then, depending on sa.sa_family, it must be large enough
|
||||
* to hold struct sockaddr_in or struct sockaddr_in6.
|
||||
*
|
||||
* @dst will always be fully initialized (including setting all un-used bytes to zero).
|
||||
*/
|
||||
void
|
||||
nm_sock_addr_union_cpy (NMSockAddrUnion *dst,
|
||||
gconstpointer src /* unaligned (const NMSockAddrUnion *) */)
|
||||
{
|
||||
struct sockaddr sa;
|
||||
gsize src_len;
|
||||
|
||||
nm_assert (dst);
|
||||
|
||||
*dst = (NMSockAddrUnion) NM_SOCK_ADDR_UNION_INIT_UNSPEC;
|
||||
|
||||
if (!src)
|
||||
return;
|
||||
|
||||
memcpy (&sa.sa_family, &((struct sockaddr *) src)->sa_family, sizeof (sa.sa_family));
|
||||
|
||||
if (sa.sa_family == AF_INET)
|
||||
src_len = sizeof (struct sockaddr_in);
|
||||
else if (sa.sa_family == AF_INET6)
|
||||
src_len = sizeof (struct sockaddr_in6);
|
||||
else
|
||||
return;
|
||||
|
||||
memcpy (dst, src, src_len);
|
||||
nm_assert (dst->sa.sa_family == sa.sa_family);
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_sock_addr_union_cpy_untrusted:
|
||||
* @dst: the destination #NMSockAddrUnion. It will always be fully initialized,
|
||||
* to one of the address families AF_INET, AF_INET6, or AF_UNSPEC (in case of
|
||||
* error).
|
||||
* @src: the source buffer with an sockaddr to copy. It may be unaligned in
|
||||
* memory.
|
||||
* @src_len: the length of @src in bytes.
|
||||
*
|
||||
* The function requires @src_len to be either sizeof(struct sockaddr_in) or sizeof (struct sockaddr_in6).
|
||||
* If that's the case, then @src will be interpreted as such structure (unaligned), and
|
||||
* accessed. It will check sa.sa_family to match the expected sizes, and if it does, the
|
||||
* struct will be copied.
|
||||
*
|
||||
* On any failure, @dst will be set to sa.sa_family AF_UNSPEC.
|
||||
* @dst will always be fully initialized (including setting all un-used bytes to zero).
|
||||
*/
|
||||
void
|
||||
nm_sock_addr_union_cpy_untrusted (NMSockAddrUnion *dst,
|
||||
gconstpointer src /* unaligned (const NMSockAddrUnion *) */,
|
||||
gsize src_len)
|
||||
{
|
||||
int f_expected;
|
||||
struct sockaddr sa;
|
||||
|
||||
nm_assert (dst);
|
||||
|
||||
*dst = (NMSockAddrUnion) NM_SOCK_ADDR_UNION_INIT_UNSPEC;
|
||||
|
||||
if (src_len == sizeof (struct sockaddr_in))
|
||||
f_expected = AF_INET;
|
||||
else if (src_len == sizeof (struct sockaddr_in6))
|
||||
f_expected = AF_INET6;
|
||||
else
|
||||
return;
|
||||
|
||||
memcpy (&sa.sa_family, &((struct sockaddr *) src)->sa_family, sizeof (sa.sa_family));
|
||||
|
||||
if (sa.sa_family != f_expected)
|
||||
return;
|
||||
|
||||
memcpy (dst, src, src_len);
|
||||
nm_assert (dst->sa.sa_family == sa.sa_family);
|
||||
}
|
||||
|
||||
const char *
|
||||
nm_sock_addr_union_to_string (const NMSockAddrUnion *sa,
|
||||
char *buf,
|
||||
gsize len)
|
||||
{
|
||||
char s_addr[NM_UTILS_INET_ADDRSTRLEN];
|
||||
char s_scope_id[40];
|
||||
|
||||
if (!nm_utils_to_string_buffer_init_null (sa, &buf, &len))
|
||||
return buf;
|
||||
|
||||
/* maybe we should use getnameinfo(), but here implement it ourself.
|
||||
*
|
||||
* We want to see the actual bytes for debugging (as we understand them),
|
||||
* and now what getnameinfo() makes of it. Also, it's simpler this way. */
|
||||
|
||||
switch (sa->sa.sa_family) {
|
||||
case AF_INET:
|
||||
g_snprintf (buf, len,
|
||||
"%s:%u",
|
||||
nm_utils_inet4_ntop (sa->in.sin_addr.s_addr, s_addr),
|
||||
(guint) htons (sa->in.sin_port));
|
||||
break;
|
||||
case AF_INET6:
|
||||
g_snprintf (buf, len,
|
||||
"[%s%s]:%u",
|
||||
nm_utils_inet6_ntop (&sa->in6.sin6_addr, s_addr),
|
||||
( sa->in6.sin6_scope_id != 0
|
||||
? nm_sprintf_buf (s_scope_id, "%u", sa->in6.sin6_scope_id)
|
||||
: ""),
|
||||
(guint) htons (sa->in6.sin6_port));
|
||||
break;
|
||||
case AF_UNSPEC:
|
||||
g_snprintf (buf, len, "unspec");
|
||||
break;
|
||||
default:
|
||||
g_snprintf (buf, len,
|
||||
"{addr-family:%u}",
|
||||
(unsigned) sa->sa.sa_family);
|
||||
break;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static const NMDedupMultiIdxTypeClass _dedup_multi_idx_type_class;
|
||||
|
||||
static void
|
||||
|
|
@ -392,13 +578,9 @@ _wireguard_peer_hash_update (const NMPWireGuardPeer *peer,
|
|||
peer->rx_bytes,
|
||||
peer->tx_bytes,
|
||||
peer->last_handshake_time.tv_sec,
|
||||
peer->last_handshake_time.tv_nsec,
|
||||
peer->endpoint.sa.sa_family);
|
||||
peer->last_handshake_time.tv_nsec);
|
||||
|
||||
if (peer->endpoint.sa.sa_family == AF_INET)
|
||||
nm_hash_update_val (h, peer->endpoint.in);
|
||||
else if (peer->endpoint.sa.sa_family == AF_INET6)
|
||||
nm_hash_update_val (h, peer->endpoint.in6);
|
||||
nm_sock_addr_union_hash_update (&peer->endpoint, h);
|
||||
|
||||
for (i = 0; i < peer->allowed_ips_len; i++)
|
||||
_wireguard_allowed_ip_hash_update (&peer->allowed_ips[i], h);
|
||||
|
|
@ -422,10 +604,7 @@ _wireguard_peer_cmp (const NMPWireGuardPeer *a,
|
|||
NM_CMP_FIELD_MEMCMP (a, b, public_key);
|
||||
NM_CMP_FIELD_MEMCMP (a, b, preshared_key);
|
||||
|
||||
if (a->endpoint.sa.sa_family == AF_INET)
|
||||
NM_CMP_FIELD_MEMCMP (a, b, endpoint.in);
|
||||
else if (a->endpoint.sa.sa_family == AF_INET6)
|
||||
NM_CMP_FIELD_MEMCMP (a, b, endpoint.in6);
|
||||
NM_CMP_RETURN (nm_sock_addr_union_cmp (&a->endpoint, &b->endpoint));
|
||||
|
||||
for (i = 0; i < a->allowed_ips_len; i++) {
|
||||
NM_CMP_RETURN (_wireguard_allowed_ip_cmp (&a->allowed_ips[i],
|
||||
|
|
|
|||
|
|
@ -37,6 +37,32 @@ typedef union {
|
|||
struct sockaddr_in6 in6;
|
||||
} NMSockAddrUnion;
|
||||
|
||||
#define NM_SOCK_ADDR_UNION_INIT_UNSPEC \
|
||||
{ \
|
||||
.sa = { \
|
||||
.sa_family = AF_UNSPEC, \
|
||||
}, \
|
||||
}
|
||||
|
||||
int nm_sock_addr_union_cmp (const NMSockAddrUnion *a,
|
||||
const NMSockAddrUnion *b);
|
||||
|
||||
void nm_sock_addr_union_hash_update (const NMSockAddrUnion *a,
|
||||
NMHashState *h);
|
||||
|
||||
void nm_sock_addr_union_cpy (NMSockAddrUnion *dst,
|
||||
gconstpointer src /* unaligned (const NMSockAddrUnion *) */);
|
||||
|
||||
void nm_sock_addr_union_cpy_untrusted (NMSockAddrUnion *dst,
|
||||
gconstpointer src /* unaligned (const NMSockAddrUnion *) */,
|
||||
gsize src_len);
|
||||
|
||||
const char *nm_sock_addr_union_to_string (const NMSockAddrUnion *sa,
|
||||
char *buf,
|
||||
gsize len);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
NMIPAddr addr;
|
||||
guint8 family;
|
||||
|
|
|
|||
|
|
@ -912,7 +912,8 @@ _test_wireguard_change (NMPlatform *platform,
|
|||
ifindex,
|
||||
&lnk_wireguard,
|
||||
(const NMPWireGuardPeer *) peers->data,
|
||||
peers->len);
|
||||
peers->len,
|
||||
TRUE);
|
||||
g_assert (NMTST_NM_ERR_SUCCESS (r));
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue