1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301 USA.
19 * Copyright 2007 - 2011 Red Hat, Inc.
20 * Copyright 2007 - 2008 Novell, Inc.
23 #include "nm-default.h"
25 #include "nm-setting.h"
29 #include "nm-setting-private.h"
31 #include "nm-core-internal.h"
32 #include "nm-utils-private.h"
33 #include "nm-property-compare.h"
35 #include "nm-setting-connection.h"
36 #include "nm-setting-bond.h"
37 #include "nm-setting-bridge.h"
38 #include "nm-setting-bridge-port.h"
39 #include "nm-setting-pppoe.h"
40 #include "nm-setting-team.h"
41 #include "nm-setting-team-port.h"
42 #include "nm-setting-vpn.h"
46 * @short_description: Describes related configuration information
48 * Each #NMSetting contains properties that describe configuration that applies
49 * to a specific network layer (like IPv4 or IPv6 configuration) or device type
50 * (like Ethernet, or Wi-Fi). A collection of individual settings together
51 * make up an #NMConnection. Each property is strongly typed and usually has
52 * a number of allowed values. See each #NMSetting subclass for a description
53 * of properties and allowed values.
56 G_DEFINE_ABSTRACT_TYPE (NMSetting, nm_setting, G_TYPE_OBJECT)
58 #define NM_SETTING_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING, NMSettingPrivate))
67 const SettingInfo *info;
77 /*************************************************************/
79 static GHashTable *registered_settings = NULL;
80 static GHashTable *registered_settings_by_type = NULL;
83 _nm_gtype_equal (gconstpointer v1, gconstpointer v2)
85 return *((const GType *) v1) == *((const GType *) v2);
88 _nm_gtype_hash (gconstpointer v)
90 return *((const GType *) v);
94 _ensure_registered (void)
96 if (G_UNLIKELY (registered_settings == NULL)) {
98 registered_settings = g_hash_table_new (g_str_hash, g_str_equal);
99 registered_settings_by_type = g_hash_table_new (_nm_gtype_hash, _nm_gtype_equal);
103 static void __attribute__((constructor))
104 _ensure_registered_constructor (void)
106 _ensure_registered ();
109 #define _ensure_setting_info(self, priv) \
111 NMSettingPrivate *_priv_esi = (priv); \
112 if (G_UNLIKELY (!_priv_esi->info)) { \
113 _priv_esi->info = _nm_setting_lookup_setting_by_type (G_OBJECT_TYPE (self)); \
114 g_assert (_priv_esi->info); \
118 /*************************************************************/
121 * _nm_register_setting:
122 * @name: the name of the #NMSetting object to register
123 * @type: the #GType of the #NMSetting
124 * @priority: the sort priority of the setting, see below
126 * INTERNAL ONLY: registers a setting's internal properties with libnm.
128 * A setting's priority should roughly follow the OSI layer model, but it also
129 * controls which settings get asked for secrets first. Thus settings which
130 * relate to things that must be working first, like hardware, should get a
131 * higher priority than things which layer on top of the hardware. For example,
132 * the GSM/CDMA settings should provide secrets before the PPP setting does,
133 * because a PIN is required to unlock the device before PPP can even start.
134 * Even settings without secrets should be assigned the right priority.
136 * 0: reserved for the Connection setting
138 * 1: hardware-related settings like Ethernet, Wi-Fi, InfiniBand, Bridge, etc.
139 * These priority 1 settings are also "base types", which means that at least
140 * one of them is required for the connection to be valid, and their name is
141 * valid in the 'type' property of the Connection setting.
143 * 2: hardware-related auxiliary settings that require a base setting to be
144 * successful first, like Wi-Fi security, 802.1x, etc.
146 * 3: hardware-independent settings that are required before IP connectivity
147 * can be established, like PPP, PPPoE, etc.
152 (_nm_register_setting) (const char *name,
154 const guint32 priority)
158 g_return_if_fail (name != NULL && *name);
159 g_return_if_fail (type != G_TYPE_INVALID);
160 g_return_if_fail (type != G_TYPE_NONE);
161 g_return_if_fail (priority <= 4);
163 _ensure_registered ();
165 if (G_LIKELY ((info = g_hash_table_lookup (registered_settings, name)))) {
166 g_return_if_fail (info->type == type);
167 g_return_if_fail (info->priority == priority);
168 g_return_if_fail (g_strcmp0 (info->name, name) == 0);
171 g_return_if_fail (g_hash_table_lookup (registered_settings_by_type, &type) == NULL);
174 g_assert_cmpstr (name, ==, NM_SETTING_CONNECTION_SETTING_NAME);
176 info = g_slice_new0 (SettingInfo);
178 info->priority = priority;
180 g_hash_table_insert (registered_settings, (void *) info->name, info);
181 g_hash_table_insert (registered_settings_by_type, &info->type, info);
184 static const SettingInfo *
185 _nm_setting_lookup_setting_by_type (GType type)
187 _ensure_registered ();
188 return g_hash_table_lookup (registered_settings_by_type, &type);
192 _get_setting_type_priority (GType type)
194 const SettingInfo *info;
196 g_return_val_if_fail (g_type_is_a (type, NM_TYPE_SETTING), G_MAXUINT32);
198 info = _nm_setting_lookup_setting_by_type (type);
199 return info->priority;
203 _nm_setting_get_setting_priority (NMSetting *setting)
205 NMSettingPrivate *priv;
207 g_return_val_if_fail (NM_IS_SETTING (setting), G_MAXUINT32);
208 priv = NM_SETTING_GET_PRIVATE (setting);
209 _ensure_setting_info (setting, priv);
210 return priv->info->priority;
214 _nm_setting_type_is_base_type (GType type)
216 /* Historical oddity: PPPoE is a base-type even though it's not
217 * priority 1. It needs to be sorted *after* lower-level stuff like
218 * Wi-Fi security or 802.1x for secrets, but it's still allowed as a
221 return _get_setting_type_priority (type) == 1 || (type == NM_TYPE_SETTING_PPPOE);
225 _nm_setting_is_base_type (NMSetting *setting)
227 return _nm_setting_type_is_base_type (G_OBJECT_TYPE (setting));
231 * nm_setting_lookup_type:
232 * @name: a setting name
234 * Returns the #GType of the setting's class for a given setting name.
236 * Returns: the #GType of the setting's class, or %G_TYPE_INVALID if
237 * @name is not recognized.
240 nm_setting_lookup_type (const char *name)
244 g_return_val_if_fail (name != NULL, G_TYPE_INVALID);
246 _ensure_registered ();
248 info = g_hash_table_lookup (registered_settings, name);
249 return info ? info->type : G_TYPE_INVALID;
253 _nm_setting_compare_priority (gconstpointer a, gconstpointer b)
255 guint32 prio_a, prio_b;
257 prio_a = _nm_setting_get_setting_priority ((NMSetting *) a);
258 prio_b = _nm_setting_get_setting_priority ((NMSetting *) b);
262 else if (prio_a == prio_b)
267 /*************************************************************/
270 _nm_setting_slave_type_is_valid (const char *slave_type, const char **out_port_type)
272 const char *port_type = NULL;
273 gboolean found = TRUE;
277 else if (!strcmp (slave_type, NM_SETTING_BOND_SETTING_NAME))
279 else if (!strcmp (slave_type, NM_SETTING_BRIDGE_SETTING_NAME))
280 port_type = NM_SETTING_BRIDGE_PORT_SETTING_NAME;
281 else if (!strcmp (slave_type, NM_SETTING_TEAM_SETTING_NAME))
282 port_type = NM_SETTING_TEAM_PORT_SETTING_NAME;
287 *out_port_type = port_type;
291 /*************************************************************/
295 GParamSpec *param_spec;
296 const GVariantType *dbus_type;
298 NMSettingPropertyGetFunc get_func;
299 NMSettingPropertySynthFunc synth_func;
300 NMSettingPropertySetFunc set_func;
301 NMSettingPropertyNotSetFunc not_set_func;
303 NMSettingPropertyTransformToFunc to_dbus;
304 NMSettingPropertyTransformFromFunc from_dbus;
307 static GQuark setting_property_overrides_quark;
308 static GQuark setting_properties_quark;
310 static NMSettingProperty *
311 find_property (GArray *properties, const char *name)
313 NMSettingProperty *property;
319 for (i = 0; i < properties->len; i++) {
320 property = &g_array_index (properties, NMSettingProperty, i);
321 if (strcmp (name, property->name) == 0)
329 add_property_override (NMSettingClass *setting_class,
330 const char *property_name,
331 GParamSpec *param_spec,
332 const GVariantType *dbus_type,
333 NMSettingPropertyGetFunc get_func,
334 NMSettingPropertySynthFunc synth_func,
335 NMSettingPropertySetFunc set_func,
336 NMSettingPropertyNotSetFunc not_set_func,
337 NMSettingPropertyTransformToFunc to_dbus,
338 NMSettingPropertyTransformFromFunc from_dbus)
340 GType setting_type = G_TYPE_FROM_CLASS (setting_class);
342 NMSettingProperty override;
344 g_return_if_fail (g_type_get_qdata (setting_type, setting_properties_quark) == NULL);
346 memset (&override, 0, sizeof (override));
347 override.name = property_name;
348 override.param_spec = param_spec;
349 override.dbus_type = dbus_type;
350 override.get_func = get_func;
351 override.synth_func = synth_func;
352 override.set_func = set_func;
353 override.not_set_func = not_set_func;
354 override.to_dbus = to_dbus;
355 override.from_dbus = from_dbus;
357 overrides = g_type_get_qdata (setting_type, setting_property_overrides_quark);
359 overrides = g_array_new (FALSE, FALSE, sizeof (NMSettingProperty));
360 g_type_set_qdata (setting_type, setting_property_overrides_quark, overrides);
362 g_return_if_fail (find_property (overrides, property_name) == NULL);
364 g_array_append_val (overrides, override);
368 * _nm_setting_class_add_dbus_only_property:
369 * @setting_class: the setting class
370 * @property_name: the name of the property to override
371 * @dbus_type: the type of the property (in its D-Bus representation)
372 * @synth_func: (allow-none): function to call to synthesize a value for the property
373 * @set_func: (allow-none): function to call to set the value of the property
375 * Registers a property named @property_name, which will be used in the D-Bus
376 * serialization of objects of @setting_class, but which does not correspond to
377 * a #GObject property.
379 * When serializing a setting to D-Bus, @synth_func will be called to synthesize
380 * a value for the property. (If it returns %NULL, no value will be added to the
381 * serialization. If @synth_func is %NULL, the property will always be omitted
382 * in the serialization.)
384 * When deserializing a D-Bus representation into a setting, if @property_name
385 * is present, then @set_func will be called to set it. (If @set_func is %NULL
386 * then the property will be ignored when deserializing.)
389 _nm_setting_class_add_dbus_only_property (NMSettingClass *setting_class,
390 const char *property_name,
391 const GVariantType *dbus_type,
392 NMSettingPropertySynthFunc synth_func,
393 NMSettingPropertySetFunc set_func)
395 g_return_if_fail (NM_IS_SETTING_CLASS (setting_class));
396 g_return_if_fail (property_name != NULL);
398 /* Must not match any GObject property. */
399 g_return_if_fail (!g_object_class_find_property (G_OBJECT_CLASS (setting_class), property_name));
401 add_property_override (setting_class,
402 property_name, NULL, dbus_type,
403 NULL, synth_func, set_func, NULL,
408 * _nm_setting_class_override_property:
409 * @setting_class: the setting class
410 * @property_name: the name of the property to override
411 * @dbus_type: the type of the property (in its D-Bus representation)
412 * @get_func: (allow-none): function to call to get the value of the property
413 * @set_func: (allow-none): function to call to set the value of the property
414 * @not_set_func: (allow-none): function to call to indicate the property was not set
416 * Overrides the D-Bus representation of the #GObject property named
417 * @property_name on @setting_class.
419 * When serializing a setting to D-Bus, if @get_func is non-%NULL, then it will
420 * be called to get the property's value. If it returns a #GVariant, the
421 * property will be added to the hash, and if it returns %NULL, the property
422 * will be omitted. (If @get_func is %NULL, the property will be read normally
423 * with g_object_get_property(), and added to the hash if it is not the default
426 * When deserializing a D-Bus representation into a setting, if @property_name
427 * is present, then @set_func will be called to set it. (If @set_func is %NULL
428 * then the property will be set normally with g_object_set_property().)
430 * If @not_set_func is non-%NULL, then it will be called when deserializing a
431 * representation that does NOT contain @property_name. This can be used, eg, if
432 * a new property needs to be initialized from some older deprecated property
433 * when it is not present.
436 _nm_setting_class_override_property (NMSettingClass *setting_class,
437 const char *property_name,
438 const GVariantType *dbus_type,
439 NMSettingPropertyGetFunc get_func,
440 NMSettingPropertySetFunc set_func,
441 NMSettingPropertyNotSetFunc not_set_func)
443 GParamSpec *param_spec;
445 param_spec = g_object_class_find_property (G_OBJECT_CLASS (setting_class), property_name);
446 g_return_if_fail (param_spec != NULL);
448 add_property_override (setting_class,
449 property_name, param_spec, dbus_type,
450 get_func, NULL, set_func, not_set_func,
455 * _nm_setting_class_transform_property:
456 * @setting_class: the setting class
457 * @property: the name of the property to transform
458 * @dbus_type: the type of the property (in its D-Bus representation)
459 * @to_dbus: function to convert from object to D-Bus format
460 * @from_dbus: function to convert from D-Bus to object format
462 * Indicates that @property on @setting_class does not have the same format as
463 * its corresponding D-Bus representation, and so must be transformed when
464 * serializing/deserializing.
466 * The transformation will also be used by nm_setting_compare(), meaning that
467 * the underlying object property does not need to be of a type that
468 * nm_property_compare() recognizes, as long as it recognizes @dbus_type.
471 _nm_setting_class_transform_property (NMSettingClass *setting_class,
472 const char *property,
473 const GVariantType *dbus_type,
474 NMSettingPropertyTransformToFunc to_dbus,
475 NMSettingPropertyTransformFromFunc from_dbus)
477 GParamSpec *param_spec;
479 param_spec = g_object_class_find_property (G_OBJECT_CLASS (setting_class), property);
480 g_return_if_fail (param_spec != NULL);
482 add_property_override (setting_class,
483 property, param_spec, dbus_type,
484 NULL, NULL, NULL, NULL,
489 _nm_setting_use_legacy_property (NMSetting *setting,
490 GVariant *connection_dict,
491 const char *legacy_property,
492 const char *new_property)
494 GVariant *setting_dict, *value;
496 setting_dict = g_variant_lookup_value (connection_dict, nm_setting_get_name (NM_SETTING (setting)), NM_VARIANT_TYPE_SETTING);
497 g_return_val_if_fail (setting_dict != NULL, FALSE);
499 /* If the new property isn't set, we have to use the legacy property. */
500 value = g_variant_lookup_value (setting_dict, new_property, NULL);
502 g_variant_unref (setting_dict);
505 g_variant_unref (value);
507 /* Otherwise, clients always prefer new properties sent from the daemon. */
508 if (!_nm_utils_is_manager_process) {
509 g_variant_unref (setting_dict);
513 /* The daemon prefers the legacy property if it exists. */
514 value = g_variant_lookup_value (setting_dict, legacy_property, NULL);
515 g_variant_unref (setting_dict);
518 g_variant_unref (value);
525 nm_setting_class_ensure_properties (NMSettingClass *setting_class)
527 GType type = G_TYPE_FROM_CLASS (setting_class), otype;
528 NMSettingProperty property, *override;
529 GArray *overrides, *type_overrides, *properties;
530 GParamSpec **property_specs;
531 guint n_property_specs, i;
533 properties = g_type_get_qdata (type, setting_properties_quark);
537 /* Build overrides array from @setting_class and its superclasses */
538 overrides = g_array_new (FALSE, FALSE, sizeof (NMSettingProperty));
539 for (otype = type; otype != G_TYPE_OBJECT; otype = g_type_parent (otype)) {
540 type_overrides = g_type_get_qdata (otype, setting_property_overrides_quark);
542 g_array_append_vals (overrides, (NMSettingProperty *)type_overrides->data, type_overrides->len);
545 /* Build the properties array from the GParamSpecs, obeying overrides */
546 properties = g_array_new (FALSE, FALSE, sizeof (NMSettingProperty));
548 property_specs = g_object_class_list_properties (G_OBJECT_CLASS (setting_class),
550 for (i = 0; i < n_property_specs; i++) {
551 override = find_property (overrides, property_specs[i]->name);
553 property = *override;
555 memset (&property, 0, sizeof (property));
556 property.name = property_specs[i]->name;
557 property.param_spec = property_specs[i];
559 g_array_append_val (properties, property);
561 g_free (property_specs);
563 /* Add any remaining overrides not corresponding to GObject properties */
564 for (i = 0; i < overrides->len; i++) {
565 override = &g_array_index (overrides, NMSettingProperty, i);
566 if (!g_object_class_find_property (G_OBJECT_CLASS (setting_class), override->name))
567 g_array_append_val (properties, *override);
569 g_array_unref (overrides);
571 g_type_set_qdata (type, setting_properties_quark, properties);
575 static const NMSettingProperty *
576 nm_setting_class_get_properties (NMSettingClass *setting_class, guint *n_properties)
580 properties = nm_setting_class_ensure_properties (setting_class);
582 *n_properties = properties->len;
583 return (NMSettingProperty *) properties->data;
586 static const NMSettingProperty *
587 nm_setting_class_find_property (NMSettingClass *setting_class, const char *property_name)
591 properties = nm_setting_class_ensure_properties (setting_class);
592 return find_property (properties, property_name);
595 /*************************************************************/
597 static const GVariantType *
598 variant_type_for_gtype (GType type)
600 if (type == G_TYPE_BOOLEAN)
601 return G_VARIANT_TYPE_BOOLEAN;
602 else if (type == G_TYPE_UCHAR)
603 return G_VARIANT_TYPE_BYTE;
604 else if (type == G_TYPE_INT)
605 return G_VARIANT_TYPE_INT32;
606 else if (type == G_TYPE_UINT)
607 return G_VARIANT_TYPE_UINT32;
608 else if (type == G_TYPE_INT64)
609 return G_VARIANT_TYPE_INT64;
610 else if (type == G_TYPE_UINT64)
611 return G_VARIANT_TYPE_UINT64;
612 else if (type == G_TYPE_STRING)
613 return G_VARIANT_TYPE_STRING;
614 else if (type == G_TYPE_DOUBLE)
615 return G_VARIANT_TYPE_DOUBLE;
616 else if (type == G_TYPE_STRV)
617 return G_VARIANT_TYPE_STRING_ARRAY;
618 else if (type == G_TYPE_BYTES)
619 return G_VARIANT_TYPE_BYTESTRING;
620 else if (g_type_is_a (type, G_TYPE_ENUM))
621 return G_VARIANT_TYPE_INT32;
622 else if (g_type_is_a (type, G_TYPE_FLAGS))
623 return G_VARIANT_TYPE_UINT32;
625 g_assert_not_reached ();
629 get_property_for_dbus (NMSetting *setting,
630 const NMSettingProperty *property,
631 gboolean ignore_default)
633 GValue prop_value = { 0, };
634 GVariant *dbus_value;
636 if (property->get_func)
637 return property->get_func (setting, property->name);
639 g_return_val_if_fail (property->param_spec != NULL, NULL);
641 g_value_init (&prop_value, property->param_spec->value_type);
642 g_object_get_property (G_OBJECT (setting), property->param_spec->name, &prop_value);
644 if (ignore_default && g_param_value_defaults (property->param_spec, &prop_value)) {
645 g_value_unset (&prop_value);
649 if (property->to_dbus)
650 dbus_value = property->to_dbus (&prop_value);
651 else if (property->dbus_type)
652 dbus_value = g_dbus_gvalue_to_gvariant (&prop_value, property->dbus_type);
653 else if (g_type_is_a (prop_value.g_type, G_TYPE_ENUM))
654 dbus_value = g_variant_new_int32 (g_value_get_enum (&prop_value));
655 else if (g_type_is_a (prop_value.g_type, G_TYPE_FLAGS))
656 dbus_value = g_variant_new_uint32 (g_value_get_flags (&prop_value));
657 else if (prop_value.g_type == G_TYPE_BYTES)
658 dbus_value = _nm_utils_bytes_to_dbus (&prop_value);
660 dbus_value = g_dbus_gvalue_to_gvariant (&prop_value, variant_type_for_gtype (prop_value.g_type));
661 g_value_unset (&prop_value);
667 set_property_from_dbus (const NMSettingProperty *property,
671 g_return_val_if_fail (property->param_spec != NULL, FALSE);
673 if (property->from_dbus) {
674 if (!g_variant_type_equal (g_variant_get_type (src_value), property->dbus_type))
677 property->from_dbus (src_value, dst_value);
678 } else if (dst_value->g_type == G_TYPE_BYTES) {
679 if (!g_variant_is_of_type (src_value, G_VARIANT_TYPE_BYTESTRING))
682 _nm_utils_bytes_from_dbus (src_value, dst_value);
684 GValue tmp = G_VALUE_INIT;
686 g_dbus_gvariant_to_gvalue (src_value, &tmp);
687 if (G_VALUE_TYPE (&tmp) == G_VALUE_TYPE (dst_value))
692 success = g_value_transform (&tmp, dst_value);
693 g_value_unset (&tmp);
704 * _nm_setting_to_dbus:
705 * @setting: the #NMSetting
706 * @connection: the #NMConnection containing @setting
707 * @flags: hash flags, e.g. %NM_CONNECTION_SERIALIZE_ALL
709 * Converts the #NMSetting into a #GVariant of type #NM_VARIANT_TYPE_SETTING
710 * mapping each setting property name to a value describing that property,
711 * suitable for marshalling over D-Bus or serializing.
713 * Returns: (transfer none): a new floating #GVariant describing the setting's
717 _nm_setting_to_dbus (NMSetting *setting, NMConnection *connection, NMConnectionSerializationFlags flags)
719 GVariantBuilder builder;
720 GVariant *dbus_value;
721 const NMSettingProperty *properties;
722 guint n_properties, i;
724 g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
726 properties = nm_setting_class_get_properties (NM_SETTING_GET_CLASS (setting), &n_properties);
728 g_variant_builder_init (&builder, NM_VARIANT_TYPE_SETTING);
730 for (i = 0; i < n_properties; i++) {
731 const NMSettingProperty *property = &properties[i];
732 GParamSpec *prop_spec = property->param_spec;
734 if (!prop_spec && !property->synth_func) {
735 /* D-Bus-only property with no synth_func, so we skip it. */
739 if (prop_spec && !(prop_spec->flags & G_PARAM_WRITABLE))
742 if ( prop_spec && (prop_spec->flags & NM_SETTING_PARAM_LEGACY)
743 && !_nm_utils_is_manager_process)
746 if ( (flags & NM_CONNECTION_SERIALIZE_NO_SECRETS)
747 && (prop_spec && (prop_spec->flags & NM_SETTING_PARAM_SECRET)))
750 if ( (flags & NM_CONNECTION_SERIALIZE_ONLY_SECRETS)
751 && !(prop_spec && (prop_spec->flags & NM_SETTING_PARAM_SECRET)))
754 if (property->synth_func)
755 dbus_value = property->synth_func (setting, connection, property->name);
757 dbus_value = get_property_for_dbus (setting, property, TRUE);
759 /* Allow dbus_value to be either floating or not. */
760 g_variant_take_ref (dbus_value);
762 g_variant_builder_add (&builder, "{sv}", property->name, dbus_value);
763 g_variant_unref (dbus_value);
767 return g_variant_builder_end (&builder);
771 * _nm_setting_new_from_dbus:
772 * @setting_type: the #NMSetting type which the hash contains properties for
773 * @setting_dict: the #GVariant containing an %NM_VARIANT_TYPE_SETTING dictionary
774 * mapping property names to values
775 * @connection_dict: the #GVariant containing an %NM_VARIANT_TYPE_CONNECTION
776 * dictionary mapping setting names to dictionaries.
777 * @parse_flags: flags to determine behavior during parsing.
778 * @error: location to store error, or %NULL
780 * Creates a new #NMSetting object and populates that object with the properties
781 * contained in @setting_dict, using each key as the property to set, and each
782 * value as the value to set that property to. Setting properties are strongly
783 * typed, thus the #GVariantType of the dict value must be correct. See the
784 * documentation on each #NMSetting object subclass for the correct property
785 * names and value types.
787 * Returns: a new #NMSetting object populated with the properties from the
788 * hash table, or %NULL if @setting_hash could not be deserialized.
791 _nm_setting_new_from_dbus (GType setting_type,
792 GVariant *setting_dict,
793 GVariant *connection_dict,
794 NMSettingParseFlags parse_flags,
797 gs_unref_object NMSetting *setting = NULL;
798 gs_unref_hashtable GHashTable *keys = NULL;
799 const NMSettingProperty *properties;
800 guint i, n_properties;
802 g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (setting_type), NULL);
803 g_return_val_if_fail (g_variant_is_of_type (setting_dict, NM_VARIANT_TYPE_SETTING), NULL);
805 nm_assert (!NM_FLAGS_ANY (parse_flags, ~NM_SETTING_PARSE_FLAGS_ALL));
806 nm_assert (!NM_FLAGS_ALL (parse_flags, NM_SETTING_PARSE_FLAGS_STRICT | NM_SETTING_PARSE_FLAGS_BEST_EFFORT));
808 /* connection_dict is not technically optional, but some tests in test-general
809 * don't bother with it in cases where they know it's not needed.
812 g_return_val_if_fail (g_variant_is_of_type (connection_dict, NM_VARIANT_TYPE_CONNECTION), NULL);
814 /* Build the setting object from the properties we know about; we assume
815 * that any propreties in @setting_dict that we don't know about can
816 * either be ignored or else has a backward-compatibility equivalent
817 * that we do know about.
819 setting = (NMSetting *) g_object_new (setting_type, NULL);
821 if (NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) {
823 GVariant *entry, *entry_key;
826 keys = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
828 g_variant_iter_init (&iter, setting_dict);
829 while ((entry = g_variant_iter_next_value (&iter))) {
830 entry_key = g_variant_get_child_value (entry, 0);
831 key = g_strdup (g_variant_get_string (entry_key, NULL));
832 g_variant_unref (entry_key);
833 g_variant_unref (entry);
835 if (!nm_g_hash_table_add (keys, key)) {
836 g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_SETTING,
837 _("duplicate property"));
838 g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), key);
844 properties = nm_setting_class_get_properties (NM_SETTING_GET_CLASS (setting), &n_properties);
845 for (i = 0; i < n_properties; i++) {
846 const NMSettingProperty *property = &properties[i];
847 gs_unref_variant GVariant *value = NULL;
848 gs_free_error GError *local = NULL;
850 if (property->param_spec && !(property->param_spec->flags & G_PARAM_WRITABLE))
853 value = g_variant_lookup_value (setting_dict, property->name, NULL);
856 g_hash_table_remove (keys, property->name);
858 if (value && property->set_func) {
860 if (!g_variant_type_equal (g_variant_get_type (value), property->dbus_type)) {
861 /* for backward behavior, fail unless best-effort is chosen. */
862 if (NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_BEST_EFFORT))
864 g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY,
865 _("can't set property of type '%s' from value of type '%s'"),
866 property->dbus_type ?
867 g_variant_type_peek_string (property->dbus_type) :
868 property->param_spec ?
869 g_type_name (property->param_spec->value_type) : "(unknown)",
870 g_variant_get_type_string (value));
871 g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), property->name);
875 if (!property->set_func (setting,
881 if (!NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_STRICT))
883 g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY,
884 _("failed to set property: %s"),
886 g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), property->name);
889 } else if (!value && property->not_set_func) {
890 if (!property->not_set_func (setting,
895 if (!NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_STRICT))
897 g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY,
898 _("failed to set property: %s"),
900 g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), property->name);
903 } else if (value && property->param_spec) {
904 nm_auto_unset_gvalue GValue object_value = G_VALUE_INIT;
906 g_value_init (&object_value, property->param_spec->value_type);
907 if (!set_property_from_dbus (property, value, &object_value)) {
908 /* for backward behavior, fail unless best-effort is chosen. */
909 if (NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_BEST_EFFORT))
911 g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY,
912 _("can't set property of type '%s' from value of type '%s'"),
913 property->dbus_type ?
914 g_variant_type_peek_string (property->dbus_type) :
915 property->param_spec ?
916 g_type_name (property->param_spec->value_type) : "(unknown)",
917 g_variant_get_type_string (value));
918 g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), property->name);
922 if (!nm_g_object_set_property (G_OBJECT (setting), property->param_spec->name, &object_value, &local)) {
923 if (!NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_STRICT))
925 g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY,
926 _("can not set property: %s"),
928 g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), property->name);
934 if ( NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)
935 && g_hash_table_size (keys) > 0) {
939 g_hash_table_iter_init (&iter, keys);
940 if (g_hash_table_iter_next (&iter, (gpointer *) &key, NULL)) {
941 g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY,
942 _("unknown property"));
943 g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), key);
948 return nm_unauto (&setting);
952 * nm_setting_get_dbus_property_type:
953 * @setting: an #NMSetting
954 * @property_name: the property of @setting to get the type of
956 * Gets the D-Bus marshalling type of a property. @property_name is a D-Bus
957 * property name, which may not necessarily be a #GObject property.
959 * Returns: the D-Bus marshalling type of @property on @setting.
962 nm_setting_get_dbus_property_type (NMSetting *setting,
963 const char *property_name)
965 const NMSettingProperty *property;
967 g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
968 g_return_val_if_fail (property_name != NULL, NULL);
970 property = nm_setting_class_find_property (NM_SETTING_GET_CLASS (setting), property_name);
971 g_return_val_if_fail (property != NULL, NULL);
973 if (property->dbus_type)
974 return property->dbus_type;
976 return variant_type_for_gtype (property->param_spec->value_type);
980 _nm_setting_get_property (NMSetting *setting, const char *property_name, GValue *value)
982 GParamSpec *prop_spec;
984 g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
985 g_return_val_if_fail (property_name, FALSE);
986 g_return_val_if_fail (value, FALSE);
988 prop_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), property_name);
991 g_value_unset (value);
995 g_value_init (value, prop_spec->value_type);
996 g_object_get_property (G_OBJECT (setting), property_name, value);
1001 duplicate_setting (NMSetting *setting,
1003 const GValue *value,
1007 if ((flags & (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)) == G_PARAM_WRITABLE)
1008 g_object_set_property (G_OBJECT (user_data), name, value);
1012 * nm_setting_duplicate:
1013 * @setting: the #NMSetting to duplicate
1015 * Duplicates a #NMSetting.
1017 * Returns: (transfer full): a new #NMSetting containing the same properties and values as the
1021 nm_setting_duplicate (NMSetting *setting)
1025 g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
1027 dup = g_object_new (G_OBJECT_TYPE (setting), NULL);
1029 g_object_freeze_notify (dup);
1030 nm_setting_enumerate_values (setting, duplicate_setting, dup);
1031 g_object_thaw_notify (dup);
1033 return NM_SETTING (dup);
1037 * nm_setting_get_name:
1038 * @setting: the #NMSetting
1040 * Returns the type name of the #NMSetting object
1042 * Returns: a string containing the type name of the #NMSetting object,
1043 * like 'ppp' or 'wireless' or 'wired'.
1046 nm_setting_get_name (NMSetting *setting)
1048 NMSettingPrivate *priv;
1050 g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
1051 priv = NM_SETTING_GET_PRIVATE (setting);
1052 _ensure_setting_info (setting, priv);
1053 return priv->info->name;
1057 * nm_setting_verify:
1058 * @setting: the #NMSetting to verify
1059 * @connection: (allow-none): the #NMConnection that @setting came from, or
1060 * %NULL if @setting is being verified in isolation.
1061 * @error: location to store error, or %NULL
1063 * Validates the setting. Each setting's properties have allowed values, and
1064 * some are dependent on other values (hence the need for @connection). The
1065 * returned #GError contains information about which property of the setting
1066 * failed validation, and in what way that property failed validation.
1068 * Returns: %TRUE if the setting is valid, %FALSE if it is not
1071 nm_setting_verify (NMSetting *setting, NMConnection *connection, GError **error)
1073 NMSettingVerifyResult result = _nm_setting_verify (setting, connection, error);
1075 if (result == NM_SETTING_VERIFY_NORMALIZABLE)
1076 g_clear_error (error);
1078 return result == NM_SETTING_VERIFY_SUCCESS || result == NM_SETTING_VERIFY_NORMALIZABLE;
1081 NMSettingVerifyResult
1082 _nm_setting_verify (NMSetting *setting, NMConnection *connection, GError **error)
1084 g_return_val_if_fail (NM_IS_SETTING (setting), NM_SETTING_VERIFY_ERROR);
1085 g_return_val_if_fail (!connection || NM_IS_CONNECTION (connection), NM_SETTING_VERIFY_ERROR);
1086 g_return_val_if_fail (!error || *error == NULL, NM_SETTING_VERIFY_ERROR);
1088 if (NM_SETTING_GET_CLASS (setting)->verify)
1089 return NM_SETTING_GET_CLASS (setting)->verify (setting, connection, error);
1091 return NM_SETTING_VERIFY_SUCCESS;
1095 * nm_setting_verify_secrets:
1096 * @setting: the #NMSetting to verify secrets in
1097 * @connection: (allow-none): the #NMConnection that @setting came from, or
1098 * %NULL if @setting is being verified in isolation.
1099 * @error: location to store error, or %NULL
1101 * Verifies the secrets in the setting.
1102 * The returned #GError contains information about which secret of the setting
1103 * failed validation, and in what way that secret failed validation.
1104 * The secret validation is done separately from main setting validation, because
1105 * in some cases connection failure is not desired just for the secrets.
1107 * Returns: %TRUE if the setting secrets are valid, %FALSE if they are not
1112 nm_setting_verify_secrets (NMSetting *setting, NMConnection *connection, GError **error)
1114 g_return_val_if_fail (NM_IS_SETTING (setting), NM_SETTING_VERIFY_ERROR);
1115 g_return_val_if_fail (!connection || NM_IS_CONNECTION (connection), NM_SETTING_VERIFY_ERROR);
1116 g_return_val_if_fail (!error || *error == NULL, NM_SETTING_VERIFY_ERROR);
1118 if (NM_SETTING_GET_CLASS (setting)->verify_secrets)
1119 return NM_SETTING_GET_CLASS (setting)->verify_secrets (setting, connection, error);
1121 return NM_SETTING_VERIFY_SUCCESS;
1125 _nm_setting_verify_secret_string (const char *str,
1126 const char *setting_name,
1127 const char *property,
1131 g_set_error_literal (error,
1132 NM_CONNECTION_ERROR,
1133 NM_CONNECTION_ERROR_INVALID_PROPERTY,
1134 _("property is empty"));
1135 g_prefix_error (error, "%s.%s: ", setting_name, property);
1142 compare_property (NMSetting *setting,
1144 const GParamSpec *prop_spec,
1145 NMSettingCompareFlags flags)
1147 const NMSettingProperty *property;
1148 GVariant *value1, *value2;
1151 /* Handle compare flags */
1152 if (prop_spec->flags & NM_SETTING_PARAM_SECRET) {
1153 NMSettingSecretFlags a_secret_flags = NM_SETTING_SECRET_FLAG_NONE;
1154 NMSettingSecretFlags b_secret_flags = NM_SETTING_SECRET_FLAG_NONE;
1156 g_return_val_if_fail (!NM_IS_SETTING_VPN (setting), FALSE);
1158 if (!nm_setting_get_secret_flags (setting, prop_spec->name, &a_secret_flags, NULL))
1159 g_return_val_if_reached (FALSE);
1160 if (!nm_setting_get_secret_flags (other, prop_spec->name, &b_secret_flags, NULL))
1161 g_return_val_if_reached (FALSE);
1163 /* If the secret flags aren't the same the settings aren't the same */
1164 if (a_secret_flags != b_secret_flags)
1167 /* Check for various secret flags that might cause us to ignore comparing
1170 if ( (flags & NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS)
1171 && (a_secret_flags & NM_SETTING_SECRET_FLAG_AGENT_OWNED))
1174 if ( (flags & NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)
1175 && (a_secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED))
1179 property = nm_setting_class_find_property (NM_SETTING_GET_CLASS (setting), prop_spec->name);
1180 g_return_val_if_fail (property != NULL, FALSE);
1182 value1 = get_property_for_dbus (setting, property, TRUE);
1183 value2 = get_property_for_dbus (other, property, TRUE);
1185 cmp = nm_property_compare (value1, value2);
1188 g_variant_unref (value1);
1190 g_variant_unref (value2);
1196 * nm_setting_compare:
1198 * @b: a second #NMSetting to compare with the first
1199 * @flags: compare flags, e.g. %NM_SETTING_COMPARE_FLAG_EXACT
1201 * Compares two #NMSetting objects for similarity, with comparison behavior
1202 * modified by a set of flags. See the documentation for #NMSettingCompareFlags
1203 * for a description of each flag's behavior.
1205 * Returns: %TRUE if the comparison succeeds, %FALSE if it does not
1208 nm_setting_compare (NMSetting *a,
1210 NMSettingCompareFlags flags)
1212 GParamSpec **property_specs;
1213 guint n_property_specs;
1217 g_return_val_if_fail (NM_IS_SETTING (a), FALSE);
1218 g_return_val_if_fail (NM_IS_SETTING (b), FALSE);
1220 /* First check that both have the same type */
1221 if (G_OBJECT_TYPE (a) != G_OBJECT_TYPE (b))
1224 /* And now all properties */
1225 property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (a), &n_property_specs);
1226 for (i = 0; i < n_property_specs && same; i++) {
1227 GParamSpec *prop_spec = property_specs[i];
1229 /* Fuzzy compare ignores secrets and properties defined with the FUZZY_IGNORE flag */
1230 if ( NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_FUZZY)
1231 && !NM_FLAGS_ANY (prop_spec->flags, NM_SETTING_PARAM_FUZZY_IGNORE | NM_SETTING_PARAM_SECRET))
1234 if ( NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_INFERRABLE)
1235 && !NM_FLAGS_HAS (prop_spec->flags, NM_SETTING_PARAM_INFERRABLE))
1238 if ( NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_IGNORE_REAPPLY_IMMEDIATELY)
1239 && NM_FLAGS_HAS (prop_spec->flags, NM_SETTING_PARAM_REAPPLY_IMMEDIATELY))
1242 if ( NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS)
1243 && NM_FLAGS_HAS (prop_spec->flags, NM_SETTING_PARAM_SECRET))
1246 same = NM_SETTING_GET_CLASS (a)->compare_property (a, b, prop_spec, flags);
1248 g_free (property_specs);
1253 static inline gboolean
1254 should_compare_prop (NMSetting *setting,
1255 const char *prop_name,
1256 NMSettingCompareFlags comp_flags,
1257 GParamFlags prop_flags)
1259 /* Fuzzy compare ignores secrets and properties defined with the FUZZY_IGNORE flag */
1260 if ( (comp_flags & NM_SETTING_COMPARE_FLAG_FUZZY)
1261 && (prop_flags & (NM_SETTING_PARAM_FUZZY_IGNORE | NM_SETTING_PARAM_SECRET)))
1264 if ((comp_flags & NM_SETTING_COMPARE_FLAG_INFERRABLE) && !(prop_flags & NM_SETTING_PARAM_INFERRABLE))
1267 if ((comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_REAPPLY_IMMEDIATELY) && !(prop_flags & NM_SETTING_PARAM_REAPPLY_IMMEDIATELY))
1270 if (prop_flags & NM_SETTING_PARAM_SECRET) {
1271 NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
1273 if (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS)
1276 if ( NM_IS_SETTING_VPN (setting)
1277 && g_strcmp0 (prop_name, NM_SETTING_VPN_SECRETS) == 0) {
1278 /* FIXME: NMSettingVPN:NM_SETTING_VPN_SECRETS has NM_SETTING_PARAM_SECRET.
1279 * nm_setting_get_secret_flags() quite possibly fails, but it might succeed if the
1280 * setting accidently uses a key "secrets". */
1284 if (!nm_setting_get_secret_flags (setting, prop_name, &secret_flags, NULL))
1285 g_return_val_if_reached (FALSE);
1287 if ( (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS)
1288 && (secret_flags & NM_SETTING_SECRET_FLAG_AGENT_OWNED))
1291 if ( (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)
1292 && (secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED))
1296 if ( (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_ID)
1297 && NM_IS_SETTING_CONNECTION (setting)
1298 && !strcmp (prop_name, NM_SETTING_CONNECTION_ID))
1301 if ( (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_TIMESTAMP)
1302 && NM_IS_SETTING_CONNECTION (setting)
1303 && !strcmp (prop_name, NM_SETTING_CONNECTION_TIMESTAMP))
1312 * @b: a second #NMSetting to compare with the first
1313 * @flags: compare flags, e.g. %NM_SETTING_COMPARE_FLAG_EXACT
1314 * @invert_results: this parameter is used internally by libnm and should
1315 * be set to %FALSE. If %TRUE inverts the meaning of the #NMSettingDiffResult.
1316 * @results: (inout) (transfer full) (element-type utf8 guint32): if the
1317 * settings differ, on return a hash table mapping the differing keys to one or
1318 * more %NMSettingDiffResult values OR-ed together. If the settings do not
1319 * differ, any hash table passed in is unmodified. If no hash table is passed
1320 * in and the settings differ, a new one is created and returned.
1322 * Compares two #NMSetting objects for similarity, with comparison behavior
1323 * modified by a set of flags. See the documentation for #NMSettingCompareFlags
1324 * for a description of each flag's behavior. If the settings differ, the keys
1325 * of each setting that differ from the other are added to @results, mapped to
1326 * one or more #NMSettingDiffResult values.
1328 * Returns: %TRUE if the settings contain the same values, %FALSE if they do not
1331 nm_setting_diff (NMSetting *a,
1333 NMSettingCompareFlags flags,
1334 gboolean invert_results,
1335 GHashTable **results)
1337 GParamSpec **property_specs;
1338 guint n_property_specs;
1340 NMSettingDiffResult a_result = NM_SETTING_DIFF_RESULT_IN_A;
1341 NMSettingDiffResult b_result = NM_SETTING_DIFF_RESULT_IN_B;
1342 NMSettingDiffResult a_result_default = NM_SETTING_DIFF_RESULT_IN_A_DEFAULT;
1343 NMSettingDiffResult b_result_default = NM_SETTING_DIFF_RESULT_IN_B_DEFAULT;
1344 gboolean results_created = FALSE;
1346 g_return_val_if_fail (results != NULL, FALSE);
1347 g_return_val_if_fail (NM_IS_SETTING (a), FALSE);
1349 g_return_val_if_fail (NM_IS_SETTING (b), FALSE);
1350 g_return_val_if_fail (G_OBJECT_TYPE (a) == G_OBJECT_TYPE (b), FALSE);
1353 if ((flags & (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) ==
1354 (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) {
1355 /* conflicting flags: default to WITH_DEFAULT (clearing NO_DEFAULT). */
1356 flags &= ~NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT;
1359 /* If the caller is calling this function in a pattern like this to get
1362 * nm_setting_diff (A, B, FALSE, &results);
1363 * nm_setting_diff (B, A, TRUE, &results);
1365 * and wants us to invert the results so that the second invocation comes
1366 * out correctly, do that here.
1368 if (invert_results) {
1369 a_result = NM_SETTING_DIFF_RESULT_IN_B;
1370 b_result = NM_SETTING_DIFF_RESULT_IN_A;
1371 a_result_default = NM_SETTING_DIFF_RESULT_IN_B_DEFAULT;
1372 b_result_default = NM_SETTING_DIFF_RESULT_IN_A_DEFAULT;
1375 if (*results == NULL) {
1376 *results = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1377 results_created = TRUE;
1380 /* And now all properties */
1381 property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (a), &n_property_specs);
1383 for (i = 0; i < n_property_specs; i++) {
1384 GParamSpec *prop_spec = property_specs[i];
1385 NMSettingDiffResult r = NM_SETTING_DIFF_RESULT_UNKNOWN;
1387 /* Handle compare flags */
1388 if (!should_compare_prop (a, prop_spec->name, flags, prop_spec->flags))
1390 if (strcmp (prop_spec->name, NM_SETTING_NAME) == 0)
1396 different = !NM_SETTING_GET_CLASS (a)->compare_property (a, b, prop_spec, flags);
1398 gboolean a_is_default, b_is_default;
1399 GValue value = G_VALUE_INIT;
1401 g_value_init (&value, prop_spec->value_type);
1402 g_object_get_property (G_OBJECT (a), prop_spec->name, &value);
1403 a_is_default = g_param_value_defaults (prop_spec, &value);
1405 g_value_reset (&value);
1406 g_object_get_property (G_OBJECT (b), prop_spec->name, &value);
1407 b_is_default = g_param_value_defaults (prop_spec, &value);
1409 g_value_unset (&value);
1410 if ((flags & NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT) == 0) {
1416 r |= a_result | b_result;
1418 r |= a_result_default;
1420 r |= b_result_default;
1423 } else if ((flags & (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) == 0)
1424 r = a_result; /* only in A */
1426 GValue value = G_VALUE_INIT;
1428 g_value_init (&value, prop_spec->value_type);
1429 g_object_get_property (G_OBJECT (a), prop_spec->name, &value);
1430 if (!g_param_value_defaults (prop_spec, &value))
1432 else if (flags & NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT)
1433 r |= a_result | a_result_default;
1435 g_value_unset (&value);
1438 if (r != NM_SETTING_DIFF_RESULT_UNKNOWN) {
1441 if (g_hash_table_lookup_extended (*results, prop_spec->name, NULL, &p)) {
1442 if ((r & GPOINTER_TO_UINT (p)) != r)
1443 g_hash_table_insert (*results, g_strdup (prop_spec->name), GUINT_TO_POINTER (r | GPOINTER_TO_UINT (p)));
1445 g_hash_table_insert (*results, g_strdup (prop_spec->name), GUINT_TO_POINTER (r));
1448 g_free (property_specs);
1450 /* Don't return an empty hash table */
1451 if (results_created && !g_hash_table_size (*results)) {
1452 g_hash_table_destroy (*results);
1459 #define CMP_AND_RETURN(n_a, n_b, name) \
1461 gboolean _is = (strcmp (n_a, ""name) == 0); \
1463 if (_is || (strcmp (n_b, ""name) == 0)) \
1464 return _is ? -1 : 1; \
1468 _enumerate_values_sort (GParamSpec **p_a, GParamSpec **p_b, GType *p_type)
1470 const char *n_a = (*p_a)->name;
1471 const char *n_b = (*p_b)->name;
1472 int c = strcmp (n_a, n_b);
1475 if (*p_type == NM_TYPE_SETTING_CONNECTION) {
1476 /* for [connection], report first id, uuid, type in that order. */
1477 CMP_AND_RETURN (n_a, n_b, NM_SETTING_CONNECTION_ID);
1478 CMP_AND_RETURN (n_a, n_b, NM_SETTING_CONNECTION_UUID);
1479 CMP_AND_RETURN (n_a, n_b, NM_SETTING_CONNECTION_TYPE);
1484 #undef CMP_AND_RETURN
1487 * nm_setting_enumerate_values:
1488 * @setting: the #NMSetting
1489 * @func: (scope call): user-supplied function called for each property of the setting
1490 * @user_data: user data passed to @func at each invocation
1492 * Iterates over each property of the #NMSetting object, calling the supplied
1493 * user function for each property.
1496 nm_setting_enumerate_values (NMSetting *setting,
1497 NMSettingValueIterFn func,
1500 GParamSpec **property_specs;
1501 guint n_property_specs;
1505 g_return_if_fail (NM_IS_SETTING (setting));
1506 g_return_if_fail (func != NULL);
1508 property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs);
1510 /* sort the properties. This has an effect on the order in which keyfile
1512 type = G_OBJECT_TYPE (setting);
1513 g_qsort_with_data (property_specs, n_property_specs, sizeof (gpointer),
1514 (GCompareDataFunc) _enumerate_values_sort, &type);
1516 for (i = 0; i < n_property_specs; i++) {
1517 GParamSpec *prop_spec = property_specs[i];
1518 GValue value = G_VALUE_INIT;
1520 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (prop_spec));
1521 g_object_get_property (G_OBJECT (setting), prop_spec->name, &value);
1522 func (setting, prop_spec->name, &value, prop_spec->flags, user_data);
1523 g_value_unset (&value);
1526 g_free (property_specs);
1530 * _nm_setting_clear_secrets:
1531 * @setting: the #NMSetting
1533 * Resets and clears any secrets in the setting. Secrets should be added to the
1534 * setting only when needed, and cleared immediately after use to prevent
1535 * leakage of information.
1537 * Returns: %TRUE if the setting changed at all
1540 _nm_setting_clear_secrets (NMSetting *setting)
1542 GParamSpec **property_specs;
1543 guint n_property_specs;
1545 gboolean changed = FALSE;
1547 g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
1549 property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs);
1551 for (i = 0; i < n_property_specs; i++) {
1552 GParamSpec *prop_spec = property_specs[i];
1554 if (prop_spec->flags & NM_SETTING_PARAM_SECRET) {
1555 GValue value = G_VALUE_INIT;
1557 g_value_init (&value, prop_spec->value_type);
1558 g_object_get_property (G_OBJECT (setting), prop_spec->name, &value);
1559 if (!g_param_value_defaults (prop_spec, &value)) {
1560 g_param_value_set_default (prop_spec, &value);
1561 g_object_set_property (G_OBJECT (setting), prop_spec->name, &value);
1564 g_value_unset (&value);
1568 g_free (property_specs);
1574 clear_secrets_with_flags (NMSetting *setting,
1576 NMSettingClearSecretsWithFlagsFn func,
1579 NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;
1580 gboolean changed = FALSE;
1582 g_return_val_if_fail (!NM_IS_SETTING_VPN (setting), FALSE);
1584 /* Clear the secret if the user function says to do so */
1585 if (!nm_setting_get_secret_flags (setting, pspec->name, &flags, NULL))
1586 g_return_val_if_reached (FALSE);
1588 if (func (setting, pspec->name, flags, user_data) == TRUE) {
1589 GValue value = G_VALUE_INIT;
1591 g_value_init (&value, pspec->value_type);
1592 g_object_get_property (G_OBJECT (setting), pspec->name, &value);
1593 if (!g_param_value_defaults (pspec, &value)) {
1594 g_param_value_set_default (pspec, &value);
1595 g_object_set_property (G_OBJECT (setting), pspec->name, &value);
1598 g_value_unset (&value);
1605 * _nm_setting_clear_secrets_with_flags:
1606 * @setting: the #NMSetting
1607 * @func: (scope call): function to be called to determine whether a
1608 * specific secret should be cleared or not
1609 * @user_data: caller-supplied data passed to @func
1611 * Clears and frees secrets determined by @func.
1613 * Returns: %TRUE if the setting changed at all
1616 _nm_setting_clear_secrets_with_flags (NMSetting *setting,
1617 NMSettingClearSecretsWithFlagsFn func,
1620 GParamSpec **property_specs;
1621 guint n_property_specs;
1623 gboolean changed = FALSE;
1625 g_return_val_if_fail (setting, FALSE);
1626 g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
1627 g_return_val_if_fail (func != NULL, FALSE);
1629 property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs);
1630 for (i = 0; i < n_property_specs; i++) {
1631 if (property_specs[i]->flags & NM_SETTING_PARAM_SECRET) {
1632 changed |= NM_SETTING_GET_CLASS (setting)->clear_secrets_with_flags (setting,
1639 g_free (property_specs);
1644 * _nm_setting_need_secrets:
1645 * @setting: the #NMSetting
1647 * Returns an array of property names for each secret which may be required
1648 * to make a successful connection. The returned hints are only intended as a
1649 * guide to what secrets may be required, because in some circumstances, there
1650 * is no way to conclusively determine exactly which secrets are needed.
1652 * Returns: (transfer container) (element-type utf8): a #GPtrArray containing
1653 * the property names of secrets of the #NMSetting which may be required; the
1654 * caller owns the array and must free it with g_ptr_array_free(), but must not
1655 * free the elements.
1658 _nm_setting_need_secrets (NMSetting *setting)
1660 GPtrArray *secrets = NULL;
1662 g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
1664 if (NM_SETTING_GET_CLASS (setting)->need_secrets)
1665 secrets = NM_SETTING_GET_CLASS (setting)->need_secrets (setting);
1671 update_one_secret (NMSetting *setting, const char *key, GVariant *value, GError **error)
1673 const NMSettingProperty *property;
1674 GParamSpec *prop_spec;
1675 GValue prop_value = { 0, };
1677 property = nm_setting_class_find_property (NM_SETTING_GET_CLASS (setting), key);
1679 g_set_error_literal (error,
1680 NM_CONNECTION_ERROR,
1681 NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND,
1682 _("secret not found"));
1683 g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), key);
1684 return NM_SETTING_UPDATE_SECRET_ERROR;
1687 /* Silently ignore non-secrets */
1688 prop_spec = property->param_spec;
1689 if (!prop_spec || !(prop_spec->flags & NM_SETTING_PARAM_SECRET))
1690 return NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED;
1692 if ( g_variant_is_of_type (value, G_VARIANT_TYPE_STRING)
1693 && G_IS_PARAM_SPEC_STRING (prop_spec)) {
1694 /* String is expected to be a common case. Handle it specially and check
1695 * whether the value is already set. Otherwise, we just reset the
1696 * property and assume the value got modified.
1700 g_object_get (G_OBJECT (setting), prop_spec->name, &v, NULL);
1701 if (g_strcmp0 (v, g_variant_get_string (value, NULL)) == 0) {
1703 return NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED;
1708 g_value_init (&prop_value, prop_spec->value_type);
1709 set_property_from_dbus (property, value, &prop_value);
1710 g_object_set_property (G_OBJECT (setting), prop_spec->name, &prop_value);
1711 g_value_unset (&prop_value);
1713 return NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED;
1717 * _nm_setting_update_secrets:
1718 * @setting: the #NMSetting
1719 * @secrets: a #GVariant of type #NM_VARIANT_TYPE_SETTING, mapping property
1721 * @error: location to store error, or %NULL
1723 * Update the setting's secrets, given a dictionary of secrets intended for that
1724 * setting (deserialized from D-Bus for example).
1726 * Returns: an #NMSettingUpdateSecretResult
1728 NMSettingUpdateSecretResult
1729 _nm_setting_update_secrets (NMSetting *setting, GVariant *secrets, GError **error)
1732 const char *secret_key;
1733 GVariant *secret_value;
1734 GError *tmp_error = NULL;
1735 NMSettingUpdateSecretResult result = NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED;
1737 g_return_val_if_fail (NM_IS_SETTING (setting), NM_SETTING_UPDATE_SECRET_ERROR);
1738 g_return_val_if_fail (g_variant_is_of_type (secrets, NM_VARIANT_TYPE_SETTING), NM_SETTING_UPDATE_SECRET_ERROR);
1740 g_return_val_if_fail (*error == NULL, NM_SETTING_UPDATE_SECRET_ERROR);
1742 g_variant_iter_init (&iter, secrets);
1743 while (g_variant_iter_next (&iter, "{&sv}", &secret_key, &secret_value)) {
1746 success = NM_SETTING_GET_CLASS (setting)->update_one_secret (setting, secret_key, secret_value, &tmp_error);
1747 g_assert (!((success == NM_SETTING_UPDATE_SECRET_ERROR) ^ (!!tmp_error)));
1749 g_variant_unref (secret_value);
1751 if (success == NM_SETTING_UPDATE_SECRET_ERROR) {
1752 g_propagate_error (error, tmp_error);
1753 return NM_SETTING_UPDATE_SECRET_ERROR;
1756 if (success == NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED)
1757 result = NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED;
1764 is_secret_prop (NMSetting *setting, const char *secret_name, GError **error)
1766 const NMSettingProperty *property;
1769 property = nm_setting_class_find_property (NM_SETTING_GET_CLASS (setting), secret_name);
1771 g_set_error_literal (error,
1772 NM_CONNECTION_ERROR,
1773 NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND,
1774 _("secret is not set"));
1775 g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), secret_name);
1779 pspec = property->param_spec;
1780 if (!pspec || !(pspec->flags & NM_SETTING_PARAM_SECRET)) {
1781 g_set_error_literal (error,
1782 NM_CONNECTION_ERROR,
1783 NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET,
1784 _("not a secret property"));
1785 g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), secret_name);
1793 get_secret_flags (NMSetting *setting,
1794 const char *secret_name,
1795 gboolean verify_secret,
1796 NMSettingSecretFlags *out_flags,
1800 NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;
1802 if (verify_secret && !is_secret_prop (setting, secret_name, error)) {
1804 *out_flags = NM_SETTING_SECRET_FLAG_NONE;
1808 flags_prop = g_strdup_printf ("%s-flags", secret_name);
1809 g_object_get (G_OBJECT (setting), flags_prop, &flags, NULL);
1810 g_free (flags_prop);
1818 * nm_setting_get_secret_flags:
1819 * @setting: the #NMSetting
1820 * @secret_name: the secret key name to get flags for
1821 * @out_flags: on success, the #NMSettingSecretFlags for the secret
1822 * @error: location to store error, or %NULL
1824 * For a given secret, retrieves the #NMSettingSecretFlags describing how to
1825 * handle that secret.
1827 * Returns: %TRUE on success (if the given secret name was a valid property of
1828 * this setting, and if that property is secret), %FALSE if not
1831 nm_setting_get_secret_flags (NMSetting *setting,
1832 const char *secret_name,
1833 NMSettingSecretFlags *out_flags,
1836 g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
1837 g_return_val_if_fail (secret_name != NULL, FALSE);
1839 return NM_SETTING_GET_CLASS (setting)->get_secret_flags (setting, secret_name, TRUE, out_flags, error);
1843 set_secret_flags (NMSetting *setting,
1844 const char *secret_name,
1845 gboolean verify_secret,
1846 NMSettingSecretFlags flags,
1852 g_return_val_if_fail (is_secret_prop (setting, secret_name, error), FALSE);
1854 flags_prop = g_strdup_printf ("%s-flags", secret_name);
1855 g_object_set (G_OBJECT (setting), flags_prop, flags, NULL);
1856 g_free (flags_prop);
1861 * nm_setting_set_secret_flags:
1862 * @setting: the #NMSetting
1863 * @secret_name: the secret key name to set flags for
1864 * @flags: the #NMSettingSecretFlags for the secret
1865 * @error: location to store error, or %NULL
1867 * For a given secret, stores the #NMSettingSecretFlags describing how to
1868 * handle that secret.
1870 * Returns: %TRUE on success (if the given secret name was a valid property of
1871 * this setting, and if that property is secret), %FALSE if not
1874 nm_setting_set_secret_flags (NMSetting *setting,
1875 const char *secret_name,
1876 NMSettingSecretFlags flags,
1879 g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
1880 g_return_val_if_fail (secret_name != NULL, FALSE);
1881 g_return_val_if_fail (flags <= NM_SETTING_SECRET_FLAGS_ALL, FALSE);
1883 return NM_SETTING_GET_CLASS (setting)->set_secret_flags (setting, secret_name, TRUE, flags, error);
1887 * nm_setting_to_string:
1888 * @setting: the #NMSetting
1890 * Convert the setting into a string. For debugging purposes ONLY, should NOT
1891 * be used for serialization of the setting, or machine-parsed in any way. The
1892 * output format is not guaranteed to be stable and may change at any time.
1894 * Returns: an allocated string containing a textual representation of the
1895 * setting's properties and values (including secrets!), which the caller should
1896 * free with g_free()
1899 nm_setting_to_string (NMSetting *setting)
1902 GParamSpec **property_specs;
1903 guint n_property_specs;
1906 g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
1908 property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs);
1910 string = g_string_new (nm_setting_get_name (setting));
1911 g_string_append_c (string, '\n');
1913 for (i = 0; i < n_property_specs; i++) {
1914 GParamSpec *prop_spec = property_specs[i];
1915 GValue value = G_VALUE_INIT;
1917 gboolean is_default;
1919 if (strcmp (prop_spec->name, NM_SETTING_NAME) == 0)
1922 g_value_init (&value, prop_spec->value_type);
1923 g_object_get_property (G_OBJECT (setting), prop_spec->name, &value);
1925 value_str = g_strdup_value_contents (&value);
1926 g_string_append_printf (string, "\t%s : %s", prop_spec->name, value_str);
1929 is_default = g_param_value_defaults (prop_spec, &value);
1930 g_value_unset (&value);
1932 g_string_append (string, " (");
1933 g_string_append_c (string, 's');
1935 g_string_append_c (string, 'd');
1936 g_string_append_c (string, ')');
1937 g_string_append_c (string, '\n');
1940 g_free (property_specs);
1941 g_string_append_c (string, '\n');
1943 return g_string_free (string, FALSE);
1947 _nm_setting_get_deprecated_virtual_interface_name (NMSetting *setting,
1948 NMConnection *connection,
1949 const char *property)
1951 NMSettingConnection *s_con;
1953 s_con = nm_connection_get_setting_connection (connection);
1954 g_return_val_if_fail (s_con != NULL, NULL);
1956 if (nm_setting_connection_get_interface_name (s_con))
1957 return g_variant_new_string (nm_setting_connection_get_interface_name (s_con));
1962 /*****************************************************************************/
1965 nm_setting_init (NMSetting *setting)
1970 constructed (GObject *object)
1972 _ensure_setting_info (object, NM_SETTING_GET_PRIVATE (object));
1974 G_OBJECT_CLASS (nm_setting_parent_class)->constructed (object);
1978 get_property (GObject *object, guint prop_id,
1979 GValue *value, GParamSpec *pspec)
1981 NMSetting *setting = NM_SETTING (object);
1985 g_value_set_string (value, nm_setting_get_name (setting));
1988 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1994 nm_setting_class_init (NMSettingClass *setting_class)
1996 GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
1998 if (!setting_property_overrides_quark)
1999 setting_property_overrides_quark = g_quark_from_static_string ("nm-setting-property-overrides");
2000 if (!setting_properties_quark)
2001 setting_properties_quark = g_quark_from_static_string ("nm-setting-properties");
2003 g_type_class_add_private (setting_class, sizeof (NMSettingPrivate));
2005 /* virtual methods */
2006 object_class->constructed = constructed;
2007 object_class->get_property = get_property;
2009 setting_class->update_one_secret = update_one_secret;
2010 setting_class->get_secret_flags = get_secret_flags;
2011 setting_class->set_secret_flags = set_secret_flags;
2012 setting_class->compare_property = compare_property;
2013 setting_class->clear_secrets_with_flags = clear_secrets_with_flags;
2020 * The setting's name, which uniquely identifies the setting within the
2021 * connection. Each setting type has a name unique to that type, for
2022 * example "ppp" or "wireless" or "wired".
2024 g_object_class_install_property
2025 (object_class, PROP_NAME,
2026 g_param_spec_string (NM_SETTING_NAME, "", "",
2029 G_PARAM_STATIC_STRINGS));