2014-07-24 08:53:33 -04:00
|
|
|
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
|
* License along with this library; if not, write to the
|
|
|
|
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
|
* Boston, MA 02110-1301 USA.
|
|
|
|
|
*
|
|
|
|
|
* Copyright 2007 - 2011 Red Hat, Inc.
|
|
|
|
|
* Copyright 2007 - 2008 Novell, Inc.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <glib/gi18n.h>
|
2014-08-16 10:09:48 -04:00
|
|
|
#include <gio/gio.h>
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
#include "nm-setting.h"
|
|
|
|
|
#include "nm-setting-private.h"
|
|
|
|
|
#include "nm-setting-connection.h"
|
|
|
|
|
#include "nm-utils.h"
|
2014-02-25 20:30:27 +01:00
|
|
|
#include "nm-core-internal.h"
|
2014-07-24 08:53:33 -04:00
|
|
|
#include "nm-utils-private.h"
|
2014-07-29 09:22:07 -04:00
|
|
|
#include "nm-property-compare.h"
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* SECTION:nm-setting
|
|
|
|
|
* @short_description: Describes related configuration information
|
|
|
|
|
*
|
|
|
|
|
* Each #NMSetting contains properties that describe configuration that applies
|
|
|
|
|
* to a specific network layer (like IPv4 or IPv6 configuration) or device type
|
|
|
|
|
* (like Ethernet, or Wi-Fi). A collection of individual settings together
|
|
|
|
|
* make up an #NMConnection. Each property is strongly typed and usually has
|
|
|
|
|
* a number of allowed values. See each #NMSetting subclass for a description
|
|
|
|
|
* of properties and allowed values.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
G_DEFINE_ABSTRACT_TYPE (NMSetting, nm_setting, G_TYPE_OBJECT)
|
|
|
|
|
|
|
|
|
|
#define NM_SETTING_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING, NMSettingPrivate))
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
const char *name;
|
|
|
|
|
GType type;
|
|
|
|
|
guint32 priority;
|
|
|
|
|
} SettingInfo;
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
const SettingInfo *info;
|
|
|
|
|
} NMSettingPrivate;
|
|
|
|
|
|
|
|
|
|
enum {
|
|
|
|
|
PROP_0,
|
|
|
|
|
PROP_NAME,
|
|
|
|
|
|
|
|
|
|
PROP_LAST
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*************************************************************/
|
|
|
|
|
|
|
|
|
|
static GHashTable *registered_settings = NULL;
|
|
|
|
|
static GHashTable *registered_settings_by_type = NULL;
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
_nm_gtype_equal (gconstpointer v1, gconstpointer v2)
|
|
|
|
|
{
|
|
|
|
|
return *((const GType *) v1) == *((const GType *) v2);
|
|
|
|
|
}
|
|
|
|
|
static guint
|
|
|
|
|
_nm_gtype_hash (gconstpointer v)
|
|
|
|
|
{
|
|
|
|
|
return *((const GType *) v);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __attribute__((constructor))
|
|
|
|
|
_ensure_registered (void)
|
|
|
|
|
{
|
|
|
|
|
if (G_UNLIKELY (registered_settings == NULL)) {
|
|
|
|
|
#if !GLIB_CHECK_VERSION (2, 35, 0)
|
|
|
|
|
g_type_init ();
|
|
|
|
|
#endif
|
|
|
|
|
registered_settings = g_hash_table_new (g_str_hash, g_str_equal);
|
|
|
|
|
registered_settings_by_type = g_hash_table_new (_nm_gtype_hash, _nm_gtype_equal);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define _ensure_setting_info(self, priv) \
|
|
|
|
|
G_STMT_START { \
|
|
|
|
|
NMSettingPrivate *_priv_esi = (priv); \
|
|
|
|
|
if (G_UNLIKELY (!_priv_esi->info)) { \
|
|
|
|
|
_priv_esi->info = _nm_setting_lookup_setting_by_type (G_OBJECT_TYPE (self)); \
|
|
|
|
|
g_assert (_priv_esi->info); \
|
|
|
|
|
} \
|
|
|
|
|
} G_STMT_END
|
|
|
|
|
|
|
|
|
|
/*************************************************************/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* _nm_register_setting:
|
|
|
|
|
* @name: the name of the #NMSetting object to register
|
|
|
|
|
* @type: the #GType of the #NMSetting
|
|
|
|
|
* @priority: the sort priority of the setting, see below
|
|
|
|
|
*
|
libnm-core: merge NMSetting*Error into NMConnectionError
Each setting type was defining its own error type, but most of them
had exactly the same three errors ("unknown", "missing property", and
"invalid property"), and none of the other values was of much use
programmatically anyway.
So, this commit merges NMSettingError, NMSettingAdslError, etc, all
into NMConnectionError. (The reason for merging into NMConnectionError
rather than NMSettingError is that we also already have
"NMSettingsError", for errors related to the settings service, so
"NMConnectionError" is a less-confusable name for settings/connection
errors than "NMSettingError".)
Also, make sure that all of the affected error messages are localized,
and (where appropriate) prefix them with the relevant property name.
Renamed error codes:
NM_SETTING_ERROR_PROPERTY_NOT_FOUND -> NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND
NM_SETTING_ERROR_PROPERTY_NOT_SECRET -> NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET
Remapped error codes:
NM_SETTING_*_ERROR_MISSING_PROPERTY -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_*_ERROR_INVALID_PROPERTY -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BLUETOOTH_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_INVALID_SETTING
NM_SETTING_BOND_ERROR_INVALID_OPTION -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BOND_ERROR_MISSING_OPTION -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_CONNECTION_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_CONNECTION_ERROR_SLAVE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_IP4_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_VLAN_ERROR_INVALID_PARENT -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_MISSING_802_1X_SETTING -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_802_1X -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_SHARED_KEY_REQUIRES_WEP -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_ERROR_CHANNEL_REQUIRES_BAND -> NM_CONNECTION_ERROR_MISSING_PROPERTY
Dropped error codes (were previously defined but unused):
NM_SETTING_CDMA_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_CONNECTION_ERROR_IP_CONFIG_NOT_ALLOWED
NM_SETTING_GSM_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_PPP_ERROR_REQUIRE_MPPE_NOT_ALLOWED
NM_SETTING_PPPOE_ERROR_MISSING_PPP_SETTING
NM_SETTING_SERIAL_ERROR_MISSING_PPP_SETTING
NM_SETTING_WIRELESS_ERROR_MISSING_SECURITY_SETTING
2014-10-20 13:52:23 -04:00
|
|
|
* INTERNAL ONLY: registers a setting's internal properties with libnm.
|
2014-07-24 08:53:33 -04:00
|
|
|
*
|
|
|
|
|
* A setting's priority should roughly follow the OSI layer model, but it also
|
|
|
|
|
* controls which settings get asked for secrets first. Thus settings which
|
|
|
|
|
* relate to things that must be working first, like hardware, should get a
|
|
|
|
|
* higher priority than things which layer on top of the hardware. For example,
|
|
|
|
|
* the GSM/CDMA settings should provide secrets before the PPP setting does,
|
|
|
|
|
* because a PIN is required to unlock the device before PPP can even start.
|
|
|
|
|
* Even settings without secrets should be assigned the right priority.
|
|
|
|
|
*
|
|
|
|
|
* 0: reserved for the Connection setting
|
|
|
|
|
*
|
|
|
|
|
* 1: hardware-related settings like Ethernet, Wi-Fi, InfiniBand, Bridge, etc.
|
|
|
|
|
* These priority 1 settings are also "base types", which means that at least
|
|
|
|
|
* one of them is required for the connection to be valid, and their name is
|
|
|
|
|
* valid in the 'type' property of the Connection setting.
|
|
|
|
|
*
|
|
|
|
|
* 2: hardware-related auxiliary settings that require a base setting to be
|
|
|
|
|
* successful first, like Wi-Fi security, 802.1x, etc.
|
|
|
|
|
*
|
|
|
|
|
* 3: hardware-independent settings that are required before IP connectivity
|
|
|
|
|
* can be established, like PPP, PPPoE, etc.
|
|
|
|
|
*
|
|
|
|
|
* 4: IP-level stuff
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
(_nm_register_setting) (const char *name,
|
|
|
|
|
const GType type,
|
2014-10-13 11:57:35 -04:00
|
|
|
const guint32 priority)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
|
|
|
|
SettingInfo *info;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (name != NULL && *name);
|
|
|
|
|
g_return_if_fail (type != G_TYPE_INVALID);
|
|
|
|
|
g_return_if_fail (type != G_TYPE_NONE);
|
|
|
|
|
g_return_if_fail (priority <= 4);
|
|
|
|
|
|
|
|
|
|
_ensure_registered ();
|
|
|
|
|
|
|
|
|
|
if (G_LIKELY ((info = g_hash_table_lookup (registered_settings, name)))) {
|
|
|
|
|
g_return_if_fail (info->type == type);
|
|
|
|
|
g_return_if_fail (info->priority == priority);
|
|
|
|
|
g_return_if_fail (g_strcmp0 (info->name, name) == 0);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
g_return_if_fail (g_hash_table_lookup (registered_settings_by_type, &type) == NULL);
|
|
|
|
|
|
|
|
|
|
if (priority == 0)
|
|
|
|
|
g_assert_cmpstr (name, ==, NM_SETTING_CONNECTION_SETTING_NAME);
|
|
|
|
|
|
|
|
|
|
info = g_slice_new0 (SettingInfo);
|
|
|
|
|
info->type = type;
|
|
|
|
|
info->priority = priority;
|
|
|
|
|
info->name = name;
|
|
|
|
|
g_hash_table_insert (registered_settings, (void *) info->name, info);
|
|
|
|
|
g_hash_table_insert (registered_settings_by_type, &info->type, info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const SettingInfo *
|
|
|
|
|
_nm_setting_lookup_setting_by_type (GType type)
|
|
|
|
|
{
|
|
|
|
|
_ensure_registered ();
|
|
|
|
|
return g_hash_table_lookup (registered_settings_by_type, &type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static guint32
|
|
|
|
|
_get_setting_type_priority (GType type)
|
|
|
|
|
{
|
|
|
|
|
const SettingInfo *info;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (g_type_is_a (type, NM_TYPE_SETTING), G_MAXUINT32);
|
|
|
|
|
|
|
|
|
|
info = _nm_setting_lookup_setting_by_type (type);
|
|
|
|
|
return info->priority;
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-25 20:30:27 +01:00
|
|
|
guint32
|
|
|
|
|
_nm_setting_get_setting_priority (NMSetting *setting)
|
|
|
|
|
{
|
|
|
|
|
NMSettingPrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_SETTING (setting), G_MAXUINT32);
|
|
|
|
|
priv = NM_SETTING_GET_PRIVATE (setting);
|
|
|
|
|
_ensure_setting_info (setting, priv);
|
|
|
|
|
return priv->info->priority;
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
gboolean
|
|
|
|
|
_nm_setting_type_is_base_type (GType type)
|
|
|
|
|
{
|
|
|
|
|
/* Historical oddity: PPPoE is a base-type even though it's not
|
|
|
|
|
* priority 1. It needs to be sorted *after* lower-level stuff like
|
|
|
|
|
* Wi-Fi security or 802.1x for secrets, but it's still allowed as a
|
|
|
|
|
* base type.
|
|
|
|
|
*/
|
|
|
|
|
return _get_setting_type_priority (type) == 1 || (type == NM_TYPE_SETTING_PPPOE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
_nm_setting_is_base_type (NMSetting *setting)
|
|
|
|
|
{
|
|
|
|
|
return _nm_setting_type_is_base_type (G_OBJECT_TYPE (setting));
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-12 17:25:26 -04:00
|
|
|
/**
|
|
|
|
|
* nm_setting_lookup_type:
|
|
|
|
|
* @name: a setting name
|
|
|
|
|
*
|
|
|
|
|
* Returns the #GType of the setting's class for a given setting name.
|
|
|
|
|
*
|
2014-08-22 10:20:29 -04:00
|
|
|
* Returns: the #GType of the setting's class, or %G_TYPE_INVALID if
|
|
|
|
|
* @name is not recognized.
|
2014-08-12 17:25:26 -04:00
|
|
|
**/
|
2014-07-24 08:53:33 -04:00
|
|
|
GType
|
2014-08-12 17:25:26 -04:00
|
|
|
nm_setting_lookup_type (const char *name)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
|
|
|
|
SettingInfo *info;
|
|
|
|
|
|
2014-08-22 10:20:29 -04:00
|
|
|
g_return_val_if_fail (name != NULL, G_TYPE_INVALID);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
_ensure_registered ();
|
|
|
|
|
|
|
|
|
|
info = g_hash_table_lookup (registered_settings, name);
|
|
|
|
|
return info ? info->type : G_TYPE_INVALID;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gint
|
|
|
|
|
_nm_setting_compare_priority (gconstpointer a, gconstpointer b)
|
|
|
|
|
{
|
|
|
|
|
guint32 prio_a, prio_b;
|
|
|
|
|
|
2014-02-25 20:30:27 +01:00
|
|
|
prio_a = _nm_setting_get_setting_priority ((NMSetting *) a);
|
|
|
|
|
prio_b = _nm_setting_get_setting_priority ((NMSetting *) b);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
if (prio_a < prio_b)
|
|
|
|
|
return -1;
|
|
|
|
|
else if (prio_a == prio_b)
|
|
|
|
|
return 0;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*************************************************************/
|
|
|
|
|
|
2014-07-07 17:05:10 +02:00
|
|
|
gboolean
|
|
|
|
|
_nm_setting_slave_type_is_valid (const char *slave_type, const char **out_port_type)
|
|
|
|
|
{
|
|
|
|
|
const char *port_type = NULL;
|
|
|
|
|
gboolean found = TRUE;
|
|
|
|
|
|
|
|
|
|
if (!slave_type)
|
|
|
|
|
found = FALSE;
|
|
|
|
|
else if (!strcmp (slave_type, NM_SETTING_BOND_SETTING_NAME))
|
|
|
|
|
;
|
|
|
|
|
else if (!strcmp (slave_type, NM_SETTING_BRIDGE_SETTING_NAME))
|
|
|
|
|
port_type = NM_SETTING_BRIDGE_PORT_SETTING_NAME;
|
|
|
|
|
else if (!strcmp (slave_type, NM_SETTING_TEAM_SETTING_NAME))
|
|
|
|
|
port_type = NM_SETTING_TEAM_PORT_SETTING_NAME;
|
|
|
|
|
else
|
|
|
|
|
found = FALSE;
|
|
|
|
|
|
|
|
|
|
if (out_port_type)
|
|
|
|
|
*out_port_type = port_type;
|
|
|
|
|
return found;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2014-07-08 18:36:02 +02:00
|
|
|
NMSetting *
|
|
|
|
|
_nm_setting_find_in_list_base_type (GSList *all_settings)
|
|
|
|
|
{
|
|
|
|
|
GSList *iter;
|
|
|
|
|
NMSetting *setting = NULL;
|
|
|
|
|
|
|
|
|
|
for (iter = all_settings; iter; iter = iter->next) {
|
|
|
|
|
NMSetting *s_iter = NM_SETTING (iter->data);
|
|
|
|
|
|
|
|
|
|
if (!_nm_setting_is_base_type (s_iter))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (setting) {
|
|
|
|
|
/* FIXME: currently, if there is more than one matching base type,
|
|
|
|
|
* we cannot detect the base setting.
|
|
|
|
|
* See: https://bugzilla.gnome.org/show_bug.cgi?id=696936#c8 */
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
setting = s_iter;
|
|
|
|
|
}
|
|
|
|
|
return setting;
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-07 17:05:10 +02:00
|
|
|
const char *
|
|
|
|
|
_nm_setting_slave_type_detect_from_settings (GSList *all_settings, NMSetting **out_s_port)
|
|
|
|
|
{
|
|
|
|
|
GSList *iter;
|
|
|
|
|
const char *slave_type = NULL;
|
|
|
|
|
NMSetting *s_port = NULL;
|
|
|
|
|
|
|
|
|
|
for (iter = all_settings; iter; iter = iter->next) {
|
|
|
|
|
NMSetting *s_iter = NM_SETTING (iter->data);
|
|
|
|
|
const char *name = nm_setting_get_name (s_iter);
|
|
|
|
|
const char *i_slave_type = NULL;
|
|
|
|
|
|
|
|
|
|
if (!strcmp (name, NM_SETTING_BRIDGE_PORT_SETTING_NAME))
|
|
|
|
|
i_slave_type = NM_SETTING_BRIDGE_SETTING_NAME;
|
|
|
|
|
else if (!strcmp (name, NM_SETTING_TEAM_PORT_SETTING_NAME))
|
|
|
|
|
i_slave_type = NM_SETTING_TEAM_SETTING_NAME;
|
|
|
|
|
else
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (slave_type) {
|
|
|
|
|
/* there are more then one matching port types, cannot detect the slave type. */
|
|
|
|
|
slave_type = NULL;
|
|
|
|
|
s_port = NULL;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
slave_type = i_slave_type;
|
|
|
|
|
s_port = s_iter;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (out_s_port)
|
|
|
|
|
*out_s_port = s_port;
|
|
|
|
|
return slave_type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*************************************************************/
|
|
|
|
|
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
typedef struct {
|
|
|
|
|
const char *name;
|
|
|
|
|
GParamSpec *param_spec;
|
2014-08-16 10:09:48 -04:00
|
|
|
const GVariantType *dbus_type;
|
2014-07-30 10:46:24 -04:00
|
|
|
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
NMSettingPropertyGetFunc get_func;
|
|
|
|
|
NMSettingPropertySetFunc set_func;
|
2014-07-29 18:25:10 -04:00
|
|
|
NMSettingPropertyNotSetFunc not_set_func;
|
2014-07-30 10:46:24 -04:00
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
NMSettingPropertyTransformToFunc to_dbus;
|
|
|
|
|
NMSettingPropertyTransformFromFunc from_dbus;
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
} NMSettingProperty;
|
|
|
|
|
|
|
|
|
|
static GQuark setting_property_overrides_quark;
|
|
|
|
|
static GQuark setting_properties_quark;
|
|
|
|
|
|
|
|
|
|
static NMSettingProperty *
|
|
|
|
|
find_property (GArray *properties, const char *name)
|
|
|
|
|
{
|
|
|
|
|
NMSettingProperty *property;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (!properties)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < properties->len; i++) {
|
|
|
|
|
property = &g_array_index (properties, NMSettingProperty, i);
|
|
|
|
|
if (strcmp (name, property->name) == 0)
|
|
|
|
|
return property;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
add_property_override (NMSettingClass *setting_class,
|
|
|
|
|
const char *property_name,
|
2014-07-29 18:25:10 -04:00
|
|
|
GParamSpec *param_spec,
|
2014-08-16 10:09:48 -04:00
|
|
|
const GVariantType *dbus_type,
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
NMSettingPropertyGetFunc get_func,
|
2014-07-29 18:25:10 -04:00
|
|
|
NMSettingPropertySetFunc set_func,
|
2014-07-30 10:46:24 -04:00
|
|
|
NMSettingPropertyNotSetFunc not_set_func,
|
2014-08-16 10:09:48 -04:00
|
|
|
NMSettingPropertyTransformToFunc to_dbus,
|
|
|
|
|
NMSettingPropertyTransformFromFunc from_dbus)
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
{
|
|
|
|
|
GType setting_type = G_TYPE_FROM_CLASS (setting_class);
|
|
|
|
|
GArray *overrides;
|
|
|
|
|
NMSettingProperty override;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (g_type_get_qdata (setting_type, setting_properties_quark) == NULL);
|
|
|
|
|
|
|
|
|
|
memset (&override, 0, sizeof (override));
|
|
|
|
|
override.name = property_name;
|
2014-07-29 18:25:10 -04:00
|
|
|
override.param_spec = param_spec;
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
override.dbus_type = dbus_type;
|
|
|
|
|
override.get_func = get_func;
|
|
|
|
|
override.set_func = set_func;
|
2014-07-29 18:25:10 -04:00
|
|
|
override.not_set_func = not_set_func;
|
2014-07-30 10:46:24 -04:00
|
|
|
override.to_dbus = to_dbus;
|
|
|
|
|
override.from_dbus = from_dbus;
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
|
|
|
|
|
overrides = g_type_get_qdata (setting_type, setting_property_overrides_quark);
|
|
|
|
|
if (!overrides) {
|
|
|
|
|
overrides = g_array_new (FALSE, FALSE, sizeof (NMSettingProperty));
|
|
|
|
|
g_type_set_qdata (setting_type, setting_property_overrides_quark, overrides);
|
|
|
|
|
}
|
|
|
|
|
g_return_if_fail (find_property (overrides, property_name) == NULL);
|
|
|
|
|
|
|
|
|
|
g_array_append_val (overrides, override);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* _nm_setting_class_add_dbus_only_property:
|
|
|
|
|
* @setting_class: the setting class
|
|
|
|
|
* @property_name: the name of the property to override
|
2014-08-16 10:09:48 -04:00
|
|
|
* @dbus_type: the type of the property (in its D-Bus representation)
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
* @get_func: (allow-none): function to call to get the value of the property
|
|
|
|
|
* @set_func: (allow-none): function to call to set the value of the property
|
|
|
|
|
*
|
|
|
|
|
* Registers a property named @property_name, which will be used in the D-Bus
|
|
|
|
|
* serialization of objects of @setting_class, but which does not correspond to
|
|
|
|
|
* a #GObject property.
|
|
|
|
|
*
|
|
|
|
|
* When serializing a setting to D-Bus, @get_func will be called to get the
|
2014-08-16 10:09:48 -04:00
|
|
|
* property's value. (If it returns %NULL, no value will be added to the
|
|
|
|
|
* serialization. If @get_func is %NULL, the property will always be omitted in
|
|
|
|
|
* the serialization.)
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
*
|
|
|
|
|
* When deserializing a D-Bus representation into a setting, if @property_name
|
|
|
|
|
* is present, then @set_func will be called to set (and/or verify) it. If it
|
|
|
|
|
* returns %TRUE, the value is considered to have been successfully set; if it
|
|
|
|
|
* returns %FALSE then the deserializing operation as a whole will fail with the
|
|
|
|
|
* returned #GError. (If @set_func is %NULL then the property will be ignored
|
|
|
|
|
* when deserializing.)
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
_nm_setting_class_add_dbus_only_property (NMSettingClass *setting_class,
|
|
|
|
|
const char *property_name,
|
2014-08-16 10:09:48 -04:00
|
|
|
const GVariantType *dbus_type,
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
NMSettingPropertyGetFunc get_func,
|
|
|
|
|
NMSettingPropertySetFunc set_func)
|
|
|
|
|
{
|
|
|
|
|
g_return_if_fail (NM_IS_SETTING_CLASS (setting_class));
|
|
|
|
|
g_return_if_fail (property_name != NULL);
|
|
|
|
|
|
|
|
|
|
/* Must not match any GObject property. */
|
|
|
|
|
g_return_if_fail (!g_object_class_find_property (G_OBJECT_CLASS (setting_class), property_name));
|
|
|
|
|
|
|
|
|
|
add_property_override (setting_class,
|
2014-07-29 18:25:10 -04:00
|
|
|
property_name, NULL, dbus_type,
|
2014-07-30 10:46:24 -04:00
|
|
|
get_func, set_func, NULL,
|
|
|
|
|
NULL, NULL);
|
2014-07-29 18:25:10 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* _nm_setting_class_override_property:
|
|
|
|
|
* @setting_class: the setting class
|
|
|
|
|
* @property_name: the name of the property to override
|
|
|
|
|
* @dbus_type: the type of the property (in its D-Bus representation)
|
|
|
|
|
* @get_func: (allow-none): function to call to get the value of the property
|
|
|
|
|
* @set_func: (allow-none): function to call to set the value of the property
|
|
|
|
|
* @not_set_func: (allow-none): function to call to indicate the property was not set
|
|
|
|
|
*
|
|
|
|
|
* Overrides the D-Bus representation of the #GObject property named
|
|
|
|
|
* @property_name on @setting_class.
|
|
|
|
|
*
|
|
|
|
|
* When serializing a setting to D-Bus, if @get_func is non-%NULL, then it will
|
|
|
|
|
* be called to get the property's value. If it returns %TRUE, the value will be
|
|
|
|
|
* added to the hash, and if %FALSE, it will not. (If @get_func is %NULL, the
|
|
|
|
|
* property will be read normally with g_object_get_property(), and added to the
|
|
|
|
|
* hash if it is not the default value.)
|
|
|
|
|
*
|
|
|
|
|
* When deserializing a D-Bus representation into a setting, if @property_name
|
|
|
|
|
* is present, then @set_func will be called to set (and/or verify) it. If it
|
|
|
|
|
* returns %TRUE, the value is considered to have been successfully set; if it
|
|
|
|
|
* returns %FALSE then the deserializing operation as a whole will fail with the
|
|
|
|
|
* returned #GError. (If @set_func is %NULL then the property will be set normally
|
|
|
|
|
* with g_object_set_property().)
|
|
|
|
|
*
|
|
|
|
|
* If @not_set_func is non-%NULL, then it will be called when deserializing a
|
|
|
|
|
* representation that does NOT contain @property_name. This can be used, eg, if
|
|
|
|
|
* a new property needs to be initialized from some older deprecated property
|
|
|
|
|
* when it is not present.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
_nm_setting_class_override_property (NMSettingClass *setting_class,
|
|
|
|
|
const char *property_name,
|
2014-08-16 10:09:48 -04:00
|
|
|
const GVariantType *dbus_type,
|
2014-07-29 18:25:10 -04:00
|
|
|
NMSettingPropertyGetFunc get_func,
|
|
|
|
|
NMSettingPropertySetFunc set_func,
|
|
|
|
|
NMSettingPropertyNotSetFunc not_set_func)
|
|
|
|
|
{
|
|
|
|
|
GParamSpec *param_spec;
|
|
|
|
|
|
|
|
|
|
param_spec = g_object_class_find_property (G_OBJECT_CLASS (setting_class), property_name);
|
|
|
|
|
g_return_if_fail (param_spec != NULL);
|
|
|
|
|
|
|
|
|
|
add_property_override (setting_class,
|
|
|
|
|
property_name, param_spec, dbus_type,
|
2014-07-30 10:46:24 -04:00
|
|
|
get_func, set_func, not_set_func,
|
|
|
|
|
NULL, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* _nm_setting_class_transform_property:
|
|
|
|
|
* @setting_class: the setting class
|
|
|
|
|
* @property: the name of the property to transform
|
|
|
|
|
* @dbus_type: the type of the property (in its D-Bus representation)
|
|
|
|
|
* @to_dbus: function to convert from object to D-Bus format
|
|
|
|
|
* @from_dbus: function to convert from D-Bus to object format
|
|
|
|
|
*
|
|
|
|
|
* Indicates that @property on @setting_class does not have the same format as
|
|
|
|
|
* its corresponding D-Bus representation, and so must be transformed when
|
|
|
|
|
* serializing/deserializing.
|
|
|
|
|
*
|
|
|
|
|
* The transformation will also be used by nm_setting_compare(), meaning that
|
|
|
|
|
* the underlying object property does not need to be of a type that
|
|
|
|
|
* nm_property_compare() recognizes, as long as it recognizes @dbus_type.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
_nm_setting_class_transform_property (NMSettingClass *setting_class,
|
|
|
|
|
const char *property,
|
2014-08-16 10:09:48 -04:00
|
|
|
const GVariantType *dbus_type,
|
|
|
|
|
NMSettingPropertyTransformToFunc to_dbus,
|
|
|
|
|
NMSettingPropertyTransformFromFunc from_dbus)
|
2014-07-30 10:46:24 -04:00
|
|
|
{
|
|
|
|
|
GParamSpec *param_spec;
|
|
|
|
|
|
|
|
|
|
param_spec = g_object_class_find_property (G_OBJECT_CLASS (setting_class), property);
|
|
|
|
|
g_return_if_fail (param_spec != NULL);
|
|
|
|
|
|
|
|
|
|
add_property_override (setting_class,
|
|
|
|
|
property, param_spec, dbus_type,
|
|
|
|
|
NULL, NULL, NULL,
|
|
|
|
|
to_dbus, from_dbus);
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static GArray *
|
|
|
|
|
nm_setting_class_ensure_properties (NMSettingClass *setting_class)
|
|
|
|
|
{
|
|
|
|
|
GType type = G_TYPE_FROM_CLASS (setting_class), otype;
|
|
|
|
|
NMSettingProperty property, *override;
|
|
|
|
|
GArray *overrides, *type_overrides, *properties;
|
|
|
|
|
GParamSpec **property_specs;
|
|
|
|
|
guint n_property_specs, i;
|
|
|
|
|
|
|
|
|
|
properties = g_type_get_qdata (type, setting_properties_quark);
|
|
|
|
|
if (properties)
|
|
|
|
|
return properties;
|
|
|
|
|
|
|
|
|
|
/* Build overrides array from @setting_class and its superclasses */
|
|
|
|
|
overrides = g_array_new (FALSE, FALSE, sizeof (NMSettingProperty));
|
|
|
|
|
for (otype = type; otype != G_TYPE_OBJECT; otype = g_type_parent (otype)) {
|
|
|
|
|
type_overrides = g_type_get_qdata (otype, setting_property_overrides_quark);
|
|
|
|
|
if (type_overrides)
|
|
|
|
|
g_array_append_vals (overrides, (NMSettingProperty *)type_overrides->data, type_overrides->len);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Build the properties array from the GParamSpecs, obeying overrides */
|
|
|
|
|
properties = g_array_new (FALSE, FALSE, sizeof (NMSettingProperty));
|
|
|
|
|
|
|
|
|
|
property_specs = g_object_class_list_properties (G_OBJECT_CLASS (setting_class),
|
|
|
|
|
&n_property_specs);
|
|
|
|
|
for (i = 0; i < n_property_specs; i++) {
|
|
|
|
|
override = find_property (overrides, property_specs[i]->name);
|
|
|
|
|
if (override)
|
|
|
|
|
property = *override;
|
|
|
|
|
else {
|
|
|
|
|
memset (&property, 0, sizeof (property));
|
|
|
|
|
property.name = property_specs[i]->name;
|
|
|
|
|
property.param_spec = property_specs[i];
|
|
|
|
|
}
|
|
|
|
|
g_array_append_val (properties, property);
|
|
|
|
|
}
|
|
|
|
|
g_free (property_specs);
|
|
|
|
|
|
|
|
|
|
/* Add any remaining overrides not corresponding to GObject properties */
|
|
|
|
|
for (i = 0; i < overrides->len; i++) {
|
|
|
|
|
override = &g_array_index (overrides, NMSettingProperty, i);
|
|
|
|
|
if (!g_object_class_find_property (G_OBJECT_CLASS (setting_class), override->name))
|
|
|
|
|
g_array_append_val (properties, *override);
|
|
|
|
|
}
|
|
|
|
|
g_array_unref (overrides);
|
|
|
|
|
|
|
|
|
|
g_type_set_qdata (type, setting_properties_quark, properties);
|
|
|
|
|
return properties;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const NMSettingProperty *
|
|
|
|
|
nm_setting_class_get_properties (NMSettingClass *setting_class, guint *n_properties)
|
|
|
|
|
{
|
|
|
|
|
GArray *properties;
|
|
|
|
|
|
|
|
|
|
properties = nm_setting_class_ensure_properties (setting_class);
|
|
|
|
|
|
|
|
|
|
*n_properties = properties->len;
|
|
|
|
|
return (NMSettingProperty *) properties->data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const NMSettingProperty *
|
|
|
|
|
nm_setting_class_find_property (NMSettingClass *setting_class, const char *property_name)
|
|
|
|
|
{
|
|
|
|
|
GArray *properties;
|
|
|
|
|
|
|
|
|
|
properties = nm_setting_class_ensure_properties (setting_class);
|
|
|
|
|
return find_property (properties, property_name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*************************************************************/
|
|
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
static const GVariantType *
|
|
|
|
|
variant_type_for_gtype (GType type)
|
|
|
|
|
{
|
|
|
|
|
if (type == G_TYPE_BOOLEAN)
|
|
|
|
|
return G_VARIANT_TYPE_BOOLEAN;
|
|
|
|
|
else if (type == G_TYPE_UCHAR)
|
|
|
|
|
return G_VARIANT_TYPE_BYTE;
|
|
|
|
|
else if (type == G_TYPE_INT)
|
|
|
|
|
return G_VARIANT_TYPE_INT32;
|
|
|
|
|
else if (type == G_TYPE_UINT)
|
|
|
|
|
return G_VARIANT_TYPE_UINT32;
|
|
|
|
|
else if (type == G_TYPE_INT64)
|
|
|
|
|
return G_VARIANT_TYPE_INT64;
|
|
|
|
|
else if (type == G_TYPE_UINT64)
|
|
|
|
|
return G_VARIANT_TYPE_UINT64;
|
|
|
|
|
else if (type == G_TYPE_STRING)
|
|
|
|
|
return G_VARIANT_TYPE_STRING;
|
|
|
|
|
else if (type == G_TYPE_DOUBLE)
|
|
|
|
|
return G_VARIANT_TYPE_DOUBLE;
|
|
|
|
|
else if (type == G_TYPE_STRV)
|
|
|
|
|
return G_VARIANT_TYPE_STRING_ARRAY;
|
|
|
|
|
else
|
|
|
|
|
g_assert_not_reached ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static GVariant *
|
|
|
|
|
get_property_for_dbus (NMSetting *setting,
|
|
|
|
|
const NMSettingProperty *property,
|
|
|
|
|
gboolean ignore_default)
|
|
|
|
|
{
|
|
|
|
|
GValue prop_value = { 0, };
|
|
|
|
|
GVariant *dbus_value;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (property->param_spec != NULL, NULL);
|
|
|
|
|
|
|
|
|
|
g_value_init (&prop_value, property->param_spec->value_type);
|
|
|
|
|
g_object_get_property (G_OBJECT (setting), property->param_spec->name, &prop_value);
|
|
|
|
|
|
|
|
|
|
if (ignore_default && g_param_value_defaults (property->param_spec, &prop_value)) {
|
|
|
|
|
g_value_unset (&prop_value);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (property->to_dbus)
|
|
|
|
|
dbus_value = property->to_dbus (&prop_value);
|
|
|
|
|
else if (property->dbus_type)
|
|
|
|
|
dbus_value = g_dbus_gvalue_to_gvariant (&prop_value, property->dbus_type);
|
2014-06-26 16:47:46 -04:00
|
|
|
else if (g_type_is_a (prop_value.g_type, G_TYPE_ENUM))
|
|
|
|
|
dbus_value = g_variant_new_int32 (g_value_get_enum (&prop_value));
|
|
|
|
|
else if (g_type_is_a (prop_value.g_type, G_TYPE_FLAGS))
|
|
|
|
|
dbus_value = g_variant_new_uint32 (g_value_get_flags (&prop_value));
|
2014-08-16 10:09:48 -04:00
|
|
|
else
|
|
|
|
|
dbus_value = g_dbus_gvalue_to_gvariant (&prop_value, variant_type_for_gtype (prop_value.g_type));
|
|
|
|
|
g_value_unset (&prop_value);
|
|
|
|
|
|
|
|
|
|
return dbus_value;
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
static void
|
2014-08-16 10:09:48 -04:00
|
|
|
set_property_from_dbus (const NMSettingProperty *property, GVariant *src_value, GValue *dst_value)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
2014-09-19 09:36:24 +02:00
|
|
|
g_return_if_fail (property->param_spec != NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
if (property->from_dbus)
|
|
|
|
|
property->from_dbus (src_value, dst_value);
|
|
|
|
|
else
|
|
|
|
|
g_dbus_gvariant_to_gvalue (src_value, dst_value);
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
/**
|
2014-08-06 19:35:31 -04:00
|
|
|
* _nm_setting_to_dbus:
|
2014-07-24 08:53:33 -04:00
|
|
|
* @setting: the #NMSetting
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
* @connection: the #NMConnection containing @setting
|
2014-08-06 19:35:31 -04:00
|
|
|
* @flags: hash flags, e.g. %NM_CONNECTION_SERIALIZE_ALL
|
2014-07-24 08:53:33 -04:00
|
|
|
*
|
2014-08-16 10:09:48 -04:00
|
|
|
* Converts the #NMSetting into a #GVariant of type #NM_VARIANT_TYPE_SETTING
|
|
|
|
|
* mapping each setting property name to a value describing that property,
|
|
|
|
|
* suitable for marshalling over D-Bus or serializing.
|
2014-07-24 08:53:33 -04:00
|
|
|
*
|
2014-08-16 10:09:48 -04:00
|
|
|
* Returns: (transfer none): a new floating #GVariant describing the setting's
|
|
|
|
|
* properties
|
2014-07-24 08:53:33 -04:00
|
|
|
**/
|
2014-08-16 10:09:48 -04:00
|
|
|
GVariant *
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
_nm_setting_to_dbus (NMSetting *setting, NMConnection *connection, NMConnectionSerializationFlags flags)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
2014-08-16 10:09:48 -04:00
|
|
|
GVariantBuilder builder;
|
|
|
|
|
GVariant *dbus_value;
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
const NMSettingProperty *properties;
|
|
|
|
|
guint n_properties, i;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
|
|
|
|
|
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
properties = nm_setting_class_get_properties (NM_SETTING_GET_CLASS (setting), &n_properties);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
g_variant_builder_init (&builder, NM_VARIANT_TYPE_SETTING);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
for (i = 0; i < n_properties; i++) {
|
|
|
|
|
const NMSettingProperty *property = &properties[i];
|
|
|
|
|
GParamSpec *prop_spec = property->param_spec;
|
|
|
|
|
|
|
|
|
|
if (!prop_spec && !property->get_func) {
|
|
|
|
|
/* Override property with no get_func, so we skip it. */
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2014-07-24 08:53:33 -04:00
|
|
|
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
if (prop_spec && !(prop_spec->flags & G_PARAM_WRITABLE))
|
2014-07-24 08:53:33 -04:00
|
|
|
continue;
|
|
|
|
|
|
2014-08-06 19:35:31 -04:00
|
|
|
if ( (flags & NM_CONNECTION_SERIALIZE_NO_SECRETS)
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
&& (prop_spec && (prop_spec->flags & NM_SETTING_PARAM_SECRET)))
|
2014-07-24 08:53:33 -04:00
|
|
|
continue;
|
|
|
|
|
|
2014-08-06 19:35:31 -04:00
|
|
|
if ( (flags & NM_CONNECTION_SERIALIZE_ONLY_SECRETS)
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
&& !(prop_spec && (prop_spec->flags & NM_SETTING_PARAM_SECRET)))
|
2014-07-24 08:53:33 -04:00
|
|
|
continue;
|
|
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
if (property->get_func)
|
|
|
|
|
dbus_value = property->get_func (setting, connection, property->name);
|
|
|
|
|
else if (prop_spec)
|
|
|
|
|
dbus_value = get_property_for_dbus (setting, property, TRUE);
|
|
|
|
|
else
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
g_assert_not_reached ();
|
2014-08-16 10:09:48 -04:00
|
|
|
if (dbus_value) {
|
|
|
|
|
/* Allow dbus_value to be either floating or not. */
|
|
|
|
|
g_variant_take_ref (dbus_value);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
g_variant_builder_add (&builder, "{sv}", property->name, dbus_value);
|
|
|
|
|
g_variant_unref (dbus_value);
|
|
|
|
|
}
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
return g_variant_builder_end (&builder);
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2014-08-06 19:35:31 -04:00
|
|
|
* _nm_setting_new_from_dbus:
|
2014-07-24 08:53:33 -04:00
|
|
|
* @setting_type: the #NMSetting type which the hash contains properties for
|
2014-08-16 10:09:48 -04:00
|
|
|
* @setting_dict: the #GVariant containing an %NM_VARIANT_TYPE_SETTING dictionary
|
|
|
|
|
* mapping property names to values
|
|
|
|
|
* @connection_dict: the #GVariant containing an %NM_VARIANT_TYPE_CONNECTION
|
|
|
|
|
* dictionary mapping setting names to dictionaries.
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
* @error: location to store error, or %NULL
|
2014-07-24 08:53:33 -04:00
|
|
|
*
|
|
|
|
|
* Creates a new #NMSetting object and populates that object with the properties
|
2014-08-16 10:09:48 -04:00
|
|
|
* contained in @setting_dict, using each key as the property to set, and each
|
|
|
|
|
* value as the value to set that property to. Setting properties are strongly
|
|
|
|
|
* typed, thus the #GVariantType of the dict value must be correct. See the
|
|
|
|
|
* documentation on each #NMSetting object subclass for the correct property
|
|
|
|
|
* names and value types.
|
2014-07-24 08:53:33 -04:00
|
|
|
*
|
|
|
|
|
* Returns: a new #NMSetting object populated with the properties from the
|
2014-09-15 13:30:07 -04:00
|
|
|
* hash table, or %NULL if @setting_hash could not be deserialized.
|
2014-07-24 08:53:33 -04:00
|
|
|
**/
|
|
|
|
|
NMSetting *
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
_nm_setting_new_from_dbus (GType setting_type,
|
2014-08-16 10:09:48 -04:00
|
|
|
GVariant *setting_dict,
|
|
|
|
|
GVariant *connection_dict,
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
GError **error)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
NMSettingClass *class;
|
2014-08-16 10:09:48 -04:00
|
|
|
NMSetting *setting;
|
|
|
|
|
GVariantIter iter;
|
2014-08-04 11:39:33 -04:00
|
|
|
const char *prop_name;
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
const NMSettingProperty *properties;
|
|
|
|
|
guint n_properties;
|
2014-08-04 11:39:33 -04:00
|
|
|
guint i;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (setting_type), NULL);
|
2014-08-16 10:09:48 -04:00
|
|
|
g_return_val_if_fail (g_variant_is_of_type (setting_dict, NM_VARIANT_TYPE_SETTING), NULL);
|
|
|
|
|
|
|
|
|
|
/* connection_dict is not technically optional, but some tests in test-general
|
|
|
|
|
* don't bother with it in cases where they know it's not needed.
|
|
|
|
|
*/
|
|
|
|
|
if (connection_dict)
|
|
|
|
|
g_return_val_if_fail (g_variant_is_of_type (connection_dict, NM_VARIANT_TYPE_CONNECTION), NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* g_type_class_ref() ensures the setting class is created if it hasn't
|
|
|
|
|
* already been used.
|
|
|
|
|
*/
|
|
|
|
|
class = g_type_class_ref (setting_type);
|
|
|
|
|
|
2014-08-04 11:39:33 -04:00
|
|
|
/* Check for invalid properties first. */
|
2014-08-16 10:09:48 -04:00
|
|
|
g_variant_iter_init (&iter, setting_dict);
|
|
|
|
|
while (g_variant_iter_next (&iter, "{&sv}", &prop_name, NULL)) {
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
if (!nm_setting_class_find_property (class, prop_name)) {
|
2014-07-24 08:53:33 -04:00
|
|
|
/* Oh, we're so nice and only warn, maybe it should be a fatal error? */
|
|
|
|
|
g_warning ("Ignoring invalid property '%s'", prop_name);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2014-08-04 11:39:33 -04:00
|
|
|
}
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-08-04 11:39:33 -04:00
|
|
|
/* Now build the setting object from the legitimate properties */
|
|
|
|
|
setting = (NMSetting *) g_object_new (setting_type, NULL);
|
2014-05-09 15:02:57 -04:00
|
|
|
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
properties = nm_setting_class_get_properties (class, &n_properties);
|
|
|
|
|
for (i = 0; i < n_properties; i++) {
|
|
|
|
|
const NMSettingProperty *property = &properties[i];
|
2014-08-16 10:09:48 -04:00
|
|
|
GVariant *value = g_variant_lookup_value (setting_dict, property->name, NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-07-29 18:25:10 -04:00
|
|
|
if (value && property->set_func) {
|
2014-09-15 13:30:07 -04:00
|
|
|
property->set_func (setting,
|
2014-08-16 10:09:48 -04:00
|
|
|
connection_dict,
|
2014-09-15 13:30:07 -04:00
|
|
|
property->name,
|
|
|
|
|
value);
|
2014-07-29 18:25:10 -04:00
|
|
|
} else if (!value && property->not_set_func) {
|
2014-09-15 13:30:07 -04:00
|
|
|
property->not_set_func (setting,
|
2014-08-16 10:09:48 -04:00
|
|
|
connection_dict,
|
2014-09-15 13:30:07 -04:00
|
|
|
property->name);
|
2014-07-29 18:25:10 -04:00
|
|
|
} else if (value && property->param_spec) {
|
2014-08-16 10:09:48 -04:00
|
|
|
GValue object_value = { 0, };
|
|
|
|
|
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
if (!(property->param_spec->flags & G_PARAM_WRITABLE))
|
|
|
|
|
continue;
|
|
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
g_value_init (&object_value, property->param_spec->value_type);
|
|
|
|
|
set_property_from_dbus (property, value, &object_value);
|
|
|
|
|
g_object_set_property (G_OBJECT (setting), property->param_spec->name, &object_value);
|
2014-10-22 16:49:32 +02:00
|
|
|
g_value_unset (&object_value);
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
}
|
2014-08-16 10:09:48 -04:00
|
|
|
|
|
|
|
|
if (value)
|
|
|
|
|
g_variant_unref (value);
|
2014-08-04 11:39:33 -04:00
|
|
|
}
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
g_type_class_unref (class);
|
|
|
|
|
|
|
|
|
|
return setting;
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-26 10:09:54 +01:00
|
|
|
gboolean
|
|
|
|
|
_nm_setting_get_property (NMSetting *setting, const char *property_name, GValue *value)
|
|
|
|
|
{
|
|
|
|
|
GParamSpec *prop_spec;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
|
|
|
|
|
g_return_val_if_fail (property_name, FALSE);
|
|
|
|
|
g_return_val_if_fail (value, FALSE);
|
|
|
|
|
|
|
|
|
|
prop_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), property_name);
|
|
|
|
|
|
|
|
|
|
if (!prop_spec) {
|
|
|
|
|
g_value_unset (value);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_value_init (value, prop_spec->value_type);
|
|
|
|
|
g_object_get_property (G_OBJECT (setting), property_name, value);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
static void
|
|
|
|
|
duplicate_setting (NMSetting *setting,
|
|
|
|
|
const char *name,
|
|
|
|
|
const GValue *value,
|
|
|
|
|
GParamFlags flags,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
if ((flags & (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)) == G_PARAM_WRITABLE)
|
|
|
|
|
g_object_set_property (G_OBJECT (user_data), 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)
|
|
|
|
|
{
|
|
|
|
|
GObject *dup;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
|
|
|
|
|
|
|
|
|
|
dup = g_object_new (G_OBJECT_TYPE (setting), NULL);
|
|
|
|
|
|
|
|
|
|
g_object_freeze_notify (dup);
|
|
|
|
|
nm_setting_enumerate_values (setting, duplicate_setting, dup);
|
|
|
|
|
g_object_thaw_notify (dup);
|
|
|
|
|
|
|
|
|
|
return NM_SETTING (dup);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gint
|
|
|
|
|
find_setting_by_name (gconstpointer a, gconstpointer b)
|
|
|
|
|
{
|
|
|
|
|
NMSetting *setting = NM_SETTING (a);
|
|
|
|
|
const char *str = (const char *) b;
|
|
|
|
|
|
|
|
|
|
return strcmp (nm_setting_get_name (setting), str);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NMSetting *
|
|
|
|
|
nm_setting_find_in_list (GSList *settings_list,
|
|
|
|
|
const char *setting_name)
|
|
|
|
|
{
|
|
|
|
|
GSList *found;
|
|
|
|
|
|
|
|
|
|
found = g_slist_find_custom (settings_list, setting_name, find_setting_by_name);
|
|
|
|
|
if (found)
|
|
|
|
|
return found->data;
|
|
|
|
|
else
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_setting_get_name:
|
|
|
|
|
* @setting: the #NMSetting
|
|
|
|
|
*
|
|
|
|
|
* Returns the type name of the #NMSetting object
|
|
|
|
|
*
|
|
|
|
|
* Returns: a string containing the type name of the #NMSetting object,
|
|
|
|
|
* like 'ppp' or 'wireless' or 'wired'.
|
|
|
|
|
**/
|
|
|
|
|
const char *
|
|
|
|
|
nm_setting_get_name (NMSetting *setting)
|
|
|
|
|
{
|
|
|
|
|
NMSettingPrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
|
|
|
|
|
priv = NM_SETTING_GET_PRIVATE (setting);
|
|
|
|
|
_ensure_setting_info (setting, priv);
|
|
|
|
|
return priv->info->name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_setting_verify:
|
|
|
|
|
* @setting: the #NMSetting to verify
|
|
|
|
|
* @all_settings: (element-type NMSetting): a #GSList of all settings
|
|
|
|
|
* in the connection from which @setting came
|
|
|
|
|
* @error: location to store error, or %NULL
|
|
|
|
|
*
|
|
|
|
|
* Validates the setting. Each setting's properties have allowed values, and
|
|
|
|
|
* some are dependent on other values (hence the need for @all_settings). The
|
|
|
|
|
* returned #GError contains information about which property of the setting
|
|
|
|
|
* failed validation, and in what way that property failed validation.
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE if the setting is valid, %FALSE if it is not
|
|
|
|
|
**/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_setting_verify (NMSetting *setting, GSList *all_settings, GError **error)
|
|
|
|
|
{
|
|
|
|
|
NMSettingVerifyResult result = _nm_setting_verify (setting, all_settings, error);
|
|
|
|
|
|
|
|
|
|
if (result == NM_SETTING_VERIFY_NORMALIZABLE)
|
|
|
|
|
g_clear_error (error);
|
|
|
|
|
|
|
|
|
|
return result == NM_SETTING_VERIFY_SUCCESS || result == NM_SETTING_VERIFY_NORMALIZABLE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NMSettingVerifyResult
|
|
|
|
|
_nm_setting_verify (NMSetting *setting, GSList *all_settings, GError **error)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (NM_IS_SETTING (setting), NM_SETTING_VERIFY_ERROR);
|
|
|
|
|
g_return_val_if_fail (!error || *error == NULL, NM_SETTING_VERIFY_ERROR);
|
|
|
|
|
|
|
|
|
|
if (NM_SETTING_GET_CLASS (setting)->verify)
|
|
|
|
|
return NM_SETTING_GET_CLASS (setting)->verify (setting, all_settings, error);
|
|
|
|
|
|
|
|
|
|
return NM_SETTING_VERIFY_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
compare_property (NMSetting *setting,
|
|
|
|
|
NMSetting *other,
|
|
|
|
|
const GParamSpec *prop_spec,
|
|
|
|
|
NMSettingCompareFlags flags)
|
|
|
|
|
{
|
2014-07-30 10:46:24 -04:00
|
|
|
const NMSettingProperty *property;
|
2014-08-16 10:09:48 -04:00
|
|
|
GVariant *value1, *value2;
|
2014-07-29 09:22:07 -04:00
|
|
|
int cmp;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Handle compare flags */
|
|
|
|
|
if (prop_spec->flags & NM_SETTING_PARAM_SECRET) {
|
|
|
|
|
NMSettingSecretFlags a_secret_flags = NM_SETTING_SECRET_FLAG_NONE;
|
|
|
|
|
NMSettingSecretFlags b_secret_flags = NM_SETTING_SECRET_FLAG_NONE;
|
|
|
|
|
|
libnm-util: don't assert in nm_setting_get_secret_flags() and avoid assertion in agent_secrets_done_cb()
When secret providers return the connection hash in GetSecrets(),
this hash should only contain secrets. However, some providers also
return non-secret properties.
for_each_secret() iterated over all entries of the @secrets hash
and triggered the assertion in nm_setting_get_secret_flags() (see
below).
NM should not assert against user provided input. Change
nm_setting_get_secret_flags() to silently return FALSE, if the property
is not a secret.
Indeed, handling of secrets is very different for NMSettingVpn and
others. Hence nm_setting_get_secret_flags() has only an inconsistent
behavior and we have to fix all call sites to do the right thing
(depending on whether we have a VPN setting or not).
Now for_each_secret() checks whether the property is a secret
without hitting the assertion. Adjust all other calls of
nm_setting_get_secret_flags(), to anticipate non-secret flags and
assert/warn where appropriate.
Also, agent_secrets_done_cb() clears now all non-secrets properties
from the hash, using the new argument @remove_non_secrets when calling
for_each_secret().
#0 0x0000003370c504e9 in g_logv () from /lib64/libglib-2.0.so.0
#1 0x0000003370c5063f in g_log () from /lib64/libglib-2.0.so.0
#2 0x00007fa4b0c1c156 in get_secret_flags (setting=0x1e3ac60, secret_name=0x1ea9180 "security", verify_secret=1, out_flags=0x7fff7507857c, error=0x0) at nm-setting.c:1091
#3 0x00007fa4b0c1c2b2 in nm_setting_get_secret_flags (setting=0x1e3ac60, secret_name=0x1ea9180 "security", out_flags=0x7fff7507857c, error=0x0) at nm-setting.c:1124
#4 0x0000000000463d03 in for_each_secret (connection=0x1deb2f0, secrets=0x1e9f860, callback=0x464f1b <has_system_owned_secrets>, callback_data=0x7fff7507865c) at settings/nm-settings-connection.c:203
#5 0x000000000046525f in agent_secrets_done_cb (manager=0x1dddf50, call_id=1, agent_dbus_owner=0x1ddb9e0 ":1.39", agent_username=0x1e51710 "thom", agent_has_modify=1, setting_name=0x1e91f90 "802-11-wireless-security",
flags=NM_SETTINGS_GET_SECRETS_FLAG_ALLOW_INTERACTION, secrets=0x1e9f860, error=0x0, user_data=0x1deb2f0, other_data2=0x477d61 <get_secrets_cb>, other_data3=0x1ea92a0) at settings/nm-settings-connection.c:757
#6 0x00000000004dc4fd in get_complete_cb (parent=0x1ea6300, secrets=0x1e9f860, agent_dbus_owner=0x1ddb9e0 ":1.39", agent_username=0x1e51710 "thom", error=0x0, user_data=0x1dddf50) at settings/nm-agent-manager.c:1139
#7 0x00000000004dab54 in req_complete_success (req=0x1ea6300, secrets=0x1e9f860, agent_dbus_owner=0x1ddb9e0 ":1.39", agent_uname=0x1e51710 "thom") at settings/nm-agent-manager.c:502
#8 0x00000000004db86e in get_done_cb (agent=0x1e89530, call_id=0x1, secrets=0x1e9f860, error=0x0, user_data=0x1ea6300) at settings/nm-agent-manager.c:856
#9 0x00000000004de9d0 in get_callback (proxy=0x1e47530, call=0x1, user_data=0x1ea10f0) at settings/nm-secret-agent.c:267
#10 0x000000337380cad2 in complete_pending_call_and_unlock () from /lib64/libdbus-1.so.3
#11 0x000000337380fdc1 in dbus_connection_dispatch () from /lib64/libdbus-1.so.3
#12 0x000000342800ad65 in message_queue_dispatch () from /lib64/libdbus-glib-1.so.2
#13 0x0000003370c492a6 in g_main_context_dispatch () from /lib64/libglib-2.0.so.0
#14 0x0000003370c49628 in g_main_context_iterate.isra.24 () from /lib64/libglib-2.0.so.0
#15 0x0000003370c49a3a in g_main_loop_run () from /lib64/libglib-2.0.so.0
#16 0x000000000042e5c6 in main (argc=1, argv=0x7fff75078e88) at main.c:644
Signed-off-by: Thomas Haller <thaller@redhat.com>
2014-02-23 17:03:01 +01:00
|
|
|
g_return_val_if_fail (!NM_IS_SETTING_VPN (setting), FALSE);
|
|
|
|
|
|
|
|
|
|
if (!nm_setting_get_secret_flags (setting, prop_spec->name, &a_secret_flags, NULL))
|
|
|
|
|
g_return_val_if_reached (FALSE);
|
|
|
|
|
if (!nm_setting_get_secret_flags (other, prop_spec->name, &b_secret_flags, NULL))
|
|
|
|
|
g_return_val_if_reached (FALSE);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* If the secret flags aren't the same the settings aren't the same */
|
|
|
|
|
if (a_secret_flags != b_secret_flags)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
/* Check for various secret flags that might cause us to ignore comparing
|
|
|
|
|
* this property.
|
|
|
|
|
*/
|
|
|
|
|
if ( (flags & NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS)
|
|
|
|
|
&& (a_secret_flags & NM_SETTING_SECRET_FLAG_AGENT_OWNED))
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
if ( (flags & NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)
|
|
|
|
|
&& (a_secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED))
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-30 10:46:24 -04:00
|
|
|
property = nm_setting_class_find_property (NM_SETTING_GET_CLASS (setting), prop_spec->name);
|
|
|
|
|
g_return_val_if_fail (property != NULL, FALSE);
|
|
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
value1 = get_property_for_dbus (setting, property, FALSE);
|
|
|
|
|
value2 = get_property_for_dbus (other, property, FALSE);
|
2014-07-30 10:46:24 -04:00
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
cmp = nm_property_compare (value1, value2);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
g_variant_unref (value1);
|
|
|
|
|
g_variant_unref (value2);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-07-29 09:22:07 -04:00
|
|
|
return cmp == 0;
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_setting_compare:
|
|
|
|
|
* @a: a #NMSetting
|
|
|
|
|
* @b: a second #NMSetting to compare with the first
|
|
|
|
|
* @flags: compare flags, e.g. %NM_SETTING_COMPARE_FLAG_EXACT
|
|
|
|
|
*
|
|
|
|
|
* Compares two #NMSetting objects for similarity, with comparison behavior
|
|
|
|
|
* modified by a set of flags. See the documentation for #NMSettingCompareFlags
|
|
|
|
|
* for a description of each flag's behavior.
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE if the comparison succeeds, %FALSE if it does not
|
|
|
|
|
**/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_setting_compare (NMSetting *a,
|
|
|
|
|
NMSetting *b,
|
|
|
|
|
NMSettingCompareFlags flags)
|
|
|
|
|
{
|
|
|
|
|
GParamSpec **property_specs;
|
|
|
|
|
guint n_property_specs;
|
|
|
|
|
gint same = TRUE;
|
|
|
|
|
guint i;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_SETTING (a), FALSE);
|
|
|
|
|
g_return_val_if_fail (NM_IS_SETTING (b), FALSE);
|
|
|
|
|
|
|
|
|
|
/* First check that both have the same type */
|
|
|
|
|
if (G_OBJECT_TYPE (a) != G_OBJECT_TYPE (b))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
/* And now all properties */
|
|
|
|
|
property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (a), &n_property_specs);
|
|
|
|
|
for (i = 0; i < n_property_specs && same; i++) {
|
|
|
|
|
GParamSpec *prop_spec = property_specs[i];
|
|
|
|
|
|
|
|
|
|
/* Fuzzy compare ignores secrets and properties defined with the FUZZY_IGNORE flag */
|
|
|
|
|
if ( (flags & NM_SETTING_COMPARE_FLAG_FUZZY)
|
|
|
|
|
&& (prop_spec->flags & (NM_SETTING_PARAM_FUZZY_IGNORE | NM_SETTING_PARAM_SECRET)))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if ((flags & NM_SETTING_COMPARE_FLAG_INFERRABLE) && !(prop_spec->flags & NM_SETTING_PARAM_INFERRABLE))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if ( (flags & NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS)
|
|
|
|
|
&& (prop_spec->flags & NM_SETTING_PARAM_SECRET))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
same = NM_SETTING_GET_CLASS (a)->compare_property (a, b, prop_spec, flags);
|
|
|
|
|
}
|
|
|
|
|
g_free (property_specs);
|
|
|
|
|
|
|
|
|
|
return same;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline gboolean
|
|
|
|
|
should_compare_prop (NMSetting *setting,
|
|
|
|
|
const char *prop_name,
|
|
|
|
|
NMSettingCompareFlags comp_flags,
|
|
|
|
|
GParamFlags prop_flags)
|
|
|
|
|
{
|
|
|
|
|
/* Fuzzy compare ignores secrets and properties defined with the FUZZY_IGNORE flag */
|
|
|
|
|
if ( (comp_flags & NM_SETTING_COMPARE_FLAG_FUZZY)
|
|
|
|
|
&& (prop_flags & (NM_SETTING_PARAM_FUZZY_IGNORE | NM_SETTING_PARAM_SECRET)))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if ((comp_flags & NM_SETTING_COMPARE_FLAG_INFERRABLE) && !(prop_flags & NM_SETTING_PARAM_INFERRABLE))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if (prop_flags & NM_SETTING_PARAM_SECRET) {
|
|
|
|
|
NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
|
|
|
|
|
|
|
|
|
|
if (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
libnm-util: don't assert in nm_setting_get_secret_flags() and avoid assertion in agent_secrets_done_cb()
When secret providers return the connection hash in GetSecrets(),
this hash should only contain secrets. However, some providers also
return non-secret properties.
for_each_secret() iterated over all entries of the @secrets hash
and triggered the assertion in nm_setting_get_secret_flags() (see
below).
NM should not assert against user provided input. Change
nm_setting_get_secret_flags() to silently return FALSE, if the property
is not a secret.
Indeed, handling of secrets is very different for NMSettingVpn and
others. Hence nm_setting_get_secret_flags() has only an inconsistent
behavior and we have to fix all call sites to do the right thing
(depending on whether we have a VPN setting or not).
Now for_each_secret() checks whether the property is a secret
without hitting the assertion. Adjust all other calls of
nm_setting_get_secret_flags(), to anticipate non-secret flags and
assert/warn where appropriate.
Also, agent_secrets_done_cb() clears now all non-secrets properties
from the hash, using the new argument @remove_non_secrets when calling
for_each_secret().
#0 0x0000003370c504e9 in g_logv () from /lib64/libglib-2.0.so.0
#1 0x0000003370c5063f in g_log () from /lib64/libglib-2.0.so.0
#2 0x00007fa4b0c1c156 in get_secret_flags (setting=0x1e3ac60, secret_name=0x1ea9180 "security", verify_secret=1, out_flags=0x7fff7507857c, error=0x0) at nm-setting.c:1091
#3 0x00007fa4b0c1c2b2 in nm_setting_get_secret_flags (setting=0x1e3ac60, secret_name=0x1ea9180 "security", out_flags=0x7fff7507857c, error=0x0) at nm-setting.c:1124
#4 0x0000000000463d03 in for_each_secret (connection=0x1deb2f0, secrets=0x1e9f860, callback=0x464f1b <has_system_owned_secrets>, callback_data=0x7fff7507865c) at settings/nm-settings-connection.c:203
#5 0x000000000046525f in agent_secrets_done_cb (manager=0x1dddf50, call_id=1, agent_dbus_owner=0x1ddb9e0 ":1.39", agent_username=0x1e51710 "thom", agent_has_modify=1, setting_name=0x1e91f90 "802-11-wireless-security",
flags=NM_SETTINGS_GET_SECRETS_FLAG_ALLOW_INTERACTION, secrets=0x1e9f860, error=0x0, user_data=0x1deb2f0, other_data2=0x477d61 <get_secrets_cb>, other_data3=0x1ea92a0) at settings/nm-settings-connection.c:757
#6 0x00000000004dc4fd in get_complete_cb (parent=0x1ea6300, secrets=0x1e9f860, agent_dbus_owner=0x1ddb9e0 ":1.39", agent_username=0x1e51710 "thom", error=0x0, user_data=0x1dddf50) at settings/nm-agent-manager.c:1139
#7 0x00000000004dab54 in req_complete_success (req=0x1ea6300, secrets=0x1e9f860, agent_dbus_owner=0x1ddb9e0 ":1.39", agent_uname=0x1e51710 "thom") at settings/nm-agent-manager.c:502
#8 0x00000000004db86e in get_done_cb (agent=0x1e89530, call_id=0x1, secrets=0x1e9f860, error=0x0, user_data=0x1ea6300) at settings/nm-agent-manager.c:856
#9 0x00000000004de9d0 in get_callback (proxy=0x1e47530, call=0x1, user_data=0x1ea10f0) at settings/nm-secret-agent.c:267
#10 0x000000337380cad2 in complete_pending_call_and_unlock () from /lib64/libdbus-1.so.3
#11 0x000000337380fdc1 in dbus_connection_dispatch () from /lib64/libdbus-1.so.3
#12 0x000000342800ad65 in message_queue_dispatch () from /lib64/libdbus-glib-1.so.2
#13 0x0000003370c492a6 in g_main_context_dispatch () from /lib64/libglib-2.0.so.0
#14 0x0000003370c49628 in g_main_context_iterate.isra.24 () from /lib64/libglib-2.0.so.0
#15 0x0000003370c49a3a in g_main_loop_run () from /lib64/libglib-2.0.so.0
#16 0x000000000042e5c6 in main (argc=1, argv=0x7fff75078e88) at main.c:644
Signed-off-by: Thomas Haller <thaller@redhat.com>
2014-02-23 17:03:01 +01:00
|
|
|
if ( NM_IS_SETTING_VPN (setting)
|
|
|
|
|
&& g_strcmp0 (prop_name, NM_SETTING_VPN_SECRETS) == 0) {
|
|
|
|
|
/* FIXME: NMSettingVPN:NM_SETTING_VPN_SECRETS has NM_SETTING_PARAM_SECRET.
|
|
|
|
|
* nm_setting_get_secret_flags() quite possibly fails, but it might succeed if the
|
|
|
|
|
* setting accidently uses a key "secrets". */
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!nm_setting_get_secret_flags (setting, prop_name, &secret_flags, NULL))
|
|
|
|
|
g_return_val_if_reached (FALSE);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
if ( (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS)
|
|
|
|
|
&& (secret_flags & NM_SETTING_SECRET_FLAG_AGENT_OWNED))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if ( (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)
|
|
|
|
|
&& (secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED))
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_ID)
|
|
|
|
|
&& NM_IS_SETTING_CONNECTION (setting)
|
|
|
|
|
&& !strcmp (prop_name, NM_SETTING_CONNECTION_ID))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_setting_diff:
|
|
|
|
|
* @a: a #NMSetting
|
|
|
|
|
* @b: a second #NMSetting to compare with the first
|
|
|
|
|
* @flags: compare flags, e.g. %NM_SETTING_COMPARE_FLAG_EXACT
|
2014-07-04 13:26:57 -04:00
|
|
|
* @invert_results: this parameter is used internally by libnm and should
|
2014-07-24 08:53:33 -04:00
|
|
|
* be set to %FALSE. If %TRUE inverts the meaning of the #NMSettingDiffResult.
|
|
|
|
|
* @results: (inout) (transfer full) (element-type utf8 guint32): if the
|
|
|
|
|
* settings differ, on return a hash table mapping the differing keys to one or
|
|
|
|
|
* more %NMSettingDiffResult values OR-ed together. If the settings do not
|
|
|
|
|
* differ, any hash table passed in is unmodified. If no hash table is passed
|
|
|
|
|
* in and the settings differ, a new one is created and returned.
|
|
|
|
|
*
|
|
|
|
|
* Compares two #NMSetting objects for similarity, with comparison behavior
|
|
|
|
|
* modified by a set of flags. See the documentation for #NMSettingCompareFlags
|
|
|
|
|
* for a description of each flag's behavior. If the settings differ, the keys
|
|
|
|
|
* of each setting that differ from the other are added to @results, mapped to
|
|
|
|
|
* one or more #NMSettingDiffResult values.
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE if the settings contain the same values, %FALSE if they do not
|
|
|
|
|
**/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_setting_diff (NMSetting *a,
|
|
|
|
|
NMSetting *b,
|
|
|
|
|
NMSettingCompareFlags flags,
|
|
|
|
|
gboolean invert_results,
|
|
|
|
|
GHashTable **results)
|
|
|
|
|
{
|
|
|
|
|
GParamSpec **property_specs;
|
|
|
|
|
guint n_property_specs;
|
|
|
|
|
guint i;
|
|
|
|
|
NMSettingDiffResult a_result = NM_SETTING_DIFF_RESULT_IN_A;
|
|
|
|
|
NMSettingDiffResult b_result = NM_SETTING_DIFF_RESULT_IN_B;
|
2014-02-26 11:26:25 +01:00
|
|
|
NMSettingDiffResult a_result_default = NM_SETTING_DIFF_RESULT_IN_A_DEFAULT;
|
|
|
|
|
NMSettingDiffResult b_result_default = NM_SETTING_DIFF_RESULT_IN_B_DEFAULT;
|
2014-07-24 08:53:33 -04:00
|
|
|
gboolean results_created = FALSE;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (results != NULL, FALSE);
|
|
|
|
|
g_return_val_if_fail (NM_IS_SETTING (a), FALSE);
|
|
|
|
|
if (b) {
|
|
|
|
|
g_return_val_if_fail (NM_IS_SETTING (b), FALSE);
|
|
|
|
|
g_return_val_if_fail (G_OBJECT_TYPE (a) == G_OBJECT_TYPE (b), FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-26 11:26:25 +01:00
|
|
|
if ((flags & (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) ==
|
|
|
|
|
(NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) {
|
|
|
|
|
/* conflicting flags: default to WITH_DEFAULT (clearing NO_DEFAULT). */
|
|
|
|
|
flags &= ~NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT;
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
/* If the caller is calling this function in a pattern like this to get
|
|
|
|
|
* complete diffs:
|
|
|
|
|
*
|
|
|
|
|
* nm_setting_diff (A, B, FALSE, &results);
|
|
|
|
|
* nm_setting_diff (B, A, TRUE, &results);
|
|
|
|
|
*
|
|
|
|
|
* and wants us to invert the results so that the second invocation comes
|
|
|
|
|
* out correctly, do that here.
|
|
|
|
|
*/
|
|
|
|
|
if (invert_results) {
|
|
|
|
|
a_result = NM_SETTING_DIFF_RESULT_IN_B;
|
|
|
|
|
b_result = NM_SETTING_DIFF_RESULT_IN_A;
|
2014-02-26 11:26:25 +01:00
|
|
|
a_result_default = NM_SETTING_DIFF_RESULT_IN_B_DEFAULT;
|
|
|
|
|
b_result_default = NM_SETTING_DIFF_RESULT_IN_A_DEFAULT;
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (*results == NULL) {
|
|
|
|
|
*results = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
|
|
|
|
results_created = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* And now all properties */
|
|
|
|
|
property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (a), &n_property_specs);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < n_property_specs; i++) {
|
|
|
|
|
GParamSpec *prop_spec = property_specs[i];
|
2014-02-26 11:26:25 +01:00
|
|
|
NMSettingDiffResult r = NM_SETTING_DIFF_RESULT_UNKNOWN;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Handle compare flags */
|
|
|
|
|
if (!should_compare_prop (a, prop_spec->name, flags, prop_spec->flags))
|
|
|
|
|
continue;
|
|
|
|
|
if (strcmp (prop_spec->name, NM_SETTING_NAME) == 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (b) {
|
2014-02-26 11:26:25 +01:00
|
|
|
gboolean different;
|
|
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
different = !NM_SETTING_GET_CLASS (a)->compare_property (a, b, prop_spec, flags);
|
|
|
|
|
if (different) {
|
2014-02-26 11:26:25 +01:00
|
|
|
gboolean a_is_default, b_is_default;
|
2014-07-24 08:53:33 -04:00
|
|
|
GValue value = G_VALUE_INIT;
|
|
|
|
|
|
|
|
|
|
g_value_init (&value, prop_spec->value_type);
|
|
|
|
|
g_object_get_property (G_OBJECT (a), prop_spec->name, &value);
|
2014-02-26 11:26:25 +01:00
|
|
|
a_is_default = g_param_value_defaults (prop_spec, &value);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
g_value_reset (&value);
|
|
|
|
|
g_object_get_property (G_OBJECT (b), prop_spec->name, &value);
|
2014-02-26 11:26:25 +01:00
|
|
|
b_is_default = g_param_value_defaults (prop_spec, &value);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
g_value_unset (&value);
|
2014-02-26 11:26:25 +01:00
|
|
|
if ((flags & NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT) == 0) {
|
|
|
|
|
if (!a_is_default)
|
|
|
|
|
r |= a_result;
|
|
|
|
|
if (!b_is_default)
|
|
|
|
|
r |= b_result;
|
|
|
|
|
} else {
|
|
|
|
|
r |= a_result | b_result;
|
|
|
|
|
if (a_is_default)
|
|
|
|
|
r |= a_result_default;
|
|
|
|
|
if (b_is_default)
|
|
|
|
|
r |= b_result_default;
|
|
|
|
|
}
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
2014-02-26 11:26:25 +01:00
|
|
|
} else if ((flags & (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) == 0)
|
2014-07-24 08:53:33 -04:00
|
|
|
r = a_result; /* only in A */
|
2014-02-26 11:26:25 +01:00
|
|
|
else {
|
|
|
|
|
GValue value = G_VALUE_INIT;
|
|
|
|
|
|
|
|
|
|
g_value_init (&value, prop_spec->value_type);
|
|
|
|
|
g_object_get_property (G_OBJECT (a), prop_spec->name, &value);
|
|
|
|
|
if (!g_param_value_defaults (prop_spec, &value))
|
|
|
|
|
r |= a_result;
|
|
|
|
|
else if (flags & NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT)
|
|
|
|
|
r |= a_result | a_result_default;
|
|
|
|
|
|
|
|
|
|
g_value_unset (&value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (r != NM_SETTING_DIFF_RESULT_UNKNOWN) {
|
|
|
|
|
void *p;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-02-26 11:26:25 +01:00
|
|
|
if (g_hash_table_lookup_extended (*results, prop_spec->name, NULL, &p)) {
|
|
|
|
|
if ((r & GPOINTER_TO_UINT (p)) != r)
|
|
|
|
|
g_hash_table_insert (*results, g_strdup (prop_spec->name), GUINT_TO_POINTER (r | GPOINTER_TO_UINT (p)));
|
|
|
|
|
} else
|
|
|
|
|
g_hash_table_insert (*results, g_strdup (prop_spec->name), GUINT_TO_POINTER (r));
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
g_free (property_specs);
|
|
|
|
|
|
|
|
|
|
/* Don't return an empty hash table */
|
|
|
|
|
if (results_created && !g_hash_table_size (*results)) {
|
|
|
|
|
g_hash_table_destroy (*results);
|
|
|
|
|
*results = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return !(*results);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_setting_enumerate_values:
|
|
|
|
|
* @setting: the #NMSetting
|
|
|
|
|
* @func: (scope call): user-supplied function called for each property of the setting
|
|
|
|
|
* @user_data: user data passed to @func at each invocation
|
|
|
|
|
*
|
|
|
|
|
* Iterates over each property of the #NMSetting object, calling the supplied
|
|
|
|
|
* user function for each property.
|
|
|
|
|
**/
|
|
|
|
|
void
|
|
|
|
|
nm_setting_enumerate_values (NMSetting *setting,
|
|
|
|
|
NMSettingValueIterFn func,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
GParamSpec **property_specs;
|
|
|
|
|
guint n_property_specs;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_SETTING (setting));
|
|
|
|
|
g_return_if_fail (func != NULL);
|
|
|
|
|
|
|
|
|
|
property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs);
|
|
|
|
|
for (i = 0; i < n_property_specs; i++) {
|
|
|
|
|
GParamSpec *prop_spec = property_specs[i];
|
|
|
|
|
GValue value = G_VALUE_INIT;
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_free (property_specs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2014-10-07 08:46:36 +02:00
|
|
|
* _nm_setting_clear_secrets:
|
2014-07-24 08:53:33 -04:00
|
|
|
* @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.
|
2014-10-07 08:46:36 +02:00
|
|
|
*
|
|
|
|
|
* Returns: %TRUE if the setting changed at all
|
2014-07-24 08:53:33 -04:00
|
|
|
**/
|
|
|
|
|
gboolean
|
|
|
|
|
_nm_setting_clear_secrets (NMSetting *setting)
|
|
|
|
|
{
|
|
|
|
|
GParamSpec **property_specs;
|
|
|
|
|
guint n_property_specs;
|
|
|
|
|
guint i;
|
|
|
|
|
gboolean changed = FALSE;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
|
|
|
|
|
|
|
|
|
|
property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < n_property_specs; i++) {
|
|
|
|
|
GParamSpec *prop_spec = property_specs[i];
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_free (property_specs);
|
|
|
|
|
|
|
|
|
|
return changed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
clear_secrets_with_flags (NMSetting *setting,
|
|
|
|
|
GParamSpec *pspec,
|
|
|
|
|
NMSettingClearSecretsWithFlagsFn func,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;
|
|
|
|
|
gboolean changed = FALSE;
|
|
|
|
|
|
libnm-util: don't assert in nm_setting_get_secret_flags() and avoid assertion in agent_secrets_done_cb()
When secret providers return the connection hash in GetSecrets(),
this hash should only contain secrets. However, some providers also
return non-secret properties.
for_each_secret() iterated over all entries of the @secrets hash
and triggered the assertion in nm_setting_get_secret_flags() (see
below).
NM should not assert against user provided input. Change
nm_setting_get_secret_flags() to silently return FALSE, if the property
is not a secret.
Indeed, handling of secrets is very different for NMSettingVpn and
others. Hence nm_setting_get_secret_flags() has only an inconsistent
behavior and we have to fix all call sites to do the right thing
(depending on whether we have a VPN setting or not).
Now for_each_secret() checks whether the property is a secret
without hitting the assertion. Adjust all other calls of
nm_setting_get_secret_flags(), to anticipate non-secret flags and
assert/warn where appropriate.
Also, agent_secrets_done_cb() clears now all non-secrets properties
from the hash, using the new argument @remove_non_secrets when calling
for_each_secret().
#0 0x0000003370c504e9 in g_logv () from /lib64/libglib-2.0.so.0
#1 0x0000003370c5063f in g_log () from /lib64/libglib-2.0.so.0
#2 0x00007fa4b0c1c156 in get_secret_flags (setting=0x1e3ac60, secret_name=0x1ea9180 "security", verify_secret=1, out_flags=0x7fff7507857c, error=0x0) at nm-setting.c:1091
#3 0x00007fa4b0c1c2b2 in nm_setting_get_secret_flags (setting=0x1e3ac60, secret_name=0x1ea9180 "security", out_flags=0x7fff7507857c, error=0x0) at nm-setting.c:1124
#4 0x0000000000463d03 in for_each_secret (connection=0x1deb2f0, secrets=0x1e9f860, callback=0x464f1b <has_system_owned_secrets>, callback_data=0x7fff7507865c) at settings/nm-settings-connection.c:203
#5 0x000000000046525f in agent_secrets_done_cb (manager=0x1dddf50, call_id=1, agent_dbus_owner=0x1ddb9e0 ":1.39", agent_username=0x1e51710 "thom", agent_has_modify=1, setting_name=0x1e91f90 "802-11-wireless-security",
flags=NM_SETTINGS_GET_SECRETS_FLAG_ALLOW_INTERACTION, secrets=0x1e9f860, error=0x0, user_data=0x1deb2f0, other_data2=0x477d61 <get_secrets_cb>, other_data3=0x1ea92a0) at settings/nm-settings-connection.c:757
#6 0x00000000004dc4fd in get_complete_cb (parent=0x1ea6300, secrets=0x1e9f860, agent_dbus_owner=0x1ddb9e0 ":1.39", agent_username=0x1e51710 "thom", error=0x0, user_data=0x1dddf50) at settings/nm-agent-manager.c:1139
#7 0x00000000004dab54 in req_complete_success (req=0x1ea6300, secrets=0x1e9f860, agent_dbus_owner=0x1ddb9e0 ":1.39", agent_uname=0x1e51710 "thom") at settings/nm-agent-manager.c:502
#8 0x00000000004db86e in get_done_cb (agent=0x1e89530, call_id=0x1, secrets=0x1e9f860, error=0x0, user_data=0x1ea6300) at settings/nm-agent-manager.c:856
#9 0x00000000004de9d0 in get_callback (proxy=0x1e47530, call=0x1, user_data=0x1ea10f0) at settings/nm-secret-agent.c:267
#10 0x000000337380cad2 in complete_pending_call_and_unlock () from /lib64/libdbus-1.so.3
#11 0x000000337380fdc1 in dbus_connection_dispatch () from /lib64/libdbus-1.so.3
#12 0x000000342800ad65 in message_queue_dispatch () from /lib64/libdbus-glib-1.so.2
#13 0x0000003370c492a6 in g_main_context_dispatch () from /lib64/libglib-2.0.so.0
#14 0x0000003370c49628 in g_main_context_iterate.isra.24 () from /lib64/libglib-2.0.so.0
#15 0x0000003370c49a3a in g_main_loop_run () from /lib64/libglib-2.0.so.0
#16 0x000000000042e5c6 in main (argc=1, argv=0x7fff75078e88) at main.c:644
Signed-off-by: Thomas Haller <thaller@redhat.com>
2014-02-23 17:03:01 +01:00
|
|
|
g_return_val_if_fail (!NM_IS_SETTING_VPN (setting), FALSE);
|
|
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
/* Clear the secret if the user function says to do so */
|
libnm-util: don't assert in nm_setting_get_secret_flags() and avoid assertion in agent_secrets_done_cb()
When secret providers return the connection hash in GetSecrets(),
this hash should only contain secrets. However, some providers also
return non-secret properties.
for_each_secret() iterated over all entries of the @secrets hash
and triggered the assertion in nm_setting_get_secret_flags() (see
below).
NM should not assert against user provided input. Change
nm_setting_get_secret_flags() to silently return FALSE, if the property
is not a secret.
Indeed, handling of secrets is very different for NMSettingVpn and
others. Hence nm_setting_get_secret_flags() has only an inconsistent
behavior and we have to fix all call sites to do the right thing
(depending on whether we have a VPN setting or not).
Now for_each_secret() checks whether the property is a secret
without hitting the assertion. Adjust all other calls of
nm_setting_get_secret_flags(), to anticipate non-secret flags and
assert/warn where appropriate.
Also, agent_secrets_done_cb() clears now all non-secrets properties
from the hash, using the new argument @remove_non_secrets when calling
for_each_secret().
#0 0x0000003370c504e9 in g_logv () from /lib64/libglib-2.0.so.0
#1 0x0000003370c5063f in g_log () from /lib64/libglib-2.0.so.0
#2 0x00007fa4b0c1c156 in get_secret_flags (setting=0x1e3ac60, secret_name=0x1ea9180 "security", verify_secret=1, out_flags=0x7fff7507857c, error=0x0) at nm-setting.c:1091
#3 0x00007fa4b0c1c2b2 in nm_setting_get_secret_flags (setting=0x1e3ac60, secret_name=0x1ea9180 "security", out_flags=0x7fff7507857c, error=0x0) at nm-setting.c:1124
#4 0x0000000000463d03 in for_each_secret (connection=0x1deb2f0, secrets=0x1e9f860, callback=0x464f1b <has_system_owned_secrets>, callback_data=0x7fff7507865c) at settings/nm-settings-connection.c:203
#5 0x000000000046525f in agent_secrets_done_cb (manager=0x1dddf50, call_id=1, agent_dbus_owner=0x1ddb9e0 ":1.39", agent_username=0x1e51710 "thom", agent_has_modify=1, setting_name=0x1e91f90 "802-11-wireless-security",
flags=NM_SETTINGS_GET_SECRETS_FLAG_ALLOW_INTERACTION, secrets=0x1e9f860, error=0x0, user_data=0x1deb2f0, other_data2=0x477d61 <get_secrets_cb>, other_data3=0x1ea92a0) at settings/nm-settings-connection.c:757
#6 0x00000000004dc4fd in get_complete_cb (parent=0x1ea6300, secrets=0x1e9f860, agent_dbus_owner=0x1ddb9e0 ":1.39", agent_username=0x1e51710 "thom", error=0x0, user_data=0x1dddf50) at settings/nm-agent-manager.c:1139
#7 0x00000000004dab54 in req_complete_success (req=0x1ea6300, secrets=0x1e9f860, agent_dbus_owner=0x1ddb9e0 ":1.39", agent_uname=0x1e51710 "thom") at settings/nm-agent-manager.c:502
#8 0x00000000004db86e in get_done_cb (agent=0x1e89530, call_id=0x1, secrets=0x1e9f860, error=0x0, user_data=0x1ea6300) at settings/nm-agent-manager.c:856
#9 0x00000000004de9d0 in get_callback (proxy=0x1e47530, call=0x1, user_data=0x1ea10f0) at settings/nm-secret-agent.c:267
#10 0x000000337380cad2 in complete_pending_call_and_unlock () from /lib64/libdbus-1.so.3
#11 0x000000337380fdc1 in dbus_connection_dispatch () from /lib64/libdbus-1.so.3
#12 0x000000342800ad65 in message_queue_dispatch () from /lib64/libdbus-glib-1.so.2
#13 0x0000003370c492a6 in g_main_context_dispatch () from /lib64/libglib-2.0.so.0
#14 0x0000003370c49628 in g_main_context_iterate.isra.24 () from /lib64/libglib-2.0.so.0
#15 0x0000003370c49a3a in g_main_loop_run () from /lib64/libglib-2.0.so.0
#16 0x000000000042e5c6 in main (argc=1, argv=0x7fff75078e88) at main.c:644
Signed-off-by: Thomas Haller <thaller@redhat.com>
2014-02-23 17:03:01 +01:00
|
|
|
if (!nm_setting_get_secret_flags (setting, pspec->name, &flags, NULL))
|
|
|
|
|
g_return_val_if_reached (FALSE);
|
|
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
if (func (setting, pspec->name, flags, user_data) == TRUE) {
|
|
|
|
|
GValue value = G_VALUE_INIT;
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return changed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2014-10-07 08:46:36 +02:00
|
|
|
* _nm_setting_clear_secrets_with_flags:
|
2014-07-24 08:53:33 -04:00
|
|
|
* @setting: the #NMSetting
|
|
|
|
|
* @func: (scope call): function to be called to determine whether a
|
|
|
|
|
* specific secret should be cleared or not
|
|
|
|
|
* @user_data: caller-supplied data passed to @func
|
|
|
|
|
*
|
|
|
|
|
* Clears and frees secrets determined by @func.
|
2014-10-07 08:46:36 +02:00
|
|
|
*
|
|
|
|
|
* Returns: %TRUE if the setting changed at all
|
2014-07-24 08:53:33 -04:00
|
|
|
**/
|
|
|
|
|
gboolean
|
|
|
|
|
_nm_setting_clear_secrets_with_flags (NMSetting *setting,
|
|
|
|
|
NMSettingClearSecretsWithFlagsFn func,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
GParamSpec **property_specs;
|
|
|
|
|
guint n_property_specs;
|
|
|
|
|
guint i;
|
|
|
|
|
gboolean changed = FALSE;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (setting, FALSE);
|
|
|
|
|
g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
|
|
|
|
|
g_return_val_if_fail (func != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs);
|
|
|
|
|
for (i = 0; i < n_property_specs; i++) {
|
|
|
|
|
if (property_specs[i]->flags & NM_SETTING_PARAM_SECRET) {
|
|
|
|
|
changed |= NM_SETTING_GET_CLASS (setting)->clear_secrets_with_flags (setting,
|
|
|
|
|
property_specs[i],
|
|
|
|
|
func,
|
|
|
|
|
user_data);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_free (property_specs);
|
|
|
|
|
return changed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2014-10-07 08:46:36 +02:00
|
|
|
* _nm_setting_need_secrets:
|
2014-07-24 08:53:33 -04:00
|
|
|
* @setting: the #NMSetting
|
|
|
|
|
*
|
|
|
|
|
* Returns an array of property names for each secret which may be required
|
|
|
|
|
* to make a successful connection. The returned hints are only intended as a
|
|
|
|
|
* guide to what secrets may be required, because in some circumstances, there
|
|
|
|
|
* is no way to conclusively determine exactly which secrets are needed.
|
|
|
|
|
*
|
|
|
|
|
* Returns: (transfer container) (element-type utf8): a #GPtrArray containing
|
|
|
|
|
* the property names of secrets of the #NMSetting which may be required; the
|
|
|
|
|
* caller owns the array and must free it with g_ptr_array_free(), but must not
|
|
|
|
|
* free the elements.
|
|
|
|
|
**/
|
|
|
|
|
GPtrArray *
|
2014-10-07 08:46:36 +02:00
|
|
|
_nm_setting_need_secrets (NMSetting *setting)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
|
|
|
|
GPtrArray *secrets = NULL;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
|
|
|
|
|
|
|
|
|
|
if (NM_SETTING_GET_CLASS (setting)->need_secrets)
|
|
|
|
|
secrets = NM_SETTING_GET_CLASS (setting)->need_secrets (setting);
|
|
|
|
|
|
|
|
|
|
return secrets;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
2014-08-16 10:09:48 -04:00
|
|
|
update_one_secret (NMSetting *setting, const char *key, GVariant *value, GError **error)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
const NMSettingProperty *property;
|
2014-07-24 08:53:33 -04:00
|
|
|
GParamSpec *prop_spec;
|
2014-08-16 10:09:48 -04:00
|
|
|
GValue prop_value = { 0, };
|
2014-07-24 08:53:33 -04:00
|
|
|
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
property = nm_setting_class_find_property (NM_SETTING_GET_CLASS (setting), key);
|
|
|
|
|
if (!property) {
|
libnm-core: merge NMSetting*Error into NMConnectionError
Each setting type was defining its own error type, but most of them
had exactly the same three errors ("unknown", "missing property", and
"invalid property"), and none of the other values was of much use
programmatically anyway.
So, this commit merges NMSettingError, NMSettingAdslError, etc, all
into NMConnectionError. (The reason for merging into NMConnectionError
rather than NMSettingError is that we also already have
"NMSettingsError", for errors related to the settings service, so
"NMConnectionError" is a less-confusable name for settings/connection
errors than "NMSettingError".)
Also, make sure that all of the affected error messages are localized,
and (where appropriate) prefix them with the relevant property name.
Renamed error codes:
NM_SETTING_ERROR_PROPERTY_NOT_FOUND -> NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND
NM_SETTING_ERROR_PROPERTY_NOT_SECRET -> NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET
Remapped error codes:
NM_SETTING_*_ERROR_MISSING_PROPERTY -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_*_ERROR_INVALID_PROPERTY -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BLUETOOTH_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_INVALID_SETTING
NM_SETTING_BOND_ERROR_INVALID_OPTION -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BOND_ERROR_MISSING_OPTION -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_CONNECTION_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_CONNECTION_ERROR_SLAVE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_IP4_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_VLAN_ERROR_INVALID_PARENT -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_MISSING_802_1X_SETTING -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_802_1X -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_SHARED_KEY_REQUIRES_WEP -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_ERROR_CHANNEL_REQUIRES_BAND -> NM_CONNECTION_ERROR_MISSING_PROPERTY
Dropped error codes (were previously defined but unused):
NM_SETTING_CDMA_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_CONNECTION_ERROR_IP_CONFIG_NOT_ALLOWED
NM_SETTING_GSM_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_PPP_ERROR_REQUIRE_MPPE_NOT_ALLOWED
NM_SETTING_PPPOE_ERROR_MISSING_PPP_SETTING
NM_SETTING_SERIAL_ERROR_MISSING_PPP_SETTING
NM_SETTING_WIRELESS_ERROR_MISSING_SECURITY_SETTING
2014-10-20 13:52:23 -04:00
|
|
|
g_set_error_literal (error,
|
|
|
|
|
NM_CONNECTION_ERROR,
|
|
|
|
|
NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND,
|
|
|
|
|
_("secret not found"));
|
|
|
|
|
g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), key);
|
2014-07-24 08:53:33 -04:00
|
|
|
return NM_SETTING_UPDATE_SECRET_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Silently ignore non-secrets */
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
prop_spec = property->param_spec;
|
|
|
|
|
if (!prop_spec || !(prop_spec->flags & NM_SETTING_PARAM_SECRET))
|
2014-07-24 08:53:33 -04:00
|
|
|
return NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED;
|
|
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
if ( g_variant_is_of_type (value, G_VARIANT_TYPE_STRING)
|
|
|
|
|
&& G_IS_PARAM_SPEC_STRING (prop_spec)) {
|
|
|
|
|
/* String is expected to be a common case. Handle it specially and check
|
|
|
|
|
* whether the value is already set. Otherwise, we just reset the
|
|
|
|
|
* property and assume the value got modified.
|
|
|
|
|
*/
|
|
|
|
|
char *v;
|
|
|
|
|
|
|
|
|
|
g_object_get (G_OBJECT (setting), prop_spec->name, &v, NULL);
|
|
|
|
|
if (g_strcmp0 (v, g_variant_get_string (value, NULL)) == 0) {
|
2014-07-24 08:53:33 -04:00
|
|
|
g_free (v);
|
2014-08-16 10:09:48 -04:00
|
|
|
return NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED;
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
2014-08-16 10:09:48 -04:00
|
|
|
g_free (v);
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
2014-08-16 10:09:48 -04:00
|
|
|
|
|
|
|
|
g_value_init (&prop_value, prop_spec->value_type);
|
|
|
|
|
set_property_from_dbus (property, value, &prop_value);
|
|
|
|
|
g_object_set_property (G_OBJECT (setting), prop_spec->name, &prop_value);
|
|
|
|
|
g_value_unset (&prop_value);
|
|
|
|
|
|
|
|
|
|
return NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED;
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2014-08-04 11:23:11 -04:00
|
|
|
* _nm_setting_update_secrets:
|
2014-07-24 08:53:33 -04:00
|
|
|
* @setting: the #NMSetting
|
2014-08-16 10:09:48 -04:00
|
|
|
* @secrets: a #GVariant of type #NM_VARIANT_TYPE_SETTING, mapping property
|
|
|
|
|
* names to secrets.
|
2014-07-24 08:53:33 -04:00
|
|
|
* @error: location to store error, or %NULL
|
|
|
|
|
*
|
2014-08-16 10:09:48 -04:00
|
|
|
* Update the setting's secrets, given a dictionary of secrets intended for that
|
2014-07-24 08:53:33 -04:00
|
|
|
* setting (deserialized from D-Bus for example).
|
|
|
|
|
*
|
2014-08-04 11:23:11 -04:00
|
|
|
* Returns: an #NMSettingUpdateSecretResult
|
2014-07-24 08:53:33 -04:00
|
|
|
**/
|
|
|
|
|
NMSettingUpdateSecretResult
|
2014-08-16 10:09:48 -04:00
|
|
|
_nm_setting_update_secrets (NMSetting *setting, GVariant *secrets, GError **error)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
2014-08-16 10:09:48 -04:00
|
|
|
GVariantIter iter;
|
|
|
|
|
const char *secret_key;
|
|
|
|
|
GVariant *secret_value;
|
2014-07-24 08:53:33 -04:00
|
|
|
GError *tmp_error = NULL;
|
|
|
|
|
NMSettingUpdateSecretResult result = NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_SETTING (setting), NM_SETTING_UPDATE_SECRET_ERROR);
|
2014-08-16 10:09:48 -04:00
|
|
|
g_return_val_if_fail (g_variant_is_of_type (secrets, NM_VARIANT_TYPE_SETTING), NM_SETTING_UPDATE_SECRET_ERROR);
|
2014-07-24 08:53:33 -04:00
|
|
|
if (error)
|
|
|
|
|
g_return_val_if_fail (*error == NULL, NM_SETTING_UPDATE_SECRET_ERROR);
|
|
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
g_variant_iter_init (&iter, secrets);
|
|
|
|
|
while (g_variant_iter_next (&iter, "{&sv}", &secret_key, &secret_value)) {
|
2014-07-24 08:53:33 -04:00
|
|
|
int success;
|
|
|
|
|
|
|
|
|
|
success = NM_SETTING_GET_CLASS (setting)->update_one_secret (setting, secret_key, secret_value, &tmp_error);
|
|
|
|
|
g_assert (!((success == NM_SETTING_UPDATE_SECRET_ERROR) ^ (!!tmp_error)));
|
|
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
g_variant_unref (secret_value);
|
|
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
if (success == NM_SETTING_UPDATE_SECRET_ERROR) {
|
|
|
|
|
g_propagate_error (error, tmp_error);
|
|
|
|
|
return NM_SETTING_UPDATE_SECRET_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (success == NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED)
|
|
|
|
|
result = NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
is_secret_prop (NMSetting *setting, const char *secret_name, GError **error)
|
|
|
|
|
{
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
const NMSettingProperty *property;
|
2014-07-24 08:53:33 -04:00
|
|
|
GParamSpec *pspec;
|
|
|
|
|
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
property = nm_setting_class_find_property (NM_SETTING_GET_CLASS (setting), secret_name);
|
|
|
|
|
if (!property) {
|
libnm-core: merge NMSetting*Error into NMConnectionError
Each setting type was defining its own error type, but most of them
had exactly the same three errors ("unknown", "missing property", and
"invalid property"), and none of the other values was of much use
programmatically anyway.
So, this commit merges NMSettingError, NMSettingAdslError, etc, all
into NMConnectionError. (The reason for merging into NMConnectionError
rather than NMSettingError is that we also already have
"NMSettingsError", for errors related to the settings service, so
"NMConnectionError" is a less-confusable name for settings/connection
errors than "NMSettingError".)
Also, make sure that all of the affected error messages are localized,
and (where appropriate) prefix them with the relevant property name.
Renamed error codes:
NM_SETTING_ERROR_PROPERTY_NOT_FOUND -> NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND
NM_SETTING_ERROR_PROPERTY_NOT_SECRET -> NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET
Remapped error codes:
NM_SETTING_*_ERROR_MISSING_PROPERTY -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_*_ERROR_INVALID_PROPERTY -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BLUETOOTH_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_INVALID_SETTING
NM_SETTING_BOND_ERROR_INVALID_OPTION -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BOND_ERROR_MISSING_OPTION -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_CONNECTION_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_CONNECTION_ERROR_SLAVE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_IP4_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_VLAN_ERROR_INVALID_PARENT -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_MISSING_802_1X_SETTING -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_802_1X -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_SHARED_KEY_REQUIRES_WEP -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_ERROR_CHANNEL_REQUIRES_BAND -> NM_CONNECTION_ERROR_MISSING_PROPERTY
Dropped error codes (were previously defined but unused):
NM_SETTING_CDMA_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_CONNECTION_ERROR_IP_CONFIG_NOT_ALLOWED
NM_SETTING_GSM_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_PPP_ERROR_REQUIRE_MPPE_NOT_ALLOWED
NM_SETTING_PPPOE_ERROR_MISSING_PPP_SETTING
NM_SETTING_SERIAL_ERROR_MISSING_PPP_SETTING
NM_SETTING_WIRELESS_ERROR_MISSING_SECURITY_SETTING
2014-10-20 13:52:23 -04:00
|
|
|
g_set_error_literal (error,
|
|
|
|
|
NM_CONNECTION_ERROR,
|
|
|
|
|
NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND,
|
|
|
|
|
_("secret is not set"));
|
|
|
|
|
g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), secret_name);
|
2014-07-24 08:53:33 -04:00
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
pspec = property->param_spec;
|
|
|
|
|
if (!pspec || !(pspec->flags & NM_SETTING_PARAM_SECRET)) {
|
libnm-core: merge NMSetting*Error into NMConnectionError
Each setting type was defining its own error type, but most of them
had exactly the same three errors ("unknown", "missing property", and
"invalid property"), and none of the other values was of much use
programmatically anyway.
So, this commit merges NMSettingError, NMSettingAdslError, etc, all
into NMConnectionError. (The reason for merging into NMConnectionError
rather than NMSettingError is that we also already have
"NMSettingsError", for errors related to the settings service, so
"NMConnectionError" is a less-confusable name for settings/connection
errors than "NMSettingError".)
Also, make sure that all of the affected error messages are localized,
and (where appropriate) prefix them with the relevant property name.
Renamed error codes:
NM_SETTING_ERROR_PROPERTY_NOT_FOUND -> NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND
NM_SETTING_ERROR_PROPERTY_NOT_SECRET -> NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET
Remapped error codes:
NM_SETTING_*_ERROR_MISSING_PROPERTY -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_*_ERROR_INVALID_PROPERTY -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BLUETOOTH_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_INVALID_SETTING
NM_SETTING_BOND_ERROR_INVALID_OPTION -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BOND_ERROR_MISSING_OPTION -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_CONNECTION_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_CONNECTION_ERROR_SLAVE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_IP4_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_VLAN_ERROR_INVALID_PARENT -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_MISSING_802_1X_SETTING -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_802_1X -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_SHARED_KEY_REQUIRES_WEP -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_ERROR_CHANNEL_REQUIRES_BAND -> NM_CONNECTION_ERROR_MISSING_PROPERTY
Dropped error codes (were previously defined but unused):
NM_SETTING_CDMA_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_CONNECTION_ERROR_IP_CONFIG_NOT_ALLOWED
NM_SETTING_GSM_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_PPP_ERROR_REQUIRE_MPPE_NOT_ALLOWED
NM_SETTING_PPPOE_ERROR_MISSING_PPP_SETTING
NM_SETTING_SERIAL_ERROR_MISSING_PPP_SETTING
NM_SETTING_WIRELESS_ERROR_MISSING_SECURITY_SETTING
2014-10-20 13:52:23 -04:00
|
|
|
g_set_error_literal (error,
|
|
|
|
|
NM_CONNECTION_ERROR,
|
|
|
|
|
NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET,
|
|
|
|
|
_("not a secret property"));
|
|
|
|
|
g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), secret_name);
|
2014-07-24 08:53:33 -04:00
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
get_secret_flags (NMSetting *setting,
|
|
|
|
|
const char *secret_name,
|
|
|
|
|
gboolean verify_secret,
|
|
|
|
|
NMSettingSecretFlags *out_flags,
|
|
|
|
|
GError **error)
|
|
|
|
|
{
|
|
|
|
|
char *flags_prop;
|
|
|
|
|
NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;
|
|
|
|
|
|
libnm-util: don't assert in nm_setting_get_secret_flags() and avoid assertion in agent_secrets_done_cb()
When secret providers return the connection hash in GetSecrets(),
this hash should only contain secrets. However, some providers also
return non-secret properties.
for_each_secret() iterated over all entries of the @secrets hash
and triggered the assertion in nm_setting_get_secret_flags() (see
below).
NM should not assert against user provided input. Change
nm_setting_get_secret_flags() to silently return FALSE, if the property
is not a secret.
Indeed, handling of secrets is very different for NMSettingVpn and
others. Hence nm_setting_get_secret_flags() has only an inconsistent
behavior and we have to fix all call sites to do the right thing
(depending on whether we have a VPN setting or not).
Now for_each_secret() checks whether the property is a secret
without hitting the assertion. Adjust all other calls of
nm_setting_get_secret_flags(), to anticipate non-secret flags and
assert/warn where appropriate.
Also, agent_secrets_done_cb() clears now all non-secrets properties
from the hash, using the new argument @remove_non_secrets when calling
for_each_secret().
#0 0x0000003370c504e9 in g_logv () from /lib64/libglib-2.0.so.0
#1 0x0000003370c5063f in g_log () from /lib64/libglib-2.0.so.0
#2 0x00007fa4b0c1c156 in get_secret_flags (setting=0x1e3ac60, secret_name=0x1ea9180 "security", verify_secret=1, out_flags=0x7fff7507857c, error=0x0) at nm-setting.c:1091
#3 0x00007fa4b0c1c2b2 in nm_setting_get_secret_flags (setting=0x1e3ac60, secret_name=0x1ea9180 "security", out_flags=0x7fff7507857c, error=0x0) at nm-setting.c:1124
#4 0x0000000000463d03 in for_each_secret (connection=0x1deb2f0, secrets=0x1e9f860, callback=0x464f1b <has_system_owned_secrets>, callback_data=0x7fff7507865c) at settings/nm-settings-connection.c:203
#5 0x000000000046525f in agent_secrets_done_cb (manager=0x1dddf50, call_id=1, agent_dbus_owner=0x1ddb9e0 ":1.39", agent_username=0x1e51710 "thom", agent_has_modify=1, setting_name=0x1e91f90 "802-11-wireless-security",
flags=NM_SETTINGS_GET_SECRETS_FLAG_ALLOW_INTERACTION, secrets=0x1e9f860, error=0x0, user_data=0x1deb2f0, other_data2=0x477d61 <get_secrets_cb>, other_data3=0x1ea92a0) at settings/nm-settings-connection.c:757
#6 0x00000000004dc4fd in get_complete_cb (parent=0x1ea6300, secrets=0x1e9f860, agent_dbus_owner=0x1ddb9e0 ":1.39", agent_username=0x1e51710 "thom", error=0x0, user_data=0x1dddf50) at settings/nm-agent-manager.c:1139
#7 0x00000000004dab54 in req_complete_success (req=0x1ea6300, secrets=0x1e9f860, agent_dbus_owner=0x1ddb9e0 ":1.39", agent_uname=0x1e51710 "thom") at settings/nm-agent-manager.c:502
#8 0x00000000004db86e in get_done_cb (agent=0x1e89530, call_id=0x1, secrets=0x1e9f860, error=0x0, user_data=0x1ea6300) at settings/nm-agent-manager.c:856
#9 0x00000000004de9d0 in get_callback (proxy=0x1e47530, call=0x1, user_data=0x1ea10f0) at settings/nm-secret-agent.c:267
#10 0x000000337380cad2 in complete_pending_call_and_unlock () from /lib64/libdbus-1.so.3
#11 0x000000337380fdc1 in dbus_connection_dispatch () from /lib64/libdbus-1.so.3
#12 0x000000342800ad65 in message_queue_dispatch () from /lib64/libdbus-glib-1.so.2
#13 0x0000003370c492a6 in g_main_context_dispatch () from /lib64/libglib-2.0.so.0
#14 0x0000003370c49628 in g_main_context_iterate.isra.24 () from /lib64/libglib-2.0.so.0
#15 0x0000003370c49a3a in g_main_loop_run () from /lib64/libglib-2.0.so.0
#16 0x000000000042e5c6 in main (argc=1, argv=0x7fff75078e88) at main.c:644
Signed-off-by: Thomas Haller <thaller@redhat.com>
2014-02-23 17:03:01 +01:00
|
|
|
if (verify_secret && !is_secret_prop (setting, secret_name, error)) {
|
|
|
|
|
if (out_flags)
|
|
|
|
|
*out_flags = NM_SETTING_SECRET_FLAG_NONE;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
flags_prop = g_strdup_printf ("%s-flags", secret_name);
|
|
|
|
|
g_object_get (G_OBJECT (setting), flags_prop, &flags, NULL);
|
|
|
|
|
g_free (flags_prop);
|
|
|
|
|
|
|
|
|
|
if (out_flags)
|
|
|
|
|
*out_flags = flags;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_setting_get_secret_flags:
|
|
|
|
|
* @setting: the #NMSetting
|
|
|
|
|
* @secret_name: the secret key name to get flags for
|
|
|
|
|
* @out_flags: on success, the #NMSettingSecretFlags for the secret
|
|
|
|
|
* @error: location to store error, or %NULL
|
|
|
|
|
*
|
|
|
|
|
* For a given secret, retrieves the #NMSettingSecretFlags describing how to
|
|
|
|
|
* handle that secret.
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE on success (if the given secret name was a valid property of
|
|
|
|
|
* this setting, and if that property is secret), %FALSE if not
|
|
|
|
|
**/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_setting_get_secret_flags (NMSetting *setting,
|
|
|
|
|
const char *secret_name,
|
|
|
|
|
NMSettingSecretFlags *out_flags,
|
|
|
|
|
GError **error)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
|
|
|
|
|
g_return_val_if_fail (secret_name != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
return NM_SETTING_GET_CLASS (setting)->get_secret_flags (setting, secret_name, TRUE, out_flags, error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
set_secret_flags (NMSetting *setting,
|
|
|
|
|
const char *secret_name,
|
|
|
|
|
gboolean verify_secret,
|
|
|
|
|
NMSettingSecretFlags flags,
|
|
|
|
|
GError **error)
|
|
|
|
|
{
|
|
|
|
|
char *flags_prop;
|
|
|
|
|
|
|
|
|
|
if (verify_secret)
|
|
|
|
|
g_return_val_if_fail (is_secret_prop (setting, secret_name, error), FALSE);
|
|
|
|
|
|
|
|
|
|
flags_prop = g_strdup_printf ("%s-flags", secret_name);
|
|
|
|
|
g_object_set (G_OBJECT (setting), flags_prop, flags, NULL);
|
|
|
|
|
g_free (flags_prop);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_setting_set_secret_flags:
|
|
|
|
|
* @setting: the #NMSetting
|
|
|
|
|
* @secret_name: the secret key name to set flags for
|
|
|
|
|
* @flags: the #NMSettingSecretFlags for the secret
|
|
|
|
|
* @error: location to store error, or %NULL
|
|
|
|
|
*
|
|
|
|
|
* For a given secret, stores the #NMSettingSecretFlags describing how to
|
|
|
|
|
* handle that secret.
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE on success (if the given secret name was a valid property of
|
|
|
|
|
* this setting, and if that property is secret), %FALSE if not
|
|
|
|
|
**/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_setting_set_secret_flags (NMSetting *setting,
|
|
|
|
|
const char *secret_name,
|
|
|
|
|
NMSettingSecretFlags flags,
|
|
|
|
|
GError **error)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
|
|
|
|
|
g_return_val_if_fail (secret_name != NULL, FALSE);
|
|
|
|
|
g_return_val_if_fail (flags <= NM_SETTING_SECRET_FLAGS_ALL, FALSE);
|
|
|
|
|
|
|
|
|
|
return NM_SETTING_GET_CLASS (setting)->set_secret_flags (setting, secret_name, TRUE, flags, error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_setting_to_string:
|
|
|
|
|
* @setting: the #NMSetting
|
|
|
|
|
*
|
|
|
|
|
* Convert the setting into a string. For debugging purposes ONLY, should NOT
|
|
|
|
|
* be used for serialization of the setting, or machine-parsed in any way. The
|
|
|
|
|
* output format is not guaranteed to be stable and may change at any time.
|
|
|
|
|
*
|
|
|
|
|
* Returns: an allocated string containing a textual representation of the
|
|
|
|
|
* setting's properties and values (including secrets!), which the caller should
|
|
|
|
|
* free with g_free()
|
|
|
|
|
**/
|
|
|
|
|
char *
|
|
|
|
|
nm_setting_to_string (NMSetting *setting)
|
|
|
|
|
{
|
|
|
|
|
GString *string;
|
|
|
|
|
GParamSpec **property_specs;
|
|
|
|
|
guint n_property_specs;
|
|
|
|
|
guint i;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
|
|
|
|
|
|
|
|
|
|
property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs);
|
|
|
|
|
|
|
|
|
|
string = g_string_new (nm_setting_get_name (setting));
|
|
|
|
|
g_string_append_c (string, '\n');
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < n_property_specs; i++) {
|
|
|
|
|
GParamSpec *prop_spec = property_specs[i];
|
|
|
|
|
GValue value = G_VALUE_INIT;
|
|
|
|
|
char *value_str;
|
|
|
|
|
gboolean is_default;
|
|
|
|
|
|
|
|
|
|
if (strcmp (prop_spec->name, NM_SETTING_NAME) == 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
g_value_init (&value, prop_spec->value_type);
|
|
|
|
|
g_object_get_property (G_OBJECT (setting), prop_spec->name, &value);
|
|
|
|
|
|
|
|
|
|
value_str = g_strdup_value_contents (&value);
|
|
|
|
|
g_string_append_printf (string, "\t%s : %s", prop_spec->name, value_str);
|
|
|
|
|
g_free (value_str);
|
|
|
|
|
|
|
|
|
|
is_default = g_param_value_defaults (prop_spec, &value);
|
|
|
|
|
g_value_unset (&value);
|
|
|
|
|
|
|
|
|
|
g_string_append (string, " (");
|
|
|
|
|
g_string_append_c (string, 's');
|
|
|
|
|
if (is_default)
|
|
|
|
|
g_string_append_c (string, 'd');
|
|
|
|
|
g_string_append_c (string, ')');
|
|
|
|
|
g_string_append_c (string, '\n');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_free (property_specs);
|
|
|
|
|
g_string_append_c (string, '\n');
|
|
|
|
|
|
|
|
|
|
return g_string_free (string, FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-08 15:01:54 +02:00
|
|
|
NMSetting *
|
|
|
|
|
_nm_setting_find_in_list_required (GSList *all_settings,
|
|
|
|
|
const char *setting_name,
|
2014-10-11 15:02:16 -04:00
|
|
|
GError **error)
|
2014-07-08 15:01:54 +02:00
|
|
|
{
|
|
|
|
|
NMSetting *setting;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (!error || !*error, NULL);
|
|
|
|
|
g_return_val_if_fail (all_settings, NULL);
|
|
|
|
|
g_return_val_if_fail (setting_name, NULL);
|
|
|
|
|
|
|
|
|
|
setting = nm_setting_find_in_list (all_settings, setting_name);
|
|
|
|
|
if (!setting) {
|
2014-10-11 15:02:16 -04:00
|
|
|
g_set_error_literal (error,
|
|
|
|
|
NM_CONNECTION_ERROR,
|
|
|
|
|
NM_CONNECTION_ERROR_MISSING_SETTING,
|
|
|
|
|
_("missing setting"));
|
|
|
|
|
g_prefix_error (error, "%s: ", setting_name);
|
2014-07-08 15:01:54 +02:00
|
|
|
}
|
|
|
|
|
return setting;
|
|
|
|
|
}
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
NMSettingVerifyResult
|
2014-08-04 19:57:20 -04:00
|
|
|
_nm_setting_verify_required_virtual_interface_name (GSList *all_settings,
|
|
|
|
|
GError **error)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
|
|
|
|
NMSettingConnection *s_con;
|
2014-08-04 19:57:20 -04:00
|
|
|
const char *interface_name;
|
2014-08-13 02:38:09 +02:00
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
s_con = NM_SETTING_CONNECTION (nm_setting_find_in_list (all_settings, NM_SETTING_CONNECTION_SETTING_NAME));
|
2014-08-04 19:57:20 -04:00
|
|
|
interface_name = s_con ? nm_setting_connection_get_interface_name (s_con) : NULL;
|
|
|
|
|
if (!interface_name) {
|
2014-07-24 08:53:33 -04:00
|
|
|
g_set_error_literal (error,
|
libnm-core: merge NMSetting*Error into NMConnectionError
Each setting type was defining its own error type, but most of them
had exactly the same three errors ("unknown", "missing property", and
"invalid property"), and none of the other values was of much use
programmatically anyway.
So, this commit merges NMSettingError, NMSettingAdslError, etc, all
into NMConnectionError. (The reason for merging into NMConnectionError
rather than NMSettingError is that we also already have
"NMSettingsError", for errors related to the settings service, so
"NMConnectionError" is a less-confusable name for settings/connection
errors than "NMSettingError".)
Also, make sure that all of the affected error messages are localized,
and (where appropriate) prefix them with the relevant property name.
Renamed error codes:
NM_SETTING_ERROR_PROPERTY_NOT_FOUND -> NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND
NM_SETTING_ERROR_PROPERTY_NOT_SECRET -> NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET
Remapped error codes:
NM_SETTING_*_ERROR_MISSING_PROPERTY -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_*_ERROR_INVALID_PROPERTY -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BLUETOOTH_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_INVALID_SETTING
NM_SETTING_BOND_ERROR_INVALID_OPTION -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BOND_ERROR_MISSING_OPTION -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_CONNECTION_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_CONNECTION_ERROR_SLAVE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_IP4_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_VLAN_ERROR_INVALID_PARENT -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_MISSING_802_1X_SETTING -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_802_1X -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_SHARED_KEY_REQUIRES_WEP -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_ERROR_CHANNEL_REQUIRES_BAND -> NM_CONNECTION_ERROR_MISSING_PROPERTY
Dropped error codes (were previously defined but unused):
NM_SETTING_CDMA_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_CONNECTION_ERROR_IP_CONFIG_NOT_ALLOWED
NM_SETTING_GSM_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_PPP_ERROR_REQUIRE_MPPE_NOT_ALLOWED
NM_SETTING_PPPOE_ERROR_MISSING_PPP_SETTING
NM_SETTING_SERIAL_ERROR_MISSING_PPP_SETTING
NM_SETTING_WIRELESS_ERROR_MISSING_SECURITY_SETTING
2014-10-20 13:52:23 -04:00
|
|
|
NM_CONNECTION_ERROR,
|
|
|
|
|
NM_CONNECTION_ERROR_MISSING_PROPERTY,
|
2014-07-24 08:53:33 -04:00
|
|
|
_("property is missing"));
|
|
|
|
|
g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_INTERFACE_NAME);
|
|
|
|
|
return NM_SETTING_VERIFY_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NM_SETTING_VERIFY_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
GVariant *
|
2014-08-04 19:57:20 -04:00
|
|
|
_nm_setting_get_deprecated_virtual_interface_name (NMSetting *setting,
|
|
|
|
|
NMConnection *connection,
|
2014-08-16 10:09:48 -04:00
|
|
|
const char *property)
|
2014-08-04 19:57:20 -04:00
|
|
|
{
|
|
|
|
|
NMSettingConnection *s_con;
|
|
|
|
|
|
|
|
|
|
s_con = nm_connection_get_setting_connection (connection);
|
2014-08-16 10:09:48 -04:00
|
|
|
g_return_val_if_fail (s_con != NULL, NULL);
|
2014-08-04 19:57:20 -04:00
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
if (nm_setting_connection_get_interface_name (s_con))
|
|
|
|
|
return g_variant_new_string (nm_setting_connection_get_interface_name (s_con));
|
|
|
|
|
else
|
|
|
|
|
return NULL;
|
2014-08-04 19:57:20 -04:00
|
|
|
}
|
|
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
nm_setting_init (NMSetting *setting)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-15 14:25:07 -04:00
|
|
|
static void
|
|
|
|
|
constructed (GObject *object)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
|
|
|
|
_ensure_setting_info (object, NM_SETTING_GET_PRIVATE (object));
|
2014-05-15 14:25:07 -04:00
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (nm_setting_parent_class)->constructed (object);
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
get_property (GObject *object, guint prop_id,
|
|
|
|
|
GValue *value, GParamSpec *pspec)
|
|
|
|
|
{
|
|
|
|
|
NMSetting *setting = NM_SETTING (object);
|
|
|
|
|
|
|
|
|
|
switch (prop_id) {
|
|
|
|
|
case PROP_NAME:
|
|
|
|
|
g_value_set_string (value, nm_setting_get_name (setting));
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
nm_setting_class_init (NMSettingClass *setting_class)
|
|
|
|
|
{
|
|
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
|
|
|
|
|
|
libnm-core: add dbus-only properties to NMSettingClass
Add _nm_setting_class_add_dbus_only_property(), for declaring
properties that appear in the D-Bus serialization, but which don't
correspond to GObject properties.
Since some property overrides will require examining settings other
than the setting that they are on (eg, the value of
802-11-wireless.security depends on whether an
NMSettingWirelessSecurity setting is present, and
NMSettingConnection:interface-name might sometimes be set from, eg,
bond.interface-name), we also update _nm_setting_to_dbus() to take the
full NMConnection as an argument, and _nm_setting_new_from_dbus() to
take the full connection hash.
Additionally, with some deprecated properties, we'll want to validate
them on construction, but we don't need to keep the value around after
that. So allow _nm_setting_new_from_dbus() to return a verification
error directly, so we don't need to store the value until the verify()
call.
2014-07-29 18:25:10 -04:00
|
|
|
if (!setting_property_overrides_quark)
|
|
|
|
|
setting_property_overrides_quark = g_quark_from_static_string ("nm-setting-property-overrides");
|
|
|
|
|
if (!setting_properties_quark)
|
|
|
|
|
setting_properties_quark = g_quark_from_static_string ("nm-setting-properties");
|
|
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
g_type_class_add_private (setting_class, sizeof (NMSettingPrivate));
|
|
|
|
|
|
|
|
|
|
/* virtual methods */
|
2014-05-15 14:25:07 -04:00
|
|
|
object_class->constructed = constructed;
|
2014-07-24 08:53:33 -04:00
|
|
|
object_class->get_property = get_property;
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
/* Properties */
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* NMSetting:name:
|
|
|
|
|
*
|
|
|
|
|
* The setting's name, which uniquely identifies the setting within the
|
|
|
|
|
* connection. Each setting type has a name unique to that type, for
|
|
|
|
|
* example "ppp" or "wireless" or "wired".
|
|
|
|
|
**/
|
|
|
|
|
g_object_class_install_property
|
|
|
|
|
(object_class, PROP_NAME,
|
|
|
|
|
g_param_spec_string (NM_SETTING_NAME, "", "",
|
|
|
|
|
NULL,
|
2014-05-09 15:02:57 -04:00
|
|
|
G_PARAM_READABLE |
|
2014-07-24 08:53:33 -04:00
|
|
|
G_PARAM_STATIC_STRINGS));
|
|
|
|
|
}
|