device: renew dhcp leases on awake for software devices
[NetworkManager.git] / libnm / nm-device-ethernet.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 2007 - 2008 Novell, Inc.
19  * Copyright 2007 - 2012 Red Hat, Inc.
20  */
21
22 #include "nm-default.h"
23
24 #include <string.h>
25
26 #include "nm-setting-connection.h"
27 #include "nm-setting-wired.h"
28 #include "nm-setting-pppoe.h"
29 #include "nm-utils.h"
30
31 #include "nm-device-ethernet.h"
32 #include "nm-device-private.h"
33 #include "nm-object-private.h"
34
35 G_DEFINE_TYPE (NMDeviceEthernet, nm_device_ethernet, NM_TYPE_DEVICE)
36
37 #define NM_DEVICE_ETHERNET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_ETHERNET, NMDeviceEthernetPrivate))
38
39 typedef struct {
40         char *hw_address;
41         char *perm_hw_address;
42         guint32 speed;
43         gboolean carrier;
44         char **s390_subchannels;
45 } NMDeviceEthernetPrivate;
46
47 enum {
48         PROP_0,
49         PROP_HW_ADDRESS,
50         PROP_PERM_HW_ADDRESS,
51         PROP_SPEED,
52         PROP_CARRIER,
53         PROP_S390_SUBCHANNELS,
54
55         LAST_PROP
56 };
57
58 /**
59  * nm_device_ethernet_get_hw_address:
60  * @device: a #NMDeviceEthernet
61  *
62  * Gets the active hardware (MAC) address of the #NMDeviceEthernet
63  *
64  * Returns: the active hardware address. This is the internal string used by the
65  * device, and must not be modified.
66  **/
67 const char *
68 nm_device_ethernet_get_hw_address (NMDeviceEthernet *device)
69 {
70         g_return_val_if_fail (NM_IS_DEVICE_ETHERNET (device), NULL);
71
72         return NM_DEVICE_ETHERNET_GET_PRIVATE (device)->hw_address;
73 }
74
75 /**
76  * nm_device_ethernet_get_permanent_hw_address:
77  * @device: a #NMDeviceEthernet
78  *
79  * Gets the permanent hardware (MAC) address of the #NMDeviceEthernet
80  *
81  * Returns: the permanent hardware address. This is the internal string used by the
82  * device, and must not be modified.
83  **/
84 const char *
85 nm_device_ethernet_get_permanent_hw_address (NMDeviceEthernet *device)
86 {
87         g_return_val_if_fail (NM_IS_DEVICE_ETHERNET (device), NULL);
88
89         return NM_DEVICE_ETHERNET_GET_PRIVATE (device)->perm_hw_address;
90 }
91
92 /**
93  * nm_device_ethernet_get_speed:
94  * @device: a #NMDeviceEthernet
95  *
96  * Gets the speed of the #NMDeviceEthernet.
97  *
98  * Returns: the speed of the device
99  **/
100 guint32
101 nm_device_ethernet_get_speed (NMDeviceEthernet *device)
102 {
103         g_return_val_if_fail (NM_IS_DEVICE_ETHERNET (device), 0);
104
105         return NM_DEVICE_ETHERNET_GET_PRIVATE (device)->speed;
106 }
107
108 /**
109  * nm_device_ethernet_get_carrier:
110  * @device: a #NMDeviceEthernet
111  *
112  * Whether the device has carrier.
113  *
114  * Returns: %TRUE if the device has carrier
115  **/
116 gboolean
117 nm_device_ethernet_get_carrier (NMDeviceEthernet *device)
118 {
119         g_return_val_if_fail (NM_IS_DEVICE_ETHERNET (device), FALSE);
120
121         return NM_DEVICE_ETHERNET_GET_PRIVATE (device)->carrier;
122 }
123
124 /**
125  * nm_device_ethernet_get_s390_subchannels:
126  * @device: a #NMDeviceEthernet
127  *
128  * Return the list of s390 subchannels if the device supports them.
129  *
130  * Returns: (transfer none) (element-type utf8): array of strings, each specifying
131  *   one subchannel the s390 device uses to communicate to the host.
132  *
133  * Since: 1.2
134  **/
135 const char * const *
136 nm_device_ethernet_get_s390_subchannels (NMDeviceEthernet *device)
137 {
138         g_return_val_if_fail (NM_IS_DEVICE_ETHERNET (device), NULL);
139
140         return (const char * const *) NM_DEVICE_ETHERNET_GET_PRIVATE (device)->s390_subchannels;
141 }
142
143 static guint32
144 _subchannels_count_num (const char * const *array)
145 {
146         int i;
147
148         if (!array)
149                 return 0;
150         for (i = 0; array[i]; i++)
151                 /* NOP */;
152         return i;
153 }
154
155 static gboolean
156 match_subchans (NMDeviceEthernet *self, NMSettingWired *s_wired, gboolean *try_mac)
157 {
158         NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
159         const char * const *subchans;
160         guint32 num1, num2;
161         int i, j;
162
163         *try_mac = TRUE;
164
165         subchans = nm_setting_wired_get_s390_subchannels (s_wired);
166         num1 = _subchannels_count_num (subchans);
167         num2 = _subchannels_count_num ((const char * const *) priv->s390_subchannels);
168         /* connection has no subchannels */
169         if (num1 == 0)
170                 return TRUE;
171         /* connection requires subchannels but the device has none */
172         if (num2 == 0)
173                 return FALSE;
174         /* number of subchannels differ */
175         if (num1 != num2)
176                 return FALSE;
177
178         /* Make sure each subchannel in the connection is a subchannel of this device */
179         for (i = 0; subchans[i]; i++) {
180                 const char *candidate = subchans[i];
181                 gboolean found = FALSE;
182
183                 for (j = 0; priv->s390_subchannels[j]; j++) {
184                         if (!g_strcmp0 (priv->s390_subchannels[j], candidate))
185                                 found = TRUE;
186                 }
187                 if (!found)
188                         return FALSE;  /* a subchannel was not found */
189         }
190
191         *try_mac = FALSE;
192         return TRUE;
193 }
194
195 static gboolean
196 connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
197 {
198         NMSettingWired *s_wired;
199
200         if (!NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->connection_compatible (device, connection, error))
201                 return FALSE;
202
203         if (nm_connection_is_type (connection, NM_SETTING_PPPOE_SETTING_NAME)) {
204                 /* NOP */
205         } else if (!nm_connection_is_type (connection, NM_SETTING_WIRED_SETTING_NAME)) {
206                 g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
207                                      _("The connection was not an Ethernet or PPPoE connection."));
208                 return FALSE;
209         }
210
211         s_wired = nm_connection_get_setting_wired (connection);
212         /* Wired setting optional for PPPoE */
213         if (s_wired) {
214                 const char *perm_addr, *s_mac;
215                 gboolean try_mac = TRUE;
216                 const char * const *mac_blacklist;
217                 int i;
218
219                 /* Check s390 subchannels */
220                 if (!match_subchans (NM_DEVICE_ETHERNET (device), s_wired, &try_mac)) {
221                         g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
222                                              _("The connection and device differ in S390 subchannels."));
223                         return FALSE;
224                 }
225
226                 /* Check MAC address */
227                 perm_addr = nm_device_ethernet_get_permanent_hw_address (NM_DEVICE_ETHERNET (device));
228                 s_mac = nm_setting_wired_get_mac_address (s_wired);
229                 if (perm_addr) {
230                         if (!nm_utils_hwaddr_valid (perm_addr, ETH_ALEN)) {
231                                 g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
232                                                      _("Invalid device MAC address."));
233                                 return FALSE;
234                         }
235                         if (try_mac && s_mac && !nm_utils_hwaddr_matches (s_mac, -1, perm_addr, -1)) {
236                                 g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
237                                                      _("The MACs of the device and the connection do not match."));
238                                 return FALSE;
239                         }
240
241                         /* Check for MAC address blacklist */
242                         mac_blacklist = nm_setting_wired_get_mac_address_blacklist (s_wired);
243                         for (i = 0; mac_blacklist[i]; i++) {
244                                 if (!nm_utils_hwaddr_valid (mac_blacklist[i], ETH_ALEN)) {
245                                         g_warn_if_reached ();
246                                         g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
247                                                      _("Invalid MAC in the blacklist: %s."), mac_blacklist[i]);
248                                         return FALSE;
249                                 }
250
251                                 if (nm_utils_hwaddr_matches (mac_blacklist[i], -1, perm_addr, -1)) {
252                                         g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
253                                                      _("Device MAC (%s) is blacklisted by the connection."), perm_addr);
254                                         return FALSE;
255                                 }
256                         }
257                 }
258         }
259
260         return TRUE;
261 }
262
263 static GType
264 get_setting_type (NMDevice *device)
265 {
266         return NM_TYPE_SETTING_WIRED;
267 }
268
269 static const char *
270 get_hw_address (NMDevice *device)
271 {
272         return nm_device_ethernet_get_hw_address (NM_DEVICE_ETHERNET (device));
273 }
274
275 /***********************************************************/
276
277 static void
278 nm_device_ethernet_init (NMDeviceEthernet *device)
279 {
280         _nm_device_set_device_type (NM_DEVICE (device), NM_DEVICE_TYPE_ETHERNET);
281 }
282
283 static void
284 init_dbus (NMObject *object)
285 {
286         NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (object);
287         const NMPropertiesInfo property_info[] = {
288                 { NM_DEVICE_ETHERNET_HW_ADDRESS,           &priv->hw_address },
289                 { NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS, &priv->perm_hw_address },
290                 { NM_DEVICE_ETHERNET_SPEED,                &priv->speed },
291                 { NM_DEVICE_ETHERNET_CARRIER,              &priv->carrier },
292                 { NM_DEVICE_ETHERNET_S390_SUBCHANNELS,     &priv->s390_subchannels },
293                 { NULL },
294         };
295
296         NM_OBJECT_CLASS (nm_device_ethernet_parent_class)->init_dbus (object);
297
298         _nm_object_register_properties (object,
299                                         NM_DBUS_INTERFACE_DEVICE_WIRED,
300                                         property_info);
301 }
302
303 static void
304 finalize (GObject *object)
305 {
306         NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (object);
307
308         g_free (priv->hw_address);
309         g_free (priv->perm_hw_address);
310         g_strfreev (priv->s390_subchannels);
311
312         G_OBJECT_CLASS (nm_device_ethernet_parent_class)->finalize (object);
313 }
314
315 static void
316 get_property (GObject *object,
317               guint prop_id,
318               GValue *value,
319               GParamSpec *pspec)
320 {
321         NMDeviceEthernet *device = NM_DEVICE_ETHERNET (object);
322         NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device);
323
324         switch (prop_id) {
325         case PROP_HW_ADDRESS:
326                 g_value_set_string (value, nm_device_ethernet_get_hw_address (device));
327                 break;
328         case PROP_PERM_HW_ADDRESS:
329                 g_value_set_string (value, nm_device_ethernet_get_permanent_hw_address (device));
330                 break;
331         case PROP_SPEED:
332                 g_value_set_uint (value, nm_device_ethernet_get_speed (device));
333                 break;
334         case PROP_CARRIER:
335                 g_value_set_boolean (value, nm_device_ethernet_get_carrier (device));
336                 break;
337         case PROP_S390_SUBCHANNELS:
338                 g_value_set_boxed (value, priv->s390_subchannels);
339                 break;
340         default:
341                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
342                 break;
343         }
344 }
345
346 static void
347 nm_device_ethernet_class_init (NMDeviceEthernetClass *eth_class)
348 {
349         GObjectClass *object_class = G_OBJECT_CLASS (eth_class);
350         NMObjectClass *nm_object_class = NM_OBJECT_CLASS (eth_class);
351         NMDeviceClass *device_class = NM_DEVICE_CLASS (eth_class);
352
353         g_type_class_add_private (eth_class, sizeof (NMDeviceEthernetPrivate));
354
355         _nm_object_class_add_interface (nm_object_class, NM_DBUS_INTERFACE_DEVICE_WIRED);
356
357         /* virtual methods */
358         object_class->finalize = finalize;
359         object_class->get_property = get_property;
360
361         nm_object_class->init_dbus = init_dbus;
362
363         device_class->connection_compatible = connection_compatible;
364         device_class->get_setting_type = get_setting_type;
365         device_class->get_hw_address = get_hw_address;
366
367         /* properties */
368
369         /**
370          * NMDeviceEthernet:hw-address:
371          *
372          * The active hardware (MAC) address of the device.
373          **/
374         g_object_class_install_property
375                 (object_class, PROP_HW_ADDRESS,
376                  g_param_spec_string (NM_DEVICE_ETHERNET_HW_ADDRESS, "", "",
377                                       NULL,
378                                       G_PARAM_READABLE |
379                                       G_PARAM_STATIC_STRINGS));
380
381         /**
382          * NMDeviceEthernet:perm-hw-address:
383          *
384          * The permanent hardware (MAC) address of the device.
385          **/
386         g_object_class_install_property
387                 (object_class, PROP_PERM_HW_ADDRESS,
388                  g_param_spec_string (NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS, "", "",
389                                       NULL,
390                                       G_PARAM_READABLE |
391                                       G_PARAM_STATIC_STRINGS));
392
393         /**
394          * NMDeviceEthernet:speed:
395          *
396          * The speed of the device.
397          **/
398         g_object_class_install_property
399                 (object_class, PROP_SPEED,
400                  g_param_spec_uint (NM_DEVICE_ETHERNET_SPEED, "", "",
401                                     0, G_MAXUINT32, 0,
402                                     G_PARAM_READABLE |
403                                     G_PARAM_STATIC_STRINGS));
404
405         /**
406          * NMDeviceEthernet:carrier:
407          *
408          * Whether the device has carrier.
409          **/
410         g_object_class_install_property
411                 (object_class, PROP_CARRIER,
412                  g_param_spec_boolean (NM_DEVICE_ETHERNET_CARRIER, "", "",
413                                        FALSE,
414                                        G_PARAM_READABLE |
415                                        G_PARAM_STATIC_STRINGS));
416
417         /**
418          * NMDeviceEthernet:s390-subchannels:
419          *
420          * Identifies subchannels of this network device used for
421          * communication with z/VM or s390 host.
422          *
423          * Since: 1.2
424          **/
425         g_object_class_install_property
426                 (object_class, PROP_S390_SUBCHANNELS,
427                  g_param_spec_boxed (NM_DEVICE_ETHERNET_S390_SUBCHANNELS, "", "",
428                                      G_TYPE_STRV,
429                                      G_PARAM_READABLE |
430                                      G_PARAM_STATIC_STRINGS));
431 }