44237d9801f14a1fd30761a3fbaef7e264eb8cc6
[NetworkManager.git] / libnm-core / nm-setting-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 "nm-setting-connection.h"
26
27 #include <string.h>
28
29 #include "nm-utils.h"
30 #include "nm-utils-private.h"
31 #include "nm-core-enum-types.h"
32 #include "nm-connection-private.h"
33 #include "nm-setting-bond.h"
34 #include "nm-setting-bridge.h"
35 #include "nm-setting-team.h"
36 #include "nm-setting-vlan.h"
37
38 /**
39  * SECTION:nm-setting-connection
40  * @short_description: Describes general connection properties
41  *
42  * The #NMSettingConnection object is a #NMSetting subclass that describes
43  * properties that apply to all #NMConnection objects, regardless of what type
44  * of network connection they describe.  Each #NMConnection object must contain
45  * a #NMSettingConnection setting.
46  **/
47
48 G_DEFINE_TYPE_WITH_CODE (NMSettingConnection, nm_setting_connection, NM_TYPE_SETTING,
49                          _nm_register_setting (CONNECTION, 0))
50 NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_CONNECTION)
51
52 #define NM_SETTING_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_CONNECTION, NMSettingConnectionPrivate))
53
54 typedef enum {
55         PERM_TYPE_USER = 0,
56 } PermType;
57
58 typedef struct {
59         guint8 ptype;
60         char *item;
61 } Permission;
62
63 typedef struct {
64         char *id;
65         char *uuid;
66         char *interface_name;
67         char *type;
68         char *master;
69         char *slave_type;
70         NMSettingConnectionAutoconnectSlaves autoconnect_slaves;
71         GSList *permissions; /* list of Permission structs */
72         gboolean autoconnect;
73         gint autoconnect_priority;
74         guint64 timestamp;
75         gboolean read_only;
76         char *zone;
77         GSList *secondaries; /* secondary connections to activate with the base connection */
78         guint gateway_ping_timeout;
79         NMMetered metered;
80         NMSettingConnectionLldp lldp;
81 } NMSettingConnectionPrivate;
82
83 enum {
84         PROP_0,
85         PROP_ID,
86         PROP_UUID,
87         PROP_INTERFACE_NAME,
88         PROP_TYPE,
89         PROP_PERMISSIONS,
90         PROP_AUTOCONNECT,
91         PROP_AUTOCONNECT_PRIORITY,
92         PROP_TIMESTAMP,
93         PROP_READ_ONLY,
94         PROP_ZONE,
95         PROP_MASTER,
96         PROP_SLAVE_TYPE,
97         PROP_AUTOCONNECT_SLAVES,
98         PROP_SECONDARIES,
99         PROP_GATEWAY_PING_TIMEOUT,
100         PROP_METERED,
101         PROP_LLDP,
102
103         LAST_PROP
104 };
105
106 /***********************************************************************/
107
108 #define PERM_USER_PREFIX  "user:"
109
110 static Permission *
111 permission_new_from_str (const char *str)
112 {
113         Permission *p;
114         const char *last_colon;
115         size_t ulen = 0, i;
116
117         g_return_val_if_fail (strncmp (str, PERM_USER_PREFIX, strlen (PERM_USER_PREFIX)) == 0, NULL);
118         str += strlen (PERM_USER_PREFIX);
119
120         last_colon = strrchr (str, ':');
121         if (last_colon) {
122                 /* Ensure that somebody didn't pass "user::" */
123                 g_return_val_if_fail (last_colon > str, NULL);
124
125                 /* Reject :[detail] for now */
126                 g_return_val_if_fail (*(last_colon + 1) == '\0', NULL);
127
128                 /* Make sure we don't include detail in the username */
129                 ulen = last_colon - str;
130         } else
131                 ulen = strlen (str);
132
133         /* Sanity check the length of the username */
134         g_return_val_if_fail (ulen < 100, NULL);
135
136         /* Make sure there's no ':' in the username */
137         for (i = 0; i < ulen; i++)
138                 g_return_val_if_fail (str[i] != ':', NULL);
139
140         /* And the username must be valid UTF-8 */
141         g_return_val_if_fail (g_utf8_validate (str, -1, NULL) == TRUE, NULL);
142
143         /* Yay, valid... create the new permission */
144         p = g_slice_new0 (Permission);
145         p->ptype = PERM_TYPE_USER;
146         if (last_colon) {
147                 p->item = g_malloc (ulen + 1);
148                 memcpy (p->item, str, ulen);
149                 p->item[ulen] = '\0';
150         } else
151                 p->item = g_strdup (str);
152
153         return p;
154 }
155
156 static Permission *
157 permission_new (const char *uname)
158 {
159         Permission *p;
160
161         g_return_val_if_fail (uname, NULL);
162         g_return_val_if_fail (uname[0] != '\0', NULL);
163         g_return_val_if_fail (strchr (uname, ':') == NULL, NULL);
164         g_return_val_if_fail (g_utf8_validate (uname, -1, NULL) == TRUE, NULL);
165
166         /* Yay, valid... create the new permission */
167         p = g_slice_new0 (Permission);
168         p->ptype = PERM_TYPE_USER;
169         p->item = g_strdup (uname);
170         return p;
171 }
172
173 static char *
174 permission_to_string (Permission *p)
175 {
176         return g_strdup_printf (PERM_USER_PREFIX "%s:", p->item);
177 }
178
179 static void
180 permission_free (Permission *p)
181 {
182         g_free (p->item);
183         memset (p, 0, sizeof (*p));
184         g_slice_free (Permission, p);
185 }
186
187 /***********************************************************************/
188
189 /**
190  * nm_setting_connection_new:
191  *
192  * Creates a new #NMSettingConnection object with default values.
193  *
194  * Returns: the new empty #NMSettingConnection object
195  **/
196 NMSetting *nm_setting_connection_new (void)
197 {
198         return (NMSetting *) g_object_new (NM_TYPE_SETTING_CONNECTION, NULL);
199 }
200
201 /**
202  * nm_setting_connection_get_id:
203  * @setting: the #NMSettingConnection
204  *
205  * Returns the #NMSettingConnection:id property of the connection.
206  *
207  * Returns: the connection ID
208  **/
209 const char *
210 nm_setting_connection_get_id (NMSettingConnection *setting)
211 {
212         g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), NULL);
213
214         return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->id;
215 }
216
217 /**
218  * nm_setting_connection_get_uuid:
219  * @setting: the #NMSettingConnection
220  *
221  * Returns the #NMSettingConnection:uuid property of the connection.
222  *
223  * Returns: the connection UUID
224  **/
225 const char *
226 nm_setting_connection_get_uuid (NMSettingConnection *setting)
227 {
228         g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), NULL);
229
230         return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->uuid;
231 }
232
233 /**
234  * nm_setting_connection_get_interface_name:
235  * @setting: the #NMSettingConnection
236  *
237  * Returns the #NMSettingConnection:interface-name property of the connection.
238  *
239  * Returns: the connection's interface name
240  **/
241 const char *
242 nm_setting_connection_get_interface_name (NMSettingConnection *setting)
243 {
244         g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), NULL);
245
246         return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->interface_name;
247 }
248
249 /**
250  * nm_setting_connection_get_connection_type:
251  * @setting: the #NMSettingConnection
252  *
253  * Returns the #NMSettingConnection:type property of the connection.
254  *
255  * Returns: the connection type
256  **/
257 const char *
258 nm_setting_connection_get_connection_type (NMSettingConnection *setting)
259 {
260         g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), NULL);
261
262         return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->type;
263 }
264
265
266 /**
267  * nm_setting_connection_get_num_permissions:
268  * @setting: the #NMSettingConnection
269  *
270  * Returns the number of entires in the #NMSettingConnection:permissions
271  * property of this setting.
272  *
273  * Returns: the number of permissions entires
274  */
275 guint32
276 nm_setting_connection_get_num_permissions (NMSettingConnection *setting)
277 {
278         g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), 0);
279
280         return g_slist_length (NM_SETTING_CONNECTION_GET_PRIVATE (setting)->permissions);
281 }
282
283 /**
284  * nm_setting_connection_get_permission:
285  * @setting: the #NMSettingConnection
286  * @idx: the zero-based index of the permissions entry
287  * @out_ptype: on return, the permission type (at this time, always "user")
288  * @out_pitem: on return, the permission item (formatted accoring to @ptype, see
289  * #NMSettingConnection:permissions for more detail
290  * @out_detail: on return, the permission detail (at this time, always %NULL)
291  *
292  * Retrieve one of the entries of the #NMSettingConnection:permissions property
293  * of this setting.
294  *
295  * Returns: %TRUE if a permission was returned, %FALSE if @idx was invalid
296  */
297 gboolean
298 nm_setting_connection_get_permission (NMSettingConnection *setting,
299                                       guint32 idx,
300                                       const char **out_ptype,
301                                       const char **out_pitem,
302                                       const char **out_detail)
303 {
304         NMSettingConnectionPrivate *priv;
305         Permission *p;
306
307         g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), FALSE);
308
309         priv = NM_SETTING_CONNECTION_GET_PRIVATE (setting);
310
311         g_return_val_if_fail (idx < g_slist_length (priv->permissions), FALSE);
312
313         p = g_slist_nth_data (priv->permissions, idx);
314         if (out_ptype)
315                 *out_ptype = "user";
316         if (out_pitem)
317                 *out_pitem = p->item;
318         if (out_detail)
319                 *out_detail = NULL;
320
321         return TRUE;
322 }
323
324 /**
325  * nm_setting_connection_permissions_user_allowed:
326  * @setting: the #NMSettingConnection
327  * @uname: the user name to check permissions for
328  *
329  * Checks whether the given username is allowed to view/access this connection.
330  *
331  * Returns: %TRUE if the requested user is allowed to view this connection,
332  * %FALSE if the given user is not allowed to view this connection
333  */
334 gboolean
335 nm_setting_connection_permissions_user_allowed (NMSettingConnection *setting,
336                                                 const char *uname)
337 {
338         NMSettingConnectionPrivate *priv;
339         GSList *iter;
340
341         g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), FALSE);
342         g_return_val_if_fail (uname != NULL, FALSE);
343         g_return_val_if_fail (*uname != '\0', FALSE);
344
345         priv = NM_SETTING_CONNECTION_GET_PRIVATE (setting);
346
347         /* If no permissions, visible to all */
348         if (priv->permissions == NULL)
349                 return TRUE;
350
351         /* Find the username in the permissions list */
352         for (iter = priv->permissions; iter; iter = g_slist_next (iter)) {
353                 Permission *p = iter->data;
354
355                 if (strcmp (uname, p->item) == 0)
356                         return TRUE;
357         }
358
359         return FALSE;
360 }
361
362 /**
363  * nm_setting_connection_add_permission:
364  * @setting: the #NMSettingConnection
365  * @ptype: the permission type; at this time only "user" is supported
366  * @pitem: the permission item formatted as required for @ptype
367  * @detail: (allow-none): unused at this time; must be %NULL
368  *
369  * Adds a permission to the connection's permission list.  At this time, only
370  * the "user" permission type is supported, and @pitem must be a username. See
371  * #NMSettingConnection:permissions: for more details.
372  *
373  * Returns: %TRUE if the permission was unique and was successfully added to the
374  * list, %FALSE if @ptype or @pitem was invalid or it the permission was already
375  * present in the list
376  */
377 gboolean
378 nm_setting_connection_add_permission (NMSettingConnection *setting,
379                                       const char *ptype,
380                                       const char *pitem,
381                                       const char *detail)
382 {
383         NMSettingConnectionPrivate *priv;
384         Permission *p;
385         GSList *iter;
386
387         g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), FALSE);
388         g_return_val_if_fail (ptype, FALSE);
389         g_return_val_if_fail (strlen (ptype) > 0, FALSE);
390         g_return_val_if_fail (detail == NULL, FALSE);
391
392         /* Only "user" for now... */
393         g_return_val_if_fail (strcmp (ptype, "user") == 0, FALSE);
394
395         priv = NM_SETTING_CONNECTION_GET_PRIVATE (setting);
396
397         /* No dupes */
398         for (iter = priv->permissions; iter; iter = g_slist_next (iter)) {
399                 p = iter->data;
400                 if (strcmp (pitem, p->item) == 0)
401                         return FALSE;
402         }
403
404         p = permission_new (pitem);
405         g_return_val_if_fail (p != NULL, FALSE);
406         priv->permissions = g_slist_append (priv->permissions, p);
407         g_object_notify (G_OBJECT (setting), NM_SETTING_CONNECTION_PERMISSIONS);
408
409         return TRUE;
410 }
411
412 /**
413  * nm_setting_connection_remove_permission:
414  * @setting: the #NMSettingConnection
415  * @idx: the zero-based index of the permission to remove
416  *
417  * Removes the permission at index @idx from the connection.
418  */
419 void
420 nm_setting_connection_remove_permission (NMSettingConnection *setting,
421                                          guint32 idx)
422 {
423         NMSettingConnectionPrivate *priv;
424         GSList *iter;
425
426         g_return_if_fail (NM_IS_SETTING_CONNECTION (setting));
427
428         priv = NM_SETTING_CONNECTION_GET_PRIVATE (setting);
429         iter = g_slist_nth (priv->permissions, idx);
430         g_return_if_fail (iter != NULL);
431
432         permission_free ((Permission *) iter->data);
433         priv->permissions = g_slist_delete_link (priv->permissions, iter);
434         g_object_notify (G_OBJECT (setting), NM_SETTING_CONNECTION_PERMISSIONS);
435 }
436
437 /**
438  * nm_setting_connection_remove_permission_by_value:
439  * @setting: the #NMSettingConnection
440  * @ptype: the permission type; at this time only "user" is supported
441  * @pitem: the permission item formatted as required for @ptype
442  * @detail: (allow-none): unused at this time; must be %NULL
443  *
444  * Removes the permission from the connection.
445  * At this time, only the "user" permission type is supported, and @pitem must
446  * be a username. See #NMSettingConnection:permissions: for more details.
447  *
448  * Returns: %TRUE if the permission was found and removed; %FALSE if it was not.
449  */
450 gboolean
451 nm_setting_connection_remove_permission_by_value (NMSettingConnection *setting,
452                                                   const char *ptype,
453                                                   const char *pitem,
454                                                   const char *detail)
455 {
456         NMSettingConnectionPrivate *priv;
457         Permission *p;
458         GSList *iter;
459
460         g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), FALSE);
461         g_return_val_if_fail (ptype, FALSE);
462         g_return_val_if_fail (strlen (ptype) > 0, FALSE);
463         g_return_val_if_fail (detail == NULL, FALSE);
464
465         /* Only "user" for now... */
466         g_return_val_if_fail (strcmp (ptype, "user") == 0, FALSE);
467
468         priv = NM_SETTING_CONNECTION_GET_PRIVATE (setting);
469         for (iter = priv->permissions; iter; iter = g_slist_next (iter)) {
470                 p = iter->data;
471                 if (strcmp (pitem, p->item) == 0) {
472                         permission_free ((Permission *) iter->data);
473                         priv->permissions = g_slist_delete_link (priv->permissions, iter);
474                         g_object_notify (G_OBJECT (setting), NM_SETTING_CONNECTION_PERMISSIONS);
475                         return TRUE;
476                 }
477         }
478         return FALSE;
479 }
480
481 /**
482  * nm_setting_connection_get_autoconnect:
483  * @setting: the #NMSettingConnection
484  *
485  * Returns the #NMSettingConnection:autoconnect property of the connection.
486  *
487  * Returns: the connection's autoconnect behavior
488  **/
489 gboolean
490 nm_setting_connection_get_autoconnect (NMSettingConnection *setting)
491 {
492         g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), FALSE);
493
494         return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->autoconnect;
495 }
496
497 /**
498  * nm_setting_connection_get_autoconnect_priority:
499  * @setting: the #NMSettingConnection
500  *
501  * Returns the #NMSettingConnection:autoconnect-priority property of the connection.
502  * The higher number, the higher priority.
503  *
504  * Returns: the connection's autoconnect priority
505  **/
506 gint
507 nm_setting_connection_get_autoconnect_priority (NMSettingConnection *setting)
508 {
509         g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), 0);
510
511         return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->autoconnect_priority;
512 }
513
514 /**
515  * nm_setting_connection_get_timestamp:
516  * @setting: the #NMSettingConnection
517  *
518  * Returns the #NMSettingConnection:timestamp property of the connection.
519  *
520  * Returns: the connection's timestamp
521  **/
522 guint64
523 nm_setting_connection_get_timestamp (NMSettingConnection *setting)
524 {
525         g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), 0);
526
527         return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->timestamp;
528 }
529
530 /**
531  * nm_setting_connection_get_read_only:
532  * @setting: the #NMSettingConnection
533  *
534  * Returns the #NMSettingConnection:read-only property of the connection.
535  *
536  * Returns: %TRUE if the connection is read-only, %FALSE if it is not
537  **/
538 gboolean
539 nm_setting_connection_get_read_only (NMSettingConnection *setting)
540 {
541         g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), TRUE);
542
543         return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->read_only;
544 }
545
546 /**
547  * nm_setting_connection_get_zone:
548  * @setting: the #NMSettingConnection
549  *
550  * Returns the #NMSettingConnection:zone property of the connection.
551  *
552  * Returns: the trust level of a connection
553  **/
554 const char *
555 nm_setting_connection_get_zone (NMSettingConnection *setting)
556 {
557         g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), NULL);
558
559         return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->zone;
560 }
561
562 /**
563  * nm_setting_connection_get_master:
564  * @setting: the #NMSettingConnection
565  *
566  * Returns the #NMSettingConnection:master property of the connection.
567  *
568  * Returns: interface name of the master device or UUID of the master
569  * connection.
570  */
571 const char *
572 nm_setting_connection_get_master (NMSettingConnection *setting)
573 {
574         g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), NULL);
575
576         return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->master;
577 }
578
579 /**
580  * nm_setting_connection_get_slave_type:
581  * @setting: the #NMSettingConnection
582  *
583  * Returns the #NMSettingConnection:slave-type property of the connection.
584  *
585  * Returns: the type of slave this connection is, if any
586  */
587 const char *
588 nm_setting_connection_get_slave_type (NMSettingConnection *setting)
589 {
590         g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), NULL);
591
592         return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->slave_type;
593 }
594
595 /**
596  * nm_setting_connection_is_slave_type:
597  * @setting: the #NMSettingConnection
598  * @type: the setting name (ie #NM_SETTING_BOND_SETTING_NAME) to be matched
599  * against @setting's slave type
600  *
601  * Returns: %TRUE if connection is of the given slave @type
602  */
603 gboolean
604 nm_setting_connection_is_slave_type (NMSettingConnection *setting,
605                                      const char *type)
606 {
607         g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), FALSE);
608
609         return !g_strcmp0 (NM_SETTING_CONNECTION_GET_PRIVATE (setting)->slave_type, type);
610 }
611
612 /**
613  * nm_setting_connection_get_autoconnect_slaves:
614  * @setting: the #NMSettingConnection
615  *
616  * Returns the #NMSettingConnection:autoconnect-slaves property of the connection.
617  *
618  * Returns: whether slaves of the connection should be activated together
619  *          with the connection.
620  *
621  * Since: 1.2
622  **/
623 NMSettingConnectionAutoconnectSlaves
624 nm_setting_connection_get_autoconnect_slaves (NMSettingConnection *setting)
625 {
626         g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_DEFAULT);
627
628         return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->autoconnect_slaves;
629 }
630 NM_BACKPORT_SYMBOL (libnm_1_0_4, NMSettingConnectionAutoconnectSlaves, nm_setting_connection_get_autoconnect_slaves, (NMSettingConnection *setting), (setting));
631
632 NM_BACKPORT_SYMBOL (libnm_1_0_4, GType, nm_setting_connection_autoconnect_slaves_get_type, (void), ());
633
634 /**
635  * nm_setting_connection_get_num_secondaries:
636  * @setting: the #NMSettingConnection
637  *
638  * Returns: the number of configured secondary connection UUIDs
639  **/
640 guint32
641 nm_setting_connection_get_num_secondaries (NMSettingConnection *setting)
642 {
643         g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), 0);
644
645         return g_slist_length (NM_SETTING_CONNECTION_GET_PRIVATE (setting)->secondaries);
646 }
647
648 /**
649  * nm_setting_connection_get_secondary:
650  * @setting: the #NMSettingConnection
651  * @idx: the zero-based index of the secondary connection UUID entry
652  *
653  * Returns: the secondary connection UUID at index @idx
654  **/
655 const char *
656 nm_setting_connection_get_secondary (NMSettingConnection *setting, guint32 idx)
657 {
658         NMSettingConnectionPrivate *priv;
659
660         g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), NULL);
661
662         priv = NM_SETTING_CONNECTION_GET_PRIVATE (setting);
663         g_return_val_if_fail (idx <= g_slist_length (priv->secondaries), NULL);
664
665         return (const char *) g_slist_nth_data (priv->secondaries, idx);
666 }
667
668 /**
669  * nm_setting_connection_add_secondary:
670  * @setting: the #NMSettingConnection
671  * @sec_uuid: the secondary connection UUID to add
672  *
673  * Adds a new secondary connetion UUID to the setting.
674  *
675  * Returns: %TRUE if the secondary connection UUID was added; %FALSE if the UUID
676  * was already present
677  **/
678 gboolean
679 nm_setting_connection_add_secondary (NMSettingConnection *setting,
680                                      const char *sec_uuid)
681 {
682         NMSettingConnectionPrivate *priv;
683         GSList *iter;
684
685         g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), FALSE);
686         g_return_val_if_fail (sec_uuid != NULL, FALSE);
687         g_return_val_if_fail (sec_uuid[0] != '\0', FALSE);
688
689         priv = NM_SETTING_CONNECTION_GET_PRIVATE (setting);
690         for (iter = priv->secondaries; iter; iter = g_slist_next (iter)) {
691                 if (!strcmp (sec_uuid, (char *) iter->data))
692                         return FALSE;
693         }
694
695         priv->secondaries = g_slist_append (priv->secondaries, g_strdup (sec_uuid));
696         g_object_notify (G_OBJECT (setting), NM_SETTING_CONNECTION_SECONDARIES);
697         return TRUE;
698 }
699
700 /**
701  * nm_setting_connection_remove_secondary:
702  * @setting: the #NMSettingConnection
703  * @idx: index number of the secondary connection UUID
704  *
705  * Removes the secondary coonnection UUID at index @idx.
706  **/
707 void
708 nm_setting_connection_remove_secondary (NMSettingConnection *setting, guint32 idx)
709 {
710         NMSettingConnectionPrivate *priv;
711         GSList *elt;
712
713         g_return_if_fail (NM_IS_SETTING_CONNECTION (setting));
714
715         priv = NM_SETTING_CONNECTION_GET_PRIVATE (setting);
716         elt = g_slist_nth (priv->secondaries, idx);
717         g_return_if_fail (elt != NULL);
718
719         g_free (elt->data);
720         priv->secondaries = g_slist_delete_link (priv->secondaries, elt);
721         g_object_notify (G_OBJECT (setting), NM_SETTING_CONNECTION_SECONDARIES);
722 }
723
724 /**
725  * nm_setting_connection_remove_secondary_by_value:
726  * @setting: the #NMSettingConnection
727  * @sec_uuid: the secondary connection UUID to remove
728  *
729  * Removes the secondary coonnection UUID @sec_uuid.
730  *
731  * Returns: %TRUE if the secondary connection UUID was found and removed; %FALSE if it was not.
732  **/
733 gboolean
734 nm_setting_connection_remove_secondary_by_value (NMSettingConnection *setting,
735                                                  const char *sec_uuid)
736 {
737         NMSettingConnectionPrivate *priv;
738         GSList *iter;
739
740         g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), FALSE);
741         g_return_val_if_fail (sec_uuid != NULL, FALSE);
742         g_return_val_if_fail (sec_uuid[0] != '\0', FALSE);
743
744         priv = NM_SETTING_CONNECTION_GET_PRIVATE (setting);
745         for (iter = priv->secondaries; iter; iter = g_slist_next (iter)) {
746                 if (!strcmp (sec_uuid, (char *) iter->data)) {
747                         priv->secondaries = g_slist_delete_link (priv->secondaries, iter);
748                         g_object_notify (G_OBJECT (setting), NM_SETTING_CONNECTION_SECONDARIES);
749                         return TRUE;
750                 }
751         }
752         return FALSE;
753 }
754
755 /**
756  * nm_setting_connection_get_gateway_ping_timeout:
757  * @setting: the #NMSettingConnection
758  *
759  * Returns: the value contained in the #NMSettingConnection:gateway-ping-timeout
760  * property.
761  **/
762 guint32
763 nm_setting_connection_get_gateway_ping_timeout (NMSettingConnection *setting)
764 {
765         g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), 0);
766
767         return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->gateway_ping_timeout;
768 }
769
770 /**
771  * nm_setting_connection_get_metered:
772  * @setting: the #NMSettingConnection
773  *
774  * Returns: the #NMSettingConnection:metered property of the setting.
775  *
776  * Since: 1.2
777  **/
778 NMMetered
779 nm_setting_connection_get_metered (NMSettingConnection *setting)
780 {
781         g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting),
782                               NM_METERED_UNKNOWN);
783
784         return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->metered;
785 }
786
787 NM_BACKPORT_SYMBOL (libnm_1_0_6, NMMetered, nm_setting_connection_get_metered, (NMSettingConnection *setting), (setting));
788
789 NM_BACKPORT_SYMBOL (libnm_1_0_6, GType, nm_metered_get_type, (void), ());
790
791 /**
792  * nm_setting_connection_get_lldp:
793  * @setting: the #NMSettingConnection
794  *
795  * Returns the #NMSettingConnection:lldp property of the connection.
796  *
797  * Returns: a %NMSettingConnectionLldp which indicates whether LLDP must be
798  * enabled for the connection.
799  *
800  * Since: 1.2
801  **/
802 NMSettingConnectionLldp
803 nm_setting_connection_get_lldp (NMSettingConnection *setting)
804 {
805         g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), NM_SETTING_CONNECTION_LLDP_DEFAULT);
806
807         return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->lldp;
808 }
809
810 static void
811 _set_error_missing_base_setting (GError **error, const char *type)
812 {
813         g_set_error (error,
814                      NM_CONNECTION_ERROR,
815                      NM_CONNECTION_ERROR_MISSING_SETTING,
816                      _("setting required for connection of type '%s'"),
817                      type);
818         g_prefix_error (error, "%s: ", type);
819 }
820
821 static gboolean
822 verify (NMSetting *setting, NMConnection *connection, GError **error)
823 {
824         NMSettingConnectionPrivate *priv = NM_SETTING_CONNECTION_GET_PRIVATE (setting);
825         gboolean is_slave;
826         const char *slave_setting_type = NULL;
827         NMSetting *normerr_base_type = NULL;
828         const char *normerr_slave_setting_type = NULL;
829         const char *normerr_missing_slave_type = NULL;
830         const char *normerr_missing_slave_type_port = NULL;
831         gboolean normerr_base_setting = FALSE;
832
833         if (!priv->id) {
834                 g_set_error_literal (error,
835                                      NM_CONNECTION_ERROR,
836                                      NM_CONNECTION_ERROR_MISSING_PROPERTY,
837                                      _("property is missing"));
838                 g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_ID);
839                 return FALSE;
840         } else if (!priv->id[0]) {
841                 g_set_error_literal (error,
842                                      NM_CONNECTION_ERROR,
843                                      NM_CONNECTION_ERROR_INVALID_PROPERTY,
844                                      _("property is empty"));
845                 g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_ID);
846                 return FALSE;
847         }
848
849         if (priv->uuid && !nm_utils_is_uuid (priv->uuid)) {
850                 g_set_error (error,
851                              NM_CONNECTION_ERROR,
852                              NM_CONNECTION_ERROR_INVALID_PROPERTY,
853                              _("'%s' is not a valid UUID"),
854                              priv->uuid);
855                 g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_UUID);
856                 return FALSE;
857         }
858
859         if (priv->interface_name) {
860                 if (!nm_utils_iface_valid_name (priv->interface_name)) {
861                         g_set_error (error,
862                                      NM_CONNECTION_ERROR,
863                                      NM_CONNECTION_ERROR_INVALID_PROPERTY,
864                                      _("'%s' is not a valid interface name"),
865                                      priv->interface_name);
866                         g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_INTERFACE_NAME);
867                         return FALSE;
868                 }
869         }
870
871         if (!priv->type) {
872                 if (!connection || !(normerr_base_type = _nm_connection_find_base_type_setting (connection))) {
873                         g_set_error_literal (error,
874                                              NM_CONNECTION_ERROR,
875                                              NM_CONNECTION_ERROR_MISSING_PROPERTY,
876                                              _("property is missing"));
877                         g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_TYPE);
878                         return FALSE;
879                 }
880         } else {
881                 GType base_type;
882
883                 if (!priv->type[0]) {
884                         g_set_error_literal (error,
885                                              NM_CONNECTION_ERROR,
886                                              NM_CONNECTION_ERROR_INVALID_PROPERTY,
887                                              _("property is empty"));
888                         g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_TYPE);
889                         return FALSE;
890                 }
891
892                 base_type = nm_setting_lookup_type (priv->type);
893                 if (base_type == G_TYPE_INVALID || !_nm_setting_type_is_base_type (base_type)) {
894                         g_set_error (error,
895                                      NM_CONNECTION_ERROR,
896                                      NM_CONNECTION_ERROR_INVALID_PROPERTY,
897                                      _("connection type '%s' is not valid"),
898                                      priv->type);
899                         g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_TYPE);
900                         return FALSE;
901                 }
902
903                 /* Make sure the corresponding 'type' item is present */
904                 if (   connection
905                     && !nm_connection_get_setting_by_name (connection, priv->type)) {
906                         NMSetting *s_base;
907                         NMConnection *connection2;
908
909                         s_base = g_object_new (base_type, NULL);
910                         connection2 = nm_simple_connection_new_clone (connection);
911                         nm_connection_add_setting (connection2, s_base);
912
913                         normerr_base_setting = nm_setting_verify (s_base, connection2, NULL);
914
915                         g_object_unref (connection2);
916
917                         if (!normerr_base_setting) {
918                                 _set_error_missing_base_setting (error, priv->type);
919                                 return FALSE;
920                         }
921                 }
922         }
923
924         is_slave = FALSE;
925         if (priv->slave_type)
926                 is_slave = _nm_setting_slave_type_is_valid (priv->slave_type, &slave_setting_type);
927
928         if (priv->slave_type && !is_slave) {
929                 g_set_error (error,
930                              NM_CONNECTION_ERROR,
931                              NM_CONNECTION_ERROR_INVALID_PROPERTY,
932                              _("Unknown slave type '%s'"), priv->slave_type);
933                 g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_SLAVE_TYPE);
934                 return FALSE;
935         }
936
937         if (is_slave) {
938                 if (!priv->master) {
939                         g_set_error (error,
940                                      NM_CONNECTION_ERROR,
941                                      NM_CONNECTION_ERROR_MISSING_PROPERTY,
942                                      _("Slave connections need a valid '%s' property"), NM_SETTING_CONNECTION_MASTER);
943                         g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_MASTER);
944                         return FALSE;
945                 }
946                 if (   slave_setting_type
947                     && connection
948                     && !nm_connection_get_setting_by_name (connection, slave_setting_type))
949                         normerr_slave_setting_type = slave_setting_type;
950         } else {
951                 if (priv->master) {
952                         const char *slave_type;
953                         NMSetting *s_port;
954
955                         if (   connection
956                             && (slave_type = _nm_connection_detect_slave_type (connection, &s_port))) {
957                                 normerr_missing_slave_type = slave_type;
958                                 normerr_missing_slave_type_port = nm_setting_get_name (s_port);
959                         } else {
960                                 g_set_error (error,
961                                              NM_CONNECTION_ERROR,
962                                              NM_CONNECTION_ERROR_MISSING_PROPERTY,
963                                              _("Cannot set '%s' without '%s'"),
964                                              NM_SETTING_CONNECTION_MASTER, NM_SETTING_CONNECTION_SLAVE_TYPE);
965                                 g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_SLAVE_TYPE);
966                                 return FALSE;
967                         }
968                 }
969         }
970
971         if (priv->metered != NM_METERED_UNKNOWN &&
972             priv->metered != NM_METERED_YES &&
973             priv->metered != NM_METERED_NO) {
974                 g_set_error (error,
975                              NM_CONNECTION_ERROR,
976                              NM_CONNECTION_ERROR_INVALID_PROPERTY,
977                              _("metered value %d is not valid"), priv->metered);
978                 g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME,
979                                 NM_SETTING_CONNECTION_METERED);
980                 return FALSE;
981         }
982
983         /* *** errors above here should be always fatal, below NORMALIZABLE_ERROR *** */
984
985         if (!priv->uuid) {
986                 g_set_error_literal (error,
987                                      NM_CONNECTION_ERROR,
988                                      NM_CONNECTION_ERROR_MISSING_PROPERTY,
989                                      _("property is missing"));
990                 g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_UUID);
991                 return NM_SETTING_VERIFY_NORMALIZABLE_ERROR;
992         }
993
994         if (normerr_base_type) {
995                 g_set_error (error,
996                              NM_CONNECTION_ERROR,
997                              NM_CONNECTION_ERROR_MISSING_PROPERTY,
998                              _("property type should be set to '%s'"),
999                              nm_setting_get_name (normerr_base_type));
1000                 g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_TYPE);
1001                 return NM_SETTING_VERIFY_NORMALIZABLE_ERROR;
1002         }
1003
1004         if (normerr_base_setting) {
1005                 _set_error_missing_base_setting (error, priv->type);
1006                 return NM_SETTING_VERIFY_NORMALIZABLE_ERROR;
1007         }
1008
1009         if (normerr_slave_setting_type) {
1010                 g_set_error (error,
1011                              NM_CONNECTION_ERROR,
1012                              NM_CONNECTION_ERROR_MISSING_SETTING,
1013                              _("slave-type '%s' requires a '%s' setting in the connection"),
1014                              priv->slave_type, normerr_slave_setting_type);
1015                 g_prefix_error (error, "%s: ", normerr_slave_setting_type);
1016                 return NM_SETTING_VERIFY_NORMALIZABLE_ERROR;
1017         }
1018
1019         if (normerr_missing_slave_type) {
1020                 g_set_error (error,
1021                              NM_CONNECTION_ERROR,
1022                              NM_CONNECTION_ERROR_MISSING_PROPERTY,
1023                              _("Detect a slave connection with '%s' set and a port type '%s'. '%s' should be set to '%s'"),
1024                              NM_SETTING_CONNECTION_MASTER, normerr_missing_slave_type_port,
1025                              NM_SETTING_CONNECTION_SLAVE_TYPE, normerr_missing_slave_type);
1026                 g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_SLAVE_TYPE);
1027                 return NM_SETTING_VERIFY_NORMALIZABLE_ERROR;
1028         }
1029
1030         return TRUE;
1031 }
1032
1033 static const char *
1034 find_virtual_interface_name (GVariant *connection_dict)
1035 {
1036         GVariant *setting_dict;
1037         const char *interface_name;
1038
1039         setting_dict = g_variant_lookup_value (connection_dict, NM_SETTING_BOND_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
1040         if (!setting_dict)
1041                 setting_dict = g_variant_lookup_value (connection_dict, NM_SETTING_BRIDGE_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
1042         if (!setting_dict)
1043                 setting_dict = g_variant_lookup_value (connection_dict, NM_SETTING_TEAM_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
1044         if (!setting_dict)
1045                 setting_dict = g_variant_lookup_value (connection_dict, NM_SETTING_VLAN_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
1046
1047         if (!setting_dict)
1048                 return NULL;
1049
1050         /* All of the deprecated virtual interface name properties were named "interface-name". */
1051         if (!g_variant_lookup (setting_dict, "interface-name", "&s", &interface_name))
1052                 interface_name = NULL;
1053
1054         g_variant_unref (setting_dict);
1055         return interface_name;
1056 }
1057
1058 static void
1059 nm_setting_connection_set_interface_name (NMSetting *setting,
1060                                           GVariant *connection_dict,
1061                                           const char *property,
1062                                           GVariant *value)
1063 {
1064         const char *interface_name;
1065
1066         /* For compatibility reasons, if there is an invalid virtual interface name,
1067          * we need to make verification fail, even if that virtual name would be
1068          * overridden by a valid connection.interface-name.
1069          */
1070         interface_name = find_virtual_interface_name (connection_dict);
1071         if (!interface_name || nm_utils_iface_valid_name (interface_name))
1072                 interface_name = g_variant_get_string (value, NULL);
1073
1074         g_object_set (G_OBJECT (setting),
1075                       NM_SETTING_CONNECTION_INTERFACE_NAME, interface_name,
1076                       NULL);
1077 }
1078
1079 static void
1080 nm_setting_connection_no_interface_name (NMSetting *setting,
1081                                          GVariant *connection_dict,
1082                                          const char *property)
1083 {
1084         const char *virtual_interface_name;
1085
1086         virtual_interface_name = find_virtual_interface_name (connection_dict);
1087         g_object_set (G_OBJECT (setting),
1088                       NM_SETTING_CONNECTION_INTERFACE_NAME, virtual_interface_name,
1089                       NULL);
1090 }
1091
1092 static gboolean
1093 compare_property (NMSetting *setting,
1094                   NMSetting *other,
1095                   const GParamSpec *prop_spec,
1096                   NMSettingCompareFlags flags)
1097 {
1098         /* Handle ignore ID */
1099         if (   (flags & NM_SETTING_COMPARE_FLAG_IGNORE_ID)
1100             && g_strcmp0 (prop_spec->name, NM_SETTING_CONNECTION_ID) == 0)
1101                 return TRUE;
1102
1103         /* Handle ignore timestamp */
1104         if (   (flags & NM_SETTING_COMPARE_FLAG_IGNORE_TIMESTAMP)
1105             && g_strcmp0 (prop_spec->name, NM_SETTING_CONNECTION_TIMESTAMP) == 0)
1106                 return TRUE;
1107
1108         /* Otherwise chain up to parent to handle generic compare */
1109         return NM_SETTING_CLASS (nm_setting_connection_parent_class)->compare_property (setting, other, prop_spec, flags);
1110 }
1111
1112 static void
1113 nm_setting_connection_init (NMSettingConnection *setting)
1114 {
1115 }
1116
1117 static void
1118 finalize (GObject *object)
1119 {
1120         NMSettingConnectionPrivate *priv = NM_SETTING_CONNECTION_GET_PRIVATE (object);
1121
1122         g_free (priv->id);
1123         g_free (priv->uuid);
1124         g_free (priv->interface_name);
1125         g_free (priv->type);
1126         g_free (priv->zone);
1127         g_free (priv->master);
1128         g_free (priv->slave_type);
1129         g_slist_free_full (priv->permissions, (GDestroyNotify) permission_free);
1130         g_slist_free_full (priv->secondaries, g_free);
1131
1132         G_OBJECT_CLASS (nm_setting_connection_parent_class)->finalize (object);
1133 }
1134
1135 static GSList *
1136 perm_strv_to_permlist (char **strv)
1137 {
1138         GSList *list = NULL;
1139         int i;
1140
1141         if (!strv)
1142                 return NULL;
1143
1144         for (i = 0; strv[i]; i++) {
1145                 Permission *p;
1146
1147                 p = permission_new_from_str (strv[i]);
1148                 if (p)
1149                         list = g_slist_append (list, p);
1150         }
1151
1152         return list;
1153 }
1154
1155 static void
1156 set_property (GObject *object, guint prop_id,
1157               const GValue *value, GParamSpec *pspec)
1158 {
1159         NMSettingConnectionPrivate *priv = NM_SETTING_CONNECTION_GET_PRIVATE (object);
1160
1161         switch (prop_id) {
1162         case PROP_ID:
1163                 g_free (priv->id);
1164                 priv->id = g_value_dup_string (value);
1165                 break;
1166         case PROP_UUID:
1167                 g_free (priv->uuid);
1168                 priv->uuid = g_value_dup_string (value);
1169                 break;
1170         case PROP_INTERFACE_NAME:
1171                 g_free (priv->interface_name);
1172                 priv->interface_name = g_value_dup_string (value);
1173                 break;
1174         case PROP_TYPE:
1175                 g_free (priv->type);
1176                 priv->type = g_value_dup_string (value);
1177                 break;
1178         case PROP_PERMISSIONS:
1179                 g_slist_free_full (priv->permissions, (GDestroyNotify) permission_free);
1180                 priv->permissions = perm_strv_to_permlist (g_value_get_boxed (value));
1181                 break;
1182         case PROP_AUTOCONNECT:
1183                 priv->autoconnect = g_value_get_boolean (value);
1184                 break;
1185         case PROP_AUTOCONNECT_PRIORITY:
1186                 priv->autoconnect_priority = g_value_get_int (value);
1187                 break;
1188         case PROP_TIMESTAMP:
1189                 priv->timestamp = g_value_get_uint64 (value);
1190                 break;
1191         case PROP_READ_ONLY:
1192                 priv->read_only = g_value_get_boolean (value);
1193                 break;
1194         case PROP_ZONE:
1195                 g_free (priv->zone);
1196                 priv->zone = g_value_dup_string (value);
1197                 break;
1198         case PROP_MASTER:
1199                 g_free (priv->master);
1200                 priv->master = g_value_dup_string (value);
1201                 break;
1202         case PROP_SLAVE_TYPE:
1203                 g_free (priv->slave_type);
1204                 priv->slave_type = g_value_dup_string (value);
1205                 break;
1206         case PROP_AUTOCONNECT_SLAVES:
1207                 priv->autoconnect_slaves = g_value_get_enum (value);
1208                 break;
1209         case PROP_SECONDARIES:
1210                 g_slist_free_full (priv->secondaries, g_free);
1211                 priv->secondaries = _nm_utils_strv_to_slist (g_value_get_boxed (value), TRUE);
1212                 break;
1213         case PROP_GATEWAY_PING_TIMEOUT:
1214                 priv->gateway_ping_timeout = g_value_get_uint (value);
1215                 break;
1216         case PROP_METERED:
1217                 priv->metered = g_value_get_enum (value);
1218                 break;
1219         case PROP_LLDP:
1220                 priv->lldp = g_value_get_int (value);
1221                 break;
1222         default:
1223                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1224                 break;
1225         }
1226 }
1227
1228 static char **
1229 perm_permlist_to_strv (GSList *permlist)
1230 {
1231         GPtrArray *strings;
1232         GSList *iter;
1233
1234         strings = g_ptr_array_new ();
1235         for (iter = permlist; iter; iter = g_slist_next (iter))
1236                 g_ptr_array_add (strings, permission_to_string ((Permission *) iter->data));
1237         g_ptr_array_add (strings, NULL);
1238
1239         return (char **) g_ptr_array_free (strings, FALSE);
1240 }
1241
1242 static void
1243 get_property (GObject *object, guint prop_id,
1244               GValue *value, GParamSpec *pspec)
1245 {
1246         NMSettingConnection *setting = NM_SETTING_CONNECTION (object);
1247         NMSettingConnectionPrivate *priv = NM_SETTING_CONNECTION_GET_PRIVATE (setting);
1248
1249         switch (prop_id) {
1250         case PROP_ID:
1251                 g_value_set_string (value, nm_setting_connection_get_id (setting));
1252                 break;
1253         case PROP_UUID:
1254                 g_value_set_string (value, nm_setting_connection_get_uuid (setting));
1255                 break;
1256         case PROP_INTERFACE_NAME:
1257                 g_value_set_string (value, nm_setting_connection_get_interface_name (setting));
1258                 break;
1259         case PROP_TYPE:
1260                 g_value_set_string (value, nm_setting_connection_get_connection_type (setting));
1261                 break;
1262         case PROP_PERMISSIONS:
1263                 g_value_take_boxed (value, perm_permlist_to_strv (priv->permissions));
1264                 break;
1265         case PROP_AUTOCONNECT:
1266                 g_value_set_boolean (value, nm_setting_connection_get_autoconnect (setting));
1267                 break;
1268         case PROP_AUTOCONNECT_PRIORITY:
1269                 g_value_set_int (value, nm_setting_connection_get_autoconnect_priority (setting));
1270                 break;
1271         case PROP_TIMESTAMP:
1272                 g_value_set_uint64 (value, nm_setting_connection_get_timestamp (setting));
1273                 break;
1274         case PROP_READ_ONLY:
1275                 g_value_set_boolean (value, nm_setting_connection_get_read_only (setting));
1276                 break;
1277         case PROP_ZONE:
1278                 g_value_set_string (value, nm_setting_connection_get_zone (setting));
1279                 break;
1280         case PROP_MASTER:
1281                 g_value_set_string (value, nm_setting_connection_get_master (setting));
1282                 break;
1283         case PROP_SLAVE_TYPE:
1284                 g_value_set_string (value, nm_setting_connection_get_slave_type (setting));
1285                 break;
1286         case PROP_AUTOCONNECT_SLAVES:
1287                 g_value_set_enum (value, nm_setting_connection_get_autoconnect_slaves (setting));
1288                 break;
1289         case PROP_SECONDARIES:
1290                 g_value_take_boxed (value, _nm_utils_slist_to_strv (priv->secondaries, TRUE));
1291                 break;
1292         case PROP_GATEWAY_PING_TIMEOUT:
1293                 g_value_set_uint (value, priv->gateway_ping_timeout);
1294                 break;
1295         case PROP_METERED:
1296                 g_value_set_enum (value, priv->metered);
1297                 break;
1298         case PROP_LLDP:
1299                 g_value_set_int (value, priv->lldp);
1300                 break;
1301         default:
1302                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1303                 break;
1304         }
1305 }
1306
1307 static void
1308 nm_setting_connection_class_init (NMSettingConnectionClass *setting_class)
1309 {
1310         GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
1311         NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
1312
1313         g_type_class_add_private (setting_class, sizeof (NMSettingConnectionPrivate));
1314
1315         /* virtual methods */
1316         object_class->set_property = set_property;
1317         object_class->get_property = get_property;
1318         object_class->finalize     = finalize;
1319         parent_class->verify       = verify;
1320         parent_class->compare_property = compare_property;
1321
1322         /* Properties */
1323
1324         /**
1325          * NMSettingConnection:id:
1326          *
1327          * A human readable unique identifier for the connection, like "Work Wi-Fi"
1328          * or "T-Mobile 3G".
1329          **/
1330         /* ---ifcfg-rh---
1331          * property: id
1332          * variable: NAME(+)
1333          * description: User friendly name for the connection profile.
1334          * ---end---
1335          */
1336         g_object_class_install_property
1337                 (object_class, PROP_ID,
1338                  g_param_spec_string (NM_SETTING_CONNECTION_ID, "", "",
1339                                       NULL,
1340                                       G_PARAM_READWRITE |
1341                                       NM_SETTING_PARAM_FUZZY_IGNORE |
1342                                       G_PARAM_STATIC_STRINGS));
1343
1344         /**
1345          * NMSettingConnection:uuid:
1346          *
1347          * A universally unique identifier for the connection, for example generated
1348          * with libuuid.  It should be assigned when the connection is created, and
1349          * never changed as long as the connection still applies to the same
1350          * network.  For example, it should not be changed when the
1351          * #NMSettingConnection:id property or #NMSettingIP4Config changes, but
1352          * might need to be re-created when the Wi-Fi SSID, mobile broadband network
1353          * provider, or #NMSettingConnection:type property changes.
1354          *
1355          * The UUID must be in the format "2815492f-7e56-435e-b2e9-246bd7cdc664"
1356          * (ie, contains only hexadecimal characters and "-").  A suitable UUID may
1357          * be generated by nm_utils_uuid_generate() or
1358          * nm_utils_uuid_generate_from_string().
1359          **/
1360         /* ---ifcfg-rh---
1361          * property: uuid
1362          * variable: UUID(+)
1363          * description: UUID for the connection profile. When missing, NetworkManager
1364          *   creates the UUID itself (by hashing the file).
1365          * ---end---
1366          */
1367         g_object_class_install_property
1368                 (object_class, PROP_UUID,
1369                  g_param_spec_string (NM_SETTING_CONNECTION_UUID, "", "",
1370                                       NULL,
1371                                       G_PARAM_READWRITE |
1372                                       NM_SETTING_PARAM_FUZZY_IGNORE |
1373                                       G_PARAM_STATIC_STRINGS));
1374
1375         /**
1376          * NMSettingConnection:interface-name:
1377          *
1378          * The name of the network interface this connection is bound to. If not
1379          * set, then the connection can be attached to any interface of the
1380          * appropriate type (subject to restrictions imposed by other settings).
1381          *
1382          * For software devices this specifies the name of the created device.
1383          *
1384          * For connection types where interface names cannot easily be made
1385          * persistent (e.g. mobile broadband or USB Ethernet), this property should
1386          * not be used. Setting this property restricts the interfaces a connection
1387          * can be used with, and if interface names change or are reordered the
1388          * connection may be applied to the wrong interface.
1389          **/
1390         /* ---ifcfg-rh---
1391          * property: interface-name
1392          * variable: DEVICE
1393          * description: Interface name of the device this profile is bound to. The variable
1394          *   can be left out when the profile should apply for more devices. Note that DEVICE
1395          *   can be required for some connection types.
1396          * ---end---
1397          */
1398         g_object_class_install_property
1399                 (object_class, PROP_INTERFACE_NAME,
1400                  g_param_spec_string (NM_SETTING_CONNECTION_INTERFACE_NAME, "", "",
1401                                       NULL,
1402                                       G_PARAM_READWRITE |
1403                                       NM_SETTING_PARAM_INFERRABLE |
1404                                       G_PARAM_STATIC_STRINGS));
1405         _nm_setting_class_override_property (parent_class, NM_SETTING_CONNECTION_INTERFACE_NAME,
1406                                              G_VARIANT_TYPE_STRING,
1407                                              NULL,
1408                                              nm_setting_connection_set_interface_name,
1409                                              nm_setting_connection_no_interface_name);
1410
1411         /**
1412          * NMSettingConnection:type:
1413          *
1414          * Base type of the connection. For hardware-dependent connections, should
1415          * contain the setting name of the hardware-type specific setting (ie,
1416          * "802-3-ethernet" or "802-11-wireless" or "bluetooth", etc), and for
1417          * non-hardware dependent connections like VPN or otherwise, should contain
1418          * the setting name of that setting type (ie, "vpn" or "bridge", etc).
1419          **/
1420         /* ---ifcfg-rh---
1421          * property: type
1422          * variable: TYPE (DEVICETYPE, DEVICE)
1423          * values: Ethernet, Wireless, InfiniBand, Bridge, Bond, Vlan, Team, TeamPort
1424          * description: Base type of the connection. DEVICETYPE is used for teaming
1425          *   connections.
1426          * example: TYPE=Ethernet; TYPE=Bond; TYPE=Bridge; DEVICETYPE=TeamPort
1427          * ---end---
1428          */
1429         g_object_class_install_property
1430                 (object_class, PROP_TYPE,
1431                  g_param_spec_string (NM_SETTING_CONNECTION_TYPE, "", "",
1432                                       NULL,
1433                                       G_PARAM_READWRITE |
1434                                       NM_SETTING_PARAM_INFERRABLE |
1435                                       G_PARAM_STATIC_STRINGS));
1436
1437         /**
1438          * NMSettingConnection:permissions:
1439          *
1440          * An array of strings defining what access a given user has to this
1441          * connection.  If this is %NULL or empty, all users are allowed to access
1442          * this connection.  Otherwise a user is allowed to access this connection
1443          * if and only if they are in this list. Each entry is of the form
1444          * "[type]:[id]:[reserved]"; for example, "user:dcbw:blah".
1445          *
1446          * At this time only the "user" [type] is allowed.  Any other values are
1447          * ignored and reserved for future use.  [id] is the username that this
1448          * permission refers to, which may not contain the ":" character. Any
1449          * [reserved] information present must be ignored and is reserved for future
1450          * use.  All of [type], [id], and [reserved] must be valid UTF-8.
1451          */
1452         /* ---ifcfg-rh---
1453          * property: permissions
1454          * variable: USERS(+)
1455          * description: USERS restrict the access for this conenction to certain
1456          *   users only.
1457          * example: USERS="joe bob"
1458          * ---end---
1459          */
1460         g_object_class_install_property
1461                 (object_class, PROP_PERMISSIONS,
1462                  g_param_spec_boxed (NM_SETTING_CONNECTION_PERMISSIONS, "", "",
1463                                      G_TYPE_STRV,
1464                                      G_PARAM_READWRITE |
1465                                      G_PARAM_STATIC_STRINGS));
1466
1467         /**
1468          * NMSettingConnection:autoconnect:
1469          *
1470          * Whether or not the connection should be automatically connected by
1471          * NetworkManager when the resources for the connection are available.
1472          * %TRUE to automatically activate the connection, %FALSE to require manual
1473          * intervention to activate the connection.
1474          **/
1475         /* ---ifcfg-rh---
1476          * property: autoconnect
1477          * variable: ONBOOT
1478          * default: yes
1479          * description: Whether the connection should be autoconnected (not only while booting).
1480          * ---end---
1481          */
1482         g_object_class_install_property
1483                 (object_class, PROP_AUTOCONNECT,
1484                  g_param_spec_boolean (NM_SETTING_CONNECTION_AUTOCONNECT, "", "",
1485                                        TRUE,
1486                                        G_PARAM_READWRITE |
1487                                        G_PARAM_CONSTRUCT |
1488                                        NM_SETTING_PARAM_FUZZY_IGNORE |
1489                                        G_PARAM_STATIC_STRINGS));
1490
1491         /**
1492          * NMSettingConnection:autoconnect-priority:
1493          *
1494          * The autoconnect priority. If the connection is set to autoconnect,
1495          * connections with higher priority will be preferred. Defaults to 0.
1496          * The higher number means higher priority.
1497          **/
1498         /* ---ifcfg-rh---
1499          * property: autoconnect-priority
1500          * variable: AUTOCONNECT_PRIORITY(+)
1501          * values: -999 to 999
1502          * default: 0
1503          * description: Connection priority for automatic activation. Connections with
1504          *  higher numbers are preferred when selecting profiles for automatic activation.
1505          * example: AUTOCONNECT_PRIORITY=20
1506          * ---end---
1507          */
1508         g_object_class_install_property
1509             (object_class, PROP_AUTOCONNECT_PRIORITY,
1510              g_param_spec_int (NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY, "", "",
1511                                NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_MIN,
1512                                NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_MAX,
1513                                NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_DEFAULT,
1514                                G_PARAM_READWRITE |
1515                                G_PARAM_CONSTRUCT |
1516                                NM_SETTING_PARAM_FUZZY_IGNORE |
1517                                G_PARAM_STATIC_STRINGS));
1518
1519         /**
1520          * NMSettingConnection:timestamp:
1521          *
1522          * The time, in seconds since the Unix Epoch, that the connection was last
1523          * _successfully_ fully activated.
1524          *
1525          * NetworkManager updates the connection timestamp periodically when the
1526          * connection is active to ensure that an active connection has the latest
1527          * timestamp. The property is only meant for reading (changes to this
1528          * property will not be preserved).
1529          **/
1530         g_object_class_install_property
1531                 (object_class, PROP_TIMESTAMP,
1532                  g_param_spec_uint64 (NM_SETTING_CONNECTION_TIMESTAMP, "", "",
1533                                       0, G_MAXUINT64, 0,
1534                                       G_PARAM_READWRITE |
1535                                       G_PARAM_CONSTRUCT |
1536                                       NM_SETTING_PARAM_FUZZY_IGNORE |
1537                                       G_PARAM_STATIC_STRINGS));
1538
1539         /**
1540          * NMSettingConnection:read-only:
1541          *
1542          * %FALSE if the connection can be modified using the provided settings
1543          * service's D-Bus interface with the right privileges, or %TRUE if the
1544          * connection is read-only and cannot be modified.
1545          **/
1546         g_object_class_install_property
1547                 (object_class, PROP_READ_ONLY,
1548                  g_param_spec_boolean (NM_SETTING_CONNECTION_READ_ONLY, "", "",
1549                                        FALSE,
1550                                        G_PARAM_READWRITE |
1551                                        G_PARAM_CONSTRUCT |
1552                                        NM_SETTING_PARAM_FUZZY_IGNORE |
1553                                        G_PARAM_STATIC_STRINGS));
1554
1555         /**
1556          * NMSettingConnection:zone:
1557          *
1558          * The trust level of a the connection.  Free form case-insensitive string
1559          * (for example "Home", "Work", "Public").  %NULL or unspecified zone means
1560          * the connection will be placed in the default zone as defined by the
1561          * firewall.
1562          *
1563          * When updating this property on a currently activated connection,
1564          * the change takes effect immediately.
1565          **/
1566         /* ---ifcfg-rh---
1567          * property: zone
1568          * variable: ZONE(+)
1569          * description: Trust level of this connection. The string is usually used
1570          *   for a firewall.
1571          * example: ZONE=Work
1572          * ---end---
1573          */
1574         g_object_class_install_property
1575                 (object_class, PROP_ZONE,
1576                  g_param_spec_string (NM_SETTING_CONNECTION_ZONE, "", "",
1577                                       NULL,
1578                                       G_PARAM_READWRITE |
1579                                       G_PARAM_CONSTRUCT |
1580                                       NM_SETTING_PARAM_FUZZY_IGNORE |
1581                                       NM_SETTING_PARAM_REAPPLY_IMMEDIATELY |
1582                                       G_PARAM_STATIC_STRINGS));
1583
1584         /**
1585          * NMSettingConnection:master:
1586          *
1587          * Interface name of the master device or UUID of the master connection.
1588          **/
1589         /* ---ifcfg-rh---
1590          * property: master
1591          * variable: MASTER, TEAM_MASTER, BRIDGE
1592          * description: Reference to master connection. The variable used depends on
1593          *   the connection type.
1594          * ---end---
1595          */
1596         g_object_class_install_property
1597                 (object_class, PROP_MASTER,
1598                  g_param_spec_string (NM_SETTING_CONNECTION_MASTER, "", "",
1599                                       NULL,
1600                                       G_PARAM_READWRITE |
1601                                       NM_SETTING_PARAM_FUZZY_IGNORE |
1602                                       NM_SETTING_PARAM_INFERRABLE |
1603                                       G_PARAM_STATIC_STRINGS));
1604
1605         /**
1606          * NMSettingConnection:slave-type:
1607          *
1608          * Setting name of the device type of this slave's master connection (eg,
1609          * %NM_SETTING_BOND_SETTING_NAME), or %NULL if this connection is not a
1610          * slave.
1611          **/
1612         /* ---ifcfg-rh---
1613          * property: slave-type
1614          * variable: MASTER, TEAM_MASTER, DEVICETYPE, BRIDGE
1615          * description: Slave type doesn't map directly to a variable, but it is
1616          *   recognized using different variables.  MASTER for bonding,
1617          *   TEAM_MASTER and DEVICETYPE for teaming, BRIDGE for bridging.
1618          * ---end---
1619          */
1620         g_object_class_install_property
1621                 (object_class, PROP_SLAVE_TYPE,
1622                  g_param_spec_string (NM_SETTING_CONNECTION_SLAVE_TYPE, "", "",
1623                                       NULL,
1624                                       G_PARAM_READWRITE |
1625                                       NM_SETTING_PARAM_FUZZY_IGNORE |
1626                                       NM_SETTING_PARAM_INFERRABLE |
1627                                       G_PARAM_STATIC_STRINGS));
1628
1629         /**
1630          * NMSettingConnection:autoconnect-slaves:
1631          *
1632          * Whether or not slaves of this connection should be automatically brought up
1633          * when NetworkManager activates this connection. This only has a real effect
1634          * for master connections.
1635          * The permitted values are: 0: leave slave connections untouched,
1636          * 1: activate all the slave connections with this connection, -1: default.
1637          * If -1 (default) is set, global connection.autoconnect-slaves is read to
1638          * determine the real value. If it is default as well, this fallbacks to 0.
1639          *
1640          * Since: 1.2
1641          **/
1642         /* ---ifcfg-rh---
1643          * property: autoconnect-slaves
1644          * variable: AUTOCONNECT-SLAVES(+)
1645          * default: missing variable means global default
1646          * description: Whether slaves of this connection should be auto-connected
1647          *   when this connection is activated.
1648          * ---end---
1649          */
1650         g_object_class_install_property
1651                 (object_class, PROP_AUTOCONNECT_SLAVES,
1652                  g_param_spec_enum (NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES, "", "",
1653                                     NM_TYPE_SETTING_CONNECTION_AUTOCONNECT_SLAVES,
1654                                     NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES_DEFAULT,
1655                                     G_PARAM_READWRITE |
1656                                     G_PARAM_CONSTRUCT |
1657                                     NM_SETTING_PARAM_FUZZY_IGNORE |
1658                                     G_PARAM_STATIC_STRINGS));
1659
1660         /**
1661          * NMSettingConnection:secondaries:
1662          *
1663          * List of connection UUIDs that should be activated when the base
1664          * connection itself is activated. Currently only VPN connections are
1665          * supported.
1666          **/
1667         /* ---ifcfg-rh---
1668          * property: secondaries
1669          * variable: SECONDARY_UUIDS(+)
1670          * description: UUID of VPN connections that should be activated
1671          *   together with this connection.
1672          * ---end---
1673          */
1674         g_object_class_install_property
1675                 (object_class, PROP_SECONDARIES,
1676                  g_param_spec_boxed (NM_SETTING_CONNECTION_SECONDARIES, "", "",
1677                                      G_TYPE_STRV,
1678                                      G_PARAM_READWRITE |
1679                                      NM_SETTING_PARAM_FUZZY_IGNORE |
1680                                      G_PARAM_STATIC_STRINGS));
1681
1682         /**
1683          * NMSettingConnection:gateway-ping-timeout:
1684          *
1685          * If greater than zero, delay success of IP addressing until either the
1686          * timeout is reached, or an IP gateway replies to a ping.
1687          **/
1688         /* ---ifcfg-rh---
1689          * property: gateway-ping-timeout
1690          * variable: GATEWAY_PING_TIMEOUT(+)
1691          * default: 0
1692          * description: If greater than zero, the IP connectivity will be checked by
1693          *   pinging the gateway and waiting for the specified timeout (in seconds).
1694          * example: GATEWAY_PING_TIMEOUT=5
1695          * ---end---
1696          */
1697         g_object_class_install_property
1698                 (object_class, PROP_GATEWAY_PING_TIMEOUT,
1699                  g_param_spec_uint (NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT, "", "",
1700                                     0, 600, 0,
1701                                     G_PARAM_READWRITE |
1702                                     G_PARAM_CONSTRUCT |
1703                                     G_PARAM_STATIC_STRINGS));
1704
1705         /**
1706          * NMSettingConnection:metered:
1707          *
1708          * Whether the connection is metered.
1709          *
1710          * When updating this property on a currently activated connection,
1711          * the change takes effect immediately.
1712          *
1713          * Since: 1.2
1714          **/
1715         /* ---ifcfg-rh---
1716          * property: metered
1717          * variable: CONNECTION_METERED
1718          * values: yes,no,unknown
1719          * description: Whether the device is metered
1720          * example: CONNECTION_METERED=yes
1721          * ---end---
1722          */
1723         g_object_class_install_property
1724                 (object_class, PROP_METERED,
1725                  g_param_spec_enum (NM_SETTING_CONNECTION_METERED, "", "",
1726                                     NM_TYPE_METERED,
1727                                     NM_METERED_UNKNOWN,
1728                                     G_PARAM_READWRITE |
1729                                     NM_SETTING_PARAM_REAPPLY_IMMEDIATELY |
1730                                     G_PARAM_STATIC_STRINGS));
1731
1732         /**
1733          * NMSettingConnection:lldp:
1734          *
1735          * Whether LLDP is enabled for the connection.
1736          *
1737          * Since: 1.2
1738          **/
1739         /* ---ifcfg-rh---
1740          * property: lldp
1741          * variable: LLDP
1742          * values: boolean value or 'rx'
1743          * default: missing variable means global default
1744          * description: whether LLDP is enabled for the connection
1745          * example: LLDP=no
1746          * ---end---
1747          */
1748         g_object_class_install_property
1749                 (object_class, PROP_LLDP,
1750                  g_param_spec_int (NM_SETTING_CONNECTION_LLDP, "", "",
1751                                    G_MININT32, G_MAXINT32, NM_SETTING_CONNECTION_LLDP_DEFAULT,
1752                                    NM_SETTING_PARAM_FUZZY_IGNORE |
1753                                    G_PARAM_READWRITE |
1754                                    G_PARAM_CONSTRUCT |
1755                                    G_PARAM_STATIC_STRINGS));
1756 }