f0b2387bac14d7c148a31bb76dbf7d9fa9d5d299
[NetworkManager.git] / libnm-core / nm-connection.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 - 2013 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-connection.h"
28 #include "nm-connection-private.h"
29 #include "nm-utils.h"
30 #include "nm-setting-private.h"
31 #include "nm-core-internal.h"
32
33 /**
34  * SECTION:nm-connection
35  * @short_description: Describes a connection to specific network or provider
36  *
37  * An #NMConnection describes all the settings and configuration values that
38  * are necessary to configure network devices for operation on a specific
39  * network.  Connections are the fundamental operating object for
40  * NetworkManager; no device is connected without a #NMConnection, or
41  * disconnected without having been connected with a #NMConnection.
42  *
43  * Each #NMConnection contains a list of #NMSetting objects usually referenced
44  * by name (using nm_connection_get_setting_by_name()) or by type (with
45  * nm_connection_get_setting()).  The settings describe the actual parameters
46  * with which the network devices are configured, including device-specific
47  * parameters (MTU, SSID, APN, channel, rate, etc) and IP-level parameters
48  * (addresses, routes, addressing methods, etc).
49  *
50  */
51
52 typedef struct {
53         NMConnection *self;
54
55         GHashTable *settings;
56
57         /* D-Bus path of the connection, if any */
58         char *path;
59 } NMConnectionPrivate;
60
61 static NMConnectionPrivate *nm_connection_get_private (NMConnection *connection);
62 #define NM_CONNECTION_GET_PRIVATE(o) (nm_connection_get_private ((NMConnection *)o))
63
64 G_DEFINE_INTERFACE (NMConnection, nm_connection, G_TYPE_OBJECT)
65
66 enum {
67         SECRETS_UPDATED,
68         SECRETS_CLEARED,
69         CHANGED,
70         LAST_SIGNAL
71 };
72
73 static guint signals[LAST_SIGNAL] = { 0 };
74
75
76 static NMSettingVerifyResult _nm_connection_verify (NMConnection *connection, GError **error);
77
78
79 /*************************************************************/
80
81 static void
82 setting_changed_cb (NMSetting *setting,
83                     GParamSpec *pspec,
84                     NMConnection *self)
85 {
86         g_signal_emit (self, signals[CHANGED], 0);
87 }
88
89 static gboolean
90 _setting_release (gpointer key, gpointer value, gpointer user_data)
91 {
92         g_signal_handlers_disconnect_by_func (user_data, setting_changed_cb, value);
93         return TRUE;
94 }
95
96 static void
97 _nm_connection_add_setting (NMConnection *connection, NMSetting *setting)
98 {
99         NMConnectionPrivate *priv = NM_CONNECTION_GET_PRIVATE (connection);
100         const char *name = G_OBJECT_TYPE_NAME (setting);
101         NMSetting *s_old;
102
103         if ((s_old = g_hash_table_lookup (priv->settings, (gpointer) name)))
104                 g_signal_handlers_disconnect_by_func (s_old, setting_changed_cb, connection);
105         g_hash_table_insert (priv->settings, (gpointer) name, setting);
106         /* Listen for property changes so we can emit the 'changed' signal */
107         g_signal_connect (setting, "notify", (GCallback) setting_changed_cb, connection);
108 }
109
110 /**
111  * nm_connection_add_setting:
112  * @connection: a #NMConnection
113  * @setting: (transfer full): the #NMSetting to add to the connection object
114  *
115  * Adds a #NMSetting to the connection, replacing any previous #NMSetting of the
116  * same name which has previously been added to the #NMConnection.  The
117  * connection takes ownership of the #NMSetting object and does not increase
118  * the setting object's reference count.
119  **/
120 void
121 nm_connection_add_setting (NMConnection *connection, NMSetting *setting)
122 {
123         g_return_if_fail (NM_IS_CONNECTION (connection));
124         g_return_if_fail (NM_IS_SETTING (setting));
125
126         _nm_connection_add_setting (connection, setting);
127         g_signal_emit (connection, signals[CHANGED], 0);
128 }
129
130 /**
131  * nm_connection_remove_setting:
132  * @connection: a #NMConnection
133  * @setting_type: the #GType of the setting object to remove
134  *
135  * Removes the #NMSetting with the given #GType from the #NMConnection.  This
136  * operation dereferences the #NMSetting object.
137  **/
138 void
139 nm_connection_remove_setting (NMConnection *connection, GType setting_type)
140 {
141         NMConnectionPrivate *priv;
142         NMSetting *setting;
143         const char *setting_name;
144
145         g_return_if_fail (NM_IS_CONNECTION (connection));
146         g_return_if_fail (g_type_is_a (setting_type, NM_TYPE_SETTING));
147
148         priv = NM_CONNECTION_GET_PRIVATE (connection);
149         setting_name = g_type_name (setting_type);
150         setting = g_hash_table_lookup (priv->settings, setting_name);
151         if (setting) {
152                 g_signal_handlers_disconnect_by_func (setting, setting_changed_cb, connection);
153                 g_hash_table_remove (priv->settings, setting_name);
154                 g_signal_emit (connection, signals[CHANGED], 0);
155         }
156 }
157
158 /**
159  * nm_connection_get_setting:
160  * @connection: a #NMConnection
161  * @setting_type: the #GType of the setting object to return
162  *
163  * Gets the #NMSetting with the given #GType, if one has been previously added
164  * to the #NMConnection.
165  *
166  * Returns: (transfer none): the #NMSetting, or %NULL if no setting of that type was previously
167  * added to the #NMConnection
168  **/
169 NMSetting *
170 nm_connection_get_setting (NMConnection *connection, GType setting_type)
171 {
172         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
173         g_return_val_if_fail (g_type_is_a (setting_type, NM_TYPE_SETTING), NULL);
174
175         return (NMSetting *) g_hash_table_lookup (NM_CONNECTION_GET_PRIVATE (connection)->settings,
176                                                   g_type_name (setting_type));
177 }
178
179 /**
180  * nm_connection_get_setting_by_name:
181  * @connection: a #NMConnection
182  * @name: a setting name
183  *
184  * Gets the #NMSetting with the given name, if one has been previously added
185  * the #NMConnection.
186  *
187  * Returns: (transfer none): the #NMSetting, or %NULL if no setting with that name was previously
188  * added to the #NMConnection
189  **/
190 NMSetting *
191 nm_connection_get_setting_by_name (NMConnection *connection, const char *name)
192 {
193         GType type;
194
195         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
196         g_return_val_if_fail (name != NULL, NULL);
197
198         type = nm_setting_lookup_type (name);
199
200         return type ? nm_connection_get_setting (connection, type) : NULL;
201 }
202
203 static gboolean
204 validate_permissions_type (GVariant *variant, GError **error)
205 {
206         GVariant *s_con;
207         GVariant *permissions;
208         gboolean valid = TRUE;
209
210         /* Ensure the connection::permissions item (if present) is the correct
211          * type, otherwise the g_object_set() will throw a warning and ignore the
212          * error, leaving us with no permissions.
213          */
214         s_con = g_variant_lookup_value (variant, NM_SETTING_CONNECTION_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
215         if (!s_con)
216                 return TRUE;
217
218         permissions = g_variant_lookup_value (s_con, NM_SETTING_CONNECTION_PERMISSIONS, NULL);
219         if (permissions) {
220                 if (!g_variant_is_of_type (permissions, G_VARIANT_TYPE_STRING_ARRAY)) {
221                         g_set_error_literal (error,
222                                              NM_CONNECTION_ERROR,
223                                              NM_CONNECTION_ERROR_INVALID_PROPERTY,
224                                              _("wrong type; should be a list of strings."));
225                         g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_PERMISSIONS);
226                         valid = FALSE;
227                 }
228                 g_variant_unref (permissions);
229         }
230
231         g_variant_unref (s_con);
232         return valid;
233 }
234
235 /**
236  * _nm_connection_replace_settings:
237  * @connection: a #NMConnection
238  * @new_settings: a #GVariant of type %NM_VARIANT_TYPE_CONNECTION, with the new settings
239  * @parse_flags: flags.
240  * @error: location to store error, or %NULL
241  *
242  * Replaces @connection's settings with @new_settings (which must be
243  * syntactically valid, and describe a known type of connection, but does not
244  * need to result in a connection that passes nm_connection_verify()).
245  *
246  * Returns: %TRUE if connection was updated, %FALSE if @new_settings could not
247  *   be deserialized (in which case @connection will be unchanged).
248  **/
249 gboolean
250 _nm_connection_replace_settings (NMConnection *connection,
251                                  GVariant *new_settings,
252                                  NMSettingParseFlags parse_flags,
253                                  GError **error)
254 {
255         NMConnectionPrivate *priv;
256         GVariantIter iter;
257         const char *setting_name;
258         GVariant *setting_dict;
259         GSList *settings = NULL, *s;
260         gboolean changed;
261
262         g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
263         g_return_val_if_fail (g_variant_is_of_type (new_settings, NM_VARIANT_TYPE_CONNECTION), FALSE);
264         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
265
266         nm_assert (!NM_FLAGS_ANY (parse_flags, ~NM_SETTING_PARSE_FLAGS_ALL));
267         nm_assert (!NM_FLAGS_ALL (parse_flags, NM_SETTING_PARSE_FLAGS_STRICT | NM_SETTING_PARSE_FLAGS_BEST_EFFORT));
268
269         priv = NM_CONNECTION_GET_PRIVATE (connection);
270
271         if (   !NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_BEST_EFFORT)
272             && !validate_permissions_type (new_settings, error))
273                 return FALSE;
274
275         g_variant_iter_init (&iter, new_settings);
276         while (g_variant_iter_next (&iter, "{&s@a{sv}}", &setting_name, &setting_dict)) {
277                 gs_unref_variant GVariant *setting_dict_free = NULL;
278                 GError *local = NULL;
279                 NMSetting *setting;
280                 GType type;
281
282                 setting_dict_free = setting_dict;
283
284                 type = nm_setting_lookup_type (setting_name);
285                 if (type == G_TYPE_INVALID) {
286                         if (NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_BEST_EFFORT))
287                                 continue;
288                         g_set_error_literal (error,
289                                              NM_CONNECTION_ERROR,
290                                              NM_CONNECTION_ERROR_INVALID_SETTING,
291                                              _("unknown setting name"));
292                         g_prefix_error (error, "%s: ", setting_name);
293                         g_slist_free_full (settings, g_object_unref);
294                         return FALSE;
295                 }
296
297                 for (s = settings; s; s = s->next) {
298                         if (G_OBJECT_TYPE (s->data) == type) {
299                                 if (NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) {
300                                         g_set_error_literal (error,
301                                                              NM_CONNECTION_ERROR,
302                                                              NM_CONNECTION_ERROR_INVALID_SETTING,
303                                                              _("duplicate setting name"));
304                                         g_prefix_error (error, "%s: ", setting_name);
305                                         g_slist_free_full (settings, g_object_unref);
306                                         return FALSE;
307                                 }
308                                 /* last wins. */
309                                 g_object_unref (s->data);
310                                 settings = g_slist_delete_link (settings, s);
311                                 break;
312                         }
313                 }
314
315                 setting = _nm_setting_new_from_dbus (type, setting_dict, new_settings, parse_flags, &local);
316
317                 if (!setting) {
318                         if (NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_BEST_EFFORT))
319                                 continue;
320                         g_propagate_error (error, local);
321                         g_slist_free_full (settings, g_object_unref);
322                         return FALSE;
323                 }
324
325                 settings = g_slist_prepend (settings, setting);
326         }
327
328         if (g_hash_table_size (priv->settings) > 0) {
329                 g_hash_table_foreach_remove (priv->settings, _setting_release, connection);
330                 changed = TRUE;
331         } else
332                 changed = (settings != NULL);
333
334         /* Note: @settings might be empty in which case the connection
335          * has no NMSetting instances... which is fine, just something
336          * to be aware of. */
337         for (s = settings; s; s = s->next)
338                 _nm_connection_add_setting (connection, s->data);
339
340         g_slist_free (settings);
341
342         if (changed)
343                 g_signal_emit (connection, signals[CHANGED], 0);
344         return TRUE;
345 }
346
347 /**
348  * nm_connection_replace_settings:
349  * @connection: a #NMConnection
350  * @new_settings: a #GVariant of type %NM_VARIANT_TYPE_CONNECTION, with the new settings
351  * @error: location to store error, or %NULL
352  *
353  * Replaces @connection's settings with @new_settings (which must be
354  * syntactically valid, and describe a known type of connection, but does not
355  * need to result in a connection that passes nm_connection_verify()).
356  *
357  * Returns: %TRUE if connection was updated, %FALSE if @new_settings could not
358  *   be deserialized (in which case @connection will be unchanged).
359  **/
360 gboolean
361 nm_connection_replace_settings (NMConnection *connection,
362                                 GVariant *new_settings,
363                                 GError **error)
364 {
365         return _nm_connection_replace_settings (connection, new_settings, NM_SETTING_PARSE_FLAGS_NONE, error);
366 }
367
368 /**
369  * nm_connection_replace_settings_from_connection:
370  * @connection: a #NMConnection
371  * @new_connection: a #NMConnection to replace the settings of @connection with
372  *
373  * Deep-copies the settings of @new_connection and replaces the settings of @connection
374  * with the copied settings.
375  **/
376 void
377 nm_connection_replace_settings_from_connection (NMConnection *connection,
378                                                 NMConnection *new_connection)
379 {
380         NMConnectionPrivate *priv, *new_priv;
381         GHashTableIter iter;
382         NMSetting *setting;
383         gboolean changed;
384
385         g_return_if_fail (NM_IS_CONNECTION (connection));
386         g_return_if_fail (NM_IS_CONNECTION (new_connection));
387
388         /* When 'connection' and 'new_connection' are the same object simply return
389          * in order not to destroy 'connection'.
390          */
391         if (connection == new_connection)
392                 return;
393
394         /* No need to validate permissions like nm_connection_replace_settings()
395          * since we're dealing with an NMConnection which has already done that.
396          */
397
398         priv = NM_CONNECTION_GET_PRIVATE (connection);
399         new_priv = NM_CONNECTION_GET_PRIVATE (new_connection);
400
401         if ((changed = g_hash_table_size (priv->settings) > 0))
402                 g_hash_table_foreach_remove (priv->settings, _setting_release, connection);
403
404         if (g_hash_table_size (new_priv->settings)) {
405                 g_hash_table_iter_init (&iter, new_priv->settings);
406                 while (g_hash_table_iter_next (&iter, NULL, (gpointer) &setting))
407                         _nm_connection_add_setting (connection, nm_setting_duplicate (setting));
408                 changed = TRUE;
409         }
410
411         if (changed)
412                 g_signal_emit (connection, signals[CHANGED], 0);
413 }
414
415 /**
416  * nm_connection_clear_settings:
417  * @connection: a #NMConnection
418  *
419  * Deletes all of @connection's settings.
420  **/
421 void
422 nm_connection_clear_settings (NMConnection *connection)
423 {
424         NMConnectionPrivate *priv;
425
426         g_return_if_fail (NM_IS_CONNECTION (connection));
427
428         priv = NM_CONNECTION_GET_PRIVATE (connection);
429
430         if (g_hash_table_size (priv->settings) > 0) {
431                 g_hash_table_foreach_remove (priv->settings, _setting_release, connection);
432                 g_signal_emit (connection, signals[CHANGED], 0);
433         }
434 }
435
436 /**
437  * nm_connection_compare:
438  * @a: a #NMConnection
439  * @b: a second #NMConnection to compare with the first
440  * @flags: compare flags, e.g. %NM_SETTING_COMPARE_FLAG_EXACT
441  *
442  * Compares two #NMConnection objects for similarity, with comparison behavior
443  * modified by a set of flags.  See nm_setting_compare() for a description of
444  * each flag's behavior.
445  *
446  * Returns: %TRUE if the comparison succeeds, %FALSE if it does not
447  **/
448 gboolean
449 nm_connection_compare (NMConnection *a,
450                        NMConnection *b,
451                        NMSettingCompareFlags flags)
452 {
453         GHashTableIter iter;
454         NMSetting *src;
455
456         if (a == b)
457                 return TRUE;
458         if (!a || !b)
459                 return FALSE;
460
461         /* B / A: ensure settings in B that are not in A make the comparison fail */
462         if (g_hash_table_size (NM_CONNECTION_GET_PRIVATE (a)->settings) !=
463             g_hash_table_size (NM_CONNECTION_GET_PRIVATE (b)->settings))
464                 return FALSE;
465
466         /* A / B: ensure all settings in A match corresponding ones in B */
467         g_hash_table_iter_init (&iter, NM_CONNECTION_GET_PRIVATE (a)->settings);
468         while (g_hash_table_iter_next (&iter, NULL, (gpointer) &src)) {
469                 NMSetting *cmp = nm_connection_get_setting (b, G_OBJECT_TYPE (src));
470
471                 if (!cmp || !nm_setting_compare (src, cmp, flags))
472                         return FALSE;
473         }
474
475         return TRUE;
476 }
477
478
479 static void
480 diff_one_connection (NMConnection *a,
481                      NMConnection *b,
482                      NMSettingCompareFlags flags,
483                      gboolean invert_results,
484                      GHashTable *diffs)
485 {
486         NMConnectionPrivate *priv = NM_CONNECTION_GET_PRIVATE (a);
487         GHashTableIter iter;
488         NMSetting *a_setting = NULL;
489
490         g_hash_table_iter_init (&iter, priv->settings);
491         while (g_hash_table_iter_next (&iter, NULL, (gpointer) &a_setting)) {
492                 NMSetting *b_setting = NULL;
493                 const char *setting_name = nm_setting_get_name (a_setting);
494                 GHashTable *results;
495                 gboolean new_results = TRUE;
496
497                 if (b)
498                         b_setting = nm_connection_get_setting (b, G_OBJECT_TYPE (a_setting));
499
500                 results = g_hash_table_lookup (diffs, setting_name);
501                 if (results)
502                         new_results = FALSE;
503
504                 if (!nm_setting_diff (a_setting, b_setting, flags, invert_results, &results)) {
505                         if (new_results)
506                                 g_hash_table_insert (diffs, g_strdup (setting_name), results);
507                 }
508         }
509 }
510
511 /**
512  * nm_connection_diff:
513  * @a: a #NMConnection
514  * @b: a second #NMConnection to compare with the first
515  * @flags: compare flags, e.g. %NM_SETTING_COMPARE_FLAG_EXACT
516  * @out_settings: (element-type utf8 GLib.HashTable): if the
517  * connections differ, on return a hash table mapping setting names to
518  * second-level GHashTable (utf8 to guint32), which contains the key names that
519  * differ mapped to one or more of %NMSettingDiffResult as a bitfield
520  *
521  * Compares two #NMConnection objects for similarity, with comparison behavior
522  * modified by a set of flags.  See nm_setting_compare() for a description of
523  * each flag's behavior.  If the connections differ, settings and keys within
524  * each setting that differ are added to the returned @out_settings hash table.
525  * No values are returned, only key names.
526  *
527  * Returns: %TRUE if the connections contain the same values, %FALSE if they do
528  * not
529  **/
530 gboolean
531 nm_connection_diff (NMConnection *a,
532                     NMConnection *b,
533                     NMSettingCompareFlags flags,
534                     GHashTable **out_settings)
535 {
536         GHashTable *diffs;
537
538         g_return_val_if_fail (NM_IS_CONNECTION (a), FALSE);
539         g_return_val_if_fail (out_settings != NULL, FALSE);
540         g_return_val_if_fail (*out_settings == NULL, FALSE);
541         if (b)
542                 g_return_val_if_fail (NM_IS_CONNECTION (b), FALSE);
543
544         if (a == b)
545                 return TRUE;
546
547         diffs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_hash_table_destroy);
548
549         /* Diff A to B, then B to A to capture keys in B that aren't in A */
550         diff_one_connection (a, b, flags, FALSE, diffs);
551         if (b)
552                 diff_one_connection (b, a, flags, TRUE, diffs);
553
554         if (g_hash_table_size (diffs) == 0)
555                 g_hash_table_destroy (diffs);
556         else
557                 *out_settings = diffs;
558
559         return *out_settings ? FALSE : TRUE;
560 }
561
562 NMSetting *
563 _nm_connection_find_base_type_setting (NMConnection *connection)
564 {
565         NMConnectionPrivate *priv = NM_CONNECTION_GET_PRIVATE (connection);
566         GHashTableIter iter;
567         NMSetting *setting = NULL, *s_iter;
568
569         g_hash_table_iter_init (&iter, priv->settings);
570         while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &s_iter)) {
571                 if (!_nm_setting_is_base_type (s_iter))
572                         continue;
573
574                 if (setting) {
575                         /* FIXME: currently, if there is more than one matching base type,
576                          * we cannot detect the base setting.
577                          * See: https://bugzilla.gnome.org/show_bug.cgi?id=696936#c8 */
578                         return NULL;
579                 }
580                 setting = s_iter;
581         }
582         return setting;
583 }
584
585 static gboolean
586 _normalize_connection_uuid (NMConnection *self)
587 {
588         NMSettingConnection *s_con = nm_connection_get_setting_connection (self);
589         char *uuid;
590
591         g_assert (s_con);
592
593         if (nm_setting_connection_get_uuid (s_con))
594                 return FALSE;
595
596         uuid = nm_utils_uuid_generate ();
597         g_object_set (s_con, NM_SETTING_CONNECTION_UUID, uuid, NULL);
598         g_free (uuid);
599
600         return TRUE;
601 }
602
603 static gboolean
604 _normalize_connection_type (NMConnection *self)
605 {
606         NMSettingConnection *s_con = nm_connection_get_setting_connection (self);
607         NMSetting *s_base = NULL;
608         const char *type;
609
610         type = nm_setting_connection_get_connection_type (s_con);
611
612         if (type) {
613                 s_base = nm_connection_get_setting_by_name (self, type);
614
615                 if (!s_base) {
616                         GType base_type = nm_setting_lookup_type (type);
617
618                         g_return_val_if_fail (base_type, FALSE);
619                         nm_connection_add_setting (self, g_object_new (base_type, NULL));
620                         return TRUE;
621                 }
622         } else {
623                 s_base =  _nm_connection_find_base_type_setting (self);
624                 g_return_val_if_fail (s_base, FALSE);
625
626                 type = nm_setting_get_name (s_base);
627                 g_object_set (s_con, NM_SETTING_CONNECTION_TYPE, type, NULL);
628                 return TRUE;
629         }
630
631         return FALSE;
632 }
633
634 const char *
635 _nm_connection_detect_slave_type (NMConnection *connection, NMSetting **out_s_port)
636 {
637         NMConnectionPrivate *priv = NM_CONNECTION_GET_PRIVATE (connection);
638         GHashTableIter iter;
639         const char *slave_type = NULL;
640         NMSetting *s_port = NULL, *s_iter;
641
642         g_hash_table_iter_init (&iter, priv->settings);
643         while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &s_iter)) {
644                 const char *name = nm_setting_get_name (s_iter);
645                 const char *i_slave_type = NULL;
646
647                 if (!strcmp (name, NM_SETTING_BRIDGE_PORT_SETTING_NAME))
648                         i_slave_type = NM_SETTING_BRIDGE_SETTING_NAME;
649                 else if (!strcmp (name, NM_SETTING_TEAM_PORT_SETTING_NAME))
650                         i_slave_type = NM_SETTING_TEAM_SETTING_NAME;
651                 else
652                         continue;
653
654                 if (slave_type) {
655                         /* there are more then one matching port types, cannot detect the slave type. */
656                         slave_type = NULL;
657                         s_port = NULL;
658                         break;
659                 }
660                 slave_type = i_slave_type;
661                 s_port = s_iter;
662         }
663
664         if (out_s_port)
665                 *out_s_port = s_port;
666         return slave_type;
667 }
668
669 static gboolean
670 _normalize_connection_slave_type (NMConnection *self)
671 {
672         NMSettingConnection *s_con = nm_connection_get_setting_connection (self);
673         const char *slave_type, *port_type;
674
675         if (!s_con)
676                 return FALSE;
677         if (!nm_setting_connection_get_master (s_con))
678                 return FALSE;
679
680         slave_type = nm_setting_connection_get_slave_type (s_con);
681         if (slave_type) {
682                 if (   _nm_setting_slave_type_is_valid (slave_type, &port_type)
683                     && port_type) {
684                         NMSetting *s_port;
685
686                         s_port = nm_connection_get_setting_by_name (self, port_type);
687                         if (!s_port) {
688                                 GType p_type = nm_setting_lookup_type (port_type);
689
690                                 g_return_val_if_fail (p_type, FALSE);
691                                 nm_connection_add_setting (self, g_object_new (p_type, NULL));
692                                 return TRUE;
693                         }
694                 }
695         } else {
696                 if ((slave_type = _nm_connection_detect_slave_type (self, NULL))) {
697                         g_object_set (s_con, NM_SETTING_CONNECTION_SLAVE_TYPE, slave_type, NULL);
698                         return TRUE;
699                 }
700         }
701         return FALSE;
702 }
703
704 static gboolean
705 _normalize_ip_config (NMConnection *self, GHashTable *parameters)
706 {
707         NMSettingConnection *s_con = nm_connection_get_setting_connection (self);
708         const char *default_ip4_method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
709         const char *default_ip6_method = NULL;
710         NMSettingIPConfig *s_ip4, *s_ip6;
711         NMSetting *setting;
712
713         if (parameters)
714                 default_ip6_method = g_hash_table_lookup (parameters, NM_CONNECTION_NORMALIZE_PARAM_IP6_CONFIG_METHOD);
715         if (!default_ip6_method)
716                 default_ip6_method = NM_SETTING_IP6_CONFIG_METHOD_AUTO;
717
718         s_ip4 = nm_connection_get_setting_ip4_config (self);
719         s_ip6 = nm_connection_get_setting_ip6_config (self);
720
721         if (nm_setting_connection_get_master (s_con)) {
722                 /* Slave connections don't have IP configuration. */
723
724                 if (s_ip4)
725                         nm_connection_remove_setting (self, NM_TYPE_SETTING_IP4_CONFIG);
726
727                 if (s_ip6)
728                         nm_connection_remove_setting (self, NM_TYPE_SETTING_IP6_CONFIG);
729
730                 return s_ip4 || s_ip6;
731         } else {
732                 /* Ensure all non-slave connections have IP4 and IP6 settings objects. If no
733                  * IP6 setting was specified, then assume that means IP6 config is allowed
734                  * to fail. But if no IP4 setting was specified, assume the caller was just
735                  * being lazy.
736                  */
737                 if (!s_ip4) {
738                         setting = nm_setting_ip4_config_new ();
739
740                         g_object_set (setting,
741                                       NM_SETTING_IP_CONFIG_METHOD, default_ip4_method,
742                                       NULL);
743                         nm_connection_add_setting (self, setting);
744                 }
745                 if (!s_ip6) {
746                         setting = nm_setting_ip6_config_new ();
747
748                         g_object_set (setting,
749                                       NM_SETTING_IP_CONFIG_METHOD, default_ip6_method,
750                                       NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
751                                       NULL);
752                         nm_connection_add_setting (self, setting);
753                 }
754                 return !s_ip4 || !s_ip6;
755         }
756 }
757
758 static gboolean
759 _normalize_infiniband_mtu (NMConnection *self, GHashTable *parameters)
760 {
761         NMSettingInfiniband *s_infini = nm_connection_get_setting_infiniband (self);
762
763         if (s_infini) {
764                 const char *transport_mode = nm_setting_infiniband_get_transport_mode (s_infini);
765                 guint32 max_mtu = 0;
766
767                 if (transport_mode) {
768                         if (!strcmp (transport_mode, "datagram"))
769                                 max_mtu = 2044;
770                         else if (!strcmp (transport_mode, "connected"))
771                                 max_mtu = 65520;
772
773                         if (max_mtu && nm_setting_infiniband_get_mtu (s_infini) > max_mtu) {
774                                 g_object_set (s_infini, NM_SETTING_INFINIBAND_MTU, max_mtu, NULL);
775                                 return TRUE;
776                         }
777                 }
778         }
779         return FALSE;
780 }
781
782 static gboolean
783 _normalize_bond_mode (NMConnection *self, GHashTable *parameters)
784 {
785         NMSettingBond *s_bond = nm_connection_get_setting_bond (self);
786
787         /* Convert mode from numeric to string notation */
788         if (s_bond) {
789                 const char *mode = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_MODE);
790                 int mode_int = nm_utils_bond_mode_string_to_int (mode);
791
792                 if (mode_int != -1) {
793                         const char *mode_new = nm_utils_bond_mode_int_to_string (mode_int);
794                         if (g_strcmp0 (mode_new, mode) != 0) {
795                                 nm_setting_bond_add_option (s_bond, NM_SETTING_BOND_OPTION_MODE, mode_new);
796                                 return TRUE;
797                         }
798                 }
799         }
800         return FALSE;
801 }
802
803 /**
804  * nm_connection_verify:
805  * @connection: the #NMConnection to verify
806  * @error: location to store error, or %NULL
807  *
808  * Validates the connection and all its settings.  Each setting's properties
809  * have allowed values, and some values are dependent on other values.  For
810  * example, if a Wi-Fi connection is security enabled, the #NMSettingWireless
811  * setting object's 'security' property must contain the setting name of the
812  * #NMSettingWirelessSecurity object, which must also be present in the
813  * connection for the connection to be valid.  As another example, the
814  * #NMSettingWired object's 'mac-address' property must be a validly formatted
815  * MAC address.  The returned #GError contains information about which
816  * setting and which property failed validation, and how it failed validation.
817  *
818  * Returns: %TRUE if the connection is valid, %FALSE if it is not
819  **/
820 gboolean
821 nm_connection_verify (NMConnection *connection, GError **error)
822 {
823         NMSettingVerifyResult result;
824
825         result = _nm_connection_verify (connection, error);
826
827         /* we treat normalizable connections as valid. */
828         if (result == NM_SETTING_VERIFY_NORMALIZABLE)
829                 g_clear_error (error);
830
831         return result == NM_SETTING_VERIFY_SUCCESS || result == NM_SETTING_VERIFY_NORMALIZABLE;
832 }
833
834 static NMSettingVerifyResult
835 _nm_connection_verify (NMConnection *connection, GError **error)
836 {
837         NMConnectionPrivate *priv;
838         NMSettingConnection *s_con;
839         NMSettingIPConfig *s_ip4, *s_ip6;
840         GHashTableIter iter;
841         gpointer value;
842         GSList *all_settings = NULL, *setting_i;
843         NMSettingVerifyResult success = NM_SETTING_VERIFY_ERROR;
844         GError *normalizable_error = NULL;
845         NMSettingVerifyResult normalizable_error_type = NM_SETTING_VERIFY_SUCCESS;
846
847         g_return_val_if_fail (NM_IS_CONNECTION (connection), NM_SETTING_VERIFY_ERROR);
848         g_return_val_if_fail (!error || !*error, NM_SETTING_VERIFY_ERROR);
849
850         priv = NM_CONNECTION_GET_PRIVATE (connection);
851
852         /* First, make sure there's at least 'connection' setting */
853         s_con = nm_connection_get_setting_connection (connection);
854         if (!s_con) {
855                 g_set_error_literal (error,
856                                      NM_CONNECTION_ERROR,
857                                      NM_CONNECTION_ERROR_MISSING_SETTING,
858                                      _("setting not found"));
859                 g_prefix_error (error, "%s: ", NM_SETTING_CONNECTION_SETTING_NAME);
860                 goto EXIT;
861         }
862
863         /* Build up the list of settings */
864         g_hash_table_iter_init (&iter, priv->settings);
865         while (g_hash_table_iter_next (&iter, NULL, &value)) {
866                 /* Order NMSettingConnection so that it will be verified first.
867                  * The reason is, that errors in this setting might be more fundamental
868                  * and should be checked and reported with higher priority.
869                  */
870                 if (value == s_con)
871                         all_settings = g_slist_append (all_settings, value);
872                 else
873                         all_settings = g_slist_prepend (all_settings, value);
874         }
875         all_settings = g_slist_reverse (all_settings);
876
877         /* Now, run the verify function of each setting */
878         for (setting_i = all_settings; setting_i; setting_i = setting_i->next) {
879                 GError *verify_error = NULL;
880                 NMSettingVerifyResult verify_result;
881
882                 /* verify all settings. We stop if we find the first non-normalizable
883                  * @NM_SETTING_VERIFY_ERROR. If we find normalizable errors we continue
884                  * but remember the error to return it to the user.
885                  * @NM_SETTING_VERIFY_NORMALIZABLE_ERROR has a higher priority then
886                  * @NM_SETTING_VERIFY_NORMALIZABLE, so, if we encounter such an error type,
887                  * we remember it instead (to return it as output).
888                  **/
889                 verify_result = _nm_setting_verify (NM_SETTING (setting_i->data), connection, &verify_error);
890                 if (verify_result == NM_SETTING_VERIFY_NORMALIZABLE ||
891                     verify_result == NM_SETTING_VERIFY_NORMALIZABLE_ERROR) {
892                         if (   verify_result == NM_SETTING_VERIFY_NORMALIZABLE_ERROR
893                             && normalizable_error_type == NM_SETTING_VERIFY_NORMALIZABLE) {
894                                 /* NORMALIZABLE_ERROR has higher priority. */
895                                 g_clear_error (&normalizable_error);
896                         }
897                         if (!normalizable_error) {
898                                 g_propagate_error (&normalizable_error, verify_error);
899                                 verify_error = NULL;
900                                 normalizable_error_type = verify_result;
901                         }
902                 } else if (verify_result != NM_SETTING_VERIFY_SUCCESS) {
903                         g_propagate_error (error, verify_error);
904                         g_slist_free (all_settings);
905                         g_return_val_if_fail (verify_result == NM_SETTING_VERIFY_ERROR, success);
906                         goto EXIT;
907                 }
908                 g_clear_error (&verify_error);
909         }
910         g_slist_free (all_settings);
911
912         s_ip4 = nm_connection_get_setting_ip4_config (connection);
913         s_ip6 = nm_connection_get_setting_ip6_config (connection);
914
915         if (nm_setting_connection_get_master (s_con)) {
916                 if ((normalizable_error_type == NM_SETTING_VERIFY_SUCCESS ||
917                     (normalizable_error_type == NM_SETTING_VERIFY_NORMALIZABLE))  && (s_ip4 || s_ip6)) {
918                         g_clear_error (&normalizable_error);
919                         g_set_error_literal (&normalizable_error,
920                                              NM_CONNECTION_ERROR,
921                                              NM_CONNECTION_ERROR_INVALID_SETTING,
922                                              _("setting not allowed in slave connection"));
923                         g_prefix_error (&normalizable_error, "%s: ",
924                                         s_ip4 ? NM_SETTING_IP4_CONFIG_SETTING_NAME : NM_SETTING_IP6_CONFIG_SETTING_NAME);
925                         /* having a slave with IP config *was* and is a verify() error. */
926                         normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE_ERROR;
927                 }
928         } else {
929                 if (normalizable_error_type == NM_SETTING_VERIFY_SUCCESS && (!s_ip4 || !s_ip6)) {
930                         g_set_error_literal (&normalizable_error,
931                                              NM_CONNECTION_ERROR,
932                                              NM_CONNECTION_ERROR_MISSING_SETTING,
933                                              _("setting is required for non-slave connections"));
934                         g_prefix_error (&normalizable_error, "%s: ",
935                                         !s_ip4 ? NM_SETTING_IP4_CONFIG_SETTING_NAME : NM_SETTING_IP6_CONFIG_SETTING_NAME);
936                         /* having a master without IP config was not a verify() error, accept
937                          * it for backward compatibility. */
938                         normalizable_error_type = NM_SETTING_VERIFY_NORMALIZABLE;
939                 }
940         }
941
942         if (normalizable_error_type != NM_SETTING_VERIFY_SUCCESS) {
943                 g_propagate_error (error, normalizable_error);
944                 normalizable_error = NULL;
945                 success = normalizable_error_type;
946         } else
947                 success = NM_SETTING_VERIFY_SUCCESS;
948
949 EXIT:
950         g_clear_error (&normalizable_error);
951         return success;
952 }
953
954 /**
955  * nm_connection_verify_secrets:
956  * @connection: the #NMConnection to verify in
957  * @error: location to store error, or %NULL
958  *
959  * Verifies the secrets in the connection.
960  *
961  * Returns: %TRUE if the secrets are valid, %FALSE if they are not
962  *
963  * Since: 1.2
964  **/
965 gboolean
966 nm_connection_verify_secrets (NMConnection *connection, GError **error)
967 {
968         GHashTableIter iter;
969         NMSetting *setting;
970
971         g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
972         g_return_val_if_fail (!error || !*error, FALSE);
973
974         g_hash_table_iter_init (&iter, NM_CONNECTION_GET_PRIVATE (connection)->settings);
975         while (g_hash_table_iter_next (&iter, NULL, (gpointer) &setting)) {
976                 if (!nm_setting_verify_secrets (setting, connection, error))
977                         return FALSE;
978         }
979         return TRUE;
980 }
981
982 /**
983  * nm_connection_normalize:
984  * @connection: the #NMConnection to normalize
985  * @parameters: (allow-none) (element-type utf8 gpointer): a #GHashTable with
986  * normalization parameters to allow customization of the normalization by providing
987  * specific arguments. Unknown arguments will be ignored and the default will be
988  * used. The keys must be strings, hashed by g_str_hash() and g_str_equal() functions.
989  * The values are opaque and depend on the parameter name.
990  * @modified: (out) (allow-none): outputs whether any settings were modified.
991  * @error: location to store error, or %NULL. Contains the reason,
992  * why the connection is invalid, if the function returns an error.
993  *
994  * Does some basic normalization and fixup of well known inconsistencies
995  * and deprecated fields. If the connection was modified in any way,
996  * the output parameter @modified is set %TRUE.
997  *
998  * Finally the connection will be verified and %TRUE returns if the connection
999  * is valid. As this function only performs some specific normalization steps
1000  * it cannot repair all connections. If the connection has errors that
1001  * cannot be normalized, the connection will not be modified.
1002  *
1003  * Returns: %TRUE if the connection is valid, %FALSE if it is not
1004  **/
1005 gboolean
1006 nm_connection_normalize (NMConnection *connection,
1007                          GHashTable *parameters,
1008                          gboolean *modified,
1009                          GError **error)
1010 {
1011         NMSettingVerifyResult success;
1012         gboolean was_modified = FALSE;
1013         GError *normalizable_error = NULL;
1014
1015         success = _nm_connection_verify (connection, &normalizable_error);
1016
1017         if (success == NM_SETTING_VERIFY_ERROR ||
1018             success == NM_SETTING_VERIFY_SUCCESS) {
1019                 if (normalizable_error)
1020                         g_propagate_error (error, normalizable_error);
1021                 if (modified)
1022                         *modified = FALSE;
1023                 if (success == NM_SETTING_VERIFY_ERROR && error && !*error) {
1024                         g_set_error_literal (error,
1025                                              NM_CONNECTION_ERROR,
1026                                              NM_CONNECTION_ERROR_FAILED,
1027                                              _("Unexpected failure to verify the connection"));
1028                         g_return_val_if_reached (FALSE);
1029                 }
1030                 return success == NM_SETTING_VERIFY_SUCCESS;
1031         }
1032         g_assert (success == NM_SETTING_VERIFY_NORMALIZABLE || success == NM_SETTING_VERIFY_NORMALIZABLE_ERROR);
1033         g_clear_error (&normalizable_error);
1034
1035         /* Try to perform all kind of normalizations on the settings to fix it.
1036          * We only do this, after verifying that the connection contains no un-normalizable
1037          * errors, because in that case we rather fail without touching the settings. */
1038
1039         was_modified |= _normalize_connection_uuid (connection);
1040         was_modified |= _normalize_connection_type (connection);
1041         was_modified |= _normalize_connection_slave_type (connection);
1042         was_modified |= _normalize_ip_config (connection, parameters);
1043         was_modified |= _normalize_infiniband_mtu (connection, parameters);
1044         was_modified |= _normalize_bond_mode (connection, parameters);
1045
1046         /* Verify anew. */
1047         success = _nm_connection_verify (connection, error);
1048
1049         if (modified)
1050                 *modified = was_modified;
1051
1052         if (success != NM_SETTING_VERIFY_SUCCESS) {
1053                 /* we would expect, that after normalization, the connection can be verified.
1054                  * Also treat NM_SETTING_VERIFY_NORMALIZABLE as failure, because there is something
1055                  * odd going on. */
1056                 if (error && !*error) {
1057                         g_set_error_literal (error,
1058                                              NM_CONNECTION_ERROR,
1059                                              NM_CONNECTION_ERROR_FAILED,
1060                                              _("Unexpected failure to normalize the connection"));
1061                 }
1062                 g_return_val_if_reached (FALSE);
1063         }
1064
1065         /* we would expect, that the connection was modified during normalization. */
1066         g_return_val_if_fail (was_modified, TRUE);
1067
1068         return TRUE;
1069 }
1070
1071 /**
1072  * nm_connection_update_secrets:
1073  * @connection: the #NMConnection
1074  * @setting_name: the setting object name to which the secrets apply
1075  * @secrets: a #GVariant of secrets, of type %NM_VARIANT_TYPE_CONNECTION
1076  *   or %NM_VARIANT_TYPE_SETTING
1077  * @error: location to store error, or %NULL
1078  *
1079  * Update the specified setting's secrets, given a dictionary of secrets
1080  * intended for that setting (deserialized from D-Bus for example).  Will also
1081  * extract the given setting's secrets hash if given a connection dictionary.
1082  * If @setting_name is %NULL, expects a fully serialized #NMConnection as
1083  * returned by nm_connection_to_dbus() and will update all secrets from all
1084  * settings contained in @secrets.
1085  *
1086  * Returns: %TRUE if the secrets were successfully updated, %FALSE if the update
1087  * failed (tried to update secrets for a setting that doesn't exist, etc)
1088  **/
1089 gboolean
1090 nm_connection_update_secrets (NMConnection *connection,
1091                               const char *setting_name,
1092                               GVariant *secrets,
1093                               GError **error)
1094 {
1095         NMSetting *setting;
1096         gboolean success = TRUE, updated = FALSE;
1097         GVariant *setting_dict = NULL;
1098         GVariantIter iter;
1099         const char *key;
1100         gboolean full_connection;
1101         int success_detail;
1102
1103         g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
1104         g_return_val_if_fail (   g_variant_is_of_type (secrets, NM_VARIANT_TYPE_SETTING)
1105                               || g_variant_is_of_type (secrets, NM_VARIANT_TYPE_CONNECTION), FALSE);
1106         if (error)
1107                 g_return_val_if_fail (*error == NULL, FALSE);
1108
1109         full_connection = g_variant_is_of_type (secrets, NM_VARIANT_TYPE_CONNECTION);
1110         g_return_val_if_fail (setting_name != NULL || full_connection, FALSE);
1111
1112         /* Empty @secrets means success */
1113         if (g_variant_n_children (secrets) == 0)
1114                 return TRUE;
1115
1116         if (setting_name) {
1117                 /* Update just one setting's secrets */
1118                 setting = nm_connection_get_setting_by_name (connection, setting_name);
1119                 if (!setting) {
1120                         g_set_error_literal (error,
1121                                              NM_CONNECTION_ERROR,
1122                                              NM_CONNECTION_ERROR_SETTING_NOT_FOUND,
1123                                              setting_name);
1124                         return FALSE;
1125                 }
1126
1127                 if (full_connection) {
1128                         setting_dict = g_variant_lookup_value (secrets, setting_name, NM_VARIANT_TYPE_SETTING);
1129                         if (!setting_dict) {
1130                                 /* The connection dictionary didn't contain any secrets for
1131                                  * @setting_name; just return success.
1132                                  */
1133                                 return TRUE;
1134                         }
1135                 }
1136
1137                 g_signal_handlers_block_by_func (setting, (GCallback) setting_changed_cb, connection);
1138                 success_detail = _nm_setting_update_secrets (setting,
1139                                                              setting_dict ? setting_dict : secrets,
1140                                                              error);
1141                 g_signal_handlers_unblock_by_func (setting, (GCallback) setting_changed_cb, connection);
1142
1143                 g_clear_pointer (&setting_dict, g_variant_unref);
1144
1145                 if (success_detail == NM_SETTING_UPDATE_SECRET_ERROR)
1146                         return FALSE;
1147                 if (success_detail == NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED)
1148                         updated = TRUE;
1149         } else {
1150                 /* check first, whether all the settings exist... */
1151                 g_variant_iter_init (&iter, secrets);
1152                 while (g_variant_iter_next (&iter, "{&s@a{sv}}", &key, NULL)) {
1153                         setting = nm_connection_get_setting_by_name (connection, key);
1154                         if (!setting) {
1155                                 g_set_error_literal (error,
1156                                                      NM_CONNECTION_ERROR,
1157                                                      NM_CONNECTION_ERROR_SETTING_NOT_FOUND,
1158                                                      key);
1159                                 return FALSE;
1160                         }
1161                 }
1162
1163                 /* Update each setting with any secrets from the connection dictionary */
1164                 g_variant_iter_init (&iter, secrets);
1165                 while (g_variant_iter_next (&iter, "{&s@a{sv}}", &key, &setting_dict)) {
1166                         /* Update the secrets for this setting */
1167                         setting = nm_connection_get_setting_by_name (connection, key);
1168
1169                         g_signal_handlers_block_by_func (setting, (GCallback) setting_changed_cb, connection);
1170                         success_detail = _nm_setting_update_secrets (setting, setting_dict, error);
1171                         g_signal_handlers_unblock_by_func (setting, (GCallback) setting_changed_cb, connection);
1172
1173                         g_variant_unref (setting_dict);
1174
1175                         if (success_detail == NM_SETTING_UPDATE_SECRET_ERROR) {
1176                                 success = FALSE;
1177                                 break;
1178                         }
1179                         if (success_detail == NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED)
1180                                 updated = TRUE;
1181                 }
1182         }
1183
1184         if (updated) {
1185                 g_signal_emit (connection, signals[SECRETS_UPDATED], 0, setting_name);
1186                 g_signal_emit (connection, signals[CHANGED], 0);
1187         }
1188
1189         return success;
1190 }
1191
1192 /**
1193  * nm_connection_need_secrets:
1194  * @connection: the #NMConnection
1195  * @hints: (out) (element-type utf8) (allow-none) (transfer container):
1196  *   the address of a pointer to a #GPtrArray, initialized to %NULL, which on
1197  *   return points to an allocated #GPtrArray containing the property names of
1198  *   secrets of the #NMSetting which may be required; the caller owns the array
1199  *   and must free the array itself with g_ptr_array_free(), but not free its
1200  *   elements
1201  *
1202  * Returns the name of the first setting object in the connection which would
1203  * need secrets to make a successful connection.  The returned hints are only
1204  * intended as a guide to what secrets may be required, because in some
1205  * circumstances, there is no way to conclusively determine exactly which
1206  * secrets are needed.
1207  *
1208  * Returns: the setting name of the #NMSetting object which has invalid or
1209  *   missing secrets
1210  **/
1211 const char *
1212 nm_connection_need_secrets (NMConnection *connection,
1213                             GPtrArray **hints)
1214 {
1215         NMConnectionPrivate *priv;
1216         GHashTableIter hiter;
1217         GSList *settings = NULL;
1218         GSList *iter;
1219         const char *name = NULL;
1220         NMSetting *setting;
1221
1222         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
1223         if (hints)
1224                 g_return_val_if_fail (*hints == NULL, NULL);
1225
1226         priv = NM_CONNECTION_GET_PRIVATE (connection);
1227
1228         /* Get list of settings in priority order */
1229         g_hash_table_iter_init (&hiter, priv->settings);
1230         while (g_hash_table_iter_next (&hiter, NULL, (gpointer) &setting))
1231                 settings = g_slist_insert_sorted (settings, setting, _nm_setting_compare_priority);
1232
1233         for (iter = settings; iter; iter = g_slist_next (iter)) {
1234                 GPtrArray *secrets;
1235
1236                 setting = NM_SETTING (iter->data);
1237                 secrets = _nm_setting_need_secrets (setting);
1238                 if (secrets) {
1239                         if (hints)
1240                                 *hints = secrets;
1241                         else
1242                                 g_ptr_array_free (secrets, TRUE);
1243
1244                         name = nm_setting_get_name (setting);
1245                         break;
1246                 }
1247         }
1248
1249         g_slist_free (settings);
1250         return name;
1251 }
1252
1253 /**
1254  * nm_connection_clear_secrets:
1255  * @connection: the #NMConnection
1256  *
1257  * Clears and frees any secrets that may be stored in the connection, to avoid
1258  * keeping secret data in memory when not needed.
1259  **/
1260 void
1261 nm_connection_clear_secrets (NMConnection *connection)
1262 {
1263         GHashTableIter iter;
1264         NMSetting *setting;
1265         gboolean changed = FALSE;
1266
1267         g_return_if_fail (NM_IS_CONNECTION (connection));
1268
1269         g_hash_table_iter_init (&iter, NM_CONNECTION_GET_PRIVATE (connection)->settings);
1270         while (g_hash_table_iter_next (&iter, NULL, (gpointer) &setting)) {
1271                 g_signal_handlers_block_by_func (setting, (GCallback) setting_changed_cb, connection);
1272                 changed |= _nm_setting_clear_secrets (setting);
1273                 g_signal_handlers_unblock_by_func (setting, (GCallback) setting_changed_cb, connection);
1274         }
1275
1276         g_signal_emit (connection, signals[SECRETS_CLEARED], 0);
1277         if (changed)
1278                 g_signal_emit (connection, signals[CHANGED], 0);
1279 }
1280
1281 /**
1282  * nm_connection_clear_secrets_with_flags:
1283  * @connection: the #NMConnection
1284  * @func: (scope call): function to be called to determine whether a
1285  *     specific secret should be cleared or not
1286  * @user_data: caller-supplied data passed to @func
1287  *
1288  * Clears and frees secrets determined by @func.
1289  **/
1290 void
1291 nm_connection_clear_secrets_with_flags (NMConnection *connection,
1292                                         NMSettingClearSecretsWithFlagsFn func,
1293                                         gpointer user_data)
1294 {
1295         GHashTableIter iter;
1296         NMSetting *setting;
1297         gboolean changed = FALSE;
1298
1299         g_return_if_fail (NM_IS_CONNECTION (connection));
1300
1301         g_hash_table_iter_init (&iter, NM_CONNECTION_GET_PRIVATE (connection)->settings);
1302         while (g_hash_table_iter_next (&iter, NULL, (gpointer) &setting)) {
1303                 g_signal_handlers_block_by_func (setting, (GCallback) setting_changed_cb, connection);
1304                 changed |= _nm_setting_clear_secrets_with_flags (setting, func, user_data);
1305                 g_signal_handlers_unblock_by_func (setting, (GCallback) setting_changed_cb, connection);
1306         }
1307
1308         g_signal_emit (connection, signals[SECRETS_CLEARED], 0);
1309         if (changed)
1310                 g_signal_emit (connection, signals[CHANGED], 0);
1311 }
1312
1313 /**
1314  * nm_connection_to_dbus:
1315  * @connection: the #NMConnection
1316  * @flags: serialization flags, e.g. %NM_CONNECTION_SERIALIZE_ALL
1317  *
1318  * Converts the #NMConnection into a #GVariant of type
1319  * %NM_VARIANT_TYPE_CONNECTION describing the connection, suitable for
1320  * marshalling over D-Bus or otherwise serializing.
1321  *
1322  * Returns: (transfer none): a new floating #GVariant describing the connection,
1323  * its settings, and each setting's properties.
1324  **/
1325 GVariant *
1326 nm_connection_to_dbus (NMConnection *connection,
1327                        NMConnectionSerializationFlags flags)
1328 {
1329         NMConnectionPrivate *priv;
1330         GVariantBuilder builder;
1331         GHashTableIter iter;
1332         gpointer key, data;
1333         GVariant *setting_dict, *ret;
1334
1335         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
1336         priv = NM_CONNECTION_GET_PRIVATE (connection);
1337
1338         g_variant_builder_init (&builder, NM_VARIANT_TYPE_CONNECTION);
1339
1340         /* Add each setting's hash to the main hash */
1341         g_hash_table_iter_init (&iter, priv->settings);
1342         while (g_hash_table_iter_next (&iter, &key, &data)) {
1343                 NMSetting *setting = NM_SETTING (data);
1344
1345                 setting_dict = _nm_setting_to_dbus (setting, connection, flags);
1346                 if (setting_dict)
1347                         g_variant_builder_add (&builder, "{s@a{sv}}", nm_setting_get_name (setting), setting_dict);
1348         }
1349
1350         ret = g_variant_builder_end (&builder);
1351
1352         /* Don't send empty hashes */
1353         if (g_variant_n_children (ret) == 0) {
1354                 g_variant_unref (ret);
1355                 ret = NULL;
1356         }
1357
1358         return ret;
1359 }
1360
1361 /**
1362  * nm_connection_is_type:
1363  * @connection: the #NMConnection
1364  * @type: a setting name to check the connection's type against (like
1365  * %NM_SETTING_WIRELESS_SETTING_NAME or %NM_SETTING_WIRED_SETTING_NAME)
1366  *
1367  * A convenience function to check if the given @connection is a particular
1368  * type (ie wired, Wi-Fi, ppp, etc). Checks the #NMSettingConnection:type
1369  * property of the connection and matches that against @type.
1370  *
1371  * Returns: %TRUE if the connection is of the given @type, %FALSE if not
1372  **/
1373 gboolean
1374 nm_connection_is_type (NMConnection *connection, const char *type)
1375 {
1376         NMSettingConnection *s_con;
1377         const char *type2;
1378
1379         g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
1380         g_return_val_if_fail (type != NULL, FALSE);
1381
1382         s_con = nm_connection_get_setting_connection (connection);
1383         if (!s_con)
1384                 return FALSE;
1385
1386         type2 = nm_setting_connection_get_connection_type (s_con);
1387
1388         return (g_strcmp0 (type2, type) == 0);
1389 }
1390
1391 static int
1392 _for_each_sort (NMSetting **p_a, NMSetting **p_b, void *unused)
1393 {
1394         NMSetting *a = *p_a;
1395         NMSetting *b = *p_b;
1396         int c;
1397
1398         c = _nm_setting_compare_priority (a, b);
1399         if (c != 0)
1400                 return c;
1401         return strcmp (nm_setting_get_name (a), nm_setting_get_name (b));
1402 }
1403
1404 /**
1405  * nm_connection_for_each_setting_value:
1406  * @connection: the #NMConnection
1407  * @func: (scope call): user-supplied function called for each setting's property
1408  * @user_data: user data passed to @func at each invocation
1409  *
1410  * Iterates over the properties of each #NMSetting object in the #NMConnection,
1411  * calling the supplied user function for each property.
1412  **/
1413 void
1414 nm_connection_for_each_setting_value (NMConnection *connection,
1415                                       NMSettingValueIterFn func,
1416                                       gpointer user_data)
1417 {
1418         NMConnectionPrivate *priv;
1419         gs_free NMSetting **arr_free = NULL;
1420         NMSetting *arr_temp[20], **arr;
1421         GHashTableIter iter;
1422         gpointer value;
1423         guint i, size;
1424
1425         g_return_if_fail (NM_IS_CONNECTION (connection));
1426         g_return_if_fail (func != NULL);
1427
1428         priv = NM_CONNECTION_GET_PRIVATE (connection);
1429
1430         size = g_hash_table_size (priv->settings);
1431         if (!size)
1432                 return;
1433
1434         if (size > G_N_ELEMENTS (arr_temp))
1435                 arr = arr_free = g_new (NMSetting *, size);
1436         else
1437                 arr = arr_temp;
1438
1439         g_hash_table_iter_init (&iter, priv->settings);
1440         for (i = 0; g_hash_table_iter_next (&iter, NULL, &value); i++)
1441                 arr[i] = NM_SETTING (value);
1442         g_assert (i == size);
1443
1444         /* sort the settings. This has an effect on the order in which keyfile
1445          * prints them. */
1446         if (size > 1)
1447                 g_qsort_with_data (arr, size, sizeof (NMSetting *), (GCompareDataFunc) _for_each_sort, NULL);
1448
1449         for (i = 0; i < size; i++)
1450                 nm_setting_enumerate_values (arr[i], func, user_data);
1451 }
1452
1453 /**
1454  * nm_connection_dump:
1455  * @connection: the #NMConnection
1456  *
1457  * Print the connection to stdout.  For debugging purposes ONLY, should NOT
1458  * be used for serialization of the connection or machine-parsed in any way. The
1459  * output format is not guaranteed to be stable and may change at any time.
1460  **/
1461 void
1462 nm_connection_dump (NMConnection *connection)
1463 {
1464         GHashTableIter iter;
1465         NMSetting *setting;
1466         const char *setting_name;
1467         char *str;
1468
1469         if (!connection)
1470                 return;
1471
1472         g_hash_table_iter_init (&iter, NM_CONNECTION_GET_PRIVATE (connection)->settings);
1473         while (g_hash_table_iter_next (&iter, (gpointer) &setting_name, (gpointer) &setting)) {
1474                 str = nm_setting_to_string (setting);
1475                 g_print ("%s\n", str);
1476                 g_free (str);
1477         }
1478 }
1479
1480 /**
1481  * nm_connection_set_path:
1482  * @connection: the #NMConnection
1483  * @path: the D-Bus path of the connection as given by the settings service
1484  * which provides the connection
1485  *
1486  * Sets the D-Bus path of the connection.  This property is not serialized, and
1487  * is only for the reference of the caller.  Sets the #NMConnection:path
1488  * property.
1489  **/
1490 void
1491 nm_connection_set_path (NMConnection *connection, const char *path)
1492 {
1493         NMConnectionPrivate *priv;
1494
1495         g_return_if_fail (NM_IS_CONNECTION (connection));
1496
1497         priv = NM_CONNECTION_GET_PRIVATE (connection);
1498
1499         g_free (priv->path);
1500         priv->path = NULL;
1501
1502         if (path)
1503                 priv->path = g_strdup (path);
1504 }
1505
1506 /**
1507  * nm_connection_get_path:
1508  * @connection: the #NMConnection
1509  *
1510  * Returns the connection's D-Bus path.
1511  *
1512  * Returns: the D-Bus path of the connection, previously set by a call to
1513  * nm_connection_set_path().
1514  **/
1515 const char *
1516 nm_connection_get_path (NMConnection *connection)
1517 {
1518         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
1519
1520         return NM_CONNECTION_GET_PRIVATE (connection)->path;
1521 }
1522
1523 /**
1524  * nm_connection_get_interface_name:
1525  * @connection: The #NMConnection
1526  *
1527  * Returns the interface name as stored in NMSettingConnection:interface_name.
1528  * If the connection contains no NMSettingConnection, it will return %NULL.
1529  *
1530  * For hardware devices and software devices created outside of NetworkManager,
1531  * this name is used to match the device. for software devices created by
1532  * NetworkManager, this is the name of the created interface.
1533  *
1534  * Returns: Name of the kernel interface or %NULL
1535  */
1536 const char *
1537 nm_connection_get_interface_name (NMConnection *connection)
1538 {
1539         NMSettingConnection *s_con;
1540
1541         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
1542
1543         s_con = nm_connection_get_setting_connection (connection);
1544
1545         return s_con ? nm_setting_connection_get_interface_name (s_con) : NULL;
1546 }
1547
1548 gboolean
1549 _nm_connection_verify_required_interface_name (NMConnection *connection,
1550                                                GError **error)
1551 {
1552         const char *interface_name;
1553
1554         interface_name = nm_connection_get_interface_name (connection);
1555         if (interface_name)
1556                 return TRUE;
1557
1558         g_set_error_literal (error,
1559                              NM_CONNECTION_ERROR,
1560                              NM_CONNECTION_ERROR_MISSING_PROPERTY,
1561                              _("property is missing"));
1562         g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_INTERFACE_NAME);
1563         return FALSE;
1564 }
1565
1566 /**
1567  * nm_connection_get_uuid:
1568  * @connection: the #NMConnection
1569  *
1570  * A shortcut to return the UUID from the connection's #NMSettingConnection.
1571  *
1572  * Returns: the UUID from the connection's 'connection' setting
1573  **/
1574 const char *
1575 nm_connection_get_uuid (NMConnection *connection)
1576 {
1577         NMSettingConnection *s_con;
1578
1579         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
1580
1581         s_con = nm_connection_get_setting_connection (connection);
1582         if (!s_con)
1583                 return NULL;
1584
1585         return nm_setting_connection_get_uuid (s_con);
1586 }
1587
1588 /**
1589  * nm_connection_get_id:
1590  * @connection: the #NMConnection
1591  *
1592  * A shortcut to return the ID from the connection's #NMSettingConnection.
1593  *
1594  * Returns: the ID from the connection's 'connection' setting
1595  **/
1596 const char *
1597 nm_connection_get_id (NMConnection *connection)
1598 {
1599         NMSettingConnection *s_con;
1600
1601         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
1602
1603         s_con = nm_connection_get_setting_connection (connection);
1604         if (!s_con)
1605                 return NULL;
1606
1607         return nm_setting_connection_get_id (s_con);
1608 }
1609
1610 /**
1611  * nm_connection_get_connection_type:
1612  * @connection: the #NMConnection
1613  *
1614  * A shortcut to return the type from the connection's #NMSettingConnection.
1615  *
1616  * Returns: the type from the connection's 'connection' setting
1617  **/
1618 const char *
1619 nm_connection_get_connection_type (NMConnection *connection)
1620 {
1621         NMSettingConnection *s_con;
1622
1623         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
1624
1625         s_con = nm_connection_get_setting_connection (connection);
1626         if (!s_con)
1627                 return NULL;
1628
1629         return nm_setting_connection_get_connection_type (s_con);
1630 }
1631
1632 /**
1633  * nm_connection_is_virtual:
1634  * @connection: an #NMConnection
1635  *
1636  * Checks if @connection refers to a virtual device (and thus can potentially be
1637  * activated even if the device it refers to doesn't exist).
1638  *
1639  * Returns: whether @connection refers to a virtual device
1640  */
1641 gboolean
1642 nm_connection_is_virtual (NMConnection *connection)
1643 {
1644         const char *type;
1645
1646         type = nm_connection_get_connection_type (connection);
1647         g_return_val_if_fail (type != NULL, FALSE);
1648
1649         if (   !strcmp (type, NM_SETTING_BOND_SETTING_NAME)
1650             || !strcmp (type, NM_SETTING_TEAM_SETTING_NAME)
1651             || !strcmp (type, NM_SETTING_BRIDGE_SETTING_NAME)
1652             || !strcmp (type, NM_SETTING_VLAN_SETTING_NAME)
1653             || !strcmp (type, NM_SETTING_TUN_SETTING_NAME)
1654             || !strcmp (type, NM_SETTING_IP_TUNNEL_SETTING_NAME)
1655             || !strcmp (type, NM_SETTING_MACVLAN_SETTING_NAME)
1656             || !strcmp (type, NM_SETTING_VXLAN_SETTING_NAME))
1657                 return TRUE;
1658
1659         if (!strcmp (type, NM_SETTING_INFINIBAND_SETTING_NAME)) {
1660                 NMSettingInfiniband *s_ib;
1661
1662                 s_ib = nm_connection_get_setting_infiniband (connection);
1663                 g_return_val_if_fail (s_ib != NULL, FALSE);
1664                 return nm_setting_infiniband_get_virtual_interface_name (s_ib) != NULL;
1665         }
1666
1667         return FALSE;
1668 }
1669
1670 /**
1671  * nm_connection_get_virtual_device_description:
1672  * @connection: an #NMConnection for a virtual device type
1673  *
1674  * Returns the name that nm_device_disambiguate_names() would
1675  * return for the virtual device that would be created for @connection.
1676  * Eg, "VLAN (eth1.1)".
1677  *
1678  * Returns: (transfer full): the name of @connection's device,
1679  *   or %NULL if @connection is not a virtual connection type
1680  */
1681 char *
1682 nm_connection_get_virtual_device_description (NMConnection *connection)
1683 {
1684         const char *type;
1685         const char *iface = NULL, *display_type = NULL;
1686
1687         iface = nm_connection_get_interface_name (connection);
1688
1689         type = nm_connection_get_connection_type (connection);
1690         g_return_val_if_fail (type != NULL, FALSE);
1691
1692         if (!strcmp (type, NM_SETTING_BOND_SETTING_NAME))
1693                 display_type = _("Bond");
1694         else if (!strcmp (type, NM_SETTING_TEAM_SETTING_NAME))
1695                 display_type = _("Team");
1696         else if (!strcmp (type, NM_SETTING_BRIDGE_SETTING_NAME))
1697                 display_type = _("Bridge");
1698         else if (!strcmp (type, NM_SETTING_VLAN_SETTING_NAME))
1699                 display_type = _("VLAN");
1700         else if (!strcmp (type, NM_SETTING_INFINIBAND_SETTING_NAME)) {
1701                 display_type = _("InfiniBand");
1702                 iface = nm_setting_infiniband_get_virtual_interface_name (nm_connection_get_setting_infiniband (connection));
1703         }
1704
1705         if (!iface || !display_type)
1706                 return NULL;
1707
1708         return g_strdup_printf ("%s (%s)", display_type, iface);
1709 }
1710
1711 /*************************************************************/
1712
1713 /**
1714  * nm_connection_get_setting_802_1x:
1715  * @connection: the #NMConnection
1716  *
1717  * A shortcut to return any #NMSetting8021x the connection might contain.
1718  *
1719  * Returns: (transfer none): an #NMSetting8021x if the connection contains one, otherwise %NULL
1720  **/
1721 NMSetting8021x *
1722 nm_connection_get_setting_802_1x (NMConnection *connection)
1723 {
1724         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
1725
1726         return (NMSetting8021x *) nm_connection_get_setting (connection, NM_TYPE_SETTING_802_1X);
1727 }
1728
1729 /**
1730  * nm_connection_get_setting_bluetooth:
1731  * @connection: the #NMConnection
1732  *
1733  * A shortcut to return any #NMSettingBluetooth the connection might contain.
1734  *
1735  * Returns: (transfer none): an #NMSettingBluetooth if the connection contains one, otherwise %NULL
1736  **/
1737 NMSettingBluetooth *
1738 nm_connection_get_setting_bluetooth (NMConnection *connection)
1739 {
1740         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
1741
1742         return (NMSettingBluetooth *) nm_connection_get_setting (connection, NM_TYPE_SETTING_BLUETOOTH);
1743 }
1744
1745 /**
1746  * nm_connection_get_setting_bond:
1747  * @connection: the #NMConnection
1748  *
1749  * A shortcut to return any #NMSettingBond the connection might contain.
1750  *
1751  * Returns: (transfer none): an #NMSettingBond if the connection contains one, otherwise %NULL
1752  **/
1753 NMSettingBond *
1754 nm_connection_get_setting_bond (NMConnection *connection)
1755 {
1756         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
1757
1758         return (NMSettingBond *) nm_connection_get_setting (connection, NM_TYPE_SETTING_BOND);
1759 }
1760
1761 /**
1762  * nm_connection_get_setting_team:
1763  * @connection: the #NMConnection
1764  *
1765  * A shortcut to return any #NMSettingTeam the connection might contain.
1766  *
1767  * Returns: (transfer none): an #NMSettingTeam if the connection contains one, otherwise %NULL
1768  **/
1769 NMSettingTeam *
1770 nm_connection_get_setting_team (NMConnection *connection)
1771 {
1772         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
1773
1774         return (NMSettingTeam *) nm_connection_get_setting (connection, NM_TYPE_SETTING_TEAM);
1775 }
1776
1777 /**
1778  * nm_connection_get_setting_team_port:
1779  * @connection: the #NMConnection
1780  *
1781  * A shortcut to return any #NMSettingTeamPort the connection might contain.
1782  *
1783  * Returns: (transfer none): an #NMSettingTeamPort if the connection contains one, otherwise %NULL
1784  **/
1785 NMSettingTeamPort *
1786 nm_connection_get_setting_team_port (NMConnection *connection)
1787 {
1788         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
1789
1790         return (NMSettingTeamPort *) nm_connection_get_setting (connection, NM_TYPE_SETTING_TEAM_PORT);
1791 }
1792
1793 /**
1794  * nm_connection_get_setting_bridge:
1795  * @connection: the #NMConnection
1796  *
1797  * A shortcut to return any #NMSettingBridge the connection might contain.
1798  *
1799  * Returns: (transfer none): an #NMSettingBridge if the connection contains one, otherwise %NULL
1800  **/
1801 NMSettingBridge *
1802 nm_connection_get_setting_bridge (NMConnection *connection)
1803 {
1804         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
1805
1806         return (NMSettingBridge *) nm_connection_get_setting (connection, NM_TYPE_SETTING_BRIDGE);
1807 }
1808
1809 /**
1810  * nm_connection_get_setting_cdma:
1811  * @connection: the #NMConnection
1812  *
1813  * A shortcut to return any #NMSettingCdma the connection might contain.
1814  *
1815  * Returns: (transfer none): an #NMSettingCdma if the connection contains one, otherwise %NULL
1816  **/
1817 NMSettingCdma *
1818 nm_connection_get_setting_cdma (NMConnection *connection)
1819 {
1820         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
1821
1822         return (NMSettingCdma *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CDMA);
1823 }
1824
1825 /**
1826  * nm_connection_get_setting_connection:
1827  * @connection: the #NMConnection
1828  *
1829  * A shortcut to return any #NMSettingConnection the connection might contain.
1830  *
1831  * Returns: (transfer none): an #NMSettingConnection if the connection contains one, otherwise %NULL
1832  **/
1833 NMSettingConnection *
1834 nm_connection_get_setting_connection (NMConnection *connection)
1835 {
1836         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
1837
1838         return (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
1839 }
1840
1841 /**
1842  * nm_connection_get_setting_dcb:
1843  * @connection: the #NMConnection
1844  *
1845  * A shortcut to return any #NMSettingDcb the connection might contain.
1846  *
1847  * Returns: (transfer none): an #NMSettingDcb if the connection contains one, otherwise NULL
1848  **/
1849 NMSettingDcb *
1850 nm_connection_get_setting_dcb (NMConnection *connection)
1851 {
1852         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
1853
1854         return (NMSettingDcb *) nm_connection_get_setting (connection, NM_TYPE_SETTING_DCB);
1855 }
1856
1857 /**
1858  * nm_connection_get_setting_generic:
1859  * @connection: the #NMConnection
1860  *
1861  * A shortcut to return any #NMSettingGeneric the connection might contain.
1862  *
1863  * Returns: (transfer none): an #NMSettingGeneric if the connection contains one, otherwise NULL
1864  **/
1865 NMSettingGeneric *
1866 nm_connection_get_setting_generic (NMConnection *connection)
1867 {
1868         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
1869
1870         return (NMSettingGeneric *) nm_connection_get_setting (connection, NM_TYPE_SETTING_GENERIC);
1871 }
1872
1873 /**
1874  * nm_connection_get_setting_gsm:
1875  * @connection: the #NMConnection
1876  *
1877  * A shortcut to return any #NMSettingGsm the connection might contain.
1878  *
1879  * Returns: (transfer none): an #NMSettingGsm if the connection contains one, otherwise %NULL
1880  **/
1881 NMSettingGsm *
1882 nm_connection_get_setting_gsm (NMConnection *connection)
1883 {
1884         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
1885
1886         return (NMSettingGsm *) nm_connection_get_setting (connection, NM_TYPE_SETTING_GSM);
1887 }
1888
1889 /**
1890  * nm_connection_get_setting_infiniband:
1891  * @connection: the #NMConnection
1892  *
1893  * A shortcut to return any #NMSettingInfiniband the connection might contain.
1894  *
1895  * Returns: (transfer none): an #NMSettingInfiniband if the connection contains one, otherwise %NULL
1896  **/
1897 NMSettingInfiniband *
1898 nm_connection_get_setting_infiniband (NMConnection *connection)
1899 {
1900         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
1901
1902         return (NMSettingInfiniband *) nm_connection_get_setting (connection, NM_TYPE_SETTING_INFINIBAND);
1903 }
1904
1905 /**
1906  * nm_connection_get_setting_ip4_config:
1907  * @connection: the #NMConnection
1908  *
1909  * A shortcut to return any #NMSettingIP4Config the connection might contain.
1910  *
1911  * Note that it returns the value as type #NMSettingIPConfig, since the vast
1912  * majority of IPv4-setting-related methods are on that type, not
1913  * #NMSettingIP4Config.
1914  *
1915  * Returns: (type NMSettingIP4Config) (transfer none): an #NMSettingIP4Config if the
1916  * connection contains one, otherwise %NULL
1917  **/
1918 NMSettingIPConfig *
1919 nm_connection_get_setting_ip4_config (NMConnection *connection)
1920 {
1921         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
1922
1923         return (NMSettingIPConfig *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
1924 }
1925
1926 /**
1927  * nm_connection_get_setting_ip_tunnel:
1928  * @connection: the #NMConnection
1929  *
1930  * A shortcut to return any #NMSettingIPTunnel the connection might contain.
1931  *
1932  * Returns: (transfer none): an #NMSettingIPTunnel if the connection contains one, otherwise %NULL
1933  *
1934  * Since: 1.2
1935  **/
1936 NMSettingIPTunnel *
1937 nm_connection_get_setting_ip_tunnel (NMConnection *connection)
1938 {
1939         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
1940
1941         return (NMSettingIPTunnel *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP_TUNNEL);
1942 }
1943
1944 /**
1945  * nm_connection_get_setting_ip6_config:
1946  * @connection: the #NMConnection
1947  *
1948  * A shortcut to return any #NMSettingIP6Config the connection might contain.
1949  *
1950  * Note that it returns the value as type #NMSettingIPConfig, since the vast
1951  * majority of IPv6-setting-related methods are on that type, not
1952  * #NMSettingIP6Config.
1953  *
1954  * Returns: (type NMSettingIP6Config) (transfer none): an #NMSettingIP6Config if the
1955  * connection contains one, otherwise %NULL
1956  **/
1957 NMSettingIPConfig *
1958 nm_connection_get_setting_ip6_config (NMConnection *connection)
1959 {
1960         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
1961
1962         return (NMSettingIPConfig *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG);
1963 }
1964
1965 /**
1966  * nm_connection_get_setting_macvlan:
1967  * @connection: the #NMConnection
1968  *
1969  * A shortcut to return any #NMSettingMacvlan the connection might contain.
1970  *
1971  * Returns: (transfer none): an #NMSettingMacvlan if the connection contains one, otherwise %NULL
1972  *
1973  * Since: 1.2
1974  **/
1975 NMSettingMacvlan *
1976 nm_connection_get_setting_macvlan (NMConnection *connection)
1977 {
1978         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
1979
1980         return (NMSettingMacvlan *) nm_connection_get_setting (connection, NM_TYPE_SETTING_MACVLAN);
1981 }
1982
1983 /**
1984  * nm_connection_get_setting_olpc_mesh:
1985  * @connection: the #NMConnection
1986  *
1987  * A shortcut to return any #NMSettingOlpcMesh the connection might contain.
1988  *
1989  * Returns: (transfer none): an #NMSettingOlpcMesh if the connection contains one, otherwise %NULL
1990  **/
1991 NMSettingOlpcMesh *
1992 nm_connection_get_setting_olpc_mesh (NMConnection *connection)
1993 {
1994         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
1995
1996         return (NMSettingOlpcMesh *) nm_connection_get_setting (connection, NM_TYPE_SETTING_OLPC_MESH);
1997 }
1998
1999 /**
2000  * nm_connection_get_setting_ppp:
2001  * @connection: the #NMConnection
2002  *
2003  * A shortcut to return any #NMSettingPpp the connection might contain.
2004  *
2005  * Returns: (transfer none): an #NMSettingPpp if the connection contains one, otherwise %NULL
2006  **/
2007 NMSettingPpp *
2008 nm_connection_get_setting_ppp (NMConnection *connection)
2009 {
2010         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
2011
2012         return (NMSettingPpp *) nm_connection_get_setting (connection, NM_TYPE_SETTING_PPP);
2013 }
2014
2015 /**
2016  * nm_connection_get_setting_pppoe:
2017  * @connection: the #NMConnection
2018  *
2019  * A shortcut to return any #NMSettingPppoe the connection might contain.
2020  *
2021  * Returns: (transfer none): an #NMSettingPppoe if the connection contains one, otherwise %NULL
2022  **/
2023 NMSettingPppoe *
2024 nm_connection_get_setting_pppoe (NMConnection *connection)
2025 {
2026         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
2027
2028         return (NMSettingPppoe *) nm_connection_get_setting (connection, NM_TYPE_SETTING_PPPOE);
2029 }
2030
2031 /**
2032  * nm_connection_get_setting_serial:
2033  * @connection: the #NMConnection
2034  *
2035  * A shortcut to return any #NMSettingSerial the connection might contain.
2036  *
2037  * Returns: (transfer none): an #NMSettingSerial if the connection contains one, otherwise %NULL
2038  **/
2039 NMSettingSerial *
2040 nm_connection_get_setting_serial (NMConnection *connection)
2041 {
2042         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
2043
2044         return (NMSettingSerial *) nm_connection_get_setting (connection, NM_TYPE_SETTING_SERIAL);
2045 }
2046
2047 /**
2048  * nm_connection_get_setting_tun:
2049  * @connection: the #NMConnection
2050  *
2051  * A shortcut to return any #NMSettingTun the connection might contain.
2052  *
2053  * Returns: (transfer none): an #NMSettingTun if the connection contains one, otherwise %NULL
2054  *
2055  * Since: 1.2
2056  **/
2057 NMSettingTun *
2058 nm_connection_get_setting_tun (NMConnection *connection)
2059 {
2060         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
2061
2062         return (NMSettingTun *) nm_connection_get_setting (connection, NM_TYPE_SETTING_TUN);
2063 }
2064
2065 /**
2066  * nm_connection_get_setting_vpn:
2067  * @connection: the #NMConnection
2068  *
2069  * A shortcut to return any #NMSettingVpn the connection might contain.
2070  *
2071  * Returns: (transfer none): an #NMSettingVpn if the connection contains one, otherwise %NULL
2072  **/
2073 NMSettingVpn *
2074 nm_connection_get_setting_vpn (NMConnection *connection)
2075 {
2076         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
2077
2078         return (NMSettingVpn *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN);
2079 }
2080
2081 /**
2082  * nm_connection_get_setting_vxlan:
2083  * @connection: the #NMConnection
2084  *
2085  * A shortcut to return any #NMSettingVxlan the connection might contain.
2086  *
2087  * Returns: (transfer none): an #NMSettingVxlan if the connection contains one, otherwise %NULL
2088  *
2089  * Since: 1.2
2090  **/
2091 NMSettingVxlan *
2092 nm_connection_get_setting_vxlan (NMConnection *connection)
2093 {
2094         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
2095
2096         return (NMSettingVxlan *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VXLAN);
2097 }
2098
2099 /**
2100  * nm_connection_get_setting_wimax:
2101  * @connection: the #NMConnection
2102  *
2103  * A shortcut to return any #NMSettingWimax the connection might contain.
2104  *
2105  * Returns: (transfer none): an #NMSettingWimax if the connection contains one, otherwise %NULL
2106  **/
2107 NMSettingWimax *
2108 nm_connection_get_setting_wimax (NMConnection *connection)
2109 {
2110         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
2111
2112         return (NMSettingWimax *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIMAX);
2113 }
2114
2115 /**
2116  * nm_connection_get_setting_wired:
2117  * @connection: the #NMConnection
2118  *
2119  * A shortcut to return any #NMSettingWired the connection might contain.
2120  *
2121  * Returns: (transfer none): an #NMSettingWired if the connection contains one, otherwise %NULL
2122  **/
2123 NMSettingWired *
2124 nm_connection_get_setting_wired (NMConnection *connection)
2125 {
2126         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
2127
2128         return (NMSettingWired *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED);
2129 }
2130
2131 /**
2132  * nm_connection_get_setting_adsl:
2133  * @connection: the #NMConnection
2134  *
2135  * A shortcut to return any #NMSettingAdsl the connection might contain.
2136  *
2137  * Returns: (transfer none): an #NMSettingAdsl if the connection contains one, otherwise %NULL
2138  **/
2139 NMSettingAdsl *
2140 nm_connection_get_setting_adsl (NMConnection *connection)
2141 {
2142         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
2143
2144         return (NMSettingAdsl *) nm_connection_get_setting (connection, NM_TYPE_SETTING_ADSL);
2145 }
2146
2147 /**
2148  * nm_connection_get_setting_wireless:
2149  * @connection: the #NMConnection
2150  *
2151  * A shortcut to return any #NMSettingWireless the connection might contain.
2152  *
2153  * Returns: (transfer none): an #NMSettingWireless if the connection contains one, otherwise %NULL
2154  **/
2155 NMSettingWireless *
2156 nm_connection_get_setting_wireless (NMConnection *connection)
2157 {
2158         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
2159
2160         return (NMSettingWireless *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS);
2161 }
2162
2163 /**
2164  * nm_connection_get_setting_wireless_security:
2165  * @connection: the #NMConnection
2166  *
2167  * A shortcut to return any #NMSettingWirelessSecurity the connection might contain.
2168  *
2169  * Returns: (transfer none): an #NMSettingWirelessSecurity if the connection contains one, otherwise %NULL
2170  **/
2171 NMSettingWirelessSecurity *
2172 nm_connection_get_setting_wireless_security (NMConnection *connection)
2173 {
2174         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
2175
2176         return (NMSettingWirelessSecurity *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS_SECURITY);
2177 }
2178
2179 /**
2180  * nm_connection_get_setting_bridge_port:
2181  * @connection: the #NMConnection
2182  *
2183  * A shortcut to return any #NMSettingBridgePort the connection might contain.
2184  *
2185  * Returns: (transfer none): an #NMSettingBridgePort if the connection contains one, otherwise %NULL
2186  **/
2187 NMSettingBridgePort *
2188 nm_connection_get_setting_bridge_port (NMConnection *connection)
2189 {
2190         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
2191
2192         return (NMSettingBridgePort *) nm_connection_get_setting (connection, NM_TYPE_SETTING_BRIDGE_PORT);
2193 }
2194
2195 /**
2196  * nm_connection_get_setting_vlan:
2197  * @connection: the #NMConnection
2198  *
2199  * A shortcut to return any #NMSettingVlan the connection might contain.
2200  *
2201  * Returns: (transfer none): an #NMSettingVlan if the connection contains one, otherwise %NULL
2202  **/
2203 NMSettingVlan *
2204 nm_connection_get_setting_vlan (NMConnection *connection)
2205 {
2206         g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
2207
2208         return (NMSettingVlan *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VLAN);
2209 }
2210
2211 /*************************************************************/
2212
2213 static void
2214 nm_connection_private_free (NMConnectionPrivate *priv)
2215 {
2216         NMConnection *self = priv->self;
2217
2218         g_hash_table_foreach_remove (priv->settings, _setting_release, self);
2219         g_hash_table_destroy (priv->settings);
2220         g_free (priv->path);
2221
2222         g_slice_free (NMConnectionPrivate, priv);
2223 }
2224
2225 static NMConnectionPrivate *
2226 nm_connection_get_private (NMConnection *connection)
2227 {
2228         NMConnectionPrivate *priv;
2229
2230         priv = g_object_get_data (G_OBJECT (connection), "NMConnectionPrivate");
2231         if (!priv) {
2232                 priv = g_slice_new0 (NMConnectionPrivate);
2233                 g_object_set_data_full (G_OBJECT (connection), "NMConnectionPrivate",
2234                                         priv, (GDestroyNotify) nm_connection_private_free);
2235
2236                 priv->self = connection;
2237                 priv->settings = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
2238         }
2239
2240         return priv;
2241 }
2242
2243 static void
2244 nm_connection_default_init (NMConnectionInterface *iface)
2245 {
2246         /* Signals */
2247
2248         /**
2249          * NMConnection::secrets-updated:
2250          * @connection: the object on which the signal is emitted
2251          * @setting_name: the setting name of the #NMSetting for which secrets were
2252          * updated
2253          *
2254          * The ::secrets-updated signal is emitted when the secrets of a setting
2255          * have been changed.
2256          */
2257         signals[SECRETS_UPDATED] =
2258                 g_signal_new (NM_CONNECTION_SECRETS_UPDATED,
2259                               NM_TYPE_CONNECTION,
2260                               G_SIGNAL_RUN_FIRST,
2261                               G_STRUCT_OFFSET (NMConnectionInterface, secrets_updated),
2262                               NULL, NULL,
2263                               g_cclosure_marshal_VOID__STRING,
2264                               G_TYPE_NONE, 1,
2265                               G_TYPE_STRING);
2266
2267         /**
2268          * NMConnection::secrets-cleared:
2269          * @connection: the object on which the signal is emitted
2270          *
2271          * The ::secrets-cleared signal is emitted when the secrets of a connection
2272          * are cleared.
2273          */
2274         signals[SECRETS_CLEARED] =
2275                 g_signal_new (NM_CONNECTION_SECRETS_CLEARED,
2276                               NM_TYPE_CONNECTION,
2277                               G_SIGNAL_RUN_FIRST,
2278                               G_STRUCT_OFFSET (NMConnectionInterface, secrets_cleared),
2279                               NULL, NULL,
2280                               g_cclosure_marshal_VOID__VOID,
2281                               G_TYPE_NONE, 0);
2282
2283         /**
2284          * NMConnection::changed:
2285          * @connection: the object on which the signal is emitted
2286          *
2287          * The ::changed signal is emitted when any property of any property
2288          * (including secrets) of any setting of the connection is modified,
2289          * or when settings are added or removed.
2290          */
2291         signals[CHANGED] =
2292                 g_signal_new (NM_CONNECTION_CHANGED,
2293                               NM_TYPE_CONNECTION,
2294                               G_SIGNAL_RUN_FIRST,
2295                               G_STRUCT_OFFSET (NMConnectionInterface, changed),
2296                               NULL, NULL,
2297                               g_cclosure_marshal_VOID__VOID,
2298                               G_TYPE_NONE, 0);
2299 }