libnm-util: don't print any warnings during nm_setting_new_from_hash()
[NetworkManager.git] / libnm-util / 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 <string.h>
26
27 #include "nm-setting.h"
28 #include "nm-setting-private.h"
29 #include "nm-setting-connection.h"
30 #include "nm-utils.h"
31 #include "nm-utils-private.h"
32
33 /**
34  * SECTION:nm-setting
35  * @short_description: Describes related configuration information
36  * @include: nm-setting.h
37  *
38  * Each #NMSetting contains properties that describe configuration that applies
39  * to a specific network layer (like IPv4 or IPv6 configuration) or device type
40  * (like Ethernet, or Wi-Fi).  A collection of individual settings together
41  * make up an #NMConnection. Each property is strongly typed and usually has
42  * a number of allowed values.  See each #NMSetting subclass for a description
43  * of properties and allowed values.
44  */
45
46 /**
47  * nm_setting_error_quark:
48  *
49  * Registers an error quark for #NMSetting if necessary.
50  *
51  * Returns: the error quark used for NMSetting errors.
52  **/
53 GQuark
54 nm_setting_error_quark (void)
55 {
56         static GQuark quark;
57
58         if (G_UNLIKELY (!quark))
59                 quark = g_quark_from_static_string ("nm-setting-error-quark");
60         return quark;
61 }
62
63 G_DEFINE_ABSTRACT_TYPE (NMSetting, nm_setting, G_TYPE_OBJECT)
64
65 #define NM_SETTING_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING, NMSettingPrivate))
66
67 typedef struct {
68         const char *name;
69         GType type;
70         guint32 priority;
71         GQuark error_quark;
72 } SettingInfo;
73
74 typedef struct {
75         const SettingInfo *info;
76 } NMSettingPrivate;
77
78 enum {
79         PROP_0,
80         PROP_NAME,
81
82         PROP_LAST
83 };
84
85 /*************************************************************/
86
87 static GHashTable *registered_settings = NULL;
88 static GHashTable *registered_settings_by_type = NULL;
89
90 static gboolean
91 _nm_gtype_equal (gconstpointer v1, gconstpointer v2)
92 {
93         return *((const GType *) v1) == *((const GType *) v2);
94 }
95 static guint
96 _nm_gtype_hash (gconstpointer v)
97 {
98         return *((const GType *) v);
99 }
100
101 static void
102 _ensure_registered (void)
103 {
104         if (G_UNLIKELY (registered_settings == NULL)) {
105                 nm_g_type_init ();
106                 _nm_value_transforms_register ();
107                 registered_settings = g_hash_table_new (g_str_hash, g_str_equal);
108                 registered_settings_by_type = g_hash_table_new (_nm_gtype_hash, _nm_gtype_equal);
109         }
110 }
111
112 static void __attribute__((constructor))
113 _ensure_registered_constructor (void)
114 {
115         _ensure_registered ();
116 }
117
118 #define _ensure_setting_info(self, priv) \
119         G_STMT_START { \
120                 NMSettingPrivate *_priv_esi = (priv); \
121                 if (G_UNLIKELY (!_priv_esi->info)) { \
122                         _priv_esi->info = _nm_setting_lookup_setting_by_type (G_OBJECT_TYPE (self)); \
123                         g_assert (_priv_esi->info); \
124                 } \
125         } G_STMT_END
126
127 /*************************************************************/
128
129 /*
130  * _nm_register_setting:
131  * @name: the name of the #NMSetting object to register
132  * @type: the #GType of the #NMSetting
133  * @priority: the sort priority of the setting, see below
134  * @error_quark: the setting's error quark
135  *
136  * INTERNAL ONLY: registers a setting's internal properties, like its priority
137  * and its error quark type, with libnm-util.
138  *
139  * A setting's priority should roughly follow the OSI layer model, but it also
140  * controls which settings get asked for secrets first.  Thus settings which
141  * relate to things that must be working first, like hardware, should get a
142  * higher priority than things which layer on top of the hardware.  For example,
143  * the GSM/CDMA settings should provide secrets before the PPP setting does,
144  * because a PIN is required to unlock the device before PPP can even start.
145  * Even settings without secrets should be assigned the right priority.
146  *
147  * 0: reserved for the Connection setting
148  *
149  * 1: hardware-related settings like Ethernet, Wi-Fi, InfiniBand, Bridge, etc.
150  * These priority 1 settings are also "base types", which means that at least
151  * one of them is required for the connection to be valid, and their name is
152  * valid in the 'type' property of the Connection setting.
153  *
154  * 2: hardware-related auxiliary settings that require a base setting to be
155  * successful first, like Wi-Fi security, 802.1x, etc.
156  *
157  * 3: hardware-independent settings that are required before IP connectivity
158  * can be established, like PPP, PPPoE, etc.
159  *
160  * 4: IP-level stuff
161  */
162 void
163 (_nm_register_setting) (const char *name,
164                         const GType type,
165                         const guint32 priority,
166                         const GQuark error_quark)
167 {
168         SettingInfo *info;
169
170         g_return_if_fail (name != NULL && *name);
171         g_return_if_fail (type != G_TYPE_INVALID);
172         g_return_if_fail (type != G_TYPE_NONE);
173         g_return_if_fail (error_quark != 0);
174         g_return_if_fail (priority <= 4);
175
176         _ensure_registered ();
177
178         if (G_LIKELY ((info = g_hash_table_lookup (registered_settings, name)))) {
179                 g_return_if_fail (info->type == type);
180                 g_return_if_fail (info->error_quark == error_quark);
181                 g_return_if_fail (info->priority == priority);
182                 g_return_if_fail (g_strcmp0 (info->name, name) == 0);
183                 return;
184         }
185         g_return_if_fail (g_hash_table_lookup (registered_settings_by_type, &type) == NULL);
186
187         if (priority == 0)
188                 g_assert_cmpstr (name, ==, NM_SETTING_CONNECTION_SETTING_NAME);
189
190         info = g_slice_new0 (SettingInfo);
191         info->type = type;
192         info->priority = priority;
193         info->error_quark = error_quark;
194         info->name = name;
195         g_hash_table_insert (registered_settings, (void *) info->name, info);
196         g_hash_table_insert (registered_settings_by_type, &info->type, info);
197 }
198
199 static const SettingInfo *
200 _nm_setting_lookup_setting_by_type (GType type)
201 {
202         _ensure_registered ();
203         return g_hash_table_lookup (registered_settings_by_type, &type);
204 }
205
206 static guint32
207 _get_setting_type_priority (GType type)
208 {
209         const SettingInfo *info;
210
211         g_return_val_if_fail (g_type_is_a (type, NM_TYPE_SETTING), G_MAXUINT32);
212
213         info = _nm_setting_lookup_setting_by_type (type);
214         return info->priority;
215 }
216
217 guint32
218 _nm_setting_get_setting_priority (NMSetting *setting)
219 {
220         NMSettingPrivate *priv;
221
222         g_return_val_if_fail (NM_IS_SETTING (setting), G_MAXUINT32);
223         priv = NM_SETTING_GET_PRIVATE (setting);
224         _ensure_setting_info (setting, priv);
225         return priv->info->priority;
226 }
227
228 gboolean
229 _nm_setting_type_is_base_type (GType type)
230 {
231         /* Historical oddity: PPPoE is a base-type even though it's not
232          * priority 1.  It needs to be sorted *after* lower-level stuff like
233          * Wi-Fi security or 802.1x for secrets, but it's still allowed as a
234          * base type.
235          */
236         return _get_setting_type_priority (type) == 1 || (type == NM_TYPE_SETTING_PPPOE);
237 }
238
239 gboolean
240 _nm_setting_is_base_type (NMSetting *setting)
241 {
242         return _nm_setting_type_is_base_type (G_OBJECT_TYPE (setting));
243 }
244
245 GType
246 _nm_setting_lookup_setting_type (const char *name)
247 {
248         SettingInfo *info;
249
250         g_return_val_if_fail (name != NULL, G_TYPE_NONE);
251
252         _ensure_registered ();
253
254         info = g_hash_table_lookup (registered_settings, name);
255         return info ? info->type : G_TYPE_INVALID;
256 }
257
258 GType
259 _nm_setting_lookup_setting_type_by_quark (GQuark error_quark)
260 {
261         SettingInfo *info;
262         GHashTableIter iter;
263
264         _ensure_registered ();
265
266         g_hash_table_iter_init (&iter, registered_settings);
267         while (g_hash_table_iter_next (&iter, NULL, (gpointer) &info)) {
268                 if (info->error_quark == error_quark)
269                         return info->type;
270         }
271         return G_TYPE_INVALID;
272 }
273
274 gint
275 _nm_setting_compare_priority (gconstpointer a, gconstpointer b)
276 {
277         guint32 prio_a, prio_b;
278
279         prio_a = _nm_setting_get_setting_priority ((NMSetting *) a);
280         prio_b = _nm_setting_get_setting_priority ((NMSetting *) b);
281
282         if (prio_a < prio_b)
283                 return -1;
284         else if (prio_a == prio_b)
285                 return 0;
286         return 1;
287 }
288
289 /*************************************************************/
290
291 static void
292 destroy_gvalue (gpointer data)
293 {
294         GValue *value = (GValue *) data;
295
296         g_value_unset (value);
297         g_slice_free (GValue, value);
298 }
299
300 /**
301  * nm_setting_to_hash:
302  * @setting: the #NMSetting
303  * @flags: hash flags, e.g. %NM_SETTING_HASH_FLAG_ALL
304  *
305  * Converts the #NMSetting into a #GHashTable mapping each setting property
306  * name to a GValue describing that property, suitable for marshalling over
307  * D-Bus or serializing.  The mapping is string to GValue.
308  *
309  * Returns: (transfer full) (element-type utf8 GObject.Value): a new #GHashTable
310  * describing the setting's properties
311  **/
312 GHashTable *
313 nm_setting_to_hash (NMSetting *setting, NMSettingHashFlags flags)
314 {
315         GHashTable *hash;
316         GParamSpec **property_specs;
317         guint n_property_specs;
318         guint i;
319
320         g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
321
322         property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs);
323
324         hash = g_hash_table_new_full (g_str_hash, g_str_equal,
325                                       (GDestroyNotify) g_free, destroy_gvalue);
326
327         for (i = 0; i < n_property_specs; i++) {
328                 GParamSpec *prop_spec = property_specs[i];
329                 GValue *value;
330
331                 /* 'name' doesn't get serialized */
332                 if (strcmp (g_param_spec_get_name (prop_spec), NM_SETTING_NAME) == 0)
333                         continue;
334
335                 if (   (flags & NM_SETTING_HASH_FLAG_NO_SECRETS)
336                     && (prop_spec->flags & NM_SETTING_PARAM_SECRET))
337                         continue;
338
339                 if (   (flags & NM_SETTING_HASH_FLAG_ONLY_SECRETS)
340                     && !(prop_spec->flags & NM_SETTING_PARAM_SECRET))
341                         continue;
342
343                 value = g_slice_new0 (GValue);
344                 g_value_init (value, prop_spec->value_type);
345                 g_object_get_property (G_OBJECT (setting), prop_spec->name, value);
346
347                 /* Don't serialize values with default values */
348                 if (!g_param_value_defaults (prop_spec, value))
349                         g_hash_table_insert (hash, g_strdup (prop_spec->name), value);
350                 else
351                         destroy_gvalue (value);
352         }
353         g_free (property_specs);
354
355         return hash;
356 }
357
358 /**
359  * nm_setting_new_from_hash:
360  * @setting_type: the #NMSetting type which the hash contains properties for
361  * @hash: (element-type utf8 GObject.Value): the #GHashTable containing a
362  * string to GValue mapping of properties that apply to the setting
363  *
364  * Creates a new #NMSetting object and populates that object with the properties
365  * contained in the hash table, using each hash key as the property to set,
366  * and each hash value as the value to set that property to.  Setting properties
367  * are strongly typed, thus the GValue type of the hash value must be correct.
368  * See the documentation on each #NMSetting object subclass for the correct
369  * property names and value types.
370  *
371  * Returns: a new #NMSetting object populated with the properties from the
372  * hash table, or %NULL on failure
373  **/
374 NMSetting *
375 nm_setting_new_from_hash (GType setting_type, GHashTable *hash)
376 {
377         GHashTableIter iter;
378         NMSetting *setting;
379         const char *prop_name;
380         GValue *src_value;
381         GObjectClass *class;
382
383         g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (setting_type), NULL);
384         g_return_val_if_fail (hash != NULL, NULL);
385
386         /* g_type_class_ref() ensures the setting class is created if it hasn't
387          * already been used.
388          */
389         class = g_type_class_ref (setting_type);
390
391         setting = (NMSetting *) g_object_new (setting_type, NULL);
392
393         g_hash_table_iter_init (&iter, hash);
394         while (g_hash_table_iter_next (&iter, (gpointer) &prop_name, (gpointer) &src_value)) {
395                 GParamSpec *param_spec;
396
397                 param_spec = g_object_class_find_property (class, prop_name);
398                 if (!param_spec) {
399                         /* Assume that any unrecognized property either can be ignored, or
400                          * else has a backward-compatibility equivalent.
401                          */
402                         continue;
403                 }
404
405                 nm_g_object_set_property ((GObject *) setting, prop_name, src_value, NULL);
406         }
407
408         g_type_class_unref (class);
409
410         return setting;
411 }
412
413 gboolean
414 _nm_setting_get_property (NMSetting *setting, const char *property_name, GValue *value)
415 {
416         GParamSpec *prop_spec;
417
418         g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
419         g_return_val_if_fail (property_name, FALSE);
420         g_return_val_if_fail (value, FALSE);
421
422         prop_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), property_name);
423
424         if (!prop_spec) {
425                 g_value_unset (value);
426                 return FALSE;
427         }
428
429         g_value_init (value, prop_spec->value_type);
430         g_object_get_property (G_OBJECT (setting), property_name, value);
431         return TRUE;
432 }
433
434 static void
435 duplicate_setting (NMSetting *setting,
436                    const char *name,
437                    const GValue *value,
438                    GParamFlags flags,
439                    gpointer user_data)
440 {
441         if ((flags & (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)) == G_PARAM_WRITABLE)
442                 g_object_set_property (G_OBJECT (user_data), name, value);
443 }
444
445 /**
446  * nm_setting_duplicate:
447  * @setting: the #NMSetting to duplicate
448  *
449  * Duplicates a #NMSetting.
450  *
451  * Returns: (transfer full): a new #NMSetting containing the same properties and values as the
452  * source #NMSetting
453  **/
454 NMSetting *
455 nm_setting_duplicate (NMSetting *setting)
456 {
457         GObject *dup;
458
459         g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
460
461         dup = g_object_new (G_OBJECT_TYPE (setting), NULL);
462
463         g_object_freeze_notify (dup);
464         nm_setting_enumerate_values (setting, duplicate_setting, dup);
465         g_object_thaw_notify (dup);
466
467         return NM_SETTING (dup);
468 }
469
470 static gint
471 find_setting_by_name (gconstpointer a, gconstpointer b)
472 {
473         NMSetting *setting = NM_SETTING (a);
474         const char *str = (const char *) b;
475
476         return strcmp (nm_setting_get_name (setting), str);
477 }
478
479 NMSetting *
480 nm_setting_find_in_list (GSList     *settings_list,
481                          const char *setting_name)
482 {
483         GSList *found;
484
485         found = g_slist_find_custom (settings_list, setting_name, find_setting_by_name);
486         if (found)
487                 return found->data;
488         else
489                 return NULL;
490 }
491
492 /**
493  * nm_setting_get_name:
494  * @setting: the #NMSetting
495  *
496  * Returns the type name of the #NMSetting object
497  *
498  * Returns: a string containing the type name of the #NMSetting object,
499  * like 'ppp' or 'wireless' or 'wired'.
500  **/
501 const char *
502 nm_setting_get_name (NMSetting *setting)
503 {
504         NMSettingPrivate *priv;
505
506         g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
507         priv = NM_SETTING_GET_PRIVATE (setting);
508         _ensure_setting_info (setting, priv);
509         return priv->info->name;
510 }
511
512 /**
513  * nm_setting_verify:
514  * @setting: the #NMSetting to verify
515  * @all_settings: (element-type NMSetting): a #GSList of all settings
516  *     in the connection from which @setting came
517  * @error: location to store error, or %NULL
518  *
519  * Validates the setting.  Each setting's properties have allowed values, and
520  * some are dependent on other values (hence the need for @all_settings).  The
521  * returned #GError contains information about which property of the setting
522  * failed validation, and in what way that property failed validation.
523  *
524  * Returns: %TRUE if the setting is valid, %FALSE if it is not
525  **/
526 gboolean
527 nm_setting_verify (NMSetting *setting, GSList *all_settings, GError **error)
528 {
529         NMSettingVerifyResult result = _nm_setting_verify (setting, all_settings, error);
530
531         if (result == NM_SETTING_VERIFY_NORMALIZABLE)
532                 g_clear_error (error);
533
534         return result == NM_SETTING_VERIFY_SUCCESS || result == NM_SETTING_VERIFY_NORMALIZABLE;
535 }
536
537 NMSettingVerifyResult
538 _nm_setting_verify (NMSetting *setting, GSList *all_settings, GError **error)
539 {
540         g_return_val_if_fail (NM_IS_SETTING (setting), NM_SETTING_VERIFY_ERROR);
541         g_return_val_if_fail (!error || *error == NULL, NM_SETTING_VERIFY_ERROR);
542
543         if (NM_SETTING_GET_CLASS (setting)->verify)
544                 return NM_SETTING_GET_CLASS (setting)->verify (setting, all_settings, error);
545
546         return NM_SETTING_VERIFY_SUCCESS;
547 }
548
549 static gboolean
550 compare_property (NMSetting *setting,
551                   NMSetting *other,
552                   const GParamSpec *prop_spec,
553                   NMSettingCompareFlags flags)
554 {
555         GValue value1 = G_VALUE_INIT;
556         GValue value2 = G_VALUE_INIT;
557         gboolean different;
558
559         /* Handle compare flags */
560         if (prop_spec->flags & NM_SETTING_PARAM_SECRET) {
561                 NMSettingSecretFlags a_secret_flags = NM_SETTING_SECRET_FLAG_NONE;
562                 NMSettingSecretFlags b_secret_flags = NM_SETTING_SECRET_FLAG_NONE;
563
564                 g_return_val_if_fail (!NM_IS_SETTING_VPN (setting), FALSE);
565
566                 if (!nm_setting_get_secret_flags (setting, prop_spec->name, &a_secret_flags, NULL))
567                         g_return_val_if_reached (FALSE);
568                 if (!nm_setting_get_secret_flags (other, prop_spec->name, &b_secret_flags, NULL))
569                         g_return_val_if_reached (FALSE);
570
571                 /* If the secret flags aren't the same the settings aren't the same */
572                 if (a_secret_flags != b_secret_flags)
573                         return FALSE;
574
575                 /* Check for various secret flags that might cause us to ignore comparing
576                  * this property.
577                  */
578                 if (   (flags & NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS)
579                     && (a_secret_flags & NM_SETTING_SECRET_FLAG_AGENT_OWNED))
580                         return TRUE;
581
582                 if (   (flags & NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)
583                     && (a_secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED))
584                         return TRUE;
585         }
586
587         g_value_init (&value1, prop_spec->value_type);
588         g_object_get_property (G_OBJECT (setting), prop_spec->name, &value1);
589
590         g_value_init (&value2, prop_spec->value_type);
591         g_object_get_property (G_OBJECT (other), prop_spec->name, &value2);
592
593         different = g_param_values_cmp ((GParamSpec *) prop_spec, &value1, &value2);
594
595         g_value_unset (&value1);
596         g_value_unset (&value2);
597
598         return different == 0 ? TRUE : FALSE;
599 }
600
601 /**
602  * nm_setting_compare:
603  * @a: a #NMSetting
604  * @b: a second #NMSetting to compare with the first
605  * @flags: compare flags, e.g. %NM_SETTING_COMPARE_FLAG_EXACT
606  *
607  * Compares two #NMSetting objects for similarity, with comparison behavior
608  * modified by a set of flags.  See the documentation for #NMSettingCompareFlags
609  * for a description of each flag's behavior.
610  *
611  * Returns: %TRUE if the comparison succeeds, %FALSE if it does not
612  **/
613 gboolean
614 nm_setting_compare (NMSetting *a,
615                     NMSetting *b,
616                     NMSettingCompareFlags flags)
617 {
618         GParamSpec **property_specs;
619         guint n_property_specs;
620         gint same = TRUE;
621         guint i;
622
623         g_return_val_if_fail (NM_IS_SETTING (a), FALSE);
624         g_return_val_if_fail (NM_IS_SETTING (b), FALSE);
625
626         /* First check that both have the same type */
627         if (G_OBJECT_TYPE (a) != G_OBJECT_TYPE (b))
628                 return FALSE;
629
630         /* And now all properties */
631         property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (a), &n_property_specs);
632         for (i = 0; i < n_property_specs && same; i++) {
633                 GParamSpec *prop_spec = property_specs[i];
634
635                 /* Fuzzy compare ignores secrets and properties defined with the FUZZY_IGNORE flag */
636                 if (   (flags & NM_SETTING_COMPARE_FLAG_FUZZY)
637                     && (prop_spec->flags & (NM_SETTING_PARAM_FUZZY_IGNORE | NM_SETTING_PARAM_SECRET)))
638                         continue;
639
640                 if ((flags & NM_SETTING_COMPARE_FLAG_INFERRABLE) && !(prop_spec->flags & NM_SETTING_PARAM_INFERRABLE))
641                         continue;
642
643                 if (   (flags & NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS)
644                     && (prop_spec->flags & NM_SETTING_PARAM_SECRET))
645                         continue;
646
647                 same = NM_SETTING_GET_CLASS (a)->compare_property (a, b, prop_spec, flags);
648         }
649         g_free (property_specs);
650
651         return same;
652 }
653
654 static inline gboolean
655 should_compare_prop (NMSetting *setting,
656                      const char *prop_name,
657                      NMSettingCompareFlags comp_flags,
658                      GParamFlags prop_flags)
659 {
660         /* Fuzzy compare ignores secrets and properties defined with the FUZZY_IGNORE flag */
661         if (   (comp_flags & NM_SETTING_COMPARE_FLAG_FUZZY)
662             && (prop_flags & (NM_SETTING_PARAM_FUZZY_IGNORE | NM_SETTING_PARAM_SECRET)))
663                 return FALSE;
664
665         if ((comp_flags & NM_SETTING_COMPARE_FLAG_INFERRABLE) && !(prop_flags & NM_SETTING_PARAM_INFERRABLE))
666                 return FALSE;
667
668         if (prop_flags & NM_SETTING_PARAM_SECRET) {
669                 NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
670
671                 if (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS)
672                         return FALSE;
673
674                 if (   NM_IS_SETTING_VPN (setting)
675                     && g_strcmp0 (prop_name, NM_SETTING_VPN_SECRETS) == 0) {
676                         /* FIXME: NMSettingVPN:NM_SETTING_VPN_SECRETS has NM_SETTING_PARAM_SECRET.
677                          * nm_setting_get_secret_flags() quite possibly fails, but it might succeed if the
678                          * setting accidently uses a key "secrets". */
679                         return FALSE;
680                 }
681
682                 if (!nm_setting_get_secret_flags (setting, prop_name, &secret_flags, NULL))
683                         g_return_val_if_reached (FALSE);
684
685                 if (   (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS)
686                     && (secret_flags & NM_SETTING_SECRET_FLAG_AGENT_OWNED))
687                         return FALSE;
688
689                 if (   (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)
690                     && (secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED))
691                         return FALSE;
692         }
693
694         if (   (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_ID)
695             && NM_IS_SETTING_CONNECTION (setting)
696             && !strcmp (prop_name, NM_SETTING_CONNECTION_ID))
697                 return FALSE;
698
699         return TRUE;
700 }
701
702 /**
703  * nm_setting_diff:
704  * @a: a #NMSetting
705  * @b: a second #NMSetting to compare with the first
706  * @flags: compare flags, e.g. %NM_SETTING_COMPARE_FLAG_EXACT
707  * @invert_results: this parameter is used internally by libnm-util and should
708  * be set to %FALSE.  If %TRUE inverts the meaning of the #NMSettingDiffResult.
709  * @results: (inout) (transfer full) (element-type utf8 guint32): if the
710  * settings differ, on return a hash table mapping the differing keys to one or
711  * more %NMSettingDiffResult values OR-ed together.  If the settings do not
712  * differ, any hash table passed in is unmodified.  If no hash table is passed
713  * in and the settings differ, a new one is created and returned.
714  *
715  * Compares two #NMSetting objects for similarity, with comparison behavior
716  * modified by a set of flags.  See the documentation for #NMSettingCompareFlags
717  * for a description of each flag's behavior.  If the settings differ, the keys
718  * of each setting that differ from the other are added to @results, mapped to
719  * one or more #NMSettingDiffResult values.
720  *
721  * Returns: %TRUE if the settings contain the same values, %FALSE if they do not
722  **/
723 gboolean
724 nm_setting_diff (NMSetting *a,
725                  NMSetting *b,
726                  NMSettingCompareFlags flags,
727                  gboolean invert_results,
728                  GHashTable **results)
729 {
730         GParamSpec **property_specs;
731         guint n_property_specs;
732         guint i;
733         NMSettingDiffResult a_result = NM_SETTING_DIFF_RESULT_IN_A;
734         NMSettingDiffResult b_result = NM_SETTING_DIFF_RESULT_IN_B;
735         NMSettingDiffResult a_result_default = NM_SETTING_DIFF_RESULT_IN_A_DEFAULT;
736         NMSettingDiffResult b_result_default = NM_SETTING_DIFF_RESULT_IN_B_DEFAULT;
737         gboolean results_created = FALSE;
738
739         g_return_val_if_fail (results != NULL, FALSE);
740         g_return_val_if_fail (NM_IS_SETTING (a), FALSE);
741         if (b) {
742                 g_return_val_if_fail (NM_IS_SETTING (b), FALSE);
743                 g_return_val_if_fail (G_OBJECT_TYPE (a) == G_OBJECT_TYPE (b), FALSE);
744         }
745
746         if ((flags & (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) ==
747                      (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) {
748                 /* conflicting flags: default to WITH_DEFAULT (clearing NO_DEFAULT). */
749                 flags &= ~NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT;
750         }
751
752         /* If the caller is calling this function in a pattern like this to get
753          * complete diffs:
754          *
755          * nm_setting_diff (A, B, FALSE, &results);
756          * nm_setting_diff (B, A, TRUE, &results);
757          *
758          * and wants us to invert the results so that the second invocation comes
759          * out correctly, do that here.
760          */
761         if (invert_results) {
762                 a_result = NM_SETTING_DIFF_RESULT_IN_B;
763                 b_result = NM_SETTING_DIFF_RESULT_IN_A;
764                 a_result_default = NM_SETTING_DIFF_RESULT_IN_B_DEFAULT;
765                 b_result_default = NM_SETTING_DIFF_RESULT_IN_A_DEFAULT;
766         }
767
768         if (*results == NULL) {
769                 *results = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
770                 results_created = TRUE;
771         }
772
773         /* And now all properties */
774         property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (a), &n_property_specs);
775
776         for (i = 0; i < n_property_specs; i++) {
777                 GParamSpec *prop_spec = property_specs[i];
778                 NMSettingDiffResult r = NM_SETTING_DIFF_RESULT_UNKNOWN;
779
780                 /* Handle compare flags */
781                 if (!should_compare_prop (a, prop_spec->name, flags, prop_spec->flags))
782                         continue;
783                 if (strcmp (prop_spec->name, NM_SETTING_NAME) == 0)
784                         continue;
785
786                 if (b) {
787                         gboolean different;
788
789                         different = !NM_SETTING_GET_CLASS (a)->compare_property (a, b, prop_spec, flags);
790                         if (different) {
791                                 gboolean a_is_default, b_is_default;
792                                 GValue value = G_VALUE_INIT;
793
794                                 g_value_init (&value, prop_spec->value_type);
795                                 g_object_get_property (G_OBJECT (a), prop_spec->name, &value);
796                                 a_is_default = g_param_value_defaults (prop_spec, &value);
797
798                                 g_value_reset (&value);
799                                 g_object_get_property (G_OBJECT (b), prop_spec->name, &value);
800                                 b_is_default = g_param_value_defaults (prop_spec, &value);
801
802                                 g_value_unset (&value);
803                                 if ((flags & NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT) == 0) {
804                                         if (!a_is_default)
805                                                 r |= a_result;
806                                         if (!b_is_default)
807                                                 r |= b_result;
808                                 } else {
809                                         r |= a_result | b_result;
810                                         if (a_is_default)
811                                                 r |= a_result_default;
812                                         if (b_is_default)
813                                                 r |= b_result_default;
814                                 }
815                         }
816                 } else if ((flags & (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) == 0)
817                         r = a_result;  /* only in A */
818                 else {
819                         GValue value = G_VALUE_INIT;
820
821                         g_value_init (&value, prop_spec->value_type);
822                         g_object_get_property (G_OBJECT (a), prop_spec->name, &value);
823                         if (!g_param_value_defaults (prop_spec, &value))
824                                 r |= a_result;
825                         else if (flags & NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT)
826                                 r |= a_result | a_result_default;
827
828                         g_value_unset (&value);
829                 }
830
831                 if (r != NM_SETTING_DIFF_RESULT_UNKNOWN) {
832                         void *p;
833
834                         if (g_hash_table_lookup_extended (*results, prop_spec->name, NULL, &p)) {
835                                 if ((r & GPOINTER_TO_UINT (p)) != r)
836                                         g_hash_table_insert (*results, g_strdup (prop_spec->name), GUINT_TO_POINTER (r | GPOINTER_TO_UINT (p)));
837                         } else
838                                 g_hash_table_insert (*results, g_strdup (prop_spec->name), GUINT_TO_POINTER (r));
839                 }
840         }
841         g_free (property_specs);
842
843         /* Don't return an empty hash table */
844         if (results_created && !g_hash_table_size (*results)) {
845                 g_hash_table_destroy (*results);
846                 *results = NULL;
847         }
848
849         return !(*results);
850 }
851
852 /**
853  * nm_setting_enumerate_values:
854  * @setting: the #NMSetting
855  * @func: (scope call): user-supplied function called for each property of the setting
856  * @user_data: user data passed to @func at each invocation
857  *
858  * Iterates over each property of the #NMSetting object, calling the supplied
859  * user function for each property.
860  **/
861 void
862 nm_setting_enumerate_values (NMSetting *setting,
863                              NMSettingValueIterFn func,
864                              gpointer user_data)
865 {
866         GParamSpec **property_specs;
867         guint n_property_specs;
868         int i;
869
870         g_return_if_fail (NM_IS_SETTING (setting));
871         g_return_if_fail (func != NULL);
872
873         property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs);
874         for (i = 0; i < n_property_specs; i++) {
875                 GParamSpec *prop_spec = property_specs[i];
876                 GValue value = G_VALUE_INIT;
877
878                 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (prop_spec));
879                 g_object_get_property (G_OBJECT (setting), prop_spec->name, &value);
880                 func (setting, prop_spec->name, &value, prop_spec->flags, user_data);
881                 g_value_unset (&value);
882         }
883
884         g_free (property_specs);
885 }
886
887 /**
888  * nm_setting_clear_secrets:
889  * @setting: the #NMSetting
890  *
891  * Resets and clears any secrets in the setting.  Secrets should be added to the
892  * setting only when needed, and cleared immediately after use to prevent
893  * leakage of information.
894  **/
895 void
896 nm_setting_clear_secrets (NMSetting *setting)
897 {
898         _nm_setting_clear_secrets (setting);
899 }
900
901 gboolean
902 _nm_setting_clear_secrets (NMSetting *setting)
903 {
904         GParamSpec **property_specs;
905         guint n_property_specs;
906         guint i;
907         gboolean changed = FALSE;
908
909         g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
910
911         property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs);
912
913         for (i = 0; i < n_property_specs; i++) {
914                 GParamSpec *prop_spec = property_specs[i];
915
916                 if (prop_spec->flags & NM_SETTING_PARAM_SECRET) {
917                         GValue value = G_VALUE_INIT;
918
919                         g_value_init (&value, prop_spec->value_type);
920                         g_object_get_property (G_OBJECT (setting), prop_spec->name, &value);
921                         if (!g_param_value_defaults (prop_spec, &value)) {
922                                 g_param_value_set_default (prop_spec, &value);
923                                 g_object_set_property (G_OBJECT (setting), prop_spec->name, &value);
924                                 changed = TRUE;
925                         }
926                         g_value_unset (&value);
927                 }
928         }
929
930         g_free (property_specs);
931
932         return changed;
933 }
934
935 static gboolean
936 clear_secrets_with_flags (NMSetting *setting,
937                           GParamSpec *pspec,
938                           NMSettingClearSecretsWithFlagsFn func,
939                           gpointer user_data)
940 {
941         NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;
942         gboolean changed = FALSE;
943
944         g_return_val_if_fail (!NM_IS_SETTING_VPN (setting), FALSE);
945
946         /* Clear the secret if the user function says to do so */
947         if (!nm_setting_get_secret_flags (setting, pspec->name, &flags, NULL))
948                 g_return_val_if_reached (FALSE);
949
950         if (func (setting, pspec->name, flags, user_data) == TRUE) {
951                 GValue value = G_VALUE_INIT;
952
953                 g_value_init (&value, pspec->value_type);
954                 g_object_get_property (G_OBJECT (setting), pspec->name, &value);
955                 if (!g_param_value_defaults (pspec, &value)) {
956                         g_param_value_set_default (pspec, &value);
957                         g_object_set_property (G_OBJECT (setting), pspec->name, &value);
958                         changed = TRUE;
959                 }
960                 g_value_unset (&value);
961         }
962
963         return changed;
964 }
965
966 /**
967  * nm_setting_clear_secrets_with_flags:
968  * @setting: the #NMSetting
969  * @func: (scope call): function to be called to determine whether a
970  *     specific secret should be cleared or not
971  * @user_data: caller-supplied data passed to @func
972  *
973  * Clears and frees secrets determined by @func.
974  **/
975 void
976 nm_setting_clear_secrets_with_flags (NMSetting *setting,
977                                      NMSettingClearSecretsWithFlagsFn func,
978                                      gpointer user_data)
979 {
980         _nm_setting_clear_secrets_with_flags (setting, func, user_data);
981 }
982
983 gboolean
984 _nm_setting_clear_secrets_with_flags (NMSetting *setting,
985                                       NMSettingClearSecretsWithFlagsFn func,
986                                       gpointer user_data)
987 {
988         GParamSpec **property_specs;
989         guint n_property_specs;
990         guint i;
991         gboolean changed = FALSE;
992
993         g_return_val_if_fail (setting, FALSE);
994         g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
995         g_return_val_if_fail (func != NULL, FALSE);
996
997         property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs);
998         for (i = 0; i < n_property_specs; i++) {
999                 if (property_specs[i]->flags & NM_SETTING_PARAM_SECRET) {
1000                         changed |= NM_SETTING_GET_CLASS (setting)->clear_secrets_with_flags (setting,
1001                                                                                              property_specs[i],
1002                                                                                              func,
1003                                                                                              user_data);
1004                 }
1005         }
1006
1007         g_free (property_specs);
1008         return changed;
1009 }
1010
1011 /**
1012  * nm_setting_need_secrets:
1013  * @setting: the #NMSetting
1014  *
1015  * Returns an array of property names for each secret which may be required
1016  * to make a successful connection.  The returned hints are only intended as a
1017  * guide to what secrets may be required, because in some circumstances, there
1018  * is no way to conclusively determine exactly which secrets are needed.
1019  *
1020  * Returns: (transfer container) (element-type utf8): a #GPtrArray containing
1021  * the property names of secrets of the #NMSetting which may be required; the
1022  * caller owns the array and must free it with g_ptr_array_free(), but must not
1023  * free the elements.
1024  **/
1025 GPtrArray *
1026 nm_setting_need_secrets (NMSetting *setting)
1027 {
1028         GPtrArray *secrets = NULL;
1029
1030         g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
1031
1032         if (NM_SETTING_GET_CLASS (setting)->need_secrets)
1033                 secrets = NM_SETTING_GET_CLASS (setting)->need_secrets (setting);
1034
1035         return secrets;
1036 }
1037
1038 static int
1039 update_one_secret (NMSetting *setting, const char *key, GValue *value, GError **error)
1040 {
1041         GParamSpec *prop_spec;
1042
1043         prop_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), key);
1044         if (!prop_spec) {
1045                 g_set_error (error,
1046                              NM_SETTING_ERROR,
1047                              NM_SETTING_ERROR_PROPERTY_NOT_FOUND,
1048                              "%s", key);
1049                 return NM_SETTING_UPDATE_SECRET_ERROR;
1050         }
1051
1052         /* Silently ignore non-secrets */
1053         if (!(prop_spec->flags & NM_SETTING_PARAM_SECRET))
1054                 return NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED;
1055
1056         if (g_value_type_compatible (G_VALUE_TYPE (value), G_PARAM_SPEC_VALUE_TYPE (prop_spec))) {
1057                 if (G_VALUE_HOLDS_STRING (value) && G_IS_PARAM_SPEC_STRING (prop_spec)) {
1058                         /* String is expected to be a common case. Handle it specially and check whether
1059                          * the value is already set. Otherwise, we just reset the property and
1060                          * assume the value got modified. */
1061                         char *v;
1062
1063                         g_object_get (G_OBJECT (setting), prop_spec->name, &v, NULL);
1064                         if (g_strcmp0 (v, g_value_get_string (value)) == 0) {
1065                                 g_free (v);
1066                                 return NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED;
1067                         }
1068                         g_free (v);
1069                 }
1070                 g_object_set_property (G_OBJECT (setting), prop_spec->name, value);
1071                 return NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED;
1072         }
1073         g_set_error (error,
1074                      NM_SETTING_ERROR,
1075                      NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH,
1076                      "%s", key);
1077         return NM_SETTING_UPDATE_SECRET_ERROR;
1078 }
1079
1080 /**
1081  * nm_setting_update_secrets:
1082  * @setting: the #NMSetting
1083  * @secrets: (element-type utf8 GObject.Value): a #GHashTable mapping
1084  * string to #GValue of setting property names and secrets
1085  * @error: location to store error, or %NULL
1086  *
1087  * Update the setting's secrets, given a hash table of secrets intended for that
1088  * setting (deserialized from D-Bus for example).
1089  *
1090  * Returns: %TRUE if the secrets were successfully updated, %FALSE on failure to
1091  * update one or more of the secrets.
1092  **/
1093 gboolean
1094 nm_setting_update_secrets (NMSetting *setting, GHashTable *secrets, GError **error)
1095 {
1096         return _nm_setting_update_secrets (setting, secrets, error) != NM_SETTING_UPDATE_SECRET_ERROR;
1097 }
1098
1099 NMSettingUpdateSecretResult
1100 _nm_setting_update_secrets (NMSetting *setting, GHashTable *secrets, GError **error)
1101 {
1102         GHashTableIter iter;
1103         gpointer key, data;
1104         GError *tmp_error = NULL;
1105         NMSettingUpdateSecretResult result = NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED;
1106
1107         g_return_val_if_fail (NM_IS_SETTING (setting), NM_SETTING_UPDATE_SECRET_ERROR);
1108         g_return_val_if_fail (secrets != NULL, NM_SETTING_UPDATE_SECRET_ERROR);
1109         if (error)
1110                 g_return_val_if_fail (*error == NULL, NM_SETTING_UPDATE_SECRET_ERROR);
1111
1112         g_hash_table_iter_init (&iter, secrets);
1113         while (g_hash_table_iter_next (&iter, &key, &data)) {
1114                 int success;
1115                 const char *secret_key = (const char *) key;
1116                 GValue *secret_value = (GValue *) data;
1117
1118                 success = NM_SETTING_GET_CLASS (setting)->update_one_secret (setting, secret_key, secret_value, &tmp_error);
1119                 g_assert (!((success == NM_SETTING_UPDATE_SECRET_ERROR) ^ (!!tmp_error)));
1120
1121                 if (success == NM_SETTING_UPDATE_SECRET_ERROR) {
1122                         g_propagate_error (error, tmp_error);
1123                         return NM_SETTING_UPDATE_SECRET_ERROR;
1124                 }
1125
1126                 if (success == NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED)
1127                         result = NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED;
1128         }
1129
1130         return result;
1131 }
1132
1133 static gboolean
1134 is_secret_prop (NMSetting *setting, const char *secret_name, GError **error)
1135 {
1136         GParamSpec *pspec;
1137
1138         pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), secret_name);
1139         if (!pspec) {
1140                 g_set_error (error,
1141                              NM_SETTING_ERROR,
1142                              NM_SETTING_ERROR_PROPERTY_NOT_FOUND,
1143                              "Secret %s not provided by this setting", secret_name);
1144                 return FALSE;
1145         }
1146
1147         if (!(pspec->flags & NM_SETTING_PARAM_SECRET)) {
1148                 g_set_error (error,
1149                              NM_SETTING_ERROR,
1150                              NM_SETTING_ERROR_PROPERTY_NOT_SECRET,
1151                              "Property %s is not a secret", secret_name);
1152                 return FALSE;
1153         }
1154
1155         return TRUE;
1156 }
1157
1158 static gboolean
1159 get_secret_flags (NMSetting *setting,
1160                   const char *secret_name,
1161                   gboolean verify_secret,
1162                   NMSettingSecretFlags *out_flags,
1163                   GError **error)
1164 {
1165         char *flags_prop;
1166         NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;
1167
1168         if (verify_secret && !is_secret_prop (setting, secret_name, error)) {
1169                 if (out_flags)
1170                         *out_flags = NM_SETTING_SECRET_FLAG_NONE;
1171                 return FALSE;
1172         }
1173
1174         flags_prop = g_strdup_printf ("%s-flags", secret_name);
1175         g_object_get (G_OBJECT (setting), flags_prop, &flags, NULL);
1176         g_free (flags_prop);
1177
1178         if (out_flags)
1179                 *out_flags = flags;
1180         return TRUE;
1181 }
1182
1183 /**
1184  * nm_setting_get_secret_flags:
1185  * @setting: the #NMSetting
1186  * @secret_name: the secret key name to get flags for
1187  * @out_flags: on success, the #NMSettingSecretFlags for the secret
1188  * @error: location to store error, or %NULL
1189  *
1190  * For a given secret, retrieves the #NMSettingSecretFlags describing how to
1191  * handle that secret.
1192  *
1193  * Returns: %TRUE on success (if the given secret name was a valid property of
1194  * this setting, and if that property is secret), %FALSE if not
1195  **/
1196 gboolean
1197 nm_setting_get_secret_flags (NMSetting *setting,
1198                              const char *secret_name,
1199                              NMSettingSecretFlags *out_flags,
1200                              GError **error)
1201 {
1202         g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
1203         g_return_val_if_fail (secret_name != NULL, FALSE);
1204
1205         return NM_SETTING_GET_CLASS (setting)->get_secret_flags (setting, secret_name, TRUE, out_flags, error);
1206 }
1207
1208 static gboolean
1209 set_secret_flags (NMSetting *setting,
1210                   const char *secret_name,
1211                   gboolean verify_secret,
1212                   NMSettingSecretFlags flags,
1213                   GError **error)
1214 {
1215         char *flags_prop;
1216
1217         if (verify_secret)
1218                 g_return_val_if_fail (is_secret_prop (setting, secret_name, error), FALSE);
1219
1220         flags_prop = g_strdup_printf ("%s-flags", secret_name);
1221         g_object_set (G_OBJECT (setting), flags_prop, flags, NULL);
1222         g_free (flags_prop);
1223         return TRUE;
1224 }
1225
1226 /**
1227  * nm_setting_set_secret_flags:
1228  * @setting: the #NMSetting
1229  * @secret_name: the secret key name to set flags for
1230  * @flags: the #NMSettingSecretFlags for the secret
1231  * @error: location to store error, or %NULL
1232  *
1233  * For a given secret, stores the #NMSettingSecretFlags describing how to
1234  * handle that secret.
1235  *
1236  * Returns: %TRUE on success (if the given secret name was a valid property of
1237  * this setting, and if that property is secret), %FALSE if not
1238  **/
1239 gboolean
1240 nm_setting_set_secret_flags (NMSetting *setting,
1241                              const char *secret_name,
1242                              NMSettingSecretFlags flags,
1243                              GError **error)
1244 {
1245         g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
1246         g_return_val_if_fail (secret_name != NULL, FALSE);
1247         g_return_val_if_fail (flags <= NM_SETTING_SECRET_FLAGS_ALL, FALSE);
1248
1249         return NM_SETTING_GET_CLASS (setting)->set_secret_flags (setting, secret_name, TRUE, flags, error);
1250 }
1251
1252 /**
1253  * nm_setting_to_string:
1254  * @setting: the #NMSetting
1255  *
1256  * Convert the setting into a string.  For debugging purposes ONLY, should NOT
1257  * be used for serialization of the setting, or machine-parsed in any way. The
1258  * output format is not guaranteed to be stable and may change at any time.
1259  *
1260  * Returns: an allocated string containing a textual representation of the
1261  * setting's properties and values (including secrets!), which the caller should
1262  * free with g_free()
1263  **/
1264 char *
1265 nm_setting_to_string (NMSetting *setting)
1266 {
1267         GString *string;
1268         GParamSpec **property_specs;
1269         guint n_property_specs;
1270         guint i;
1271
1272         g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
1273
1274         property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs);
1275
1276         string = g_string_new (nm_setting_get_name (setting));
1277         g_string_append_c (string, '\n');
1278
1279         for (i = 0; i < n_property_specs; i++) {
1280                 GParamSpec *prop_spec = property_specs[i];
1281                 GValue value = G_VALUE_INIT;
1282                 char *value_str;
1283                 gboolean is_default;
1284
1285                 if (strcmp (prop_spec->name, NM_SETTING_NAME) == 0)
1286                         continue;
1287
1288                 g_value_init (&value, prop_spec->value_type);
1289                 g_object_get_property (G_OBJECT (setting), prop_spec->name, &value);
1290
1291                 value_str = g_strdup_value_contents (&value);
1292                 g_string_append_printf (string, "\t%s : %s", prop_spec->name, value_str);
1293                 g_free (value_str);
1294
1295                 is_default = g_param_value_defaults (prop_spec, &value);
1296                 g_value_unset (&value);
1297
1298                 g_string_append (string, " (");
1299                 g_string_append_c (string, 's');
1300                 if (is_default)
1301                         g_string_append_c (string, 'd');
1302                 g_string_append_c (string, ')');
1303                 g_string_append_c (string, '\n');
1304         }
1305
1306         g_free (property_specs);
1307         g_string_append_c (string, '\n');
1308
1309         return g_string_free (string, FALSE);
1310 }
1311
1312 /**
1313  * nm_setting_get_virtual_iface_name:
1314  * @setting: the #NMSetting
1315  *
1316  * Returns the name of the virtual kernel interface which the connection
1317  * needs to use if specified in the settings.
1318  *
1319  * Returns: Name of the virtual interface or %NULL if the setting does not
1320  * support this feature
1321  **/
1322 const char *
1323 nm_setting_get_virtual_iface_name (NMSetting *setting)
1324 {
1325         g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
1326
1327         if (NM_SETTING_GET_CLASS (setting)->get_virtual_iface_name)
1328                 return NM_SETTING_GET_CLASS (setting)->get_virtual_iface_name (setting);
1329
1330         return NULL;
1331 }
1332
1333
1334 NMSettingVerifyResult
1335 _nm_setting_verify_deprecated_virtual_iface_name (const char *interface_name,
1336                                                   gboolean allow_missing,
1337                                                   const char *setting_name,
1338                                                   const char *setting_property,
1339                                                   GQuark error_quark,
1340                                                   gint e_invalid_property,
1341                                                   gint e_missing_property,
1342                                                   GSList *all_settings,
1343                                                   GError **error)
1344 {
1345         NMSettingConnection *s_con;
1346         const char *con_name;
1347
1348         s_con = NM_SETTING_CONNECTION (nm_setting_find_in_list (all_settings, NM_SETTING_CONNECTION_SETTING_NAME));
1349         con_name = s_con ? nm_setting_connection_get_interface_name (s_con) : NULL;
1350         if (!interface_name && !con_name) {
1351                 if (allow_missing)
1352                         return NM_SETTING_VERIFY_SUCCESS;
1353
1354                 g_set_error_literal (error,
1355                                      NM_SETTING_CONNECTION_ERROR,
1356                                      NM_SETTING_CONNECTION_ERROR_MISSING_PROPERTY,
1357                                      _("property is missing"));
1358                 g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_INTERFACE_NAME);
1359                 return NM_SETTING_VERIFY_ERROR;
1360         }
1361         if (!con_name && !nm_utils_iface_valid_name (interface_name)) {
1362                 /* the interface_name is invalid, we cannot normalize it. Only do this if !con_name,
1363                  * because if con_name is set, it can overwrite interface_name. */
1364                 g_set_error_literal (error,
1365                                      error_quark,
1366                                      e_invalid_property,
1367                                      _("property is invalid"));
1368                 g_prefix_error (error, "%s.%s: ", setting_name, setting_property);
1369                 return NM_SETTING_VERIFY_ERROR;
1370         }
1371         if (!con_name) {
1372                 /* NMSettingConnection has interface not set, it should be normalized to interface_name */
1373                 g_set_error_literal (error,
1374                                      NM_SETTING_CONNECTION_ERROR,
1375                                      NM_SETTING_CONNECTION_ERROR_MISSING_PROPERTY,
1376                                      _("property is missing"));
1377                 g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_INTERFACE_NAME);
1378                 return NM_SETTING_VERIFY_NORMALIZABLE;
1379         }
1380         if (!nm_utils_iface_valid_name (con_name)) {
1381                 /* NMSettingConnection:interface_name is invalid, we cannot normalize it. */
1382                 g_set_error_literal (error,
1383                                      NM_SETTING_CONNECTION_ERROR,
1384                                      NM_SETTING_CONNECTION_ERROR_INVALID_PROPERTY,
1385                                      _("property is invalid"));
1386                 g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_INTERFACE_NAME);
1387                 return NM_SETTING_VERIFY_ERROR;
1388         }
1389         if (!interface_name) {
1390                 /* Normalize by setting NMSettingConnection:interface_name. */
1391                 g_set_error_literal (error,
1392                                      error_quark,
1393                                      e_missing_property,
1394                                      _("property is missing"));
1395                 g_prefix_error (error, "%s.%s: ", setting_name, setting_property);
1396                 return NM_SETTING_VERIFY_NORMALIZABLE;
1397         }
1398         if (strcmp (con_name, interface_name) != 0) {
1399                 /* con_name and interface_name are different. It can be normalized by setting interface_name
1400                  * to con_name. */
1401                 g_set_error_literal (error,
1402                                      error_quark,
1403                                      e_invalid_property,
1404                                      _("property is invalid"));
1405                 g_prefix_error (error, "%s.%s: ", setting_name, setting_property);
1406                 /* we would like to make this a NORMALIZEABLE_ERROR, but that might
1407                  * break older connections. */
1408                 return NM_SETTING_VERIFY_NORMALIZABLE;
1409         }
1410
1411         return NM_SETTING_VERIFY_SUCCESS;
1412 }
1413
1414 /*****************************************************************************/
1415
1416 static void
1417 nm_setting_init (NMSetting *setting)
1418 {
1419 }
1420
1421 static GObject*
1422 constructor (GType type,
1423              guint n_construct_params,
1424              GObjectConstructParam *construct_params)
1425 {
1426         GObject *object;
1427
1428         object = G_OBJECT_CLASS (nm_setting_parent_class)->constructor (type,
1429                                                                         n_construct_params,
1430                                                                         construct_params);
1431
1432         _ensure_setting_info (object, NM_SETTING_GET_PRIVATE (object));
1433         return object;
1434 }
1435
1436 static void
1437 set_property (GObject *object, guint prop_id,
1438               const GValue *value, GParamSpec *pspec)
1439 {
1440         NMSettingPrivate *priv = NM_SETTING_GET_PRIVATE (object);
1441
1442         switch (prop_id) {
1443         case PROP_NAME:
1444                 /* The setter for NAME is deprecated and should not be used anymore.
1445                  * Keep the setter for NAME to remain backward compatible.
1446                  * Only assert that the caller does not try to set the name to a different value
1447                  * then the registered name, which would be extra wrong.
1448                  **/
1449                 _ensure_setting_info (object, priv);
1450                 g_return_if_fail (!g_strcmp0 (priv->info->name, g_value_get_string (value)));
1451                 break;
1452         default:
1453                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1454                 break;
1455         }
1456 }
1457
1458 static void
1459 get_property (GObject *object, guint prop_id,
1460               GValue *value, GParamSpec *pspec)
1461 {
1462         NMSetting *setting = NM_SETTING (object);
1463
1464         switch (prop_id) {
1465         case PROP_NAME:
1466                 g_value_set_string (value, nm_setting_get_name (setting));
1467                 break;
1468         default:
1469                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1470                 break;
1471         }
1472 }
1473
1474 static void
1475 nm_setting_class_init (NMSettingClass *setting_class)
1476 {
1477         GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
1478
1479         g_type_class_add_private (setting_class, sizeof (NMSettingPrivate));
1480
1481         /* virtual methods */
1482         object_class->constructor  = constructor;
1483         object_class->set_property = set_property;
1484         object_class->get_property = get_property;
1485
1486         setting_class->update_one_secret = update_one_secret;
1487         setting_class->get_secret_flags = get_secret_flags;
1488         setting_class->set_secret_flags = set_secret_flags;
1489         setting_class->compare_property = compare_property;
1490         setting_class->clear_secrets_with_flags = clear_secrets_with_flags;
1491
1492         /* Properties */
1493
1494         /**
1495          * NMSetting:name:
1496          *
1497          * The setting's name, which uniquely identifies the setting within the
1498          * connection.  Each setting type has a name unique to that type, for
1499          * example "ppp" or "wireless" or "wired".
1500          **/
1501         g_object_class_install_property
1502                 (object_class, PROP_NAME,
1503                  g_param_spec_string (NM_SETTING_NAME, "", "",
1504                                       NULL,
1505                                       G_PARAM_READWRITE |
1506                                       G_PARAM_STATIC_STRINGS));
1507 }