mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-05-09 03:38:09 +02:00
libnm,core: merge branch 'th/various-for-wireguard-2'
https://github.com/NetworkManager/NetworkManager/pull/291
This commit is contained in:
commit
2727c713ca
7 changed files with 366 additions and 226 deletions
|
|
@ -1873,6 +1873,108 @@ nm_connection_clear_secrets_with_flags (NMConnection *connection,
|
|||
g_signal_emit (connection, signals[SECRETS_CLEARED], 0);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Returns always a non-NULL, floating variant that must
|
||||
* be unrefed by the caller. */
|
||||
GVariant *
|
||||
_nm_connection_for_each_secret (NMConnection *self,
|
||||
GVariant *secrets,
|
||||
gboolean remove_non_secrets,
|
||||
_NMConnectionForEachSecretFunc callback,
|
||||
gpointer callback_data)
|
||||
{
|
||||
GVariantBuilder secrets_builder;
|
||||
GVariantBuilder setting_builder;
|
||||
GVariantIter secrets_iter;
|
||||
GVariantIter *setting_iter;
|
||||
const char *setting_name;
|
||||
|
||||
/* This function, given a dict of dicts representing new secrets of
|
||||
* an NMConnection, walks through each toplevel dict (which represents a
|
||||
* NMSetting), and for each setting, walks through that setting dict's
|
||||
* properties. For each property that's a secret, it will check that
|
||||
* secret's flags in the backing NMConnection object, and call a supplied
|
||||
* callback.
|
||||
*
|
||||
* The one complexity is that the VPN setting's 'secrets' property is
|
||||
* *also* a dict (since the key/value pairs are arbitrary and known
|
||||
* only to the VPN plugin itself). That means we have three levels of
|
||||
* dicts that we potentially have to traverse here. The differences
|
||||
* are handled by the virtual for_each_secret() function.
|
||||
*/
|
||||
|
||||
g_return_val_if_fail (callback, NULL);
|
||||
|
||||
g_variant_iter_init (&secrets_iter, secrets);
|
||||
g_variant_builder_init (&secrets_builder, NM_VARIANT_TYPE_CONNECTION);
|
||||
while (g_variant_iter_next (&secrets_iter, "{&sa{sv}}", &setting_name, &setting_iter)) {
|
||||
_nm_unused nm_auto_free_variant_iter GVariantIter *setting_iter_free = setting_iter;
|
||||
NMSetting *setting;
|
||||
const char *secret_name;
|
||||
GVariant *val;
|
||||
|
||||
setting = nm_connection_get_setting_by_name (self, setting_name);
|
||||
if (!setting)
|
||||
continue;
|
||||
|
||||
g_variant_builder_init (&setting_builder, NM_VARIANT_TYPE_SETTING);
|
||||
while (g_variant_iter_next (setting_iter, "{&sv}", &secret_name, &val)) {
|
||||
_nm_unused gs_unref_variant GVariant *val_free = val;
|
||||
|
||||
NM_SETTING_GET_CLASS (setting)->for_each_secret (setting,
|
||||
secret_name,
|
||||
val,
|
||||
remove_non_secrets,
|
||||
callback,
|
||||
callback_data,
|
||||
&setting_builder);
|
||||
}
|
||||
|
||||
g_variant_builder_add (&secrets_builder, "{sa{sv}}", setting_name, &setting_builder);
|
||||
}
|
||||
|
||||
return g_variant_builder_end (&secrets_builder);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
NMConnectionFindSecretFunc find_func;
|
||||
gpointer find_func_data;
|
||||
gboolean found;
|
||||
} FindSecretData;
|
||||
|
||||
static gboolean
|
||||
find_secret_for_each_func (NMSettingSecretFlags flags,
|
||||
gpointer user_data)
|
||||
{
|
||||
FindSecretData *data = user_data;
|
||||
|
||||
if (!data->found)
|
||||
data->found = data->find_func (flags, data->find_func_data);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_nm_connection_find_secret (NMConnection *self,
|
||||
GVariant *secrets,
|
||||
NMConnectionFindSecretFunc callback,
|
||||
gpointer callback_data)
|
||||
{
|
||||
gs_unref_variant GVariant *dummy = NULL;
|
||||
FindSecretData data = {
|
||||
.find_func = callback,
|
||||
.find_func_data = callback_data,
|
||||
.found = FALSE,
|
||||
};
|
||||
|
||||
dummy = _nm_connection_for_each_secret (self, secrets, FALSE, find_secret_for_each_func, &data);
|
||||
return data.found;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
* nm_connection_to_dbus:
|
||||
* @connection: the #NMConnection
|
||||
|
|
|
|||
|
|
@ -614,7 +614,8 @@ gboolean _nm_setting_sriov_sort_vfs (NMSettingSriov *setting);
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct _NMSettInfoSetting NMSettInfoSetting;
|
||||
typedef struct _NMSettInfoSetting NMSettInfoSetting;
|
||||
typedef struct _NMSettInfoProperty NMSettInfoProperty;
|
||||
|
||||
typedef GVariant *(*NMSettingPropertyGetFunc) (NMSetting *setting,
|
||||
const char *property);
|
||||
|
|
@ -638,7 +639,7 @@ typedef GVariant *(*NMSettingPropertyTransformToFunc) (const GValue *from);
|
|||
typedef void (*NMSettingPropertyTransformFromFunc) (GVariant *from,
|
||||
GValue *to);
|
||||
|
||||
typedef struct {
|
||||
struct _NMSettInfoProperty {
|
||||
const char *name;
|
||||
GParamSpec *param_spec;
|
||||
const GVariantType *dbus_type;
|
||||
|
|
@ -650,7 +651,7 @@ typedef struct {
|
|||
|
||||
NMSettingPropertyTransformToFunc to_dbus;
|
||||
NMSettingPropertyTransformFromFunc from_dbus;
|
||||
} NMSettInfoProperty;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
const GVariantType *(*get_variant_type) (const struct _NMSettInfoSetting *sett_info,
|
||||
|
|
@ -732,4 +733,20 @@ GBytes *_nm_setting_802_1x_cert_value_to_bytes (NMSetting8021xCKScheme scheme,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
GVariant *_nm_connection_for_each_secret (NMConnection *self,
|
||||
GVariant *secrets,
|
||||
gboolean remove_non_secrets,
|
||||
_NMConnectionForEachSecretFunc callback,
|
||||
gpointer callback_data);
|
||||
|
||||
typedef gboolean (*NMConnectionFindSecretFunc) (NMSettingSecretFlags flags,
|
||||
gpointer user_data);
|
||||
|
||||
gboolean _nm_connection_find_secret (NMConnection *self,
|
||||
GVariant *secrets,
|
||||
NMConnectionFindSecretFunc callback,
|
||||
gpointer callback_data);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ int _nm_setting_compare_priority (gconstpointer a, gconstpointer b);
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
void _nm_setting_emit_property_changed (NMSetting *setting);
|
||||
|
||||
typedef enum NMSettingUpdateSecretResult {
|
||||
NM_SETTING_UPDATE_SECRET_ERROR = FALSE,
|
||||
NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED = TRUE,
|
||||
|
|
@ -99,9 +101,6 @@ gboolean _nm_setting_verify_secret_string (const char *str,
|
|||
gboolean _nm_setting_aggregate (NMSetting *setting,
|
||||
NMConnectionAggregateType type,
|
||||
gpointer arg);
|
||||
gboolean _nm_setting_vpn_aggregate (NMSettingVpn *setting,
|
||||
NMConnectionAggregateType type,
|
||||
gpointer arg);
|
||||
|
||||
gboolean _nm_setting_slave_type_is_valid (const char *slave_type, const char **out_port_type);
|
||||
|
||||
|
|
|
|||
|
|
@ -449,20 +449,17 @@ nm_setting_vpn_foreach_secret (NMSettingVpn *setting,
|
|||
foreach_item_helper (setting, TRUE, func, user_data);
|
||||
}
|
||||
|
||||
gboolean
|
||||
_nm_setting_vpn_aggregate (NMSettingVpn *setting,
|
||||
NMConnectionAggregateType type,
|
||||
gpointer arg)
|
||||
static gboolean
|
||||
aggregate (NMSetting *setting,
|
||||
int type_i,
|
||||
gpointer arg)
|
||||
{
|
||||
NMSettingVpnPrivate *priv;
|
||||
NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (setting);
|
||||
NMConnectionAggregateType type = type_i;
|
||||
NMSettingSecretFlags secret_flags;
|
||||
const char *key_name;
|
||||
GHashTableIter iter;
|
||||
|
||||
g_return_val_if_fail (NM_IS_SETTING_VPN (setting), FALSE);
|
||||
|
||||
priv = NM_SETTING_VPN_GET_PRIVATE (setting);
|
||||
|
||||
switch (type) {
|
||||
|
||||
case NM_CONNECTION_AGGREGATE_ANY_SECRETS:
|
||||
|
|
@ -687,6 +684,57 @@ update_one_secret (NMSetting *setting, const char *key, GVariant *value, GError
|
|||
return success;
|
||||
}
|
||||
|
||||
static void
|
||||
for_each_secret (NMSetting *setting,
|
||||
const char *secret_name,
|
||||
GVariant *val,
|
||||
gboolean remove_non_secrets,
|
||||
_NMConnectionForEachSecretFunc callback,
|
||||
gpointer callback_data,
|
||||
GVariantBuilder *setting_builder)
|
||||
{
|
||||
GVariantBuilder vpn_secrets_builder;
|
||||
GVariantIter vpn_secrets_iter;
|
||||
const char *vpn_secret_name;
|
||||
const char *secret;
|
||||
|
||||
if (!nm_streq (secret_name, NM_SETTING_VPN_SECRETS)) {
|
||||
NM_SETTING_CLASS (nm_setting_vpn_parent_class)->for_each_secret (setting,
|
||||
secret_name,
|
||||
val,
|
||||
remove_non_secrets,
|
||||
callback,
|
||||
callback_data,
|
||||
setting_builder);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_variant_is_of_type (val, G_VARIANT_TYPE ("a{ss}"))) {
|
||||
/* invalid type. Silently ignore the secrets as we cannot find out the
|
||||
* secret-flags. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Iterate through each secret from the VPN dict in the overall secrets dict */
|
||||
g_variant_builder_init (&vpn_secrets_builder, G_VARIANT_TYPE ("a{ss}"));
|
||||
g_variant_iter_init (&vpn_secrets_iter, val);
|
||||
while (g_variant_iter_next (&vpn_secrets_iter, "{&s&s}", &vpn_secret_name, &secret)) {
|
||||
NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
|
||||
|
||||
/* we ignore the return value of get_secret_flags. The function may determine
|
||||
* that this is not a secret, based on having not secret-flags and no secrets.
|
||||
* But we have the secret at hand. We know it would be a valid secret, if we
|
||||
* only add it to the VPN settings. */
|
||||
nm_setting_get_secret_flags (setting, vpn_secret_name, &secret_flags, NULL);
|
||||
|
||||
if (callback (secret_flags, callback_data))
|
||||
g_variant_builder_add (&vpn_secrets_builder, "{ss}", vpn_secret_name, secret);
|
||||
}
|
||||
|
||||
g_variant_builder_add (setting_builder, "{sv}",
|
||||
secret_name, g_variant_builder_end (&vpn_secrets_builder));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
get_secret_flags (NMSetting *setting,
|
||||
const char *secret_name,
|
||||
|
|
@ -979,11 +1027,13 @@ nm_setting_vpn_class_init (NMSettingVpnClass *klass)
|
|||
|
||||
setting_class->verify = verify;
|
||||
setting_class->update_one_secret = update_one_secret;
|
||||
setting_class->for_each_secret = for_each_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;
|
||||
setting_class->aggregate = aggregate;
|
||||
|
||||
/**
|
||||
* NMSettingVpn:service-type:
|
||||
|
|
|
|||
|
|
@ -32,15 +32,6 @@
|
|||
#include "nm-utils-private.h"
|
||||
#include "nm-property-compare.h"
|
||||
|
||||
#include "nm-setting-connection.h"
|
||||
#include "nm-setting-bond.h"
|
||||
#include "nm-setting-bridge.h"
|
||||
#include "nm-setting-bridge-port.h"
|
||||
#include "nm-setting-pppoe.h"
|
||||
#include "nm-setting-team.h"
|
||||
#include "nm-setting-team-port.h"
|
||||
#include "nm-setting-vpn.h"
|
||||
|
||||
/**
|
||||
* SECTION:nm-setting
|
||||
* @short_description: Describes related configuration information
|
||||
|
|
@ -67,7 +58,7 @@ typedef struct {
|
|||
NMSettingPriority priority;
|
||||
} SettingInfo;
|
||||
|
||||
NM_GOBJECT_PROPERTIES_DEFINE_BASE (
|
||||
NM_GOBJECT_PROPERTIES_DEFINE (NMSetting,
|
||||
PROP_NAME,
|
||||
);
|
||||
|
||||
|
|
@ -553,6 +544,35 @@ _nm_setting_class_get_sett_info (NMSettingClass *setting_class)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
void
|
||||
_nm_setting_emit_property_changed (NMSetting *setting)
|
||||
{
|
||||
/* Some settings have "properties" that are not implemented as GObject properties.
|
||||
*
|
||||
* For example:
|
||||
*
|
||||
* - gendata-base settings like NMSettingEthtool. Here properties are just
|
||||
* GVariant values in the gendata hash.
|
||||
*
|
||||
* - NMSettingWireGuard's peers are not backed by a GObject property. Instead
|
||||
* there is C-API to access/modify peers.
|
||||
*
|
||||
* We still want to emit property-changed notifications for such properties,
|
||||
* in particular because NMConnection registers to such signals to re-emit
|
||||
* it as NM_CONNECTION_CHANGED signal. In fact, there are unlikely any other
|
||||
* uses of such a property-changed signal, because generally it doesn't make
|
||||
* too much sense.
|
||||
*
|
||||
* So, instead of adding yet another (artificial) signal "setting-changed",
|
||||
* hijack the "notify" signal and just notify about changes of the "name".
|
||||
* Of course, the "name" doesn't really ever change, because it's tied to
|
||||
* the GObject's type.
|
||||
*/
|
||||
_notify (setting, PROP_NAME);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
gboolean
|
||||
_nm_setting_use_legacy_property (NMSetting *setting,
|
||||
GVariant *connection_dict,
|
||||
|
|
@ -1082,6 +1102,8 @@ duplicate_copy_properties (const NMSettInfoSetting *sett_info,
|
|||
if (sett_info->detail.gendata_info) {
|
||||
GenData *gendata = _gendata_hash (src, FALSE);
|
||||
|
||||
nm_assert (!_gendata_hash (dst, FALSE));
|
||||
|
||||
if ( gendata
|
||||
&& g_hash_table_size (gendata->hash) > 0) {
|
||||
GHashTableIter iter;
|
||||
|
|
@ -1698,6 +1720,27 @@ nm_setting_diff (NMSetting *a,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
enumerate_values (const NMSettInfoProperty *property_info,
|
||||
NMSetting *setting,
|
||||
NMSettingValueIterFn func,
|
||||
gpointer user_data)
|
||||
{
|
||||
GValue value = G_VALUE_INIT;
|
||||
|
||||
if (!property_info->param_spec)
|
||||
return;
|
||||
|
||||
g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (property_info->param_spec));
|
||||
g_object_get_property (G_OBJECT (setting), property_info->param_spec->name, &value);
|
||||
func (setting,
|
||||
property_info->param_spec->name,
|
||||
&value,
|
||||
property_info->param_spec->flags,
|
||||
user_data);
|
||||
g_value_unset (&value);
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_setting_enumerate_values:
|
||||
* @setting: the #NMSetting
|
||||
|
|
@ -1753,50 +1796,24 @@ nm_setting_enumerate_values (NMSetting *setting,
|
|||
}
|
||||
|
||||
for (i = 0; i < sett_info->property_infos_len; i++) {
|
||||
GParamSpec *prop_spec = _nm_sett_info_property_info_get_sorted (sett_info, i)->param_spec;
|
||||
GValue value = G_VALUE_INIT;
|
||||
|
||||
if (!prop_spec)
|
||||
continue;
|
||||
|
||||
g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (prop_spec));
|
||||
g_object_get_property (G_OBJECT (setting), prop_spec->name, &value);
|
||||
func (setting, prop_spec->name, &value, prop_spec->flags, user_data);
|
||||
g_value_unset (&value);
|
||||
NM_SETTING_GET_CLASS (setting)->enumerate_values (_nm_sett_info_property_info_get_sorted (sett_info, i),
|
||||
setting,
|
||||
func,
|
||||
user_data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* _nm_setting_aggregate:
|
||||
* @setting: the #NMSetting to aggregate.
|
||||
* @type: the #NMConnectionAggregateType aggregate type.
|
||||
* @arg: the in/out arguments for aggregation. They depend on @type.
|
||||
*
|
||||
* This is the implementation detail of _nm_connection_aggregate(). It
|
||||
* makes no sense to call this function directly outside of _nm_connection_aggregate().
|
||||
*
|
||||
* Returns: %TRUE if afterwards the aggregation is complete. That means,
|
||||
* the only caller _nm_connection_aggregate() will not visit other settings
|
||||
* after a setting returns %TRUE (indicating that there is nothing further
|
||||
* to aggregate). Note that is very different from the boolean return
|
||||
* argument of _nm_connection_aggregate(), which serves a different purpose.
|
||||
*/
|
||||
gboolean
|
||||
_nm_setting_aggregate (NMSetting *setting,
|
||||
NMConnectionAggregateType type,
|
||||
gpointer arg)
|
||||
static gboolean
|
||||
aggregate (NMSetting *setting,
|
||||
int type_i,
|
||||
gpointer arg)
|
||||
{
|
||||
NMConnectionAggregateType type = type_i;
|
||||
const NMSettInfoSetting *sett_info;
|
||||
guint i;
|
||||
|
||||
g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
|
||||
g_return_val_if_fail (arg, FALSE);
|
||||
g_return_val_if_fail (NM_IN_SET (type, NM_CONNECTION_AGGREGATE_ANY_SECRETS,
|
||||
NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS),
|
||||
FALSE);
|
||||
|
||||
if (NM_IS_SETTING_VPN (setting))
|
||||
return _nm_setting_vpn_aggregate (NM_SETTING_VPN (setting), type, arg);
|
||||
nm_assert (NM_IN_SET (type, NM_CONNECTION_AGGREGATE_ANY_SECRETS,
|
||||
NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS));
|
||||
|
||||
sett_info = _nm_setting_class_get_sett_info (NM_SETTING_GET_CLASS (setting));
|
||||
for (i = 0; i < sett_info->property_infos_len; i++) {
|
||||
|
|
@ -1840,6 +1857,35 @@ _nm_setting_aggregate (NMSetting *setting,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* _nm_setting_aggregate:
|
||||
* @setting: the #NMSetting to aggregate.
|
||||
* @type: the #NMConnectionAggregateType aggregate type.
|
||||
* @arg: the in/out arguments for aggregation. They depend on @type.
|
||||
*
|
||||
* This is the implementation detail of _nm_connection_aggregate(). It
|
||||
* makes no sense to call this function directly outside of _nm_connection_aggregate().
|
||||
*
|
||||
* Returns: %TRUE if afterwards the aggregation is complete. That means,
|
||||
* the only caller _nm_connection_aggregate() will not visit other settings
|
||||
* after a setting returns %TRUE (indicating that there is nothing further
|
||||
* to aggregate). Note that is very different from the boolean return
|
||||
* argument of _nm_connection_aggregate(), which serves a different purpose.
|
||||
*/
|
||||
gboolean
|
||||
_nm_setting_aggregate (NMSetting *setting,
|
||||
NMConnectionAggregateType type,
|
||||
gpointer arg)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
|
||||
g_return_val_if_fail (arg, FALSE);
|
||||
g_return_val_if_fail (NM_IN_SET (type, NM_CONNECTION_AGGREGATE_ANY_SECRETS,
|
||||
NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS),
|
||||
FALSE);
|
||||
|
||||
return NM_SETTING_GET_CLASS (setting)->aggregate (setting, type, arg);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clear_secrets (const NMSettInfoSetting *sett_info,
|
||||
guint property_idx,
|
||||
|
|
@ -2039,6 +2085,26 @@ _nm_setting_update_secrets (NMSetting *setting, GVariant *secrets, GError **erro
|
|||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
for_each_secret (NMSetting *setting,
|
||||
const char *secret_name,
|
||||
GVariant *val,
|
||||
gboolean remove_non_secrets,
|
||||
_NMConnectionForEachSecretFunc callback,
|
||||
gpointer callback_data,
|
||||
GVariantBuilder *setting_builder)
|
||||
{
|
||||
NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
|
||||
|
||||
if (!nm_setting_get_secret_flags (setting, secret_name, &secret_flags, NULL)) {
|
||||
if (!remove_non_secrets)
|
||||
g_variant_builder_add (setting_builder, "{sv}", secret_name, val);
|
||||
return;
|
||||
}
|
||||
if (callback (secret_flags, callback_data))
|
||||
g_variant_builder_add (setting_builder, "{sv}", secret_name, val);
|
||||
}
|
||||
|
||||
static void
|
||||
_set_error_secret_property_not_found (GError **error,
|
||||
NMSetting *setting,
|
||||
|
|
@ -2293,7 +2359,7 @@ _nm_setting_gendata_notify (NMSetting *setting,
|
|||
|
||||
gendata = _gendata_hash (setting, FALSE);
|
||||
if (!gendata)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
nm_clear_g_free (&gendata->values);
|
||||
|
||||
|
|
@ -2303,7 +2369,7 @@ _nm_setting_gendata_notify (NMSetting *setting,
|
|||
nm_clear_g_free (&gendata->names);
|
||||
}
|
||||
|
||||
/* Note, that currently there is now way to notify the subclass when gendata changed.
|
||||
/* Note, currently there is no way to notify the subclass when gendata changed.
|
||||
* gendata is only changed in two situations:
|
||||
* 1) from within NMSetting itself, for example when creating a NMSetting instance
|
||||
* from keyfile or a D-Bus GVariant.
|
||||
|
|
@ -2316,6 +2382,9 @@ _nm_setting_gendata_notify (NMSetting *setting,
|
|||
*
|
||||
* If we ever need it, then we would need to call a virtual function to notify the subclass
|
||||
* that gendata changed. */
|
||||
|
||||
out:
|
||||
_nm_setting_emit_property_changed (setting);
|
||||
}
|
||||
|
||||
GVariant *
|
||||
|
|
@ -2438,7 +2507,7 @@ nm_setting_gendata_get_all_values (NMSetting *setting)
|
|||
|
||||
void
|
||||
_nm_setting_gendata_to_gvalue (NMSetting *setting,
|
||||
GValue *value)
|
||||
GValue *value)
|
||||
{
|
||||
GenData *gendata;
|
||||
GHashTable *new;
|
||||
|
|
@ -2571,7 +2640,10 @@ nm_setting_class_init (NMSettingClass *setting_class)
|
|||
setting_class->set_secret_flags = set_secret_flags;
|
||||
setting_class->compare_property = compare_property;
|
||||
setting_class->clear_secrets = clear_secrets;
|
||||
setting_class->for_each_secret = for_each_secret;
|
||||
setting_class->duplicate_copy_properties = duplicate_copy_properties;
|
||||
setting_class->enumerate_values = enumerate_values;
|
||||
setting_class->aggregate = aggregate;
|
||||
|
||||
/**
|
||||
* NMSetting:name:
|
||||
|
|
|
|||
|
|
@ -170,6 +170,26 @@ typedef gboolean (*NMSettingClearSecretsWithFlagsFn) (NMSetting *setting,
|
|||
|
||||
struct _NMMetaSettingInfo;
|
||||
struct _NMSettInfoSetting;
|
||||
struct _NMSettInfoProperty;
|
||||
|
||||
/**
|
||||
* NMSettingValueIterFn:
|
||||
* @setting: The setting for which properties are being iterated, given to
|
||||
* nm_setting_enumerate_values()
|
||||
* @key: The value/property name
|
||||
* @value: The property's value
|
||||
* @flags: The property's flags, like %NM_SETTING_PARAM_SECRET
|
||||
* @user_data: User data passed to nm_setting_enumerate_values()
|
||||
*/
|
||||
typedef void (*NMSettingValueIterFn) (NMSetting *setting,
|
||||
const char *key,
|
||||
const GValue *value,
|
||||
GParamFlags flags,
|
||||
gpointer user_data);
|
||||
|
||||
/*< private >*/
|
||||
typedef gboolean (*_NMConnectionForEachSecretFunc) (NMSettingSecretFlags flags,
|
||||
gpointer user_data);
|
||||
|
||||
typedef struct {
|
||||
GObjectClass parent;
|
||||
|
|
@ -226,26 +246,31 @@ typedef struct {
|
|||
NMSetting *dst);
|
||||
|
||||
/*< private >*/
|
||||
const struct _NMMetaSettingInfo *setting_info;
|
||||
void (*enumerate_values) (const struct _NMSettInfoProperty *property_info,
|
||||
NMSetting *setting,
|
||||
NMSettingValueIterFn func,
|
||||
gpointer user_data);
|
||||
|
||||
/*< private >*/
|
||||
gpointer padding[5];
|
||||
} NMSettingClass;
|
||||
gboolean (*aggregate) (NMSetting *setting,
|
||||
int type_i,
|
||||
gpointer arg);
|
||||
|
||||
/**
|
||||
* NMSettingValueIterFn:
|
||||
* @setting: The setting for which properties are being iterated, given to
|
||||
* nm_setting_enumerate_values()
|
||||
* @key: The value/property name
|
||||
* @value: The property's value
|
||||
* @flags: The property's flags, like %NM_SETTING_PARAM_SECRET
|
||||
* @user_data: User data passed to nm_setting_enumerate_values()
|
||||
*/
|
||||
typedef void (*NMSettingValueIterFn) (NMSetting *setting,
|
||||
const char *key,
|
||||
const GValue *value,
|
||||
GParamFlags flags,
|
||||
gpointer user_data);
|
||||
/*< private >*/
|
||||
void (*for_each_secret) (NMSetting *setting,
|
||||
const char *secret_name,
|
||||
GVariant *val,
|
||||
gboolean remove_non_secrets,
|
||||
_NMConnectionForEachSecretFunc callback,
|
||||
gpointer callback_data,
|
||||
GVariantBuilder *setting_builder);
|
||||
|
||||
/*< private >*/
|
||||
gpointer padding[2];
|
||||
|
||||
/*< private >*/
|
||||
const struct _NMMetaSettingInfo *setting_info;
|
||||
} NMSettingClass;
|
||||
|
||||
GType nm_setting_get_type (void);
|
||||
|
||||
|
|
|
|||
|
|
@ -208,141 +208,6 @@ nm_settings_connection_get_last_secret_agent_version_id (NMSettingsConnection *s
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Return TRUE to keep, FALSE to drop */
|
||||
typedef gboolean (*ForEachSecretFunc) (NMSettingSecretFlags flags,
|
||||
gpointer user_data);
|
||||
|
||||
/* Returns always a non-NULL, non-floating variant that must
|
||||
* be unrefed by the caller. */
|
||||
static GVariant *
|
||||
for_each_secret (NMConnection *self,
|
||||
GVariant *secrets,
|
||||
gboolean remove_non_secrets,
|
||||
ForEachSecretFunc callback,
|
||||
gpointer callback_data)
|
||||
{
|
||||
GVariantBuilder secrets_builder, setting_builder;
|
||||
GVariantIter secrets_iter, *setting_iter;
|
||||
const char *setting_name;
|
||||
|
||||
/* This function, given a dict of dicts representing new secrets of
|
||||
* an NMConnection, walks through each toplevel dict (which represents a
|
||||
* NMSetting), and for each setting, walks through that setting dict's
|
||||
* properties. For each property that's a secret, it will check that
|
||||
* secret's flags in the backing NMConnection object, and call a supplied
|
||||
* callback.
|
||||
*
|
||||
* The one complexity is that the VPN setting's 'secrets' property is
|
||||
* *also* a dict (since the key/value pairs are arbitrary and known
|
||||
* only to the VPN plugin itself). That means we have three levels of
|
||||
* dicts that we potentially have to traverse here. When we hit the
|
||||
* VPN setting's 'secrets' property, we special-case that and iterate over
|
||||
* each item in that 'secrets' dict, calling the supplied callback
|
||||
* each time.
|
||||
*/
|
||||
|
||||
g_return_val_if_fail (callback, NULL);
|
||||
|
||||
g_variant_iter_init (&secrets_iter, secrets);
|
||||
g_variant_builder_init (&secrets_builder, NM_VARIANT_TYPE_CONNECTION);
|
||||
while (g_variant_iter_next (&secrets_iter, "{&sa{sv}}", &setting_name, &setting_iter)) {
|
||||
NMSetting *setting;
|
||||
const char *secret_name;
|
||||
GVariant *val;
|
||||
|
||||
setting = nm_connection_get_setting_by_name (self, setting_name);
|
||||
if (setting == NULL) {
|
||||
g_variant_iter_free (setting_iter);
|
||||
continue;
|
||||
}
|
||||
|
||||
g_variant_builder_init (&setting_builder, NM_VARIANT_TYPE_SETTING);
|
||||
while (g_variant_iter_next (setting_iter, "{&sv}", &secret_name, &val)) {
|
||||
NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
|
||||
|
||||
/* VPN secrets need slightly different treatment here since the
|
||||
* "secrets" property is actually a hash table of secrets.
|
||||
*/
|
||||
if (NM_IS_SETTING_VPN (setting) && !g_strcmp0 (secret_name, NM_SETTING_VPN_SECRETS)) {
|
||||
GVariantBuilder vpn_secrets_builder;
|
||||
GVariantIter vpn_secrets_iter;
|
||||
const char *vpn_secret_name, *secret;
|
||||
|
||||
/* Iterate through each secret from the VPN dict in the overall secrets dict */
|
||||
g_variant_builder_init (&vpn_secrets_builder, G_VARIANT_TYPE ("a{ss}"));
|
||||
g_variant_iter_init (&vpn_secrets_iter, val);
|
||||
while (g_variant_iter_next (&vpn_secrets_iter, "{&s&s}", &vpn_secret_name, &secret)) {
|
||||
if (!nm_setting_get_secret_flags (setting, vpn_secret_name, &secret_flags, NULL)) {
|
||||
if (!remove_non_secrets)
|
||||
g_variant_builder_add (&vpn_secrets_builder, "{ss}", vpn_secret_name, secret);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (callback (secret_flags, callback_data))
|
||||
g_variant_builder_add (&vpn_secrets_builder, "{ss}", vpn_secret_name, secret);
|
||||
}
|
||||
|
||||
g_variant_builder_add (&setting_builder, "{sv}",
|
||||
secret_name, g_variant_builder_end (&vpn_secrets_builder));
|
||||
} else {
|
||||
if (!nm_setting_get_secret_flags (setting, secret_name, &secret_flags, NULL)) {
|
||||
if (!remove_non_secrets)
|
||||
g_variant_builder_add (&setting_builder, "{sv}", secret_name, val);
|
||||
continue;
|
||||
}
|
||||
if (callback (secret_flags, callback_data))
|
||||
g_variant_builder_add (&setting_builder, "{sv}", secret_name, val);
|
||||
}
|
||||
g_variant_unref (val);
|
||||
}
|
||||
|
||||
g_variant_iter_free (setting_iter);
|
||||
g_variant_builder_add (&secrets_builder, "{sa{sv}}", setting_name, &setting_builder);
|
||||
}
|
||||
|
||||
return g_variant_ref_sink (g_variant_builder_end (&secrets_builder));
|
||||
}
|
||||
|
||||
typedef gboolean (*FindSecretFunc) (NMSettingSecretFlags flags,
|
||||
gpointer user_data);
|
||||
|
||||
typedef struct {
|
||||
FindSecretFunc find_func;
|
||||
gpointer find_func_data;
|
||||
gboolean found;
|
||||
} FindSecretData;
|
||||
|
||||
static gboolean
|
||||
find_secret_for_each_func (NMSettingSecretFlags flags,
|
||||
gpointer user_data)
|
||||
{
|
||||
FindSecretData *data = user_data;
|
||||
|
||||
if (!data->found)
|
||||
data->found = data->find_func (flags, data->find_func_data);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
find_secret (NMConnection *self,
|
||||
GVariant *secrets,
|
||||
FindSecretFunc callback,
|
||||
gpointer callback_data)
|
||||
{
|
||||
FindSecretData data;
|
||||
GVariant *dummy;
|
||||
|
||||
data.find_func = callback;
|
||||
data.find_func_data = callback_data;
|
||||
data.found = FALSE;
|
||||
|
||||
dummy = for_each_secret (self, secrets, FALSE, find_secret_for_each_func, &data);
|
||||
g_variant_unref (dummy);
|
||||
return data.found;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
set_visible (NMSettingsConnection *self, gboolean new_visible)
|
||||
{
|
||||
|
|
@ -938,8 +803,8 @@ typedef struct {
|
|||
} ForEachSecretFlags;
|
||||
|
||||
static gboolean
|
||||
validate_secret_flags (NMSettingSecretFlags flags,
|
||||
gpointer user_data)
|
||||
validate_secret_flags_cb (NMSettingSecretFlags flags,
|
||||
gpointer user_data)
|
||||
{
|
||||
ForEachSecretFlags *cmp_flags = user_data;
|
||||
|
||||
|
|
@ -950,6 +815,18 @@ validate_secret_flags (NMSettingSecretFlags flags,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static GVariant *
|
||||
validate_secret_flags (NMConnection *connection,
|
||||
GVariant *secrets,
|
||||
ForEachSecretFlags *cmp_flags)
|
||||
{
|
||||
return g_variant_ref_sink (_nm_connection_for_each_secret (connection,
|
||||
secrets,
|
||||
TRUE,
|
||||
validate_secret_flags_cb,
|
||||
cmp_flags));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
secret_is_system_owned (NMSettingSecretFlags flags,
|
||||
gpointer user_data)
|
||||
|
|
@ -992,7 +869,7 @@ get_cmp_flags (NMSettingsConnection *self, /* only needed for logging */
|
|||
* save those system-owned secrets. If not, discard them and use the
|
||||
* existing secrets, or fail the connection.
|
||||
*/
|
||||
*agent_had_system = find_secret (connection, secrets, secret_is_system_owned, NULL);
|
||||
*agent_had_system = _nm_connection_find_secret (connection, secrets, secret_is_system_owned, NULL);
|
||||
if (*agent_had_system) {
|
||||
if (flags == NM_SECRET_AGENT_GET_SECRETS_FLAG_NONE) {
|
||||
/* No user interaction was allowed when requesting secrets; the
|
||||
|
|
@ -1151,14 +1028,14 @@ get_secrets_done_cb (NMAgentManager *manager,
|
|||
/* Update the connection with our existing secrets from backing storage */
|
||||
nm_connection_clear_secrets (nm_settings_connection_get_connection (self));
|
||||
if (!dict || nm_connection_update_secrets (nm_settings_connection_get_connection (self), setting_name, dict, &local)) {
|
||||
GVariant *filtered_secrets;
|
||||
gs_unref_variant GVariant *filtered_secrets = NULL;
|
||||
|
||||
/* Update the connection with the agent's secrets; by this point if any
|
||||
* system-owned secrets exist in 'secrets' the agent that provided them
|
||||
* will have been authenticated, so those secrets can replace the existing
|
||||
* system secrets.
|
||||
*/
|
||||
filtered_secrets = for_each_secret (nm_settings_connection_get_connection (self), secrets, TRUE, validate_secret_flags, &cmp_flags);
|
||||
filtered_secrets = validate_secret_flags (nm_settings_connection_get_connection (self), secrets, &cmp_flags);
|
||||
if (nm_connection_update_secrets (nm_settings_connection_get_connection (self), setting_name, filtered_secrets, &local)) {
|
||||
/* Now that all secrets are updated, copy and cache new secrets,
|
||||
* then save them to backing storage.
|
||||
|
|
@ -1194,7 +1071,6 @@ get_secrets_done_cb (NMAgentManager *manager,
|
|||
call_id,
|
||||
local->message);
|
||||
}
|
||||
g_variant_unref (filtered_secrets);
|
||||
} else {
|
||||
_LOGD ("(%s:%p) failed to update with existing secrets: %s",
|
||||
setting_name,
|
||||
|
|
@ -1218,11 +1094,10 @@ get_secrets_done_cb (NMAgentManager *manager,
|
|||
nm_connection_clear_secrets (applied_connection);
|
||||
|
||||
if (!dict || nm_connection_update_secrets (applied_connection, setting_name, dict, NULL)) {
|
||||
GVariant *filtered_secrets;
|
||||
gs_unref_variant GVariant *filtered_secrets = NULL;
|
||||
|
||||
filtered_secrets = for_each_secret (applied_connection, secrets, TRUE, validate_secret_flags, &cmp_flags);
|
||||
filtered_secrets = validate_secret_flags (applied_connection, secrets, &cmp_flags);
|
||||
nm_connection_update_secrets (applied_connection, setting_name, filtered_secrets, NULL);
|
||||
g_variant_unref (filtered_secrets);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue