fec645b2633748a4e5399c7fd60ad71a092706c3
[NetworkManager.git] / libnm-core / nm-setting.c
1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2
3 /*
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.
8  *
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.
13  *
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.
18  *
19  * Copyright 2007 - 2011 Red Hat, Inc.
20  * Copyright 2007 - 2008 Novell, Inc.
21  */
22
23 #include "nm-default.h"
24
25 #include "nm-setting.h"
26
27 #include <string.h>
28
29 #include "nm-setting-private.h"
30 #include "nm-utils.h"
31 #include "nm-core-internal.h"
32 #include "nm-utils-private.h"
33 #include "nm-property-compare.h"
34
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"
43
44 /**
45  * SECTION:nm-setting
46  * @short_description: Describes related configuration information
47  *
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.
54  */
55
56 G_DEFINE_ABSTRACT_TYPE (NMSetting, nm_setting, G_TYPE_OBJECT)
57
58 #define NM_SETTING_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING, NMSettingPrivate))
59
60 typedef struct {
61         const char *name;
62         GType type;
63         guint32 priority;
64 } SettingInfo;
65
66 typedef struct {
67         const SettingInfo *info;
68 } NMSettingPrivate;
69
70 enum {
71         PROP_0,
72         PROP_NAME,
73
74         PROP_LAST
75 };
76
77 /*************************************************************/
78
79 static GHashTable *registered_settings = NULL;
80 static GHashTable *registered_settings_by_type = NULL;
81
82 static gboolean
83 _nm_gtype_equal (gconstpointer v1, gconstpointer v2)
84 {
85         return *((const GType *) v1) == *((const GType *) v2);
86 }
87 static guint
88 _nm_gtype_hash (gconstpointer v)
89 {
90         return *((const GType *) v);
91 }
92
93 static void
94 _ensure_registered (void)
95 {
96         if (G_UNLIKELY (registered_settings == NULL)) {
97                 nm_g_type_init ();
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);
100         }
101 }
102
103 static void __attribute__((constructor))
104 _ensure_registered_constructor (void)
105 {
106         _ensure_registered ();
107 }
108
109 #define _ensure_setting_info(self, priv) \
110         G_STMT_START { \
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); \
115                 } \
116         } G_STMT_END
117
118 /*************************************************************/
119
120 /*
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
125  *
126  * INTERNAL ONLY: registers a setting's internal properties with libnm.
127  *
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.
135  *
136  * 0: reserved for the Connection setting
137  *
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.
142  *
143  * 2: hardware-related auxiliary settings that require a base setting to be
144  * successful first, like Wi-Fi security, 802.1x, etc.
145  *
146  * 3: hardware-independent settings that are required before IP connectivity
147  * can be established, like PPP, PPPoE, etc.
148  *
149  * 4: IP-level stuff
150  */
151 void
152 (_nm_register_setting) (const char *name,
153                         const GType type,
154                         const guint32 priority)
155 {
156         SettingInfo *info;
157
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);
162
163         _ensure_registered ();
164
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);
169                 return;
170         }
171         g_return_if_fail (g_hash_table_lookup (registered_settings_by_type, &type) == NULL);
172
173         if (priority == 0)
174                 g_assert_cmpstr (name, ==, NM_SETTING_CONNECTION_SETTING_NAME);
175
176         info = g_slice_new0 (SettingInfo);
177         info->type = type;
178         info->priority = priority;
179         info->name = name;
180         g_hash_table_insert (registered_settings, (void *) info->name, info);
181         g_hash_table_insert (registered_settings_by_type, &info->type, info);
182 }
183
184 static const SettingInfo *
185 _nm_setting_lookup_setting_by_type (GType type)
186 {
187         _ensure_registered ();
188         return g_hash_table_lookup (registered_settings_by_type, &type);
189 }
190
191 static guint32
192 _get_setting_type_priority (GType type)
193 {
194         const SettingInfo *info;
195
196         g_return_val_if_fail (g_type_is_a (type, NM_TYPE_SETTING), G_MAXUINT32);
197
198         info = _nm_setting_lookup_setting_by_type (type);
199         return info->priority;
200 }
201
202 guint32
203 _nm_setting_get_setting_priority (NMSetting *setting)
204 {
205         NMSettingPrivate *priv;
206
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;
211 }
212
213 gboolean
214 _nm_setting_type_is_base_type (GType type)
215 {
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
219          * base type.
220          */
221         return _get_setting_type_priority (type) == 1 || (type == NM_TYPE_SETTING_PPPOE);
222 }
223
224 gboolean
225 _nm_setting_is_base_type (NMSetting *setting)
226 {
227         return _nm_setting_type_is_base_type (G_OBJECT_TYPE (setting));
228 }
229
230 /**
231  * nm_setting_lookup_type:
232  * @name: a setting name
233  *
234  * Returns the #GType of the setting's class for a given setting name.
235  *
236  * Returns: the #GType of the setting's class, or %G_TYPE_INVALID if
237  *   @name is not recognized.
238  **/
239 GType
240 nm_setting_lookup_type (const char *name)
241 {
242         SettingInfo *info;
243
244         g_return_val_if_fail (name != NULL, G_TYPE_INVALID);
245
246         _ensure_registered ();
247
248         info = g_hash_table_lookup (registered_settings, name);
249         return info ? info->type : G_TYPE_INVALID;
250 }
251
252 gint
253 _nm_setting_compare_priority (gconstpointer a, gconstpointer b)
254 {
255         guint32 prio_a, prio_b;
256
257         prio_a = _nm_setting_get_setting_priority ((NMSetting *) a);
258         prio_b = _nm_setting_get_setting_priority ((NMSetting *) b);
259
260         if (prio_a < prio_b)
261                 return -1;
262         else if (prio_a == prio_b)
263                 return 0;
264         return 1;
265 }
266
267 /*************************************************************/
268
269 gboolean
270 _nm_setting_slave_type_is_valid (const char *slave_type, const char **out_port_type)
271 {
272         const char *port_type = NULL;
273         gboolean found = TRUE;
274
275         if (!slave_type)
276                 found = FALSE;
277         else if (!strcmp (slave_type, NM_SETTING_BOND_SETTING_NAME))
278                 ;
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;
283         else
284                 found = FALSE;
285
286         if (out_port_type)
287                 *out_port_type = port_type;
288         return found;
289 }
290
291 /*************************************************************/
292
293 typedef struct {
294         const char *name;
295         GParamSpec *param_spec;
296         const GVariantType *dbus_type;
297
298         NMSettingPropertyGetFunc get_func;
299         NMSettingPropertySynthFunc synth_func;
300         NMSettingPropertySetFunc set_func;
301         NMSettingPropertyNotSetFunc not_set_func;
302
303         NMSettingPropertyTransformToFunc to_dbus;
304         NMSettingPropertyTransformFromFunc from_dbus;
305 } NMSettingProperty;
306
307 static GQuark setting_property_overrides_quark;
308 static GQuark setting_properties_quark;
309
310 static NMSettingProperty *
311 find_property (GArray *properties, const char *name)
312 {
313         NMSettingProperty *property;
314         int i;
315
316         if (!properties)
317                 return NULL;
318
319         for (i = 0; i < properties->len; i++) {
320                 property = &g_array_index (properties, NMSettingProperty, i);
321                 if (strcmp (name, property->name) == 0)
322                         return property;
323         }
324
325         return NULL;
326 }
327
328 static void
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)
339 {
340         GType setting_type = G_TYPE_FROM_CLASS (setting_class);
341         GArray *overrides;
342         NMSettingProperty override;
343
344         g_return_if_fail (g_type_get_qdata (setting_type, setting_properties_quark) == NULL);
345
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;
356
357         overrides = g_type_get_qdata (setting_type, setting_property_overrides_quark);
358         if (!overrides) {
359                 overrides = g_array_new (FALSE, FALSE, sizeof (NMSettingProperty));
360                 g_type_set_qdata (setting_type, setting_property_overrides_quark, overrides);
361         }
362         g_return_if_fail (find_property (overrides, property_name) == NULL);
363
364         g_array_append_val (overrides, override);
365 }
366
367 /**
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
374  *
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.
378  *
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.)
383  *
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.)
387  */
388 void
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)
394 {
395         g_return_if_fail (NM_IS_SETTING_CLASS (setting_class));
396         g_return_if_fail (property_name != NULL);
397
398         /* Must not match any GObject property. */
399         g_return_if_fail (!g_object_class_find_property (G_OBJECT_CLASS (setting_class), property_name));
400
401         add_property_override (setting_class,
402                                property_name, NULL, dbus_type,
403                                NULL, synth_func, set_func, NULL,
404                                NULL, NULL);
405 }
406
407 /**
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
415  *
416  * Overrides the D-Bus representation of the #GObject property named
417  * @property_name on @setting_class.
418  *
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
424  * value.)
425  *
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().)
429  *
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.
434  */
435 void
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)
442 {
443         GParamSpec *param_spec;
444
445         param_spec = g_object_class_find_property (G_OBJECT_CLASS (setting_class), property_name);
446         g_return_if_fail (param_spec != NULL);
447
448         add_property_override (setting_class,
449                                property_name, param_spec, dbus_type,
450                                get_func, NULL, set_func, not_set_func,
451                                NULL, NULL);
452 }
453
454 /**
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
461  *
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.
465  *
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.
469  */
470 void
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)
476 {
477         GParamSpec *param_spec;
478
479         param_spec = g_object_class_find_property (G_OBJECT_CLASS (setting_class), property);
480         g_return_if_fail (param_spec != NULL);
481
482         add_property_override (setting_class,
483                                property, param_spec, dbus_type,
484                                NULL, NULL, NULL, NULL,
485                                to_dbus, from_dbus);
486 }
487
488 gboolean
489 _nm_setting_use_legacy_property (NMSetting *setting,
490                                  GVariant *connection_dict,
491                                  const char *legacy_property,
492                                  const char *new_property)
493 {
494         GVariant *setting_dict, *value;
495
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);
498
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);
501         if (!value) {
502                 g_variant_unref (setting_dict);
503                 return TRUE;
504         }
505         g_variant_unref (value);
506
507         /* Otherwise, clients always prefer new properties sent from the daemon. */
508         if (!_nm_utils_is_manager_process) {
509                 g_variant_unref (setting_dict);
510                 return FALSE;
511         }
512
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);
516
517         if (value) {
518                 g_variant_unref (value);
519                 return TRUE;
520         } else
521                 return FALSE;
522 }
523
524 static GArray *
525 nm_setting_class_ensure_properties (NMSettingClass *setting_class)
526 {
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;
532
533         properties = g_type_get_qdata (type, setting_properties_quark);
534         if (properties)
535                 return properties;
536
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);
541                 if (type_overrides)
542                         g_array_append_vals (overrides, (NMSettingProperty *)type_overrides->data, type_overrides->len);
543         }
544
545         /* Build the properties array from the GParamSpecs, obeying overrides */
546         properties = g_array_new (FALSE, FALSE, sizeof (NMSettingProperty));
547
548         property_specs = g_object_class_list_properties (G_OBJECT_CLASS (setting_class),
549                                                          &n_property_specs);
550         for (i = 0; i < n_property_specs; i++) {
551                 override = find_property (overrides, property_specs[i]->name);
552                 if (override)
553                         property = *override;
554                 else {
555                         memset (&property, 0, sizeof (property));
556                         property.name = property_specs[i]->name;
557                         property.param_spec = property_specs[i];
558                 }
559                 g_array_append_val (properties, property);
560         }
561         g_free (property_specs);
562
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);
568         }
569         g_array_unref (overrides);
570
571         g_type_set_qdata (type, setting_properties_quark, properties);
572         return properties;
573 }
574
575 static const NMSettingProperty *
576 nm_setting_class_get_properties (NMSettingClass *setting_class, guint *n_properties)
577 {
578         GArray *properties;
579
580         properties = nm_setting_class_ensure_properties (setting_class);
581
582         *n_properties = properties->len;
583         return (NMSettingProperty *) properties->data;
584 }
585
586 static const NMSettingProperty *
587 nm_setting_class_find_property (NMSettingClass *setting_class, const char *property_name)
588 {
589         GArray *properties;
590
591         properties = nm_setting_class_ensure_properties (setting_class);
592         return find_property (properties, property_name);
593 }
594
595 /*************************************************************/
596
597 static const GVariantType *
598 variant_type_for_gtype (GType type)
599 {
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;
624         else
625                 g_assert_not_reached ();
626 }
627
628 static GVariant *
629 get_property_for_dbus (NMSetting *setting,
630                        const NMSettingProperty *property,
631                        gboolean ignore_default)
632 {
633         GValue prop_value = { 0, };
634         GVariant *dbus_value;
635
636         if (property->get_func)
637                 return property->get_func (setting, property->name);
638         else
639                 g_return_val_if_fail (property->param_spec != NULL, NULL);
640
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);
643
644         if (ignore_default && g_param_value_defaults (property->param_spec, &prop_value)) {
645                 g_value_unset (&prop_value);
646                 return NULL;
647         }
648
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);
659         else
660                 dbus_value = g_dbus_gvalue_to_gvariant (&prop_value, variant_type_for_gtype (prop_value.g_type));
661         g_value_unset (&prop_value);
662
663         return dbus_value;
664 }
665
666 static gboolean
667 set_property_from_dbus (const NMSettingProperty *property,
668                         GVariant *src_value,
669                         GValue *dst_value)
670 {
671         g_return_val_if_fail (property->param_spec != NULL, FALSE);
672
673         if (property->from_dbus) {
674                 if (!g_variant_type_equal (g_variant_get_type (src_value), property->dbus_type))
675                         return FALSE;
676
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))
680                         return FALSE;
681
682                 _nm_utils_bytes_from_dbus (src_value, dst_value);
683         } else {
684                 GValue tmp = G_VALUE_INIT;
685
686                 g_dbus_gvariant_to_gvalue (src_value, &tmp);
687                 if (G_VALUE_TYPE (&tmp) == G_VALUE_TYPE (dst_value))
688                         *dst_value = tmp;
689                 else {
690                         gboolean success;
691
692                         success = g_value_transform (&tmp, dst_value);
693                         g_value_unset (&tmp);
694                         if (!success)
695                                 return FALSE;
696                 }
697         }
698
699         return TRUE;
700 }
701
702
703 /**
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
708  *
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.
712  *
713  * Returns: (transfer none): a new floating #GVariant describing the setting's
714  * properties
715  **/
716 GVariant *
717 _nm_setting_to_dbus (NMSetting *setting, NMConnection *connection, NMConnectionSerializationFlags flags)
718 {
719         GVariantBuilder builder;
720         GVariant *dbus_value;
721         const NMSettingProperty *properties;
722         guint n_properties, i;
723
724         g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
725
726         properties = nm_setting_class_get_properties (NM_SETTING_GET_CLASS (setting), &n_properties);
727
728         g_variant_builder_init (&builder, NM_VARIANT_TYPE_SETTING);
729
730         for (i = 0; i < n_properties; i++) {
731                 const NMSettingProperty *property = &properties[i];
732                 GParamSpec *prop_spec = property->param_spec;
733
734                 if (!prop_spec && !property->synth_func) {
735                         /* D-Bus-only property with no synth_func, so we skip it. */
736                         continue;
737                 }
738
739                 if (prop_spec && !(prop_spec->flags & G_PARAM_WRITABLE))
740                         continue;
741
742                 if (   prop_spec && (prop_spec->flags & NM_SETTING_PARAM_LEGACY)
743                     && !_nm_utils_is_manager_process)
744                         continue;
745
746                 if (   (flags & NM_CONNECTION_SERIALIZE_NO_SECRETS)
747                     && (prop_spec && (prop_spec->flags & NM_SETTING_PARAM_SECRET)))
748                         continue;
749
750                 if (   (flags & NM_CONNECTION_SERIALIZE_ONLY_SECRETS)
751                     && !(prop_spec && (prop_spec->flags & NM_SETTING_PARAM_SECRET)))
752                         continue;
753
754                 if (property->synth_func)
755                         dbus_value = property->synth_func (setting, connection, property->name);
756                 else
757                         dbus_value = get_property_for_dbus (setting, property, TRUE);
758                 if (dbus_value) {
759                         /* Allow dbus_value to be either floating or not. */
760                         g_variant_take_ref (dbus_value);
761
762                         g_variant_builder_add (&builder, "{sv}", property->name, dbus_value);
763                         g_variant_unref (dbus_value);
764                 }
765         }
766
767         return g_variant_builder_end (&builder);
768 }
769
770 /**
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  * @error: location to store error, or %NULL
778  *
779  * Creates a new #NMSetting object and populates that object with the properties
780  * contained in @setting_dict, using each key as the property to set, and each
781  * value as the value to set that property to.  Setting properties are strongly
782  * typed, thus the #GVariantType of the dict value must be correct.  See the
783  * documentation on each #NMSetting object subclass for the correct property
784  * names and value types.
785  *
786  * Returns: a new #NMSetting object populated with the properties from the
787  * hash table, or %NULL if @setting_hash could not be deserialized.
788  **/
789 NMSetting *
790 _nm_setting_new_from_dbus (GType setting_type,
791                            GVariant *setting_dict,
792                            GVariant *connection_dict,
793                            GError **error)
794 {
795         NMSetting *setting;
796         const NMSettingProperty *properties;
797         guint n_properties;
798         guint i;
799
800         g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (setting_type), NULL);
801         g_return_val_if_fail (g_variant_is_of_type (setting_dict, NM_VARIANT_TYPE_SETTING), NULL);
802
803         /* connection_dict is not technically optional, but some tests in test-general
804          * don't bother with it in cases where they know it's not needed.
805          */
806         if (connection_dict)
807                 g_return_val_if_fail (g_variant_is_of_type (connection_dict, NM_VARIANT_TYPE_CONNECTION), NULL);
808
809         /* Build the setting object from the properties we know about; we assume
810          * that any propreties in @setting_dict that we don't know about can
811          * either be ignored or else has a backward-compatibility equivalent
812          * that we do know about.
813          */
814         setting = (NMSetting *) g_object_new (setting_type, NULL);
815
816         properties = nm_setting_class_get_properties (NM_SETTING_GET_CLASS (setting), &n_properties);
817         for (i = 0; i < n_properties; i++) {
818                 const NMSettingProperty *property = &properties[i];
819                 GVariant *value;
820
821                 if (property->param_spec && !(property->param_spec->flags & G_PARAM_WRITABLE))
822                         continue;
823
824                 value = g_variant_lookup_value (setting_dict, property->name, NULL);
825
826                 if (value && property->set_func) {
827                         if (!g_variant_type_equal (g_variant_get_type (value), property->dbus_type)) {
828                         property_type_error:
829                                 g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY,
830                                              _("can't set property of type '%s' from value of type '%s'"),
831                                              property->dbus_type ?
832                                                  g_variant_type_peek_string (property->dbus_type) :
833                                                  property->param_spec ?
834                                                      g_type_name (property->param_spec->value_type) : "(unknown)",
835                                              g_variant_get_type_string (value));
836                                 g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), property->name);
837
838                                 g_variant_unref (value);
839                                 g_object_unref (setting);
840                                 return NULL;
841                         }
842
843                         property->set_func (setting,
844                                             connection_dict,
845                                             property->name,
846                                             value);
847                 } else if (!value && property->not_set_func) {
848                         property->not_set_func (setting,
849                                                 connection_dict,
850                                                 property->name);
851                 } else if (value && property->param_spec) {
852                         GValue object_value = { 0, };
853
854                         g_value_init (&object_value, property->param_spec->value_type);
855                         if (!set_property_from_dbus (property, value, &object_value))
856                                 goto property_type_error;
857
858                         g_object_set_property (G_OBJECT (setting), property->param_spec->name, &object_value);
859                         g_value_unset (&object_value);
860                 }
861
862                 if (value)
863                         g_variant_unref (value);
864         }
865
866         return setting;
867 }
868
869 /**
870  * nm_setting_get_dbus_property_type:
871  * @setting: an #NMSetting
872  * @property_name: the property of @setting to get the type of
873  *
874  * Gets the D-Bus marshalling type of a property. @property_name is a D-Bus
875  * property name, which may not necessarily be a #GObject property.
876  *
877  * Returns: the D-Bus marshalling type of @property on @setting.
878  */
879 const GVariantType *
880 nm_setting_get_dbus_property_type (NMSetting *setting,
881                                    const char *property_name)
882 {
883         const NMSettingProperty *property;
884
885         g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
886         g_return_val_if_fail (property_name != NULL, NULL);
887
888         property = nm_setting_class_find_property (NM_SETTING_GET_CLASS (setting), property_name);
889         g_return_val_if_fail (property != NULL, NULL);
890
891         if (property->dbus_type)
892                 return property->dbus_type;
893         else
894                 return variant_type_for_gtype (property->param_spec->value_type);
895 }
896
897 gboolean
898 _nm_setting_get_property (NMSetting *setting, const char *property_name, GValue *value)
899 {
900         GParamSpec *prop_spec;
901
902         g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
903         g_return_val_if_fail (property_name, FALSE);
904         g_return_val_if_fail (value, FALSE);
905
906         prop_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), property_name);
907
908         if (!prop_spec) {
909                 g_value_unset (value);
910                 return FALSE;
911         }
912
913         g_value_init (value, prop_spec->value_type);
914         g_object_get_property (G_OBJECT (setting), property_name, value);
915         return TRUE;
916 }
917
918 static void
919 duplicate_setting (NMSetting *setting,
920                    const char *name,
921                    const GValue *value,
922                    GParamFlags flags,
923                    gpointer user_data)
924 {
925         if ((flags & (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)) == G_PARAM_WRITABLE)
926                 g_object_set_property (G_OBJECT (user_data), name, value);
927 }
928
929 /**
930  * nm_setting_duplicate:
931  * @setting: the #NMSetting to duplicate
932  *
933  * Duplicates a #NMSetting.
934  *
935  * Returns: (transfer full): a new #NMSetting containing the same properties and values as the
936  * source #NMSetting
937  **/
938 NMSetting *
939 nm_setting_duplicate (NMSetting *setting)
940 {
941         GObject *dup;
942
943         g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
944
945         dup = g_object_new (G_OBJECT_TYPE (setting), NULL);
946
947         g_object_freeze_notify (dup);
948         nm_setting_enumerate_values (setting, duplicate_setting, dup);
949         g_object_thaw_notify (dup);
950
951         return NM_SETTING (dup);
952 }
953
954 /**
955  * nm_setting_get_name:
956  * @setting: the #NMSetting
957  *
958  * Returns the type name of the #NMSetting object
959  *
960  * Returns: a string containing the type name of the #NMSetting object,
961  * like 'ppp' or 'wireless' or 'wired'.
962  **/
963 const char *
964 nm_setting_get_name (NMSetting *setting)
965 {
966         NMSettingPrivate *priv;
967
968         g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
969         priv = NM_SETTING_GET_PRIVATE (setting);
970         _ensure_setting_info (setting, priv);
971         return priv->info->name;
972 }
973
974 /**
975  * nm_setting_verify:
976  * @setting: the #NMSetting to verify
977  * @connection: (allow-none): the #NMConnection that @setting came from, or
978  *   %NULL if @setting is being verified in isolation.
979  * @error: location to store error, or %NULL
980  *
981  * Validates the setting.  Each setting's properties have allowed values, and
982  * some are dependent on other values (hence the need for @connection).  The
983  * returned #GError contains information about which property of the setting
984  * failed validation, and in what way that property failed validation.
985  *
986  * Returns: %TRUE if the setting is valid, %FALSE if it is not
987  **/
988 gboolean
989 nm_setting_verify (NMSetting *setting, NMConnection *connection, GError **error)
990 {
991         NMSettingVerifyResult result = _nm_setting_verify (setting, connection, error);
992
993         if (result == NM_SETTING_VERIFY_NORMALIZABLE)
994                 g_clear_error (error);
995
996         return result == NM_SETTING_VERIFY_SUCCESS || result == NM_SETTING_VERIFY_NORMALIZABLE;
997 }
998
999 NMSettingVerifyResult
1000 _nm_setting_verify (NMSetting *setting, NMConnection *connection, GError **error)
1001 {
1002         g_return_val_if_fail (NM_IS_SETTING (setting), NM_SETTING_VERIFY_ERROR);
1003         g_return_val_if_fail (!connection || NM_IS_CONNECTION (connection), NM_SETTING_VERIFY_ERROR);
1004         g_return_val_if_fail (!error || *error == NULL, NM_SETTING_VERIFY_ERROR);
1005
1006         if (NM_SETTING_GET_CLASS (setting)->verify)
1007                 return NM_SETTING_GET_CLASS (setting)->verify (setting, connection, error);
1008
1009         return NM_SETTING_VERIFY_SUCCESS;
1010 }
1011
1012 /**
1013  * nm_setting_verify_secrets:
1014  * @setting: the #NMSetting to verify secrets in
1015  * @connection: (allow-none): the #NMConnection that @setting came from, or
1016  *   %NULL if @setting is being verified in isolation.
1017  * @error: location to store error, or %NULL
1018  *
1019  * Verifies the secrets in the setting.
1020  * The returned #GError contains information about which secret of the setting
1021  * failed validation, and in what way that secret failed validation.
1022  * The secret validation is done separately from main setting validation, because
1023  * in some cases connection failure is not desired just for the secrets.
1024  *
1025  * Returns: %TRUE if the setting secrets are valid, %FALSE if they are not
1026  *
1027  * Since: 1.2
1028  **/
1029 gboolean
1030 nm_setting_verify_secrets (NMSetting *setting, NMConnection *connection, GError **error)
1031 {
1032         g_return_val_if_fail (NM_IS_SETTING (setting), NM_SETTING_VERIFY_ERROR);
1033         g_return_val_if_fail (!connection || NM_IS_CONNECTION (connection), NM_SETTING_VERIFY_ERROR);
1034         g_return_val_if_fail (!error || *error == NULL, NM_SETTING_VERIFY_ERROR);
1035
1036         if (NM_SETTING_GET_CLASS (setting)->verify_secrets)
1037                 return NM_SETTING_GET_CLASS (setting)->verify_secrets (setting, connection, error);
1038
1039         return NM_SETTING_VERIFY_SUCCESS;
1040 }
1041
1042 gboolean
1043 _nm_setting_verify_secret_string (const char *str,
1044                                   const char *setting_name,
1045                                   const char *property,
1046                                   GError **error)
1047 {
1048         if (str && !*str) {
1049                 g_set_error_literal (error,
1050                                      NM_CONNECTION_ERROR,
1051                                      NM_CONNECTION_ERROR_INVALID_PROPERTY,
1052                                      _("property is empty"));
1053                 g_prefix_error (error, "%s.%s: ", setting_name, property);
1054                 return FALSE;
1055         }
1056         return TRUE;
1057 }
1058
1059 static gboolean
1060 compare_property (NMSetting *setting,
1061                   NMSetting *other,
1062                   const GParamSpec *prop_spec,
1063                   NMSettingCompareFlags flags)
1064 {
1065         const NMSettingProperty *property;
1066         GVariant *value1, *value2;
1067         int cmp;
1068
1069         /* Handle compare flags */
1070         if (prop_spec->flags & NM_SETTING_PARAM_SECRET) {
1071                 NMSettingSecretFlags a_secret_flags = NM_SETTING_SECRET_FLAG_NONE;
1072                 NMSettingSecretFlags b_secret_flags = NM_SETTING_SECRET_FLAG_NONE;
1073
1074                 g_return_val_if_fail (!NM_IS_SETTING_VPN (setting), FALSE);
1075
1076                 if (!nm_setting_get_secret_flags (setting, prop_spec->name, &a_secret_flags, NULL))
1077                         g_return_val_if_reached (FALSE);
1078                 if (!nm_setting_get_secret_flags (other, prop_spec->name, &b_secret_flags, NULL))
1079                         g_return_val_if_reached (FALSE);
1080
1081                 /* If the secret flags aren't the same the settings aren't the same */
1082                 if (a_secret_flags != b_secret_flags)
1083                         return FALSE;
1084
1085                 /* Check for various secret flags that might cause us to ignore comparing
1086                  * this property.
1087                  */
1088                 if (   (flags & NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS)
1089                     && (a_secret_flags & NM_SETTING_SECRET_FLAG_AGENT_OWNED))
1090                         return TRUE;
1091
1092                 if (   (flags & NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)
1093                     && (a_secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED))
1094                         return TRUE;
1095         }
1096
1097         property = nm_setting_class_find_property (NM_SETTING_GET_CLASS (setting), prop_spec->name);
1098         g_return_val_if_fail (property != NULL, FALSE);
1099
1100         value1 = get_property_for_dbus (setting, property, TRUE);
1101         value2 = get_property_for_dbus (other, property, TRUE);
1102
1103         cmp = nm_property_compare (value1, value2);
1104
1105         if (value1)
1106                 g_variant_unref (value1);
1107         if (value2)
1108                 g_variant_unref (value2);
1109
1110         return cmp == 0;
1111 }
1112
1113 /**
1114  * nm_setting_compare:
1115  * @a: a #NMSetting
1116  * @b: a second #NMSetting to compare with the first
1117  * @flags: compare flags, e.g. %NM_SETTING_COMPARE_FLAG_EXACT
1118  *
1119  * Compares two #NMSetting objects for similarity, with comparison behavior
1120  * modified by a set of flags.  See the documentation for #NMSettingCompareFlags
1121  * for a description of each flag's behavior.
1122  *
1123  * Returns: %TRUE if the comparison succeeds, %FALSE if it does not
1124  **/
1125 gboolean
1126 nm_setting_compare (NMSetting *a,
1127                     NMSetting *b,
1128                     NMSettingCompareFlags flags)
1129 {
1130         GParamSpec **property_specs;
1131         guint n_property_specs;
1132         gint same = TRUE;
1133         guint i;
1134
1135         g_return_val_if_fail (NM_IS_SETTING (a), FALSE);
1136         g_return_val_if_fail (NM_IS_SETTING (b), FALSE);
1137
1138         /* First check that both have the same type */
1139         if (G_OBJECT_TYPE (a) != G_OBJECT_TYPE (b))
1140                 return FALSE;
1141
1142         /* And now all properties */
1143         property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (a), &n_property_specs);
1144         for (i = 0; i < n_property_specs && same; i++) {
1145                 GParamSpec *prop_spec = property_specs[i];
1146
1147                 /* Fuzzy compare ignores secrets and properties defined with the FUZZY_IGNORE flag */
1148                 if (   NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_FUZZY)
1149                     && !NM_FLAGS_ANY (prop_spec->flags, NM_SETTING_PARAM_FUZZY_IGNORE | NM_SETTING_PARAM_SECRET))
1150                         continue;
1151
1152                 if (   NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_INFERRABLE)
1153                     && !NM_FLAGS_HAS (prop_spec->flags, NM_SETTING_PARAM_INFERRABLE))
1154                         continue;
1155
1156                 if (   NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_IGNORE_REAPPLY_IMMEDIATELY)
1157                     && NM_FLAGS_HAS (prop_spec->flags, NM_SETTING_PARAM_REAPPLY_IMMEDIATELY))
1158                         continue;
1159
1160                 if (   NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS)
1161                     && NM_FLAGS_HAS (prop_spec->flags, NM_SETTING_PARAM_SECRET))
1162                         continue;
1163
1164                 same = NM_SETTING_GET_CLASS (a)->compare_property (a, b, prop_spec, flags);
1165         }
1166         g_free (property_specs);
1167
1168         return same;
1169 }
1170
1171 static inline gboolean
1172 should_compare_prop (NMSetting *setting,
1173                      const char *prop_name,
1174                      NMSettingCompareFlags comp_flags,
1175                      GParamFlags prop_flags)
1176 {
1177         /* Fuzzy compare ignores secrets and properties defined with the FUZZY_IGNORE flag */
1178         if (   (comp_flags & NM_SETTING_COMPARE_FLAG_FUZZY)
1179             && (prop_flags & (NM_SETTING_PARAM_FUZZY_IGNORE | NM_SETTING_PARAM_SECRET)))
1180                 return FALSE;
1181
1182         if ((comp_flags & NM_SETTING_COMPARE_FLAG_INFERRABLE) && !(prop_flags & NM_SETTING_PARAM_INFERRABLE))
1183                 return FALSE;
1184
1185         if ((comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_REAPPLY_IMMEDIATELY) && !(prop_flags & NM_SETTING_PARAM_REAPPLY_IMMEDIATELY))
1186                 return FALSE;
1187
1188         if (prop_flags & NM_SETTING_PARAM_SECRET) {
1189                 NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
1190
1191                 if (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS)
1192                         return FALSE;
1193
1194                 if (   NM_IS_SETTING_VPN (setting)
1195                     && g_strcmp0 (prop_name, NM_SETTING_VPN_SECRETS) == 0) {
1196                         /* FIXME: NMSettingVPN:NM_SETTING_VPN_SECRETS has NM_SETTING_PARAM_SECRET.
1197                          * nm_setting_get_secret_flags() quite possibly fails, but it might succeed if the
1198                          * setting accidently uses a key "secrets". */
1199                         return TRUE;
1200                 }
1201
1202                 if (!nm_setting_get_secret_flags (setting, prop_name, &secret_flags, NULL))
1203                         g_return_val_if_reached (FALSE);
1204
1205                 if (   (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS)
1206                     && (secret_flags & NM_SETTING_SECRET_FLAG_AGENT_OWNED))
1207                         return FALSE;
1208
1209                 if (   (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)
1210                     && (secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED))
1211                         return FALSE;
1212         }
1213
1214         if (   (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_ID)
1215             && NM_IS_SETTING_CONNECTION (setting)
1216             && !strcmp (prop_name, NM_SETTING_CONNECTION_ID))
1217                 return FALSE;
1218
1219         if (   (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_TIMESTAMP)
1220             && NM_IS_SETTING_CONNECTION (setting)
1221             && !strcmp (prop_name, NM_SETTING_CONNECTION_TIMESTAMP))
1222                 return FALSE;
1223
1224         return TRUE;
1225 }
1226
1227 /**
1228  * nm_setting_diff:
1229  * @a: a #NMSetting
1230  * @b: a second #NMSetting to compare with the first
1231  * @flags: compare flags, e.g. %NM_SETTING_COMPARE_FLAG_EXACT
1232  * @invert_results: this parameter is used internally by libnm and should
1233  * be set to %FALSE.  If %TRUE inverts the meaning of the #NMSettingDiffResult.
1234  * @results: (inout) (transfer full) (element-type utf8 guint32): if the
1235  * settings differ, on return a hash table mapping the differing keys to one or
1236  * more %NMSettingDiffResult values OR-ed together.  If the settings do not
1237  * differ, any hash table passed in is unmodified.  If no hash table is passed
1238  * in and the settings differ, a new one is created and returned.
1239  *
1240  * Compares two #NMSetting objects for similarity, with comparison behavior
1241  * modified by a set of flags.  See the documentation for #NMSettingCompareFlags
1242  * for a description of each flag's behavior.  If the settings differ, the keys
1243  * of each setting that differ from the other are added to @results, mapped to
1244  * one or more #NMSettingDiffResult values.
1245  *
1246  * Returns: %TRUE if the settings contain the same values, %FALSE if they do not
1247  **/
1248 gboolean
1249 nm_setting_diff (NMSetting *a,
1250                  NMSetting *b,
1251                  NMSettingCompareFlags flags,
1252                  gboolean invert_results,
1253                  GHashTable **results)
1254 {
1255         GParamSpec **property_specs;
1256         guint n_property_specs;
1257         guint i;
1258         NMSettingDiffResult a_result = NM_SETTING_DIFF_RESULT_IN_A;
1259         NMSettingDiffResult b_result = NM_SETTING_DIFF_RESULT_IN_B;
1260         NMSettingDiffResult a_result_default = NM_SETTING_DIFF_RESULT_IN_A_DEFAULT;
1261         NMSettingDiffResult b_result_default = NM_SETTING_DIFF_RESULT_IN_B_DEFAULT;
1262         gboolean results_created = FALSE;
1263
1264         g_return_val_if_fail (results != NULL, FALSE);
1265         g_return_val_if_fail (NM_IS_SETTING (a), FALSE);
1266         if (b) {
1267                 g_return_val_if_fail (NM_IS_SETTING (b), FALSE);
1268                 g_return_val_if_fail (G_OBJECT_TYPE (a) == G_OBJECT_TYPE (b), FALSE);
1269         }
1270
1271         if ((flags & (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) ==
1272                      (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) {
1273                 /* conflicting flags: default to WITH_DEFAULT (clearing NO_DEFAULT). */
1274                 flags &= ~NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT;
1275         }
1276
1277         /* If the caller is calling this function in a pattern like this to get
1278          * complete diffs:
1279          *
1280          * nm_setting_diff (A, B, FALSE, &results);
1281          * nm_setting_diff (B, A, TRUE, &results);
1282          *
1283          * and wants us to invert the results so that the second invocation comes
1284          * out correctly, do that here.
1285          */
1286         if (invert_results) {
1287                 a_result = NM_SETTING_DIFF_RESULT_IN_B;
1288                 b_result = NM_SETTING_DIFF_RESULT_IN_A;
1289                 a_result_default = NM_SETTING_DIFF_RESULT_IN_B_DEFAULT;
1290                 b_result_default = NM_SETTING_DIFF_RESULT_IN_A_DEFAULT;
1291         }
1292
1293         if (*results == NULL) {
1294                 *results = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
1295                 results_created = TRUE;
1296         }
1297
1298         /* And now all properties */
1299         property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (a), &n_property_specs);
1300
1301         for (i = 0; i < n_property_specs; i++) {
1302                 GParamSpec *prop_spec = property_specs[i];
1303                 NMSettingDiffResult r = NM_SETTING_DIFF_RESULT_UNKNOWN;
1304
1305                 /* Handle compare flags */
1306                 if (!should_compare_prop (a, prop_spec->name, flags, prop_spec->flags))
1307                         continue;
1308                 if (strcmp (prop_spec->name, NM_SETTING_NAME) == 0)
1309                         continue;
1310
1311                 if (b) {
1312                         gboolean different;
1313
1314                         different = !NM_SETTING_GET_CLASS (a)->compare_property (a, b, prop_spec, flags);
1315                         if (different) {
1316                                 gboolean a_is_default, b_is_default;
1317                                 GValue value = G_VALUE_INIT;
1318
1319                                 g_value_init (&value, prop_spec->value_type);
1320                                 g_object_get_property (G_OBJECT (a), prop_spec->name, &value);
1321                                 a_is_default = g_param_value_defaults (prop_spec, &value);
1322
1323                                 g_value_reset (&value);
1324                                 g_object_get_property (G_OBJECT (b), prop_spec->name, &value);
1325                                 b_is_default = g_param_value_defaults (prop_spec, &value);
1326
1327                                 g_value_unset (&value);
1328                                 if ((flags & NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT) == 0) {
1329                                         if (!a_is_default)
1330                                                 r |= a_result;
1331                                         if (!b_is_default)
1332                                                 r |= b_result;
1333                                 } else {
1334                                         r |= a_result | b_result;
1335                                         if (a_is_default)
1336                                                 r |= a_result_default;
1337                                         if (b_is_default)
1338                                                 r |= b_result_default;
1339                                 }
1340                         }
1341                 } else if ((flags & (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) == 0)
1342                         r = a_result;  /* only in A */
1343                 else {
1344                         GValue value = G_VALUE_INIT;
1345
1346                         g_value_init (&value, prop_spec->value_type);
1347                         g_object_get_property (G_OBJECT (a), prop_spec->name, &value);
1348                         if (!g_param_value_defaults (prop_spec, &value))
1349                                 r |= a_result;
1350                         else if (flags & NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT)
1351                                 r |= a_result | a_result_default;
1352
1353                         g_value_unset (&value);
1354                 }
1355
1356                 if (r != NM_SETTING_DIFF_RESULT_UNKNOWN) {
1357                         void *p;
1358
1359                         if (g_hash_table_lookup_extended (*results, prop_spec->name, NULL, &p)) {
1360                                 if ((r & GPOINTER_TO_UINT (p)) != r)
1361                                         g_hash_table_insert (*results, g_strdup (prop_spec->name), GUINT_TO_POINTER (r | GPOINTER_TO_UINT (p)));
1362                         } else
1363                                 g_hash_table_insert (*results, g_strdup (prop_spec->name), GUINT_TO_POINTER (r));
1364                 }
1365         }
1366         g_free (property_specs);
1367
1368         /* Don't return an empty hash table */
1369         if (results_created && !g_hash_table_size (*results)) {
1370                 g_hash_table_destroy (*results);
1371                 *results = NULL;
1372         }
1373
1374         return !(*results);
1375 }
1376
1377 #define CMP_AND_RETURN(n_a, n_b, name) \
1378         G_STMT_START { \
1379                 gboolean _is = (strcmp (n_a, ""name) == 0); \
1380                 \
1381                 if (_is || (strcmp (n_b, ""name) == 0)) \
1382                         return _is ? -1 : 1; \
1383         } G_STMT_END
1384
1385 static int
1386 _enumerate_values_sort (GParamSpec **p_a, GParamSpec **p_b, GType *p_type)
1387 {
1388         const char *n_a = (*p_a)->name;
1389         const char *n_b = (*p_b)->name;
1390         int c = strcmp (n_a, n_b);
1391
1392         if (c) {
1393                 if (*p_type == NM_TYPE_SETTING_CONNECTION) {
1394                         /* for [connection], report first id, uuid, type in that order. */
1395                         CMP_AND_RETURN (n_a, n_b, NM_SETTING_CONNECTION_ID);
1396                         CMP_AND_RETURN (n_a, n_b, NM_SETTING_CONNECTION_UUID);
1397                         CMP_AND_RETURN (n_a, n_b, NM_SETTING_CONNECTION_TYPE);
1398                 }
1399         }
1400         return c;
1401 }
1402 #undef CMP_AND_RETURN
1403
1404 /**
1405  * nm_setting_enumerate_values:
1406  * @setting: the #NMSetting
1407  * @func: (scope call): user-supplied function called for each property of the setting
1408  * @user_data: user data passed to @func at each invocation
1409  *
1410  * Iterates over each property of the #NMSetting object, calling the supplied
1411  * user function for each property.
1412  **/
1413 void
1414 nm_setting_enumerate_values (NMSetting *setting,
1415                              NMSettingValueIterFn func,
1416                              gpointer user_data)
1417 {
1418         GParamSpec **property_specs;
1419         guint n_property_specs;
1420         int i;
1421         GType type;
1422
1423         g_return_if_fail (NM_IS_SETTING (setting));
1424         g_return_if_fail (func != NULL);
1425
1426         property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs);
1427
1428         /* sort the properties. This has an effect on the order in which keyfile
1429          * prints them. */
1430         type = G_OBJECT_TYPE (setting);
1431         g_qsort_with_data (property_specs, n_property_specs, sizeof (gpointer),
1432                            (GCompareDataFunc) _enumerate_values_sort, &type);
1433
1434         for (i = 0; i < n_property_specs; i++) {
1435                 GParamSpec *prop_spec = property_specs[i];
1436                 GValue value = G_VALUE_INIT;
1437
1438                 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (prop_spec));
1439                 g_object_get_property (G_OBJECT (setting), prop_spec->name, &value);
1440                 func (setting, prop_spec->name, &value, prop_spec->flags, user_data);
1441                 g_value_unset (&value);
1442         }
1443
1444         g_free (property_specs);
1445 }
1446
1447 /**
1448  * _nm_setting_clear_secrets:
1449  * @setting: the #NMSetting
1450  *
1451  * Resets and clears any secrets in the setting.  Secrets should be added to the
1452  * setting only when needed, and cleared immediately after use to prevent
1453  * leakage of information.
1454  *
1455  * Returns: %TRUE if the setting changed at all
1456  **/
1457 gboolean
1458 _nm_setting_clear_secrets (NMSetting *setting)
1459 {
1460         GParamSpec **property_specs;
1461         guint n_property_specs;
1462         guint i;
1463         gboolean changed = FALSE;
1464
1465         g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
1466
1467         property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs);
1468
1469         for (i = 0; i < n_property_specs; i++) {
1470                 GParamSpec *prop_spec = property_specs[i];
1471
1472                 if (prop_spec->flags & NM_SETTING_PARAM_SECRET) {
1473                         GValue value = G_VALUE_INIT;
1474
1475                         g_value_init (&value, prop_spec->value_type);
1476                         g_object_get_property (G_OBJECT (setting), prop_spec->name, &value);
1477                         if (!g_param_value_defaults (prop_spec, &value)) {
1478                                 g_param_value_set_default (prop_spec, &value);
1479                                 g_object_set_property (G_OBJECT (setting), prop_spec->name, &value);
1480                                 changed = TRUE;
1481                         }
1482                         g_value_unset (&value);
1483                 }
1484         }
1485
1486         g_free (property_specs);
1487
1488         return changed;
1489 }
1490
1491 static gboolean
1492 clear_secrets_with_flags (NMSetting *setting,
1493                           GParamSpec *pspec,
1494                           NMSettingClearSecretsWithFlagsFn func,
1495                           gpointer user_data)
1496 {
1497         NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;
1498         gboolean changed = FALSE;
1499
1500         g_return_val_if_fail (!NM_IS_SETTING_VPN (setting), FALSE);
1501
1502         /* Clear the secret if the user function says to do so */
1503         if (!nm_setting_get_secret_flags (setting, pspec->name, &flags, NULL))
1504                 g_return_val_if_reached (FALSE);
1505
1506         if (func (setting, pspec->name, flags, user_data) == TRUE) {
1507                 GValue value = G_VALUE_INIT;
1508
1509                 g_value_init (&value, pspec->value_type);
1510                 g_object_get_property (G_OBJECT (setting), pspec->name, &value);
1511                 if (!g_param_value_defaults (pspec, &value)) {
1512                         g_param_value_set_default (pspec, &value);
1513                         g_object_set_property (G_OBJECT (setting), pspec->name, &value);
1514                         changed = TRUE;
1515                 }
1516                 g_value_unset (&value);
1517         }
1518
1519         return changed;
1520 }
1521
1522 /**
1523  * _nm_setting_clear_secrets_with_flags:
1524  * @setting: the #NMSetting
1525  * @func: (scope call): function to be called to determine whether a
1526  *     specific secret should be cleared or not
1527  * @user_data: caller-supplied data passed to @func
1528  *
1529  * Clears and frees secrets determined by @func.
1530  *
1531  * Returns: %TRUE if the setting changed at all
1532  **/
1533 gboolean
1534 _nm_setting_clear_secrets_with_flags (NMSetting *setting,
1535                                       NMSettingClearSecretsWithFlagsFn func,
1536                                       gpointer user_data)
1537 {
1538         GParamSpec **property_specs;
1539         guint n_property_specs;
1540         guint i;
1541         gboolean changed = FALSE;
1542
1543         g_return_val_if_fail (setting, FALSE);
1544         g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
1545         g_return_val_if_fail (func != NULL, FALSE);
1546
1547         property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs);
1548         for (i = 0; i < n_property_specs; i++) {
1549                 if (property_specs[i]->flags & NM_SETTING_PARAM_SECRET) {
1550                         changed |= NM_SETTING_GET_CLASS (setting)->clear_secrets_with_flags (setting,
1551                                                                                              property_specs[i],
1552                                                                                              func,
1553                                                                                              user_data);
1554                 }
1555         }
1556
1557         g_free (property_specs);
1558         return changed;
1559 }
1560
1561 /**
1562  * _nm_setting_need_secrets:
1563  * @setting: the #NMSetting
1564  *
1565  * Returns an array of property names for each secret which may be required
1566  * to make a successful connection.  The returned hints are only intended as a
1567  * guide to what secrets may be required, because in some circumstances, there
1568  * is no way to conclusively determine exactly which secrets are needed.
1569  *
1570  * Returns: (transfer container) (element-type utf8): a #GPtrArray containing
1571  * the property names of secrets of the #NMSetting which may be required; the
1572  * caller owns the array and must free it with g_ptr_array_free(), but must not
1573  * free the elements.
1574  **/
1575 GPtrArray *
1576 _nm_setting_need_secrets (NMSetting *setting)
1577 {
1578         GPtrArray *secrets = NULL;
1579
1580         g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
1581
1582         if (NM_SETTING_GET_CLASS (setting)->need_secrets)
1583                 secrets = NM_SETTING_GET_CLASS (setting)->need_secrets (setting);
1584
1585         return secrets;
1586 }
1587
1588 static int
1589 update_one_secret (NMSetting *setting, const char *key, GVariant *value, GError **error)
1590 {
1591         const NMSettingProperty *property;
1592         GParamSpec *prop_spec;
1593         GValue prop_value = { 0, };
1594
1595         property = nm_setting_class_find_property (NM_SETTING_GET_CLASS (setting), key);
1596         if (!property) {
1597                 g_set_error_literal (error,
1598                                      NM_CONNECTION_ERROR,
1599                                      NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND,
1600                                      _("secret not found"));
1601                 g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), key);
1602                 return NM_SETTING_UPDATE_SECRET_ERROR;
1603         }
1604
1605         /* Silently ignore non-secrets */
1606         prop_spec = property->param_spec;
1607         if (!prop_spec || !(prop_spec->flags & NM_SETTING_PARAM_SECRET))
1608                 return NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED;
1609
1610         if (   g_variant_is_of_type (value, G_VARIANT_TYPE_STRING)
1611             && G_IS_PARAM_SPEC_STRING (prop_spec)) {
1612                 /* String is expected to be a common case. Handle it specially and check
1613                  * whether the value is already set. Otherwise, we just reset the
1614                  * property and assume the value got modified.
1615                  */
1616                 char *v;
1617
1618                 g_object_get (G_OBJECT (setting), prop_spec->name, &v, NULL);
1619                 if (g_strcmp0 (v, g_variant_get_string (value, NULL)) == 0) {
1620                         g_free (v);
1621                         return NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED;
1622                 }
1623                 g_free (v);
1624         }
1625
1626         g_value_init (&prop_value, prop_spec->value_type);
1627         set_property_from_dbus (property, value, &prop_value);
1628         g_object_set_property (G_OBJECT (setting), prop_spec->name, &prop_value);
1629         g_value_unset (&prop_value);
1630
1631         return NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED;
1632 }
1633
1634 /**
1635  * _nm_setting_update_secrets:
1636  * @setting: the #NMSetting
1637  * @secrets: a #GVariant of type #NM_VARIANT_TYPE_SETTING, mapping property
1638  *   names to secrets.
1639  * @error: location to store error, or %NULL
1640  *
1641  * Update the setting's secrets, given a dictionary of secrets intended for that
1642  * setting (deserialized from D-Bus for example).
1643  *
1644  * Returns: an #NMSettingUpdateSecretResult
1645  **/
1646 NMSettingUpdateSecretResult
1647 _nm_setting_update_secrets (NMSetting *setting, GVariant *secrets, GError **error)
1648 {
1649         GVariantIter iter;
1650         const char *secret_key;
1651         GVariant *secret_value;
1652         GError *tmp_error = NULL;
1653         NMSettingUpdateSecretResult result = NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED;
1654
1655         g_return_val_if_fail (NM_IS_SETTING (setting), NM_SETTING_UPDATE_SECRET_ERROR);
1656         g_return_val_if_fail (g_variant_is_of_type (secrets, NM_VARIANT_TYPE_SETTING), NM_SETTING_UPDATE_SECRET_ERROR);
1657         if (error)
1658                 g_return_val_if_fail (*error == NULL, NM_SETTING_UPDATE_SECRET_ERROR);
1659
1660         g_variant_iter_init (&iter, secrets);
1661         while (g_variant_iter_next (&iter, "{&sv}", &secret_key, &secret_value)) {
1662                 int success;
1663
1664                 success = NM_SETTING_GET_CLASS (setting)->update_one_secret (setting, secret_key, secret_value, &tmp_error);
1665                 g_assert (!((success == NM_SETTING_UPDATE_SECRET_ERROR) ^ (!!tmp_error)));
1666
1667                 g_variant_unref (secret_value);
1668
1669                 if (success == NM_SETTING_UPDATE_SECRET_ERROR) {
1670                         g_propagate_error (error, tmp_error);
1671                         return NM_SETTING_UPDATE_SECRET_ERROR;
1672                 }
1673
1674                 if (success == NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED)
1675                         result = NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED;
1676         }
1677
1678         return result;
1679 }
1680
1681 static gboolean
1682 is_secret_prop (NMSetting *setting, const char *secret_name, GError **error)
1683 {
1684         const NMSettingProperty *property;
1685         GParamSpec *pspec;
1686
1687         property = nm_setting_class_find_property (NM_SETTING_GET_CLASS (setting), secret_name);
1688         if (!property) {
1689                 g_set_error_literal (error,
1690                                      NM_CONNECTION_ERROR,
1691                                      NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND,
1692                                      _("secret is not set"));
1693                 g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), secret_name);
1694                 return FALSE;
1695         }
1696
1697         pspec = property->param_spec;
1698         if (!pspec || !(pspec->flags & NM_SETTING_PARAM_SECRET)) {
1699                 g_set_error_literal (error,
1700                                      NM_CONNECTION_ERROR,
1701                                      NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET,
1702                                      _("not a secret property"));
1703                 g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), secret_name);
1704                 return FALSE;
1705         }
1706
1707         return TRUE;
1708 }
1709
1710 static gboolean
1711 get_secret_flags (NMSetting *setting,
1712                   const char *secret_name,
1713                   gboolean verify_secret,
1714                   NMSettingSecretFlags *out_flags,
1715                   GError **error)
1716 {
1717         char *flags_prop;
1718         NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;
1719
1720         if (verify_secret && !is_secret_prop (setting, secret_name, error)) {
1721                 if (out_flags)
1722                         *out_flags = NM_SETTING_SECRET_FLAG_NONE;
1723                 return FALSE;
1724         }
1725
1726         flags_prop = g_strdup_printf ("%s-flags", secret_name);
1727         g_object_get (G_OBJECT (setting), flags_prop, &flags, NULL);
1728         g_free (flags_prop);
1729
1730         if (out_flags)
1731                 *out_flags = flags;
1732         return TRUE;
1733 }
1734
1735 /**
1736  * nm_setting_get_secret_flags:
1737  * @setting: the #NMSetting
1738  * @secret_name: the secret key name to get flags for
1739  * @out_flags: on success, the #NMSettingSecretFlags for the secret
1740  * @error: location to store error, or %NULL
1741  *
1742  * For a given secret, retrieves the #NMSettingSecretFlags describing how to
1743  * handle that secret.
1744  *
1745  * Returns: %TRUE on success (if the given secret name was a valid property of
1746  * this setting, and if that property is secret), %FALSE if not
1747  **/
1748 gboolean
1749 nm_setting_get_secret_flags (NMSetting *setting,
1750                              const char *secret_name,
1751                              NMSettingSecretFlags *out_flags,
1752                              GError **error)
1753 {
1754         g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
1755         g_return_val_if_fail (secret_name != NULL, FALSE);
1756
1757         return NM_SETTING_GET_CLASS (setting)->get_secret_flags (setting, secret_name, TRUE, out_flags, error);
1758 }
1759
1760 static gboolean
1761 set_secret_flags (NMSetting *setting,
1762                   const char *secret_name,
1763                   gboolean verify_secret,
1764                   NMSettingSecretFlags flags,
1765                   GError **error)
1766 {
1767         char *flags_prop;
1768
1769         if (verify_secret)
1770                 g_return_val_if_fail (is_secret_prop (setting, secret_name, error), FALSE);
1771
1772         flags_prop = g_strdup_printf ("%s-flags", secret_name);
1773         g_object_set (G_OBJECT (setting), flags_prop, flags, NULL);
1774         g_free (flags_prop);
1775         return TRUE;
1776 }
1777
1778 /**
1779  * nm_setting_set_secret_flags:
1780  * @setting: the #NMSetting
1781  * @secret_name: the secret key name to set flags for
1782  * @flags: the #NMSettingSecretFlags for the secret
1783  * @error: location to store error, or %NULL
1784  *
1785  * For a given secret, stores the #NMSettingSecretFlags describing how to
1786  * handle that secret.
1787  *
1788  * Returns: %TRUE on success (if the given secret name was a valid property of
1789  * this setting, and if that property is secret), %FALSE if not
1790  **/
1791 gboolean
1792 nm_setting_set_secret_flags (NMSetting *setting,
1793                              const char *secret_name,
1794                              NMSettingSecretFlags flags,
1795                              GError **error)
1796 {
1797         g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
1798         g_return_val_if_fail (secret_name != NULL, FALSE);
1799         g_return_val_if_fail (flags <= NM_SETTING_SECRET_FLAGS_ALL, FALSE);
1800
1801         return NM_SETTING_GET_CLASS (setting)->set_secret_flags (setting, secret_name, TRUE, flags, error);
1802 }
1803
1804 /**
1805  * nm_setting_to_string:
1806  * @setting: the #NMSetting
1807  *
1808  * Convert the setting into a string.  For debugging purposes ONLY, should NOT
1809  * be used for serialization of the setting, or machine-parsed in any way. The
1810  * output format is not guaranteed to be stable and may change at any time.
1811  *
1812  * Returns: an allocated string containing a textual representation of the
1813  * setting's properties and values (including secrets!), which the caller should
1814  * free with g_free()
1815  **/
1816 char *
1817 nm_setting_to_string (NMSetting *setting)
1818 {
1819         GString *string;
1820         GParamSpec **property_specs;
1821         guint n_property_specs;
1822         guint i;
1823
1824         g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
1825
1826         property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs);
1827
1828         string = g_string_new (nm_setting_get_name (setting));
1829         g_string_append_c (string, '\n');
1830
1831         for (i = 0; i < n_property_specs; i++) {
1832                 GParamSpec *prop_spec = property_specs[i];
1833                 GValue value = G_VALUE_INIT;
1834                 char *value_str;
1835                 gboolean is_default;
1836
1837                 if (strcmp (prop_spec->name, NM_SETTING_NAME) == 0)
1838                         continue;
1839
1840                 g_value_init (&value, prop_spec->value_type);
1841                 g_object_get_property (G_OBJECT (setting), prop_spec->name, &value);
1842
1843                 value_str = g_strdup_value_contents (&value);
1844                 g_string_append_printf (string, "\t%s : %s", prop_spec->name, value_str);
1845                 g_free (value_str);
1846
1847                 is_default = g_param_value_defaults (prop_spec, &value);
1848                 g_value_unset (&value);
1849
1850                 g_string_append (string, " (");
1851                 g_string_append_c (string, 's');
1852                 if (is_default)
1853                         g_string_append_c (string, 'd');
1854                 g_string_append_c (string, ')');
1855                 g_string_append_c (string, '\n');
1856         }
1857
1858         g_free (property_specs);
1859         g_string_append_c (string, '\n');
1860
1861         return g_string_free (string, FALSE);
1862 }
1863
1864 GVariant *
1865 _nm_setting_get_deprecated_virtual_interface_name (NMSetting *setting,
1866                                                    NMConnection *connection,
1867                                                    const char *property)
1868 {
1869         NMSettingConnection *s_con;
1870
1871         s_con = nm_connection_get_setting_connection (connection);
1872         g_return_val_if_fail (s_con != NULL, NULL);
1873
1874         if (nm_setting_connection_get_interface_name (s_con))
1875                 return g_variant_new_string (nm_setting_connection_get_interface_name (s_con));
1876         else
1877                 return NULL;
1878 }
1879
1880 /*****************************************************************************/
1881
1882 static void
1883 nm_setting_init (NMSetting *setting)
1884 {
1885 }
1886
1887 static void
1888 constructed (GObject *object)
1889 {
1890         _ensure_setting_info (object, NM_SETTING_GET_PRIVATE (object));
1891
1892         G_OBJECT_CLASS (nm_setting_parent_class)->constructed (object);
1893 }
1894
1895 static void
1896 get_property (GObject *object, guint prop_id,
1897               GValue *value, GParamSpec *pspec)
1898 {
1899         NMSetting *setting = NM_SETTING (object);
1900
1901         switch (prop_id) {
1902         case PROP_NAME:
1903                 g_value_set_string (value, nm_setting_get_name (setting));
1904                 break;
1905         default:
1906                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1907                 break;
1908         }
1909 }
1910
1911 static void
1912 nm_setting_class_init (NMSettingClass *setting_class)
1913 {
1914         GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
1915
1916         if (!setting_property_overrides_quark)
1917                 setting_property_overrides_quark = g_quark_from_static_string ("nm-setting-property-overrides");
1918         if (!setting_properties_quark)
1919                 setting_properties_quark = g_quark_from_static_string ("nm-setting-properties");
1920
1921         g_type_class_add_private (setting_class, sizeof (NMSettingPrivate));
1922
1923         /* virtual methods */
1924         object_class->constructed  = constructed;
1925         object_class->get_property = get_property;
1926
1927         setting_class->update_one_secret = update_one_secret;
1928         setting_class->get_secret_flags = get_secret_flags;
1929         setting_class->set_secret_flags = set_secret_flags;
1930         setting_class->compare_property = compare_property;
1931         setting_class->clear_secrets_with_flags = clear_secrets_with_flags;
1932
1933         /* Properties */
1934
1935         /**
1936          * NMSetting:name:
1937          *
1938          * The setting's name, which uniquely identifies the setting within the
1939          * connection.  Each setting type has a name unique to that type, for
1940          * example "ppp" or "wireless" or "wired".
1941          **/
1942         g_object_class_install_property
1943                 (object_class, PROP_NAME,
1944                  g_param_spec_string (NM_SETTING_NAME, "", "",
1945                                       NULL,
1946                                       G_PARAM_READABLE |
1947                                       G_PARAM_STATIC_STRINGS));
1948 }