device: renew dhcp leases on awake for software devices
[NetworkManager.git] / libnm-util / nm-setting-bridge.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 2011 - 2013 Red Hat, Inc.
20  */
21
22 #include "nm-default.h"
23
24 #include <string.h>
25 #include <ctype.h>
26 #include <stdlib.h>
27 #include <dbus/dbus-glib.h>
28 #include <linux/if_ether.h>
29
30 #include "nm-setting-bridge.h"
31 #include "nm-param-spec-specialized.h"
32 #include "nm-setting-private.h"
33 #include "nm-utils.h"
34 #include "nm-utils-private.h"
35 #include "nm-dbus-glib-types.h"
36
37 /**
38  * SECTION:nm-setting-bridge
39  * @short_description: Describes connection properties for bridges
40  * @include: nm-setting-bridge.h
41  *
42  * The #NMSettingBridge object is a #NMSetting subclass that describes properties
43  * necessary for bridging connections.
44  *
45  * Since: 0.9.8
46  **/
47
48 /**
49  * nm_setting_bridge_error_quark:
50  *
51  * Registers an error quark for #NMSettingBridge if necessary.
52  *
53  * Returns: the error quark used for #NMSettingBridge errors.
54  *
55  * Since: 0.9.8
56  **/
57 GQuark
58 nm_setting_bridge_error_quark (void)
59 {
60         static GQuark quark;
61
62         if (G_UNLIKELY (!quark))
63                 quark = g_quark_from_static_string ("nm-setting-bridge-error-quark");
64         return quark;
65 }
66
67
68 G_DEFINE_TYPE_WITH_CODE (NMSettingBridge, nm_setting_bridge, NM_TYPE_SETTING,
69                          _nm_register_setting (NM_SETTING_BRIDGE_SETTING_NAME,
70                                                g_define_type_id,
71                                                1,
72                                                NM_SETTING_BRIDGE_ERROR))
73 NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_BRIDGE)
74
75 #define NM_SETTING_BRIDGE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_BRIDGE, NMSettingBridgePrivate))
76
77 typedef struct {
78         char *   interface_name;
79         GByteArray *mac_address;
80         gboolean stp;
81         guint16  priority;
82         guint16  forward_delay;
83         guint16  hello_time;
84         guint16  max_age;
85         guint32  ageing_time;
86 } NMSettingBridgePrivate;
87
88 enum {
89         PROP_0,
90         PROP_INTERFACE_NAME,
91         PROP_MAC_ADDRESS,
92         PROP_STP,
93         PROP_PRIORITY,
94         PROP_FORWARD_DELAY,
95         PROP_HELLO_TIME,
96         PROP_MAX_AGE,
97         PROP_AGEING_TIME,
98         LAST_PROP
99 };
100
101 /**
102  * nm_setting_bridge_new:
103  *
104  * Creates a new #NMSettingBridge object with default values.
105  *
106  * Returns: (transfer full): the new empty #NMSettingBridge object
107  *
108  * Since: 0.9.8
109  **/
110 NMSetting *
111 nm_setting_bridge_new (void)
112 {
113         return (NMSetting *) g_object_new (NM_TYPE_SETTING_BRIDGE, NULL);
114 }
115
116 /**
117  * nm_setting_bridge_get_interface_name:
118  * @setting: the #NMSettingBridge
119  *
120  * Returns: the #NMSettingBridge:interface-name property of the setting
121  *
122  * Since: 0.9.8
123  **/
124 const char *
125 nm_setting_bridge_get_interface_name (NMSettingBridge *setting)
126 {
127         g_return_val_if_fail (NM_IS_SETTING_BRIDGE (setting), 0);
128
129         return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->interface_name;
130 }
131
132 /**
133  * nm_setting_bridge_get_mac_address:
134  * @setting: the #NMSettingBridge
135  *
136  * Returns: the #NMSettingBridge:mac-address property of the setting
137  *
138  * Since: 0.9.10
139  **/
140 const GByteArray *
141 nm_setting_bridge_get_mac_address (NMSettingBridge *setting)
142 {
143         g_return_val_if_fail (NM_IS_SETTING_BRIDGE (setting), NULL);
144
145         return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->mac_address;
146 }
147
148 /**
149  * nm_setting_bridge_get_stp:
150  * @setting: the #NMSettingBridge
151  *
152  * Returns: the #NMSettingBridge:stp property of the setting
153  *
154  * Since: 0.9.8
155  **/
156 gboolean
157 nm_setting_bridge_get_stp (NMSettingBridge *setting)
158 {
159         g_return_val_if_fail (NM_IS_SETTING_BRIDGE (setting), FALSE);
160
161         return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->stp;
162 }
163
164 /**
165  * nm_setting_bridge_get_priority:
166  * @setting: the #NMSettingBridge
167  *
168  * Returns: the #NMSettingBridge:priority property of the setting
169  *
170  * Since: 0.9.8
171  **/
172 guint16
173 nm_setting_bridge_get_priority (NMSettingBridge *setting)
174 {
175         g_return_val_if_fail (NM_IS_SETTING_BRIDGE (setting), 0);
176
177         return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->priority;
178 }
179
180 /**
181  * nm_setting_bridge_get_forward_delay:
182  * @setting: the #NMSettingBridge
183  *
184  * Returns: the #NMSettingBridge:forward-delay property of the setting
185  *
186  * Since: 0.9.8
187  **/
188 guint16
189 nm_setting_bridge_get_forward_delay (NMSettingBridge *setting)
190 {
191         g_return_val_if_fail (NM_IS_SETTING_BRIDGE (setting), 0);
192
193         return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->forward_delay;
194 }
195
196 /**
197  * nm_setting_bridge_get_hello_time:
198  * @setting: the #NMSettingBridge
199  *
200  * Returns: the #NMSettingBridge:hello-time property of the setting
201  *
202  * Since: 0.9.8
203  **/
204 guint16
205 nm_setting_bridge_get_hello_time (NMSettingBridge *setting)
206 {
207         g_return_val_if_fail (NM_IS_SETTING_BRIDGE (setting), 0);
208
209         return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->hello_time;
210 }
211
212 /**
213  * nm_setting_bridge_get_max_age:
214  * @setting: the #NMSettingBridge
215  *
216  * Returns: the #NMSettingBridge:max-age property of the setting
217  *
218  * Since: 0.9.8
219  **/
220 guint16
221 nm_setting_bridge_get_max_age (NMSettingBridge *setting)
222 {
223         g_return_val_if_fail (NM_IS_SETTING_BRIDGE (setting), 0);
224
225         return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->max_age;
226 }
227
228 /**
229  * nm_setting_bridge_get_ageing_time:
230  * @setting: the #NMSettingBridge
231  *
232  * Returns: the #NMSettingBridge:ageing-time property of the setting
233  *
234  * Since: 0.9.8
235  **/
236 guint
237 nm_setting_bridge_get_ageing_time (NMSettingBridge *setting)
238 {
239         g_return_val_if_fail (NM_IS_SETTING_BRIDGE (setting), 0);
240
241         return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->ageing_time;
242 }
243
244 /* IEEE 802.1D-1998 timer values */
245 #define BR_MIN_HELLO_TIME    1
246 #define BR_MAX_HELLO_TIME    10
247
248 #define BR_MIN_FORWARD_DELAY 2
249 #define BR_MAX_FORWARD_DELAY 30
250
251 #define BR_MIN_MAX_AGE       6
252 #define BR_MAX_MAX_AGE       40
253
254 /* IEEE 802.1D-1998 Table 7.4 */
255 #define BR_MIN_AGEING_TIME   0
256 #define BR_MAX_AGEING_TIME   1000000
257
258 static inline gboolean
259 check_range (guint32 val,
260              guint32 min,
261              guint32 max,
262              const char *prop,
263              GError **error)
264 {
265         if ((val != 0) && (val < min || val > max)) {
266                 g_set_error (error,
267                              NM_SETTING_BRIDGE_ERROR,
268                              NM_SETTING_BRIDGE_ERROR_INVALID_PROPERTY,
269                              _("value '%d' is out of range <%d-%d>"),
270                              val, min, max);
271                 g_prefix_error (error, "%s.%s: ", NM_SETTING_BRIDGE_SETTING_NAME, prop);
272                 return FALSE;
273         }
274         return TRUE;
275 }
276
277 static gboolean
278 verify (NMSetting *setting, GSList *all_settings, GError **error)
279 {
280         NMSettingBridgePrivate *priv = NM_SETTING_BRIDGE_GET_PRIVATE (setting);
281
282         if (priv->mac_address && priv->mac_address->len != ETH_ALEN) {
283                 g_set_error_literal (error,
284                                      NM_SETTING_BRIDGE_ERROR,
285                                      NM_SETTING_BRIDGE_ERROR_INVALID_PROPERTY,
286                                      _("is not a valid MAC address"));
287                 g_prefix_error (error, "%s.%s: ", NM_SETTING_BRIDGE_SETTING_NAME, NM_SETTING_BRIDGE_MAC_ADDRESS);
288                 return FALSE;
289         }
290
291         if (!check_range (priv->forward_delay,
292                           BR_MIN_FORWARD_DELAY,
293                           BR_MAX_FORWARD_DELAY,
294                           NM_SETTING_BRIDGE_FORWARD_DELAY,
295                           error))
296                 return FALSE;
297
298         if (!check_range (priv->hello_time,
299                           BR_MIN_HELLO_TIME,
300                           BR_MAX_HELLO_TIME,
301                           NM_SETTING_BRIDGE_HELLO_TIME,
302                           error))
303                 return FALSE;
304
305         if (!check_range (priv->max_age,
306                           BR_MIN_MAX_AGE,
307                           BR_MAX_MAX_AGE,
308                           NM_SETTING_BRIDGE_MAX_AGE,
309                           error))
310                 return FALSE;
311
312         if (!check_range (priv->ageing_time,
313                           BR_MIN_AGEING_TIME,
314                           BR_MAX_AGEING_TIME,
315                           NM_SETTING_BRIDGE_AGEING_TIME,
316                           error))
317                 return FALSE;
318
319         return _nm_setting_verify_deprecated_virtual_iface_name (
320                  priv->interface_name, FALSE,
321                  NM_SETTING_BRIDGE_SETTING_NAME, NM_SETTING_BRIDGE_INTERFACE_NAME,
322                  NM_SETTING_BRIDGE_ERROR,
323                  NM_SETTING_BRIDGE_ERROR_INVALID_PROPERTY,
324                  NM_SETTING_BRIDGE_ERROR_MISSING_PROPERTY,
325                  all_settings, error);
326 }
327
328 static const char *
329 get_virtual_iface_name (NMSetting *setting)
330 {
331         NMSettingBridge *self = NM_SETTING_BRIDGE (setting);
332
333         return nm_setting_bridge_get_interface_name (self);
334 }
335
336 static void
337 nm_setting_bridge_init (NMSettingBridge *setting)
338 {
339 }
340
341 static void
342 finalize (GObject *object)
343 {
344         NMSettingBridgePrivate *priv = NM_SETTING_BRIDGE_GET_PRIVATE (object);
345
346         g_free (priv->interface_name);
347
348         if (priv->mac_address)
349                 g_byte_array_free (priv->mac_address, TRUE);
350
351         G_OBJECT_CLASS (nm_setting_bridge_parent_class)->finalize (object);
352 }
353
354 static void
355 set_property (GObject *object, guint prop_id,
356               const GValue *value, GParamSpec *pspec)
357 {
358         NMSettingBridgePrivate *priv = NM_SETTING_BRIDGE_GET_PRIVATE (object);
359
360         switch (prop_id) {
361         case PROP_INTERFACE_NAME:
362                 g_free (priv->interface_name);
363                 priv->interface_name = g_value_dup_string (value);
364                 break;
365         case PROP_MAC_ADDRESS:
366                 if (priv->mac_address)
367                         g_byte_array_free (priv->mac_address, TRUE);
368                 priv->mac_address = g_value_dup_boxed (value);
369                 break;
370         case PROP_STP:
371                 priv->stp = g_value_get_boolean (value);
372                 break;
373         case PROP_PRIORITY:
374                 priv->priority = (guint16) g_value_get_uint (value);
375                 break;
376         case PROP_FORWARD_DELAY:
377                 priv->forward_delay = (guint16) g_value_get_uint (value);
378                 break;
379         case PROP_HELLO_TIME:
380                 priv->hello_time = (guint16) g_value_get_uint (value);
381                 break;
382         case PROP_MAX_AGE:
383                 priv->max_age = (guint16) g_value_get_uint (value);
384                 break;
385         case PROP_AGEING_TIME:
386                 priv->ageing_time = g_value_get_uint (value);
387                 break;
388         default:
389                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
390                 break;
391         }
392 }
393
394 static void
395 get_property (GObject *object, guint prop_id,
396               GValue *value, GParamSpec *pspec)
397 {
398         NMSettingBridgePrivate *priv = NM_SETTING_BRIDGE_GET_PRIVATE (object);
399         NMSettingBridge *setting = NM_SETTING_BRIDGE (object);
400
401         switch (prop_id) {
402         case PROP_INTERFACE_NAME:
403                 g_value_set_string (value, nm_setting_bridge_get_interface_name (setting));
404                 break;
405         case PROP_MAC_ADDRESS:
406                 g_value_set_boxed (value, nm_setting_bridge_get_mac_address (setting));
407                 break;
408         case PROP_STP:
409                 g_value_set_boolean (value, priv->stp);
410                 break;
411         case PROP_PRIORITY:
412                 g_value_set_uint (value, priv->priority);
413                 break;
414         case PROP_FORWARD_DELAY:
415                 g_value_set_uint (value, priv->forward_delay);
416                 break;
417         case PROP_HELLO_TIME:
418                 g_value_set_uint (value, priv->hello_time);
419                 break;
420         case PROP_MAX_AGE:
421                 g_value_set_uint (value, priv->max_age);
422                 break;
423         case PROP_AGEING_TIME:
424                 g_value_set_uint (value, priv->ageing_time);
425                 break;
426         default:
427                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
428                 break;
429         }
430 }
431
432 static void
433 nm_setting_bridge_class_init (NMSettingBridgeClass *setting_class)
434 {
435         GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
436         NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
437
438         g_type_class_add_private (setting_class, sizeof (NMSettingBridgePrivate));
439
440         /* virtual methods */
441         object_class->set_property = set_property;
442         object_class->get_property = get_property;
443         object_class->finalize     = finalize;
444         parent_class->verify       = verify;
445         parent_class->get_virtual_iface_name = get_virtual_iface_name;
446
447         /* Properties */
448         /**
449          * NMSettingBridge:interface-name:
450          *
451          * The name of the virtual in-kernel bridging network interface
452          *
453          * Since: 0.9.8
454          **/
455         g_object_class_install_property
456                 (object_class, PROP_INTERFACE_NAME,
457                  g_param_spec_string (NM_SETTING_BRIDGE_INTERFACE_NAME, "", "",
458                                       NULL,
459                                       G_PARAM_READWRITE |
460                                       NM_SETTING_PARAM_INFERRABLE |
461                                       G_PARAM_STATIC_STRINGS));
462
463         /**
464          * NMSettingBridge:mac-address:
465          *
466          * If specified, the MAC address of bridge. When creating a new bridge, this
467          * MAC address will be set. When matching an existing (outside
468          * NetworkManager created) bridge, this MAC address must match.
469          *
470          * Since: 0.9.10
471          **/
472         g_object_class_install_property
473                 (object_class, PROP_MAC_ADDRESS,
474                  _nm_param_spec_specialized (NM_SETTING_BRIDGE_MAC_ADDRESS, "", "",
475                                              DBUS_TYPE_G_UCHAR_ARRAY,
476                                              G_PARAM_READWRITE |
477                                              NM_SETTING_PARAM_INFERRABLE |
478                                              G_PARAM_STATIC_STRINGS));
479
480         /**
481          * NMSettingBridge:stp:
482          *
483          * Controls whether Spanning Tree Protocol (STP) is enabled for this bridge.
484          *
485          * Since: 0.9.8
486          **/
487         g_object_class_install_property
488                 (object_class, PROP_STP,
489                  g_param_spec_boolean (NM_SETTING_BRIDGE_STP, "", "",
490                                        TRUE,
491                                        G_PARAM_READWRITE |
492                                        G_PARAM_CONSTRUCT |
493                                        NM_SETTING_PARAM_INFERRABLE |
494                                        G_PARAM_STATIC_STRINGS));
495
496         /**
497          * NMSettingBridge:priority:
498          *
499          * Sets the Spanning Tree Protocol (STP) priority for this bridge.  Lower
500          * values are "better"; the lowest priority bridge will be elected the root
501          * bridge.
502          *
503          * Since: 0.9.8
504          **/
505         g_object_class_install_property
506                 (object_class, PROP_PRIORITY,
507                  g_param_spec_uint (NM_SETTING_BRIDGE_PRIORITY, "", "",
508                                     0, G_MAXUINT16, 0x8000,
509                                     G_PARAM_READWRITE |
510                                     G_PARAM_CONSTRUCT |
511                                     NM_SETTING_PARAM_INFERRABLE |
512                                     G_PARAM_STATIC_STRINGS));
513
514         /**
515          * NMSettingBridge:forward-delay:
516          *
517          * The Spanning Tree Protocol (STP) forwarding delay, in seconds.
518          *
519          * Since: 0.9.8
520          **/
521         g_object_class_install_property
522                 (object_class, PROP_FORWARD_DELAY,
523                  g_param_spec_uint (NM_SETTING_BRIDGE_FORWARD_DELAY, "", "",
524                                     0, BR_MAX_FORWARD_DELAY, 15,
525                                     G_PARAM_READWRITE |
526                                     G_PARAM_CONSTRUCT |
527                                     NM_SETTING_PARAM_INFERRABLE |
528                                     G_PARAM_STATIC_STRINGS));
529
530         /**
531          * NMSettingBridge:hello-time:
532          *
533          * The Spanning Tree Protocol (STP) hello time, in seconds.
534          *
535          * Since: 0.9.8
536          **/
537         g_object_class_install_property
538                 (object_class, PROP_HELLO_TIME,
539                  g_param_spec_uint (NM_SETTING_BRIDGE_HELLO_TIME, "", "",
540                                     0, BR_MAX_HELLO_TIME, 2,
541                                     G_PARAM_READWRITE |
542                                     G_PARAM_CONSTRUCT |
543                                     NM_SETTING_PARAM_INFERRABLE |
544                                     G_PARAM_STATIC_STRINGS));
545
546         /**
547          * NMSettingBridge:max-age:
548          *
549          * The Spanning Tree Protocol (STP) maximum message age, in seconds.
550          *
551          * Since: 0.9.8
552          **/
553         g_object_class_install_property
554                 (object_class, PROP_MAX_AGE,
555                  g_param_spec_uint (NM_SETTING_BRIDGE_MAX_AGE, "", "",
556                                     0, BR_MAX_MAX_AGE, 20,
557                                     G_PARAM_READWRITE |
558                                     G_PARAM_CONSTRUCT |
559                                     NM_SETTING_PARAM_INFERRABLE |
560                                     G_PARAM_STATIC_STRINGS));
561
562         /**
563          * NMSettingBridge:ageing-time:
564          *
565          * The Ethernet MAC address aging time, in seconds.
566          *
567          * Since: 0.9.8
568          **/
569         g_object_class_install_property
570                 (object_class, PROP_AGEING_TIME,
571                  g_param_spec_uint (NM_SETTING_BRIDGE_AGEING_TIME, "", "",
572                                     0, BR_MAX_AGEING_TIME, 300,
573                                     G_PARAM_READWRITE |
574                                     G_PARAM_CONSTRUCT |
575                                     NM_SETTING_PARAM_INFERRABLE |
576                                     G_PARAM_STATIC_STRINGS));
577 }