1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2
3 /*
4 * Weiping Pan <wpan@redhat.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA.
20 *
21 * (C) Copyright 2011 - 2013 Red Hat, Inc.
22 */
23
24 #include <stdlib.h>
25 #include <string.h>
26 #include <dbus/dbus-glib.h>
27 #include <glib/gi18n.h>
28
29 #include "nm-setting-vlan.h"
30 #include "nm-param-spec-specialized.h"
31 #include "nm-utils.h"
32 #include "nm-dbus-glib-types.h"
33 #include "nm-setting-connection.h"
34 #include "nm-setting-private.h"
35
36 /**
37 * SECTION:nm-setting-vlan
38 * @short_description: Describes connection properties for VLAN interfaces
39 * @include: nm-setting-vlan.h
40 *
41 * The #NMSettingVlan object is a #NMSetting subclass that describes properties
42 * necessary for connection to VLAN interfaces.
43 **/
44
45 /**
46 * nm_setting_vlan_error_quark:
47 *
48 * Registers an error quark for #NMSettingVlan if necessary.
49 *
50 * Returns: the error quark used for #NMSettingVlan errors.
51 **/
52 GQuark
53 nm_setting_vlan_error_quark (void)
54 {
55 static GQuark quark;
56
57 if (G_UNLIKELY (!quark))
58 quark = g_quark_from_static_string ("nm-setting-vlan-error-quark");
59 return quark;
60 }
61
62 G_DEFINE_TYPE_WITH_CODE (NMSettingVlan, nm_setting_vlan, NM_TYPE_SETTING,
63 _nm_register_setting (NM_SETTING_VLAN_SETTING_NAME,
64 g_define_type_id,
65 1,
66 NM_SETTING_VLAN_ERROR))
67 NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_VLAN)
68
69 #define NM_SETTING_VLAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_VLAN, NMSettingVlanPrivate))
70
71 typedef struct {
72 char *iface_name;
73 char *parent;
74 guint32 id;
75 guint32 flags;
76 GSList *ingress_priority_map;
77 GSList *egress_priority_map;
78 } NMSettingVlanPrivate;
79
80 enum {
81 PROP_0,
82 PROP_IFACE_NAME,
83 PROP_PARENT,
84 PROP_ID,
85 PROP_FLAGS,
86 PROP_INGRESS_PRIORITY_MAP,
87 PROP_EGRESS_PRIORITY_MAP,
88 LAST_PROP
89 };
90
91 #define MAX_SKB_PRIO G_MAXUINT32
92 #define MAX_8021P_PRIO 7 /* Max 802.1p priority */
93
94 typedef struct {
95 guint32 from;
96 guint32 to;
97 } PriorityMap;
98
99 /**
100 * nm_setting_vlan_new:
101 *
102 * Creates a new #NMSettingVlan object with default values.
103 *
104 * Returns: (transfer full): the new empty #NMSettingVlan object
105 **/
106 NMSetting *
107 nm_setting_vlan_new (void)
108 {
109 return (NMSetting *) g_object_new (NM_TYPE_SETTING_VLAN, NULL);
110 }
111
112 /**
113 * nm_setting_vlan_get_interface_name:
114 * @setting: the #NMSettingVlan
115 *
116 * Returns: the #NMSettingVlan:interface_name property of the setting
117 **/
118 const char *
119 nm_setting_vlan_get_interface_name (NMSettingVlan *setting)
120 {
121 g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), NULL);
122 return NM_SETTING_VLAN_GET_PRIVATE (setting)->iface_name;
123 }
124
125 /**
126 * nm_setting_vlan_get_parent:
127 * @setting: the #NMSettingVlan
128 *
129 * Returns: the #NMSettingVlan:parent property of the setting
130 **/
131 const char *
132 nm_setting_vlan_get_parent (NMSettingVlan *setting)
133 {
134 g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), NULL);
135 return NM_SETTING_VLAN_GET_PRIVATE (setting)->parent;
136 }
137
138 /**
139 * nm_setting_vlan_get_id:
140 * @setting: the #NMSettingVlan
141 *
142 * Returns: the #NMSettingVlan:id property of the setting
143 **/
144 guint32
145 nm_setting_vlan_get_id (NMSettingVlan *setting)
146 {
147 g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), 0);
148 return NM_SETTING_VLAN_GET_PRIVATE (setting)->id;
149 }
150
151 /**
152 * nm_setting_vlan_get_flags:
153 * @setting: the #NMSettingVlan
154 *
155 * Returns: the #NMSettingVlan:flags property of the setting
156 **/
157 guint32
158 nm_setting_vlan_get_flags (NMSettingVlan *setting)
159 {
160 g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), 0);
161 return NM_SETTING_VLAN_GET_PRIVATE (setting)->flags;
162 }
163
164 static guint32
165 get_max_prio (NMVlanPriorityMap map, gboolean from)
166 {
167 if (map == NM_VLAN_INGRESS_MAP)
168 return from ? MAX_8021P_PRIO : MAX_SKB_PRIO;
169 else if (map == NM_VLAN_EGRESS_MAP)
170 return from ? MAX_SKB_PRIO : MAX_8021P_PRIO;
171 g_assert_not_reached ();
172 }
173
174 static PriorityMap *
175 priority_map_new_from_str (NMVlanPriorityMap map, const char *str)
176 {
177 PriorityMap *p = NULL;
178 gchar **t = NULL;
179 guint32 len;
180 guint64 from, to;
181
182 g_return_val_if_fail (str && str[0], NULL);
183
184 t = g_strsplit (str, ":", 0);
185 len = g_strv_length (t);
186 if (len == 2) {
187 from = g_ascii_strtoull (t[0], NULL, 10);
188 to = g_ascii_strtoull (t[1], NULL, 10);
189
190 if ((from <= get_max_prio (map, TRUE)) && (to <= get_max_prio (map, FALSE))) {
191 p = g_malloc0 (sizeof (PriorityMap));
192 p->from = from;
193 p->to = to;
194 }
195 } else {
196 /* Warn */
197 g_warn_if_fail (len == 2);
198 }
199
200 g_strfreev (t);
201 return p;
202 }
203
204 static void
205 priority_map_free (PriorityMap *map)
206 {
207 g_return_if_fail (map != NULL);
208 g_free (map);
209 }
210
211 static GSList *
212 get_map (NMSettingVlan *self, NMVlanPriorityMap map)
213 {
214 if (map == NM_VLAN_INGRESS_MAP)
215 return NM_SETTING_VLAN_GET_PRIVATE (self)->ingress_priority_map;
216 else if (map == NM_VLAN_EGRESS_MAP)
217 return NM_SETTING_VLAN_GET_PRIVATE (self)->egress_priority_map;
218 g_assert_not_reached ();
219 return NULL;
220 }
221
222 static void
223 set_map (NMSettingVlan *self, NMVlanPriorityMap map, GSList *list)
224 {
225 if (map == NM_VLAN_INGRESS_MAP) {
226 NM_SETTING_VLAN_GET_PRIVATE (self)->ingress_priority_map = list;
227 g_object_notify (G_OBJECT (self), NM_SETTING_VLAN_INGRESS_PRIORITY_MAP);
228 } else if (map == NM_VLAN_EGRESS_MAP) {
229 NM_SETTING_VLAN_GET_PRIVATE (self)->egress_priority_map = list;
230 g_object_notify (G_OBJECT (self), NM_SETTING_VLAN_EGRESS_PRIORITY_MAP);
231 } else
232 g_assert_not_reached ();
233 }
234
235 /**
236 * nm_setting_vlan_add_priority_str:
237 * @setting: the #NMSettingVlan
238 * @map: the type of priority map
239 * @str: the string which contains a priority map, like "3:7"
240 *
241 * Adds a priority map entry into either the #NMSettingVlan:ingress_priority_map
242 * or the #NMSettingVlan:egress_priority_map properties. The priority map maps
243 * the Linux SKB priorities to 802.1p priorities.
244 *
245 * Returns: TRUE if the entry was successfully added to the list, or it
246 * overwrote the old value, FALSE if error
247 */
248 gboolean
249 nm_setting_vlan_add_priority_str (NMSettingVlan *setting,
250 NMVlanPriorityMap map,
251 const char *str)
252 {
253 NMSettingVlanPrivate *priv = NULL;
254 GSList *list = NULL, *iter = NULL;
255 PriorityMap *item = NULL;
256
257 g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), FALSE);
258 g_return_val_if_fail (map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP, FALSE);
259 g_return_val_if_fail (str && str[0], FALSE);
260
(1) Event returned_pointer: |
Pointer "priv" returned by "g_type_instance_get_private((GTypeInstance *)setting, nm_setting_vlan_get_type())" is never used. |
261 priv = NM_SETTING_VLAN_GET_PRIVATE (setting);
262 list = get_map (setting, map);
263
264 item = priority_map_new_from_str (map, str);
265 g_return_val_if_fail (item != NULL, FALSE);
266
267 /* Duplicates get replaced */
268 for (iter = list; iter; iter = g_slist_next (iter)) {
269 PriorityMap *p = iter->data;
270
271 if (p->from == item->from) {
272 p->to = item->to;
273 g_free (item);
274 if (map == NM_VLAN_INGRESS_MAP)
275 g_object_notify (G_OBJECT (setting), NM_SETTING_VLAN_INGRESS_PRIORITY_MAP);
276 else
277 g_object_notify (G_OBJECT (setting), NM_SETTING_VLAN_EGRESS_PRIORITY_MAP);
278 return TRUE;
279 }
280 }
281
282 set_map (setting, map, g_slist_append (list, item));
283 return TRUE;
284 }
285
286 /**
287 * nm_setting_vlan_get_num_priorities:
288 * @setting: the #NMSettingVlan
289 * @map: the type of priority map
290 *
291 * Returns the number of entires in the
292 * #NMSettingVlan:ingress_priority_map or #NMSettingVlan:egress_priority_map
293 * properties of this setting.
294 *
295 * Returns: return the number of ingress/egress priority entries, -1 if error
296 **/
297 gint32
298 nm_setting_vlan_get_num_priorities (NMSettingVlan *setting, NMVlanPriorityMap map)
299 {
300 g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), -1);
301 g_return_val_if_fail (map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP, -1);
302
303 return g_slist_length (get_map (setting, map));
304 }
305
306 /**
307 * nm_setting_vlan_get_priority:
308 * @setting: the #NMSettingVlan
309 * @map: the type of priority map
310 * @idx: the zero-based index of the ingress/egress priority map entry
311 * @out_from: (out): on return the value of the priority map's 'from' item
312 * @out_to: (out): on return the value of priority map's 'to' item
313 *
314 * Retrieve one of the entries of the #NMSettingVlan:ingress_priority_map
315 * or #NMSettingVlan:egress_priority_map properties of this setting.
316 *
317 * Returns: %TRUE if a priority map was returned, %FALSE if error
318 **/
319 gboolean
320 nm_setting_vlan_get_priority (NMSettingVlan *setting,
321 NMVlanPriorityMap map,
322 guint32 idx,
323 guint32 *out_from,
324 guint32 *out_to)
325 {
326 GSList *list = NULL;
327 PriorityMap *item = NULL;
328
329 g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), FALSE);
330 g_return_val_if_fail (map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP, FALSE);
331 g_return_val_if_fail (out_from != NULL, FALSE);
332 g_return_val_if_fail (out_to != NULL, FALSE);
333
334 list = get_map (setting, map);
335 g_return_val_if_fail (idx < g_slist_length (list), FALSE);
336
337 item = g_slist_nth_data (list, idx);
338 g_assert (item);
339 *out_from = item->from;
340 *out_to = item->to;
341 return TRUE;
342 }
343
344 /**
345 * nm_setting_vlan_add_priority:
346 * @setting: the #NMSettingVlan
347 * @map: the type of priority map
348 * @from: the priority to map to @to
349 * @to: the priority to map @from to
350 *
351 * Adds a priority mapping to the #NMSettingVlan:ingress_priority_map or
352 * #NMSettingVlan:egress_priority_map properties of the setting. If @from is
353 * already in the given priority map, this function will overwrite the
354 * existing entry with the new @to.
355 *
356 * If @map is #NM_VLAN_INGRESS_MAP then @from is the incoming 802.1q VLAN
357 * Priority Code Point (PCP) value, and @to is the Linux SKB priority value.
358 *
359 * If @map is #NM_VLAN_EGRESS_MAP then @from is the Linux SKB priority value and
360 * @to is the outgoing 802.1q VLAN Priority Code Point (PCP) value.
361 *
362 * Returns: TRUE if the new priority mapping was successfully added to the
363 * list, FALSE if error
364 */
365 gboolean
366 nm_setting_vlan_add_priority (NMSettingVlan *setting,
367 NMVlanPriorityMap map,
368 guint32 from,
369 guint32 to)
370 {
371 GSList *list = NULL, *iter = NULL;
372 PriorityMap *item;
373
374 g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), FALSE);
375 g_return_val_if_fail (map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP, FALSE);
376
377 list = get_map (setting, map);
378 for (iter = list; iter; iter = g_slist_next (iter)) {
379 item = iter->data;
380 if (item->from == from) {
381 item->to = to;
382 if (map == NM_VLAN_INGRESS_MAP)
383 g_object_notify (G_OBJECT (setting), NM_SETTING_VLAN_INGRESS_PRIORITY_MAP);
384 else
385 g_object_notify (G_OBJECT (setting), NM_SETTING_VLAN_EGRESS_PRIORITY_MAP);
386 return TRUE;
387 }
388 }
389
390 item = g_malloc0 (sizeof (PriorityMap));
391 item->from = from;
392 item->to = to;
393 set_map (setting, map, g_slist_append (list, item));
394
395 return TRUE;
396 }
397
398 /**
399 * nm_setting_vlan_remove_priority:
400 * @setting: the #NMSettingVlan
401 * @map: the type of priority map
402 * @idx: the zero-based index of the priority map to remove
403 *
404 * Removes the priority map at index @idx from the
405 * #NMSettingVlan:ingress_priority_map or #NMSettingVlan:egress_priority_map
406 * properties.
407 */
408 void
409 nm_setting_vlan_remove_priority (NMSettingVlan *setting,
410 NMVlanPriorityMap map,
411 guint32 idx)
412 {
413 GSList *list = NULL, *item = NULL;
414
415 g_return_if_fail (NM_IS_SETTING_VLAN (setting));
416 g_return_if_fail (map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP);
417
418 list = get_map (setting, map);
419 g_return_if_fail (idx < g_slist_length (list));
420
421 item = g_slist_nth (list, idx);
422 priority_map_free ((PriorityMap *) (item->data));
423 set_map (setting, map, g_slist_delete_link (list, item));
424 }
425
426 /**
427 * nm_setting_vlan_clear_priorities:
428 * @setting: the #NMSettingVlan
429 * @map: the type of priority map
430 *
431 * Clear all the entires from #NMSettingVlan:ingress_priority_map or
432 * #NMSettingVlan:egress_priority_map properties.
433 */
434 void
435 nm_setting_vlan_clear_priorities (NMSettingVlan *setting, NMVlanPriorityMap map)
436 {
437 GSList *list = NULL;
438
439 g_return_if_fail (NM_IS_SETTING_VLAN (setting));
440 g_return_if_fail (map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP);
441
442 list = get_map (setting, map);
443 g_slist_free_full (list, g_free);
444 set_map (setting, map, NULL);
445 }
446
447 /*********************************************************************/
448
449 static void
450 nm_setting_vlan_init (NMSettingVlan *setting)
451 {
452 g_object_set (setting, NM_SETTING_NAME, NM_SETTING_VLAN_SETTING_NAME, NULL);
453 }
454
455 static gboolean
456 verify (NMSetting *setting, GSList *all_settings, GError **error)
457 {
458 NMSettingVlanPrivate *priv = NM_SETTING_VLAN_GET_PRIVATE (setting);
459 NMSettingConnection *s_con = NULL;
460 NMSettingWired *s_wired = NULL;
461 GSList *iter;
462
463 for (iter = all_settings; iter; iter = iter->next) {
464 if (NM_IS_SETTING_CONNECTION (iter->data))
465 s_con = iter->data;
466 else if (NM_IS_SETTING_WIRED (iter->data))
467 s_wired = iter->data;
468 }
469
470 /* If iface_name is specified, it must be a valid interface name. We
471 * don't check that it matches parent and/or id, because we allowing
472 * renaming vlans to arbitrary names.
473 */
474 if (priv->iface_name && !nm_utils_iface_valid_name (priv->iface_name)) {
475 g_set_error (error,
476 NM_SETTING_VLAN_ERROR,
477 NM_SETTING_VLAN_ERROR_INVALID_PROPERTY,
478 _("'%s' is not a valid interface name"),
479 priv->iface_name);
480 g_prefix_error (error, "%s.%s: ", NM_SETTING_VLAN_SETTING_NAME, NM_SETTING_VLAN_INTERFACE_NAME);
481 return FALSE;
482 }
483
484 if (priv->parent) {
485 if (nm_utils_is_uuid (priv->parent)) {
486 /* If we have an NMSettingConnection:master with slave-type="vlan",
487 * then it must be the same UUID.
488 */
489 if (s_con) {
490 const char *master = NULL, *slave_type = NULL;
491
492 slave_type = nm_setting_connection_get_slave_type (s_con);
493 if (!g_strcmp0 (slave_type, NM_SETTING_VLAN_SETTING_NAME))
494 master = nm_setting_connection_get_master (s_con);
495
496 if (master && g_strcmp0 (priv->parent, master) != 0) {
497 g_set_error (error,
498 NM_SETTING_VLAN_ERROR,
499 NM_SETTING_VLAN_ERROR_INVALID_PARENT,
500 _("'%s' value doesn't match '%s=%s'"),
501 priv->parent, NM_SETTING_CONNECTION_MASTER, master);
502 g_prefix_error (error, "%s.%s: ", NM_SETTING_VLAN_SETTING_NAME, NM_SETTING_VLAN_PARENT);
503 return FALSE;
504 }
505 }
506 } else if (!nm_utils_iface_valid_name (priv->parent)) {
507 /* parent must be either a UUID or an interface name */
508 g_set_error (error,
509 NM_SETTING_VLAN_ERROR,
510 NM_SETTING_VLAN_ERROR_INVALID_PROPERTY,
511 _("'%s' is neither an UUID nor an interface name"),
512 priv->parent);
513 g_prefix_error (error, "%s.%s: ", NM_SETTING_VLAN_SETTING_NAME, NM_SETTING_VLAN_PARENT);
514 return FALSE;
515 }
516 } else {
517 /* If parent is NULL, the parent must be specified via
518 * NMSettingWired:mac-address.
519 */
520 if (!s_wired || !nm_setting_wired_get_mac_address (s_wired)) {
521 g_set_error (error,
522 NM_SETTING_VLAN_ERROR,
523 NM_SETTING_VLAN_ERROR_MISSING_PROPERTY,
524 _("property is not specified and neither is '%s:%s'"),
525 NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_MAC_ADDRESS);
526 g_prefix_error (error, "%s.%s: ", NM_SETTING_VLAN_SETTING_NAME, NM_SETTING_VLAN_PARENT);
527 return FALSE;
528 }
529 }
530
531 if (priv->flags & ~(NM_VLAN_FLAG_REORDER_HEADERS |
532 NM_VLAN_FLAG_GVRP |
533 NM_VLAN_FLAG_LOOSE_BINDING)) {
534 g_set_error_literal (error,
535 NM_SETTING_VLAN_ERROR,
536 NM_SETTING_VLAN_ERROR_INVALID_PROPERTY,
537 _("flags are invalid"));
538 g_prefix_error (error, "%s.%s: ", NM_SETTING_VLAN_SETTING_NAME, NM_SETTING_VLAN_FLAGS);
539 return FALSE;
540 }
541
542 return TRUE;
543 }
544
545 static const char *
546 get_virtual_iface_name (NMSetting *setting)
547 {
548 return nm_setting_vlan_get_interface_name (NM_SETTING_VLAN (setting));
549 }
550
551 static GSList *
552 priority_stringlist_to_maplist (NMVlanPriorityMap map, GSList *strlist)
553 {
554 GSList *list = NULL, *iter;
555
556 for (iter = strlist; iter; iter = g_slist_next (iter)) {
557 PriorityMap *item;
558
559 item = priority_map_new_from_str (map, (const char *) iter->data);
560 if (item)
561 list = g_slist_prepend (list, item);
562 }
563 return g_slist_reverse (list);
564 }
565
566 static void
567 set_property (GObject *object, guint prop_id,
568 const GValue *value, GParamSpec *pspec)
569 {
570 NMSettingVlan *setting = NM_SETTING_VLAN (object);
571 NMSettingVlanPrivate *priv = NM_SETTING_VLAN_GET_PRIVATE (setting);
572
573 switch (prop_id) {
574 case PROP_IFACE_NAME:
575 g_free (priv->iface_name);
576 priv->iface_name = g_value_dup_string (value);
577 break;
578 case PROP_PARENT:
579 g_free (priv->parent);
580 priv->parent = g_value_dup_string (value);
581 break;
582 case PROP_ID:
583 priv->id = g_value_get_uint (value);
584 break;
585 case PROP_FLAGS:
586 priv->flags = g_value_get_uint (value);
587 break;
588 case PROP_INGRESS_PRIORITY_MAP:
589 g_slist_free_full (priv->ingress_priority_map, g_free);
590 priv->ingress_priority_map =
591 priority_stringlist_to_maplist (NM_VLAN_INGRESS_MAP, g_value_get_boxed (value));
592 break;
593 case PROP_EGRESS_PRIORITY_MAP:
594 g_slist_free_full (priv->egress_priority_map, g_free);
595 priv->egress_priority_map =
596 priority_stringlist_to_maplist (NM_VLAN_EGRESS_MAP, g_value_get_boxed (value));
597 break;
598 default:
599 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
600 break;
601 }
602 }
603
604 static GSList *
605 priority_maplist_to_stringlist (GSList *list)
606 {
607 GSList *strlist = NULL, *iter;
608
609 for (iter = list; iter; iter = g_slist_next (iter)) {
610 PriorityMap *item = iter->data;
611
612 strlist = g_slist_prepend (strlist, g_strdup_printf ("%d:%d", item->from, item->to));
613 }
614 return g_slist_reverse (strlist);
615 }
616
617 static void
618 get_property (GObject *object, guint prop_id,
619 GValue *value, GParamSpec *pspec)
620 {
621 NMSettingVlan *setting = NM_SETTING_VLAN (object);
622 NMSettingVlanPrivate *priv = NM_SETTING_VLAN_GET_PRIVATE (setting);
623
624 switch (prop_id) {
625 case PROP_IFACE_NAME:
626 g_value_set_string (value, priv->iface_name);
627 break;
628 case PROP_PARENT:
629 g_value_set_string (value, priv->parent);
630 break;
631 case PROP_ID:
632 g_value_set_uint (value, priv->id);
633 break;
634 case PROP_FLAGS:
635 g_value_set_uint (value, priv->flags);
636 break;
637 case PROP_INGRESS_PRIORITY_MAP:
638 g_value_take_boxed (value, priority_maplist_to_stringlist (priv->ingress_priority_map));
639 break;
640 case PROP_EGRESS_PRIORITY_MAP:
641 g_value_take_boxed (value, priority_maplist_to_stringlist (priv->egress_priority_map));
642 break;
643 default:
644 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
645 break;
646 }
647 }
648
649 static void
650 finalize (GObject *object)
651 {
652 NMSettingVlan *setting = NM_SETTING_VLAN (object);
653 NMSettingVlanPrivate *priv = NM_SETTING_VLAN_GET_PRIVATE (setting);
654
655 g_free (priv->iface_name);
656 g_free (priv->parent);
657 g_slist_free_full (priv->ingress_priority_map, g_free);
658 g_slist_free_full (priv->egress_priority_map, g_free);
659
660 G_OBJECT_CLASS (nm_setting_vlan_parent_class)->finalize (object);
661 }
662
663 static void
664 nm_setting_vlan_class_init (NMSettingVlanClass *setting_class)
665 {
666 GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
667 NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
668
669 g_type_class_add_private (setting_class, sizeof (NMSettingVlanPrivate));
670
671 /* virtual methods */
672 object_class->set_property = set_property;
673 object_class->get_property = get_property;
674 object_class->finalize = finalize;
675 parent_class->verify = verify;
676 parent_class->get_virtual_iface_name = get_virtual_iface_name;
677
678 /* Properties */
679
680 /**
681 * NMSettingVlan:interface-name:
682 *
683 * If given, specifies the kernel name of the VLAN interface. If not given,
684 * a default name will be constructed from the interface described by the
685 * parent interface and the #NMSettingVlan:id , ex 'eth2.1'. The parent
686 * interface may be given by the #NMSettingVlan:parent property or by the
687 * #NMSettingWired:mac-address property of an #NMSettingWired.
688 **/
689 g_object_class_install_property
690 (object_class, PROP_IFACE_NAME,
691 g_param_spec_string (NM_SETTING_VLAN_INTERFACE_NAME,
692 "InterfaceName",
693 "If given, specifies the kernel name of the VLAN "
694 "interface. If not given, a default name will be "
695 "constructed from the interface described by the "
696 "parent interface and the 'id' property, ex "
697 "'eth2.1'. The parent interface may be given by "
698 "the 'parent' property or by the 'mac-address' "
699 "property of a 'wired' setting.",
700 NULL,
701 G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
702
703 /**
704 * NMSettingVlan:parent:
705 *
706 * If given, specifies the parent interface name or parent connection UUID
707 * from which this VLAN interface should be created. If this property is
708 * not specified, the connection must contain a #NMSettingWired:mac-address
709 * in an #NMSettingWired setting.
710 **/
711 g_object_class_install_property
712 (object_class, PROP_PARENT,
713 g_param_spec_string (NM_SETTING_VLAN_PARENT,
714 "Parent",
715 "If given, specifies the parent interface name or "
716 "parent connection UUID from which this VLAN "
717 "interface should be created. If this property is "
718 "not specified, the connection must contain a "
719 "'wired' setting with a 'mac-address' property.",
720 NULL,
721 G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
722
723 /**
724 * NMSettingVlan:id:
725 *
726 * The VLAN identifier the interface created by this connection should be
727 * assigned.
728 **/
729 g_object_class_install_property
730 (object_class, PROP_ID,
731 g_param_spec_uint (NM_SETTING_VLAN_ID,
732 "VLAN ID",
733 "The VLAN indentifier the interface created by "
734 "this connection should be assigned.",
735 0, 4095, 0,
736 G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
737
738 /**
739 * NMSettingVlan:flags:
740 *
741 * One or more of %NMVlanFlags which control the behavior and features of
742 * the VLAN interface.
743 **/
744 g_object_class_install_property
745 (object_class, PROP_FLAGS,
746 g_param_spec_uint (NM_SETTING_VLAN_FLAGS,
747 "VLAN flags",
748 "One or more flags which control the behavior and "
749 "features of the VLAN interface. Flags include "
750 "reordering of output packet headers (0x01), use "
751 "of the GVRP protocol (0x02), and loose binding "
752 "of the interface to its master device's operating "
753 "state (0x04).",
754 0, G_MAXUINT32, 0,
755 G_PARAM_READWRITE | G_PARAM_CONSTRUCT | NM_SETTING_PARAM_SERIALIZE));
756
757 /**
758 * NMSettingVlan:ingress-priority-map:
759 *
760 * For incoming packets, a list of mappings from 802.1p priorities to Linux
761 * SKB priorities. The mapping is given in the format 'from:to' where both
762 * 'from' and 'to' are unsigned integers, ie '7:3'.
763 **/
764 g_object_class_install_property
765 (object_class, PROP_INGRESS_PRIORITY_MAP,
766 _nm_param_spec_specialized (NM_SETTING_VLAN_INGRESS_PRIORITY_MAP,
767 "VLAN ingress priority mapping",
768 "For incoming packets, a list of mappings "
769 "from 802.1p priorities to Linux SKB "
770 "priorities. The mapping is given in the "
771 "format 'from:to' where both 'from' and "
772 "'to' are unsigned integers, ie '7:3'.",
773 DBUS_TYPE_G_LIST_OF_STRING,
774 G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
775
776 /**
777 * NMSettingVlan:egress-priority-map:
778 *
779 * For outgoing packets, a list of mappings from Linux SKB priorities to
780 * 802.1p priorities. The mapping is given in the format 'from:to'
781 * where both 'from' and 'to' are unsigned integers, ie '7:3'.
782 **/
783 g_object_class_install_property
784 (object_class, PROP_EGRESS_PRIORITY_MAP,
785 _nm_param_spec_specialized (NM_SETTING_VLAN_EGRESS_PRIORITY_MAP,
786 "VLAN egress priority mapping",
787 "For outgoing packets, a list of mappings "
788 "from Linux SKB priorities to 802.1p "
789 "priorities. The mapping is given in the "
790 "format 'from:to' where both 'from' and "
791 "'to' are unsigned integers, ie '7:3'.",
792 DBUS_TYPE_G_LIST_OF_STRING,
793 G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
794 }
795