add3ad9795d1c6b89032a0464638761c2a914c61
[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         guint n_params = 0;
383         GParameter *params;
384         int i;
385
386         g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (setting_type), NULL);
387         g_return_val_if_fail (hash != NULL, NULL);
388
389         /* g_type_class_ref() ensures the setting class is created if it hasn't
390          * already been used.
391          */
392         class = g_type_class_ref (setting_type);
393         params = g_new0 (GParameter, g_hash_table_size (hash));
394
395         g_hash_table_iter_init (&iter, hash);
396         while (g_hash_table_iter_next (&iter, (gpointer) &prop_name, (gpointer) &src_value)) {
397                 GValue *dst_value = &params[n_params].value;
398                 GParamSpec *param_spec;
399
400                 param_spec = g_object_class_find_property (class, prop_name);
401                 if (!param_spec) {
402                         /* Assume that any unrecognized property either can be ignored, or
403                          * else has a backward-compatibility equivalent.
404                          */
405                         g_debug ("Ignoring unrecognized property '%s'", prop_name);
406                         continue;
407                 }
408
409                 g_value_init (dst_value, G_VALUE_TYPE (src_value));
410                 g_value_copy (src_value, dst_value);
411                 params[n_params++].name = prop_name;
412         }
413
414         setting = (NMSetting *) g_object_newv (setting_type, n_params, params);
415
416         for (i = 0; i < n_params; i++)
417                 g_value_unset (&params[i].value);
418
419         g_free (params);
420         g_type_class_unref (class);
421
422         return setting;
423 }
424
425 gboolean
426 _nm_setting_get_property (NMSetting *setting, const char *property_name, GValue *value)
427 {
428         GParamSpec *prop_spec;
429
430         g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
431         g_return_val_if_fail (property_name, FALSE);
432         g_return_val_if_fail (value, FALSE);
433
434         prop_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), property_name);
435
436         if (!prop_spec) {
437                 g_value_unset (value);
438                 return FALSE;
439         }
440
441         g_value_init (value, prop_spec->value_type);
442         g_object_get_property (G_OBJECT (setting), property_name, value);
443         return TRUE;
444 }
445
446 static void
447 duplicate_setting (NMSetting *setting,
448                    const char *name,
449                    const GValue *value,
450                    GParamFlags flags,
451                    gpointer user_data)
452 {
453         if ((flags & (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)) == G_PARAM_WRITABLE)
454                 g_object_set_property (G_OBJECT (user_data), name, value);
455 }
456
457 /**
458  * nm_setting_duplicate:
459  * @setting: the #NMSetting to duplicate
460  *
461  * Duplicates a #NMSetting.
462  *
463  * Returns: (transfer full): a new #NMSetting containing the same properties and values as the
464  * source #NMSetting
465  **/
466 NMSetting *
467 nm_setting_duplicate (NMSetting *setting)
468 {
469         GObject *dup;
470
471         g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
472
473         dup = g_object_new (G_OBJECT_TYPE (setting), NULL);
474
475         g_object_freeze_notify (dup);
476         nm_setting_enumerate_values (setting, duplicate_setting, dup);
477         g_object_thaw_notify (dup);
478
479         return NM_SETTING (dup);
480 }
481
482 static gint
483 find_setting_by_name (gconstpointer a, gconstpointer b)
484 {
485         NMSetting *setting = NM_SETTING (a);
486         const char *str = (const char *) b;
487
488         return strcmp (nm_setting_get_name (setting), str);
489 }
490
491 NMSetting *
492 nm_setting_find_in_list (GSList     *settings_list,
493                          const char *setting_name)
494 {
495         GSList *found;
496
497         found = g_slist_find_custom (settings_list, setting_name, find_setting_by_name);
498         if (found)
499                 return found->data;
500         else
501                 return NULL;
502 }
503
504 /**
505  * nm_setting_get_name:
506  * @setting: the #NMSetting
507  *
508  * Returns the type name of the #NMSetting object
509  *
510  * Returns: a string containing the type name of the #NMSetting object,
511  * like 'ppp' or 'wireless' or 'wired'.
512  **/
513 const char *
514 nm_setting_get_name (NMSetting *setting)
515 {
516         NMSettingPrivate *priv;
517
518         g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
519         priv = NM_SETTING_GET_PRIVATE (setting);
520         _ensure_setting_info (setting, priv);
521         return priv->info->name;
522 }
523
524 /**
525  * nm_setting_verify:
526  * @setting: the #NMSetting to verify
527  * @all_settings: (element-type NMSetting): a #GSList of all settings
528  *     in the connection from which @setting came
529  * @error: location to store error, or %NULL
530  *
531  * Validates the setting.  Each setting's properties have allowed values, and
532  * some are dependent on other values (hence the need for @all_settings).  The
533  * returned #GError contains information about which property of the setting
534  * failed validation, and in what way that property failed validation.
535  *
536  * Returns: %TRUE if the setting is valid, %FALSE if it is not
537  **/
538 gboolean
539 nm_setting_verify (NMSetting *setting, GSList *all_settings, GError **error)
540 {
541         NMSettingVerifyResult result = _nm_setting_verify (setting, all_settings, error);
542
543         if (result == NM_SETTING_VERIFY_NORMALIZABLE)
544                 g_clear_error (error);
545
546         return result == NM_SETTING_VERIFY_SUCCESS || result == NM_SETTING_VERIFY_NORMALIZABLE;
547 }
548
549 NMSettingVerifyResult
550 _nm_setting_verify (NMSetting *setting, GSList *all_settings, GError **error)
551 {
552         g_return_val_if_fail (NM_IS_SETTING (setting), NM_SETTING_VERIFY_ERROR);
553         g_return_val_if_fail (!error || *error == NULL, NM_SETTING_VERIFY_ERROR);
554
555         if (NM_SETTING_GET_CLASS (setting)->verify)
556                 return NM_SETTING_GET_CLASS (setting)->verify (setting, all_settings, error);
557
558         return NM_SETTING_VERIFY_SUCCESS;
559 }
560
561 static gboolean
562 compare_property (NMSetting *setting,
563                   NMSetting *other,
564                   const GParamSpec *prop_spec,
565                   NMSettingCompareFlags flags)
566 {
567         GValue value1 = G_VALUE_INIT;
568         GValue value2 = G_VALUE_INIT;
569         gboolean different;
570
571         /* Handle compare flags */
572         if (prop_spec->flags & NM_SETTING_PARAM_SECRET) {
573                 NMSettingSecretFlags a_secret_flags = NM_SETTING_SECRET_FLAG_NONE;
574                 NMSettingSecretFlags b_secret_flags = NM_SETTING_SECRET_FLAG_NONE;
575
576                 g_return_val_if_fail (!NM_IS_SETTING_VPN (setting), FALSE);
577
578                 if (!nm_setting_get_secret_flags (setting, prop_spec->name, &a_secret_flags, NULL))
579                         g_return_val_if_reached (FALSE);
580                 if (!nm_setting_get_secret_flags (other, prop_spec->name, &b_secret_flags, NULL))
581                         g_return_val_if_reached (FALSE);
582
583                 /* If the secret flags aren't the same the settings aren't the same */
584                 if (a_secret_flags != b_secret_flags)
585                         return FALSE;
586
587                 /* Check for various secret flags that might cause us to ignore comparing
588                  * this property.
589                  */
590                 if (   (flags & NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS)
591                     && (a_secret_flags & NM_SETTING_SECRET_FLAG_AGENT_OWNED))
592                         return TRUE;
593
594                 if (   (flags & NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)
595                     && (a_secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED))
596                         return TRUE;
597         }
598
599         g_value_init (&value1, prop_spec->value_type);
600         g_object_get_property (G_OBJECT (setting), prop_spec->name, &value1);
601
602         g_value_init (&value2, prop_spec->value_type);
603         g_object_get_property (G_OBJECT (other), prop_spec->name, &value2);
604
605         different = g_param_values_cmp ((GParamSpec *) prop_spec, &value1, &value2);
606
607         g_value_unset (&value1);
608         g_value_unset (&value2);
609
610         return different == 0 ? TRUE : FALSE;
611 }
612
613 /**
614  * nm_setting_compare:
615  * @a: a #NMSetting
616  * @b: a second #NMSetting to compare with the first
617  * @flags: compare flags, e.g. %NM_SETTING_COMPARE_FLAG_EXACT
618  *
619  * Compares two #NMSetting objects for similarity, with comparison behavior
620  * modified by a set of flags.  See the documentation for #NMSettingCompareFlags
621  * for a description of each flag's behavior.
622  *
623  * Returns: %TRUE if the comparison succeeds, %FALSE if it does not
624  **/
625 gboolean
626 nm_setting_compare (NMSetting *a,
627                     NMSetting *b,
628                     NMSettingCompareFlags flags)
629 {
630         GParamSpec **property_specs;
631         guint n_property_specs;
632         gint same = TRUE;
633         guint i;
634
635         g_return_val_if_fail (NM_IS_SETTING (a), FALSE);
636         g_return_val_if_fail (NM_IS_SETTING (b), FALSE);
637
638         /* First check that both have the same type */
639         if (G_OBJECT_TYPE (a) != G_OBJECT_TYPE (b))
640                 return FALSE;
641
642         /* And now all properties */
643         property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (a), &n_property_specs);
644         for (i = 0; i < n_property_specs && same; i++) {
645                 GParamSpec *prop_spec = property_specs[i];
646
647                 /* Fuzzy compare ignores secrets and properties defined with the FUZZY_IGNORE flag */
648                 if (   (flags & NM_SETTING_COMPARE_FLAG_FUZZY)
649                     && (prop_spec->flags & (NM_SETTING_PARAM_FUZZY_IGNORE | NM_SETTING_PARAM_SECRET)))
650                         continue;
651
652                 if ((flags & NM_SETTING_COMPARE_FLAG_INFERRABLE) && !(prop_spec->flags & NM_SETTING_PARAM_INFERRABLE))
653                         continue;
654
655                 if (   (flags & NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS)
656                     && (prop_spec->flags & NM_SETTING_PARAM_SECRET))
657                         continue;
658
659                 same = NM_SETTING_GET_CLASS (a)->compare_property (a, b, prop_spec, flags);
660         }
661         g_free (property_specs);
662
663         return same;
664 }
665
666 static inline gboolean
667 should_compare_prop (NMSetting *setting,
668                      const char *prop_name,
669                      NMSettingCompareFlags comp_flags,
670                      GParamFlags prop_flags)
671 {
672         /* Fuzzy compare ignores secrets and properties defined with the FUZZY_IGNORE flag */
673         if (   (comp_flags & NM_SETTING_COMPARE_FLAG_FUZZY)
674             && (prop_flags & (NM_SETTING_PARAM_FUZZY_IGNORE | NM_SETTING_PARAM_SECRET)))
675                 return FALSE;
676
677         if ((comp_flags & NM_SETTING_COMPARE_FLAG_INFERRABLE) && !(prop_flags & NM_SETTING_PARAM_INFERRABLE))
678                 return FALSE;
679
680         if (prop_flags & NM_SETTING_PARAM_SECRET) {
681                 NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
682
683                 if (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS)
684                         return FALSE;
685
686                 if (   NM_IS_SETTING_VPN (setting)
687                     && g_strcmp0 (prop_name, NM_SETTING_VPN_SECRETS) == 0) {
688                         /* FIXME: NMSettingVPN:NM_SETTING_VPN_SECRETS has NM_SETTING_PARAM_SECRET.
689                          * nm_setting_get_secret_flags() quite possibly fails, but it might succeed if the
690                          * setting accidently uses a key "secrets". */
691                         return FALSE;
692                 }
693
694                 if (!nm_setting_get_secret_flags (setting, prop_name, &secret_flags, NULL))
695                         g_return_val_if_reached (FALSE);
696
697                 if (   (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS)
698                     && (secret_flags & NM_SETTING_SECRET_FLAG_AGENT_OWNED))
699                         return FALSE;
700
701                 if (   (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)
702                     && (secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED))
703                         return FALSE;
704         }
705
706         if (   (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_ID)
707             && NM_IS_SETTING_CONNECTION (setting)
708             && !strcmp (prop_name, NM_SETTING_CONNECTION_ID))
709                 return FALSE;
710
711         return TRUE;
712 }
713
714 /**
715  * nm_setting_diff:
716  * @a: a #NMSetting
717  * @b: a second #NMSetting to compare with the first
718  * @flags: compare flags, e.g. %NM_SETTING_COMPARE_FLAG_EXACT
719  * @invert_results: this parameter is used internally by libnm-util and should
720  * be set to %FALSE.  If %TRUE inverts the meaning of the #NMSettingDiffResult.
721  * @results: (inout) (transfer full) (element-type utf8 guint32): if the
722  * settings differ, on return a hash table mapping the differing keys to one or
723  * more %NMSettingDiffResult values OR-ed together.  If the settings do not
724  * differ, any hash table passed in is unmodified.  If no hash table is passed
725  * in and the settings differ, a new one is created and returned.
726  *
727  * Compares two #NMSetting objects for similarity, with comparison behavior
728  * modified by a set of flags.  See the documentation for #NMSettingCompareFlags
729  * for a description of each flag's behavior.  If the settings differ, the keys
730  * of each setting that differ from the other are added to @results, mapped to
731  * one or more #NMSettingDiffResult values.
732  *
733  * Returns: %TRUE if the settings contain the same values, %FALSE if they do not
734  **/
735 gboolean
736 nm_setting_diff (NMSetting *a,
737                  NMSetting *b,
738                  NMSettingCompareFlags flags,
739                  gboolean invert_results,
740                  GHashTable **results)
741 {
742         GParamSpec **property_specs;
743         guint n_property_specs;
744         guint i;
745         NMSettingDiffResult a_result = NM_SETTING_DIFF_RESULT_IN_A;
746         NMSettingDiffResult b_result = NM_SETTING_DIFF_RESULT_IN_B;
747         NMSettingDiffResult a_result_default = NM_SETTING_DIFF_RESULT_IN_A_DEFAULT;
748         NMSettingDiffResult b_result_default = NM_SETTING_DIFF_RESULT_IN_B_DEFAULT;
749         gboolean results_created = FALSE;
750
751         g_return_val_if_fail (results != NULL, FALSE);
752         g_return_val_if_fail (NM_IS_SETTING (a), FALSE);
753         if (b) {
754                 g_return_val_if_fail (NM_IS_SETTING (b), FALSE);
755                 g_return_val_if_fail (G_OBJECT_TYPE (a) == G_OBJECT_TYPE (b), FALSE);
756         }
757
758         if ((flags & (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) ==
759                      (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) {
760                 /* conflicting flags: default to WITH_DEFAULT (clearing NO_DEFAULT). */
761                 flags &= ~NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT;
762         }
763
764         /* If the caller is calling this function in a pattern like this to get
765          * complete diffs:
766          *
767          * nm_setting_diff (A, B, FALSE, &results);
768          * nm_setting_diff (B, A, TRUE, &results);
769          *
770          * and wants us to invert the results so that the second invocation comes
771          * out correctly, do that here.
772          */
773         if (invert_results) {
774                 a_result = NM_SETTING_DIFF_RESULT_IN_B;
775                 b_result = NM_SETTING_DIFF_RESULT_IN_A;
776                 a_result_default = NM_SETTING_DIFF_RESULT_IN_B_DEFAULT;
777                 b_result_default = NM_SETTING_DIFF_RESULT_IN_A_DEFAULT;
778         }
779
780         if (*results == NULL) {
781                 *results = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
782                 results_created = TRUE;
783         }
784
785         /* And now all properties */
786         property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (a), &n_property_specs);
787
788         for (i = 0; i < n_property_specs; i++) {
789                 GParamSpec *prop_spec = property_specs[i];
790                 NMSettingDiffResult r = NM_SETTING_DIFF_RESULT_UNKNOWN;
791
792                 /* Handle compare flags */
793                 if (!should_compare_prop (a, prop_spec->name, flags, prop_spec->flags))
794                         continue;
795                 if (strcmp (prop_spec->name, NM_SETTING_NAME) == 0)
796                         continue;
797
798                 if (b) {
799                         gboolean different;
800
801                         different = !NM_SETTING_GET_CLASS (a)->compare_property (a, b, prop_spec, flags);
802                         if (different) {
803                                 gboolean a_is_default, b_is_default;
804                                 GValue value = G_VALUE_INIT;
805
806                                 g_value_init (&value, prop_spec->value_type);
807                                 g_object_get_property (G_OBJECT (a), prop_spec->name, &value);
808                                 a_is_default = g_param_value_defaults (prop_spec, &value);
809
810                                 g_value_reset (&value);
811                                 g_object_get_property (G_OBJECT (b), prop_spec->name, &value);
812                                 b_is_default = g_param_value_defaults (prop_spec, &value);
813
814                                 g_value_unset (&value);
815                                 if ((flags & NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT) == 0) {
816                                         if (!a_is_default)
817                                                 r |= a_result;
818                                         if (!b_is_default)
819                                                 r |= b_result;
820                                 } else {
821                                         r |= a_result | b_result;
822                                         if (a_is_default)
823                                                 r |= a_result_default;
824                                         if (b_is_default)
825                                                 r |= b_result_default;
826                                 }
827                         }
828                 } else if ((flags & (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) == 0)
829                         r = a_result;  /* only in A */
830                 else {
831                         GValue value = G_VALUE_INIT;
832
833                         g_value_init (&value, prop_spec->value_type);
834                         g_object_get_property (G_OBJECT (a), prop_spec->name, &value);
835                         if (!g_param_value_defaults (prop_spec, &value))
836                                 r |= a_result;
837                         else if (flags & NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT)
838                                 r |= a_result | a_result_default;
839
840                         g_value_unset (&value);
841                 }
842
843                 if (r != NM_SETTING_DIFF_RESULT_UNKNOWN) {
844                         void *p;
845
846                         if (g_hash_table_lookup_extended (*results, prop_spec->name, NULL, &p)) {
847                                 if ((r & GPOINTER_TO_UINT (p)) != r)
848                                         g_hash_table_insert (*results, g_strdup (prop_spec->name), GUINT_TO_POINTER (r | GPOINTER_TO_UINT (p)));
849                         } else
850                                 g_hash_table_insert (*results, g_strdup (prop_spec->name), GUINT_TO_POINTER (r));
851                 }
852         }
853         g_free (property_specs);
854
855         /* Don't return an empty hash table */
856         if (results_created && !g_hash_table_size (*results)) {
857                 g_hash_table_destroy (*results);
858                 *results = NULL;
859         }
860
861         return !(*results);
862 }
863
864 /**
865  * nm_setting_enumerate_values:
866  * @setting: the #NMSetting
867  * @func: (scope call): user-supplied function called for each property of the setting
868  * @user_data: user data passed to @func at each invocation
869  *
870  * Iterates over each property of the #NMSetting object, calling the supplied
871  * user function for each property.
872  **/
873 void
874 nm_setting_enumerate_values (NMSetting *setting,
875                              NMSettingValueIterFn func,
876                              gpointer user_data)
877 {
878         GParamSpec **property_specs;
879         guint n_property_specs;
880         int i;
881
882         g_return_if_fail (NM_IS_SETTING (setting));
883         g_return_if_fail (func != NULL);
884
885         property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs);
886         for (i = 0; i < n_property_specs; i++) {
887                 GParamSpec *prop_spec = property_specs[i];
888                 GValue value = G_VALUE_INIT;
889
890                 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (prop_spec));
891                 g_object_get_property (G_OBJECT (setting), prop_spec->name, &value);
892                 func (setting, prop_spec->name, &value, prop_spec->flags, user_data);
893                 g_value_unset (&value);
894         }
895
896         g_free (property_specs);
897 }
898
899 /**
900  * nm_setting_clear_secrets:
901  * @setting: the #NMSetting
902  *
903  * Resets and clears any secrets in the setting.  Secrets should be added to the
904  * setting only when needed, and cleared immediately after use to prevent
905  * leakage of information.
906  **/
907 void
908 nm_setting_clear_secrets (NMSetting *setting)
909 {
910         _nm_setting_clear_secrets (setting);
911 }
912
913 gboolean
914 _nm_setting_clear_secrets (NMSetting *setting)
915 {
916         GParamSpec **property_specs;
917         guint n_property_specs;
918         guint i;
919         gboolean changed = FALSE;
920
921         g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
922
923         property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs);
924
925         for (i = 0; i < n_property_specs; i++) {
926                 GParamSpec *prop_spec = property_specs[i];
927
928                 if (prop_spec->flags & NM_SETTING_PARAM_SECRET) {
929                         GValue value = G_VALUE_INIT;
930
931                         g_value_init (&value, prop_spec->value_type);
932                         g_object_get_property (G_OBJECT (setting), prop_spec->name, &value);
933                         if (!g_param_value_defaults (prop_spec, &value)) {
934                                 g_param_value_set_default (prop_spec, &value);
935                                 g_object_set_property (G_OBJECT (setting), prop_spec->name, &value);
936                                 changed = TRUE;
937                         }
938                         g_value_unset (&value);
939                 }
940         }
941
942         g_free (property_specs);
943
944         return changed;
945 }
946
947 static gboolean
948 clear_secrets_with_flags (NMSetting *setting,
949                           GParamSpec *pspec,
950                           NMSettingClearSecretsWithFlagsFn func,
951                           gpointer user_data)
952 {
953         NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;
954         gboolean changed = FALSE;
955
956         g_return_val_if_fail (!NM_IS_SETTING_VPN (setting), FALSE);
957
958         /* Clear the secret if the user function says to do so */
959         if (!nm_setting_get_secret_flags (setting, pspec->name, &flags, NULL))
960                 g_return_val_if_reached (FALSE);
961
962         if (func (setting, pspec->name, flags, user_data) == TRUE) {
963                 GValue value = G_VALUE_INIT;
964
965                 g_value_init (&value, pspec->value_type);
966                 g_object_get_property (G_OBJECT (setting), pspec->name, &value);
967                 if (!g_param_value_defaults (pspec, &value)) {
968                         g_param_value_set_default (pspec, &value);
969                         g_object_set_property (G_OBJECT (setting), pspec->name, &value);
970                         changed = TRUE;
971                 }
972                 g_value_unset (&value);
973         }
974
975         return changed;
976 }
977
978 /**
979  * nm_setting_clear_secrets_with_flags:
980  * @setting: the #NMSetting
981  * @func: (scope call): function to be called to determine whether a
982  *     specific secret should be cleared or not
983  * @user_data: caller-supplied data passed to @func
984  *
985  * Clears and frees secrets determined by @func.
986  **/
987 void
988 nm_setting_clear_secrets_with_flags (NMSetting *setting,
989                                      NMSettingClearSecretsWithFlagsFn func,
990                                      gpointer user_data)
991 {
992         _nm_setting_clear_secrets_with_flags (setting, func, user_data);
993 }
994
995 gboolean
996 _nm_setting_clear_secrets_with_flags (NMSetting *setting,
997                                       NMSettingClearSecretsWithFlagsFn func,
998                                       gpointer user_data)
999 {
1000         GParamSpec **property_specs;
1001         guint n_property_specs;
1002         guint i;
1003         gboolean changed = FALSE;
1004
1005         g_return_val_if_fail (setting, FALSE);
1006         g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
1007         g_return_val_if_fail (func != NULL, FALSE);
1008
1009         property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs);
1010         for (i = 0; i < n_property_specs; i++) {
1011                 if (property_specs[i]->flags & NM_SETTING_PARAM_SECRET) {
1012                         changed |= NM_SETTING_GET_CLASS (setting)->clear_secrets_with_flags (setting,
1013                                                                                              property_specs[i],
1014                                                                                              func,
1015                                                                                              user_data);
1016                 }
1017         }
1018
1019         g_free (property_specs);
1020         return changed;
1021 }
1022
1023 /**
1024  * nm_setting_need_secrets:
1025  * @setting: the #NMSetting
1026  *
1027  * Returns an array of property names for each secret which may be required
1028  * to make a successful connection.  The returned hints are only intended as a
1029  * guide to what secrets may be required, because in some circumstances, there
1030  * is no way to conclusively determine exactly which secrets are needed.
1031  *
1032  * Returns: (transfer container) (element-type utf8): a #GPtrArray containing
1033  * the property names of secrets of the #NMSetting which may be required; the
1034  * caller owns the array and must free it with g_ptr_array_free(), but must not
1035  * free the elements.
1036  **/
1037 GPtrArray *
1038 nm_setting_need_secrets (NMSetting *setting)
1039 {
1040         GPtrArray *secrets = NULL;
1041
1042         g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
1043
1044         if (NM_SETTING_GET_CLASS (setting)->need_secrets)
1045                 secrets = NM_SETTING_GET_CLASS (setting)->need_secrets (setting);
1046
1047         return secrets;
1048 }
1049
1050 static int
1051 update_one_secret (NMSetting *setting, const char *key, GValue *value, GError **error)
1052 {
1053         GParamSpec *prop_spec;
1054
1055         prop_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), key);
1056         if (!prop_spec) {
1057                 g_set_error (error,
1058                              NM_SETTING_ERROR,
1059                              NM_SETTING_ERROR_PROPERTY_NOT_FOUND,
1060                              "%s", key);
1061                 return NM_SETTING_UPDATE_SECRET_ERROR;
1062         }
1063
1064         /* Silently ignore non-secrets */
1065         if (!(prop_spec->flags & NM_SETTING_PARAM_SECRET))
1066                 return NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED;
1067
1068         if (g_value_type_compatible (G_VALUE_TYPE (value), G_PARAM_SPEC_VALUE_TYPE (prop_spec))) {
1069                 if (G_VALUE_HOLDS_STRING (value) && G_IS_PARAM_SPEC_STRING (prop_spec)) {
1070                         /* String is expected to be a common case. Handle it specially and check whether
1071                          * the value is already set. Otherwise, we just reset the property and
1072                          * assume the value got modified. */
1073                         char *v;
1074
1075                         g_object_get (G_OBJECT (setting), prop_spec->name, &v, NULL);
1076                         if (g_strcmp0 (v, g_value_get_string (value)) == 0) {
1077                                 g_free (v);
1078                                 return NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED;
1079                         }
1080                         g_free (v);
1081                 }
1082                 g_object_set_property (G_OBJECT (setting), prop_spec->name, value);
1083                 return NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED;
1084         }
1085         g_set_error (error,
1086                      NM_SETTING_ERROR,
1087                      NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH,
1088                      "%s", key);
1089         return NM_SETTING_UPDATE_SECRET_ERROR;
1090 }
1091
1092 /**
1093  * nm_setting_update_secrets:
1094  * @setting: the #NMSetting
1095  * @secrets: (element-type utf8 GObject.Value): a #GHashTable mapping
1096  * string to #GValue of setting property names and secrets
1097  * @error: location to store error, or %NULL
1098  *
1099  * Update the setting's secrets, given a hash table of secrets intended for that
1100  * setting (deserialized from D-Bus for example).
1101  *
1102  * Returns: %TRUE if the secrets were successfully updated, %FALSE on failure to
1103  * update one or more of the secrets.
1104  **/
1105 gboolean
1106 nm_setting_update_secrets (NMSetting *setting, GHashTable *secrets, GError **error)
1107 {
1108         return _nm_setting_update_secrets (setting, secrets, error) != NM_SETTING_UPDATE_SECRET_ERROR;
1109 }
1110
1111 NMSettingUpdateSecretResult
1112 _nm_setting_update_secrets (NMSetting *setting, GHashTable *secrets, GError **error)
1113 {
1114         GHashTableIter iter;
1115         gpointer key, data;
1116         GError *tmp_error = NULL;
1117         NMSettingUpdateSecretResult result = NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED;
1118
1119         g_return_val_if_fail (NM_IS_SETTING (setting), NM_SETTING_UPDATE_SECRET_ERROR);
1120         g_return_val_if_fail (secrets != NULL, NM_SETTING_UPDATE_SECRET_ERROR);
1121         if (error)
1122                 g_return_val_if_fail (*error == NULL, NM_SETTING_UPDATE_SECRET_ERROR);
1123
1124         g_hash_table_iter_init (&iter, secrets);
1125         while (g_hash_table_iter_next (&iter, &key, &data)) {
1126                 int success;
1127                 const char *secret_key = (const char *) key;
1128                 GValue *secret_value = (GValue *) data;
1129
1130                 success = NM_SETTING_GET_CLASS (setting)->update_one_secret (setting, secret_key, secret_value, &tmp_error);
1131                 g_assert (!((success == NM_SETTING_UPDATE_SECRET_ERROR) ^ (!!tmp_error)));
1132
1133                 if (success == NM_SETTING_UPDATE_SECRET_ERROR) {
1134                         g_propagate_error (error, tmp_error);
1135                         return NM_SETTING_UPDATE_SECRET_ERROR;
1136                 }
1137
1138                 if (success == NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED)
1139                         result = NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED;
1140         }
1141
1142         return result;
1143 }
1144
1145 static gboolean
1146 is_secret_prop (NMSetting *setting, const char *secret_name, GError **error)
1147 {
1148         GParamSpec *pspec;
1149
1150         pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), secret_name);
1151         if (!pspec) {
1152                 g_set_error (error,
1153                              NM_SETTING_ERROR,
1154                              NM_SETTING_ERROR_PROPERTY_NOT_FOUND,
1155                              "Secret %s not provided by this setting", secret_name);
1156                 return FALSE;
1157         }
1158
1159         if (!(pspec->flags & NM_SETTING_PARAM_SECRET)) {
1160                 g_set_error (error,
1161                              NM_SETTING_ERROR,
1162                              NM_SETTING_ERROR_PROPERTY_NOT_SECRET,
1163                              "Property %s is not a secret", secret_name);
1164                 return FALSE;
1165         }
1166
1167         return TRUE;
1168 }
1169
1170 static gboolean
1171 get_secret_flags (NMSetting *setting,
1172                   const char *secret_name,
1173                   gboolean verify_secret,
1174                   NMSettingSecretFlags *out_flags,
1175                   GError **error)
1176 {
1177         char *flags_prop;
1178         NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;
1179
1180         if (verify_secret && !is_secret_prop (setting, secret_name, error)) {
1181                 if (out_flags)
1182                         *out_flags = NM_SETTING_SECRET_FLAG_NONE;
1183                 return FALSE;
1184         }
1185
1186         flags_prop = g_strdup_printf ("%s-flags", secret_name);
1187         g_object_get (G_OBJECT (setting), flags_prop, &flags, NULL);
1188         g_free (flags_prop);
1189
1190         if (out_flags)
1191                 *out_flags = flags;
1192         return TRUE;
1193 }
1194
1195 /**
1196  * nm_setting_get_secret_flags:
1197  * @setting: the #NMSetting
1198  * @secret_name: the secret key name to get flags for
1199  * @out_flags: on success, the #NMSettingSecretFlags for the secret
1200  * @error: location to store error, or %NULL
1201  *
1202  * For a given secret, retrieves the #NMSettingSecretFlags describing how to
1203  * handle that secret.
1204  *
1205  * Returns: %TRUE on success (if the given secret name was a valid property of
1206  * this setting, and if that property is secret), %FALSE if not
1207  **/
1208 gboolean
1209 nm_setting_get_secret_flags (NMSetting *setting,
1210                              const char *secret_name,
1211                              NMSettingSecretFlags *out_flags,
1212                              GError **error)
1213 {
1214         g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
1215         g_return_val_if_fail (secret_name != NULL, FALSE);
1216
1217         return NM_SETTING_GET_CLASS (setting)->get_secret_flags (setting, secret_name, TRUE, out_flags, error);
1218 }
1219
1220 static gboolean
1221 set_secret_flags (NMSetting *setting,
1222                   const char *secret_name,
1223                   gboolean verify_secret,
1224                   NMSettingSecretFlags flags,
1225                   GError **error)
1226 {
1227         char *flags_prop;
1228
1229         if (verify_secret)
1230                 g_return_val_if_fail (is_secret_prop (setting, secret_name, error), FALSE);
1231
1232         flags_prop = g_strdup_printf ("%s-flags", secret_name);
1233         g_object_set (G_OBJECT (setting), flags_prop, flags, NULL);
1234         g_free (flags_prop);
1235         return TRUE;
1236 }
1237
1238 /**
1239  * nm_setting_set_secret_flags:
1240  * @setting: the #NMSetting
1241  * @secret_name: the secret key name to set flags for
1242  * @flags: the #NMSettingSecretFlags for the secret
1243  * @error: location to store error, or %NULL
1244  *
1245  * For a given secret, stores the #NMSettingSecretFlags describing how to
1246  * handle that secret.
1247  *
1248  * Returns: %TRUE on success (if the given secret name was a valid property of
1249  * this setting, and if that property is secret), %FALSE if not
1250  **/
1251 gboolean
1252 nm_setting_set_secret_flags (NMSetting *setting,
1253                              const char *secret_name,
1254                              NMSettingSecretFlags flags,
1255                              GError **error)
1256 {
1257         g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
1258         g_return_val_if_fail (secret_name != NULL, FALSE);
1259         g_return_val_if_fail (flags <= NM_SETTING_SECRET_FLAGS_ALL, FALSE);
1260
1261         return NM_SETTING_GET_CLASS (setting)->set_secret_flags (setting, secret_name, TRUE, flags, error);
1262 }
1263
1264 /**
1265  * nm_setting_to_string:
1266  * @setting: the #NMSetting
1267  *
1268  * Convert the setting into a string.  For debugging purposes ONLY, should NOT
1269  * be used for serialization of the setting, or machine-parsed in any way. The
1270  * output format is not guaranteed to be stable and may change at any time.
1271  *
1272  * Returns: an allocated string containing a textual representation of the
1273  * setting's properties and values (including secrets!), which the caller should
1274  * free with g_free()
1275  **/
1276 char *
1277 nm_setting_to_string (NMSetting *setting)
1278 {
1279         GString *string;
1280         GParamSpec **property_specs;
1281         guint n_property_specs;
1282         guint i;
1283
1284         g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
1285
1286         property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs);
1287
1288         string = g_string_new (nm_setting_get_name (setting));
1289         g_string_append_c (string, '\n');
1290
1291         for (i = 0; i < n_property_specs; i++) {
1292                 GParamSpec *prop_spec = property_specs[i];
1293                 GValue value = G_VALUE_INIT;
1294                 char *value_str;
1295                 gboolean is_default;
1296
1297                 if (strcmp (prop_spec->name, NM_SETTING_NAME) == 0)
1298                         continue;
1299
1300                 g_value_init (&value, prop_spec->value_type);
1301                 g_object_get_property (G_OBJECT (setting), prop_spec->name, &value);
1302
1303                 value_str = g_strdup_value_contents (&value);
1304                 g_string_append_printf (string, "\t%s : %s", prop_spec->name, value_str);
1305                 g_free (value_str);
1306
1307                 is_default = g_param_value_defaults (prop_spec, &value);
1308                 g_value_unset (&value);
1309
1310                 g_string_append (string, " (");
1311                 g_string_append_c (string, 's');
1312                 if (is_default)
1313                         g_string_append_c (string, 'd');
1314                 g_string_append_c (string, ')');
1315                 g_string_append_c (string, '\n');
1316         }
1317
1318         g_free (property_specs);
1319         g_string_append_c (string, '\n');
1320
1321         return g_string_free (string, FALSE);
1322 }
1323
1324 /**
1325  * nm_setting_get_virtual_iface_name:
1326  * @setting: the #NMSetting
1327  *
1328  * Returns the name of the virtual kernel interface which the connection
1329  * needs to use if specified in the settings.
1330  *
1331  * Returns: Name of the virtual interface or %NULL if the setting does not
1332  * support this feature
1333  **/
1334 const char *
1335 nm_setting_get_virtual_iface_name (NMSetting *setting)
1336 {
1337         g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
1338
1339         if (NM_SETTING_GET_CLASS (setting)->get_virtual_iface_name)
1340                 return NM_SETTING_GET_CLASS (setting)->get_virtual_iface_name (setting);
1341
1342         return NULL;
1343 }
1344
1345
1346 NMSettingVerifyResult
1347 _nm_setting_verify_deprecated_virtual_iface_name (const char *interface_name,
1348                                                   gboolean allow_missing,
1349                                                   const char *setting_name,
1350                                                   const char *setting_property,
1351                                                   GQuark error_quark,
1352                                                   gint e_invalid_property,
1353                                                   gint e_missing_property,
1354                                                   GSList *all_settings,
1355                                                   GError **error)
1356 {
1357         NMSettingConnection *s_con;
1358         const char *con_name;
1359
1360         s_con = NM_SETTING_CONNECTION (nm_setting_find_in_list (all_settings, NM_SETTING_CONNECTION_SETTING_NAME));
1361         con_name = s_con ? nm_setting_connection_get_interface_name (s_con) : NULL;
1362         if (!interface_name && !con_name) {
1363                 if (allow_missing)
1364                         return NM_SETTING_VERIFY_SUCCESS;
1365
1366                 g_set_error_literal (error,
1367                                      NM_SETTING_CONNECTION_ERROR,
1368                                      NM_SETTING_CONNECTION_ERROR_MISSING_PROPERTY,
1369                                      _("property is missing"));
1370                 g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_INTERFACE_NAME);
1371                 return NM_SETTING_VERIFY_ERROR;
1372         }
1373         if (!con_name && !nm_utils_iface_valid_name (interface_name)) {
1374                 /* the interface_name is invalid, we cannot normalize it. Only do this if !con_name,
1375                  * because if con_name is set, it can overwrite interface_name. */
1376                 g_set_error_literal (error,
1377                                      error_quark,
1378                                      e_invalid_property,
1379                                      _("property is invalid"));
1380                 g_prefix_error (error, "%s.%s: ", setting_name, setting_property);
1381                 return NM_SETTING_VERIFY_ERROR;
1382         }
1383         if (!con_name) {
1384                 /* NMSettingConnection has interface not set, it should be normalized to interface_name */
1385                 g_set_error_literal (error,
1386                                      NM_SETTING_CONNECTION_ERROR,
1387                                      NM_SETTING_CONNECTION_ERROR_MISSING_PROPERTY,
1388                                      _("property is missing"));
1389                 g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_INTERFACE_NAME);
1390                 return NM_SETTING_VERIFY_NORMALIZABLE;
1391         }
1392         if (!nm_utils_iface_valid_name (con_name)) {
1393                 /* NMSettingConnection:interface_name is invalid, we cannot normalize it. */
1394                 g_set_error_literal (error,
1395                                      NM_SETTING_CONNECTION_ERROR,
1396                                      NM_SETTING_CONNECTION_ERROR_INVALID_PROPERTY,
1397                                      _("property is invalid"));
1398                 g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_INTERFACE_NAME);
1399                 return NM_SETTING_VERIFY_ERROR;
1400         }
1401         if (!interface_name) {
1402                 /* Normalize by setting NMSettingConnection:interface_name. */
1403                 g_set_error_literal (error,
1404                                      error_quark,
1405                                      e_missing_property,
1406                                      _("property is missing"));
1407                 g_prefix_error (error, "%s.%s: ", setting_name, setting_property);
1408                 return NM_SETTING_VERIFY_NORMALIZABLE;
1409         }
1410         if (strcmp (con_name, interface_name) != 0) {
1411                 /* con_name and interface_name are different. It can be normalized by setting interface_name
1412                  * to con_name. */
1413                 g_set_error_literal (error,
1414                                      error_quark,
1415                                      e_invalid_property,
1416                                      _("property is invalid"));
1417                 g_prefix_error (error, "%s.%s: ", setting_name, setting_property);
1418                 /* we would like to make this a NORMALIZEABLE_ERROR, but that might
1419                  * break older connections. */
1420                 return NM_SETTING_VERIFY_NORMALIZABLE;
1421         }
1422
1423         return NM_SETTING_VERIFY_SUCCESS;
1424 }
1425
1426 /*****************************************************************************/
1427
1428 static void
1429 nm_setting_init (NMSetting *setting)
1430 {
1431 }
1432
1433 static GObject*
1434 constructor (GType type,
1435              guint n_construct_params,
1436              GObjectConstructParam *construct_params)
1437 {
1438         GObject *object;
1439
1440         object = G_OBJECT_CLASS (nm_setting_parent_class)->constructor (type,
1441                                                                         n_construct_params,
1442                                                                         construct_params);
1443
1444         _ensure_setting_info (object, NM_SETTING_GET_PRIVATE (object));
1445         return object;
1446 }
1447
1448 static void
1449 set_property (GObject *object, guint prop_id,
1450               const GValue *value, GParamSpec *pspec)
1451 {
1452         NMSettingPrivate *priv = NM_SETTING_GET_PRIVATE (object);
1453
1454         switch (prop_id) {
1455         case PROP_NAME:
1456                 /* The setter for NAME is deprecated and should not be used anymore.
1457                  * Keep the setter for NAME to remain backward compatible.
1458                  * Only assert that the caller does not try to set the name to a different value
1459                  * then the registered name, which would be extra wrong.
1460                  **/
1461                 _ensure_setting_info (object, priv);
1462                 g_return_if_fail (!g_strcmp0 (priv->info->name, g_value_get_string (value)));
1463                 break;
1464         default:
1465                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1466                 break;
1467         }
1468 }
1469
1470 static void
1471 get_property (GObject *object, guint prop_id,
1472               GValue *value, GParamSpec *pspec)
1473 {
1474         NMSetting *setting = NM_SETTING (object);
1475
1476         switch (prop_id) {
1477         case PROP_NAME:
1478                 g_value_set_string (value, nm_setting_get_name (setting));
1479                 break;
1480         default:
1481                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1482                 break;
1483         }
1484 }
1485
1486 static void
1487 nm_setting_class_init (NMSettingClass *setting_class)
1488 {
1489         GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
1490
1491         g_type_class_add_private (setting_class, sizeof (NMSettingPrivate));
1492
1493         /* virtual methods */
1494         object_class->constructor  = constructor;
1495         object_class->set_property = set_property;
1496         object_class->get_property = get_property;
1497
1498         setting_class->update_one_secret = update_one_secret;
1499         setting_class->get_secret_flags = get_secret_flags;
1500         setting_class->set_secret_flags = set_secret_flags;
1501         setting_class->compare_property = compare_property;
1502         setting_class->clear_secrets_with_flags = clear_secrets_with_flags;
1503
1504         /* Properties */
1505
1506         /**
1507          * NMSetting:name:
1508          *
1509          * The setting's name, which uniquely identifies the setting within the
1510          * connection.  Each setting type has a name unique to that type, for
1511          * example "ppp" or "wireless" or "wired".
1512          **/
1513         g_object_class_install_property
1514                 (object_class, PROP_NAME,
1515                  g_param_spec_string (NM_SETTING_NAME, "", "",
1516                                       NULL,
1517                                       G_PARAM_READWRITE |
1518                                       G_PARAM_STATIC_STRINGS));
1519 }