device: renew dhcp leases on awake for software devices
[NetworkManager.git] / libnm-glib / nm-device-bridge.c
1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2 /*
3  * This library is free software; you can redistribute it and/or
4  * modify it under the terms of the GNU Lesser General Public
5  * License as published by the Free Software Foundation; either
6  * version 2 of the License, or (at your option) any later version.
7  *
8  * This library is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public
14  * License along with this library; if not, write to the
15  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16  * Boston, MA 02110-1301 USA.
17  *
18  * Copyright 2012 Red Hat, Inc.
19  */
20
21 #include "nm-default.h"
22
23 #include <string.h>
24 #include <netinet/ether.h>
25
26 #include "nm-setting-connection.h"
27 #include "nm-setting-bridge.h"
28 #include "nm-utils.h"
29
30 #include "nm-device-bridge.h"
31 #include "nm-device-private.h"
32 #include "nm-object-private.h"
33 #include "nm-types.h"
34
35 G_DEFINE_TYPE (NMDeviceBridge, nm_device_bridge, NM_TYPE_DEVICE)
36
37 #define NM_DEVICE_BRIDGE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_BRIDGE, NMDeviceBridgePrivate))
38
39 typedef struct {
40         DBusGProxy *proxy;
41
42         char *hw_address;
43         gboolean carrier;
44         GPtrArray *slaves;
45 } NMDeviceBridgePrivate;
46
47 enum {
48         PROP_0,
49         PROP_HW_ADDRESS,
50         PROP_CARRIER,
51         PROP_SLAVES,
52
53         LAST_PROP
54 };
55
56 /**
57  * nm_device_bridge_error_quark:
58  *
59  * Registers an error quark for #NMDeviceBridge if necessary.
60  *
61  * Returns: the error quark used for #NMDeviceBridge errors.
62  *
63  * Since: 0.9.8
64  **/
65 GQuark
66 nm_device_bridge_error_quark (void)
67 {
68         static GQuark quark = 0;
69
70         if (G_UNLIKELY (quark == 0))
71                 quark = g_quark_from_static_string ("nm-device-bridge-error-quark");
72         return quark;
73 }
74
75 /**
76  * nm_device_bridge_new:
77  * @connection: the #DBusGConnection
78  * @path: the DBus object path of the device
79  *
80  * Creates a new #NMDeviceBridge.
81  *
82  * Returns: (transfer full): a new device
83  *
84  * Since: 0.9.8
85  **/
86 GObject *
87 nm_device_bridge_new (DBusGConnection *connection, const char *path)
88 {
89         GObject *device;
90
91         g_return_val_if_fail (connection != NULL, NULL);
92         g_return_val_if_fail (path != NULL, NULL);
93
94         device = g_object_new (NM_TYPE_DEVICE_BRIDGE,
95                                NM_OBJECT_DBUS_CONNECTION, connection,
96                                NM_OBJECT_DBUS_PATH, path,
97                                NULL);
98         _nm_object_ensure_inited (NM_OBJECT (device));
99         return device;
100 }
101
102 /**
103  * nm_device_bridge_get_hw_address:
104  * @device: a #NMDeviceBridge
105  *
106  * Gets the hardware (MAC) address of the #NMDeviceBridge
107  *
108  * Returns: the hardware address. This is the internal string used by the
109  * device, and must not be modified.
110  *
111  * Since: 0.9.8
112  **/
113 const char *
114 nm_device_bridge_get_hw_address (NMDeviceBridge *device)
115 {
116         g_return_val_if_fail (NM_IS_DEVICE_BRIDGE (device), NULL);
117
118         _nm_object_ensure_inited (NM_OBJECT (device));
119         return NM_DEVICE_BRIDGE_GET_PRIVATE (device)->hw_address;
120 }
121
122 /**
123  * nm_device_bridge_get_carrier:
124  * @device: a #NMDeviceBridge
125  *
126  * Whether the device has carrier.
127  *
128  * Returns: %TRUE if the device has carrier
129  *
130  * Since: 0.9.8
131  **/
132 gboolean
133 nm_device_bridge_get_carrier (NMDeviceBridge *device)
134 {
135         g_return_val_if_fail (NM_IS_DEVICE_BRIDGE (device), FALSE);
136
137         _nm_object_ensure_inited (NM_OBJECT (device));
138         return NM_DEVICE_BRIDGE_GET_PRIVATE (device)->carrier;
139 }
140
141 /**
142  * nm_device_bridge_get_slaves:
143  * @device: a #NMDeviceBridge
144  *
145  * Gets the devices currently slaved to @device.
146  *
147  * Returns: (element-type NMDevice): the #GPtrArray containing
148  * #NMDevices that are slaves of @device. This is the internal
149  * copy used by the device, and must not be modified.
150  *
151  * Since: 0.9.8
152  **/
153 const GPtrArray *
154 nm_device_bridge_get_slaves (NMDeviceBridge *device)
155 {
156         g_return_val_if_fail (NM_IS_DEVICE_BRIDGE (device), FALSE);
157
158         _nm_object_ensure_inited (NM_OBJECT (device));
159         return handle_ptr_array_return (NM_DEVICE_BRIDGE_GET_PRIVATE (device)->slaves);
160 }
161
162 static gboolean
163 connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
164 {
165         NMSettingConnection *s_con;
166         NMSettingBridge *s_bridge;
167         const char *ctype, *dev_iface_name, *bridge_iface_name;
168
169         s_con = nm_connection_get_setting_connection (connection);
170         g_assert (s_con);
171
172         ctype = nm_setting_connection_get_connection_type (s_con);
173         if (strcmp (ctype, NM_SETTING_BRIDGE_SETTING_NAME) != 0) {
174                 g_set_error (error, NM_DEVICE_BRIDGE_ERROR, NM_DEVICE_BRIDGE_ERROR_NOT_BRIDGE_CONNECTION,
175                              "The connection was not a bridge connection.");
176                 return FALSE;
177         }
178
179         s_bridge = nm_connection_get_setting_bridge (connection);
180         if (!s_bridge) {
181                 g_set_error (error, NM_DEVICE_BRIDGE_ERROR, NM_DEVICE_BRIDGE_ERROR_INVALID_BRIDGE_CONNECTION,
182                              "The connection was not a valid bridge connection.");
183                 return FALSE;
184         }
185
186         dev_iface_name = nm_device_get_iface (device);
187         bridge_iface_name = nm_setting_bridge_get_interface_name (s_bridge);
188         if (g_strcmp0 (dev_iface_name, bridge_iface_name) != 0) {
189                 g_set_error (error, NM_DEVICE_BRIDGE_ERROR, NM_DEVICE_BRIDGE_ERROR_INTERFACE_MISMATCH,
190                              "The interfaces of the device and the connection didn't match.");
191                 return FALSE;
192         }
193
194         /* FIXME: check ports? */
195
196         return NM_DEVICE_CLASS (nm_device_bridge_parent_class)->connection_compatible (device, connection, error);
197 }
198
199 static GType
200 get_setting_type (NMDevice *device)
201 {
202         return NM_TYPE_SETTING_BRIDGE;
203 }
204
205 static const char *
206 get_hw_address (NMDevice *device)
207 {
208         return nm_device_bridge_get_hw_address (NM_DEVICE_BRIDGE (device));
209 }
210
211 /***********************************************************/
212
213 static void
214 nm_device_bridge_init (NMDeviceBridge *device)
215 {
216         _nm_device_set_device_type (NM_DEVICE (device), NM_DEVICE_TYPE_BRIDGE);
217 }
218
219 static void
220 register_properties (NMDeviceBridge *device)
221 {
222         NMDeviceBridgePrivate *priv = NM_DEVICE_BRIDGE_GET_PRIVATE (device);
223         const NMPropertiesInfo property_info[] = {
224                 { NM_DEVICE_BRIDGE_HW_ADDRESS, &priv->hw_address },
225                 { NM_DEVICE_BRIDGE_CARRIER,    &priv->carrier },
226                 { NM_DEVICE_BRIDGE_SLAVES,     &priv->slaves, NULL, NM_TYPE_DEVICE },
227                 { NULL },
228         };
229
230         _nm_object_register_properties (NM_OBJECT (device),
231                                         priv->proxy,
232                                         property_info);
233 }
234
235 static void
236 constructed (GObject *object)
237 {
238         NMDeviceBridgePrivate *priv = NM_DEVICE_BRIDGE_GET_PRIVATE (object);
239
240         G_OBJECT_CLASS (nm_device_bridge_parent_class)->constructed (object);
241
242         priv->proxy = _nm_object_new_proxy (NM_OBJECT (object), NULL, NM_DBUS_INTERFACE_DEVICE_BRIDGE);
243         register_properties (NM_DEVICE_BRIDGE (object));
244 }
245
246 static void
247 dispose (GObject *object)
248 {
249         NMDeviceBridgePrivate *priv = NM_DEVICE_BRIDGE_GET_PRIVATE (object);
250
251         g_clear_object (&priv->proxy);
252
253         if (priv->slaves) {
254                 g_ptr_array_set_free_func (priv->slaves, g_object_unref);
255                 g_ptr_array_free (priv->slaves, TRUE);
256                 priv->slaves = NULL;
257         }
258
259         G_OBJECT_CLASS (nm_device_bridge_parent_class)->dispose (object);
260 }
261
262 static void
263 finalize (GObject *object)
264 {
265         NMDeviceBridgePrivate *priv = NM_DEVICE_BRIDGE_GET_PRIVATE (object);
266
267         g_free (priv->hw_address);
268
269         G_OBJECT_CLASS (nm_device_bridge_parent_class)->finalize (object);
270 }
271
272 static void
273 get_property (GObject *object,
274               guint prop_id,
275               GValue *value,
276               GParamSpec *pspec)
277 {
278         NMDeviceBridge *device = NM_DEVICE_BRIDGE (object);
279
280         _nm_object_ensure_inited (NM_OBJECT (object));
281
282         switch (prop_id) {
283         case PROP_HW_ADDRESS:
284                 g_value_set_string (value, nm_device_bridge_get_hw_address (device));
285                 break;
286         case PROP_CARRIER:
287                 g_value_set_boolean (value, nm_device_bridge_get_carrier (device));
288                 break;
289         case PROP_SLAVES:
290                 g_value_set_boxed (value, nm_device_bridge_get_slaves (device));
291                 break;
292         default:
293                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
294                 break;
295         }
296 }
297
298 static void
299 nm_device_bridge_class_init (NMDeviceBridgeClass *bridge_class)
300 {
301         GObjectClass *object_class = G_OBJECT_CLASS (bridge_class);
302         NMDeviceClass *device_class = NM_DEVICE_CLASS (bridge_class);
303
304         g_type_class_add_private (bridge_class, sizeof (NMDeviceBridgePrivate));
305
306         /* virtual methods */
307         object_class->constructed = constructed;
308         object_class->dispose = dispose;
309         object_class->finalize = finalize;
310         object_class->get_property = get_property;
311         device_class->connection_compatible = connection_compatible;
312         device_class->get_setting_type = get_setting_type;
313         device_class->get_hw_address = get_hw_address;
314
315         /* properties */
316
317         /**
318          * NMDeviceBridge:hw-address:
319          *
320          * The hardware (MAC) address of the device.
321          *
322          * Since: 0.9.8
323          **/
324         g_object_class_install_property
325                 (object_class, PROP_HW_ADDRESS,
326                  g_param_spec_string (NM_DEVICE_BRIDGE_HW_ADDRESS, "", "",
327                                       NULL,
328                                       G_PARAM_READABLE |
329                                       G_PARAM_STATIC_STRINGS));
330
331         /**
332          * NMDeviceBridge:carrier:
333          *
334          * Whether the device has carrier.
335          *
336          * Since: 0.9.8
337          **/
338         g_object_class_install_property
339                 (object_class, PROP_CARRIER,
340                  g_param_spec_boolean (NM_DEVICE_BRIDGE_CARRIER, "", "",
341                                        FALSE,
342                                        G_PARAM_READABLE |
343                                        G_PARAM_STATIC_STRINGS));
344
345         /**
346          * NMDeviceBridge:slaves:
347          *
348          * The devices (#NMDevice) slaved to the bridge device.
349          *
350          * Since: 0.9.8
351          **/
352         g_object_class_install_property
353                 (object_class, PROP_SLAVES,
354                  g_param_spec_boxed (NM_DEVICE_BRIDGE_SLAVES, "", "",
355                                      NM_TYPE_OBJECT_ARRAY,
356                                      G_PARAM_READABLE |
357                                      G_PARAM_STATIC_STRINGS));
358 }